本站源代码
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1064 lines
34KB

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