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