rfc8555.go 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476
  1. // Copyright 2019 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. "context"
  7. "crypto"
  8. "encoding/base64"
  9. "encoding/json"
  10. "encoding/pem"
  11. "errors"
  12. "fmt"
  13. "io"
  14. "net/http"
  15. "time"
  16. )
  17. // DeactivateReg permanently disables an existing account associated with c.Key.
  18. // A deactivated account can no longer request certificate issuance or access
  19. // resources related to the account, such as orders or authorizations.
  20. //
  21. // It only works with CAs implementing RFC 8555.
  22. func (c *Client) DeactivateReg(ctx context.Context) error {
  23. if _, err := c.Discover(ctx); err != nil { // required by c.accountKID
  24. return err
  25. }
  26. url := string(c.accountKID(ctx))
  27. if url == "" {
  28. return ErrNoAccount
  29. }
  30. req := json.RawMessage(`{"status": "deactivated"}`)
  31. res, err := c.post(ctx, nil, url, req, wantStatus(http.StatusOK))
  32. if err != nil {
  33. return err
  34. }
  35. res.Body.Close()
  36. return nil
  37. }
  38. // registerRFC is equivalent to c.Register but for CAs implementing RFC 8555.
  39. // It expects c.Discover to have already been called.
  40. func (c *Client) registerRFC(ctx context.Context, acct *Account, prompt func(tosURL string) bool) (*Account, error) {
  41. c.cacheMu.Lock() // guard c.kid access
  42. defer c.cacheMu.Unlock()
  43. req := struct {
  44. TermsAgreed bool `json:"termsOfServiceAgreed,omitempty"`
  45. Contact []string `json:"contact,omitempty"`
  46. ExternalAccountBinding *jsonWebSignature `json:"externalAccountBinding,omitempty"`
  47. }{
  48. Contact: acct.Contact,
  49. }
  50. if c.dir.Terms != "" {
  51. req.TermsAgreed = prompt(c.dir.Terms)
  52. }
  53. // set 'externalAccountBinding' field if requested
  54. if acct.ExternalAccountBinding != nil {
  55. eabJWS, err := c.encodeExternalAccountBinding(acct.ExternalAccountBinding)
  56. if err != nil {
  57. return nil, fmt.Errorf("acme: failed to encode external account binding: %v", err)
  58. }
  59. req.ExternalAccountBinding = eabJWS
  60. }
  61. res, err := c.post(ctx, c.Key, c.dir.RegURL, req, wantStatus(
  62. http.StatusOK, // account with this key already registered
  63. http.StatusCreated, // new account created
  64. ))
  65. if err != nil {
  66. return nil, err
  67. }
  68. defer res.Body.Close()
  69. a, err := responseAccount(res)
  70. if err != nil {
  71. return nil, err
  72. }
  73. // Cache Account URL even if we return an error to the caller.
  74. // It is by all means a valid and usable "kid" value for future requests.
  75. c.KID = KeyID(a.URI)
  76. if res.StatusCode == http.StatusOK {
  77. return nil, ErrAccountAlreadyExists
  78. }
  79. return a, nil
  80. }
  81. // encodeExternalAccountBinding will encode an external account binding stanza
  82. // as described in https://tools.ietf.org/html/rfc8555#section-7.3.4.
  83. func (c *Client) encodeExternalAccountBinding(eab *ExternalAccountBinding) (*jsonWebSignature, error) {
  84. jwk, err := jwkEncode(c.Key.Public())
  85. if err != nil {
  86. return nil, err
  87. }
  88. return jwsWithMAC(eab.Key, eab.KID, c.dir.RegURL, []byte(jwk))
  89. }
  90. // updateRegRFC is equivalent to c.UpdateReg but for CAs implementing RFC 8555.
  91. // It expects c.Discover to have already been called.
  92. func (c *Client) updateRegRFC(ctx context.Context, a *Account) (*Account, error) {
  93. url := string(c.accountKID(ctx))
  94. if url == "" {
  95. return nil, ErrNoAccount
  96. }
  97. req := struct {
  98. Contact []string `json:"contact,omitempty"`
  99. }{
  100. Contact: a.Contact,
  101. }
  102. res, err := c.post(ctx, nil, url, req, wantStatus(http.StatusOK))
  103. if err != nil {
  104. return nil, err
  105. }
  106. defer res.Body.Close()
  107. return responseAccount(res)
  108. }
  109. // getRegRFC is equivalent to c.GetReg but for CAs implementing RFC 8555.
  110. // It expects c.Discover to have already been called.
  111. func (c *Client) getRegRFC(ctx context.Context) (*Account, error) {
  112. req := json.RawMessage(`{"onlyReturnExisting": true}`)
  113. res, err := c.post(ctx, c.Key, c.dir.RegURL, req, wantStatus(http.StatusOK))
  114. if e, ok := err.(*Error); ok && e.ProblemType == "urn:ietf:params:acme:error:accountDoesNotExist" {
  115. return nil, ErrNoAccount
  116. }
  117. if err != nil {
  118. return nil, err
  119. }
  120. defer res.Body.Close()
  121. return responseAccount(res)
  122. }
  123. func responseAccount(res *http.Response) (*Account, error) {
  124. var v struct {
  125. Status string
  126. Contact []string
  127. Orders string
  128. }
  129. if err := json.NewDecoder(res.Body).Decode(&v); err != nil {
  130. return nil, fmt.Errorf("acme: invalid account response: %v", err)
  131. }
  132. return &Account{
  133. URI: res.Header.Get("Location"),
  134. Status: v.Status,
  135. Contact: v.Contact,
  136. OrdersURL: v.Orders,
  137. }, nil
  138. }
  139. // accountKeyRollover attempts to perform account key rollover.
  140. // On success it will change client.Key to the new key.
  141. func (c *Client) accountKeyRollover(ctx context.Context, newKey crypto.Signer) error {
  142. dir, err := c.Discover(ctx) // Also required by c.accountKID
  143. if err != nil {
  144. return err
  145. }
  146. kid := c.accountKID(ctx)
  147. if kid == noKeyID {
  148. return ErrNoAccount
  149. }
  150. oldKey, err := jwkEncode(c.Key.Public())
  151. if err != nil {
  152. return err
  153. }
  154. payload := struct {
  155. Account string `json:"account"`
  156. OldKey json.RawMessage `json:"oldKey"`
  157. }{
  158. Account: string(kid),
  159. OldKey: json.RawMessage(oldKey),
  160. }
  161. inner, err := jwsEncodeJSON(payload, newKey, noKeyID, noNonce, dir.KeyChangeURL)
  162. if err != nil {
  163. return err
  164. }
  165. res, err := c.post(ctx, nil, dir.KeyChangeURL, base64.RawURLEncoding.EncodeToString(inner), wantStatus(http.StatusOK))
  166. if err != nil {
  167. return err
  168. }
  169. defer res.Body.Close()
  170. c.Key = newKey
  171. return nil
  172. }
  173. // AuthorizeOrder initiates the order-based application for certificate issuance,
  174. // as opposed to pre-authorization in Authorize.
  175. // It is only supported by CAs implementing RFC 8555.
  176. //
  177. // The caller then needs to fetch each authorization with GetAuthorization,
  178. // identify those with StatusPending status and fulfill a challenge using Accept.
  179. // Once all authorizations are satisfied, the caller will typically want to poll
  180. // order status using WaitOrder until it's in StatusReady state.
  181. // To finalize the order and obtain a certificate, the caller submits a CSR with CreateOrderCert.
  182. func (c *Client) AuthorizeOrder(ctx context.Context, id []AuthzID, opt ...OrderOption) (*Order, error) {
  183. dir, err := c.Discover(ctx)
  184. if err != nil {
  185. return nil, err
  186. }
  187. req := struct {
  188. Identifiers []wireAuthzID `json:"identifiers"`
  189. NotBefore string `json:"notBefore,omitempty"`
  190. NotAfter string `json:"notAfter,omitempty"`
  191. }{}
  192. for _, v := range id {
  193. req.Identifiers = append(req.Identifiers, wireAuthzID{
  194. Type: v.Type,
  195. Value: v.Value,
  196. })
  197. }
  198. for _, o := range opt {
  199. switch o := o.(type) {
  200. case orderNotBeforeOpt:
  201. req.NotBefore = time.Time(o).Format(time.RFC3339)
  202. case orderNotAfterOpt:
  203. req.NotAfter = time.Time(o).Format(time.RFC3339)
  204. default:
  205. // Package's fault if we let this happen.
  206. panic(fmt.Sprintf("unsupported order option type %T", o))
  207. }
  208. }
  209. res, err := c.post(ctx, nil, dir.OrderURL, req, wantStatus(http.StatusCreated))
  210. if err != nil {
  211. return nil, err
  212. }
  213. defer res.Body.Close()
  214. return responseOrder(res)
  215. }
  216. // GetOrder retrives an order identified by the given URL.
  217. // For orders created with AuthorizeOrder, the url value is Order.URI.
  218. //
  219. // If a caller needs to poll an order until its status is final,
  220. // see the WaitOrder method.
  221. func (c *Client) GetOrder(ctx context.Context, url string) (*Order, error) {
  222. if _, err := c.Discover(ctx); err != nil {
  223. return nil, err
  224. }
  225. res, err := c.postAsGet(ctx, url, wantStatus(http.StatusOK))
  226. if err != nil {
  227. return nil, err
  228. }
  229. defer res.Body.Close()
  230. return responseOrder(res)
  231. }
  232. // WaitOrder polls an order from the given URL until it is in one of the final states,
  233. // StatusReady, StatusValid or StatusInvalid, the CA responded with a non-retryable error
  234. // or the context is done.
  235. //
  236. // It returns a non-nil Order only if its Status is StatusReady or StatusValid.
  237. // In all other cases WaitOrder returns an error.
  238. // If the Status is StatusInvalid, the returned error is of type *OrderError.
  239. func (c *Client) WaitOrder(ctx context.Context, url string) (*Order, error) {
  240. if _, err := c.Discover(ctx); err != nil {
  241. return nil, err
  242. }
  243. for {
  244. res, err := c.postAsGet(ctx, url, wantStatus(http.StatusOK))
  245. if err != nil {
  246. return nil, err
  247. }
  248. o, err := responseOrder(res)
  249. res.Body.Close()
  250. switch {
  251. case err != nil:
  252. // Skip and retry.
  253. case o.Status == StatusInvalid:
  254. return nil, &OrderError{OrderURL: o.URI, Status: o.Status}
  255. case o.Status == StatusReady || o.Status == StatusValid:
  256. return o, nil
  257. }
  258. d := retryAfter(res.Header.Get("Retry-After"))
  259. if d == 0 {
  260. // Default retry-after.
  261. // Same reasoning as in WaitAuthorization.
  262. d = time.Second
  263. }
  264. t := time.NewTimer(d)
  265. select {
  266. case <-ctx.Done():
  267. t.Stop()
  268. return nil, ctx.Err()
  269. case <-t.C:
  270. // Retry.
  271. }
  272. }
  273. }
  274. func responseOrder(res *http.Response) (*Order, error) {
  275. var v struct {
  276. Status string
  277. Expires time.Time
  278. Identifiers []wireAuthzID
  279. NotBefore time.Time
  280. NotAfter time.Time
  281. Error *wireError
  282. Authorizations []string
  283. Finalize string
  284. Certificate string
  285. }
  286. if err := json.NewDecoder(res.Body).Decode(&v); err != nil {
  287. return nil, fmt.Errorf("acme: error reading order: %v", err)
  288. }
  289. o := &Order{
  290. URI: res.Header.Get("Location"),
  291. Status: v.Status,
  292. Expires: v.Expires,
  293. NotBefore: v.NotBefore,
  294. NotAfter: v.NotAfter,
  295. AuthzURLs: v.Authorizations,
  296. FinalizeURL: v.Finalize,
  297. CertURL: v.Certificate,
  298. }
  299. for _, id := range v.Identifiers {
  300. o.Identifiers = append(o.Identifiers, AuthzID{Type: id.Type, Value: id.Value})
  301. }
  302. if v.Error != nil {
  303. o.Error = v.Error.error(nil /* headers */)
  304. }
  305. return o, nil
  306. }
  307. // CreateOrderCert submits the CSR (Certificate Signing Request) to a CA at the specified URL.
  308. // The URL is the FinalizeURL field of an Order created with AuthorizeOrder.
  309. //
  310. // If the bundle argument is true, the returned value also contain the CA (issuer)
  311. // certificate chain. Otherwise, only a leaf certificate is returned.
  312. // The returned URL can be used to re-fetch the certificate using FetchCert.
  313. //
  314. // This method is only supported by CAs implementing RFC 8555. See CreateCert for pre-RFC CAs.
  315. //
  316. // CreateOrderCert returns an error if the CA's response is unreasonably large.
  317. // Callers are encouraged to parse the returned value to ensure the certificate is valid and has the expected features.
  318. func (c *Client) CreateOrderCert(ctx context.Context, url string, csr []byte, bundle bool) (der [][]byte, certURL string, err error) {
  319. if _, err := c.Discover(ctx); err != nil { // required by c.accountKID
  320. return nil, "", err
  321. }
  322. // RFC describes this as "finalize order" request.
  323. req := struct {
  324. CSR string `json:"csr"`
  325. }{
  326. CSR: base64.RawURLEncoding.EncodeToString(csr),
  327. }
  328. res, err := c.post(ctx, nil, url, req, wantStatus(http.StatusOK))
  329. if err != nil {
  330. return nil, "", err
  331. }
  332. defer res.Body.Close()
  333. o, err := responseOrder(res)
  334. if err != nil {
  335. return nil, "", err
  336. }
  337. // Wait for CA to issue the cert if they haven't.
  338. if o.Status != StatusValid {
  339. o, err = c.WaitOrder(ctx, o.URI)
  340. }
  341. if err != nil {
  342. return nil, "", err
  343. }
  344. // The only acceptable status post finalize and WaitOrder is "valid".
  345. if o.Status != StatusValid {
  346. return nil, "", &OrderError{OrderURL: o.URI, Status: o.Status}
  347. }
  348. crt, err := c.fetchCertRFC(ctx, o.CertURL, bundle)
  349. return crt, o.CertURL, err
  350. }
  351. // fetchCertRFC downloads issued certificate from the given URL.
  352. // It expects the CA to respond with PEM-encoded certificate chain.
  353. //
  354. // The URL argument is the CertURL field of Order.
  355. func (c *Client) fetchCertRFC(ctx context.Context, url string, bundle bool) ([][]byte, error) {
  356. res, err := c.postAsGet(ctx, url, wantStatus(http.StatusOK))
  357. if err != nil {
  358. return nil, err
  359. }
  360. defer res.Body.Close()
  361. // Get all the bytes up to a sane maximum.
  362. // Account very roughly for base64 overhead.
  363. const max = maxCertChainSize + maxCertChainSize/33
  364. b, err := io.ReadAll(io.LimitReader(res.Body, max+1))
  365. if err != nil {
  366. return nil, fmt.Errorf("acme: fetch cert response stream: %v", err)
  367. }
  368. if len(b) > max {
  369. return nil, errors.New("acme: certificate chain is too big")
  370. }
  371. // Decode PEM chain.
  372. var chain [][]byte
  373. for {
  374. var p *pem.Block
  375. p, b = pem.Decode(b)
  376. if p == nil {
  377. break
  378. }
  379. if p.Type != "CERTIFICATE" {
  380. return nil, fmt.Errorf("acme: invalid PEM cert type %q", p.Type)
  381. }
  382. chain = append(chain, p.Bytes)
  383. if !bundle {
  384. return chain, nil
  385. }
  386. if len(chain) > maxChainLen {
  387. return nil, errors.New("acme: certificate chain is too long")
  388. }
  389. }
  390. if len(chain) == 0 {
  391. return nil, errors.New("acme: certificate chain is empty")
  392. }
  393. return chain, nil
  394. }
  395. // sends a cert revocation request in either JWK form when key is non-nil or KID form otherwise.
  396. func (c *Client) revokeCertRFC(ctx context.Context, key crypto.Signer, cert []byte, reason CRLReasonCode) error {
  397. req := &struct {
  398. Cert string `json:"certificate"`
  399. Reason int `json:"reason"`
  400. }{
  401. Cert: base64.RawURLEncoding.EncodeToString(cert),
  402. Reason: int(reason),
  403. }
  404. res, err := c.post(ctx, key, c.dir.RevokeURL, req, wantStatus(http.StatusOK))
  405. if err != nil {
  406. if isAlreadyRevoked(err) {
  407. // Assume it is not an error to revoke an already revoked cert.
  408. return nil
  409. }
  410. return err
  411. }
  412. defer res.Body.Close()
  413. return nil
  414. }
  415. func isAlreadyRevoked(err error) bool {
  416. e, ok := err.(*Error)
  417. return ok && e.ProblemType == "urn:ietf:params:acme:error:alreadyRevoked"
  418. }
  419. // ListCertAlternates retrieves any alternate certificate chain URLs for the
  420. // given certificate chain URL. These alternate URLs can be passed to FetchCert
  421. // in order to retrieve the alternate certificate chains.
  422. //
  423. // If there are no alternate issuer certificate chains, a nil slice will be
  424. // returned.
  425. func (c *Client) ListCertAlternates(ctx context.Context, url string) ([]string, error) {
  426. if _, err := c.Discover(ctx); err != nil { // required by c.accountKID
  427. return nil, err
  428. }
  429. res, err := c.postAsGet(ctx, url, wantStatus(http.StatusOK))
  430. if err != nil {
  431. return nil, err
  432. }
  433. defer res.Body.Close()
  434. // We don't need the body but we need to discard it so we don't end up
  435. // preventing keep-alive
  436. if _, err := io.Copy(io.Discard, res.Body); err != nil {
  437. return nil, fmt.Errorf("acme: cert alternates response stream: %v", err)
  438. }
  439. alts := linkHeader(res.Header, "alternate")
  440. return alts, nil
  441. }