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