-
Notifications
You must be signed in to change notification settings - Fork 110
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add CRL Lints for the ReasonCode extension from the baseline requirem…
…ents and RFC 5280 (#715) Add CRL Lints for the ReasonCode extension from the baseline requirements and RFC 5280. #715 Co-authored-by: Rob <3725956+robplee@users.noreply.github.com> Co-authored-by: David Adrian <davidcadrian@gmail.com>
- Loading branch information
1 parent
1e3cf01
commit 38b7484
Showing
15 changed files
with
464 additions
and
0 deletions.
There are no files selected for viewing
60 changes: 60 additions & 0 deletions
60
v3/lints/cabf_br/lint_cabf_crl_reason_code_not_critical.go
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
package cabf_br | ||
|
||
/* | ||
* 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. | ||
*/ | ||
|
||
import ( | ||
"github.com/zmap/zcrypto/x509" | ||
"github.com/zmap/zlint/v3/lint" | ||
"github.com/zmap/zlint/v3/util" | ||
) | ||
|
||
type crlReasonCodeNotCritical struct{} | ||
|
||
func init() { | ||
lint.RegisterRevocationListLint(&lint.RevocationListLint{ | ||
LintMetadata: lint.LintMetadata{ | ||
Name: "e_cab_crl_reason_code_not_critical", | ||
Description: "If present, CRL Reason Code extension MUST NOT be marked critical.", | ||
Citation: "BRs: 7.2.2", | ||
Source: lint.CABFBaselineRequirements, | ||
EffectiveDate: util.CABEffectiveDate, | ||
}, | ||
Lint: NewCrlReasonCodeNotCritical, | ||
}) | ||
} | ||
|
||
func NewCrlReasonCodeNotCritical() lint.RevocationListLintInterface { | ||
return &crlReasonCodeNotCritical{} | ||
} | ||
|
||
func (l *crlReasonCodeNotCritical) CheckApplies(c *x509.RevocationList) bool { | ||
return len(c.RevokedCertificates) > 0 | ||
} | ||
|
||
func (l *crlReasonCodeNotCritical) Execute(c *x509.RevocationList) *lint.LintResult { | ||
for _, c := range c.RevokedCertificates { | ||
if c.ReasonCode == nil { | ||
continue | ||
} | ||
for _, ext := range c.Extensions { | ||
if ext.Id.Equal(util.ReasonCodeOID) { | ||
if ext.Critical { | ||
return &lint.LintResult{Status: lint.Error, Details: "CRL Reason Code extension MUST NOT be marked as critical."} | ||
} | ||
} | ||
} | ||
} | ||
return &lint.LintResult{Status: lint.Pass} | ||
} |
64 changes: 64 additions & 0 deletions
64
v3/lints/cabf_br/lint_cabf_crl_reason_code_not_critical_test.go
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
package cabf_br | ||
|
||
import ( | ||
"strings" | ||
"testing" | ||
|
||
"github.com/zmap/zlint/v3/lint" | ||
"github.com/zmap/zlint/v3/test" | ||
) | ||
|
||
/* | ||
* 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. | ||
*/ | ||
|
||
func TestCrlReasonCodeNotCritical(t *testing.T) { | ||
t.Parallel() | ||
testCases := []struct { | ||
name string | ||
path string | ||
want lint.LintStatus | ||
wantSubStr string | ||
}{ | ||
{ | ||
name: "CRL reason code critical", | ||
path: "crlReasonCodeCrit.pem", | ||
want: lint.Error, | ||
wantSubStr: "MUST NOT be marked as critical", | ||
}, | ||
{ | ||
name: "CRL with reason code 5", | ||
path: "crlWithReasonCode5.pem", | ||
want: lint.Pass, | ||
}, | ||
{ | ||
name: "CRL no revoked certificates", | ||
path: "crlEmpty.pem", | ||
want: lint.NA, | ||
}, | ||
} | ||
|
||
for _, tc := range testCases { | ||
tc := tc | ||
t.Run(tc.name, func(t *testing.T) { | ||
gotStatus := test.TestRevocationListLint(t, "e_cab_crl_reason_code_not_critical", tc.path) | ||
if tc.want != gotStatus.Status { | ||
t.Errorf("%s: expected %s, got %s", tc.path, tc.want, gotStatus.Status) | ||
} | ||
if !strings.Contains(gotStatus.Details, tc.wantSubStr) { | ||
t.Errorf("%s: expected %s, got %s", tc.path, tc.wantSubStr, gotStatus.Details) | ||
} | ||
}) | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
package cabf_br | ||
|
||
/* | ||
* 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. | ||
*/ | ||
|
||
import ( | ||
"github.com/zmap/zcrypto/x509" | ||
"github.com/zmap/zlint/v3/lint" | ||
"github.com/zmap/zlint/v3/util" | ||
) | ||
|
||
type crlHasValidReasonCodes struct{} | ||
|
||
func init() { | ||
lint.RegisterRevocationListLint(&lint.RevocationListLint{ | ||
LintMetadata: lint.LintMetadata{ | ||
Name: "e_cab_crl_has_valid_reason_code", | ||
Description: "Only the following CRLReasons MAY be present: 1, 3, 4, 5, 9.", | ||
Citation: "BRs: 7.2.2", | ||
Source: lint.CABFBaselineRequirements, | ||
EffectiveDate: util.CABFBRs_1_8_7_Date, | ||
}, | ||
Lint: NewCrlHasValidReasonCode, | ||
}) | ||
} | ||
|
||
func NewCrlHasValidReasonCode() lint.RevocationListLintInterface { | ||
return &crlHasValidReasonCodes{} | ||
} | ||
|
||
func (l *crlHasValidReasonCodes) CheckApplies(c *x509.RevocationList) bool { | ||
return len(c.RevokedCertificates) > 0 | ||
} | ||
|
||
var validReasons = map[int]bool{ | ||
1: true, | ||
3: true, | ||
4: true, | ||
5: true, | ||
9: true, | ||
} | ||
|
||
func (l *crlHasValidReasonCodes) Execute(c *x509.RevocationList) *lint.LintResult { | ||
for _, c := range c.RevokedCertificates { | ||
if c.ReasonCode == nil { | ||
continue | ||
} | ||
code := *c.ReasonCode | ||
if code == 0 { | ||
return &lint.LintResult{Status: lint.Error, Details: "The reason code CRL entry extension SHOULD be absent instead of using the unspecified (0) reasonCode value."} | ||
} | ||
if _, ok := validReasons[code]; !ok { | ||
return &lint.LintResult{Status: lint.Error, Details: "Reason code not included in BR: 7.2.2"} | ||
} | ||
} | ||
return &lint.LintResult{Status: lint.Pass} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
package cabf_br | ||
|
||
import ( | ||
"strings" | ||
"testing" | ||
|
||
"github.com/zmap/zlint/v3/lint" | ||
"github.com/zmap/zlint/v3/test" | ||
) | ||
|
||
/* | ||
* 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. | ||
*/ | ||
|
||
func TestCrlValidReasonCodes(t *testing.T) { | ||
t.Parallel() | ||
testCases := []struct { | ||
name string | ||
path string | ||
want lint.LintStatus | ||
wantSubStr string | ||
}{ | ||
{ | ||
name: "CRL with reason code 0", | ||
path: "crlWithReasonCode0.pem", | ||
want: lint.Error, | ||
wantSubStr: "The reason code CRL entry extension SHOULD be absent instead of using the unspecified", | ||
}, | ||
{ | ||
// This test case is significant since reason code 2 is not allowed by CABF | ||
name: "CRL with reason code 2", | ||
path: "crlWithReasonCode2.pem", | ||
want: lint.Error, | ||
wantSubStr: "Reason code not included in BR: 7.2.2", | ||
}, | ||
{ | ||
name: "CRL with reason code 5", | ||
path: "crlWithReasonCode5.pem", | ||
want: lint.Pass, | ||
}, | ||
{ | ||
name: "CRL with reason code 7", | ||
path: "crlWithReasonCode7.pem", | ||
want: lint.Error, | ||
wantSubStr: "Reason code not included in BR: 7.2.2", | ||
}, | ||
{ | ||
name: "CRL thisUpdate before enforcement", | ||
path: "crlThisUpdate20230505.pem", | ||
want: lint.NE, | ||
}, | ||
} | ||
|
||
for _, tc := range testCases { | ||
tc := tc | ||
t.Run(tc.name, func(t *testing.T) { | ||
gotStatus := test.TestRevocationListLint(t, "e_cab_crl_has_valid_reason_code", tc.path) | ||
if tc.want != gotStatus.Status { | ||
t.Errorf("%s: expected %s, got %s", tc.path, tc.want, gotStatus.Status) | ||
} | ||
if !strings.Contains(gotStatus.Details, tc.wantSubStr) { | ||
t.Errorf("%s: expected %s, got %s", tc.path, tc.wantSubStr, gotStatus.Details) | ||
} | ||
}) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
package rfc | ||
|
||
/* | ||
* 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. | ||
*/ | ||
|
||
import ( | ||
"fmt" | ||
|
||
"github.com/zmap/zcrypto/x509" | ||
"github.com/zmap/zlint/v3/lint" | ||
"github.com/zmap/zlint/v3/util" | ||
) | ||
|
||
type crlHasValidReasonCode struct{} | ||
|
||
/* | ||
*********************************************** | ||
RFC 5280: 5.3.1 | ||
CRL issuers are strongly | ||
encouraged to include meaningful reason codes in CRL entries; | ||
however, the reason code CRL entry extension SHOULD be absent instead | ||
of using the unspecified (0) reasonCode value. | ||
*********************************************** | ||
*/ | ||
func init() { | ||
lint.RegisterRevocationListLint(&lint.RevocationListLint{ | ||
LintMetadata: lint.LintMetadata{ | ||
Name: "e_crl_has_valid_reason_code", | ||
Description: "If a CRL entry has a reason code, it MUST be in RFC5280 section 5.3.1 and SHOULD be absent instead of using unspecified (0)", | ||
Citation: "RFC 5280: 5.3.1", | ||
Source: lint.RFC5280, | ||
EffectiveDate: util.RFC5280Date, | ||
}, | ||
Lint: NewCrlHasValidReasonCode, | ||
}) | ||
} | ||
|
||
func NewCrlHasValidReasonCode() lint.RevocationListLintInterface { | ||
return &crlHasValidReasonCode{} | ||
} | ||
|
||
func (l *crlHasValidReasonCode) CheckApplies(c *x509.RevocationList) bool { | ||
return len(c.RevokedCertificates) > 0 | ||
} | ||
|
||
func (l *crlHasValidReasonCode) Execute(c *x509.RevocationList) *lint.LintResult { | ||
for _, c := range c.RevokedCertificates { | ||
if c.ReasonCode == nil { | ||
continue | ||
} | ||
code := *c.ReasonCode | ||
if code == 0 { | ||
return &lint.LintResult{Status: lint.Warn, Details: "The reason code CRL entry extension SHOULD be absent instead of using the unspecified (0) reasonCode value."} | ||
} | ||
if code == 7 || code > 10 { | ||
return &lint.LintResult{Status: lint.Error, Details: fmt.Sprintf("Reason code, %v, not included in RFC 5280 section 5.3.1", code)} | ||
} | ||
} | ||
return &lint.LintResult{Status: lint.Pass} | ||
} |
Oops, something went wrong.