123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439 |
- package errors
- import (
- "crypto/x509"
- "encoding/json"
- "fmt"
- )
- // Error is the error type usually returned by functions in CF SSL package.
- // It contains a 4-digit error code where the most significant digit
- // describes the category where the error occurred and the rest 3 digits
- // describe the specific error reason.
- type Error struct {
- ErrorCode int `json:"code"`
- Message string `json:"message"`
- }
- // Category is the most significant digit of the error code.
- type Category int
- // Reason is the last 3 digits of the error code.
- type Reason int
- const (
- // Success indicates no error occurred.
- Success Category = 1000 * iota // 0XXX
- // CertificateError indicates a fault in a certificate.
- CertificateError // 1XXX
- // PrivateKeyError indicates a fault in a private key.
- PrivateKeyError // 2XXX
- // IntermediatesError indicates a fault in an intermediate.
- IntermediatesError // 3XXX
- // RootError indicates a fault in a root.
- RootError // 4XXX
- // PolicyError indicates an error arising from a malformed or
- // non-existent policy, or a breach of policy.
- PolicyError // 5XXX
- // DialError indicates a network fault.
- DialError // 6XXX
- // APIClientError indicates a problem with the API client.
- APIClientError // 7XXX
- // OCSPError indicates a problem with OCSP signing
- OCSPError // 8XXX
- // CSRError indicates a problem with CSR parsing
- CSRError // 9XXX
- // CTError indicates a problem with the certificate transparency process
- CTError // 10XXX
- // CertStoreError indicates a problem with the certificate store
- CertStoreError // 11XXX
- )
- // None is a non-specified error.
- const (
- None Reason = iota
- )
- // Warning code for a success
- const (
- BundleExpiringBit int = 1 << iota // 0x01
- BundleNotUbiquitousBit // 0x02
- )
- // Parsing errors
- const (
- Unknown Reason = iota // X000
- ReadFailed // X001
- DecodeFailed // X002
- ParseFailed // X003
- )
- // The following represent certificate non-parsing errors, and must be
- // specified along with CertificateError.
- const (
- // SelfSigned indicates that a certificate is self-signed and
- // cannot be used in the manner being attempted.
- SelfSigned Reason = 100 * (iota + 1) // Code 11XX
- // VerifyFailed is an X.509 verification failure. The least two
- // significant digits of 12XX is determined as the actual x509
- // error is examined.
- VerifyFailed // Code 12XX
- // BadRequest indicates that the certificate request is invalid.
- BadRequest // Code 13XX
- // MissingSerial indicates that the profile specified
- // 'ClientProvidesSerialNumbers', but the SignRequest did not include a serial
- // number.
- MissingSerial // Code 14XX
- )
- const (
- certificateInvalid = 10 * (iota + 1) //121X
- unknownAuthority //122x
- )
- // The following represent private-key non-parsing errors, and must be
- // specified with PrivateKeyError.
- const (
- // Encrypted indicates that the private key is a PKCS #8 encrypted
- // private key. At this time, CFSSL does not support decrypting
- // these keys.
- Encrypted Reason = 100 * (iota + 1) //21XX
- // NotRSAOrECCOrEd25519 indicates that they key is not an RSA or ECC or Ed25519
- // private key; these are the only two private key types supported
- // at this time by CFSSL.
- NotRSAOrECCOrEd25519 //22XX
- // KeyMismatch indicates that the private key does not match
- // the public key or certificate being presented with the key.
- KeyMismatch //23XX
- // GenerationFailed indicates that a private key could not
- // be generated.
- GenerationFailed //24XX
- // Unavailable indicates that a private key mechanism (such as
- // PKCS #11) was requested but support for that mechanism is
- // not available.
- Unavailable
- )
- // The following are policy-related non-parsing errors, and must be
- // specified along with PolicyError.
- const (
- // NoKeyUsages indicates that the profile does not permit any
- // key usages for the certificate.
- NoKeyUsages Reason = 100 * (iota + 1) // 51XX
- // InvalidPolicy indicates that policy being requested is not
- // a valid policy or does not exist.
- InvalidPolicy // 52XX
- // InvalidRequest indicates a certificate request violated the
- // constraints of the policy being applied to the request.
- InvalidRequest // 53XX
- // UnknownProfile indicates that the profile does not exist.
- UnknownProfile // 54XX
- UnmatchedWhitelist // 55xx
- )
- // The following are API client related errors, and should be
- // specified with APIClientError.
- const (
- // AuthenticationFailure occurs when the client is unable
- // to obtain an authentication token for the request.
- AuthenticationFailure Reason = 100 * (iota + 1)
- // JSONError wraps an encoding/json error.
- JSONError
- // IOError wraps an io/ioutil error.
- IOError
- // ClientHTTPError wraps a net/http error.
- ClientHTTPError
- // ServerRequestFailed covers any other failures from the API
- // client.
- ServerRequestFailed
- )
- // The following are OCSP related errors, and should be
- // specified with OCSPError
- const (
- // IssuerMismatch ocurs when the certificate in the OCSP signing
- // request was not issued by the CA that this responder responds for.
- IssuerMismatch Reason = 100 * (iota + 1) // 81XX
- // InvalidStatus occurs when the OCSP signing requests includes an
- // invalid value for the certificate status.
- InvalidStatus
- )
- // Certificate transparency related errors specified with CTError
- const (
- // PrecertSubmissionFailed occurs when submitting a precertificate to
- // a log server fails
- PrecertSubmissionFailed = 100 * (iota + 1)
- // CTClientConstructionFailed occurs when the construction of a new
- // github.com/google/certificate-transparency client fails.
- CTClientConstructionFailed
- // PrecertMissingPoison occurs when a precert is passed to SignFromPrecert
- // and is missing the CT poison extension.
- PrecertMissingPoison
- // PrecertInvalidPoison occurs when a precert is passed to SignFromPrecert
- // and has a invalid CT poison extension value or the extension is not
- // critical.
- PrecertInvalidPoison
- )
- // Certificate persistence related errors specified with CertStoreError
- const (
- // InsertionFailed occurs when a SQL insert query failes to complete.
- InsertionFailed = 100 * (iota + 1)
- // RecordNotFound occurs when a SQL query targeting on one unique
- // record failes to update the specified row in the table.
- RecordNotFound
- )
- // The error interface implementation, which formats to a JSON object string.
- func (e *Error) Error() string {
- marshaled, err := json.Marshal(e)
- if err != nil {
- panic(err)
- }
- return string(marshaled)
- }
- // New returns an error that contains an error code and message derived from
- // the given category, reason. Currently, to avoid confusion, it is not
- // allowed to create an error of category Success
- func New(category Category, reason Reason) *Error {
- errorCode := int(category) + int(reason)
- var msg string
- switch category {
- case OCSPError:
- switch reason {
- case ReadFailed:
- msg = "No certificate provided"
- case IssuerMismatch:
- msg = "Certificate not issued by this issuer"
- case InvalidStatus:
- msg = "Invalid revocation status"
- }
- case CertificateError:
- switch reason {
- case Unknown:
- msg = "Unknown certificate error"
- case ReadFailed:
- msg = "Failed to read certificate"
- case DecodeFailed:
- msg = "Failed to decode certificate"
- case ParseFailed:
- msg = "Failed to parse certificate"
- case SelfSigned:
- msg = "Certificate is self signed"
- case VerifyFailed:
- msg = "Unable to verify certificate"
- case BadRequest:
- msg = "Invalid certificate request"
- case MissingSerial:
- msg = "Missing serial number in request"
- default:
- panic(fmt.Sprintf("Unsupported CFSSL error reason %d under category CertificateError.",
- reason))
- }
- case PrivateKeyError:
- switch reason {
- case Unknown:
- msg = "Unknown private key error"
- case ReadFailed:
- msg = "Failed to read private key"
- case DecodeFailed:
- msg = "Failed to decode private key"
- case ParseFailed:
- msg = "Failed to parse private key"
- case Encrypted:
- msg = "Private key is encrypted."
- case NotRSAOrECCOrEd25519:
- msg = "Private key algorithm is not RSA or ECC or Ed25519"
- case KeyMismatch:
- msg = "Private key does not match public key"
- case GenerationFailed:
- msg = "Failed to new private key"
- case Unavailable:
- msg = "Private key is unavailable"
- default:
- panic(fmt.Sprintf("Unsupported CFSSL error reason %d under category PrivateKeyError.",
- reason))
- }
- case IntermediatesError:
- switch reason {
- case Unknown:
- msg = "Unknown intermediate certificate error"
- case ReadFailed:
- msg = "Failed to read intermediate certificate"
- case DecodeFailed:
- msg = "Failed to decode intermediate certificate"
- case ParseFailed:
- msg = "Failed to parse intermediate certificate"
- default:
- panic(fmt.Sprintf("Unsupported CFSSL error reason %d under category IntermediatesError.",
- reason))
- }
- case RootError:
- switch reason {
- case Unknown:
- msg = "Unknown root certificate error"
- case ReadFailed:
- msg = "Failed to read root certificate"
- case DecodeFailed:
- msg = "Failed to decode root certificate"
- case ParseFailed:
- msg = "Failed to parse root certificate"
- default:
- panic(fmt.Sprintf("Unsupported CFSSL error reason %d under category RootError.",
- reason))
- }
- case PolicyError:
- switch reason {
- case Unknown:
- msg = "Unknown policy error"
- case NoKeyUsages:
- msg = "Invalid policy: no key usage available"
- case InvalidPolicy:
- msg = "Invalid or unknown policy"
- case InvalidRequest:
- msg = "Policy violation request"
- case UnknownProfile:
- msg = "Unknown policy profile"
- case UnmatchedWhitelist:
- msg = "Request does not match policy whitelist"
- default:
- panic(fmt.Sprintf("Unsupported CFSSL error reason %d under category PolicyError.",
- reason))
- }
- case DialError:
- switch reason {
- case Unknown:
- msg = "Failed to dial remote server"
- default:
- panic(fmt.Sprintf("Unsupported CFSSL error reason %d under category DialError.",
- reason))
- }
- case APIClientError:
- switch reason {
- case AuthenticationFailure:
- msg = "API client authentication failure"
- case JSONError:
- msg = "API client JSON config error"
- case ClientHTTPError:
- msg = "API client HTTP error"
- case IOError:
- msg = "API client IO error"
- case ServerRequestFailed:
- msg = "API client error: Server request failed"
- default:
- panic(fmt.Sprintf("Unsupported CFSSL error reason %d under category APIClientError.",
- reason))
- }
- case CSRError:
- switch reason {
- case Unknown:
- msg = "CSR parsing failed due to unknown error"
- case ReadFailed:
- msg = "CSR file read failed"
- case ParseFailed:
- msg = "CSR Parsing failed"
- case DecodeFailed:
- msg = "CSR Decode failed"
- case BadRequest:
- msg = "CSR Bad request"
- default:
- panic(fmt.Sprintf("Unsupported CF-SSL error reason %d under category APIClientError.", reason))
- }
- case CTError:
- switch reason {
- case Unknown:
- msg = "Certificate transparency parsing failed due to unknown error"
- case PrecertSubmissionFailed:
- msg = "Certificate transparency precertificate submission failed"
- case PrecertMissingPoison:
- msg = "Precertificate is missing CT poison extension"
- case PrecertInvalidPoison:
- msg = "Precertificate contains an invalid CT poison extension"
- default:
- panic(fmt.Sprintf("Unsupported CF-SSL error reason %d under category CTError.", reason))
- }
- case CertStoreError:
- switch reason {
- case Unknown:
- msg = "Certificate store action failed due to unknown error"
- default:
- panic(fmt.Sprintf("Unsupported CF-SSL error reason %d under category CertStoreError.", reason))
- }
- default:
- panic(fmt.Sprintf("Unsupported CFSSL error type: %d.",
- category))
- }
- return &Error{ErrorCode: errorCode, Message: msg}
- }
- // Wrap returns an error that contains the given error and an error code derived from
- // the given category, reason and the error. Currently, to avoid confusion, it is not
- // allowed to create an error of category Success
- func Wrap(category Category, reason Reason, err error) *Error {
- errorCode := int(category) + int(reason)
- if err == nil {
- panic("Wrap needs a supplied error to initialize.")
- }
- // do not double wrap a error
- switch err.(type) {
- case *Error:
- panic("Unable to wrap a wrapped error.")
- }
- switch category {
- case CertificateError:
- // given VerifyFailed , report the status with more detailed status code
- // for some certificate errors we care.
- if reason == VerifyFailed {
- switch errorType := err.(type) {
- case x509.CertificateInvalidError:
- errorCode += certificateInvalid + int(errorType.Reason)
- case x509.UnknownAuthorityError:
- errorCode += unknownAuthority
- }
- }
- case PrivateKeyError, IntermediatesError, RootError, PolicyError, DialError,
- APIClientError, CSRError, CTError, CertStoreError, OCSPError:
- // no-op, just use the error
- default:
- panic(fmt.Sprintf("Unsupported CFSSL error type: %d.",
- category))
- }
- return &Error{ErrorCode: errorCode, Message: err.Error()}
- }
|