diff --git a/security/advancedtls/crl.go b/security/advancedtls/crl.go index d825ef10d..7d044413f 100644 --- a/security/advancedtls/crl.go +++ b/security/advancedtls/crl.go @@ -279,7 +279,7 @@ func checkCert(c *x509.Certificate, crlVerifyCrt []*x509.Certificate, cfg Revoca crl, err := fetchCRL(c, crlVerifyCrt, cfg) if err != nil { // We couldn't load any CRL files for the certificate, so we don't know if it's RevocationUnrevoked or not. - grpclogLogger.Warningf("getIssuerCRL(%v) err = %v", c.Issuer, err) + grpclogLogger.Warningf("fetchCRL(%v) err = %v", c.Issuer, err) return RevocationUndetermined } revocation, err := checkCertRevocation(c, crl) @@ -441,6 +441,39 @@ func parseCRLExtensions(c *x509.RevocationList) (*CRL, error) { return certList, nil } +func readCRLFile(crlPath string) (*CRL, error) { + crlBytes, err := os.ReadFile(crlPath) + if err != nil { + return nil, err + } + + crl, err := parseRevocationList(crlBytes) + if err != nil { + return nil, fmt.Errorf("parseRevocationList(%v) failed: %v", crlPath, err) + } + var certList *CRL + if certList, err = parseCRLExtensions(crl); err != nil { + grpclogLogger.Infof("fetchCRL: unsupported crl %v: %v", crlPath, err) + return nil, fmt.Errorf("fetchCRL: unsupported crl %v: %v", crlPath, err) + } + + rawCRLIssuer, err := extractCRLIssuer(crlBytes) + if err != nil { + return nil, err + } + certList.RawIssuer = rawCRLIssuer + // // RFC5280, 6.3.3 (b) Verify the issuer and scope of the complete CRL. + // TODO we may need to do this check elsewhere + // HOWEVER, the structure of CRL providers is that we let people use their + // own impl, so they should be making sure issuers match if + // bytes.Equal(rawIssuer, rawCRLIssuer) { + // parsedCRL = certList + // // Continue to find the highest number in the .rN suffix. + // continue + // } + return certList, nil +} + func fetchCRLOpenSSLHashDir(rawIssuer []byte, cfg RevocationConfig) (*CRL, error) { var parsedCRL *CRL // 6.3.3 (a) (1) (ii) diff --git a/security/advancedtls/crl_provider.go b/security/advancedtls/crl_provider.go index 276db374c..709726472 100644 --- a/security/advancedtls/crl_provider.go +++ b/security/advancedtls/crl_provider.go @@ -28,14 +28,23 @@ type CRLProvider interface { } type StaticCRLProvider struct { + // TODO CRL is sort of our internal representation - provide an API for + // people to read into it, or provide a simpler type in the API then + // internally convert to this form crls map[string]*CRL } +func MakeStaticCRLProvider() *StaticCRLProvider { + p := StaticCRLProvider{} + p.crls = make(map[string]*CRL) + return &p +} + func (p *StaticCRLProvider) AddCRL(crl *CRL) { p.crls[crl.CertList.Issuer.ToRDNSequence().String()] = crl } func (p *StaticCRLProvider) CRL(cert *x509.Certificate) (*CRL, error) { - // TODO what to do if no CRL found + // TODO handle no CRL found return p.crls[cert.Issuer.ToRDNSequence().String()], nil } diff --git a/security/advancedtls/crl_provider_test.go b/security/advancedtls/crl_provider_test.go new file mode 100644 index 000000000..4bc79bce1 --- /dev/null +++ b/security/advancedtls/crl_provider_test.go @@ -0,0 +1,46 @@ +/* + * + * Copyright 2023 gRPC authors. + * + * 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 advancedtls + +import ( + "fmt" + "testing" + + "google.golang.org/grpc/security/advancedtls/testdata" +) + +func TestStaticCRLProvider(t *testing.T) { + p := MakeStaticCRLProvider() + for i := 1; i <= 6; i++ { + // TODO use loadCRL in test instead of new readCRLFile func + crl, err := readCRLFile(testdata.Path(fmt.Sprintf("crl/%d.crl", i))) + if err != nil { + t.Fatalf("TODO couldn't read file") + } + p.AddCRL(crl) + } + certs := makeChain(t, testdata.Path("crl/unrevoked.pem")) + crl, err := p.CRL(certs[0]) + if err != nil { + t.Fatalf("TODO fetching from provider") + } + if crl == nil { + t.Fatalf("TODO CRL is nil") + } +}