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