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	dir, err := c.Discover(ctx)
367	if err != nil {
368		return nil, err
369	}
370	if dir.rfcCompliant() {
371		return c.registerRFC(ctx, acct, prompt)
372	}
373
374	// Legacy ACME draft registration flow.
375	a, err := c.doReg(ctx, dir.RegURL, "new-reg", acct)
376	if err != nil {
377		return nil, err
378	}
379	var accept bool
380	if a.CurrentTerms != "" && a.CurrentTerms != a.AgreedTerms {
381		accept = prompt(a.CurrentTerms)
382	}
383	if accept {
384		a.AgreedTerms = a.CurrentTerms
385		a, err = c.UpdateReg(ctx, a)
386	}
387	return a, err
388}
389
390// GetReg retrieves an existing account associated with c.Key.
391//
392// The url argument is an Account URI used with pre-RFC 8555 CAs.
393// It is ignored when interfacing with an RFC-compliant CA.
394func (c *Client) GetReg(ctx context.Context, url string) (*Account, error) {
395	dir, err := c.Discover(ctx)
396	if err != nil {
397		return nil, err
398	}
399	if dir.rfcCompliant() {
400		return c.getRegRFC(ctx)
401	}
402
403	// Legacy CA.
404	a, err := c.doReg(ctx, url, "reg", nil)
405	if err != nil {
406		return nil, err
407	}
408	a.URI = url
409	return a, nil
410}
411
412// UpdateReg updates an existing registration.
413// It returns an updated account copy. The provided account is not modified.
414//
415// When interfacing with RFC-compliant CAs, a.URI is ignored and the account URL
416// associated with c.Key is used instead.
417func (c *Client) UpdateReg(ctx context.Context, acct *Account) (*Account, error) {
418	dir, err := c.Discover(ctx)
419	if err != nil {
420		return nil, err
421	}
422	if dir.rfcCompliant() {
423		return c.updateRegRFC(ctx, acct)
424	}
425
426	// Legacy CA.
427	uri := acct.URI
428	a, err := c.doReg(ctx, uri, "reg", acct)
429	if err != nil {
430		return nil, err
431	}
432	a.URI = uri
433	return a, nil
434}
435
436// Authorize performs the initial step in the pre-authorization flow,
437// as opposed to order-based flow.
438// The caller will then need to choose from and perform a set of returned
439// challenges using c.Accept in order to successfully complete authorization.
440//
441// Once complete, the caller can use AuthorizeOrder which the CA
442// should provision with the already satisfied authorization.
443// For pre-RFC CAs, the caller can proceed directly to requesting a certificate
444// using CreateCert method.
445//
446// If an authorization has been previously granted, the CA may return
447// a valid authorization which has its Status field set to StatusValid.
448//
449// More about pre-authorization can be found at
450// https://tools.ietf.org/html/rfc8555#section-7.4.1.
451func (c *Client) Authorize(ctx context.Context, domain string) (*Authorization, error) {
452	return c.authorize(ctx, "dns", domain)
453}
454
455// AuthorizeIP is the same as Authorize but requests IP address authorization.
456// Clients which successfully obtain such authorization may request to issue
457// a certificate for IP addresses.
458//
459// See the ACME spec extension for more details about IP address identifiers:
460// https://tools.ietf.org/html/draft-ietf-acme-ip.
461func (c *Client) AuthorizeIP(ctx context.Context, ipaddr string) (*Authorization, error) {
462	return c.authorize(ctx, "ip", ipaddr)
463}
464
465func (c *Client) authorize(ctx context.Context, typ, val string) (*Authorization, error) {
466	if _, err := c.Discover(ctx); err != nil {
467		return nil, err
468	}
469
470	type authzID struct {
471		Type  string `json:"type"`
472		Value string `json:"value"`
473	}
474	req := struct {
475		Resource   string  `json:"resource"`
476		Identifier authzID `json:"identifier"`
477	}{
478		Resource:   "new-authz",
479		Identifier: authzID{Type: typ, Value: val},
480	}
481	res, err := c.post(ctx, nil, c.dir.AuthzURL, req, wantStatus(http.StatusCreated))
482	if err != nil {
483		return nil, err
484	}
485	defer res.Body.Close()
486
487	var v wireAuthz
488	if err := json.NewDecoder(res.Body).Decode(&v); err != nil {
489		return nil, fmt.Errorf("acme: invalid response: %v", err)
490	}
491	if v.Status != StatusPending && v.Status != StatusValid {
492		return nil, fmt.Errorf("acme: unexpected status: %s", v.Status)
493	}
494	return v.authorization(res.Header.Get("Location")), nil
495}
496
497// GetAuthorization retrieves an authorization identified by the given URL.
498//
499// If a caller needs to poll an authorization until its status is final,
500// see the WaitAuthorization method.
501func (c *Client) GetAuthorization(ctx context.Context, url string) (*Authorization, error) {
502	dir, err := c.Discover(ctx)
503	if err != nil {
504		return nil, err
505	}
506
507	var res *http.Response
508	if dir.rfcCompliant() {
509		res, err = c.postAsGet(ctx, url, wantStatus(http.StatusOK))
510	} else {
511		res, err = c.get(ctx, url, wantStatus(http.StatusOK, http.StatusAccepted))
512	}
513	if err != nil {
514		return nil, err
515	}
516	defer res.Body.Close()
517	var v wireAuthz
518	if err := json.NewDecoder(res.Body).Decode(&v); err != nil {
519		return nil, fmt.Errorf("acme: invalid response: %v", err)
520	}
521	return v.authorization(url), nil
522}
523
524// RevokeAuthorization relinquishes an existing authorization identified
525// by the given URL.
526// The url argument is an Authorization.URI value.
527//
528// If successful, the caller will be required to obtain a new authorization
529// using the Authorize or AuthorizeOrder methods before being able to request
530// a new certificate for the domain associated with the authorization.
531//
532// It does not revoke existing certificates.
533func (c *Client) RevokeAuthorization(ctx context.Context, url string) error {
534	// Required for c.accountKID() when in RFC mode.
535	if _, err := c.Discover(ctx); err != nil {
536		return err
537	}
538
539	req := struct {
540		Resource string `json:"resource"`
541		Status   string `json:"status"`
542		Delete   bool   `json:"delete"`
543	}{
544		Resource: "authz",
545		Status:   "deactivated",
546		Delete:   true,
547	}
548	res, err := c.post(ctx, nil, url, req, wantStatus(http.StatusOK))
549	if err != nil {
550		return err
551	}
552	defer res.Body.Close()
553	return nil
554}
555
556// WaitAuthorization polls an authorization at the given URL
557// until it is in one of the final states, StatusValid or StatusInvalid,
558// the ACME CA responded with a 4xx error code, or the context is done.
559//
560// It returns a non-nil Authorization only if its Status is StatusValid.
561// In all other cases WaitAuthorization returns an error.
562// If the Status is StatusInvalid, the returned error is of type *AuthorizationError.
563func (c *Client) WaitAuthorization(ctx context.Context, url string) (*Authorization, error) {
564	// Required for c.accountKID() when in RFC mode.
565	dir, err := c.Discover(ctx)
566	if err != nil {
567		return nil, err
568	}
569	getfn := c.postAsGet
570	if !dir.rfcCompliant() {
571		getfn = c.get
572	}
573
574	for {
575		res, err := getfn(ctx, url, wantStatus(http.StatusOK, http.StatusAccepted))
576		if err != nil {
577			return nil, err
578		}
579
580		var raw wireAuthz
581		err = json.NewDecoder(res.Body).Decode(&raw)
582		res.Body.Close()
583		switch {
584		case err != nil:
585			// Skip and retry.
586		case raw.Status == StatusValid:
587			return raw.authorization(url), nil
588		case raw.Status == StatusInvalid:
589			return nil, raw.error(url)
590		}
591
592		// Exponential backoff is implemented in c.get above.
593		// This is just to prevent continuously hitting the CA
594		// while waiting for a final authorization status.
595		d := retryAfter(res.Header.Get("Retry-After"))
596		if d == 0 {
597			// Given that the fastest challenges TLS-SNI and HTTP-01
598			// require a CA to make at least 1 network round trip
599			// and most likely persist a challenge state,
600			// this default delay seems reasonable.
601			d = time.Second
602		}
603		t := time.NewTimer(d)
604		select {
605		case <-ctx.Done():
606			t.Stop()
607			return nil, ctx.Err()
608		case <-t.C:
609			// Retry.
610		}
611	}
612}
613
614// GetChallenge retrieves the current status of an challenge.
615//
616// A client typically polls a challenge status using this method.
617func (c *Client) GetChallenge(ctx context.Context, url string) (*Challenge, error) {
618	// Required for c.accountKID() when in RFC mode.
619	dir, err := c.Discover(ctx)
620	if err != nil {
621		return nil, err
622	}
623
624	getfn := c.postAsGet
625	if !dir.rfcCompliant() {
626		getfn = c.get
627	}
628	res, err := getfn(ctx, url, wantStatus(http.StatusOK, http.StatusAccepted))
629	if err != nil {
630		return nil, err
631	}
632
633	defer res.Body.Close()
634	v := wireChallenge{URI: url}
635	if err := json.NewDecoder(res.Body).Decode(&v); err != nil {
636		return nil, fmt.Errorf("acme: invalid response: %v", err)
637	}
638	return v.challenge(), nil
639}
640
641// Accept informs the server that the client accepts one of its challenges
642// previously obtained with c.Authorize.
643//
644// The server will then perform the validation asynchronously.
645func (c *Client) Accept(ctx context.Context, chal *Challenge) (*Challenge, error) {
646	// Required for c.accountKID() when in RFC mode.
647	dir, err := c.Discover(ctx)
648	if err != nil {
649		return nil, err
650	}
651
652	var req interface{} = json.RawMessage("{}") // RFC-compliant CA
653	if !dir.rfcCompliant() {
654		auth, err := keyAuth(c.Key.Public(), chal.Token)
655		if err != nil {
656			return nil, err
657		}
658		req = struct {
659			Resource string `json:"resource"`
660			Type     string `json:"type"`
661			Auth     string `json:"keyAuthorization"`
662		}{
663			Resource: "challenge",
664			Type:     chal.Type,
665			Auth:     auth,
666		}
667	}
668	res, err := c.post(ctx, nil, chal.URI, req, wantStatus(
669		http.StatusOK,       // according to the spec
670		http.StatusAccepted, // Let's Encrypt: see https://goo.gl/WsJ7VT (acme-divergences.md)
671	))
672	if err != nil {
673		return nil, err
674	}
675	defer res.Body.Close()
676
677	var v wireChallenge
678	if err := json.NewDecoder(res.Body).Decode(&v); err != nil {
679		return nil, fmt.Errorf("acme: invalid response: %v", err)
680	}
681	return v.challenge(), nil
682}
683
684// DNS01ChallengeRecord returns a DNS record value for a dns-01 challenge response.
685// A TXT record containing the returned value must be provisioned under
686// "_acme-challenge" name of the domain being validated.
687//
688// The token argument is a Challenge.Token value.
689func (c *Client) DNS01ChallengeRecord(token string) (string, error) {
690	ka, err := keyAuth(c.Key.Public(), token)
691	if err != nil {
692		return "", err
693	}
694	b := sha256.Sum256([]byte(ka))
695	return base64.RawURLEncoding.EncodeToString(b[:]), nil
696}
697
698// HTTP01ChallengeResponse returns the response for an http-01 challenge.
699// Servers should respond with the value to HTTP requests at the URL path
700// provided by HTTP01ChallengePath to validate the challenge and prove control
701// over a domain name.
702//
703// The token argument is a Challenge.Token value.
704func (c *Client) HTTP01ChallengeResponse(token string) (string, error) {
705	return keyAuth(c.Key.Public(), token)
706}
707
708// HTTP01ChallengePath returns the URL path at which the response for an http-01 challenge
709// should be provided by the servers.
710// The response value can be obtained with HTTP01ChallengeResponse.
711//
712// The token argument is a Challenge.Token value.
713func (c *Client) HTTP01ChallengePath(token string) string {
714	return "/.well-known/acme-challenge/" + token
715}
716
717// TLSSNI01ChallengeCert creates a certificate for TLS-SNI-01 challenge response.
718//
719// Deprecated: This challenge type is unused in both draft-02 and RFC versions of ACME spec.
720func (c *Client) TLSSNI01ChallengeCert(token string, opt ...CertOption) (cert tls.Certificate, name string, err error) {
721	ka, err := keyAuth(c.Key.Public(), token)
722	if err != nil {
723		return tls.Certificate{}, "", err
724	}
725	b := sha256.Sum256([]byte(ka))
726	h := hex.EncodeToString(b[:])
727	name = fmt.Sprintf("%s.%s.acme.invalid", h[:32], h[32:])
728	cert, err = tlsChallengeCert([]string{name}, opt)
729	if err != nil {
730		return tls.Certificate{}, "", err
731	}
732	return cert, name, nil
733}
734
735// TLSSNI02ChallengeCert creates a certificate for TLS-SNI-02 challenge response.
736//
737// Deprecated: This challenge type is unused in both draft-02 and RFC versions of ACME spec.
738func (c *Client) TLSSNI02ChallengeCert(token string, opt ...CertOption) (cert tls.Certificate, name string, err error) {
739	b := sha256.Sum256([]byte(token))
740	h := hex.EncodeToString(b[:])
741	sanA := fmt.Sprintf("%s.%s.token.acme.invalid", h[:32], h[32:])
742
743	ka, err := keyAuth(c.Key.Public(), token)
744	if err != nil {
745		return tls.Certificate{}, "", err
746	}
747	b = sha256.Sum256([]byte(ka))
748	h = hex.EncodeToString(b[:])
749	sanB := fmt.Sprintf("%s.%s.ka.acme.invalid", h[:32], h[32:])
750
751	cert, err = tlsChallengeCert([]string{sanA, sanB}, opt)
752	if err != nil {
753		return tls.Certificate{}, "", err
754	}
755	return cert, sanA, nil
756}
757
758// TLSALPN01ChallengeCert creates a certificate for TLS-ALPN-01 challenge response.
759// Servers can present the certificate to validate the challenge and prove control
760// over a domain name. For more details on TLS-ALPN-01 see
761// https://tools.ietf.org/html/draft-shoemaker-acme-tls-alpn-00#section-3
762//
763// The token argument is a Challenge.Token value.
764// If a WithKey option is provided, its private part signs the returned cert,
765// and the public part is used to specify the signee.
766// If no WithKey option is provided, a new ECDSA key is generated using P-256 curve.
767//
768// The returned certificate is valid for the next 24 hours and must be presented only when
769// the server name in the TLS ClientHello matches the domain, and the special acme-tls/1 ALPN protocol
770// has been specified.
771func (c *Client) TLSALPN01ChallengeCert(token, domain string, opt ...CertOption) (cert tls.Certificate, err error) {
772	ka, err := keyAuth(c.Key.Public(), token)
773	if err != nil {
774		return tls.Certificate{}, err
775	}
776	shasum := sha256.Sum256([]byte(ka))
777	extValue, err := asn1.Marshal(shasum[:])
778	if err != nil {
779		return tls.Certificate{}, err
780	}
781	acmeExtension := pkix.Extension{
782		Id:       idPeACMEIdentifier,
783		Critical: true,
784		Value:    extValue,
785	}
786
787	tmpl := defaultTLSChallengeCertTemplate()
788
789	var newOpt []CertOption
790	for _, o := range opt {
791		switch o := o.(type) {
792		case *certOptTemplate:
793			t := *(*x509.Certificate)(o) // shallow copy is ok
794			tmpl = &t
795		default:
796			newOpt = append(newOpt, o)
797		}
798	}
799	tmpl.ExtraExtensions = append(tmpl.ExtraExtensions, acmeExtension)
800	newOpt = append(newOpt, WithTemplate(tmpl))
801	return tlsChallengeCert([]string{domain}, newOpt)
802}
803
804// doReg sends all types of registration requests the old way (pre-RFC world).
805// The type of request is identified by typ argument, which is a "resource"
806// in the ACME spec terms.
807//
808// A non-nil acct argument indicates whether the intention is to mutate data
809// of the Account. Only Contact and Agreement of its fields are used
810// in such cases.
811func (c *Client) doReg(ctx context.Context, url string, typ string, acct *Account) (*Account, error) {
812	req := struct {
813		Resource  string   `json:"resource"`
814		Contact   []string `json:"contact,omitempty"`
815		Agreement string   `json:"agreement,omitempty"`
816	}{
817		Resource: typ,
818	}
819	if acct != nil {
820		req.Contact = acct.Contact
821		req.Agreement = acct.AgreedTerms
822	}
823	res, err := c.post(ctx, nil, url, req, wantStatus(
824		http.StatusOK,       // updates and deletes
825		http.StatusCreated,  // new account creation
826		http.StatusAccepted, // Let's Encrypt divergent implementation
827	))
828	if err != nil {
829		return nil, err
830	}
831	defer res.Body.Close()
832
833	var v struct {
834		Contact        []string
835		Agreement      string
836		Authorizations string
837		Certificates   string
838	}
839	if err := json.NewDecoder(res.Body).Decode(&v); err != nil {
840		return nil, fmt.Errorf("acme: invalid response: %v", err)
841	}
842	var tos string
843	if v := linkHeader(res.Header, "terms-of-service"); len(v) > 0 {
844		tos = v[0]
845	}
846	var authz string
847	if v := linkHeader(res.Header, "next"); len(v) > 0 {
848		authz = v[0]
849	}
850	return &Account{
851		URI:            res.Header.Get("Location"),
852		Contact:        v.Contact,
853		AgreedTerms:    v.Agreement,
854		CurrentTerms:   tos,
855		Authz:          authz,
856		Authorizations: v.Authorizations,
857		Certificates:   v.Certificates,
858	}, nil
859}
860
861// popNonce returns a nonce value previously stored with c.addNonce
862// or fetches a fresh one from c.dir.NonceURL.
863// If NonceURL is empty, it first tries c.directoryURL() and, failing that,
864// the provided url.
865func (c *Client) popNonce(ctx context.Context, url string) (string, error) {
866	c.noncesMu.Lock()
867	defer c.noncesMu.Unlock()
868	if len(c.nonces) == 0 {
869		if c.dir != nil && c.dir.NonceURL != "" {
870			return c.fetchNonce(ctx, c.dir.NonceURL)
871		}
872		dirURL := c.directoryURL()
873		v, err := c.fetchNonce(ctx, dirURL)
874		if err != nil && url != dirURL {
875			v, err = c.fetchNonce(ctx, url)
876		}
877		return v, err
878	}
879	var nonce string
880	for nonce = range c.nonces {
881		delete(c.nonces, nonce)
882		break
883	}
884	return nonce, nil
885}
886
887// clearNonces clears any stored nonces
888func (c *Client) clearNonces() {
889	c.noncesMu.Lock()
890	defer c.noncesMu.Unlock()
891	c.nonces = make(map[string]struct{})
892}
893
894// addNonce stores a nonce value found in h (if any) for future use.
895func (c *Client) addNonce(h http.Header) {
896	v := nonceFromHeader(h)
897	if v == "" {
898		return
899	}
900	c.noncesMu.Lock()
901	defer c.noncesMu.Unlock()
902	if len(c.nonces) >= maxNonces {
903		return
904	}
905	if c.nonces == nil {
906		c.nonces = make(map[string]struct{})
907	}
908	c.nonces[v] = struct{}{}
909}
910
911func (c *Client) fetchNonce(ctx context.Context, url string) (string, error) {
912	r, err := http.NewRequest("HEAD", url, nil)
913	if err != nil {
914		return "", err
915	}
916	resp, err := c.doNoRetry(ctx, r)
917	if err != nil {
918		return "", err
919	}
920	defer resp.Body.Close()
921	nonce := nonceFromHeader(resp.Header)
922	if nonce == "" {
923		if resp.StatusCode > 299 {
924			return "", responseError(resp)
925		}
926		return "", errors.New("acme: nonce not found")
927	}
928	return nonce, nil
929}
930
931func nonceFromHeader(h http.Header) string {
932	return h.Get("Replay-Nonce")
933}
934
935func (c *Client) responseCert(ctx context.Context, res *http.Response, bundle bool) ([][]byte, error) {
936	b, err := ioutil.ReadAll(io.LimitReader(res.Body, maxCertSize+1))
937	if err != nil {
938		return nil, fmt.Errorf("acme: response stream: %v", err)
939	}
940	if len(b) > maxCertSize {
941		return nil, errors.New("acme: certificate is too big")
942	}
943	cert := [][]byte{b}
944	if !bundle {
945		return cert, nil
946	}
947
948	// Append CA chain cert(s).
949	// At least one is required according to the spec:
950	// https://tools.ietf.org/html/draft-ietf-acme-acme-03#section-6.3.1
951	up := linkHeader(res.Header, "up")
952	if len(up) == 0 {
953		return nil, errors.New("acme: rel=up link not found")
954	}
955	if len(up) > maxChainLen {
956		return nil, errors.New("acme: rel=up link is too large")
957	}
958	for _, url := range up {
959		cc, err := c.chainCert(ctx, url, 0)
960		if err != nil {
961			return nil, err
962		}
963		cert = append(cert, cc...)
964	}
965	return cert, nil
966}
967
968// chainCert fetches CA certificate chain recursively by following "up" links.
969// Each recursive call increments the depth by 1, resulting in an error
970// if the recursion level reaches maxChainLen.
971//
972// First chainCert call starts with depth of 0.
973func (c *Client) chainCert(ctx context.Context, url string, depth int) ([][]byte, error) {
974	if depth >= maxChainLen {
975		return nil, errors.New("acme: certificate chain is too deep")
976	}
977
978	res, err := c.get(ctx, url, wantStatus(http.StatusOK))
979	if err != nil {
980		return nil, err
981	}
982	defer res.Body.Close()
983	b, err := ioutil.ReadAll(io.LimitReader(res.Body, maxCertSize+1))
984	if err != nil {
985		return nil, err
986	}
987	if len(b) > maxCertSize {
988		return nil, errors.New("acme: certificate is too big")
989	}
990	chain := [][]byte{b}
991
992	uplink := linkHeader(res.Header, "up")
993	if len(uplink) > maxChainLen {
994		return nil, errors.New("acme: certificate chain is too large")
995	}
996	for _, up := range uplink {
997		cc, err := c.chainCert(ctx, up, depth+1)
998		if err != nil {
999			return nil, err
1000		}
1001		chain = append(chain, cc...)
1002	}
1003
1004	return chain, nil
1005}
1006
1007// linkHeader returns URI-Reference values of all Link headers
1008// with relation-type rel.
1009// See https://tools.ietf.org/html/rfc5988#section-5 for details.
1010func linkHeader(h http.Header, rel string) []string {
1011	var links []string
1012	for _, v := range h["Link"] {
1013		parts := strings.Split(v, ";")
1014		for _, p := range parts {
1015			p = strings.TrimSpace(p)
1016			if !strings.HasPrefix(p, "rel=") {
1017				continue
1018			}
1019			if v := strings.Trim(p[4:], `"`); v == rel {
1020				links = append(links, strings.Trim(parts[0], "<>"))
1021			}
1022		}
1023	}
1024	return links
1025}
1026
1027// keyAuth generates a key authorization string for a given token.
1028func keyAuth(pub crypto.PublicKey, token string) (string, error) {
1029	th, err := JWKThumbprint(pub)
1030	if err != nil {
1031		return "", err
1032	}
1033	return fmt.Sprintf("%s.%s", token, th), nil
1034}
1035
1036// defaultTLSChallengeCertTemplate is a template used to create challenge certs for TLS challenges.
1037func defaultTLSChallengeCertTemplate() *x509.Certificate {
1038	return &x509.Certificate{
1039		SerialNumber:          big.NewInt(1),
1040		NotBefore:             time.Now(),
1041		NotAfter:              time.Now().Add(24 * time.Hour),
1042		BasicConstraintsValid: true,
1043		KeyUsage:              x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature,
1044		ExtKeyUsage:           []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
1045	}
1046}
1047
1048// tlsChallengeCert creates a temporary certificate for TLS-SNI challenges
1049// with the given SANs and auto-generated public/private key pair.
1050// The Subject Common Name is set to the first SAN to aid debugging.
1051// To create a cert with a custom key pair, specify WithKey option.
1052func tlsChallengeCert(san []string, opt []CertOption) (tls.Certificate, error) {
1053	var key crypto.Signer
1054	tmpl := defaultTLSChallengeCertTemplate()
1055	for _, o := range opt {
1056		switch o := o.(type) {
1057		case *certOptKey:
1058			if key != nil {
1059				return tls.Certificate{}, errors.New("acme: duplicate key option")
1060			}
1061			key = o.key
1062		case *certOptTemplate:
1063			t := *(*x509.Certificate)(o) // shallow copy is ok
1064			tmpl = &t
1065		default:
1066			// package's fault, if we let this happen:
1067			panic(fmt.Sprintf("unsupported option type %T", o))
1068		}
1069	}
1070	if key == nil {
1071		var err error
1072		if key, err = ecdsa.GenerateKey(elliptic.P256(), rand.Reader); err != nil {
1073			return tls.Certificate{}, err
1074		}
1075	}
1076	tmpl.DNSNames = san
1077	if len(san) > 0 {
1078		tmpl.Subject.CommonName = san[0]
1079	}
1080
1081	der, err := x509.CreateCertificate(rand.Reader, tmpl, tmpl, key.Public(), key)
1082	if err != nil {
1083		return tls.Certificate{}, err
1084	}
1085	return tls.Certificate{
1086		Certificate: [][]byte{der},
1087		PrivateKey:  key,
1088	}, nil
1089}
1090
1091// encodePEM returns b encoded as PEM with block of type typ.
1092func encodePEM(typ string, b []byte) []byte {
1093	pb := &pem.Block{Type: typ, Bytes: b}
1094	return pem.EncodeToMemory(pb)
1095}
1096
1097// timeNow is useful for testing for fixed current time.
1098var timeNow = time.Now
1099