Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Permit underscores in DNSNames if-and-only-if those certificates are valid for less than 30 days and during BR 1.6.2's permissibility period #660

Merged
merged 17 commits into from
Sep 27, 2023
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 59 additions & 0 deletions v3/lints/cabf_br/lint_underscore_present_with_too_long_validity.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
/*
* ZLint Copyright 2021 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_br

import (
"fmt"
"strings"
"time"

"github.com/zmap/zcrypto/x509"
"github.com/zmap/zlint/v3/lint"
"github.com/zmap/zlint/v3/util"
)

func init() {
lint.RegisterLint(&lint.Lint{
Name: "e_underscore_present_with_too_long_validity",
Description: "From December 10th 2018 to April 1st 2019 DNSNames may contain underscores if-and-only-if the certificate is valid for less than thirty days.",
christopher-henderson marked this conversation as resolved.
Show resolved Hide resolved
Citation: "BR 7.1.4.2.1",
Source: lint.CABFBaselineRequirements,
EffectiveDate: util.CABFBRs_1_6_2_Date,
IneffectiveDate: util.BALLOT_SC_12_Ineffective,
Lint: func() lint.LintInterface { return &UnderscorePresentWithTooLongValidity{} },
})
}

type UnderscorePresentWithTooLongValidity struct{}

func (l *UnderscorePresentWithTooLongValidity) CheckApplies(c *x509.Certificate) bool {
return util.IsSubscriberCert(c) && util.DNSNamesExist(c)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can/should the check from 47 - 49 be moved here?

Suggested change
return util.IsSubscriberCert(c) && util.DNSNamesExist(c)
return util.IsSubscriberCert(c) &&
util.DNSNamesExist(c) &&
c.NotBefore.AddDate(0, 0, 30).Before(c.NotAfter)

Might be a way to simplify further. But is a bit of a suggestion

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think so? If we do this check here then what we would be saying is that this lint does not apply to this certificate at all (which is usually reserved for scenarios such as being an irrelevant cert type or not having a particular field).

I do prefer that method of adding 30 days, though. Far more correct than the naive time.Hour*24*30.

}

func (l *UnderscorePresentWithTooLongValidity) Execute(c *x509.Certificate) *lint.LintResult {
validity := c.NotAfter.Sub(c.NotBefore)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Something something "inclusive", but this predates the 5280 language coming over :)

if validity <= time.Hour*24*30 {
// Underscores are permissible if the cert is valid for less than thirty days
return &lint.LintResult{Status: lint.Pass}
}
for _, dns := range c.DNSNames {
if strings.Contains(dns, "_") {
return &lint.LintResult{Status: lint.Error, Details: fmt.Sprintf("The DNSName '%s' contains an "+
"underscore character which is only permissible if the certiticate is valid for less than 30 days "+
"(this certificate is valid for %d days)", dns, validity)}
}
}
return &lint.LintResult{Status: lint.Pass}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
/*
* ZLint Copyright 2021 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_br

import (
"testing"

"github.com/zmap/zlint/v3/lint"
"github.com/zmap/zlint/v3/test"
)

func TestNoUnderscoreBefore1_6_2(t *testing.T) {
testCases := []struct {
Name string
InputFilename string
ExpectedResult lint.LintStatus
}{
{
Name: "Underscores but 30 day validity",
InputFilename: "dNSUnderscoresShortValidity.pem",
ExpectedResult: lint.Pass,
},
{
Name: "Underscores with too long validity",
InputFilename: "dNSUnderscoresLongValidity.pem",
ExpectedResult: lint.Error,
},
{
Name: "No underscores",
InputFilename: "dNSNoUnderscoresLongValidity.pem",
ExpectedResult: lint.Pass,
},
{
Name: "Not effective",
InputFilename: "dNSUnderscoresPermissibleOutOfDateRange.pem",
ExpectedResult: lint.NE,
},
}
for _, tc := range testCases {
t.Run(tc.Name, func(t *testing.T) {
result := test.TestLint("e_underscore_present_with_too_long_validity", tc.InputFilename)
if result.Status != tc.ExpectedResult {
t.Errorf("expected result %v was %v", tc.ExpectedResult, result.Status)
}
})
}
}
37 changes: 37 additions & 0 deletions v3/testdata/dNSNoUnderscoresLongValidity.pem
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
Certificate:
Data:
Version: 3 (0x2)
Serial Number: 3 (0x3)
Signature Algorithm: ecdsa-with-SHA256
Issuer:
Validity
Not Before: Dec 11 00:00:00 2018 GMT
Not After : Jan 11 00:00:00 2019 GMT
Subject:
Subject Public Key Info:
Public Key Algorithm: id-ecPublicKey
Public-Key: (256 bit)
pub:
04:9d:46:d8:ce:3d:5f:ff:e2:70:6c:30:04:3f:0e:
aa:b0:7c:50:8c:48:89:6e:ee:19:e6:e4:e4:31:3a:
d0:41:e9:2d:b8:de:ef:99:fc:5e:26:fd:ef:b9:e0:
1a:6a:ab:c5:15:8a:b8:b5:2c:7a:ac:7e:b8:70:61:
58:88:2c:52:38
ASN1 OID: prime256v1
NIST CURVE: P-256
X509v3 extensions:
X509v3 Subject Alternative Name:
DNS:no.underscore.com
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ditto re: .test fixes

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done (thank you for your patience on this, I've been traveling for business and I almost missed a flight trying to juggle these similiar-but-different certs so I just punted for the week).

Signature Algorithm: ecdsa-with-SHA256
30:45:02:21:00:b3:76:a9:18:1a:5a:bd:70:9b:6c:52:b3:b8:
84:61:cc:e7:a5:98:b0:8a:fb:fc:86:ee:d5:9c:5b:19:47:16:
4d:02:20:57:6e:7c:7f:a9:fa:4d:71:df:30:f6:21:69:20:78:
99:a4:51:7a:06:56:4d:05:17:ed:43:45:07:6e:72:52:cd
-----BEGIN CERTIFICATE-----
MIIBDjCBtaADAgECAgEDMAoGCCqGSM49BAMCMAAwHhcNMTgxMjExMDAwMDAwWhcN
MTkwMTExMDAwMDAwWjAAMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEnUbYzj1f
/+JwbDAEPw6qsHxQjEiJbu4Z5uTkMTrQQektuN7vmfxeJv3vueAaaqvFFYq4tSx6
rH64cGFYiCxSOKMgMB4wHAYDVR0RBBUwE4IRbm8udW5kZXJzY29yZS5jb20wCgYI
KoZIzj0EAwIDSAAwRQIhALN2qRgaWr1wm2xSs7iEYcznpZiwivv8hu7VnFsZRxZN
AiBXbnx/qfpNcd8w9iFpIHiZpFF6BlZNBRftQ0UHbnJSzQ==
-----END CERTIFICATE-----
37 changes: 37 additions & 0 deletions v3/testdata/dNSUnderscoresLongValidity.pem
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
Certificate:
Data:
Version: 3 (0x2)
Serial Number: 3 (0x3)
Signature Algorithm: ecdsa-with-SHA256
Issuer:
Validity
Not Before: Dec 11 00:00:00 2018 GMT
Not After : Jan 11 00:00:00 2019 GMT
Subject:
Subject Public Key Info:
Public Key Algorithm: id-ecPublicKey
Public-Key: (256 bit)
pub:
04:8d:eb:c3:b3:a2:53:99:f6:ce:1a:19:ee:82:5a:
c7:f8:a7:4b:29:11:2c:19:da:b7:d3:85:7a:b0:d9:
41:0b:3d:71:9e:4d:30:c1:27:bf:8d:3f:79:db:c2:
c8:6d:e2:b8:41:c1:1c:72:7c:10:de:24:6e:f8:88:
08:11:64:be:75
ASN1 OID: prime256v1
NIST CURVE: P-256
X509v3 extensions:
X509v3 Subject Alternative Name:
DNS:with.an_underscore.com
Signature Algorithm: ecdsa-with-SHA256
30:44:02:20:2e:cc:49:27:0f:d6:01:0d:60:98:ce:f6:1b:b3:
35:f6:66:ea:76:5f:e3:43:7e:17:f0:6f:55:38:c9:d5:76:d6:
02:20:5a:10:02:7c:8e:45:33:72:5e:8a:9d:4e:e2:bc:68:4c:
75:82:df:0a:a4:63:c0:8c:73:8a:b7:ac:71:d4:f8:07
-----BEGIN CERTIFICATE-----
MIIBEjCBuqADAgECAgEDMAoGCCqGSM49BAMCMAAwHhcNMTgxMjExMDAwMDAwWhcN
MTkwMTExMDAwMDAwWjAAMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEjevDs6JT
mfbOGhnuglrH+KdLKREsGdq304V6sNlBCz1xnk0wwSe/jT9528LIbeK4QcEccnwQ
3iRu+IgIEWS+daMlMCMwIQYDVR0RBBowGIIWd2l0aC5hbl91bmRlcnNjb3JlLmNv
bTAKBggqhkjOPQQDAgNHADBEAiAuzEknD9YBDWCYzvYbszX2Zup2X+NDfhfwb1U4
ydV21gIgWhACfI5FM3Jeip1O4rxoTHWC3wqkY8CMc4q3rHHU+Ac=
-----END CERTIFICATE-----
37 changes: 37 additions & 0 deletions v3/testdata/dNSUnderscoresPermissibleOutOfDateRange.pem
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
Certificate:
Data:
Version: 3 (0x2)
Serial Number: 3 (0x3)
Signature Algorithm: ecdsa-with-SHA256
Issuer:
Validity
Not Before: Feb 6 18:40:00 2022 GMT
Not After : Feb 6 18:40:00 2022 GMT
Subject:
Subject Public Key Info:
Public Key Algorithm: id-ecPublicKey
Public-Key: (256 bit)
pub:
04:e0:4c:d9:e7:ca:e9:5c:4d:30:55:1d:1d:03:c9:
bb:87:fe:cc:a0:fe:f8:be:76:21:2c:7c:63:39:66:
f1:2b:fb:42:14:a3:52:32:8e:38:38:1b:bc:7c:09:
28:3d:20:05:c5:8c:80:68:c6:a2:d1:6b:99:95:74:
0c:e2:af:eb:a3
ASN1 OID: prime256v1
NIST CURVE: P-256
X509v3 extensions:
X509v3 Subject Alternative Name:
DNS:with.an_underscore.com
Signature Algorithm: ecdsa-with-SHA256
30:46:02:21:00:a4:d9:a5:37:51:3c:a7:93:4f:19:38:98:cf:
b1:30:60:b8:7d:1e:fa:d2:21:2c:30:15:2e:29:96:f4:e6:c2:
68:02:21:00:86:ea:41:1e:82:d7:d5:40:60:89:cd:75:6c:15:
29:f1:1e:40:9b:17:71:48:ee:4e:e3:b7:c1:67:1e:5c:bf:90
-----BEGIN CERTIFICATE-----
MIIBFDCBuqADAgECAgEDMAoGCCqGSM49BAMCMAAwHhcNMjIwMjA2MTg0MDAwWhcN
MjIwMjA2MTg0MDAwWjAAMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE4EzZ58rp
XE0wVR0dA8m7h/7MoP74vnYhLHxjOWbxK/tCFKNSMo44OBu8fAkoPSAFxYyAaMai
0WuZlXQM4q/ro6MlMCMwIQYDVR0RBBowGIIWd2l0aC5hbl91bmRlcnNjb3JlLmNv
bTAKBggqhkjOPQQDAgNJADBGAiEApNmlN1E8p5NPGTiYz7EwYLh9HvrSISwwFS4p
lvTmwmgCIQCG6kEegtfVQGCJzXVsFSnxHkCbF3FI7k7jt8FnHly/kA==
-----END CERTIFICATE-----
37 changes: 37 additions & 0 deletions v3/testdata/dNSUnderscoresShortValidity.pem
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
Certificate:
Data:
Version: 3 (0x2)
Serial Number: 3 (0x3)
Signature Algorithm: ecdsa-with-SHA256
Issuer:
Validity
Not Before: Dec 11 00:00:00 2018 GMT
Not After : Dec 12 00:00:00 2018 GMT
Subject:
Subject Public Key Info:
Public Key Algorithm: id-ecPublicKey
Public-Key: (256 bit)
pub:
04:1b:2c:2f:bf:60:24:c7:17:aa:eb:e9:d6:da:a0:
cb:b3:ea:68:01:9e:bb:5c:e0:26:a1:04:74:ee:8b:
a6:e4:33:b1:37:f9:1e:79:b3:c4:a6:f3:f6:74:9c:
4b:0e:5b:b7:64:36:3a:73:98:b5:9e:4d:aa:9c:40:
c5:29:01:b3:4a
ASN1 OID: prime256v1
NIST CURVE: P-256
X509v3 extensions:
X509v3 Subject Alternative Name:
DNS:with.an_underscore.com
Signature Algorithm: ecdsa-with-SHA256
30:45:02:20:0e:b7:14:8f:39:71:8b:95:0a:10:74:50:f6:d3:
d9:72:8c:8a:7f:67:00:d5:cf:2f:c6:72:bd:14:fa:07:1d:aa:
02:21:00:c3:27:e4:12:b1:8d:e4:6e:a2:70:61:bf:ef:23:db:
6d:a4:10:ff:b5:3a:d2:80:d9:84:54:a9:18:a9:88:e7:74
-----BEGIN CERTIFICATE-----
MIIBEzCBuqADAgECAgEDMAoGCCqGSM49BAMCMAAwHhcNMTgxMjExMDAwMDAwWhcN
MTgxMjEyMDAwMDAwWjAAMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEGywvv2Ak
xxeq6+nW2qDLs+poAZ67XOAmoQR07oum5DOxN/keebPEpvP2dJxLDlu3ZDY6c5i1
nk2qnEDFKQGzSqMlMCMwIQYDVR0RBBowGIIWd2l0aC5hbl91bmRlcnNjb3JlLmNv
bTAKBggqhkjOPQQDAgNIADBFAiAOtxSPOXGLlQoQdFD209lyjIp/ZwDVzy/Gcr0U
+gcdqgIhAMMn5BKxjeRuonBhv+8j222kEP+1OtKA2YRUqRipiOd0
-----END CERTIFICATE-----
2 changes: 2 additions & 0 deletions v3/util/time.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,10 @@ var (
MozillaPolicy24Date = time.Date(2017, time.February, 28, 0, 0, 0, 0, time.UTC)
MozillaPolicy241Date = time.Date(2017, time.March, 31, 0, 0, 0, 0, time.UTC)
MozillaPolicy27Date = time.Date(2020, time.January, 1, 0, 0, 0, 0, time.UTC)
BALLOT_SC_12_Ineffective = time.Date(2019, time.April, 1, 0, 0, 0, 0, time.UTC)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
BALLOT_SC_12_Ineffective = time.Date(2019, time.April, 1, 0, 0, 0, 0, time.UTC)
BallotSC12Ineffective = time.Date(2019, time.April, 1, 0, 0, 0, 0, time.UTC)

WDYT? (e.g. lines 47-62)

Copy link
Member Author

@christopher-henderson christopher-henderson Feb 14, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, I hop back-and-forth between Go/Rust/Python/Java often enough that the naming conventions bleed over each other sometimes.

And yeah, with regard to the certs, they may be duplicates DNS names but I believe that I did generate entirely different ones just for the sake of tests not sharing literally same test certs, which you can easily imagine exploding in someone's face in the future (and also because merge management woulda been a little annoying).

CABFBRs_1_2_1_Date = time.Date(2015, time.January, 16, 0, 0, 0, 0, time.UTC)
CABFBRs_1_6_9_Date = time.Date(2020, time.March, 27, 0, 0, 0, 0, time.UTC)
CABFBRs_1_6_2_Date = time.Date(2018, time.December, 10, 0, 0, 0, 0, time.UTC)
CABFBRs_1_7_1_Date = time.Date(2020, time.August, 20, 0, 0, 0, 0, time.UTC)
AppleReducedLifetimeDate = time.Date(2020, time.September, 1, 0, 0, 0, 0, time.UTC)
CABFBRs_1_8_0_Date = time.Date(2021, time.August, 21, 0, 0, 0, 0, time.UTC)
Expand Down