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