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