...

Source file src/golang.org/x/crypto/acme/acme.go

Documentation: golang.org/x/crypto/acme

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

View as plain text