rfc8555.go 14 KB

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