From a063d317122dce598d26ac03b4975cbb6469f8e4 Mon Sep 17 00:00:00 2001 From: Adam Date: Sat, 9 Mar 2024 10:55:49 -0800 Subject: [PATCH] Add lints for S/MIME BR 7.1.2.3.b (#779) * Add lints for S/MIME BR 7.1.2.3.b * remove logging * Update logic to include legacy certs * Add test for legacy certs * add test * Add tests with mixed HTTP and non-HTTP * URL -> URI * Fix text * UseCertificateLint * Rename testdata files to reflect their type --------- Co-authored-by: Christopher Henderson --- ...ribers_crl_distribution_points_are_http.go | 77 +++++++++++++++++++ ...s_crl_distribution_points_are_http_test.go | 58 ++++++++++++++ ...ber_with_mixed_crl_distribution_points.pem | 47 +++++++++++ ...r_with_non_http_crl_distribution_point.pem | 44 +++++++++++ ...riber_with_http_crl_distribution_point.pem | 44 +++++++++++ ...ber_with_mixed_crl_distribution_points.pem | 47 +++++++++++ ...r_with_non_http_crl_distribution_point.pem | 44 +++++++++++ 7 files changed, 361 insertions(+) create mode 100644 v3/lints/cabf_smime_br/lint_subscribers_crl_distribution_points_are_http.go create mode 100644 v3/lints/cabf_smime_br/lint_subscribers_crl_distribution_points_are_http_test.go create mode 100644 v3/testdata/smime/legacy_subscriber_with_mixed_crl_distribution_points.pem create mode 100644 v3/testdata/smime/legacy_subscriber_with_non_http_crl_distribution_point.pem create mode 100644 v3/testdata/smime/strict_subscriber_with_http_crl_distribution_point.pem create mode 100644 v3/testdata/smime/strict_subscriber_with_mixed_crl_distribution_points.pem create mode 100644 v3/testdata/smime/strict_subscriber_with_non_http_crl_distribution_point.pem diff --git a/v3/lints/cabf_smime_br/lint_subscribers_crl_distribution_points_are_http.go b/v3/lints/cabf_smime_br/lint_subscribers_crl_distribution_points_are_http.go new file mode 100644 index 000000000..3333e36ba --- /dev/null +++ b/v3/lints/cabf_smime_br/lint_subscribers_crl_distribution_points_are_http.go @@ -0,0 +1,77 @@ +/* + * ZLint Copyright 2023 Regents of the University of Michigan + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +package cabf_smime_br + +import ( + "net/url" + + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +func init() { + lint.RegisterCertificateLint(&lint.CertificateLint{ + LintMetadata: lint.LintMetadata{ + Name: "e_subscribers_crl_distribution_points_are_http", + Description: "cRLDistributionPoints SHALL have URI scheme HTTP.", + Citation: "7.1.2.3.b", + Source: lint.CABFSMIMEBaselineRequirements, + EffectiveDate: util.CABF_SMIME_BRs_1_0_0_Date, + }, + Lint: NewSubscriberCrlDistributionPointsHTTP, + }) +} + +type subscriberCrlDistributionPointsHTTP struct{} + +func NewSubscriberCrlDistributionPointsHTTP() lint.LintInterface { + return &subscriberCrlDistributionPointsHTTP{} +} + +func (l *subscriberCrlDistributionPointsHTTP) CheckApplies(c *x509.Certificate) bool { + return util.IsSubscriberCert(c) && util.IsSMIMEBRCertificate(c) +} + +func (l *subscriberCrlDistributionPointsHTTP) Execute(c *x509.Certificate) *lint.LintResult { + httpCount := 0 + for _, dp := range c.CRLDistributionPoints { + parsed, err := url.Parse(dp) + if err != nil { + return &lint.LintResult{ + Status: lint.Error, + Details: "SMIME certificate contains invalid CRL distribution point", + } + } + if parsed.Scheme == "http" { + httpCount++ + } + } + + if (util.IsMultipurposeSMIMECertificate(c) || util.IsStrictSMIMECertificate(c)) && httpCount != len(c.CRLDistributionPoints) { + return &lint.LintResult{ + Status: lint.Error, + Details: "SMIME certificate contains invalid URI scheme in CRL distribution point", + } + } + if util.IsLegacySMIMECertificate(c) && httpCount == 0 { + return &lint.LintResult{ + Status: lint.Error, + Details: "SMIME certificate contains no HTTP URI schemes as CRL distribution points", + } + } + + return &lint.LintResult{Status: lint.Pass} +} diff --git a/v3/lints/cabf_smime_br/lint_subscribers_crl_distribution_points_are_http_test.go b/v3/lints/cabf_smime_br/lint_subscribers_crl_distribution_points_are_http_test.go new file mode 100644 index 000000000..15b133f7d --- /dev/null +++ b/v3/lints/cabf_smime_br/lint_subscribers_crl_distribution_points_are_http_test.go @@ -0,0 +1,58 @@ +package cabf_smime_br + +import ( + "testing" + + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/test" +) + +func TestSubscriberCrlDistributionPointsAreHTTP(t *testing.T) { + testCases := []struct { + Name string + InputFilename string + ExpectedResult lint.LintStatus + ExpectedDetails string + }{ + { + Name: "pass - strict cert with only HTTP CRL distribution points", + InputFilename: "smime/strict_subscriber_with_http_crl_distribution_point.pem", + ExpectedResult: lint.Pass, + }, + { + Name: "error - strict cert with a non-HTTP CRL distribution point", + InputFilename: "smime/strict_subscriber_with_non_http_crl_distribution_point.pem", + ExpectedResult: lint.Error, + ExpectedDetails: "SMIME certificate contains invalid URI scheme in CRL distribution point", + }, + { + Name: "error - legacy cert with no HTTP CRL distribution points", + InputFilename: "smime/legacy_subscriber_with_non_http_crl_distribution_point.pem", + ExpectedResult: lint.Error, + ExpectedDetails: "SMIME certificate contains no HTTP URI schemes as CRL distribution points", + }, + { + Name: "pass - legacy cert with HTTP and non-HTTP CRL distribution points", + InputFilename: "smime/legacy_subscriber_with_mixed_crl_distribution_points.pem", + ExpectedResult: lint.Pass, + }, + { + Name: "error - strict cert with HTTP and non-HTTP CRL distribution points", + InputFilename: "smime/strict_subscriber_with_mixed_crl_distribution_points.pem", + ExpectedResult: lint.Error, + ExpectedDetails: "SMIME certificate contains invalid URI scheme in CRL distribution point", + }, + } + for _, tc := range testCases { + t.Run(tc.Name, func(t *testing.T) { + result := test.TestLint("e_subscribers_crl_distribution_points_are_http", tc.InputFilename) + if result.Status != tc.ExpectedResult { + t.Errorf("expected result %v was %v - details: %v", tc.ExpectedResult, result.Status, result.Details) + } + + if tc.ExpectedDetails != "" && tc.ExpectedDetails != result.Details { + t.Errorf("expected details: %s, was %s", tc.ExpectedDetails, result.Details) + } + }) + } +} diff --git a/v3/testdata/smime/legacy_subscriber_with_mixed_crl_distribution_points.pem b/v3/testdata/smime/legacy_subscriber_with_mixed_crl_distribution_points.pem new file mode 100644 index 000000000..f65ce5d29 --- /dev/null +++ b/v3/testdata/smime/legacy_subscriber_with_mixed_crl_distribution_points.pem @@ -0,0 +1,47 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 3 (0x3) + Signature Algorithm: ecdsa-with-SHA256 + Issuer: + Validity + Not Before: Feb 13 19:15:27 2024 GMT + Not After : Nov 30 00:00:00 9998 GMT + Subject: + Subject Public Key Info: + Public Key Algorithm: id-ecPublicKey + Public-Key: (256 bit) + pub: + 04:df:e4:01:1a:7b:25:62:45:ce:af:1a:0c:f6:34: + 35:ca:c6:25:a8:7a:b2:de:2e:13:6c:8e:82:96:57: + 1e:7b:a4:ab:b4:42:4b:25:8a:ec:13:2b:77:67:96: + fe:b4:c5:32:c4:e3:8f:9f:17:fd:3c:a4:e1:fb:2f: + f4:f5:b7:fe:99 + ASN1 OID: prime256v1 + NIST CURVE: P-256 + X509v3 extensions: + X509v3 Extended Key Usage: + E-mail Protection + X509v3 Certificate Policies: + Policy: 2.23.140.1.5.1.1 + X509v3 CRL Distribution Points: + Full Name: + URI:ldap://example.com + Full Name: + URI:http://example.com + Signature Algorithm: ecdsa-with-SHA256 + Signature Value: + 30:45:02:21:00:e1:7e:f6:31:49:1b:5d:ca:70:cc:b4:a7:3a: + 50:57:21:1f:77:ee:d1:49:c1:06:51:1d:a3:ce:fd:30:47:a8: + 5d:02:20:51:b7:49:53:5f:4d:2e:87:d3:0d:c0:ea:51:64:0e: + 7c:46:e2:30:18:1a:ac:80:4a:2a:9f:2d:3b:0f:7f:a5:67 +-----BEGIN CERTIFICATE----- +MIIBXTCCAQOgAwIBAgIBAzAKBggqhkjOPQQDAjAAMCAXDTI0MDIxMzE5MTUyN1oY +Dzk5OTgxMTMwMDAwMDAwWjAAMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE3+QB +GnslYkXOrxoM9jQ1ysYlqHqy3i4TbI6Cllcee6SrtEJLJYrsEyt3Z5b+tMUyxOOP +nxf9PKTh+y/09bf+maNsMGowEwYDVR0lBAwwCgYIKwYBBQUHAwQwFAYDVR0gBA0w +CzAJBgdngQwBBQEBMD0GA1UdHwQ2MDQwGKAWoBSGEmxkYXA6Ly9leGFtcGxlLmNv +bTAYoBagFIYSaHR0cDovL2V4YW1wbGUuY29tMAoGCCqGSM49BAMCA0gAMEUCIQDh +fvYxSRtdynDMtKc6UFchH3fu0UnBBlEdo879MEeoXQIgUbdJU19NLofTDcDqUWQO +fEbiMBgarIBKKp8tOw9/pWc= +-----END CERTIFICATE----- diff --git a/v3/testdata/smime/legacy_subscriber_with_non_http_crl_distribution_point.pem b/v3/testdata/smime/legacy_subscriber_with_non_http_crl_distribution_point.pem new file mode 100644 index 000000000..433000e52 --- /dev/null +++ b/v3/testdata/smime/legacy_subscriber_with_non_http_crl_distribution_point.pem @@ -0,0 +1,44 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 3 (0x3) + Signature Algorithm: ecdsa-with-SHA256 + Issuer: + Validity + Not Before: Dec 19 17:22:50 2023 GMT + Not After : Nov 30 00:00:00 9998 GMT + Subject: + Subject Public Key Info: + Public Key Algorithm: id-ecPublicKey + Public-Key: (256 bit) + pub: + 04:4c:6f:d1:2b:55:07:e8:4c:93:9f:89:29:eb:c5: + 3f:e1:d5:61:14:43:39:5f:ac:f7:db:af:3c:68:37: + ca:b4:94:d9:b6:06:da:d8:39:4e:d3:58:19:29:60: + 5a:32:f3:9e:20:df:2a:51:e8:c1:ca:1d:d0:be:c5: + 77:06:b5:09:6c + ASN1 OID: prime256v1 + NIST CURVE: P-256 + X509v3 extensions: + X509v3 Extended Key Usage: + E-mail Protection + X509v3 Certificate Policies: + Policy: 2.23.140.1.5.1.1 + X509v3 CRL Distribution Points: + Full Name: + URI:ldap://example.com + Signature Algorithm: ecdsa-with-SHA256 + Signature Value: + 30:44:02:20:37:8f:bc:61:b8:09:d3:bb:6e:c0:b6:ae:2a:64: + 1e:8e:02:60:dc:28:4a:74:88:bd:fb:a9:6f:e2:a8:3d:a1:b4: + 02:20:4e:db:12:05:79:b3:09:17:9b:66:b3:a3:d6:6b:45:52: + 7f:df:9b:58:93:36:13:1c:73:fb:78:95:4e:7f:ee:56 +-----BEGIN CERTIFICATE----- +MIIBQTCB6aADAgECAgEDMAoGCCqGSM49BAMCMAAwIBcNMjMxMjE5MTcyMjUwWhgP +OTk5ODExMzAwMDAwMDBaMAAwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAARMb9Er +VQfoTJOfiSnrxT/h1WEUQzlfrPfbrzxoN8q0lNm2BtrYOU7TWBkpYFoy854g3ypR +6MHKHdC+xXcGtQlso1IwUDATBgNVHSUEDDAKBggrBgEFBQcDBDAUBgNVHSAEDTAL +MAkGB2eBDAEFAQEwIwYDVR0fBBwwGjAYoBagFIYSbGRhcDovL2V4YW1wbGUuY29t +MAoGCCqGSM49BAMCA0cAMEQCIDePvGG4CdO7bsC2ripkHo4CYNwoSnSIvfupb+Ko +PaG0AiBO2xIFebMJF5tms6PWa0VSf9+bWJM2Exxz+3iVTn/uVg== +-----END CERTIFICATE----- diff --git a/v3/testdata/smime/strict_subscriber_with_http_crl_distribution_point.pem b/v3/testdata/smime/strict_subscriber_with_http_crl_distribution_point.pem new file mode 100644 index 000000000..11834e698 --- /dev/null +++ b/v3/testdata/smime/strict_subscriber_with_http_crl_distribution_point.pem @@ -0,0 +1,44 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 3 (0x3) + Signature Algorithm: ecdsa-with-SHA256 + Issuer: + Validity + Not Before: Dec 13 22:18:21 2023 GMT + Not After : Nov 30 00:00:00 9998 GMT + Subject: + Subject Public Key Info: + Public Key Algorithm: id-ecPublicKey + Public-Key: (256 bit) + pub: + 04:c8:dc:df:60:b9:e2:c3:90:c7:c6:03:32:04:e1: + 4a:de:08:08:24:4c:0c:97:ed:3a:31:0f:7b:ed:47: + a0:a9:af:df:04:9d:eb:7c:df:64:87:ab:2d:f2:60: + 42:2d:65:3e:18:4d:cb:12:2e:fb:74:ef:7f:3b:ae: + 0a:e3:f3:56:d3 + ASN1 OID: prime256v1 + NIST CURVE: P-256 + X509v3 extensions: + X509v3 Extended Key Usage: + E-mail Protection + X509v3 Certificate Policies: + Policy: 2.23.140.1.5.1.3 + X509v3 CRL Distribution Points: + Full Name: + URI:http://example.com + Signature Algorithm: ecdsa-with-SHA256 + Signature Value: + 30:45:02:20:0c:0b:81:2d:9c:12:c2:86:59:1a:cd:1f:46:3c: + b4:22:a0:91:0c:33:3f:ad:f4:4d:a7:64:34:d8:37:ab:53:eb: + 02:21:00:c7:d4:f1:98:29:55:db:fe:3e:21:1e:0e:db:58:57: + c1:04:20:2f:d8:6f:53:74:05:ce:ec:f0:c4:63:0e:4d:09 +-----BEGIN CERTIFICATE----- +MIIBQjCB6aADAgECAgEDMAoGCCqGSM49BAMCMAAwIBcNMjMxMjEzMjIxODIxWhgP +OTk5ODExMzAwMDAwMDBaMAAwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAATI3N9g +ueLDkMfGAzIE4UreCAgkTAyX7ToxD3vtR6Cpr98Enet832SHqy3yYEItZT4YTcsS +Lvt07387rgrj81bTo1IwUDATBgNVHSUEDDAKBggrBgEFBQcDBDAUBgNVHSAEDTAL +MAkGB2eBDAEFAQMwIwYDVR0fBBwwGjAYoBagFIYSaHR0cDovL2V4YW1wbGUuY29t +MAoGCCqGSM49BAMCA0gAMEUCIAwLgS2cEsKGWRrNH0Y8tCKgkQwzP630TadkNNg3 +q1PrAiEAx9TxmClV2/4+IR4O21hXwQQgL9hvU3QFzuzwxGMOTQk= +-----END CERTIFICATE----- diff --git a/v3/testdata/smime/strict_subscriber_with_mixed_crl_distribution_points.pem b/v3/testdata/smime/strict_subscriber_with_mixed_crl_distribution_points.pem new file mode 100644 index 000000000..b70d8b27e --- /dev/null +++ b/v3/testdata/smime/strict_subscriber_with_mixed_crl_distribution_points.pem @@ -0,0 +1,47 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 3 (0x3) + Signature Algorithm: ecdsa-with-SHA256 + Issuer: + Validity + Not Before: Feb 13 19:20:31 2024 GMT + Not After : Nov 30 00:00:00 9998 GMT + Subject: + Subject Public Key Info: + Public Key Algorithm: id-ecPublicKey + Public-Key: (256 bit) + pub: + 04:7d:26:16:25:1e:57:16:05:f0:e2:95:77:56:b8: + f6:66:c0:ba:1a:35:fd:6c:57:3d:07:16:c7:fc:44: + 67:32:41:b9:f6:1e:94:91:ad:37:90:28:34:45:70: + 32:c0:9e:64:e8:9a:14:55:41:ff:19:87:fb:43:0b: + 25:c2:8d:3d:f5 + ASN1 OID: prime256v1 + NIST CURVE: P-256 + X509v3 extensions: + X509v3 Extended Key Usage: + E-mail Protection + X509v3 Certificate Policies: + Policy: 2.23.140.1.5.1.3 + X509v3 CRL Distribution Points: + Full Name: + URI:ldap://example.com + Full Name: + URI:http://example.com + Signature Algorithm: ecdsa-with-SHA256 + Signature Value: + 30:45:02:21:00:eb:f3:1b:63:15:c8:38:41:05:24:c1:29:51: + 12:23:99:d6:aa:86:a2:5e:37:eb:48:13:8b:51:19:33:97:f4: + c1:02:20:7b:02:fd:c7:4f:7d:ff:fd:1b:b2:7e:66:f8:b9:d5: + e5:be:8b:18:8a:f2:3e:55:33:84:dd:cb:ae:19:ad:c8:c0 +-----BEGIN CERTIFICATE----- +MIIBXTCCAQOgAwIBAgIBAzAKBggqhkjOPQQDAjAAMCAXDTI0MDIxMzE5MjAzMVoY +Dzk5OTgxMTMwMDAwMDAwWjAAMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEfSYW +JR5XFgXw4pV3Vrj2ZsC6GjX9bFc9BxbH/ERnMkG59h6Uka03kCg0RXAywJ5k6JoU +VUH/GYf7Qwslwo099aNsMGowEwYDVR0lBAwwCgYIKwYBBQUHAwQwFAYDVR0gBA0w +CzAJBgdngQwBBQEDMD0GA1UdHwQ2MDQwGKAWoBSGEmxkYXA6Ly9leGFtcGxlLmNv +bTAYoBagFIYSaHR0cDovL2V4YW1wbGUuY29tMAoGCCqGSM49BAMCA0gAMEUCIQDr +8xtjFcg4QQUkwSlREiOZ1qqGol4360gTi1EZM5f0wQIgewL9x099//0bsn5m+LnV +5b6LGIryPlUzhN3LrhmtyMA= +-----END CERTIFICATE----- diff --git a/v3/testdata/smime/strict_subscriber_with_non_http_crl_distribution_point.pem b/v3/testdata/smime/strict_subscriber_with_non_http_crl_distribution_point.pem new file mode 100644 index 000000000..dd401daa4 --- /dev/null +++ b/v3/testdata/smime/strict_subscriber_with_non_http_crl_distribution_point.pem @@ -0,0 +1,44 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 3 (0x3) + Signature Algorithm: ecdsa-with-SHA256 + Issuer: + Validity + Not Before: Dec 13 22:06:27 2023 GMT + Not After : Nov 30 00:00:00 9998 GMT + Subject: + Subject Public Key Info: + Public Key Algorithm: id-ecPublicKey + Public-Key: (256 bit) + pub: + 04:55:ab:f1:eb:ba:b6:de:14:c5:9f:02:33:86:2d: + 85:61:4a:b1:21:cf:3f:7e:95:37:fc:98:8d:21:a5: + a5:26:df:51:f4:97:9d:ec:b5:d0:c4:2b:41:66:52: + e0:a6:c4:a6:3f:0a:f3:fd:90:6a:2e:0a:b9:33:27: + c2:56:df:ae:19 + ASN1 OID: prime256v1 + NIST CURVE: P-256 + X509v3 extensions: + X509v3 Extended Key Usage: + E-mail Protection + X509v3 Certificate Policies: + Policy: 2.23.140.1.5.1.3 + X509v3 CRL Distribution Points: + Full Name: + URI:ldap://example.com + Signature Algorithm: ecdsa-with-SHA256 + Signature Value: + 30:45:02:20:05:60:ca:c3:8c:12:a6:58:6f:d3:7f:e9:82:cc: + 38:ec:1e:dc:51:88:a1:45:f2:37:64:47:d4:96:1f:9c:1e:ef: + 02:21:00:93:d1:b3:6a:b5:32:69:e0:14:be:8f:70:d9:1c:54: + 7d:1a:cd:7f:5a:a5:d2:30:ad:a2:9c:fa:37:66:8a:31:61 +-----BEGIN CERTIFICATE----- +MIIBQjCB6aADAgECAgEDMAoGCCqGSM49BAMCMAAwIBcNMjMxMjEzMjIwNjI3WhgP +OTk5ODExMzAwMDAwMDBaMAAwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAARVq/Hr +urbeFMWfAjOGLYVhSrEhzz9+lTf8mI0hpaUm31H0l53stdDEK0FmUuCmxKY/CvP9 +kGouCrkzJ8JW364Zo1IwUDATBgNVHSUEDDAKBggrBgEFBQcDBDAUBgNVHSAEDTAL +MAkGB2eBDAEFAQMwIwYDVR0fBBwwGjAYoBagFIYSbGRhcDovL2V4YW1wbGUuY29t +MAoGCCqGSM49BAMCA0gAMEUCIAVgysOMEqZYb9N/6YLMOOwe3FGIoUXyN2RH1JYf +nB7vAiEAk9GzarUyaeAUvo9w2RxUfRrNf1ql0jCtopz6N2aKMWE= +-----END CERTIFICATE-----