error.go 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439
  1. package errors
  2. import (
  3. "crypto/x509"
  4. "encoding/json"
  5. "fmt"
  6. )
  7. // Error is the error type usually returned by functions in CF SSL package.
  8. // It contains a 4-digit error code where the most significant digit
  9. // describes the category where the error occurred and the rest 3 digits
  10. // describe the specific error reason.
  11. type Error struct {
  12. ErrorCode int `json:"code"`
  13. Message string `json:"message"`
  14. }
  15. // Category is the most significant digit of the error code.
  16. type Category int
  17. // Reason is the last 3 digits of the error code.
  18. type Reason int
  19. const (
  20. // Success indicates no error occurred.
  21. Success Category = 1000 * iota // 0XXX
  22. // CertificateError indicates a fault in a certificate.
  23. CertificateError // 1XXX
  24. // PrivateKeyError indicates a fault in a private key.
  25. PrivateKeyError // 2XXX
  26. // IntermediatesError indicates a fault in an intermediate.
  27. IntermediatesError // 3XXX
  28. // RootError indicates a fault in a root.
  29. RootError // 4XXX
  30. // PolicyError indicates an error arising from a malformed or
  31. // non-existent policy, or a breach of policy.
  32. PolicyError // 5XXX
  33. // DialError indicates a network fault.
  34. DialError // 6XXX
  35. // APIClientError indicates a problem with the API client.
  36. APIClientError // 7XXX
  37. // OCSPError indicates a problem with OCSP signing
  38. OCSPError // 8XXX
  39. // CSRError indicates a problem with CSR parsing
  40. CSRError // 9XXX
  41. // CTError indicates a problem with the certificate transparency process
  42. CTError // 10XXX
  43. // CertStoreError indicates a problem with the certificate store
  44. CertStoreError // 11XXX
  45. )
  46. // None is a non-specified error.
  47. const (
  48. None Reason = iota
  49. )
  50. // Warning code for a success
  51. const (
  52. BundleExpiringBit int = 1 << iota // 0x01
  53. BundleNotUbiquitousBit // 0x02
  54. )
  55. // Parsing errors
  56. const (
  57. Unknown Reason = iota // X000
  58. ReadFailed // X001
  59. DecodeFailed // X002
  60. ParseFailed // X003
  61. )
  62. // The following represent certificate non-parsing errors, and must be
  63. // specified along with CertificateError.
  64. const (
  65. // SelfSigned indicates that a certificate is self-signed and
  66. // cannot be used in the manner being attempted.
  67. SelfSigned Reason = 100 * (iota + 1) // Code 11XX
  68. // VerifyFailed is an X.509 verification failure. The least two
  69. // significant digits of 12XX is determined as the actual x509
  70. // error is examined.
  71. VerifyFailed // Code 12XX
  72. // BadRequest indicates that the certificate request is invalid.
  73. BadRequest // Code 13XX
  74. // MissingSerial indicates that the profile specified
  75. // 'ClientProvidesSerialNumbers', but the SignRequest did not include a serial
  76. // number.
  77. MissingSerial // Code 14XX
  78. )
  79. const (
  80. certificateInvalid = 10 * (iota + 1) //121X
  81. unknownAuthority //122x
  82. )
  83. // The following represent private-key non-parsing errors, and must be
  84. // specified with PrivateKeyError.
  85. const (
  86. // Encrypted indicates that the private key is a PKCS #8 encrypted
  87. // private key. At this time, CFSSL does not support decrypting
  88. // these keys.
  89. Encrypted Reason = 100 * (iota + 1) //21XX
  90. // NotRSAOrECCOrEd25519 indicates that they key is not an RSA or ECC or Ed25519
  91. // private key; these are the only two private key types supported
  92. // at this time by CFSSL.
  93. NotRSAOrECCOrEd25519 //22XX
  94. // KeyMismatch indicates that the private key does not match
  95. // the public key or certificate being presented with the key.
  96. KeyMismatch //23XX
  97. // GenerationFailed indicates that a private key could not
  98. // be generated.
  99. GenerationFailed //24XX
  100. // Unavailable indicates that a private key mechanism (such as
  101. // PKCS #11) was requested but support for that mechanism is
  102. // not available.
  103. Unavailable
  104. )
  105. // The following are policy-related non-parsing errors, and must be
  106. // specified along with PolicyError.
  107. const (
  108. // NoKeyUsages indicates that the profile does not permit any
  109. // key usages for the certificate.
  110. NoKeyUsages Reason = 100 * (iota + 1) // 51XX
  111. // InvalidPolicy indicates that policy being requested is not
  112. // a valid policy or does not exist.
  113. InvalidPolicy // 52XX
  114. // InvalidRequest indicates a certificate request violated the
  115. // constraints of the policy being applied to the request.
  116. InvalidRequest // 53XX
  117. // UnknownProfile indicates that the profile does not exist.
  118. UnknownProfile // 54XX
  119. UnmatchedWhitelist // 55xx
  120. )
  121. // The following are API client related errors, and should be
  122. // specified with APIClientError.
  123. const (
  124. // AuthenticationFailure occurs when the client is unable
  125. // to obtain an authentication token for the request.
  126. AuthenticationFailure Reason = 100 * (iota + 1)
  127. // JSONError wraps an encoding/json error.
  128. JSONError
  129. // IOError wraps an io/ioutil error.
  130. IOError
  131. // ClientHTTPError wraps a net/http error.
  132. ClientHTTPError
  133. // ServerRequestFailed covers any other failures from the API
  134. // client.
  135. ServerRequestFailed
  136. )
  137. // The following are OCSP related errors, and should be
  138. // specified with OCSPError
  139. const (
  140. // IssuerMismatch ocurs when the certificate in the OCSP signing
  141. // request was not issued by the CA that this responder responds for.
  142. IssuerMismatch Reason = 100 * (iota + 1) // 81XX
  143. // InvalidStatus occurs when the OCSP signing requests includes an
  144. // invalid value for the certificate status.
  145. InvalidStatus
  146. )
  147. // Certificate transparency related errors specified with CTError
  148. const (
  149. // PrecertSubmissionFailed occurs when submitting a precertificate to
  150. // a log server fails
  151. PrecertSubmissionFailed = 100 * (iota + 1)
  152. // CTClientConstructionFailed occurs when the construction of a new
  153. // github.com/google/certificate-transparency client fails.
  154. CTClientConstructionFailed
  155. // PrecertMissingPoison occurs when a precert is passed to SignFromPrecert
  156. // and is missing the CT poison extension.
  157. PrecertMissingPoison
  158. // PrecertInvalidPoison occurs when a precert is passed to SignFromPrecert
  159. // and has a invalid CT poison extension value or the extension is not
  160. // critical.
  161. PrecertInvalidPoison
  162. )
  163. // Certificate persistence related errors specified with CertStoreError
  164. const (
  165. // InsertionFailed occurs when a SQL insert query failes to complete.
  166. InsertionFailed = 100 * (iota + 1)
  167. // RecordNotFound occurs when a SQL query targeting on one unique
  168. // record failes to update the specified row in the table.
  169. RecordNotFound
  170. )
  171. // The error interface implementation, which formats to a JSON object string.
  172. func (e *Error) Error() string {
  173. marshaled, err := json.Marshal(e)
  174. if err != nil {
  175. panic(err)
  176. }
  177. return string(marshaled)
  178. }
  179. // New returns an error that contains an error code and message derived from
  180. // the given category, reason. Currently, to avoid confusion, it is not
  181. // allowed to create an error of category Success
  182. func New(category Category, reason Reason) *Error {
  183. errorCode := int(category) + int(reason)
  184. var msg string
  185. switch category {
  186. case OCSPError:
  187. switch reason {
  188. case ReadFailed:
  189. msg = "No certificate provided"
  190. case IssuerMismatch:
  191. msg = "Certificate not issued by this issuer"
  192. case InvalidStatus:
  193. msg = "Invalid revocation status"
  194. }
  195. case CertificateError:
  196. switch reason {
  197. case Unknown:
  198. msg = "Unknown certificate error"
  199. case ReadFailed:
  200. msg = "Failed to read certificate"
  201. case DecodeFailed:
  202. msg = "Failed to decode certificate"
  203. case ParseFailed:
  204. msg = "Failed to parse certificate"
  205. case SelfSigned:
  206. msg = "Certificate is self signed"
  207. case VerifyFailed:
  208. msg = "Unable to verify certificate"
  209. case BadRequest:
  210. msg = "Invalid certificate request"
  211. case MissingSerial:
  212. msg = "Missing serial number in request"
  213. default:
  214. panic(fmt.Sprintf("Unsupported CFSSL error reason %d under category CertificateError.",
  215. reason))
  216. }
  217. case PrivateKeyError:
  218. switch reason {
  219. case Unknown:
  220. msg = "Unknown private key error"
  221. case ReadFailed:
  222. msg = "Failed to read private key"
  223. case DecodeFailed:
  224. msg = "Failed to decode private key"
  225. case ParseFailed:
  226. msg = "Failed to parse private key"
  227. case Encrypted:
  228. msg = "Private key is encrypted."
  229. case NotRSAOrECCOrEd25519:
  230. msg = "Private key algorithm is not RSA or ECC or Ed25519"
  231. case KeyMismatch:
  232. msg = "Private key does not match public key"
  233. case GenerationFailed:
  234. msg = "Failed to new private key"
  235. case Unavailable:
  236. msg = "Private key is unavailable"
  237. default:
  238. panic(fmt.Sprintf("Unsupported CFSSL error reason %d under category PrivateKeyError.",
  239. reason))
  240. }
  241. case IntermediatesError:
  242. switch reason {
  243. case Unknown:
  244. msg = "Unknown intermediate certificate error"
  245. case ReadFailed:
  246. msg = "Failed to read intermediate certificate"
  247. case DecodeFailed:
  248. msg = "Failed to decode intermediate certificate"
  249. case ParseFailed:
  250. msg = "Failed to parse intermediate certificate"
  251. default:
  252. panic(fmt.Sprintf("Unsupported CFSSL error reason %d under category IntermediatesError.",
  253. reason))
  254. }
  255. case RootError:
  256. switch reason {
  257. case Unknown:
  258. msg = "Unknown root certificate error"
  259. case ReadFailed:
  260. msg = "Failed to read root certificate"
  261. case DecodeFailed:
  262. msg = "Failed to decode root certificate"
  263. case ParseFailed:
  264. msg = "Failed to parse root certificate"
  265. default:
  266. panic(fmt.Sprintf("Unsupported CFSSL error reason %d under category RootError.",
  267. reason))
  268. }
  269. case PolicyError:
  270. switch reason {
  271. case Unknown:
  272. msg = "Unknown policy error"
  273. case NoKeyUsages:
  274. msg = "Invalid policy: no key usage available"
  275. case InvalidPolicy:
  276. msg = "Invalid or unknown policy"
  277. case InvalidRequest:
  278. msg = "Policy violation request"
  279. case UnknownProfile:
  280. msg = "Unknown policy profile"
  281. case UnmatchedWhitelist:
  282. msg = "Request does not match policy whitelist"
  283. default:
  284. panic(fmt.Sprintf("Unsupported CFSSL error reason %d under category PolicyError.",
  285. reason))
  286. }
  287. case DialError:
  288. switch reason {
  289. case Unknown:
  290. msg = "Failed to dial remote server"
  291. default:
  292. panic(fmt.Sprintf("Unsupported CFSSL error reason %d under category DialError.",
  293. reason))
  294. }
  295. case APIClientError:
  296. switch reason {
  297. case AuthenticationFailure:
  298. msg = "API client authentication failure"
  299. case JSONError:
  300. msg = "API client JSON config error"
  301. case ClientHTTPError:
  302. msg = "API client HTTP error"
  303. case IOError:
  304. msg = "API client IO error"
  305. case ServerRequestFailed:
  306. msg = "API client error: Server request failed"
  307. default:
  308. panic(fmt.Sprintf("Unsupported CFSSL error reason %d under category APIClientError.",
  309. reason))
  310. }
  311. case CSRError:
  312. switch reason {
  313. case Unknown:
  314. msg = "CSR parsing failed due to unknown error"
  315. case ReadFailed:
  316. msg = "CSR file read failed"
  317. case ParseFailed:
  318. msg = "CSR Parsing failed"
  319. case DecodeFailed:
  320. msg = "CSR Decode failed"
  321. case BadRequest:
  322. msg = "CSR Bad request"
  323. default:
  324. panic(fmt.Sprintf("Unsupported CF-SSL error reason %d under category APIClientError.", reason))
  325. }
  326. case CTError:
  327. switch reason {
  328. case Unknown:
  329. msg = "Certificate transparency parsing failed due to unknown error"
  330. case PrecertSubmissionFailed:
  331. msg = "Certificate transparency precertificate submission failed"
  332. case PrecertMissingPoison:
  333. msg = "Precertificate is missing CT poison extension"
  334. case PrecertInvalidPoison:
  335. msg = "Precertificate contains an invalid CT poison extension"
  336. default:
  337. panic(fmt.Sprintf("Unsupported CF-SSL error reason %d under category CTError.", reason))
  338. }
  339. case CertStoreError:
  340. switch reason {
  341. case Unknown:
  342. msg = "Certificate store action failed due to unknown error"
  343. default:
  344. panic(fmt.Sprintf("Unsupported CF-SSL error reason %d under category CertStoreError.", reason))
  345. }
  346. default:
  347. panic(fmt.Sprintf("Unsupported CFSSL error type: %d.",
  348. category))
  349. }
  350. return &Error{ErrorCode: errorCode, Message: msg}
  351. }
  352. // Wrap returns an error that contains the given error and an error code derived from
  353. // the given category, reason and the error. Currently, to avoid confusion, it is not
  354. // allowed to create an error of category Success
  355. func Wrap(category Category, reason Reason, err error) *Error {
  356. errorCode := int(category) + int(reason)
  357. if err == nil {
  358. panic("Wrap needs a supplied error to initialize.")
  359. }
  360. // do not double wrap a error
  361. switch err.(type) {
  362. case *Error:
  363. panic("Unable to wrap a wrapped error.")
  364. }
  365. switch category {
  366. case CertificateError:
  367. // given VerifyFailed , report the status with more detailed status code
  368. // for some certificate errors we care.
  369. if reason == VerifyFailed {
  370. switch errorType := err.(type) {
  371. case x509.CertificateInvalidError:
  372. errorCode += certificateInvalid + int(errorType.Reason)
  373. case x509.UnknownAuthorityError:
  374. errorCode += unknownAuthority
  375. }
  376. }
  377. case PrivateKeyError, IntermediatesError, RootError, PolicyError, DialError,
  378. APIClientError, CSRError, CTError, CertStoreError, OCSPError:
  379. // no-op, just use the error
  380. default:
  381. panic(fmt.Sprintf("Unsupported CFSSL error type: %d.",
  382. category))
  383. }
  384. return &Error{ErrorCode: errorCode, Message: err.Error()}
  385. }