Skip to content

Commit

Permalink
Add lint to check that CRL does not have duplicates in RevokedCertifi…
Browse files Browse the repository at this point in the history
…cates (#890)

* Add lint to check that CRL does not have duplicates in
RevokedCertificates

* Change lint status to lint.Warn from lint.Error

---------

Co-authored-by: Christopher Henderson <[email protected]>
  • Loading branch information
kowshikRoy and christopher-henderson authored Oct 28, 2024
1 parent d0dc117 commit 4b55d49
Show file tree
Hide file tree
Showing 4 changed files with 131 additions and 0 deletions.
59 changes: 59 additions & 0 deletions v3/lints/community/lint_crl_unique_revoked_certificate.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
/*
* 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"

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

func init() {
lint.RegisterRevocationListLint(&lint.RevocationListLint{
LintMetadata: lint.LintMetadata{
Name: "e_crl_unique_revoked_certificate",
Description: "The CRL must not include duplicate serial numbers in its revoked certificates list.",
Source: lint.Community,
EffectiveDate: util.ZeroDate,
},
Lint: NewUniqueRevokedCertificate,
})
}

type uniqueRevokedCertificate struct{}

func NewUniqueRevokedCertificate() lint.RevocationListLintInterface {
return &uniqueRevokedCertificate{}
}

func (l *uniqueRevokedCertificate) CheckApplies(c *x509.RevocationList) bool {
return true
}

func (l *uniqueRevokedCertificate) Execute(c *x509.RevocationList) *lint.LintResult {
serials := make(map[string]bool)
for _, rc := range c.RevokedCertificates {
if serials[rc.SerialNumber.String()] {
return &lint.LintResult{
Status: lint.Warn,
Details: fmt.Sprintf("Revoked certificates list contains duplicate serial number: %x", rc.SerialNumber),
}
}
serials[rc.SerialNumber.String()] = true
}
return &lint.LintResult{Status: lint.Pass}
}
57 changes: 57 additions & 0 deletions v3/lints/community/lint_crl_unique_revoked_certificate_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
/*
* 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 (
"strings"
"testing"

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

func TestUniqueRevokedCertificate(t *testing.T) {
t.Parallel()
testCases := []struct {
name string
path string
want lint.LintStatus
wantSubStr string
}{
{
name: "CRL with duplicates in revoked certificates list",
path: "crlWithDuplicatesInRevokedCertificateList.pem",
want: lint.Warn,
},
{
name: "CRL with no duplicates in revoked certificates list",
path: "crlWithNoDuplicatesInRevokedCertificateList.pem",
want: lint.Pass,
},
}

for _, tc := range testCases {
tc := tc
t.Run(tc.name, func(t *testing.T) {
gotStatus := test.TestRevocationListLint(t, "e_crl_unique_revoked_certificate", 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)
}
})
}
}
8 changes: 8 additions & 0 deletions v3/testdata/crlWithDuplicatesInRevokedCertificateList.pem
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
-----BEGIN X509 CRL-----
MIIBBzCBrgIBATAKBggqhkjOPQQDAjASMRAwDgYDVQQDEwdSb290IENBGA8wMDAx
MDEwMTAwMDAwMFowSDAiAgEDGA8wMDAxMDEwMTAwMDAwMFowDDAKBgNVHRUEAwoB
BTAiAgEDGA8wMDAxMDEwMTAwMDAwMFowDDAKBgNVHRUEAwoBBaAuMCwwHgYDVR0j
BBcwFYATcm9vdCBzdWJqZWN0IGtleSBpZDAKBgNVHRQEAwIBATAKBggqhkjOPQQD
AgNIADBFAiEAuKyEUD/rZigP95CfYTTujgc6hpQV5481Y+9N2vt7Y8cCIDSt1fNi
qv6UqrWJlIzWSpJYkm5jZZgf4MqTtHjJ40bM
-----END X509 CRL-----
7 changes: 7 additions & 0 deletions v3/testdata/crlWithNoDuplicatesInRevokedCertificateList.pem
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
-----BEGIN X509 CRL-----
MIHYMIGAAgEBMAoGCCqGSM49BAMCMAAYDzAwMDEwMTAxMDAwMDAwWjAkMCICAQMY
DzAwMDEwMTAxMDAwMDAwWjAMMAoGA1UdFQQDCgEFoDYwNDAmBgNVHSMEHzAdgBtp
bnRlcm1lZGlhdGUgc3ViamVjdCBrZXkgaWQwCgYDVR0UBAMCAQEwCgYIKoZIzj0E
AwIDRwAwRAIgKW/t2p4I+U4VJ3Tuo70JGzUY7vgv8BHCCyCnWtuKoiQCID3zPiiV
X2MUcmUEIoNvck0XyDbsxWFaDn76xddAMD/v
-----END X509 CRL-----

0 comments on commit 4b55d49

Please sign in to comment.