Skip to content

Commit

Permalink
Add support to deprecated CRL functions for go1.18
Browse files Browse the repository at this point in the history
Move and separate version-sensitive functionalities related to
CRL into two go files within the config package so that it can
build with the corresponding go version.

Signed-off-by: Ziqi Zhang <ziqi.zhang.ext@ericsson.com>
  • Loading branch information
Ziqi Zhang committed Aug 3, 2023
1 parent e87d76c commit 679b65a
Show file tree
Hide file tree
Showing 4 changed files with 157 additions and 40 deletions.
75 changes: 75 additions & 0 deletions config/crl.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
// Copyright 2016 The Prometheus 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.

// This file is built for It provides functionalities to parse raw CRLs,
// check their validity and verify their signatures against provided
// certificates (CAs). It also allows checking the revocation status of the
// provided certificates.

// It is built for Go versions after and include Go version 1.19 as there
// are new functionality related to CRL handling.

//go:build go1.19
// +build go1.19

package config

import (
"crypto/x509"
"encoding/pem"
"fmt"
"time"
)

// Parse all CRLs and return a slice of valid CRLs.
func parseCRLs(rawCRL []byte, cAs []*x509.Certificate) ([]*x509.RevocationList, error) {
var crls []*x509.RevocationList
for p, r := pem.Decode(rawCRL); p != nil; p, r = pem.Decode(r) {
if p.Type != "X509 CRL" {
return nil, fmt.Errorf("unable to decode raw certificate revocation list")
}
crl, err := x509.ParseRevocationList(p.Bytes)
if err != nil {
return nil, err
}

// Check CRL exipry status.
if crl.NextUpdate.Before(time.Now()) {
return nil, fmt.Errorf("certificate revocation list is outdated")
}

// Check each CRL is signed by any CA, if not, ignore the CRL.
// Otherwise, append to the valid slice of CRL.
for _, ca := range cAs {
err = crl.CheckSignatureFrom(ca)
if err == nil {
crls = append(crls, crl)
break
}
}
}
return crls, nil
}

func validRevocationStatus(cAs []*x509.Certificate, cRLs []*x509.RevocationList) error {
for _, cert := range cAs {
for _, crl := range cRLs {
for _, revokedCertificate := range crl.RevokedCertificates {
if revokedCertificate.SerialNumber.Cmp(cert.SerialNumber) == 0 {
return fmt.Errorf("certificate was revoked")
}
}
}
}
return nil
}
76 changes: 76 additions & 0 deletions config/crl_deprecated.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
// Copyright 2016 The Prometheus 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.

// This file is built for It provides functionalities to parse raw CRLs,
// check their validity and verify their signatures against provided
// certificates (CAs). It also allows checking the revocation status of the
// provided certificates.

// It is built for Go versions before 1.19 as there are deprecated
// functionality related to CRL handling.

//go:build !go1.19
// +build !go1.19

package config

import (
"crypto/x509"
"crypto/x509/pkix"
"encoding/pem"
"fmt"
"time"
)

// Parse all CRLs and return a slice of valid CRLs.
func parseCRLs(rawCRL []byte, cAs []*x509.Certificate) ([]*pkix.CertificateList, error) {
var crls []*pkix.CertificateList
for p, r := pem.Decode(rawCRL); p != nil; p, r = pem.Decode(r) {
if p.Type != "X509 CRL" {
return nil, fmt.Errorf("unable to decode raw certificate revocation list")
}
crl, err := x509.ParseCRL(p.Bytes)
if err != nil {
return nil, err
}

// Check CRL exipry status.
if crl.TBSCertList.NextUpdate.Before(time.Now()) {
return nil, fmt.Errorf("certificate revocation list is outdated")
}

// Check each CRL is signed by any CA, if not, ignore the CRL.
// Otherwise, append to the valid slice of CRL.
for _, ca := range cAs {
err = ca.CheckCRLSignature(crl)
if err == nil {
crls = append(crls, crl)
break
}
}
}
return crls, nil
}

func validRevocationStatus(cAs []*x509.Certificate, cRLs []*pkix.CertificateList) error {
for _, cert := range cAs {
for _, crl := range cRLs {
for _, revokedCertificate := range crl.TBSCertList.RevokedCertificates {
if revokedCertificate.SerialNumber.Cmp(cert.SerialNumber) == 0 {
return fmt.Errorf("certificate was revoked")
}
}
}
}
return nil
}
41 changes: 3 additions & 38 deletions config/http_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -1356,49 +1356,14 @@ func (c *TLSConfig) verifyPeerCertificate(rawCerts [][]byte, verifiedChains [][]
// against valid CRLs.
cAs = append(cAs, verifiedChains[0][0])

for _, cert := range cAs {
for _, crl := range crlsList {
for _, revokedCertificate := range crl.RevokedCertificates {
if revokedCertificate.SerialNumber.Cmp(cert.SerialNumber) == 0 {
return fmt.Errorf("certificate was revoked")
}
}
}
err = validRevocationStatus(cAs, crlsList)
if err != nil {
return err
}

return nil
}

// Parse all CRLs and return a slice of valid CRLs.
func parseCRLs(rawCRL []byte, cAs []*x509.Certificate) ([]*x509.RevocationList, error) {
var crls []*x509.RevocationList
for p, r := pem.Decode(rawCRL); p != nil; p, r = pem.Decode(r) {
if p.Type != "X509 CRL" {
return nil, fmt.Errorf("unable to decode raw certificate revocation list")
}
crl, err := x509.ParseRevocationList(p.Bytes)
if err != nil {
return nil, err
}

// Check CRL exipry status.
if crl.NextUpdate.Before(time.Now()) {
return nil, fmt.Errorf("certificate revocation list is outdated")
}

// Check each CRL is signed by any CA, if not, ignore the CRL.
// Otherwise, append to the valid slice of CRL.
for _, ca := range cAs {
err = crl.CheckSignatureFrom(ca)
if err == nil {
crls = append(crls, crl)
break
}
}
}
return crls, nil
}

// Parse raw certificates with padding structure.
func parseCerts(rawCerts []byte) ([]*x509.Certificate, error) {
var certList []*x509.Certificate
Expand Down
5 changes: 3 additions & 2 deletions config/http_config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2139,7 +2139,7 @@ func TestNewClientFromRevokedCertConfig(t *testing.T) {
handler: func(w http.ResponseWriter, r *http.Request) {
fmt.Fprint(w, ExpectedMessage)
},
}, { // Full chain of CA and the single root CA revoke the intermediate CA certificate.
}, { // Full chain of CA and CRL, the single root CA revoke the intermediate CA certificate.
clientConfig: HTTPClientConfig{
TLSConfig: TLSConfig{
CAFile: TLSCAChainPath,
Expand All @@ -2152,7 +2152,8 @@ func TestNewClientFromRevokedCertConfig(t *testing.T) {
handler: func(w http.ResponseWriter, r *http.Request) {
fmt.Fprint(w, ExpectedMessage)
},
}, { // Missing root in the CA Chain and the full chain of CRLs, the Intermediate CA revoke the peer certificate.
}, { // Missing root in the CA Chain and the full chain of CRLs,
// the Intermediate CA revoke the peer certificate.
clientConfig: HTTPClientConfig{
TLSConfig: TLSConfig{
CAFile: TLSCACHainNoRootPath,
Expand Down

0 comments on commit 679b65a

Please sign in to comment.