types.go 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186
  1. package acme
  2. import (
  3. "errors"
  4. "fmt"
  5. "net/http"
  6. )
  7. // ACME server response statuses used to describe Authorization and Challenge states.
  8. const (
  9. StatusUnknown = "unknown"
  10. StatusPending = "pending"
  11. StatusProcessing = "processing"
  12. StatusValid = "valid"
  13. StatusInvalid = "invalid"
  14. StatusRevoked = "revoked"
  15. )
  16. // ErrUnsupportedKey is returned when an unsupported key type is encountered.
  17. var ErrUnsupportedKey = errors.New("acme: unknown key type; only RSA and ECDSA are supported")
  18. // Error is an ACME error, defined in Problem Details for HTTP APIs doc
  19. // http://tools.ietf.org/html/draft-ietf-appsawg-http-problem.
  20. type Error struct {
  21. // StatusCode is The HTTP status code generated by the origin server.
  22. StatusCode int
  23. // ProblemType is a URI reference that identifies the problem type,
  24. // typically in a "urn:acme:error:xxx" form.
  25. ProblemType string
  26. // Detail is a human-readable explanation specific to this occurrence of the problem.
  27. Detail string
  28. // Header is the original server error response headers.
  29. Header http.Header
  30. }
  31. func (e *Error) Error() string {
  32. return fmt.Sprintf("%d %s: %s", e.StatusCode, e.ProblemType, e.Detail)
  33. }
  34. // Account is a user account. It is associated with a private key.
  35. type Account struct {
  36. // URI is the account unique ID, which is also a URL used to retrieve
  37. // account data from the CA.
  38. URI string
  39. // Contact is a slice of contact info used during registration.
  40. Contact []string
  41. // The terms user has agreed to.
  42. // A value not matching CurrentTerms indicates that the user hasn't agreed
  43. // to the actual Terms of Service of the CA.
  44. AgreedTerms string
  45. // Actual terms of a CA.
  46. CurrentTerms string
  47. // Authz is the authorization URL used to initiate a new authz flow.
  48. Authz string
  49. // Authorizations is a URI from which a list of authorizations
  50. // granted to this account can be fetched via a GET request.
  51. Authorizations string
  52. // Certificates is a URI from which a list of certificates
  53. // issued for this account can be fetched via a GET request.
  54. Certificates string
  55. }
  56. // Directory is ACME server discovery data.
  57. type Directory struct {
  58. // RegURL is an account endpoint URL, allowing for creating new
  59. // and modifying existing accounts.
  60. RegURL string
  61. // AuthzURL is used to initiate Identifier Authorization flow.
  62. AuthzURL string
  63. // CertURL is a new certificate issuance endpoint URL.
  64. CertURL string
  65. // RevokeURL is used to initiate a certificate revocation flow.
  66. RevokeURL string
  67. // Term is a URI identifying the current terms of service.
  68. Terms string
  69. // Website is an HTTP or HTTPS URL locating a website
  70. // providing more information about the ACME server.
  71. Website string
  72. // CAA consists of lowercase hostname elements, which the ACME server
  73. // recognises as referring to itself for the purposes of CAA record validation
  74. // as defined in RFC6844.
  75. CAA []string
  76. }
  77. // Challenge encodes a returned CA challenge.
  78. type Challenge struct {
  79. // Type is the challenge type, e.g. "http-01", "tls-sni-02", "dns-01".
  80. Type string
  81. // URI is where a challenge response can be posted to.
  82. URI string
  83. // Token is a random value that uniquely identifies the challenge.
  84. Token string
  85. // Status identifies the status of this challenge.
  86. Status string
  87. }
  88. // Authorization encodes an authorization response.
  89. type Authorization struct {
  90. // URI uniquely identifies a authorization.
  91. URI string
  92. // Status identifies the status of an authorization.
  93. Status string
  94. // Identifier is what the account is authorized to represent.
  95. Identifier AuthzID
  96. // Challenges that the client needs to fulfill in order to prove possession
  97. // of the identifier (for pending authorizations).
  98. // For final authorizations, the challenges that were used.
  99. Challenges []*Challenge
  100. // A collection of sets of challenges, each of which would be sufficient
  101. // to prove possession of the identifier.
  102. // Clients must complete a set of challenges that covers at least one set.
  103. // Challenges are identified by their indices in the challenges array.
  104. // If this field is empty, the client needs to complete all challenges.
  105. Combinations [][]int
  106. }
  107. // AuthzID is an identifier that an account is authorized to represent.
  108. type AuthzID struct {
  109. Type string // The type of identifier, e.g. "dns".
  110. Value string // The identifier itself, e.g. "example.org".
  111. }
  112. // wireAuthz is ACME JSON representation of Authorization objects.
  113. type wireAuthz struct {
  114. Status string
  115. Challenges []wireChallenge
  116. Combinations [][]int
  117. Identifier struct {
  118. Type string
  119. Value string
  120. }
  121. }
  122. func (z *wireAuthz) authorization(uri string) *Authorization {
  123. a := &Authorization{
  124. URI: uri,
  125. Status: z.Status,
  126. Identifier: AuthzID{Type: z.Identifier.Type, Value: z.Identifier.Value},
  127. Combinations: z.Combinations, // shallow copy
  128. Challenges: make([]*Challenge, len(z.Challenges)),
  129. }
  130. for i, v := range z.Challenges {
  131. a.Challenges[i] = v.challenge()
  132. }
  133. return a
  134. }
  135. // wireChallenge is ACME JSON challenge representation.
  136. type wireChallenge struct {
  137. URI string `json:"uri"`
  138. Type string
  139. Token string
  140. Status string
  141. }
  142. func (c *wireChallenge) challenge() *Challenge {
  143. v := &Challenge{
  144. URI: c.URI,
  145. Type: c.Type,
  146. Token: c.Token,
  147. Status: c.Status,
  148. }
  149. if v.Status == "" {
  150. v.Status = StatusPending
  151. }
  152. return v
  153. }