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