capi/lib/expiration/expiration.go (58 lines of code) (raw):
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package expiration
import (
"crypto/x509"
"github.com/mozilla/CCADB-Tools/capi/lib/expiration/certutil"
"github.com/pkg/errors"
)
type Status string
const (
Valid Status = "valid"
Expired = "expired"
IssuerUnknown = "issuerUnknown"
UnexpectedResponse = "unexpectedResponse"
)
func toStatus(nssResponse string) (Status, bool) {
status, ok := map[string]Status{
certutil.VALID: Valid,
certutil.EXPIRED: Expired,
certutil.ISSUER_UNKOWN: IssuerUnknown,
}[nssResponse]
return status, ok
}
type ExpirationStatus struct {
Raw string `json:"-"`
Error string
Status Status
}
func VerifyChain(chain []*x509.Certificate) ([]ExpirationStatus, error) {
statuses := make([]ExpirationStatus, len(chain))
c, err := certutil.NewCertutil()
if err != nil {
return statuses, errors.Wrap(err, "failed to initialize a new NSS certificate database")
}
defer c.Delete()
for _, cert := range chain {
out, err := c.Install(cert)
o := string(out)
if err != nil {
return statuses, errors.Wrapf(err, "failed to install certificate, %v", o)
}
}
for i, cert := range chain {
statuses[i] = queryExpiration(cert, c)
}
return statuses, nil
}
func queryExpiration(certificate *x509.Certificate, c certutil.Certutil) (exps ExpirationStatus) {
// @TODO try to figure certutil's error codes. It uses non zero codes when the answer is
// anything other than just "valid", so it's not a reliable way to know whether or not
// the tool was fundamentally used wrong or if the cert is just expired or what.
resp, _ := c.Verify(certificate)
response := string(resp)
exps.Raw = response
switch status, ok := toStatus(response); ok {
case true:
exps.Status = status
case false:
exps.Error = response
exps.Status = UnexpectedResponse
}
return
}