diff --git a/go.mod b/go.mod index 52925ba..7aa8ed5 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,7 @@ go 1.24.2 require ( github.com/zmap/zcrypto v0.0.0-20250418211859-7510c141e4b7 - github.com/zmap/zlint/v3 v3.6.6 + github.com/zmap/zlint/v3 v3.6.7 ) require ( diff --git a/go.sum b/go.sum index 43b04bd..b4210e9 100644 --- a/go.sum +++ b/go.sum @@ -14,18 +14,12 @@ github.com/weppos/publicsuffix-go v0.40.3-0.20250408071509-6074bbe7fd39 h1:Bz/zV github.com/weppos/publicsuffix-go v0.40.3-0.20250408071509-6074bbe7fd39/go.mod h1:2oFzEwGYI7lhiqG0YkkcKa6VcpjVinQbWxaPzytDmLA= github.com/zmap/zcrypto v0.0.0-20250418211859-7510c141e4b7 h1:EMuQ1vVR92UNChHMxYVBwCRSdU3UOiBaotqX0CvEGwc= github.com/zmap/zcrypto v0.0.0-20250418211859-7510c141e4b7/go.mod h1:GEZQan3t3hrYRBTDj+R6NVHWbrlgbFIEJIIuW7eKgSI= -github.com/zmap/zlint/v3 v3.6.6 h1:tH7RJM9bDmh7IonlLEkFIkIn8XDYDYjehhUPgpLVqYA= -github.com/zmap/zlint/v3 v3.6.6/go.mod h1:6yXG+CBOQBRpMCOnpIVPUUL296m5HYksZC9bj5LZkwE= -golang.org/x/crypto v0.37.0 h1:kJNSjF/Xp7kU0iB2Z+9viTPMW4EqqsrywMXLJOOsXSE= -golang.org/x/crypto v0.37.0/go.mod h1:vg+k43peMZ0pUMhYmVAWysMK35e6ioLh3wB8ZCAfbVc= +github.com/zmap/zlint/v3 v3.6.7 h1:ETRdgQ0MpcoyZqGGhBINCWnlFJ8TmmFotX9ezjzQRsU= +github.com/zmap/zlint/v3 v3.6.7/go.mod h1:Tm0qwwaO629pgJ/En7M9U9Edx4+rQRuoeXVpXvgVHhA= golang.org/x/crypto v0.38.0 h1:jt+WWG8IZlBnVbomuhg2Mdq0+BBQaHbtqHEFEigjUV8= golang.org/x/crypto v0.38.0/go.mod h1:MvrbAqul58NNYPKnOra203SB9vpuZW0e+RRZV+Ggqjw= -golang.org/x/net v0.39.0 h1:ZCu7HMWDxpXpaiKdhzIfaltL9Lp31x/3fCP11bc6/fY= -golang.org/x/net v0.39.0/go.mod h1:X7NRbYVEA+ewNkCNyJ513WmMdQ3BineSwVtN2zD/d+E= golang.org/x/net v0.40.0 h1:79Xs7wF06Gbdcg4kdCCIQArK11Z1hr5POQ6+fIYHNuY= golang.org/x/net v0.40.0/go.mod h1:y0hY0exeL2Pku80/zKK7tpntoX23cqL3Oa6njdgRtds= -golang.org/x/text v0.24.0 h1:dd5Bzh4yt5KYA8f9CJHCP4FB4D51c2c6JvN37xJJkJ0= -golang.org/x/text v0.24.0/go.mod h1:L8rBsPeo2pSS+xqN0d5u2ikmjtmoJbDBT1b7nHvFCdU= golang.org/x/text v0.25.0 h1:qVyWApTSYLk/drJRO5mDlNYskwQznZmkpV2c8q9zls4= golang.org/x/text v0.25.0/go.mod h1:WEdwpYrmk1qmdHvhkSTNPm3app7v4rsT8F2UD6+VHIA= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= diff --git a/vendor/github.com/pelletier/go-toml/example-crlf.toml b/vendor/github.com/pelletier/go-toml/example-crlf.toml index f45bf88..780d9c6 100644 --- a/vendor/github.com/pelletier/go-toml/example-crlf.toml +++ b/vendor/github.com/pelletier/go-toml/example-crlf.toml @@ -1,30 +1,30 @@ -# This is a TOML document. Boom. - -title = "TOML Example" - -[owner] -name = "Tom Preston-Werner" -organization = "GitHub" -bio = "GitHub Cofounder & CEO\nLikes tater tots and beer." -dob = 1979-05-27T07:32:00Z # First class dates? Why not? - -[database] -server = "192.168.1.1" -ports = [ 8001, 8001, 8002 ] -connection_max = 5000 -enabled = true - -[servers] - - # You can indent as you please. Tabs or spaces. TOML don't care. - [servers.alpha] - ip = "10.0.0.1" - dc = "eqdc10" - - [servers.beta] - ip = "10.0.0.2" - dc = "eqdc10" - -[clients] -data = [ ["gamma", "delta"], [1, 2] ] # just an update to make sure parsers support it +# This is a TOML document. Boom. + +title = "TOML Example" + +[owner] +name = "Tom Preston-Werner" +organization = "GitHub" +bio = "GitHub Cofounder & CEO\nLikes tater tots and beer." +dob = 1979-05-27T07:32:00Z # First class dates? Why not? + +[database] +server = "192.168.1.1" +ports = [ 8001, 8001, 8002 ] +connection_max = 5000 +enabled = true + +[servers] + + # You can indent as you please. Tabs or spaces. TOML don't care. + [servers.alpha] + ip = "10.0.0.1" + dc = "eqdc10" + + [servers.beta] + ip = "10.0.0.2" + dc = "eqdc10" + +[clients] +data = [ ["gamma", "delta"], [1, 2] ] # just an update to make sure parsers support it score = 4e-08 # to make sure leading zeroes in exponent parts of floats are supported \ No newline at end of file diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_ca_aia_non_http_url.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_ca_aia_non_http_url.go new file mode 100644 index 0000000..e241703 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_ca_aia_non_http_url.go @@ -0,0 +1,69 @@ +/* + * ZLint Copyright 2024 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 ( + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" + + "strings" +) + +func init() { + lint.RegisterCertificateLint(&lint.CertificateLint{ + LintMetadata: lint.LintMetadata{ + Name: "e_ca_aia_non_http_url", + Description: "Within the AIA extension of CA certificates, accessLocations must contain HTTP URLs", + Citation: "CABF BRs section 7.1.2.10.3 (CA Certificate Authority Information Access)", + Source: lint.CABFBaselineRequirements, + EffectiveDate: util.SC62EffectiveDate, + }, + Lint: NewCAAIANonHTTPURL, + }) +} + +type CAAIANonHTTPURL struct{} + +func NewCAAIANonHTTPURL() lint.LintInterface { + return &CAAIANonHTTPURL{} +} + +func (l *CAAIANonHTTPURL) CheckApplies(c *x509.Certificate) bool { + return util.IsSubCA(c) && + (len(c.IssuingCertificateURL) > 0 || len(c.OCSPServer) > 0) +} + +func (l *CAAIANonHTTPURL) Execute(c *x509.Certificate) *lint.LintResult { + for _, url := range c.IssuingCertificateURL { + if !strings.HasPrefix(strings.ToLower(url), "http://") { + return &lint.LintResult{ + Status: lint.Error, + Details: "For the 'caIssuers' accessMethod within the AIA extension, accessLocation must contain an HTTP URL", + } + } + } + + for _, url := range c.OCSPServer { + if !strings.HasPrefix(strings.ToLower(url), "http://") { + return &lint.LintResult{ + Status: lint.Error, + Details: "For the 'ocsp' accessMethod within the AIA extension, accessLocation must contain an HTTP URL", + } + } + } + + return &lint.LintResult{Status: lint.Pass} +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_ca_multiple_reserved_policy_oids.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_ca_multiple_reserved_policy_oids.go new file mode 100644 index 0000000..a2f9007 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_ca_multiple_reserved_policy_oids.go @@ -0,0 +1,93 @@ +/* + * ZLint Copyright 2024 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 ( + "github.com/zmap/zcrypto/encoding/asn1" + "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_ca_multiple_reserved_policy_oids", + Description: "The CA MUST include exactly one Reserved Certificate Policy Identifier", + Citation: "CABF BRs §7.1.2.10.5, Table 73 (Policy Restricted)", + Source: lint.CABFBaselineRequirements, + EffectiveDate: util.CABFBRs_2_0_0_Date, + }, + Lint: NewCAMultipleReservedPolicyOIDs, + }) +} + +type CAMultipleReservedPolicyOIDs struct { + CrossCert bool `comment:"Set this to true if the certificate to be linted is a cross-certificate"` +} + +func NewCAMultipleReservedPolicyOIDs() lint.LintInterface { + return &CAMultipleReservedPolicyOIDs{ + CrossCert: false, + } +} + +func (l *CAMultipleReservedPolicyOIDs) Configure() interface{} { + return l +} + +func (l *CAMultipleReservedPolicyOIDs) CheckApplies(c *x509.Certificate) bool { + // Exclude non-policy-restricted SubCAs and cross-certificates + return util.IsSubCA(c) && isPolicyRestricted(c) && !l.CrossCert +} + +func (l *CAMultipleReservedPolicyOIDs) Execute(c *x509.Certificate) *lint.LintResult { + if hasMultipleReservedPolicyOIDs(c) { + return &lint.LintResult{ + Status: lint.Error, + Details: "A Subordinate CA certificate MUST include exactly one Reserved Certificate Policy Identifier", + } + } + return &lint.LintResult{Status: lint.Pass} +} + +// By definition, a Policy Restricted CA is one that does NOT +// contain the anyPolicy OID in its CertificatePolicies extension +func isPolicyRestricted(c *x509.Certificate) bool { + return !util.SliceContainsOID(c.PolicyIdentifiers, util.AnyPolicyOID) +} + +func hasMultipleReservedPolicyOIDs(c *x509.Certificate) bool { + cabfReservedPolicyOIDs := []asn1.ObjectIdentifier{ + util.BRDomainValidatedOID, + util.BROrganizationValidatedOID, + util.BRIndividualValidatedOID, + util.BRExtendedValidatedOID, + } + + // This way we also detect the weird case of multiple instances of + // the same reserved policy OID, but this would still be an error... + alreadyFoundOne := false + for _, oid := range c.PolicyIdentifiers { + if util.SliceContainsOID(cabfReservedPolicyOIDs, oid) { + if alreadyFoundOne { + return true + } else { + alreadyFoundOne = true + } + } + } + return false +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_crl_extensions.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_crl_extensions.go new file mode 100644 index 0000000..d090db9 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_crl_extensions.go @@ -0,0 +1,119 @@ +/* + * ZLint Copyright 2024 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" + + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zcrypto/x509/pkix" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +func init() { + lint.RegisterRevocationListLint(&lint.RevocationListLint{ + LintMetadata: lint.LintMetadata{ + Name: "e_crl_extensions_validity", + Description: "Checks that only allowed extensions are present in a CRL and that their criticality is set correctly.", + Citation: "BRs: 7.2.2", + Source: lint.CABFBaselineRequirements, + }, + Lint: func() lint.RevocationListLintInterface { return &crlExtensions{} }, + }) +} + +type crlExtensions struct { + // allowedExtensions maps the OID of an allowed extension to a boolean + // indicating whether the extension MUST be marked critical. + allowedExtensions map[string]bool + + // discouragedExtensions contains OIDs of extensions that are not forbidden + // but should be noted with a warning. + discouragedExtensions map[string]struct{} +} + +// newCRLExtensions initializes and returns a new crlExtensions lint. +// This function is not called directly but is used by the ZLint framework. +func (l *crlExtensions) Initialize() { + l.allowedExtensions = map[string]bool{ + util.CRLNumberOID.String(): false, // cRLNumber + util.AuthkeyOID.String(): false, // authorityKeyIdentifier + util.CrlDistOID.String(): true, // issuingDistributionPoint + } + l.discouragedExtensions = map[string]struct{}{ + util.IssuerAlternateNameOID.String(): {}, // issuerAltName + util.DeltaCRLIndicatorOID.String(): {}, // deltaCRLIndicator + util.FreshCRLOID.String(): {}, // freshestCRL + util.AiaOID.String(): {}, // authorityInfoAccess + } +} + +// CheckApplies returns true for any CRL, as all CRLs must be checked for extension validity. +func (l *crlExtensions) CheckApplies(c *x509.RevocationList) bool { + return true +} + +// isExtensionAllowed checks if a given extension is in the list of allowed or discouraged extensions. +func (l *crlExtensions) isExtensionAllowed(ext pkix.Extension) bool { + oid := ext.Id.String() + if _, ok := l.allowedExtensions[oid]; ok { + return true + } + if _, ok := l.discouragedExtensions[oid]; ok { + return true + } + return false +} + +// Execute performs the linting checks on the CRL extensions. +func (l *crlExtensions) Execute(c *x509.RevocationList) *lint.LintResult { + l.Initialize() + // First, check for any extensions that are explicitly forbidden. + for _, ext := range c.Extensions { + if !l.isExtensionAllowed(ext) { + return &lint.LintResult{ + Status: lint.Error, + Details: fmt.Sprintf("CRL must not contain forbidden extension %s", ext.Id), + } + } + } + + // Second, check that the criticality of allowed extensions is correct. + for _, ext := range c.Extensions { + oid := ext.Id.String() + if mustBeCritical, ok := l.allowedExtensions[oid]; ok { + if ext.Critical != mustBeCritical { + return &lint.LintResult{ + Status: lint.Error, + Details: fmt.Sprintf("CRL extension %s has incorrect criticality; expected %t, got %t", ext.Id, mustBeCritical, ext.Critical), + } + } + } + } + + // Third, warn about the presence of any discouraged extensions. + for _, ext := range c.Extensions { + oid := ext.Id.String() + if _, ok := l.discouragedExtensions[oid]; ok { + return &lint.LintResult{ + Status: lint.Warn, + Details: fmt.Sprintf("CRL contains discouraged extension %s", ext.Id), + } + } + } + + return &lint.LintResult{Status: lint.Pass} +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_crl_number_range.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_crl_number_range.go new file mode 100644 index 0000000..15a2724 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_crl_number_range.go @@ -0,0 +1,72 @@ +/* + * ZLint Copyright 2024 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" + "math/big" + + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" +) + +/* + * Baseline Requirements: 7.2.2 CRL and CRL entry extensions + * CRLNumber MUST be an INTEGER greater than or equal + * to zero (0) and less than 2^159 and convey a strictly + * increasing sequence. + */ + +func init() { + lint.RegisterRevocationListLint(&lint.RevocationListLint{ + LintMetadata: lint.LintMetadata{ + Name: "e_crl_number_out_of_range", + Description: "The CRL number must be greater than or equal to 0 and less than 2^159.", + Citation: "BRs: 7.2.2", + Source: lint.CABFBaselineRequirements, + }, + Lint: func() lint.RevocationListLintInterface { return &crlNumberLimit{} }, + }) +} + +type crlNumberLimit struct{} + +func (*crlNumberLimit) CheckApplies(c *x509.RevocationList) bool { + return true +} + +// Execute checks that the CRL number is within the valid range [0, 2^159). +func (*crlNumberLimit) Execute(c *x509.RevocationList) *lint.LintResult { + if c.Number == nil { + return &lint.LintResult{ + Status: lint.Error, + Details: "CRL number extension is missing", + } + } + if c.Number.Cmp(big.NewInt(0)) < 0 { + return &lint.LintResult{ + Status: lint.Error, + Details: fmt.Sprintf("CRL number is negative: %v", c.Number), + } + } + crlNumberUpperBound := new(big.Int).Exp(big.NewInt(2), big.NewInt(159), nil) + if c.Number.Cmp(crlNumberUpperBound) >= 0 { + return &lint.LintResult{ + Status: lint.Error, + Details: fmt.Sprintf("CRL number is greater than or equal to 2^159: %v", c.Number), + } + } + return &lint.LintResult{Status: lint.Pass} +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_e_server_cert_valid_time_longer_than_100_days.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_e_server_cert_valid_time_longer_than_100_days.go new file mode 100644 index 0000000..5a92ebc --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_e_server_cert_valid_time_longer_than_100_days.go @@ -0,0 +1,79 @@ +/* + * ZLint Copyright 2025 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" + + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type sc081SecondDate100ServerCertValidityTooLong struct{} + +/************************************************************************ + +CA/B-Forum SC-081 introduces new validity periods for certificates issued on or after + +March 15, 2026 +March 15, 2027 +March 15, 2029 + +The change in the requirements is described here: https://github.com/cabforum/servercert/pull/553/files + +Subscriber Certificates issued on or after 15 March 2026 and before 15 March 2027 SHOULD NOT have a Validity Period greater than 199 days and MUST NOT have a Validity Period greater than 200 days. + +Subscriber Certificates issued on or after 15 March 2027 and before 15 March 2029 SHOULD NOT have a Validity Period greater than 99 days and MUST NOT have a Validity Period greater than 100 days. + +Subscriber Certificates issued on or after 15 March 2029 SHOULD NOT have a Validity Period greater than 46 days and MUST NOT have a Validity Period greater than 47 days. + +| __Certificate issued on or after__ | __Certificate issued before__ | __Maximum Validity Period__ | +| -- | -- | -- | +| | March 15, 2026 | 398 days | +| March 15, 2026 | March 15, 2027 | 200 days | +| March 15, 2027 | March 15, 2029 | 100 days | +| March 15, 2029 | | 47 days | + +*************************************************************************/ + +func init() { + lint.RegisterCertificateLint(&lint.CertificateLint{ + LintMetadata: lint.LintMetadata{ + Name: "e_server_cert_valid_time_longer_than_100_days", + Description: "TLS server certificates issued on or after on or after March 15, 2027 00:00 GMT/UTC must not have a validity period greater than 100 days", + Citation: "https://github.com/cabforum/servercert/pull/553", + Source: lint.CABFBaselineRequirements, + EffectiveDate: util.CABF_SC081_SECOND_MILESTONE, + IneffectiveDate: util.CABF_SC081_THIRD_MILESTONE, + }, + Lint: NewSC081SecondDate100ServerCertValidityTooLong, + }) +} + +func NewSC081SecondDate100ServerCertValidityTooLong() lint.LintInterface { + return &sc081SecondDate100ServerCertValidityTooLong{} +} + +func (l *sc081SecondDate100ServerCertValidityTooLong) CheckApplies(c *x509.Certificate) bool { + return util.IsServerAuthCert(c) && !c.IsCA +} + +func (l *sc081SecondDate100ServerCertValidityTooLong) Execute(c *x509.Certificate) *lint.LintResult { + if util.GreaterThan(c, 100) { + return &lint.LintResult{Status: lint.Error, Details: fmt.Sprintf("Certificate is issued on or after March 15, 2027 and has a validity of %.0f days", util.CertificateValidityInDays(c))} + } + return &lint.LintResult{Status: lint.Pass} +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_e_server_cert_valid_time_longer_than_200_days.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_e_server_cert_valid_time_longer_than_200_days.go new file mode 100644 index 0000000..9990529 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_e_server_cert_valid_time_longer_than_200_days.go @@ -0,0 +1,79 @@ +/* + * ZLint Copyright 2025 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" + + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type sc081FirstDate200ServerCertValidityTooLong struct{} + +/************************************************************************ + +CA/B-Forum SC-081 introduces new validity periods for certificates issued on or after + +March 15, 2026 +March 15, 2027 +March 15, 2029 + +The change in the requirements is described here: https://github.com/cabforum/servercert/pull/553/files + +Subscriber Certificates issued on or after 15 March 2026 and before 15 March 2027 SHOULD NOT have a Validity Period greater than 199 days and MUST NOT have a Validity Period greater than 200 days. + +Subscriber Certificates issued on or after 15 March 2027 and before 15 March 2029 SHOULD NOT have a Validity Period greater than 99 days and MUST NOT have a Validity Period greater than 100 days. + +Subscriber Certificates issued on or after 15 March 2029 SHOULD NOT have a Validity Period greater than 46 days and MUST NOT have a Validity Period greater than 47 days. + +| __Certificate issued on or after__ | __Certificate issued before__ | __Maximum Validity Period__ | +| -- | -- | -- | +| | March 15, 2026 | 398 days | +| March 15, 2026 | March 15, 2027 | 200 days | +| March 15, 2027 | March 15, 2029 | 100 days | +| March 15, 2029 | | 47 days | + +*************************************************************************/ + +func init() { + lint.RegisterCertificateLint(&lint.CertificateLint{ + LintMetadata: lint.LintMetadata{ + Name: "e_server_cert_valid_time_longer_than_200_days", + Description: "TLS server certificates issued on or after on or after March 15, 2026 00:00 GMT/UTC must not have a validity period greater than 200 days", + Citation: "https://github.com/cabforum/servercert/pull/553", + Source: lint.CABFBaselineRequirements, + EffectiveDate: util.CABF_SC081_FIRST_MILESTONE, + IneffectiveDate: util.CABF_SC081_SECOND_MILESTONE, + }, + Lint: NewSC081FirstDate200ServerCertValidityTooLong, + }) +} + +func NewSC081FirstDate200ServerCertValidityTooLong() lint.LintInterface { + return &sc081FirstDate200ServerCertValidityTooLong{} +} + +func (l *sc081FirstDate200ServerCertValidityTooLong) CheckApplies(c *x509.Certificate) bool { + return util.IsServerAuthCert(c) && !c.IsCA +} + +func (l *sc081FirstDate200ServerCertValidityTooLong) Execute(c *x509.Certificate) *lint.LintResult { + if util.GreaterThan(c, 200) { + return &lint.LintResult{Status: lint.Error, Details: fmt.Sprintf("Certificate is issued on or after March 15, 2026 and has a validity of %.0f days", util.CertificateValidityInDays(c))} + } + return &lint.LintResult{Status: lint.Pass} +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_e_server_cert_valid_time_longer_than_47_days.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_e_server_cert_valid_time_longer_than_47_days.go new file mode 100644 index 0000000..8a73911 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_e_server_cert_valid_time_longer_than_47_days.go @@ -0,0 +1,78 @@ +/* + * ZLint Copyright 2025 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" + + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type sc081ThirdDate47ServerCertValidityTooLong struct{} + +/************************************************************************ + +CA/B-Forum SC-081 introduces new validity periods for certificates issued on or after + +March 15, 2026 +March 15, 2027 +March 15, 2029 + +The change in the requirements is described here: https://github.com/cabforum/servercert/pull/553/files + +Subscriber Certificates issued on or after 15 March 2026 and before 15 March 2027 SHOULD NOT have a Validity Period greater than 199 days and MUST NOT have a Validity Period greater than 200 days. + +Subscriber Certificates issued on or after 15 March 2027 and before 15 March 2029 SHOULD NOT have a Validity Period greater than 99 days and MUST NOT have a Validity Period greater than 100 days. + +Subscriber Certificates issued on or after 15 March 2029 SHOULD NOT have a Validity Period greater than 46 days and MUST NOT have a Validity Period greater than 47 days. + +| __Certificate issued on or after__ | __Certificate issued before__ | __Maximum Validity Period__ | +| -- | -- | -- | +| | March 15, 2026 | 398 days | +| March 15, 2026 | March 15, 2027 | 200 days | +| March 15, 2027 | March 15, 2029 | 100 days | +| March 15, 2029 | | 47 days | + +*************************************************************************/ + +func init() { + lint.RegisterCertificateLint(&lint.CertificateLint{ + LintMetadata: lint.LintMetadata{ + Name: "e_server_cert_valid_time_longer_than_47_days", + Description: "TLS server certificates issued on or after on or after March 15, 2029 00:00 GMT/UTC must not have a validity period greater than 47 days", + Citation: "https://github.com/cabforum/servercert/pull/553", + Source: lint.CABFBaselineRequirements, + EffectiveDate: util.CABF_SC081_THIRD_MILESTONE, + }, + Lint: NewSC081ThirdDate47ServerCertValidityTooLong, + }) +} + +func NewSC081ThirdDate47ServerCertValidityTooLong() lint.LintInterface { + return &sc081ThirdDate47ServerCertValidityTooLong{} +} + +func (l *sc081ThirdDate47ServerCertValidityTooLong) CheckApplies(c *x509.Certificate) bool { + return util.IsServerAuthCert(c) && !c.IsCA +} + +func (l *sc081ThirdDate47ServerCertValidityTooLong) Execute(c *x509.Certificate) *lint.LintResult { + if util.GreaterThan(c, 47) { + return &lint.LintResult{Status: lint.Error, Details: fmt.Sprintf("Certificate is issued on or after March 15, 2029 and has a validity of %.0f days", util.CertificateValidityInDays(c))} + } + return &lint.LintResult{Status: lint.Pass} +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_missing_crl_distrib_point.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_missing_crl_distrib_point.go new file mode 100644 index 0000000..b587e45 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_missing_crl_distrib_point.go @@ -0,0 +1,72 @@ +/* + * ZLint Copyright 2024 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 ( + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" + + "time" +) + +func init() { + lint.RegisterCertificateLint(&lint.CertificateLint{ + LintMetadata: lint.LintMetadata{ + Name: "e_missing_crl_distrib_point", + Description: "Checks for the CDP extension in non-Short-lived Subscriber Certificates lacking an OCSP pointer", + Citation: "CABF BRs section 7.1.2.11.2 (CRL Distribution Points)", + Source: lint.CABFBaselineRequirements, + EffectiveDate: util.SC63EffectiveDate, + }, + Lint: NewMissingCRLDistribPoint, + }) +} + +type MissingCRLDistribPoint struct{} + +func NewMissingCRLDistribPoint() lint.LintInterface { + return &MissingCRLDistribPoint{} +} + +func (l *MissingCRLDistribPoint) CheckApplies(c *x509.Certificate) bool { + return util.IsSubscriberCert(c) && !IsShortLivedCert(c) +} + +func (l *MissingCRLDistribPoint) Execute(c *x509.Certificate) *lint.LintResult { + + if len(c.CRLDistributionPoints) == 0 && len(c.OCSPServer) == 0 { + return &lint.LintResult{ + Status: lint.Error, + Details: "The CRLDistributionPoints extension MUST be present in " + + "non-Short-Lived certificates lacking an OCSP URI", + } + } + + return &lint.LintResult{Status: lint.Pass} +} + +// Based on CABF BRs §1.6.1 (Definitions) +func IsShortLivedCert(c *x509.Certificate) bool { + thresholdDate := time.Date(2026, time.March, 15, 0, 0, 0, 0, time.UTC) + tenDaysInSeconds := 864000 + sevenDaysInSeconds := 604800 + + if c.NotBefore.Before(thresholdDate) { + return c.ValidityPeriod <= tenDaysInSeconds + } else { + return c.ValidityPeriod <= sevenDaysInSeconds + } +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_ca_aia_does_not_contain_issuing_ca_url.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_ca_aia_does_not_contain_issuing_ca_url.go index c65bced..faaae3f 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_ca_aia_does_not_contain_issuing_ca_url.go +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_sub_ca_aia_does_not_contain_issuing_ca_url.go @@ -35,11 +35,12 @@ It SHOULD contain the HTTP URL of the Issuing CA’s certificate (accessMethod = func init() { lint.RegisterCertificateLint(&lint.CertificateLint{ LintMetadata: lint.LintMetadata{ - Name: "w_sub_ca_aia_does_not_contain_issuing_ca_url", - Description: "Subordinate CA Certificate: authorityInformationAccess SHOULD also contain the HTTP URL of the Issuing CA's certificate.", - Citation: "BRs: 7.1.2.2", - Source: lint.CABFBaselineRequirements, - EffectiveDate: util.CABEffectiveDate, + Name: "w_sub_ca_aia_does_not_contain_issuing_ca_url", + Description: "Subordinate CA Certificate: authorityInformationAccess SHOULD also contain the HTTP URL of the Issuing CA's certificate.", + Citation: "BRs: 7.1.2.2", + Source: lint.CABFBaselineRequirements, + EffectiveDate: util.CABEffectiveDate, + IneffectiveDate: util.CABFBRs_2_0_0_Date, }, Lint: NewSubCaIssuerUrl, }) diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_w_server_cert_valid_time_longer_than_199_days.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_w_server_cert_valid_time_longer_than_199_days.go new file mode 100644 index 0000000..859bb61 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_w_server_cert_valid_time_longer_than_199_days.go @@ -0,0 +1,79 @@ +/* + * ZLint Copyright 2025 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" + + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type sc081FirstDate199ServerCertValidityTooLong struct{} + +/************************************************************************ + +CA/B-Forum SC-081 introduces new validity periods for certificates issued on or after + +March 15, 2026 +March 15, 2027 +March 15, 2029 + +The change in the requirements is described here: https://github.com/cabforum/servercert/pull/553/files + +Subscriber Certificates issued on or after 15 March 2026 and before 15 March 2027 SHOULD NOT have a Validity Period greater than 199 days and MUST NOT have a Validity Period greater than 200 days. + +Subscriber Certificates issued on or after 15 March 2027 and before 15 March 2029 SHOULD NOT have a Validity Period greater than 99 days and MUST NOT have a Validity Period greater than 100 days. + +Subscriber Certificates issued on or after 15 March 2029 SHOULD NOT have a Validity Period greater than 46 days and MUST NOT have a Validity Period greater than 47 days. + +| __Certificate issued on or after__ | __Certificate issued before__ | __Maximum Validity Period__ | +| -- | -- | -- | +| | March 15, 2026 | 398 days | +| March 15, 2026 | March 15, 2027 | 200 days | +| March 15, 2027 | March 15, 2029 | 100 days | +| March 15, 2029 | | 47 days | + +*************************************************************************/ + +func init() { + lint.RegisterCertificateLint(&lint.CertificateLint{ + LintMetadata: lint.LintMetadata{ + Name: "w_server_cert_valid_time_longer_than_199_days", + Description: "TLS server certificates issued on or after on or after March 15, 2026 00:00 GMT/UTC should not have a validity period greater than 199 days", + Citation: "https://github.com/cabforum/servercert/pull/553", + Source: lint.CABFBaselineRequirements, + EffectiveDate: util.CABF_SC081_FIRST_MILESTONE, + IneffectiveDate: util.CABF_SC081_SECOND_MILESTONE, + }, + Lint: NewSC081FirstDate199ServerCertValidityTooLong, + }) +} + +func NewSC081FirstDate199ServerCertValidityTooLong() lint.LintInterface { + return &sc081FirstDate199ServerCertValidityTooLong{} +} + +func (l *sc081FirstDate199ServerCertValidityTooLong) CheckApplies(c *x509.Certificate) bool { + return util.IsServerAuthCert(c) && !c.IsCA +} + +func (l *sc081FirstDate199ServerCertValidityTooLong) Execute(c *x509.Certificate) *lint.LintResult { + if util.GreaterThan(c, 199) { + return &lint.LintResult{Status: lint.Warn, Details: fmt.Sprintf("Certificate is issued on or after March 15, 2026 and has a validity of %.0f days", util.CertificateValidityInDays(c))} + } + return &lint.LintResult{Status: lint.Pass} +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_w_server_cert_valid_time_longer_than_46_days.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_w_server_cert_valid_time_longer_than_46_days.go new file mode 100644 index 0000000..b73ded5 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_w_server_cert_valid_time_longer_than_46_days.go @@ -0,0 +1,79 @@ +/* + * ZLint Copyright 2025 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" + + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type sc081ThirdDate46ServerCertValidityTooLong struct{} + +/************************************************************************ + +CA/B-Forum SC-081 introduces new validity periods for certificates issued on or after + +March 15, 2026 +March 15, 2027 +March 15, 2029 + +The change in the requirements is described here: https://github.com/cabforum/servercert/pull/553/files + +Subscriber Certificates issued on or after 15 March 2026 and before 15 March 2027 SHOULD NOT have a Validity Period greater than 199 days and MUST NOT have a Validity Period greater than 200 days. + +Subscriber Certificates issued on or after 15 March 2027 and before 15 March 2029 SHOULD NOT have a Validity Period greater than 99 days and MUST NOT have a Validity Period greater than 100 days. + +Subscriber Certificates issued on or after 15 March 2029 SHOULD NOT have a Validity Period greater than 46 days and MUST NOT have a Validity Period greater than 47 days. + +| __Certificate issued on or after__ | __Certificate issued before__ | __Maximum Validity Period__ | +| -- | -- | -- | +| | March 15, 2026 | 398 days | +| March 15, 2026 | March 15, 2027 | 200 days | +| March 15, 2027 | March 15, 2029 | 100 days | +| March 15, 2029 | | 47 days | + +*************************************************************************/ + +func init() { + lint.RegisterCertificateLint(&lint.CertificateLint{ + LintMetadata: lint.LintMetadata{ + Name: "w_server_cert_valid_time_longer_than_46_days", + Description: "TLS server certificates issued on or after on or after March 15, 2029 00:00 GMT/UTC should not have a validity period greater than 46 days", + Citation: "https://github.com/cabforum/servercert/pull/553", + Source: lint.CABFBaselineRequirements, + EffectiveDate: util.CABF_SC081_THIRD_MILESTONE, + }, + Lint: NewSC081ThirdDate46ServerCertValidityTooLong, + }) +} + +func NewSC081ThirdDate46ServerCertValidityTooLong() lint.LintInterface { + return &sc081ThirdDate46ServerCertValidityTooLong{} +} + +func (l *sc081ThirdDate46ServerCertValidityTooLong) CheckApplies(c *x509.Certificate) bool { + return util.IsServerAuthCert(c) && !c.IsCA +} + +func (l *sc081ThirdDate46ServerCertValidityTooLong) Execute(c *x509.Certificate) *lint.LintResult { + if util.GreaterThan(c, 46) { + return &lint.LintResult{Status: lint.Warn, Details: fmt.Sprintf("Certificate is issued on or after March 15, 2029 and has a validity of %.0f days", util.CertificateValidityInDays(c))} + } + return &lint.LintResult{Status: lint.Pass} + +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_w_server_cert_valid_time_longer_than_99_days.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_w_server_cert_valid_time_longer_than_99_days.go new file mode 100644 index 0000000..a8c6d3b --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_br/lint_w_server_cert_valid_time_longer_than_99_days.go @@ -0,0 +1,79 @@ +/* + * ZLint Copyright 2025 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" + + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type sc081SecondDate99ServerCertValidityTooLong struct{} + +/************************************************************************ + +CA/B-Forum SC-081 introduces new validity periods for certificates issued on or after + +March 15, 2026 +March 15, 2027 +March 15, 2029 + +The change in the requirements is described here: https://github.com/cabforum/servercert/pull/553/files + +Subscriber Certificates issued on or after 15 March 2026 and before 15 March 2027 SHOULD NOT have a Validity Period greater than 199 days and MUST NOT have a Validity Period greater than 200 days. + +Subscriber Certificates issued on or after 15 March 2027 and before 15 March 2029 SHOULD NOT have a Validity Period greater than 99 days and MUST NOT have a Validity Period greater than 100 days. + +Subscriber Certificates issued on or after 15 March 2029 SHOULD NOT have a Validity Period greater than 46 days and MUST NOT have a Validity Period greater than 47 days. + +| __Certificate issued on or after__ | __Certificate issued before__ | __Maximum Validity Period__ | +| -- | -- | -- | +| | March 15, 2026 | 398 days | +| March 15, 2026 | March 15, 2027 | 200 days | +| March 15, 2027 | March 15, 2029 | 100 days | +| March 15, 2029 | | 47 days | + +*************************************************************************/ + +func init() { + lint.RegisterCertificateLint(&lint.CertificateLint{ + LintMetadata: lint.LintMetadata{ + Name: "w_server_cert_valid_time_longer_than_99_days", + Description: "TLS server certificates issued on or after on or after March 15, 2027 00:00 GMT/UTC should not have a validity period greater than 99 days", + Citation: "https://github.com/cabforum/servercert/pull/553", + Source: lint.CABFBaselineRequirements, + EffectiveDate: util.CABF_SC081_SECOND_MILESTONE, + IneffectiveDate: util.CABF_SC081_THIRD_MILESTONE, + }, + Lint: NewSC081SecondDate99ServerCertValidityTooLong, + }) +} + +func NewSC081SecondDate99ServerCertValidityTooLong() lint.LintInterface { + return &sc081SecondDate99ServerCertValidityTooLong{} +} + +func (l *sc081SecondDate99ServerCertValidityTooLong) CheckApplies(c *x509.Certificate) bool { + return util.IsServerAuthCert(c) && !c.IsCA +} + +func (l *sc081SecondDate99ServerCertValidityTooLong) Execute(c *x509.Certificate) *lint.LintResult { + if util.GreaterThan(c, 99) { + return &lint.LintResult{Status: lint.Warn, Details: fmt.Sprintf("Certificate is issued on or after March 15, 2027 and has a validity of %.0f days", util.CertificateValidityInDays(c))} + } + return &lint.LintResult{Status: lint.Pass} +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_smime_br/lint_invalid_individual_identity.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_smime_br/lint_invalid_individual_identity.go new file mode 100644 index 0000000..8441711 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_smime_br/lint_invalid_individual_identity.go @@ -0,0 +1,73 @@ +/* + * ZLint Copyright 2024 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 ( + "github.com/zmap/zcrypto/encoding/asn1" + "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_invalid_individual_identity", + Description: "Non-legacy IV and SV certificates... SHALL include either subject:givenName and/or subject:surname, or the subject:pseudonym.", + Citation: "CABF S/MIME BR 7.1.4.2.5 and 7.1.4.2.6", + Source: lint.CABFSMIMEBaselineRequirements, + EffectiveDate: util.CABF_SMIME_BRs_1_0_0_Date, + }, + Lint: NewInvalidPersonalSubject, + }) +} + +type InvalidPersonalSubject struct{} + +func NewInvalidPersonalSubject() lint.LintInterface { + return &InvalidPersonalSubject{} +} + +func (l *InvalidPersonalSubject) CheckApplies(c *x509.Certificate) bool { + return util.IsSubscriberCert(c) && !util.IsLegacySMIMECertificate(c) && + (util.IsIndividualValidatedCertificate(c) || util.IsSponsorValidatedCertificate(c)) +} + +func (l *InvalidPersonalSubject) Execute(c *x509.Certificate) *lint.LintResult { + + if !(isPseudonymPresent(c) || isPersonalNamePresent(c)) { + return &lint.LintResult{ + Status: lint.Error, + Details: "Non-Legacy IV and SV S/MIME certificates MUST contain either a Personal Name or a Pseudonym", + } + } + return &lint.LintResult{Status: lint.Pass} +} + +func isPersonalNamePresent(c *x509.Certificate) bool { + return len(c.Subject.GivenName) > 0 || len(c.Subject.Surname) > 0 +} + +func isPseudonymPresent(c *x509.Certificate) bool { + + pseudonymOID := asn1.ObjectIdentifier{2, 5, 4, 65} + + for _, atv := range c.Subject.Names { + if atv.Type.Equal(pseudonymOID) { + return true + } + } + return false +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/cabf_smime_br/lint_legacy_gen_deprecated.go b/vendor/github.com/zmap/zlint/v3/lints/cabf_smime_br/lint_legacy_gen_deprecated.go new file mode 100644 index 0000000..0f20c6f --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/cabf_smime_br/lint_legacy_gen_deprecated.go @@ -0,0 +1,52 @@ +/* + * ZLint Copyright 2024 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 ( + "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_legacy_generation_deprecated", + Description: "S/MIME Subscriber Certificates SHALL NOT be issued using the Legacy Generation profiles", + Citation: "CABF SMIME BRs v1.0.6 implementing the results of ballot SMC08", + Source: lint.CABFSMIMEBaselineRequirements, + EffectiveDate: util.SMC08EffectiveDate, + }, + Lint: NewLegacyGenerationDeprecated, + }) +} + +type LegacyGenerationDeprecated struct{} + +func NewLegacyGenerationDeprecated() lint.LintInterface { + return &LegacyGenerationDeprecated{} +} + +func (l *LegacyGenerationDeprecated) CheckApplies(c *x509.Certificate) bool { + return util.IsLegacySMIMECertificate(c) +} + +func (l *LegacyGenerationDeprecated) Execute(c *x509.Certificate) *lint.LintResult { + return &lint.LintResult{ + Status: lint.Error, + Details: "Legacy generation S/MIME policies are deprecated since " + + util.SMC08EffectiveDate.Format("January 2, 2006"), + } +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/community/lint_crl_no_duplicate_extensions.go b/vendor/github.com/zmap/zlint/v3/lints/community/lint_crl_no_duplicate_extensions.go new file mode 100644 index 0000000..d0ddb3f --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/community/lint_crl_no_duplicate_extensions.go @@ -0,0 +1,54 @@ +/* + * ZLint Copyright 2024 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 community + +import ( + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" +) + +func init() { + lint.RegisterRevocationListLint(&lint.RevocationListLint{ + LintMetadata: lint.LintMetadata{ + Name: "e_crl_no_duplicate_extensions", + Description: "The CRL must not include duplicate extensions.", + Source: lint.Community, + }, + Lint: func() lint.RevocationListLintInterface { return &noDuplicateExtensions{} }, + }) +} + +type noDuplicateExtensions struct{} + +// CheckApplies returns true if the CRL has any extensions to check. +func (l *noDuplicateExtensions) CheckApplies(c *x509.RevocationList) bool { + return len(c.Extensions) > 0 +} + +// Execute checks for duplicate extensions within the CRL. +func (l *noDuplicateExtensions) Execute(c *x509.RevocationList) *lint.LintResult { + extensions := make(map[string]struct{}) + for _, ext := range c.Extensions { + oid := ext.Id.String() + if _, ok := extensions[oid]; ok { + return &lint.LintResult{ + Status: lint.Error, + Details: "CRL contains duplicate extension " + oid, + } + } + extensions[oid] = struct{}{} + } + return &lint.LintResult{Status: lint.Pass} +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/community/lint_crl_revocation_date_too_early.go b/vendor/github.com/zmap/zlint/v3/lints/community/lint_crl_revocation_date_too_early.go new file mode 100644 index 0000000..820073c --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/community/lint_crl_revocation_date_too_early.go @@ -0,0 +1,63 @@ +/* + * ZLint Copyright 2024 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 community + +import ( + "fmt" + "time" + + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +/* + * This lint checks that the revocation time for a revoked certificate is not too early. + * This is particularly useful when a programming language (e.g., Go) uses a default + * zero-value (0001-01-01T00:00:00Z) for a time if not set explicitly. + * For all intents and purposes, the revocation time for a revoked certificate should not be + * before the RFC 2459 (Internet X.509 Public Key Infrastructure Certificate and CRL Profile), + * which first introduced the CRL profile. + */ + +func init() { + lint.RegisterRevocationListLint(&lint.RevocationListLint{ + LintMetadata: lint.LintMetadata{ + Name: "e_crl_revocation_date_too_early", + Description: "The revocation time of each revoked certificate should not before the publication date of RFC 2459.", + Source: lint.Community, + }, + Lint: func() lint.RevocationListLintInterface { return &revocationDateTooEarly{} }, + }) +} + +type revocationDateTooEarly struct{} + +func (l *revocationDateTooEarly) CheckApplies(c *x509.RevocationList) bool { + // This check applies to any CRL that has at least one revoked certificate. + return len(c.RevokedCertificates) > 0 +} + +func (l *revocationDateTooEarly) Execute(c *x509.RevocationList) *lint.LintResult { + for _, rc := range c.RevokedCertificates { + if rc.RevocationTime.Before(util.RFC2459Date) { + return &lint.LintResult{ + Status: lint.Error, + Details: fmt.Sprintf("Revoked certificate with serial number %x has a revocation time (%s) that is before RFC 2459", rc.SerialNumber, rc.RevocationTime.Format(time.RFC3339)), + } + } + } + return &lint.LintResult{Status: lint.Pass} +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/etsi/lint_qcstatem_qcpds_https_url.go b/vendor/github.com/zmap/zlint/v3/lints/etsi/lint_qcstatem_qcpds_https_url.go new file mode 100644 index 0000000..c8dae46 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/etsi/lint_qcstatem_qcpds_https_url.go @@ -0,0 +1,113 @@ +package etsi + +/* + * ZLint Copyright 2025 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. + */ + +import ( + "fmt" + "strings" + + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +type qcStatemPdsHttpsOnly struct{} + +/************************************************************************ + +ETSI EN 319 412-5 V2.4.1 (2023-09) +https://www.etsi.org/deliver/etsi_en/319400_319499/31941205/02.04.01_60/en_31941205v020401p.pdf#%5B%7B%22num%22%3A30%2C%22gen%22%3A0%7D%2C%7B%22name%22%3A%22FitH%22%7D%2C381%5D + +4.3.4 QCStatement regarding location of PKI Disclosure Statements (PDS) +This QCStatement holds URLs to PKI Disclosure Statements (PDS) in accordance with Annex A of ETSI EN 319 411-1 [i.10]. + +Syntax: + +esi4-qcStatement-5 QC-STATEMENT ::= { SYNTAX QcEuPDS IDENTIFIED +BY id-etsi-qcs-QcPDS } + +QcEuPDS ::= PdsLocations //nolint:dupword + +PdsLocations ::= SEQUENCE SIZE (1..MAX) OF PdsLocation //nolint:dupword // dup comes from the specification + +PdsLocation::= SEQUENCE { +url IA5String, +language PrintableString (SIZE(2))} --ISO 639-1 language code + +id-etsi-qcs-QcPDS OBJECT IDENTIFIER ::= { id-etsi-qcs 5 } + +QCS-4.3.4-01: The language shall be as defined in ISO 639-1 [1]. + +QCS-4.3.4-02: Referenced PKI Disclosure Statements should be structured according to Annex A of ETSI +EN 319 411-1 [i.10]. + +The signature of the certificate does not cover the content of the PDS and hence does not protect the integrity of the +PDS which can change over time. End users trust in the accuracy of a PDS is therefore based on the mechanisms used +to protect the authenticity of the PDS. + +QCS-4.3.4-03: As a minimum, a URL to a PDS provided in this statement shall use the "https" (https://) scheme, IETF +RFC 2818 [5] or later documents updating this specification + +*************************************************************************/ + +func init() { + lint.RegisterCertificateLint(&lint.CertificateLint{ + LintMetadata: lint.LintMetadata{ + Name: "e_qcstatem_pds_must_have_https_only", + Description: "Checks that a QC Statement of the type id-etsi-qcs-QcPDS contains a URL that uses the https scheme.", + Citation: "ETSI EN 319 412 - 5 V2.4.1 (2023 - 09) / Section 4.3.4", + Source: lint.EtsiEsi, + EffectiveDate: util.EtsiEn319_412_5_V2_4_1_Date, + }, + Lint: NewQcStatemPdsHasHTTPSOnly, + }) +} + +func NewQcStatemPdsHasHTTPSOnly() lint.LintInterface { + return &qcStatemPdsHttpsOnly{} +} + +func (l *qcStatemPdsHttpsOnly) CheckApplies(c *x509.Certificate) bool { + qcEuPDS := &util.IdEtsiQcsQcEuPDS + if !util.IsExtInCert(c, util.QcStateOid) { + return false + } + if util.ParseQcStatem(util.GetExtFromCert(c, util.QcStateOid).Value, *qcEuPDS).IsPresent() { + return true + } + return false +} + +func (l *qcStatemPdsHttpsOnly) Execute(c *x509.Certificate) *lint.LintResult { + + ext := util.GetExtFromCert(c, util.QcStateOid) + s := util.ParseQcStatem(ext.Value, util.IdEtsiQcsQcEuPDS) + + errString := s.GetErrorInfo() + + if len(errString) != 0 { + return &lint.LintResult{Status: lint.Error, Details: "Could not parse qcStatement with PDS: " + errString} + } + + pds := s.(util.EtsiQcPds) + for _, loc := range pds.PdsLocations { + if !strings.HasPrefix(loc.Url, "https://") { + return &lint.LintResult{Status: lint.Error, Details: fmt.Sprintf("PDS URL %s does not use the https scheme", loc.Url)} + } + } + + return &lint.LintResult{Status: lint.Pass} + +} diff --git a/vendor/github.com/zmap/zlint/v3/lints/mozilla/lint_mp_ecdsa_pub_key_encoding_correct.go b/vendor/github.com/zmap/zlint/v3/lints/mozilla/lint_mp_ecdsa_pub_key_encoding_correct.go index ecf72f9..c4523a2 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/mozilla/lint_mp_ecdsa_pub_key_encoding_correct.go +++ b/vendor/github.com/zmap/zlint/v3/lints/mozilla/lint_mp_ecdsa_pub_key_encoding_correct.go @@ -29,14 +29,17 @@ type ecdsaPubKeyAidEncoding struct{} /************************************************ https://www.mozilla.org/en-US/about/governance/policies/security-group/certs/policy/ -When ECDSA keys are encoded in a SubjectPublicKeyInfo structure, the algorithm field MUST be one of the following, as -specified by RFC 5480, Section 2.1.1: +When ECDSA keys are encoded in a SubjectPublicKeyInfo structure, the algorithm field MUST be one of the following, +as specified by RFC 5480, Section 2.1.1: The encoded AlgorithmIdentifier for a P-256 key MUST match the following hex-encoded -bytes: > 301306072a8648ce3d020106082a8648ce3d030107. +bytes: 301306072a8648ce3d020106082a8648ce3d030107; The encoded AlgorithmIdentifier for a P-384 key MUST match the following hex-encoded -bytes: > 301006072a8648ce3d020106052b81040022. +bytes: 301006072a8648ce3d020106052b81040022; + +The encoded AlgorithmIdentifier for a P-521 key MUST match the following hex-encoded +bytes: 301006072a8648ce3d020106052b81040023. The above encodings consist of an ecPublicKey OID (1.2.840.10045.2.1) with a named curve parameter of the corresponding curve OID. Certificates MUST NOT use the implicit or specified curve forms. @@ -50,7 +53,7 @@ func init() { Description: "The encoded algorithm identifiers for ECDSA public keys MUST match specific bytes", Citation: "Mozilla Root Store Policy / Section 5.1.2", Source: lint.MozillaRootStorePolicy, - EffectiveDate: util.MozillaPolicy27Date, + EffectiveDate: util.MozillaPolicy30Date, }, Lint: NewEcdsaPubKeyAidEncoding, }) @@ -60,11 +63,13 @@ func NewEcdsaPubKeyAidEncoding() lint.LintInterface { return &ecdsaPubKeyAidEncoding{} } -var acceptedAlgIDEncodingsDER = [2][]byte{ +var acceptedAlgIDEncodingsDER = [3][]byte{ // encoded AlgorithmIdentifier for a P-256 key {0x30, 0x13, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07}, // encoded AlgorithmIdentifier for a P-384 key {0x30, 0x10, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x05, 0x2b, 0x81, 0x04, 0x00, 0x22}, + // encoded AlgorithmIdentifier for P-521 key + {0x30, 0x10, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x05, 0x2b, 0x81, 0x04, 0x00, 0x23}, } func (l *ecdsaPubKeyAidEncoding) CheckApplies(c *x509.Certificate) bool { diff --git a/vendor/github.com/zmap/zlint/v3/lints/mozilla/lint_mp_ecdsa_signature_encoding_correct.go b/vendor/github.com/zmap/zlint/v3/lints/mozilla/lint_mp_ecdsa_signature_encoding_correct.go index 0a1c7db..8546ad7 100644 --- a/vendor/github.com/zmap/zlint/v3/lints/mozilla/lint_mp_ecdsa_signature_encoding_correct.go +++ b/vendor/github.com/zmap/zlint/v3/lints/mozilla/lint_mp_ecdsa_signature_encoding_correct.go @@ -38,6 +38,9 @@ following hex-encoded bytes: 300a06082a8648ce3d040302. If the signing key is P-384, the signature MUST use ECDSA with SHA-384. The encoded AlgorithmIdentifier MUST match the following hex-encoded bytes: 300a06082a8648ce3d040303. +If the signing key is P-521, the signature MUST use ECDSA with SHA-512. When encoded, the AlgorithmIdentifier MUST +be byte-for-byte identical with the following hex-encoded bytes: 300a06082a8648ce3d040304. + The above encodings consist of the corresponding OID with the parameters field omitted, as specified by RFC 5758, Section 3.2. Certificates MUST NOT include a NULL parameter. Note this differs from RSASSA-PKCS1-v1_5, which includes an explicit NULL. @@ -51,7 +54,7 @@ func init() { Description: "The encoded algorithm identifiers for ECDSA signatures MUST match specific hex-encoded bytes", Citation: "Mozilla Root Store Policy / Section 5.1.2", Source: lint.MozillaRootStorePolicy, - EffectiveDate: util.MozillaPolicy27Date, + EffectiveDate: util.MozillaPolicy30Date, }, Lint: NewEcdsaSignatureAidEncoding, }) @@ -71,6 +74,7 @@ func (l *ecdsaSignatureAidEncoding) CheckApplies(c *x509.Certificate) bool { c.SignatureAlgorithmOID.Equal(util.OidSignatureSHA224withECDSA) } +//nolint:nestif func (l *ecdsaSignatureAidEncoding) Execute(c *x509.Certificate) *lint.LintResult { // We must check consistency of the issuer public key to the signature algorithm // (see for example: If the signing key is P-256, the signature MUST use ECDSA with SHA-256. @@ -94,6 +98,8 @@ func (l *ecdsaSignatureAidEncoding) Execute(c *x509.Certificate) *lint.LintResul const maxP256SigByteLen = 72 // len <= 2+2+2+49+49 (= 104) const maxP384SigByteLen = 104 + // len <= 2+2+2+67+67 (= 140) + const maxP521SigByteLen = 140 if signatureSize <= maxP256SigByteLen { expectedEncoding := []byte{0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02} @@ -115,6 +121,15 @@ func (l *ecdsaSignatureAidEncoding) Execute(c *x509.Certificate) *lint.LintResul Status: lint.Error, Details: "Encoding of signature algorithm does not match signing key on P-384 curve. Got the unsupported " + hex.EncodeToString(encoded), } + } else if signatureSize <= maxP521SigByteLen { + expectedEncoding := []byte{0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x04} + if bytes.Equal(encoded, expectedEncoding) { + return &lint.LintResult{Status: lint.Pass} + } + return &lint.LintResult{ + Status: lint.Error, + Details: "Encoding of signature algorithm does not match signing key on P-521 curve. Got the unsupported " + hex.EncodeToString(encoded), + } } return &lint.LintResult{ Status: lint.Error, diff --git a/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_crl_revocation_time_not_after_this_update.go b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_crl_revocation_time_not_after_this_update.go new file mode 100644 index 0000000..22427e2 --- /dev/null +++ b/vendor/github.com/zmap/zlint/v3/lints/rfc/lint_crl_revocation_time_not_after_this_update.go @@ -0,0 +1,68 @@ +/* + * ZLint Copyright 2024 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 rfc + +import ( + "fmt" + "time" + + "github.com/zmap/zcrypto/x509" + "github.com/zmap/zlint/v3/lint" + "github.com/zmap/zlint/v3/util" +) + +/* + * The thisUpdate field in a CRL indicates the time at which the CRL was issued. + * For each entry in the revokedCertificates list within the CRL, there is a + * revocationDate field. This revocationDate signifies when the certificate was revoked. + * Logically, a certificate cannot be listed as revoked on a CRL with a revocationDate + * that is after the thisUpdate of that CRL, because thisUpdate marks the point + * in time that the information in the CRL is considered valid. If a revocation + * happened after the CRL was issued, it would appear on a subsequent CRL. + */ + +func init() { + lint.RegisterRevocationListLint(&lint.RevocationListLint{ + LintMetadata: lint.LintMetadata{ + Name: "e_crl_revocation_time_after_this_update", + Description: "All revocation times for revoked certificates must be on or before the thisUpdate field of the CRL.", + Citation: "RFC 5280: Section 5.1.2.4 & 5.1.2.6", + Source: lint.RFC5280, + EffectiveDate: util.RFC5280Date, + }, + Lint: func() lint.RevocationListLintInterface { return &revocationTimeNotAfterThisUpdate{} }, + }) +} + +type revocationTimeNotAfterThisUpdate struct{} + +// CheckApplies returns true if the CRL has any revoked certificates. +func (l *revocationTimeNotAfterThisUpdate) CheckApplies(c *x509.RevocationList) bool { + return len(c.RevokedCertificates) > 0 +} + +// Execute checks that for each revoked certificate, the revocation time is not after the CRL's thisUpdate time. +func (l *revocationTimeNotAfterThisUpdate) Execute(c *x509.RevocationList) *lint.LintResult { + for _, rc := range c.RevokedCertificates { + if rc.RevocationTime.After(c.ThisUpdate) { + return &lint.LintResult{ + Status: lint.Error, + Details: fmt.Sprintf("revoked certificate with serial number %x has a revocation time (%s) after the CRL's thisUpdate time (%s)", + rc.SerialNumber, rc.RevocationTime.Format(time.RFC3339), c.ThisUpdate.Format(time.RFC3339)), + } + } + } + return &lint.LintResult{Status: lint.Pass} +} diff --git a/vendor/github.com/zmap/zlint/v3/util/gtld_map.go b/vendor/github.com/zmap/zlint/v3/util/gtld_map.go index 6d25031..c89126d 100644 --- a/vendor/github.com/zmap/zlint/v3/util/gtld_map.go +++ b/vendor/github.com/zmap/zlint/v3/util/gtld_map.go @@ -656,7 +656,7 @@ var tldMap = map[string]GTLDPeriod{ "bentley": { GTLD: "bentley", DelegationDate: "2015-07-09", - RemovalDate: "", + RemovalDate: "2025-04-23", }, "berlin": { GTLD: "berlin", @@ -3596,7 +3596,7 @@ var tldMap = map[string]GTLDPeriod{ "lancaster": { GTLD: "lancaster", DelegationDate: "2015-07-15", - RemovalDate: "", + RemovalDate: "2025-04-29", }, "lancia": { GTLD: "lancia", @@ -5046,7 +5046,7 @@ var tldMap = map[string]GTLDPeriod{ "pramerica": { GTLD: "pramerica", DelegationDate: "2016-07-28", - RemovalDate: "", + RemovalDate: "2025-05-16", }, "praxi": { GTLD: "praxi", diff --git a/vendor/github.com/zmap/zlint/v3/util/time.go b/vendor/github.com/zmap/zlint/v3/util/time.go index 1709402..be34fed 100644 --- a/vendor/github.com/zmap/zlint/v3/util/time.go +++ b/vendor/github.com/zmap/zlint/v3/util/time.go @@ -1,5 +1,5 @@ /* - * ZLint Copyright 2024 Regents of the University of Michigan + * ZLint Copyright 2025 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 @@ -15,6 +15,7 @@ package util import ( + "math" "time" "github.com/zmap/zcrypto/encoding/asn1" @@ -61,6 +62,7 @@ var ( SubCert825Days = time.Date(2018, time.March, 2, 0, 0, 0, 0, time.UTC) CABV148Date = time.Date(2017, time.June, 8, 0, 0, 0, 0, time.UTC) EtsiEn319_412_5_V2_2_1_Date = time.Date(2017, time.November, 1, 0, 0, 0, 0, time.UTC) + EtsiEn319_412_5_V2_4_1_Date = time.Date(2023, time.September, 1, 0, 0, 0, 0, time.UTC) OnionOnlyEVDate = time.Date(2015, time.May, 1, 0, 0, 0, 0, time.UTC) CABV201Date = time.Date(2017, time.July, 28, 0, 0, 0, 0, time.UTC) AppleCTPolicyDate = time.Date(2018, time.October, 15, 0, 0, 0, 0, time.UTC) @@ -68,6 +70,7 @@ 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) + MozillaPolicy30Date = time.Date(2025, time.March, 15, 0, 0, 0, 0, time.UTC) CABFBRs_1_6_2_UnderscorePermissibilitySunsetDate = time.Date(2019, time.April, 1, 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_2_1_Date = time.Date(2015, time.January, 16, 0, 0, 0, 0, time.UTC) @@ -90,19 +93,30 @@ var ( SC16EffectiveDate = time.Date(2019, time.April, 16, 0, 0, 0, 0, time.UTC) SC17EffectiveDate = time.Date(2019, time.June, 21, 0, 0, 0, 0, time.UTC) CABF_SMIME_BRs_1_0_0_Date = time.Date(2023, time.September, 1, 0, 0, 0, 0, time.UTC) + // Date of deprecation of S/MIME legacy policies from Ballot SMC08 + SMC08EffectiveDate = time.Date(2025, time.July, 15, 0, 0, 0, 0, time.UTC) // Enforcement date of CRL reason codes from Ballot SC 061 CABFBRs_1_8_7_Date = time.Date(2023, time.July, 15, 0, 0, 0, 0, time.UTC) // Updates to the CABF BRs and EVGLs from Ballot SC 062 https://cabforum.org/2023/03/17/ballot-sc62v2-certificate-profiles-update/ SC62EffectiveDate = time.Date(2023, time.September, 15, 0, 0, 0, 0, time.UTC) + // Updates to the CABF BRs from Ballot SC 063 https://cabforum.org/2023/07/14/ballot-sc063v4-make-ocsp-optional-require-crls-and-incentivize-automation/ + SC63EffectiveDate = time.Date(2024, time.March, 15, 0, 0, 0, 0, time.UTC) // Date when section 9.2.8 of CABF EVG became effective - CABFEV_Sec9_2_8_Date = time.Date(2020, time.January, 31, 0, 0, 0, 0, time.UTC) - CABF_CS_BRs_1_2_Date = time.Date(2019, time.August, 13, 0, 0, 0, 0, time.UTC) + CABFEV_Sec9_2_8_Date = time.Date(2020, time.January, 31, 0, 0, 0, 0, time.UTC) + CABF_CS_BRs_1_2_Date = time.Date(2019, time.August, 13, 0, 0, 0, 0, time.UTC) + CABF_SC081_FIRST_MILESTONE = time.Date(2026, time.March, 15, 0, 0, 0, 0, time.UTC) + CABF_SC081_SECOND_MILESTONE = time.Date(2027, time.March, 15, 0, 0, 0, 0, time.UTC) + CABF_SC081_THIRD_MILESTONE = time.Date(2029, time.March, 15, 0, 0, 0, 0, time.UTC) ) var ( CABFEV_9_8_2 = CABV170Date ) +var ( + DAY_LENGTH = 86400 * time.Second.Seconds() +) + func FindTimeType(firstDate, secondDate asn1.RawValue) (int, int) { return firstDate.Tag, secondDate.Tag } @@ -162,3 +176,18 @@ func BeforeOrOn(left, right time.Time) bool { func OnOrAfter(left, right time.Time) bool { return !left.Before(right) } + +func CertificateValidityInSeconds(cert *x509.Certificate) float64 { + return cert.NotAfter.Add(1 * time.Second).Sub(cert.NotBefore).Seconds() +} + +func CertificateValidityInDays(cert *x509.Certificate) float64 { + return math.Ceil(CertificateValidityInSeconds(cert) / DAY_LENGTH) +} + +// GreaterThan returns true if the validity of this cert in days is greater than +// this maxDaysAllowed, false otherwise +func GreaterThan(cert *x509.Certificate, maxDaysAllowed float64) bool { + maxValidity := maxDaysAllowed * DAY_LENGTH + return CertificateValidityInSeconds(cert) > maxValidity +} diff --git a/vendor/modules.txt b/vendor/modules.txt index c9a2a5e..cbfd4f0 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -16,8 +16,8 @@ github.com/zmap/zcrypto/util github.com/zmap/zcrypto/x509 github.com/zmap/zcrypto/x509/ct github.com/zmap/zcrypto/x509/pkix -# github.com/zmap/zlint/v3 v3.6.6 -## explicit; go 1.23.0 +# github.com/zmap/zlint/v3 v3.6.7 +## explicit; go 1.24.0 github.com/zmap/zlint/v3 github.com/zmap/zlint/v3/lint github.com/zmap/zlint/v3/lints/apple