error.go 12 KB

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