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