1// Copyright 2016 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
5package acme
6
7import (
8	"crypto"
9	"crypto/x509"
10	"errors"
11	"fmt"
12	"net/http"
13	"strings"
14	"time"
15)
16
17// ACME status values of Account, Order, Authorization and Challenge objects.
18// See https://tools.ietf.org/html/rfc8555#section-7.1.6 for details.
19const (
20	StatusDeactivated = "deactivated"
21	StatusExpired     = "expired"
22	StatusInvalid     = "invalid"
23	StatusPending     = "pending"
24	StatusProcessing  = "processing"
25	StatusReady       = "ready"
26	StatusRevoked     = "revoked"
27	StatusUnknown     = "unknown"
28	StatusValid       = "valid"
29)
30
31// CRLReasonCode identifies the reason for a certificate revocation.
32type CRLReasonCode int
33
34// CRL reason codes as defined in RFC 5280.
35const (
36	CRLReasonUnspecified          CRLReasonCode = 0
37	CRLReasonKeyCompromise        CRLReasonCode = 1
38	CRLReasonCACompromise         CRLReasonCode = 2
39	CRLReasonAffiliationChanged   CRLReasonCode = 3
40	CRLReasonSuperseded           CRLReasonCode = 4
41	CRLReasonCessationOfOperation CRLReasonCode = 5
42	CRLReasonCertificateHold      CRLReasonCode = 6
43	CRLReasonRemoveFromCRL        CRLReasonCode = 8
44	CRLReasonPrivilegeWithdrawn   CRLReasonCode = 9
45	CRLReasonAACompromise         CRLReasonCode = 10
46)
47
48var (
49	// ErrUnsupportedKey is returned when an unsupported key type is encountered.
50	ErrUnsupportedKey = errors.New("acme: unknown key type; only RSA and ECDSA are supported")
51
52	// ErrAccountAlreadyExists indicates that the Client's key has already been registered
53	// with the CA. It is returned by Register method.
54	ErrAccountAlreadyExists = errors.New("acme: account already exists")
55
56	// ErrNoAccount indicates that the Client's key has not been registered with the CA.
57	ErrNoAccount = errors.New("acme: account does not exist")
58)
59
60// A Subproblem describes an ACME subproblem as reported in an Error.
61type Subproblem struct {
62	// Type is a URI reference that identifies the problem type,
63	// typically in a "urn:acme:error:xxx" form.
64	Type string
65	// Detail is a human-readable explanation specific to this occurrence of the problem.
66	Detail string
67	// Instance indicates a URL that the client should direct a human user to visit
68	// in order for instructions on how to agree to the updated Terms of Service.
69	// In such an event CA sets StatusCode to 403, Type to
70	// "urn:ietf:params:acme:error:userActionRequired", and adds a Link header with relation
71	// "terms-of-service" containing the latest TOS URL.
72	Instance string
73	// Identifier may contain the ACME identifier that the error is for.
74	Identifier *AuthzID
75}
76
77func (sp Subproblem) String() string {
78	str := fmt.Sprintf("%s: ", sp.Type)
79	if sp.Identifier != nil {
80		str += fmt.Sprintf("[%s: %s] ", sp.Identifier.Type, sp.Identifier.Value)
81	}
82	str += sp.Detail
83	return str
84}
85
86// Error is an ACME error, defined in Problem Details for HTTP APIs doc
87// http://tools.ietf.org/html/draft-ietf-appsawg-http-problem.
88type Error struct {
89	// StatusCode is The HTTP status code generated by the origin server.
90	StatusCode int
91	// ProblemType is a URI reference that identifies the problem type,
92	// typically in a "urn:acme:error:xxx" form.
93	ProblemType string
94	// Detail is a human-readable explanation specific to this occurrence of the problem.
95	Detail string
96	// Instance indicates a URL that the client should direct a human user to visit
97	// in order for instructions on how to agree to the updated Terms of Service.
98	// In such an event CA sets StatusCode to 403, ProblemType to
99	// "urn:ietf:params:acme:error:userActionRequired" and a Link header with relation
100	// "terms-of-service" containing the latest TOS URL.
101	Instance string
102	// Header is the original server error response headers.
103	// It may be nil.
104	Header http.Header
105	// Subproblems may contain more detailed information about the individual problems
106	// that caused the error. This field is only sent by RFC 8555 compatible ACME
107	// servers. Defined in RFC 8555 Section 6.7.1.
108	Subproblems []Subproblem
109}
110
111func (e *Error) Error() string {
112	str := fmt.Sprintf("%d %s: %s", e.StatusCode, e.ProblemType, e.Detail)
113	if len(e.Subproblems) > 0 {
114		str += fmt.Sprintf("; subproblems:")
115		for _, sp := range e.Subproblems {
116			str += fmt.Sprintf("\n\t%s", sp)
117		}
118	}
119	return str
120}
121
122// AuthorizationError indicates that an authorization for an identifier
123// did not succeed.
124// It contains all errors from Challenge items of the failed Authorization.
125type AuthorizationError struct {
126	// URI uniquely identifies the failed Authorization.
127	URI string
128
129	// Identifier is an AuthzID.Value of the failed Authorization.
130	Identifier string
131
132	// Errors is a collection of non-nil error values of Challenge items
133	// of the failed Authorization.
134	Errors []error
135}
136
137func (a *AuthorizationError) Error() string {
138	e := make([]string, len(a.Errors))
139	for i, err := range a.Errors {
140		e[i] = err.Error()
141	}
142
143	if a.Identifier != "" {
144		return fmt.Sprintf("acme: authorization error for %s: %s", a.Identifier, strings.Join(e, "; "))
145	}
146
147	return fmt.Sprintf("acme: authorization error: %s", strings.Join(e, "; "))
148}
149
150// OrderError is returned from Client's order related methods.
151// It indicates the order is unusable and the clients should start over with
152// AuthorizeOrder.
153//
154// The clients can still fetch the order object from CA using GetOrder
155// to inspect its state.
156type OrderError struct {
157	OrderURL string
158	Status   string
159}
160
161func (oe *OrderError) Error() string {
162	return fmt.Sprintf("acme: order %s status: %s", oe.OrderURL, oe.Status)
163}
164
165// RateLimit reports whether err represents a rate limit error and
166// any Retry-After duration returned by the server.
167//
168// See the following for more details on rate limiting:
169// https://tools.ietf.org/html/draft-ietf-acme-acme-05#section-5.6
170func RateLimit(err error) (time.Duration, bool) {
171	e, ok := err.(*Error)
172	if !ok {
173		return 0, false
174	}
175	// Some CA implementations may return incorrect values.
176	// Use case-insensitive comparison.
177	if !strings.HasSuffix(strings.ToLower(e.ProblemType), ":ratelimited") {
178		return 0, false
179	}
180	if e.Header == nil {
181		return 0, true
182	}
183	return retryAfter(e.Header.Get("Retry-After")), true
184}
185
186// Account is a user account. It is associated with a private key.
187// Non-RFC 8555 fields are empty when interfacing with a compliant CA.
188type Account struct {
189	// URI is the account unique ID, which is also a URL used to retrieve
190	// account data from the CA.
191	// When interfacing with RFC 8555-compliant CAs, URI is the "kid" field
192	// value in JWS signed requests.
193	URI string
194
195	// Contact is a slice of contact info used during registration.
196	// See https://tools.ietf.org/html/rfc8555#section-7.3 for supported
197	// formats.
198	Contact []string
199
200	// Status indicates current account status as returned by the CA.
201	// Possible values are StatusValid, StatusDeactivated, and StatusRevoked.
202	Status string
203
204	// OrdersURL is a URL from which a list of orders submitted by this account
205	// can be fetched.
206	OrdersURL string
207
208	// The terms user has agreed to.
209	// A value not matching CurrentTerms indicates that the user hasn't agreed
210	// to the actual Terms of Service of the CA.
211	//
212	// It is non-RFC 8555 compliant. Package users can store the ToS they agree to
213	// during Client's Register call in the prompt callback function.
214	AgreedTerms string
215
216	// Actual terms of a CA.
217	//
218	// It is non-RFC 8555 compliant. Use Directory's Terms field.
219	// When a CA updates their terms and requires an account agreement,
220	// a URL at which instructions to do so is available in Error's Instance field.
221	CurrentTerms string
222
223	// Authz is the authorization URL used to initiate a new authz flow.
224	//
225	// It is non-RFC 8555 compliant. Use Directory's AuthzURL or OrderURL.
226	Authz string
227
228	// Authorizations is a URI from which a list of authorizations
229	// granted to this account can be fetched via a GET request.
230	//
231	// It is non-RFC 8555 compliant and is obsoleted by OrdersURL.
232	Authorizations string
233
234	// Certificates is a URI from which a list of certificates
235	// issued for this account can be fetched via a GET request.
236	//
237	// It is non-RFC 8555 compliant and is obsoleted by OrdersURL.
238	Certificates string
239
240	// ExternalAccountBinding represents an arbitrary binding to an account of
241	// the CA which the ACME server is tied to.
242	// See https://tools.ietf.org/html/rfc8555#section-7.3.4 for more details.
243	ExternalAccountBinding *ExternalAccountBinding
244}
245
246// ExternalAccountBinding contains the data needed to form a request with
247// an external account binding.
248// See https://tools.ietf.org/html/rfc8555#section-7.3.4 for more details.
249type ExternalAccountBinding struct {
250	// KID is the Key ID of the symmetric MAC key that the CA provides to
251	// identify an external account from ACME.
252	KID string
253
254	// Key is the bytes of the symmetric key that the CA provides to identify
255	// the account. Key must correspond to the KID.
256	Key []byte
257}
258
259func (e *ExternalAccountBinding) String() string {
260	return fmt.Sprintf("&{KID: %q, Key: redacted}", e.KID)
261}
262
263// Directory is ACME server discovery data.
264// See https://tools.ietf.org/html/rfc8555#section-7.1.1 for more details.
265type Directory struct {
266	// NonceURL indicates an endpoint where to fetch fresh nonce values from.
267	NonceURL string
268
269	// RegURL is an account endpoint URL, allowing for creating new accounts.
270	// Pre-RFC 8555 CAs also allow modifying existing accounts at this URL.
271	RegURL string
272
273	// OrderURL is used to initiate the certificate issuance flow
274	// as described in RFC 8555.
275	OrderURL string
276
277	// AuthzURL is used to initiate identifier pre-authorization flow.
278	// Empty string indicates the flow is unsupported by the CA.
279	AuthzURL string
280
281	// CertURL is a new certificate issuance endpoint URL.
282	// It is non-RFC 8555 compliant and is obsoleted by OrderURL.
283	CertURL string
284
285	// RevokeURL is used to initiate a certificate revocation flow.
286	RevokeURL string
287
288	// KeyChangeURL allows to perform account key rollover flow.
289	KeyChangeURL string
290
291	// Term is a URI identifying the current terms of service.
292	Terms string
293
294	// Website is an HTTP or HTTPS URL locating a website
295	// providing more information about the ACME server.
296	Website string
297
298	// CAA consists of lowercase hostname elements, which the ACME server
299	// recognises as referring to itself for the purposes of CAA record validation
300	// as defined in RFC6844.
301	CAA []string
302
303	// ExternalAccountRequired indicates that the CA requires for all account-related
304	// requests to include external account binding information.
305	ExternalAccountRequired bool
306}
307
308// rfcCompliant reports whether the ACME server implements RFC 8555.
309// Note that some servers may have incomplete RFC implementation
310// even if the returned value is true.
311// If rfcCompliant reports false, the server most likely implements draft-02.
312func (d *Directory) rfcCompliant() bool {
313	return d.OrderURL != ""
314}
315
316// Order represents a client's request for a certificate.
317// It tracks the request flow progress through to issuance.
318type Order struct {
319	// URI uniquely identifies an order.
320	URI string
321
322	// Status represents the current status of the order.
323	// It indicates which action the client should take.
324	//
325	// Possible values are StatusPending, StatusReady, StatusProcessing, StatusValid and StatusInvalid.
326	// Pending means the CA does not believe that the client has fulfilled the requirements.
327	// Ready indicates that the client has fulfilled all the requirements and can submit a CSR
328	// to obtain a certificate. This is done with Client's CreateOrderCert.
329	// Processing means the certificate is being issued.
330	// Valid indicates the CA has issued the certificate. It can be downloaded
331	// from the Order's CertURL. This is done with Client's FetchCert.
332	// Invalid means the certificate will not be issued. Users should consider this order
333	// abandoned.
334	Status string
335
336	// Expires is the timestamp after which CA considers this order invalid.
337	Expires time.Time
338
339	// Identifiers contains all identifier objects which the order pertains to.
340	Identifiers []AuthzID
341
342	// NotBefore is the requested value of the notBefore field in the certificate.
343	NotBefore time.Time
344
345	// NotAfter is the requested value of the notAfter field in the certificate.
346	NotAfter time.Time
347
348	// AuthzURLs represents authorizations to complete before a certificate
349	// for identifiers specified in the order can be issued.
350	// It also contains unexpired authorizations that the client has completed
351	// in the past.
352	//
353	// Authorization objects can be fetched using Client's GetAuthorization method.
354	//
355	// The required authorizations are dictated by CA policies.
356	// There may not be a 1:1 relationship between the identifiers and required authorizations.
357	// Required authorizations can be identified by their StatusPending status.
358	//
359	// For orders in the StatusValid or StatusInvalid state these are the authorizations
360	// which were completed.
361	AuthzURLs []string
362
363	// FinalizeURL is the endpoint at which a CSR is submitted to obtain a certificate
364	// once all the authorizations are satisfied.
365	FinalizeURL string
366
367	// CertURL points to the certificate that has been issued in response to this order.
368	CertURL string
369
370	// The error that occurred while processing the order as received from a CA, if any.
371	Error *Error
372}
373
374// OrderOption allows customizing Client.AuthorizeOrder call.
375type OrderOption interface {
376	privateOrderOpt()
377}
378
379// WithOrderNotBefore sets order's NotBefore field.
380func WithOrderNotBefore(t time.Time) OrderOption {
381	return orderNotBeforeOpt(t)
382}
383
384// WithOrderNotAfter sets order's NotAfter field.
385func WithOrderNotAfter(t time.Time) OrderOption {
386	return orderNotAfterOpt(t)
387}
388
389type orderNotBeforeOpt time.Time
390
391func (orderNotBeforeOpt) privateOrderOpt() {}
392
393type orderNotAfterOpt time.Time
394
395func (orderNotAfterOpt) privateOrderOpt() {}
396
397// Authorization encodes an authorization response.
398type Authorization struct {
399	// URI uniquely identifies a authorization.
400	URI string
401
402	// Status is the current status of an authorization.
403	// Possible values are StatusPending, StatusValid, StatusInvalid, StatusDeactivated,
404	// StatusExpired and StatusRevoked.
405	Status string
406
407	// Identifier is what the account is authorized to represent.
408	Identifier AuthzID
409
410	// The timestamp after which the CA considers the authorization invalid.
411	Expires time.Time
412
413	// Wildcard is true for authorizations of a wildcard domain name.
414	Wildcard bool
415
416	// Challenges that the client needs to fulfill in order to prove possession
417	// of the identifier (for pending authorizations).
418	// For valid authorizations, the challenge that was validated.
419	// For invalid authorizations, the challenge that was attempted and failed.
420	//
421	// RFC 8555 compatible CAs require users to fuflfill only one of the challenges.
422	Challenges []*Challenge
423
424	// A collection of sets of challenges, each of which would be sufficient
425	// to prove possession of the identifier.
426	// Clients must complete a set of challenges that covers at least one set.
427	// Challenges are identified by their indices in the challenges array.
428	// If this field is empty, the client needs to complete all challenges.
429	//
430	// This field is unused in RFC 8555.
431	Combinations [][]int
432}
433
434// AuthzID is an identifier that an account is authorized to represent.
435type AuthzID struct {
436	Type  string // The type of identifier, "dns" or "ip".
437	Value string // The identifier itself, e.g. "example.org".
438}
439
440// DomainIDs creates a slice of AuthzID with "dns" identifier type.
441func DomainIDs(names ...string) []AuthzID {
442	a := make([]AuthzID, len(names))
443	for i, v := range names {
444		a[i] = AuthzID{Type: "dns", Value: v}
445	}
446	return a
447}
448
449// IPIDs creates a slice of AuthzID with "ip" identifier type.
450// Each element of addr is textual form of an address as defined
451// in RFC1123 Section 2.1 for IPv4 and in RFC5952 Section 4 for IPv6.
452func IPIDs(addr ...string) []AuthzID {
453	a := make([]AuthzID, len(addr))
454	for i, v := range addr {
455		a[i] = AuthzID{Type: "ip", Value: v}
456	}
457	return a
458}
459
460// wireAuthzID is ACME JSON representation of authorization identifier objects.
461type wireAuthzID struct {
462	Type  string `json:"type"`
463	Value string `json:"value"`
464}
465
466// wireAuthz is ACME JSON representation of Authorization objects.
467type wireAuthz struct {
468	Identifier   wireAuthzID
469	Status       string
470	Expires      time.Time
471	Wildcard     bool
472	Challenges   []wireChallenge
473	Combinations [][]int
474	Error        *wireError
475}
476
477func (z *wireAuthz) authorization(uri string) *Authorization {
478	a := &Authorization{
479		URI:          uri,
480		Status:       z.Status,
481		Identifier:   AuthzID{Type: z.Identifier.Type, Value: z.Identifier.Value},
482		Expires:      z.Expires,
483		Wildcard:     z.Wildcard,
484		Challenges:   make([]*Challenge, len(z.Challenges)),
485		Combinations: z.Combinations, // shallow copy
486	}
487	for i, v := range z.Challenges {
488		a.Challenges[i] = v.challenge()
489	}
490	return a
491}
492
493func (z *wireAuthz) error(uri string) *AuthorizationError {
494	err := &AuthorizationError{
495		URI:        uri,
496		Identifier: z.Identifier.Value,
497	}
498
499	if z.Error != nil {
500		err.Errors = append(err.Errors, z.Error.error(nil))
501	}
502
503	for _, raw := range z.Challenges {
504		if raw.Error != nil {
505			err.Errors = append(err.Errors, raw.Error.error(nil))
506		}
507	}
508
509	return err
510}
511
512// Challenge encodes a returned CA challenge.
513// Its Error field may be non-nil if the challenge is part of an Authorization
514// with StatusInvalid.
515type Challenge struct {
516	// Type is the challenge type, e.g. "http-01", "tls-alpn-01", "dns-01".
517	Type string
518
519	// URI is where a challenge response can be posted to.
520	URI string
521
522	// Token is a random value that uniquely identifies the challenge.
523	Token string
524
525	// Status identifies the status of this challenge.
526	// In RFC 8555, possible values are StatusPending, StatusProcessing, StatusValid,
527	// and StatusInvalid.
528	Status string
529
530	// Validated is the time at which the CA validated this challenge.
531	// Always zero value in pre-RFC 8555.
532	Validated time.Time
533
534	// Error indicates the reason for an authorization failure
535	// when this challenge was used.
536	// The type of a non-nil value is *Error.
537	Error error
538}
539
540// wireChallenge is ACME JSON challenge representation.
541type wireChallenge struct {
542	URL       string `json:"url"` // RFC
543	URI       string `json:"uri"` // pre-RFC
544	Type      string
545	Token     string
546	Status    string
547	Validated time.Time
548	Error     *wireError
549}
550
551func (c *wireChallenge) challenge() *Challenge {
552	v := &Challenge{
553		URI:    c.URL,
554		Type:   c.Type,
555		Token:  c.Token,
556		Status: c.Status,
557	}
558	if v.URI == "" {
559		v.URI = c.URI // c.URL was empty; use legacy
560	}
561	if v.Status == "" {
562		v.Status = StatusPending
563	}
564	if c.Error != nil {
565		v.Error = c.Error.error(nil)
566	}
567	return v
568}
569
570// wireError is a subset of fields of the Problem Details object
571// as described in https://tools.ietf.org/html/rfc7807#section-3.1.
572type wireError struct {
573	Status      int
574	Type        string
575	Detail      string
576	Instance    string
577	Subproblems []Subproblem
578}
579
580func (e *wireError) error(h http.Header) *Error {
581	err := &Error{
582		StatusCode:  e.Status,
583		ProblemType: e.Type,
584		Detail:      e.Detail,
585		Instance:    e.Instance,
586		Header:      h,
587		Subproblems: e.Subproblems,
588	}
589	return err
590}
591
592// CertOption is an optional argument type for the TLS ChallengeCert methods for
593// customizing a temporary certificate for TLS-based challenges.
594type CertOption interface {
595	privateCertOpt()
596}
597
598// WithKey creates an option holding a private/public key pair.
599// The private part signs a certificate, and the public part represents the signee.
600func WithKey(key crypto.Signer) CertOption {
601	return &certOptKey{key}
602}
603
604type certOptKey struct {
605	key crypto.Signer
606}
607
608func (*certOptKey) privateCertOpt() {}
609
610// WithTemplate creates an option for specifying a certificate template.
611// See x509.CreateCertificate for template usage details.
612//
613// In TLS ChallengeCert methods, the template is also used as parent,
614// resulting in a self-signed certificate.
615// The DNSNames field of t is always overwritten for tls-sni challenge certs.
616func WithTemplate(t *x509.Certificate) CertOption {
617	return (*certOptTemplate)(t)
618}
619
620type certOptTemplate x509.Certificate
621
622func (*certOptTemplate) privateCertOpt() {}
623