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 5 // Package acme provides an implementation of the
6 // Automatic Certificate Management Environment (ACME) spec,
7 // most famously used by Let's Encrypt.
8 //
9 // The initial implementation of this package was based on an early version
10 // of the spec. The current implementation supports only the modern
11 // RFC 8555 but some of the old API surface remains for compatibility.
12 // While code using the old API will still compile, it will return an error.
13 // Note the deprecation comments to update your code.
14 //
15 // See https://tools.ietf.org/html/rfc8555 for the spec.
16 //
17 // Most common scenarios will want to use autocert subdirectory instead,
18 // which provides automatic access to certificates from Let's Encrypt
19 // and any other ACME-based CA.
20 package acme
21 22 import (
23 "context"
24 "crypto"
25 "crypto/ecdsa"
26 "crypto/elliptic"
27 "crypto/rand"
28 "crypto/sha256"
29 "crypto/tls"
30 "crypto/x509"
31 "crypto/x509/pkix"
32 "encoding/asn1"
33 "encoding/base64"
34 "encoding/json"
35 "errors"
36 "fmt"
37 "math/big"
38 "net"
39 "net/http"
40 "strings"
41 "sync"
42 "time"
43 )
44 45 const (
46 // LetsEncryptURL is the Directory endpoint of Let's Encrypt CA.
47 LetsEncryptURL = "https://acme-v02.api.letsencrypt.org/directory"
48 49 // ALPNProto is the ALPN protocol name used by a CA server when validating
50 // tls-alpn-01 challenges.
51 //
52 // Package users must ensure their servers can negotiate the ACME ALPN in
53 // order for tls-alpn-01 challenge verifications to succeed.
54 // See the crypto/tls package's Config.NextProtos field.
55 ALPNProto = "acme-tls/1"
56 )
57 58 // idPeACMEIdentifier is the OID for the ACME extension for the TLS-ALPN challenge.
59 // https://tools.ietf.org/html/draft-ietf-acme-tls-alpn-05#section-5.1
60 var idPeACMEIdentifier = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 1, 31}
61 62 const (
63 maxChainLen = 5 // max depth and breadth of a certificate chain
64 maxCertSize = 1 << 20 // max size of a certificate, in DER bytes
65 // Used for decoding certs from application/pem-certificate-chain response,
66 // the default when in RFC mode.
67 maxCertChainSize = maxCertSize * maxChainLen
68 69 // Max number of collected nonces kept in memory.
70 // Expect usual peak of 1 or 2.
71 maxNonces = 100
72 )
73 74 // Client is an ACME client.
75 //
76 // The only required field is Key. An example of creating a client with a new key
77 // is as follows:
78 //
79 // key, err := rsa.GenerateKey(rand.Reader, 2048)
80 // if err != nil {
81 // log.Fatal(err)
82 // }
83 // client := &Client{Key: key}
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 //
88 // The following algorithms are supported:
89 // RS256, ES256, ES384 and ES512.
90 // See RFC 7518 for more details about the algorithms.
91 Key crypto.Signer
92 93 // HTTPClient optionally specifies an HTTP client to use
94 // instead of http.DefaultClient.
95 HTTPClient *http.Client
96 97 // DirectoryURL points to the CA directory endpoint.
98 // If empty, LetsEncryptURL is used.
99 // Mutating this value after a successful call of Client's Discover method
100 // will have no effect.
101 DirectoryURL string
102 103 // RetryBackoff computes the duration after which the nth retry of a failed request
104 // should occur. The value of n for the first call on failure is 1.
105 // The values of r and resp are the request and response of the last failed attempt.
106 // If the returned value is negative or zero, no more retries are done and an error
107 // is returned to the caller of the original method.
108 //
109 // Requests which result in a 4xx client error are not retried,
110 // except for 400 Bad Request due to "bad nonce" errors and 429 Too Many Requests.
111 //
112 // If RetryBackoff is nil, a truncated exponential backoff algorithm
113 // with the ceiling of 10 seconds is used, where each subsequent retry n
114 // is done after either ("Retry-After" + jitter) or (2^n seconds + jitter),
115 // preferring the former if "Retry-After" header is found in the resp.
116 // The jitter is a random value up to 1 second.
117 RetryBackoff func(n int, r *http.Request, resp *http.Response) time.Duration
118 119 // UserAgent is prepended to the User-Agent header sent to the ACME server,
120 // which by default is this package's name and version.
121 //
122 // Reusable libraries and tools in particular should set this value to be
123 // identifiable by the server, in case they are causing issues.
124 UserAgent string
125 126 cacheMu sync.Mutex
127 dir *Directory // cached result of Client's Discover method
128 // KID is the key identifier provided by the CA. If not provided it will be
129 // retrieved from the CA by making a call to the registration endpoint.
130 KID KeyID
131 132 noncesMu sync.Mutex
133 nonces map[string]struct{} // nonces collected from previous responses
134 }
135 136 // accountKID returns a key ID associated with c.Key, the account identity
137 // provided by the CA during RFC based registration.
138 // It assumes c.Discover has already been called.
139 //
140 // accountKID requires at most one network roundtrip.
141 // It caches only successful result.
142 //
143 // When in pre-RFC mode or when c.getRegRFC responds with an error, accountKID
144 // returns noKeyID.
145 func (c *Client) accountKID(ctx context.Context) KeyID {
146 c.cacheMu.Lock()
147 defer c.cacheMu.Unlock()
148 if c.KID != noKeyID {
149 return c.KID
150 }
151 a, err := c.getRegRFC(ctx)
152 if err != nil {
153 return noKeyID
154 }
155 c.KID = KeyID(a.URI)
156 return c.KID
157 }
158 159 var errPreRFC = errors.New("acme: server does not support the RFC 8555 version of ACME")
160 161 // Discover performs ACME server discovery using c.DirectoryURL.
162 //
163 // It caches successful result. So, subsequent calls will not result in
164 // a network round-trip. This also means mutating c.DirectoryURL after successful call
165 // of this method will have no effect.
166 func (c *Client) Discover(ctx context.Context) (Directory, error) {
167 c.cacheMu.Lock()
168 defer c.cacheMu.Unlock()
169 if c.dir != nil {
170 return *c.dir, nil
171 }
172 173 res, err := c.get(ctx, c.directoryURL(), wantStatus(http.StatusOK))
174 if err != nil {
175 return Directory{}, err
176 }
177 defer res.Body.Close()
178 c.addNonce(res.Header)
179 180 var v struct {
181 Reg string `json:"newAccount"`
182 Authz string `json:"newAuthz"`
183 Order string `json:"newOrder"`
184 Revoke string `json:"revokeCert"`
185 Nonce string `json:"newNonce"`
186 KeyChange string `json:"keyChange"`
187 Meta struct {
188 Terms string `json:"termsOfService"`
189 Website string `json:"website"`
190 CAA []string `json:"caaIdentities"`
191 ExternalAcct bool `json:"externalAccountRequired"`
192 }
193 }
194 if err := json.NewDecoder(res.Body).Decode(&v); err != nil {
195 return Directory{}, err
196 }
197 if v.Order == "" {
198 return Directory{}, errPreRFC
199 }
200 c.dir = &Directory{
201 RegURL: v.Reg,
202 AuthzURL: v.Authz,
203 OrderURL: v.Order,
204 RevokeURL: v.Revoke,
205 NonceURL: v.Nonce,
206 KeyChangeURL: v.KeyChange,
207 Terms: v.Meta.Terms,
208 Website: v.Meta.Website,
209 CAA: v.Meta.CAA,
210 ExternalAccountRequired: v.Meta.ExternalAcct,
211 }
212 return *c.dir, nil
213 }
214 215 func (c *Client) directoryURL() string {
216 if c.DirectoryURL != "" {
217 return c.DirectoryURL
218 }
219 return LetsEncryptURL
220 }
221 222 // CreateCert was part of the old version of ACME. It is incompatible with RFC 8555.
223 //
224 // Deprecated: this was for the pre-RFC 8555 version of ACME. Callers should use CreateOrderCert.
225 func (c *Client) CreateCert(ctx context.Context, csr []byte, exp time.Duration, bundle bool) (der [][]byte, certURL string, err error) {
226 return nil, "", errPreRFC
227 }
228 229 // FetchCert retrieves already issued certificate from the given url, in DER format.
230 // It retries the request until the certificate is successfully retrieved,
231 // context is cancelled by the caller or an error response is received.
232 //
233 // If the bundle argument is true, the returned value also contains the CA (issuer)
234 // certificate chain.
235 //
236 // FetchCert returns an error if the CA's response or chain was unreasonably large.
237 // Callers are encouraged to parse the returned value to ensure the certificate is valid
238 // and has expected features.
239 func (c *Client) FetchCert(ctx context.Context, url string, bundle bool) ([][]byte, error) {
240 if _, err := c.Discover(ctx); err != nil {
241 return nil, err
242 }
243 return c.fetchCertRFC(ctx, url, bundle)
244 }
245 246 // RevokeCert revokes a previously issued certificate cert, provided in DER format.
247 //
248 // The key argument, used to sign the request, must be authorized
249 // to revoke the certificate. It's up to the CA to decide which keys are authorized.
250 // For instance, the key pair of the certificate may be authorized.
251 // If the key is nil, c.Key is used instead.
252 func (c *Client) RevokeCert(ctx context.Context, key crypto.Signer, cert []byte, reason CRLReasonCode) error {
253 if _, err := c.Discover(ctx); err != nil {
254 return err
255 }
256 return c.revokeCertRFC(ctx, key, cert, reason)
257 }
258 259 // AcceptTOS always returns true to indicate the acceptance of a CA's Terms of Service
260 // during account registration. See Register method of Client for more details.
261 func AcceptTOS(tosURL string) bool { return true }
262 263 // Register creates a new account with the CA using c.Key.
264 // It returns the registered account. The account acct 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 //
271 // When interfacing with an RFC-compliant CA, non-RFC 8555 fields of acct are ignored
272 // and prompt is called if Directory's Terms field is non-zero.
273 // Also see Error's Instance field for when a CA requires already registered accounts to agree
274 // to an updated Terms of Service.
275 func (c *Client) Register(ctx context.Context, acct *Account, prompt func(tosURL string) bool) (*Account, error) {
276 if c.Key == nil {
277 return nil, errors.New("acme: client.Key must be set to Register")
278 }
279 if _, err := c.Discover(ctx); err != nil {
280 return nil, err
281 }
282 return c.registerRFC(ctx, acct, prompt)
283 }
284 285 // GetReg retrieves an existing account associated with c.Key.
286 //
287 // The url argument is a legacy artifact of the pre-RFC 8555 API
288 // and is ignored.
289 func (c *Client) GetReg(ctx context.Context, url string) (*Account, error) {
290 if _, err := c.Discover(ctx); err != nil {
291 return nil, err
292 }
293 return c.getRegRFC(ctx)
294 }
295 296 // UpdateReg updates an existing registration.
297 // It returns an updated account copy. The provided account is not modified.
298 //
299 // The account's URI is ignored and the account URL associated with
300 // c.Key is used instead.
301 func (c *Client) UpdateReg(ctx context.Context, acct *Account) (*Account, error) {
302 if _, err := c.Discover(ctx); err != nil {
303 return nil, err
304 }
305 return c.updateRegRFC(ctx, acct)
306 }
307 308 // AccountKeyRollover attempts to transition a client's account key to a new key.
309 // On success client's Key is updated which is not concurrency safe.
310 // On failure an error will be returned.
311 // The new key is already registered with the ACME provider if the following is true:
312 // - error is of type acme.Error
313 // - StatusCode should be 409 (Conflict)
314 // - Location header will have the KID of the associated account
315 //
316 // More about account key rollover can be found at
317 // https://tools.ietf.org/html/rfc8555#section-7.3.5.
318 func (c *Client) AccountKeyRollover(ctx context.Context, newKey crypto.Signer) error {
319 return c.accountKeyRollover(ctx, newKey)
320 }
321 322 // Authorize performs the initial step in the pre-authorization flow,
323 // as opposed to order-based flow.
324 // The caller will then need to choose from and perform a set of returned
325 // challenges using c.Accept in order to successfully complete authorization.
326 //
327 // Once complete, the caller can use AuthorizeOrder which the CA
328 // should provision with the already satisfied authorization.
329 // For pre-RFC CAs, the caller can proceed directly to requesting a certificate
330 // using CreateCert method.
331 //
332 // If an authorization has been previously granted, the CA may return
333 // a valid authorization which has its Status field set to StatusValid.
334 //
335 // More about pre-authorization can be found at
336 // https://tools.ietf.org/html/rfc8555#section-7.4.1.
337 func (c *Client) Authorize(ctx context.Context, domain string) (*Authorization, error) {
338 return c.authorize(ctx, "dns", domain)
339 }
340 341 // AuthorizeIP is the same as Authorize but requests IP address authorization.
342 // Clients which successfully obtain such authorization may request to issue
343 // a certificate for IP addresses.
344 //
345 // See the ACME spec extension for more details about IP address identifiers:
346 // https://tools.ietf.org/html/draft-ietf-acme-ip.
347 func (c *Client) AuthorizeIP(ctx context.Context, ipaddr string) (*Authorization, error) {
348 return c.authorize(ctx, "ip", ipaddr)
349 }
350 351 func (c *Client) authorize(ctx context.Context, typ, val string) (*Authorization, error) {
352 if _, err := c.Discover(ctx); err != nil {
353 return nil, err
354 }
355 if c.dir.AuthzURL == "" {
356 // Pre-Authorization is unsupported
357 return nil, errPreAuthorizationNotSupported
358 }
359 360 type authzID struct {
361 Type string `json:"type"`
362 Value string `json:"value"`
363 }
364 req := struct {
365 Resource string `json:"resource"`
366 Identifier authzID `json:"identifier"`
367 }{
368 Resource: "new-authz",
369 Identifier: authzID{Type: typ, Value: val},
370 }
371 res, err := c.post(ctx, nil, c.dir.AuthzURL, req, wantStatus(http.StatusCreated))
372 if err != nil {
373 return nil, err
374 }
375 defer res.Body.Close()
376 377 var v wireAuthz
378 if err := json.NewDecoder(res.Body).Decode(&v); err != nil {
379 return nil, fmt.Errorf("acme: invalid response: %v", err)
380 }
381 if v.Status != StatusPending && v.Status != StatusValid {
382 return nil, fmt.Errorf("acme: unexpected status: %s", v.Status)
383 }
384 return v.authorization(res.Header.Get("Location")), nil
385 }
386 387 // GetAuthorization retrieves an authorization identified by the given URL.
388 //
389 // If a caller needs to poll an authorization until its status is final,
390 // see the WaitAuthorization method.
391 func (c *Client) GetAuthorization(ctx context.Context, url string) (*Authorization, error) {
392 if _, err := c.Discover(ctx); err != nil {
393 return nil, err
394 }
395 396 res, err := c.postAsGet(ctx, url, wantStatus(http.StatusOK))
397 if err != nil {
398 return nil, err
399 }
400 defer res.Body.Close()
401 var v wireAuthz
402 if err := json.NewDecoder(res.Body).Decode(&v); err != nil {
403 return nil, fmt.Errorf("acme: invalid response: %v", err)
404 }
405 return v.authorization(url), nil
406 }
407 408 // RevokeAuthorization relinquishes an existing authorization identified
409 // by the given URL.
410 // The url argument is an Authorization.URI value.
411 //
412 // If successful, the caller will be required to obtain a new authorization
413 // using the Authorize or AuthorizeOrder methods before being able to request
414 // a new certificate for the domain associated with the authorization.
415 //
416 // It does not revoke existing certificates.
417 func (c *Client) RevokeAuthorization(ctx context.Context, url string) error {
418 if _, err := c.Discover(ctx); err != nil {
419 return err
420 }
421 422 req := struct {
423 Resource string `json:"resource"`
424 Status string `json:"status"`
425 Delete bool `json:"delete"`
426 }{
427 Resource: "authz",
428 Status: "deactivated",
429 Delete: true,
430 }
431 res, err := c.post(ctx, nil, url, req, wantStatus(http.StatusOK))
432 if err != nil {
433 return err
434 }
435 defer res.Body.Close()
436 return nil
437 }
438 439 // WaitAuthorization polls an authorization at the given URL
440 // until it is in one of the final states, StatusValid or StatusInvalid,
441 // the ACME CA responded with a 4xx error code, or the context is done.
442 //
443 // It returns a non-nil Authorization only if its Status is StatusValid.
444 // In all other cases WaitAuthorization returns an error.
445 // If the Status is StatusInvalid, the returned error is of type *AuthorizationError.
446 func (c *Client) WaitAuthorization(ctx context.Context, url string) (*Authorization, error) {
447 if _, err := c.Discover(ctx); err != nil {
448 return nil, err
449 }
450 for {
451 res, err := c.postAsGet(ctx, url, wantStatus(http.StatusOK, http.StatusAccepted))
452 if err != nil {
453 return nil, err
454 }
455 456 var raw wireAuthz
457 err = json.NewDecoder(res.Body).Decode(&raw)
458 res.Body.Close()
459 switch {
460 case err != nil:
461 // Skip and retry.
462 case raw.Status == StatusValid:
463 return raw.authorization(url), nil
464 case raw.Status == StatusInvalid:
465 return nil, raw.error(url)
466 }
467 468 // Exponential backoff is implemented in c.get above.
469 // This is just to prevent continuously hitting the CA
470 // while waiting for a final authorization status.
471 d := retryAfter(res.Header.Get("Retry-After"))
472 if d == 0 {
473 // Given that the fastest challenges TLS-ALPN and HTTP-01
474 // require a CA to make at least 1 network round trip
475 // and most likely persist a challenge state,
476 // this default delay seems reasonable.
477 d = time.Second
478 }
479 t := time.NewTimer(d)
480 select {
481 case <-ctx.Done():
482 t.Stop()
483 return nil, ctx.Err()
484 case <-t.C:
485 // Retry.
486 }
487 }
488 }
489 490 // GetChallenge retrieves the current status of an challenge.
491 //
492 // A client typically polls a challenge status using this method.
493 func (c *Client) GetChallenge(ctx context.Context, url string) (*Challenge, error) {
494 if _, err := c.Discover(ctx); err != nil {
495 return nil, err
496 }
497 498 res, err := c.postAsGet(ctx, url, wantStatus(http.StatusOK, http.StatusAccepted))
499 if err != nil {
500 return nil, err
501 }
502 503 defer res.Body.Close()
504 v := wireChallenge{URI: url}
505 if err := json.NewDecoder(res.Body).Decode(&v); err != nil {
506 return nil, fmt.Errorf("acme: invalid response: %v", err)
507 }
508 return v.challenge(), nil
509 }
510 511 // Accept informs the server that the client accepts one of its challenges
512 // previously obtained with c.Authorize.
513 //
514 // The server will then perform the validation asynchronously.
515 func (c *Client) Accept(ctx context.Context, chal *Challenge) (*Challenge, error) {
516 if _, err := c.Discover(ctx); err != nil {
517 return nil, err
518 }
519 520 payload := json.RawMessage("{}")
521 if len(chal.Payload) != 0 {
522 payload = chal.Payload
523 }
524 res, err := c.post(ctx, nil, chal.URI, payload, wantStatus(
525 http.StatusOK, // according to the spec
526 http.StatusAccepted, // Let's Encrypt: see https://goo.gl/WsJ7VT (acme-divergences.md)
527 ))
528 if err != nil {
529 return nil, err
530 }
531 defer res.Body.Close()
532 533 var v wireChallenge
534 if err := json.NewDecoder(res.Body).Decode(&v); err != nil {
535 return nil, fmt.Errorf("acme: invalid response: %v", err)
536 }
537 return v.challenge(), nil
538 }
539 540 // DNS01ChallengeRecord returns a DNS record value for a dns-01 challenge response.
541 // A TXT record containing the returned value must be provisioned under
542 // "_acme-challenge" name of the domain being validated.
543 //
544 // The token argument is a Challenge.Token value.
545 func (c *Client) DNS01ChallengeRecord(token string) (string, error) {
546 ka, err := keyAuth(c.Key.Public(), token)
547 if err != nil {
548 return "", err
549 }
550 b := sha256.Sum256([]byte(ka))
551 return base64.RawURLEncoding.EncodeToString(b[:]), nil
552 }
553 554 // HTTP01ChallengeResponse returns the response for an http-01 challenge.
555 // Servers should respond with the value to HTTP requests at the URL path
556 // provided by HTTP01ChallengePath to validate the challenge and prove control
557 // over a domain name.
558 //
559 // The token argument is a Challenge.Token value.
560 func (c *Client) HTTP01ChallengeResponse(token string) (string, error) {
561 return keyAuth(c.Key.Public(), token)
562 }
563 564 // HTTP01ChallengePath returns the URL path at which the response for an http-01 challenge
565 // should be provided by the servers.
566 // The response value can be obtained with HTTP01ChallengeResponse.
567 //
568 // The token argument is a Challenge.Token value.
569 func (c *Client) HTTP01ChallengePath(token string) string {
570 return "/.well-known/acme-challenge/" + token
571 }
572 573 // TLSSNI01ChallengeCert creates a certificate for TLS-SNI-01 challenge response.
574 // Always returns an error.
575 //
576 // Deprecated: This challenge type was only present in pre-standardized ACME
577 // protocol drafts and is insecure for use in shared hosting environments.
578 func (c *Client) TLSSNI01ChallengeCert(token string, opt ...CertOption) (tls.Certificate, string, error) {
579 return tls.Certificate{}, "", errPreRFC
580 }
581 582 // TLSSNI02ChallengeCert creates a certificate for TLS-SNI-02 challenge response.
583 // Always returns an error.
584 //
585 // Deprecated: This challenge type was only present in pre-standardized ACME
586 // protocol drafts and is insecure for use in shared hosting environments.
587 func (c *Client) TLSSNI02ChallengeCert(token string, opt ...CertOption) (tls.Certificate, string, error) {
588 return tls.Certificate{}, "", errPreRFC
589 }
590 591 // TLSALPN01ChallengeCert creates a certificate for TLS-ALPN-01 challenge response.
592 // Servers can present the certificate to validate the challenge and prove control
593 // over an identifier (either a DNS name or the textual form of an IPv4 or IPv6
594 // address). For more details on TLS-ALPN-01 see
595 // https://www.rfc-editor.org/rfc/rfc8737 and https://www.rfc-editor.org/rfc/rfc8738
596 //
597 // The token argument is a Challenge.Token value.
598 // If a WithKey option is provided, its private part signs the returned cert,
599 // and the public part is used to specify the signee.
600 // If no WithKey option is provided, a new ECDSA key is generated using P-256 curve.
601 //
602 // The returned certificate is valid for the next 24 hours and must be presented only when
603 // the server name in the TLS ClientHello matches the identifier, and the special acme-tls/1 ALPN protocol
604 // has been specified.
605 //
606 // Validation requests for IP address identifiers will use the reverse DNS form in the server name
607 // in the TLS ClientHello since the SNI extension is not supported for IP addresses.
608 // See RFC 8738 Section 6 for more information.
609 func (c *Client) TLSALPN01ChallengeCert(token, identifier string, opt ...CertOption) (cert tls.Certificate, err error) {
610 ka, err := keyAuth(c.Key.Public(), token)
611 if err != nil {
612 return tls.Certificate{}, err
613 }
614 shasum := sha256.Sum256([]byte(ka))
615 extValue, err := asn1.Marshal(shasum[:])
616 if err != nil {
617 return tls.Certificate{}, err
618 }
619 acmeExtension := pkix.Extension{
620 Id: idPeACMEIdentifier,
621 Critical: true,
622 Value: extValue,
623 }
624 625 tmpl := defaultTLSChallengeCertTemplate()
626 627 var newOpt []CertOption
628 for _, o := range opt {
629 switch o := o.(type) {
630 case *certOptTemplate:
631 t := *(*x509.Certificate)(o) // shallow copy is ok
632 tmpl = &t
633 default:
634 newOpt = append(newOpt, o)
635 }
636 }
637 tmpl.ExtraExtensions = append(tmpl.ExtraExtensions, acmeExtension)
638 newOpt = append(newOpt, WithTemplate(tmpl))
639 return tlsChallengeCert(identifier, newOpt)
640 }
641 642 // popNonce returns a nonce value previously stored with c.addNonce
643 // or fetches a fresh one from c.dir.NonceURL.
644 // If NonceURL is empty, it first tries c.directoryURL() and, failing that,
645 // the provided url.
646 func (c *Client) popNonce(ctx context.Context, url string) (string, error) {
647 c.noncesMu.Lock()
648 defer c.noncesMu.Unlock()
649 if len(c.nonces) == 0 {
650 if c.dir != nil && c.dir.NonceURL != "" {
651 return c.fetchNonce(ctx, c.dir.NonceURL)
652 }
653 dirURL := c.directoryURL()
654 v, err := c.fetchNonce(ctx, dirURL)
655 if err != nil && url != dirURL {
656 v, err = c.fetchNonce(ctx, url)
657 }
658 return v, err
659 }
660 var nonce string
661 for nonce = range c.nonces {
662 delete(c.nonces, nonce)
663 break
664 }
665 return nonce, nil
666 }
667 668 // clearNonces clears any stored nonces
669 func (c *Client) clearNonces() {
670 c.noncesMu.Lock()
671 defer c.noncesMu.Unlock()
672 c.nonces = make(map[string]struct{})
673 }
674 675 // addNonce stores a nonce value found in h (if any) for future use.
676 func (c *Client) addNonce(h http.Header) {
677 v := nonceFromHeader(h)
678 if v == "" {
679 return
680 }
681 c.noncesMu.Lock()
682 defer c.noncesMu.Unlock()
683 if len(c.nonces) >= maxNonces {
684 return
685 }
686 if c.nonces == nil {
687 c.nonces = make(map[string]struct{})
688 }
689 c.nonces[v] = struct{}{}
690 }
691 692 func (c *Client) fetchNonce(ctx context.Context, url string) (string, error) {
693 r, err := http.NewRequestWithContext(ctx, "HEAD", url, nil)
694 if err != nil {
695 return "", err
696 }
697 resp, err := c.doNoRetry(ctx, r)
698 if err != nil {
699 return "", err
700 }
701 defer resp.Body.Close()
702 nonce := nonceFromHeader(resp.Header)
703 if nonce == "" {
704 if resp.StatusCode > 299 {
705 return "", responseError(resp)
706 }
707 return "", errors.New("acme: nonce not found")
708 }
709 return nonce, nil
710 }
711 712 func nonceFromHeader(h http.Header) string {
713 return h.Get("Replay-Nonce")
714 }
715 716 // linkHeader returns URI-Reference values of all Link headers
717 // with relation-type rel.
718 // See https://tools.ietf.org/html/rfc5988#section-5 for details.
719 func linkHeader(h http.Header, rel string) []string {
720 var links []string
721 for _, v := range h["Link"] {
722 parts := strings.Split(v, ";")
723 for _, p := range parts {
724 p = strings.TrimSpace(p)
725 if !strings.HasPrefix(p, "rel=") {
726 continue
727 }
728 if v := strings.Trim(p[4:], `"`); v == rel {
729 links = append(links, strings.Trim(parts[0], "<>"))
730 }
731 }
732 }
733 return links
734 }
735 736 // keyAuth generates a key authorization string for a given token.
737 func keyAuth(pub crypto.PublicKey, token string) (string, error) {
738 th, err := JWKThumbprint(pub)
739 if err != nil {
740 return "", err
741 }
742 return fmt.Sprintf("%s.%s", token, th), nil
743 }
744 745 // defaultTLSChallengeCertTemplate is a template used to create challenge certs for TLS challenges.
746 func defaultTLSChallengeCertTemplate() *x509.Certificate {
747 return &x509.Certificate{
748 SerialNumber: big.NewInt(1),
749 NotBefore: time.Now(),
750 NotAfter: time.Now().Add(24 * time.Hour),
751 BasicConstraintsValid: true,
752 KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature,
753 ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
754 }
755 }
756 757 // tlsChallengeCert creates a temporary certificate for TLS-ALPN challenges
758 // for the given identifier, using an auto-generated public/private key pair.
759 //
760 // If the provided identifier is a domain name, it will be used as a DNS type SAN and for the
761 // subject common name. If the provided identifier is an IP address it will be used as an IP type
762 // SAN.
763 //
764 // To create a cert with a custom key pair, specify WithKey option.
765 func tlsChallengeCert(identifier string, opt []CertOption) (tls.Certificate, error) {
766 var key crypto.Signer
767 tmpl := defaultTLSChallengeCertTemplate()
768 for _, o := range opt {
769 switch o := o.(type) {
770 case *certOptKey:
771 if key != nil {
772 return tls.Certificate{}, errors.New("acme: duplicate key option")
773 }
774 key = o.key
775 case *certOptTemplate:
776 t := *(*x509.Certificate)(o) // shallow copy is ok
777 tmpl = &t
778 default:
779 // package's fault, if we let this happen:
780 panic(fmt.Sprintf("unsupported option type %T", o))
781 }
782 }
783 if key == nil {
784 var err error
785 if key, err = ecdsa.GenerateKey(elliptic.P256(), rand.Reader); err != nil {
786 return tls.Certificate{}, err
787 }
788 }
789 790 if ip := net.ParseIP(identifier); ip != nil {
791 tmpl.IPAddresses = []net.IP{ip}
792 } else {
793 tmpl.DNSNames = []string{identifier}
794 tmpl.Subject.CommonName = identifier
795 }
796 797 der, err := x509.CreateCertificate(rand.Reader, tmpl, tmpl, key.Public(), key)
798 if err != nil {
799 return tls.Certificate{}, err
800 }
801 return tls.Certificate{
802 Certificate: [][]byte{der},
803 PrivateKey: key,
804 }, nil
805 }
806 807 // timeNow is time.Now, except in tests which can mess with it.
808 var timeNow = time.Now
809