Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.
 
 
 

1000 строки
30 KiB

  1. // Copyright 2015 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 provides an implementation of the
  5. // Automatic Certificate Management Environment (ACME) spec.
  6. // See https://tools.ietf.org/html/draft-ietf-acme-acme-02 for details.
  7. //
  8. // Most common scenarios will want to use autocert subdirectory instead,
  9. // which provides automatic access to certificates from Let's Encrypt
  10. // and any other ACME-based CA.
  11. //
  12. // This package is a work in progress and makes no API stability promises.
  13. package acme
  14. import (
  15. "bytes"
  16. "crypto"
  17. "crypto/ecdsa"
  18. "crypto/elliptic"
  19. "crypto/rand"
  20. "crypto/sha256"
  21. "crypto/tls"
  22. "crypto/x509"
  23. "encoding/base64"
  24. "encoding/hex"
  25. "encoding/json"
  26. "encoding/pem"
  27. "errors"
  28. "fmt"
  29. "io"
  30. "io/ioutil"
  31. "math/big"
  32. "net/http"
  33. "strconv"
  34. "strings"
  35. "sync"
  36. "time"
  37. "golang.org/x/net/context"
  38. "golang.org/x/net/context/ctxhttp"
  39. )
  40. // LetsEncryptURL is the Directory endpoint of Let's Encrypt CA.
  41. const LetsEncryptURL = "https://acme-v01.api.letsencrypt.org/directory"
  42. const (
  43. maxChainLen = 5 // max depth and breadth of a certificate chain
  44. maxCertSize = 1 << 20 // max size of a certificate, in bytes
  45. // Max number of collected nonces kept in memory.
  46. // Expect usual peak of 1 or 2.
  47. maxNonces = 100
  48. )
  49. // CertOption is an optional argument type for Client methods which manipulate
  50. // certificate data.
  51. type CertOption interface {
  52. privateCertOpt()
  53. }
  54. // WithKey creates an option holding a private/public key pair.
  55. // The private part signs a certificate, and the public part represents the signee.
  56. func WithKey(key crypto.Signer) CertOption {
  57. return &certOptKey{key}
  58. }
  59. type certOptKey struct {
  60. key crypto.Signer
  61. }
  62. func (*certOptKey) privateCertOpt() {}
  63. // WithTemplate creates an option for specifying a certificate template.
  64. // See x509.CreateCertificate for template usage details.
  65. //
  66. // In TLSSNIxChallengeCert methods, the template is also used as parent,
  67. // resulting in a self-signed certificate.
  68. // The DNSNames field of t is always overwritten for tls-sni challenge certs.
  69. func WithTemplate(t *x509.Certificate) CertOption {
  70. return (*certOptTemplate)(t)
  71. }
  72. type certOptTemplate x509.Certificate
  73. func (*certOptTemplate) privateCertOpt() {}
  74. // Client is an ACME client.
  75. // The only required field is Key. An example of creating a client with a new key
  76. // is as follows:
  77. //
  78. // key, err := rsa.GenerateKey(rand.Reader, 2048)
  79. // if err != nil {
  80. // log.Fatal(err)
  81. // }
  82. // client := &Client{Key: key}
  83. //
  84. type Client struct {
  85. // Key is the account key used to register with a CA and sign requests.
  86. // Key.Public() must return a *rsa.PublicKey or *ecdsa.PublicKey.
  87. Key crypto.Signer
  88. // HTTPClient optionally specifies an HTTP client to use
  89. // instead of http.DefaultClient.
  90. HTTPClient *http.Client
  91. // DirectoryURL points to the CA directory endpoint.
  92. // If empty, LetsEncryptURL is used.
  93. // Mutating this value after a successful call of Client's Discover method
  94. // will have no effect.
  95. DirectoryURL string
  96. dirMu sync.Mutex // guards writes to dir
  97. dir *Directory // cached result of Client's Discover method
  98. noncesMu sync.Mutex
  99. nonces map[string]struct{} // nonces collected from previous responses
  100. }
  101. // Discover performs ACME server discovery using c.DirectoryURL.
  102. //
  103. // It caches successful result. So, subsequent calls will not result in
  104. // a network round-trip. This also means mutating c.DirectoryURL after successful call
  105. // of this method will have no effect.
  106. func (c *Client) Discover(ctx context.Context) (Directory, error) {
  107. c.dirMu.Lock()
  108. defer c.dirMu.Unlock()
  109. if c.dir != nil {
  110. return *c.dir, nil
  111. }
  112. dirURL := c.DirectoryURL
  113. if dirURL == "" {
  114. dirURL = LetsEncryptURL
  115. }
  116. res, err := ctxhttp.Get(ctx, c.HTTPClient, dirURL)
  117. if err != nil {
  118. return Directory{}, err
  119. }
  120. defer res.Body.Close()
  121. c.addNonce(res.Header)
  122. if res.StatusCode != http.StatusOK {
  123. return Directory{}, responseError(res)
  124. }
  125. var v struct {
  126. Reg string `json:"new-reg"`
  127. Authz string `json:"new-authz"`
  128. Cert string `json:"new-cert"`
  129. Revoke string `json:"revoke-cert"`
  130. Meta struct {
  131. Terms string `json:"terms-of-service"`
  132. Website string `json:"website"`
  133. CAA []string `json:"caa-identities"`
  134. }
  135. }
  136. if json.NewDecoder(res.Body).Decode(&v); err != nil {
  137. return Directory{}, err
  138. }
  139. c.dir = &Directory{
  140. RegURL: v.Reg,
  141. AuthzURL: v.Authz,
  142. CertURL: v.Cert,
  143. RevokeURL: v.Revoke,
  144. Terms: v.Meta.Terms,
  145. Website: v.Meta.Website,
  146. CAA: v.Meta.CAA,
  147. }
  148. return *c.dir, nil
  149. }
  150. // CreateCert requests a new certificate using the Certificate Signing Request csr encoded in DER format.
  151. // The exp argument indicates the desired certificate validity duration. CA may issue a certificate
  152. // with a different duration.
  153. // If the bundle argument is true, the returned value will also contain the CA (issuer) certificate chain.
  154. //
  155. // In the case where CA server does not provide the issued certificate in the response,
  156. // CreateCert will poll certURL using c.FetchCert, which will result in additional round-trips.
  157. // In such scenario the caller can cancel the polling with ctx.
  158. //
  159. // CreateCert returns an error if the CA's response or chain was unreasonably large.
  160. // Callers are encouraged to parse the returned value to ensure the certificate is valid and has the expected features.
  161. func (c *Client) CreateCert(ctx context.Context, csr []byte, exp time.Duration, bundle bool) (der [][]byte, certURL string, err error) {
  162. if _, err := c.Discover(ctx); err != nil {
  163. return nil, "", err
  164. }
  165. req := struct {
  166. Resource string `json:"resource"`
  167. CSR string `json:"csr"`
  168. NotBefore string `json:"notBefore,omitempty"`
  169. NotAfter string `json:"notAfter,omitempty"`
  170. }{
  171. Resource: "new-cert",
  172. CSR: base64.RawURLEncoding.EncodeToString(csr),
  173. }
  174. now := timeNow()
  175. req.NotBefore = now.Format(time.RFC3339)
  176. if exp > 0 {
  177. req.NotAfter = now.Add(exp).Format(time.RFC3339)
  178. }
  179. res, err := c.postJWS(ctx, c.Key, c.dir.CertURL, req)
  180. if err != nil {
  181. return nil, "", err
  182. }
  183. defer res.Body.Close()
  184. if res.StatusCode != http.StatusCreated {
  185. return nil, "", responseError(res)
  186. }
  187. curl := res.Header.Get("location") // cert permanent URL
  188. if res.ContentLength == 0 {
  189. // no cert in the body; poll until we get it
  190. cert, err := c.FetchCert(ctx, curl, bundle)
  191. return cert, curl, err
  192. }
  193. // slurp issued cert and CA chain, if requested
  194. cert, err := responseCert(ctx, c.HTTPClient, res, bundle)
  195. return cert, curl, err
  196. }
  197. // FetchCert retrieves already issued certificate from the given url, in DER format.
  198. // It retries the request until the certificate is successfully retrieved,
  199. // context is cancelled by the caller or an error response is received.
  200. //
  201. // The returned value will also contain the CA (issuer) certificate if the bundle argument is true.
  202. //
  203. // FetchCert returns an error if the CA's response or chain was unreasonably large.
  204. // Callers are encouraged to parse the returned value to ensure the certificate is valid
  205. // and has expected features.
  206. func (c *Client) FetchCert(ctx context.Context, url string, bundle bool) ([][]byte, error) {
  207. for {
  208. res, err := ctxhttp.Get(ctx, c.HTTPClient, url)
  209. if err != nil {
  210. return nil, err
  211. }
  212. defer res.Body.Close()
  213. if res.StatusCode == http.StatusOK {
  214. return responseCert(ctx, c.HTTPClient, res, bundle)
  215. }
  216. if res.StatusCode > 299 {
  217. return nil, responseError(res)
  218. }
  219. d := retryAfter(res.Header.Get("retry-after"), 3*time.Second)
  220. select {
  221. case <-time.After(d):
  222. // retry
  223. case <-ctx.Done():
  224. return nil, ctx.Err()
  225. }
  226. }
  227. }
  228. // RevokeCert revokes a previously issued certificate cert, provided in DER format.
  229. //
  230. // The key argument, used to sign the request, must be authorized
  231. // to revoke the certificate. It's up to the CA to decide which keys are authorized.
  232. // For instance, the key pair of the certificate may be authorized.
  233. // If the key is nil, c.Key is used instead.
  234. func (c *Client) RevokeCert(ctx context.Context, key crypto.Signer, cert []byte, reason CRLReasonCode) error {
  235. if _, err := c.Discover(ctx); err != nil {
  236. return err
  237. }
  238. body := &struct {
  239. Resource string `json:"resource"`
  240. Cert string `json:"certificate"`
  241. Reason int `json:"reason"`
  242. }{
  243. Resource: "revoke-cert",
  244. Cert: base64.RawURLEncoding.EncodeToString(cert),
  245. Reason: int(reason),
  246. }
  247. if key == nil {
  248. key = c.Key
  249. }
  250. res, err := c.postJWS(ctx, key, c.dir.RevokeURL, body)
  251. if err != nil {
  252. return err
  253. }
  254. defer res.Body.Close()
  255. if res.StatusCode != http.StatusOK {
  256. return responseError(res)
  257. }
  258. return nil
  259. }
  260. // AcceptTOS always returns true to indicate the acceptance of a CA's Terms of Service
  261. // during account registration. See Register method of Client for more details.
  262. func AcceptTOS(tosURL string) bool { return true }
  263. // Register creates a new account registration by following the "new-reg" flow.
  264. // It returns registered account. The a argument is not modified.
  265. //
  266. // The registration may require the caller to agree to the CA's Terms of Service (TOS).
  267. // If so, and the account has not indicated the acceptance of the terms (see Account for details),
  268. // Register calls prompt with a TOS URL provided by the CA. Prompt should report
  269. // whether the caller agrees to the terms. To always accept the terms, the caller can use AcceptTOS.
  270. func (c *Client) Register(ctx context.Context, a *Account, prompt func(tosURL string) bool) (*Account, error) {
  271. if _, err := c.Discover(ctx); err != nil {
  272. return nil, err
  273. }
  274. var err error
  275. if a, err = c.doReg(ctx, c.dir.RegURL, "new-reg", a); err != nil {
  276. return nil, err
  277. }
  278. var accept bool
  279. if a.CurrentTerms != "" && a.CurrentTerms != a.AgreedTerms {
  280. accept = prompt(a.CurrentTerms)
  281. }
  282. if accept {
  283. a.AgreedTerms = a.CurrentTerms
  284. a, err = c.UpdateReg(ctx, a)
  285. }
  286. return a, err
  287. }
  288. // GetReg retrieves an existing registration.
  289. // The url argument is an Account URI.
  290. func (c *Client) GetReg(ctx context.Context, url string) (*Account, error) {
  291. a, err := c.doReg(ctx, url, "reg", nil)
  292. if err != nil {
  293. return nil, err
  294. }
  295. a.URI = url
  296. return a, nil
  297. }
  298. // UpdateReg updates an existing registration.
  299. // It returns an updated account copy. The provided account is not modified.
  300. func (c *Client) UpdateReg(ctx context.Context, a *Account) (*Account, error) {
  301. uri := a.URI
  302. a, err := c.doReg(ctx, uri, "reg", a)
  303. if err != nil {
  304. return nil, err
  305. }
  306. a.URI = uri
  307. return a, nil
  308. }
  309. // Authorize performs the initial step in an authorization flow.
  310. // The caller will then need to choose from and perform a set of returned
  311. // challenges using c.Accept in order to successfully complete authorization.
  312. //
  313. // If an authorization has been previously granted, the CA may return
  314. // a valid authorization (Authorization.Status is StatusValid). If so, the caller
  315. // need not fulfill any challenge and can proceed to requesting a certificate.
  316. func (c *Client) Authorize(ctx context.Context, domain string) (*Authorization, error) {
  317. if _, err := c.Discover(ctx); err != nil {
  318. return nil, err
  319. }
  320. type authzID struct {
  321. Type string `json:"type"`
  322. Value string `json:"value"`
  323. }
  324. req := struct {
  325. Resource string `json:"resource"`
  326. Identifier authzID `json:"identifier"`
  327. }{
  328. Resource: "new-authz",
  329. Identifier: authzID{Type: "dns", Value: domain},
  330. }
  331. res, err := c.postJWS(ctx, c.Key, c.dir.AuthzURL, req)
  332. if err != nil {
  333. return nil, err
  334. }
  335. defer res.Body.Close()
  336. if res.StatusCode != http.StatusCreated {
  337. return nil, responseError(res)
  338. }
  339. var v wireAuthz
  340. if err := json.NewDecoder(res.Body).Decode(&v); err != nil {
  341. return nil, fmt.Errorf("acme: invalid response: %v", err)
  342. }
  343. if v.Status != StatusPending && v.Status != StatusValid {
  344. return nil, fmt.Errorf("acme: unexpected status: %s", v.Status)
  345. }
  346. return v.authorization(res.Header.Get("Location")), nil
  347. }
  348. // GetAuthorization retrieves an authorization identified by the given URL.
  349. //
  350. // If a caller needs to poll an authorization until its status is final,
  351. // see the WaitAuthorization method.
  352. func (c *Client) GetAuthorization(ctx context.Context, url string) (*Authorization, error) {
  353. res, err := ctxhttp.Get(ctx, c.HTTPClient, url)
  354. if err != nil {
  355. return nil, err
  356. }
  357. defer res.Body.Close()
  358. if res.StatusCode != http.StatusOK && res.StatusCode != http.StatusAccepted {
  359. return nil, responseError(res)
  360. }
  361. var v wireAuthz
  362. if err := json.NewDecoder(res.Body).Decode(&v); err != nil {
  363. return nil, fmt.Errorf("acme: invalid response: %v", err)
  364. }
  365. return v.authorization(url), nil
  366. }
  367. // RevokeAuthorization relinquishes an existing authorization identified
  368. // by the given URL.
  369. // The url argument is an Authorization.URI value.
  370. //
  371. // If successful, the caller will be required to obtain a new authorization
  372. // using the Authorize method before being able to request a new certificate
  373. // for the domain associated with the authorization.
  374. //
  375. // It does not revoke existing certificates.
  376. func (c *Client) RevokeAuthorization(ctx context.Context, url string) error {
  377. req := struct {
  378. Resource string `json:"resource"`
  379. Status string `json:"status"`
  380. Delete bool `json:"delete"`
  381. }{
  382. Resource: "authz",
  383. Status: "deactivated",
  384. Delete: true,
  385. }
  386. res, err := c.postJWS(ctx, c.Key, url, req)
  387. if err != nil {
  388. return err
  389. }
  390. defer res.Body.Close()
  391. if res.StatusCode != http.StatusOK {
  392. return responseError(res)
  393. }
  394. return nil
  395. }
  396. // WaitAuthorization polls an authorization at the given URL
  397. // until it is in one of the final states, StatusValid or StatusInvalid,
  398. // or the context is done.
  399. //
  400. // It returns a non-nil Authorization only if its Status is StatusValid.
  401. // In all other cases WaitAuthorization returns an error.
  402. // If the Status is StatusInvalid, the returned error is ErrAuthorizationFailed.
  403. func (c *Client) WaitAuthorization(ctx context.Context, url string) (*Authorization, error) {
  404. var count int
  405. sleep := func(v string, inc int) error {
  406. count += inc
  407. d := backoff(count, 10*time.Second)
  408. d = retryAfter(v, d)
  409. wakeup := time.NewTimer(d)
  410. defer wakeup.Stop()
  411. select {
  412. case <-ctx.Done():
  413. return ctx.Err()
  414. case <-wakeup.C:
  415. return nil
  416. }
  417. }
  418. for {
  419. res, err := ctxhttp.Get(ctx, c.HTTPClient, url)
  420. if err != nil {
  421. return nil, err
  422. }
  423. retry := res.Header.Get("retry-after")
  424. if res.StatusCode != http.StatusOK && res.StatusCode != http.StatusAccepted {
  425. res.Body.Close()
  426. if err := sleep(retry, 1); err != nil {
  427. return nil, err
  428. }
  429. continue
  430. }
  431. var raw wireAuthz
  432. err = json.NewDecoder(res.Body).Decode(&raw)
  433. res.Body.Close()
  434. if err != nil {
  435. if err := sleep(retry, 0); err != nil {
  436. return nil, err
  437. }
  438. continue
  439. }
  440. if raw.Status == StatusValid {
  441. return raw.authorization(url), nil
  442. }
  443. if raw.Status == StatusInvalid {
  444. return nil, ErrAuthorizationFailed
  445. }
  446. if err := sleep(retry, 0); err != nil {
  447. return nil, err
  448. }
  449. }
  450. }
  451. // GetChallenge retrieves the current status of an challenge.
  452. //
  453. // A client typically polls a challenge status using this method.
  454. func (c *Client) GetChallenge(ctx context.Context, url string) (*Challenge, error) {
  455. res, err := ctxhttp.Get(ctx, c.HTTPClient, url)
  456. if err != nil {
  457. return nil, err
  458. }
  459. defer res.Body.Close()
  460. if res.StatusCode != http.StatusOK && res.StatusCode != http.StatusAccepted {
  461. return nil, responseError(res)
  462. }
  463. v := wireChallenge{URI: url}
  464. if err := json.NewDecoder(res.Body).Decode(&v); err != nil {
  465. return nil, fmt.Errorf("acme: invalid response: %v", err)
  466. }
  467. return v.challenge(), nil
  468. }
  469. // Accept informs the server that the client accepts one of its challenges
  470. // previously obtained with c.Authorize.
  471. //
  472. // The server will then perform the validation asynchronously.
  473. func (c *Client) Accept(ctx context.Context, chal *Challenge) (*Challenge, error) {
  474. auth, err := keyAuth(c.Key.Public(), chal.Token)
  475. if err != nil {
  476. return nil, err
  477. }
  478. req := struct {
  479. Resource string `json:"resource"`
  480. Type string `json:"type"`
  481. Auth string `json:"keyAuthorization"`
  482. }{
  483. Resource: "challenge",
  484. Type: chal.Type,
  485. Auth: auth,
  486. }
  487. res, err := c.postJWS(ctx, c.Key, chal.URI, req)
  488. if err != nil {
  489. return nil, err
  490. }
  491. defer res.Body.Close()
  492. // Note: the protocol specifies 200 as the expected response code, but
  493. // letsencrypt seems to be returning 202.
  494. if res.StatusCode != http.StatusOK && res.StatusCode != http.StatusAccepted {
  495. return nil, responseError(res)
  496. }
  497. var v wireChallenge
  498. if err := json.NewDecoder(res.Body).Decode(&v); err != nil {
  499. return nil, fmt.Errorf("acme: invalid response: %v", err)
  500. }
  501. return v.challenge(), nil
  502. }
  503. // DNS01ChallengeRecord returns a DNS record value for a dns-01 challenge response.
  504. // A TXT record containing the returned value must be provisioned under
  505. // "_acme-challenge" name of the domain being validated.
  506. //
  507. // The token argument is a Challenge.Token value.
  508. func (c *Client) DNS01ChallengeRecord(token string) (string, error) {
  509. ka, err := keyAuth(c.Key.Public(), token)
  510. if err != nil {
  511. return "", err
  512. }
  513. b := sha256.Sum256([]byte(ka))
  514. return base64.RawURLEncoding.EncodeToString(b[:]), nil
  515. }
  516. // HTTP01ChallengeResponse returns the response for an http-01 challenge.
  517. // Servers should respond with the value to HTTP requests at the URL path
  518. // provided by HTTP01ChallengePath to validate the challenge and prove control
  519. // over a domain name.
  520. //
  521. // The token argument is a Challenge.Token value.
  522. func (c *Client) HTTP01ChallengeResponse(token string) (string, error) {
  523. return keyAuth(c.Key.Public(), token)
  524. }
  525. // HTTP01ChallengePath returns the URL path at which the response for an http-01 challenge
  526. // should be provided by the servers.
  527. // The response value can be obtained with HTTP01ChallengeResponse.
  528. //
  529. // The token argument is a Challenge.Token value.
  530. func (c *Client) HTTP01ChallengePath(token string) string {
  531. return "/.well-known/acme-challenge/" + token
  532. }
  533. // TLSSNI01ChallengeCert creates a certificate for TLS-SNI-01 challenge response.
  534. // Servers can present the certificate to validate the challenge and prove control
  535. // over a domain name.
  536. //
  537. // The implementation is incomplete in that the returned value is a single certificate,
  538. // computed only for Z0 of the key authorization. ACME CAs are expected to update
  539. // their implementations to use the newer version, TLS-SNI-02.
  540. // For more details on TLS-SNI-01 see https://tools.ietf.org/html/draft-ietf-acme-acme-01#section-7.3.
  541. //
  542. // The token argument is a Challenge.Token value.
  543. // If a WithKey option is provided, its private part signs the returned cert,
  544. // and the public part is used to specify the signee.
  545. // If no WithKey option is provided, a new ECDSA key is generated using P-256 curve.
  546. //
  547. // The returned certificate is valid for the next 24 hours and must be presented only when
  548. // the server name of the client hello matches exactly the returned name value.
  549. func (c *Client) TLSSNI01ChallengeCert(token string, opt ...CertOption) (cert tls.Certificate, name string, err error) {
  550. ka, err := keyAuth(c.Key.Public(), token)
  551. if err != nil {
  552. return tls.Certificate{}, "", err
  553. }
  554. b := sha256.Sum256([]byte(ka))
  555. h := hex.EncodeToString(b[:])
  556. name = fmt.Sprintf("%s.%s.acme.invalid", h[:32], h[32:])
  557. cert, err = tlsChallengeCert([]string{name}, opt)
  558. if err != nil {
  559. return tls.Certificate{}, "", err
  560. }
  561. return cert, name, nil
  562. }
  563. // TLSSNI02ChallengeCert creates a certificate for TLS-SNI-02 challenge response.
  564. // Servers can present the certificate to validate the challenge and prove control
  565. // over a domain name. For more details on TLS-SNI-02 see
  566. // https://tools.ietf.org/html/draft-ietf-acme-acme-03#section-7.3.
  567. //
  568. // The token argument is a Challenge.Token value.
  569. // If a WithKey option is provided, its private part signs the returned cert,
  570. // and the public part is used to specify the signee.
  571. // If no WithKey option is provided, a new ECDSA key is generated using P-256 curve.
  572. //
  573. // The returned certificate is valid for the next 24 hours and must be presented only when
  574. // the server name in the client hello matches exactly the returned name value.
  575. func (c *Client) TLSSNI02ChallengeCert(token string, opt ...CertOption) (cert tls.Certificate, name string, err error) {
  576. b := sha256.Sum256([]byte(token))
  577. h := hex.EncodeToString(b[:])
  578. sanA := fmt.Sprintf("%s.%s.token.acme.invalid", h[:32], h[32:])
  579. ka, err := keyAuth(c.Key.Public(), token)
  580. if err != nil {
  581. return tls.Certificate{}, "", err
  582. }
  583. b = sha256.Sum256([]byte(ka))
  584. h = hex.EncodeToString(b[:])
  585. sanB := fmt.Sprintf("%s.%s.ka.acme.invalid", h[:32], h[32:])
  586. cert, err = tlsChallengeCert([]string{sanA, sanB}, opt)
  587. if err != nil {
  588. return tls.Certificate{}, "", err
  589. }
  590. return cert, sanA, nil
  591. }
  592. // doReg sends all types of registration requests.
  593. // The type of request is identified by typ argument, which is a "resource"
  594. // in the ACME spec terms.
  595. //
  596. // A non-nil acct argument indicates whether the intention is to mutate data
  597. // of the Account. Only Contact and Agreement of its fields are used
  598. // in such cases.
  599. func (c *Client) doReg(ctx context.Context, url string, typ string, acct *Account) (*Account, error) {
  600. req := struct {
  601. Resource string `json:"resource"`
  602. Contact []string `json:"contact,omitempty"`
  603. Agreement string `json:"agreement,omitempty"`
  604. }{
  605. Resource: typ,
  606. }
  607. if acct != nil {
  608. req.Contact = acct.Contact
  609. req.Agreement = acct.AgreedTerms
  610. }
  611. res, err := c.postJWS(ctx, c.Key, url, req)
  612. if err != nil {
  613. return nil, err
  614. }
  615. defer res.Body.Close()
  616. if res.StatusCode < 200 || res.StatusCode > 299 {
  617. return nil, responseError(res)
  618. }
  619. var v struct {
  620. Contact []string
  621. Agreement string
  622. Authorizations string
  623. Certificates string
  624. }
  625. if err := json.NewDecoder(res.Body).Decode(&v); err != nil {
  626. return nil, fmt.Errorf("acme: invalid response: %v", err)
  627. }
  628. var tos string
  629. if v := linkHeader(res.Header, "terms-of-service"); len(v) > 0 {
  630. tos = v[0]
  631. }
  632. var authz string
  633. if v := linkHeader(res.Header, "next"); len(v) > 0 {
  634. authz = v[0]
  635. }
  636. return &Account{
  637. URI: res.Header.Get("Location"),
  638. Contact: v.Contact,
  639. AgreedTerms: v.Agreement,
  640. CurrentTerms: tos,
  641. Authz: authz,
  642. Authorizations: v.Authorizations,
  643. Certificates: v.Certificates,
  644. }, nil
  645. }
  646. // postJWS signs the body with the given key and POSTs it to the provided url.
  647. // The body argument must be JSON-serializable.
  648. func (c *Client) postJWS(ctx context.Context, key crypto.Signer, url string, body interface{}) (*http.Response, error) {
  649. nonce, err := c.popNonce(ctx, url)
  650. if err != nil {
  651. return nil, err
  652. }
  653. b, err := jwsEncodeJSON(body, key, nonce)
  654. if err != nil {
  655. return nil, err
  656. }
  657. res, err := ctxhttp.Post(ctx, c.HTTPClient, url, "application/jose+json", bytes.NewReader(b))
  658. if err != nil {
  659. return nil, err
  660. }
  661. c.addNonce(res.Header)
  662. return res, nil
  663. }
  664. // popNonce returns a nonce value previously stored with c.addNonce
  665. // or fetches a fresh one from the given URL.
  666. func (c *Client) popNonce(ctx context.Context, url string) (string, error) {
  667. c.noncesMu.Lock()
  668. defer c.noncesMu.Unlock()
  669. if len(c.nonces) == 0 {
  670. return fetchNonce(ctx, c.HTTPClient, url)
  671. }
  672. var nonce string
  673. for nonce = range c.nonces {
  674. delete(c.nonces, nonce)
  675. break
  676. }
  677. return nonce, nil
  678. }
  679. // addNonce stores a nonce value found in h (if any) for future use.
  680. func (c *Client) addNonce(h http.Header) {
  681. v := nonceFromHeader(h)
  682. if v == "" {
  683. return
  684. }
  685. c.noncesMu.Lock()
  686. defer c.noncesMu.Unlock()
  687. if len(c.nonces) >= maxNonces {
  688. return
  689. }
  690. if c.nonces == nil {
  691. c.nonces = make(map[string]struct{})
  692. }
  693. c.nonces[v] = struct{}{}
  694. }
  695. func fetchNonce(ctx context.Context, client *http.Client, url string) (string, error) {
  696. resp, err := ctxhttp.Head(ctx, client, url)
  697. if err != nil {
  698. return "", err
  699. }
  700. defer resp.Body.Close()
  701. nonce := nonceFromHeader(resp.Header)
  702. if nonce == "" {
  703. if resp.StatusCode > 299 {
  704. return "", responseError(resp)
  705. }
  706. return "", errors.New("acme: nonce not found")
  707. }
  708. return nonce, nil
  709. }
  710. func nonceFromHeader(h http.Header) string {
  711. return h.Get("Replay-Nonce")
  712. }
  713. func responseCert(ctx context.Context, client *http.Client, res *http.Response, bundle bool) ([][]byte, error) {
  714. b, err := ioutil.ReadAll(io.LimitReader(res.Body, maxCertSize+1))
  715. if err != nil {
  716. return nil, fmt.Errorf("acme: response stream: %v", err)
  717. }
  718. if len(b) > maxCertSize {
  719. return nil, errors.New("acme: certificate is too big")
  720. }
  721. cert := [][]byte{b}
  722. if !bundle {
  723. return cert, nil
  724. }
  725. // Append CA chain cert(s).
  726. // At least one is required according to the spec:
  727. // https://tools.ietf.org/html/draft-ietf-acme-acme-03#section-6.3.1
  728. up := linkHeader(res.Header, "up")
  729. if len(up) == 0 {
  730. return nil, errors.New("acme: rel=up link not found")
  731. }
  732. if len(up) > maxChainLen {
  733. return nil, errors.New("acme: rel=up link is too large")
  734. }
  735. for _, url := range up {
  736. cc, err := chainCert(ctx, client, url, 0)
  737. if err != nil {
  738. return nil, err
  739. }
  740. cert = append(cert, cc...)
  741. }
  742. return cert, nil
  743. }
  744. // responseError creates an error of Error type from resp.
  745. func responseError(resp *http.Response) error {
  746. // don't care if ReadAll returns an error:
  747. // json.Unmarshal will fail in that case anyway
  748. b, _ := ioutil.ReadAll(resp.Body)
  749. e := struct {
  750. Status int
  751. Type string
  752. Detail string
  753. }{
  754. Status: resp.StatusCode,
  755. }
  756. if err := json.Unmarshal(b, &e); err != nil {
  757. // this is not a regular error response:
  758. // populate detail with anything we received,
  759. // e.Status will already contain HTTP response code value
  760. e.Detail = string(b)
  761. if e.Detail == "" {
  762. e.Detail = resp.Status
  763. }
  764. }
  765. return &Error{
  766. StatusCode: e.Status,
  767. ProblemType: e.Type,
  768. Detail: e.Detail,
  769. Header: resp.Header,
  770. }
  771. }
  772. // chainCert fetches CA certificate chain recursively by following "up" links.
  773. // Each recursive call increments the depth by 1, resulting in an error
  774. // if the recursion level reaches maxChainLen.
  775. //
  776. // First chainCert call starts with depth of 0.
  777. func chainCert(ctx context.Context, client *http.Client, url string, depth int) ([][]byte, error) {
  778. if depth >= maxChainLen {
  779. return nil, errors.New("acme: certificate chain is too deep")
  780. }
  781. res, err := ctxhttp.Get(ctx, client, url)
  782. if err != nil {
  783. return nil, err
  784. }
  785. defer res.Body.Close()
  786. if res.StatusCode != http.StatusOK {
  787. return nil, responseError(res)
  788. }
  789. b, err := ioutil.ReadAll(io.LimitReader(res.Body, maxCertSize+1))
  790. if err != nil {
  791. return nil, err
  792. }
  793. if len(b) > maxCertSize {
  794. return nil, errors.New("acme: certificate is too big")
  795. }
  796. chain := [][]byte{b}
  797. uplink := linkHeader(res.Header, "up")
  798. if len(uplink) > maxChainLen {
  799. return nil, errors.New("acme: certificate chain is too large")
  800. }
  801. for _, up := range uplink {
  802. cc, err := chainCert(ctx, client, up, depth+1)
  803. if err != nil {
  804. return nil, err
  805. }
  806. chain = append(chain, cc...)
  807. }
  808. return chain, nil
  809. }
  810. // linkHeader returns URI-Reference values of all Link headers
  811. // with relation-type rel.
  812. // See https://tools.ietf.org/html/rfc5988#section-5 for details.
  813. func linkHeader(h http.Header, rel string) []string {
  814. var links []string
  815. for _, v := range h["Link"] {
  816. parts := strings.Split(v, ";")
  817. for _, p := range parts {
  818. p = strings.TrimSpace(p)
  819. if !strings.HasPrefix(p, "rel=") {
  820. continue
  821. }
  822. if v := strings.Trim(p[4:], `"`); v == rel {
  823. links = append(links, strings.Trim(parts[0], "<>"))
  824. }
  825. }
  826. }
  827. return links
  828. }
  829. // retryAfter parses a Retry-After HTTP header value,
  830. // trying to convert v into an int (seconds) or use http.ParseTime otherwise.
  831. // It returns d if v cannot be parsed.
  832. func retryAfter(v string, d time.Duration) time.Duration {
  833. if i, err := strconv.Atoi(v); err == nil {
  834. return time.Duration(i) * time.Second
  835. }
  836. t, err := http.ParseTime(v)
  837. if err != nil {
  838. return d
  839. }
  840. return t.Sub(timeNow())
  841. }
  842. // backoff computes a duration after which an n+1 retry iteration should occur
  843. // using truncated exponential backoff algorithm.
  844. //
  845. // The n argument is always bounded between 0 and 30.
  846. // The max argument defines upper bound for the returned value.
  847. func backoff(n int, max time.Duration) time.Duration {
  848. if n < 0 {
  849. n = 0
  850. }
  851. if n > 30 {
  852. n = 30
  853. }
  854. var d time.Duration
  855. if x, err := rand.Int(rand.Reader, big.NewInt(1000)); err == nil {
  856. d = time.Duration(x.Int64()) * time.Millisecond
  857. }
  858. d += time.Duration(1<<uint(n)) * time.Second
  859. if d > max {
  860. return max
  861. }
  862. return d
  863. }
  864. // keyAuth generates a key authorization string for a given token.
  865. func keyAuth(pub crypto.PublicKey, token string) (string, error) {
  866. th, err := JWKThumbprint(pub)
  867. if err != nil {
  868. return "", err
  869. }
  870. return fmt.Sprintf("%s.%s", token, th), nil
  871. }
  872. // tlsChallengeCert creates a temporary certificate for TLS-SNI challenges
  873. // with the given SANs and auto-generated public/private key pair.
  874. // To create a cert with a custom key pair, specify WithKey option.
  875. func tlsChallengeCert(san []string, opt []CertOption) (tls.Certificate, error) {
  876. var (
  877. key crypto.Signer
  878. tmpl *x509.Certificate
  879. )
  880. for _, o := range opt {
  881. switch o := o.(type) {
  882. case *certOptKey:
  883. if key != nil {
  884. return tls.Certificate{}, errors.New("acme: duplicate key option")
  885. }
  886. key = o.key
  887. case *certOptTemplate:
  888. var t = *(*x509.Certificate)(o) // shallow copy is ok
  889. tmpl = &t
  890. default:
  891. // package's fault, if we let this happen:
  892. panic(fmt.Sprintf("unsupported option type %T", o))
  893. }
  894. }
  895. if key == nil {
  896. var err error
  897. if key, err = ecdsa.GenerateKey(elliptic.P256(), rand.Reader); err != nil {
  898. return tls.Certificate{}, err
  899. }
  900. }
  901. if tmpl == nil {
  902. tmpl = &x509.Certificate{
  903. SerialNumber: big.NewInt(1),
  904. NotBefore: time.Now(),
  905. NotAfter: time.Now().Add(24 * time.Hour),
  906. BasicConstraintsValid: true,
  907. KeyUsage: x509.KeyUsageKeyEncipherment,
  908. }
  909. }
  910. tmpl.DNSNames = san
  911. der, err := x509.CreateCertificate(rand.Reader, tmpl, tmpl, key.Public(), key)
  912. if err != nil {
  913. return tls.Certificate{}, err
  914. }
  915. return tls.Certificate{
  916. Certificate: [][]byte{der},
  917. PrivateKey: key,
  918. }, nil
  919. }
  920. // encodePEM returns b encoded as PEM with block of type typ.
  921. func encodePEM(typ string, b []byte) []byte {
  922. pb := &pem.Block{Type: typ, Bytes: b}
  923. return pem.EncodeToMemory(pb)
  924. }
  925. // timeNow is useful for testing for fixed current time.
  926. var timeNow = time.Now