types.go 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295
  1. // Copyright 2016 The Go Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style
  3. // license that can be found in the LICENSE file.
  4. package acme
  5. import (
  6. "errors"
  7. "fmt"
  8. "net/http"
  9. "strings"
  10. "time"
  11. )
  12. // ACME server response statuses used to describe Authorization and Challenge states.
  13. const (
  14. StatusUnknown = "unknown"
  15. StatusPending = "pending"
  16. StatusProcessing = "processing"
  17. StatusValid = "valid"
  18. StatusInvalid = "invalid"
  19. StatusRevoked = "revoked"
  20. )
  21. // CRLReasonCode identifies the reason for a certificate revocation.
  22. type CRLReasonCode int
  23. // CRL reason codes as defined in RFC 5280.
  24. const (
  25. CRLReasonUnspecified CRLReasonCode = 0
  26. CRLReasonKeyCompromise CRLReasonCode = 1
  27. CRLReasonCACompromise CRLReasonCode = 2
  28. CRLReasonAffiliationChanged CRLReasonCode = 3
  29. CRLReasonSuperseded CRLReasonCode = 4
  30. CRLReasonCessationOfOperation CRLReasonCode = 5
  31. CRLReasonCertificateHold CRLReasonCode = 6
  32. CRLReasonRemoveFromCRL CRLReasonCode = 8
  33. CRLReasonPrivilegeWithdrawn CRLReasonCode = 9
  34. CRLReasonAACompromise CRLReasonCode = 10
  35. )
  36. // ErrUnsupportedKey is returned when an unsupported key type is encountered.
  37. var ErrUnsupportedKey = errors.New("acme: unknown key type; only RSA and ECDSA are supported")
  38. // Error is an ACME error, defined in Problem Details for HTTP APIs doc
  39. // http://tools.ietf.org/html/draft-ietf-appsawg-http-problem.
  40. type Error struct {
  41. // StatusCode is The HTTP status code generated by the origin server.
  42. StatusCode int
  43. // ProblemType is a URI reference that identifies the problem type,
  44. // typically in a "urn:acme:error:xxx" form.
  45. ProblemType string
  46. // Detail is a human-readable explanation specific to this occurrence of the problem.
  47. Detail string
  48. // Header is the original server error response headers.
  49. // It may be nil.
  50. Header http.Header
  51. }
  52. func (e *Error) Error() string {
  53. return fmt.Sprintf("%d %s: %s", e.StatusCode, e.ProblemType, e.Detail)
  54. }
  55. // AuthorizationError indicates that an authorization for an identifier
  56. // did not succeed.
  57. // It contains all errors from Challenge items of the failed Authorization.
  58. type AuthorizationError struct {
  59. // URI uniquely identifies the failed Authorization.
  60. URI string
  61. // Identifier is an AuthzID.Value of the failed Authorization.
  62. Identifier string
  63. // Errors is a collection of non-nil error values of Challenge items
  64. // of the failed Authorization.
  65. Errors []error
  66. }
  67. func (a *AuthorizationError) Error() string {
  68. e := make([]string, len(a.Errors))
  69. for i, err := range a.Errors {
  70. e[i] = err.Error()
  71. }
  72. return fmt.Sprintf("acme: authorization error for %s: %s", a.Identifier, strings.Join(e, "; "))
  73. }
  74. // RateLimit reports whether err represents a rate limit error and
  75. // any Retry-After duration returned by the server.
  76. //
  77. // See the following for more details on rate limiting:
  78. // https://tools.ietf.org/html/draft-ietf-acme-acme-05#section-5.6
  79. func RateLimit(err error) (time.Duration, bool) {
  80. e, ok := err.(*Error)
  81. if !ok {
  82. return 0, false
  83. }
  84. // Some CA implementations may return incorrect values.
  85. // Use case-insensitive comparison.
  86. if !strings.HasSuffix(strings.ToLower(e.ProblemType), ":ratelimited") {
  87. return 0, false
  88. }
  89. if e.Header == nil {
  90. return 0, true
  91. }
  92. return retryAfter(e.Header.Get("Retry-After"), 0), true
  93. }
  94. // Account is a user account. It is associated with a private key.
  95. type Account struct {
  96. // URI is the account unique ID, which is also a URL used to retrieve
  97. // account data from the CA.
  98. URI string
  99. // Contact is a slice of contact info used during registration.
  100. Contact []string
  101. // The terms user has agreed to.
  102. // A value not matching CurrentTerms indicates that the user hasn't agreed
  103. // to the actual Terms of Service of the CA.
  104. AgreedTerms string
  105. // Actual terms of a CA.
  106. CurrentTerms string
  107. // Authz is the authorization URL used to initiate a new authz flow.
  108. Authz string
  109. // Authorizations is a URI from which a list of authorizations
  110. // granted to this account can be fetched via a GET request.
  111. Authorizations string
  112. // Certificates is a URI from which a list of certificates
  113. // issued for this account can be fetched via a GET request.
  114. Certificates string
  115. }
  116. // Directory is ACME server discovery data.
  117. type Directory struct {
  118. // RegURL is an account endpoint URL, allowing for creating new
  119. // and modifying existing accounts.
  120. RegURL string
  121. // AuthzURL is used to initiate Identifier Authorization flow.
  122. AuthzURL string
  123. // CertURL is a new certificate issuance endpoint URL.
  124. CertURL string
  125. // RevokeURL is used to initiate a certificate revocation flow.
  126. RevokeURL string
  127. // Term is a URI identifying the current terms of service.
  128. Terms string
  129. // Website is an HTTP or HTTPS URL locating a website
  130. // providing more information about the ACME server.
  131. Website string
  132. // CAA consists of lowercase hostname elements, which the ACME server
  133. // recognises as referring to itself for the purposes of CAA record validation
  134. // as defined in RFC6844.
  135. CAA []string
  136. }
  137. // Challenge encodes a returned CA challenge.
  138. // Its Error field may be non-nil if the challenge is part of an Authorization
  139. // with StatusInvalid.
  140. type Challenge struct {
  141. // Type is the challenge type, e.g. "http-01", "tls-sni-02", "dns-01".
  142. Type string
  143. // URI is where a challenge response can be posted to.
  144. URI string
  145. // Token is a random value that uniquely identifies the challenge.
  146. Token string
  147. // Status identifies the status of this challenge.
  148. Status string
  149. // Error indicates the reason for an authorization failure
  150. // when this challenge was used.
  151. // The type of a non-nil value is *Error.
  152. Error error
  153. }
  154. // Authorization encodes an authorization response.
  155. type Authorization struct {
  156. // URI uniquely identifies a authorization.
  157. URI string
  158. // Status identifies the status of an authorization.
  159. Status string
  160. // Identifier is what the account is authorized to represent.
  161. Identifier AuthzID
  162. // Challenges that the client needs to fulfill in order to prove possession
  163. // of the identifier (for pending authorizations).
  164. // For final authorizations, the challenges that were used.
  165. Challenges []*Challenge
  166. // A collection of sets of challenges, each of which would be sufficient
  167. // to prove possession of the identifier.
  168. // Clients must complete a set of challenges that covers at least one set.
  169. // Challenges are identified by their indices in the challenges array.
  170. // If this field is empty, the client needs to complete all challenges.
  171. Combinations [][]int
  172. }
  173. // AuthzID is an identifier that an account is authorized to represent.
  174. type AuthzID struct {
  175. Type string // The type of identifier, e.g. "dns".
  176. Value string // The identifier itself, e.g. "example.org".
  177. }
  178. // wireAuthz is ACME JSON representation of Authorization objects.
  179. type wireAuthz struct {
  180. Status string
  181. Challenges []wireChallenge
  182. Combinations [][]int
  183. Identifier struct {
  184. Type string
  185. Value string
  186. }
  187. }
  188. func (z *wireAuthz) authorization(uri string) *Authorization {
  189. a := &Authorization{
  190. URI: uri,
  191. Status: z.Status,
  192. Identifier: AuthzID{Type: z.Identifier.Type, Value: z.Identifier.Value},
  193. Combinations: z.Combinations, // shallow copy
  194. Challenges: make([]*Challenge, len(z.Challenges)),
  195. }
  196. for i, v := range z.Challenges {
  197. a.Challenges[i] = v.challenge()
  198. }
  199. return a
  200. }
  201. func (z *wireAuthz) error(uri string) *AuthorizationError {
  202. err := &AuthorizationError{
  203. URI: uri,
  204. Identifier: z.Identifier.Value,
  205. }
  206. for _, raw := range z.Challenges {
  207. if raw.Error != nil {
  208. err.Errors = append(err.Errors, raw.Error.error(nil))
  209. }
  210. }
  211. return err
  212. }
  213. // wireChallenge is ACME JSON challenge representation.
  214. type wireChallenge struct {
  215. URI string `json:"uri"`
  216. Type string
  217. Token string
  218. Status string
  219. Error *wireError
  220. }
  221. func (c *wireChallenge) challenge() *Challenge {
  222. v := &Challenge{
  223. URI: c.URI,
  224. Type: c.Type,
  225. Token: c.Token,
  226. Status: c.Status,
  227. }
  228. if v.Status == "" {
  229. v.Status = StatusPending
  230. }
  231. if c.Error != nil {
  232. v.Error = c.Error.error(nil)
  233. }
  234. return v
  235. }
  236. // wireError is a subset of fields of the Problem Details object
  237. // as described in https://tools.ietf.org/html/rfc7807#section-3.1.
  238. type wireError struct {
  239. Status int
  240. Type string
  241. Detail string
  242. }
  243. func (e *wireError) error(h http.Header) *Error {
  244. return &Error{
  245. StatusCode: e.Status,
  246. ProblemType: e.Type,
  247. Detail: e.Detail,
  248. Header: h,
  249. }
  250. }