error.go 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424
  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. // NotRSAOrECC indicates that they key is not an RSA or ECC
  91. // private key; these are the only two private key types supported
  92. // at this time by CFSSL.
  93. NotRSAOrECC //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. )
  153. // Certificate persistence related errors specified with CertStoreError
  154. const (
  155. // InsertionFailed occurs when a SQL insert query failes to complete.
  156. InsertionFailed = 100 * (iota + 1)
  157. // RecordNotFound occurs when a SQL query targeting on one unique
  158. // record failes to update the specified row in the table.
  159. RecordNotFound
  160. )
  161. // The error interface implementation, which formats to a JSON object string.
  162. func (e *Error) Error() string {
  163. marshaled, err := json.Marshal(e)
  164. if err != nil {
  165. panic(err)
  166. }
  167. return string(marshaled)
  168. }
  169. // New returns an error that contains an error code and message derived from
  170. // the given category, reason. Currently, to avoid confusion, it is not
  171. // allowed to create an error of category Success
  172. func New(category Category, reason Reason) *Error {
  173. errorCode := int(category) + int(reason)
  174. var msg string
  175. switch category {
  176. case OCSPError:
  177. switch reason {
  178. case ReadFailed:
  179. msg = "No certificate provided"
  180. case IssuerMismatch:
  181. msg = "Certificate not issued by this issuer"
  182. case InvalidStatus:
  183. msg = "Invalid revocation status"
  184. }
  185. case CertificateError:
  186. switch reason {
  187. case Unknown:
  188. msg = "Unknown certificate error"
  189. case ReadFailed:
  190. msg = "Failed to read certificate"
  191. case DecodeFailed:
  192. msg = "Failed to decode certificate"
  193. case ParseFailed:
  194. msg = "Failed to parse certificate"
  195. case SelfSigned:
  196. msg = "Certificate is self signed"
  197. case VerifyFailed:
  198. msg = "Unable to verify certificate"
  199. case BadRequest:
  200. msg = "Invalid certificate request"
  201. case MissingSerial:
  202. msg = "Missing serial number in request"
  203. default:
  204. panic(fmt.Sprintf("Unsupported CFSSL error reason %d under category CertificateError.",
  205. reason))
  206. }
  207. case PrivateKeyError:
  208. switch reason {
  209. case Unknown:
  210. msg = "Unknown private key error"
  211. case ReadFailed:
  212. msg = "Failed to read private key"
  213. case DecodeFailed:
  214. msg = "Failed to decode private key"
  215. case ParseFailed:
  216. msg = "Failed to parse private key"
  217. case Encrypted:
  218. msg = "Private key is encrypted."
  219. case NotRSAOrECC:
  220. msg = "Private key algorithm is not RSA or ECC"
  221. case KeyMismatch:
  222. msg = "Private key does not match public key"
  223. case GenerationFailed:
  224. msg = "Failed to new private key"
  225. case Unavailable:
  226. msg = "Private key is unavailable"
  227. default:
  228. panic(fmt.Sprintf("Unsupported CFSSL error reason %d under category PrivateKeyError.",
  229. reason))
  230. }
  231. case IntermediatesError:
  232. switch reason {
  233. case Unknown:
  234. msg = "Unknown intermediate certificate error"
  235. case ReadFailed:
  236. msg = "Failed to read intermediate certificate"
  237. case DecodeFailed:
  238. msg = "Failed to decode intermediate certificate"
  239. case ParseFailed:
  240. msg = "Failed to parse intermediate certificate"
  241. default:
  242. panic(fmt.Sprintf("Unsupported CFSSL error reason %d under category IntermediatesError.",
  243. reason))
  244. }
  245. case RootError:
  246. switch reason {
  247. case Unknown:
  248. msg = "Unknown root certificate error"
  249. case ReadFailed:
  250. msg = "Failed to read root certificate"
  251. case DecodeFailed:
  252. msg = "Failed to decode root certificate"
  253. case ParseFailed:
  254. msg = "Failed to parse root certificate"
  255. default:
  256. panic(fmt.Sprintf("Unsupported CFSSL error reason %d under category RootError.",
  257. reason))
  258. }
  259. case PolicyError:
  260. switch reason {
  261. case Unknown:
  262. msg = "Unknown policy error"
  263. case NoKeyUsages:
  264. msg = "Invalid policy: no key usage available"
  265. case InvalidPolicy:
  266. msg = "Invalid or unknown policy"
  267. case InvalidRequest:
  268. msg = "Policy violation request"
  269. case UnknownProfile:
  270. msg = "Unknown policy profile"
  271. case UnmatchedWhitelist:
  272. msg = "Request does not match policy whitelist"
  273. default:
  274. panic(fmt.Sprintf("Unsupported CFSSL error reason %d under category PolicyError.",
  275. reason))
  276. }
  277. case DialError:
  278. switch reason {
  279. case Unknown:
  280. msg = "Failed to dial remote server"
  281. default:
  282. panic(fmt.Sprintf("Unsupported CFSSL error reason %d under category DialError.",
  283. reason))
  284. }
  285. case APIClientError:
  286. switch reason {
  287. case AuthenticationFailure:
  288. msg = "API client authentication failure"
  289. case JSONError:
  290. msg = "API client JSON config error"
  291. case ClientHTTPError:
  292. msg = "API client HTTP error"
  293. case IOError:
  294. msg = "API client IO error"
  295. case ServerRequestFailed:
  296. msg = "API client error: Server request failed"
  297. default:
  298. panic(fmt.Sprintf("Unsupported CFSSL error reason %d under category APIClientError.",
  299. reason))
  300. }
  301. case CSRError:
  302. switch reason {
  303. case Unknown:
  304. msg = "CSR parsing failed due to unknown error"
  305. case ReadFailed:
  306. msg = "CSR file read failed"
  307. case ParseFailed:
  308. msg = "CSR Parsing failed"
  309. case DecodeFailed:
  310. msg = "CSR Decode failed"
  311. case BadRequest:
  312. msg = "CSR Bad request"
  313. default:
  314. panic(fmt.Sprintf("Unsupported CF-SSL error reason %d under category APIClientError.", reason))
  315. }
  316. case CTError:
  317. switch reason {
  318. case Unknown:
  319. msg = "Certificate transparency parsing failed due to unknown error"
  320. case PrecertSubmissionFailed:
  321. msg = "Certificate transparency precertificate submission failed"
  322. default:
  323. panic(fmt.Sprintf("Unsupported CF-SSL error reason %d under category CTError.", reason))
  324. }
  325. case CertStoreError:
  326. switch reason {
  327. case Unknown:
  328. msg = "Certificate store action failed due to unknown error"
  329. default:
  330. panic(fmt.Sprintf("Unsupported CF-SSL error reason %d under category CertStoreError.", reason))
  331. }
  332. default:
  333. panic(fmt.Sprintf("Unsupported CFSSL error type: %d.",
  334. category))
  335. }
  336. return &Error{ErrorCode: errorCode, Message: msg}
  337. }
  338. // Wrap returns an error that contains the given error and an error code derived from
  339. // the given category, reason and the error. Currently, to avoid confusion, it is not
  340. // allowed to create an error of category Success
  341. func Wrap(category Category, reason Reason, err error) *Error {
  342. errorCode := int(category) + int(reason)
  343. if err == nil {
  344. panic("Wrap needs a supplied error to initialize.")
  345. }
  346. // do not double wrap a error
  347. switch err.(type) {
  348. case *Error:
  349. panic("Unable to wrap a wrapped error.")
  350. }
  351. switch category {
  352. case CertificateError:
  353. // given VerifyFailed , report the status with more detailed status code
  354. // for some certificate errors we care.
  355. if reason == VerifyFailed {
  356. switch errorType := err.(type) {
  357. case x509.CertificateInvalidError:
  358. errorCode += certificateInvalid + int(errorType.Reason)
  359. case x509.UnknownAuthorityError:
  360. errorCode += unknownAuthority
  361. }
  362. }
  363. case PrivateKeyError, IntermediatesError, RootError, PolicyError, DialError,
  364. APIClientError, CSRError, CTError, CertStoreError:
  365. // no-op, just use the error
  366. default:
  367. panic(fmt.Sprintf("Unsupported CFSSL error type: %d.",
  368. category))
  369. }
  370. return &Error{ErrorCode: errorCode, Message: err.Error()}
  371. }