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