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