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 5 package acme 6 7 import ( 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. 19 const ( 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. 32 type CRLReasonCode int 33 34 // CRL reason codes as defined in RFC 5280. 35 const ( 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 48 var ( 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. 61 type 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 77 func (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. 88 type 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 111 func (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. 125 type 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 137 func (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. 156 type OrderError struct { 157 OrderURL string 158 Status string 159 } 160 161 func (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 170 func 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. 188 type 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. 249 type 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 259 func (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. 265 type 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 RFC 6844. 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 // Order represents a client's request for a certificate. 309 // It tracks the request flow progress through to issuance. 310 type Order struct { 311 // URI uniquely identifies an order. 312 URI string 313 314 // Status represents the current status of the order. 315 // It indicates which action the client should take. 316 // 317 // Possible values are StatusPending, StatusReady, StatusProcessing, StatusValid and StatusInvalid. 318 // Pending means the CA does not believe that the client has fulfilled the requirements. 319 // Ready indicates that the client has fulfilled all the requirements and can submit a CSR 320 // to obtain a certificate. This is done with Client's CreateOrderCert. 321 // Processing means the certificate is being issued. 322 // Valid indicates the CA has issued the certificate. It can be downloaded 323 // from the Order's CertURL. This is done with Client's FetchCert. 324 // Invalid means the certificate will not be issued. Users should consider this order 325 // abandoned. 326 Status string 327 328 // Expires is the timestamp after which CA considers this order invalid. 329 Expires time.Time 330 331 // Identifiers contains all identifier objects which the order pertains to. 332 Identifiers []AuthzID 333 334 // NotBefore is the requested value of the notBefore field in the certificate. 335 NotBefore time.Time 336 337 // NotAfter is the requested value of the notAfter field in the certificate. 338 NotAfter time.Time 339 340 // AuthzURLs represents authorizations to complete before a certificate 341 // for identifiers specified in the order can be issued. 342 // It also contains unexpired authorizations that the client has completed 343 // in the past. 344 // 345 // Authorization objects can be fetched using Client's GetAuthorization method. 346 // 347 // The required authorizations are dictated by CA policies. 348 // There may not be a 1:1 relationship between the identifiers and required authorizations. 349 // Required authorizations can be identified by their StatusPending status. 350 // 351 // For orders in the StatusValid or StatusInvalid state these are the authorizations 352 // which were completed. 353 AuthzURLs []string 354 355 // FinalizeURL is the endpoint at which a CSR is submitted to obtain a certificate 356 // once all the authorizations are satisfied. 357 FinalizeURL string 358 359 // CertURL points to the certificate that has been issued in response to this order. 360 CertURL string 361 362 // The error that occurred while processing the order as received from a CA, if any. 363 Error *Error 364 } 365 366 // OrderOption allows customizing Client.AuthorizeOrder call. 367 type OrderOption interface { 368 privateOrderOpt() 369 } 370 371 // WithOrderNotBefore sets order's NotBefore field. 372 func WithOrderNotBefore(t time.Time) OrderOption { 373 return orderNotBeforeOpt(t) 374 } 375 376 // WithOrderNotAfter sets order's NotAfter field. 377 func WithOrderNotAfter(t time.Time) OrderOption { 378 return orderNotAfterOpt(t) 379 } 380 381 type orderNotBeforeOpt time.Time 382 383 func (orderNotBeforeOpt) privateOrderOpt() {} 384 385 type orderNotAfterOpt time.Time 386 387 func (orderNotAfterOpt) privateOrderOpt() {} 388 389 // Authorization encodes an authorization response. 390 type Authorization struct { 391 // URI uniquely identifies a authorization. 392 URI string 393 394 // Status is the current status of an authorization. 395 // Possible values are StatusPending, StatusValid, StatusInvalid, StatusDeactivated, 396 // StatusExpired and StatusRevoked. 397 Status string 398 399 // Identifier is what the account is authorized to represent. 400 Identifier AuthzID 401 402 // The timestamp after which the CA considers the authorization invalid. 403 Expires time.Time 404 405 // Wildcard is true for authorizations of a wildcard domain name. 406 Wildcard bool 407 408 // Challenges that the client needs to fulfill in order to prove possession 409 // of the identifier (for pending authorizations). 410 // For valid authorizations, the challenge that was validated. 411 // For invalid authorizations, the challenge that was attempted and failed. 412 // 413 // RFC 8555 compatible CAs require users to fuflfill only one of the challenges. 414 Challenges []*Challenge 415 416 // A collection of sets of challenges, each of which would be sufficient 417 // to prove possession of the identifier. 418 // Clients must complete a set of challenges that covers at least one set. 419 // Challenges are identified by their indices in the challenges array. 420 // If this field is empty, the client needs to complete all challenges. 421 // 422 // This field is unused in RFC 8555. 423 Combinations [][]int 424 } 425 426 // AuthzID is an identifier that an account is authorized to represent. 427 type AuthzID struct { 428 Type string // The type of identifier, "dns" or "ip". 429 Value string // The identifier itself, e.g. "example.org". 430 } 431 432 // DomainIDs creates a slice of AuthzID with "dns" identifier type. 433 func DomainIDs(names ...string) []AuthzID { 434 a := make([]AuthzID, len(names)) 435 for i, v := range names { 436 a[i] = AuthzID{Type: "dns", Value: v} 437 } 438 return a 439 } 440 441 // IPIDs creates a slice of AuthzID with "ip" identifier type. 442 // Each element of addr is textual form of an address as defined 443 // in RFC 1123 Section 2.1 for IPv4 and in RFC 5952 Section 4 for IPv6. 444 func IPIDs(addr ...string) []AuthzID { 445 a := make([]AuthzID, len(addr)) 446 for i, v := range addr { 447 a[i] = AuthzID{Type: "ip", Value: v} 448 } 449 return a 450 } 451 452 // wireAuthzID is ACME JSON representation of authorization identifier objects. 453 type wireAuthzID struct { 454 Type string `json:"type"` 455 Value string `json:"value"` 456 } 457 458 // wireAuthz is ACME JSON representation of Authorization objects. 459 type wireAuthz struct { 460 Identifier wireAuthzID 461 Status string 462 Expires time.Time 463 Wildcard bool 464 Challenges []wireChallenge 465 Combinations [][]int 466 Error *wireError 467 } 468 469 func (z *wireAuthz) authorization(uri string) *Authorization { 470 a := &Authorization{ 471 URI: uri, 472 Status: z.Status, 473 Identifier: AuthzID{Type: z.Identifier.Type, Value: z.Identifier.Value}, 474 Expires: z.Expires, 475 Wildcard: z.Wildcard, 476 Challenges: make([]*Challenge, len(z.Challenges)), 477 Combinations: z.Combinations, // shallow copy 478 } 479 for i, v := range z.Challenges { 480 a.Challenges[i] = v.challenge() 481 } 482 return a 483 } 484 485 func (z *wireAuthz) error(uri string) *AuthorizationError { 486 err := &AuthorizationError{ 487 URI: uri, 488 Identifier: z.Identifier.Value, 489 } 490 491 if z.Error != nil { 492 err.Errors = append(err.Errors, z.Error.error(nil)) 493 } 494 495 for _, raw := range z.Challenges { 496 if raw.Error != nil { 497 err.Errors = append(err.Errors, raw.Error.error(nil)) 498 } 499 } 500 501 return err 502 } 503 504 // Challenge encodes a returned CA challenge. 505 // Its Error field may be non-nil if the challenge is part of an Authorization 506 // with StatusInvalid. 507 type Challenge struct { 508 // Type is the challenge type, e.g. "http-01", "tls-alpn-01", "dns-01". 509 Type string 510 511 // URI is where a challenge response can be posted to. 512 URI string 513 514 // Token is a random value that uniquely identifies the challenge. 515 Token string 516 517 // Status identifies the status of this challenge. 518 // In RFC 8555, possible values are StatusPending, StatusProcessing, StatusValid, 519 // and StatusInvalid. 520 Status string 521 522 // Validated is the time at which the CA validated this challenge. 523 // Always zero value in pre-RFC 8555. 524 Validated time.Time 525 526 // Error indicates the reason for an authorization failure 527 // when this challenge was used. 528 // The type of a non-nil value is *Error. 529 Error error 530 } 531 532 // wireChallenge is ACME JSON challenge representation. 533 type wireChallenge struct { 534 URL string `json:"url"` // RFC 535 URI string `json:"uri"` // pre-RFC 536 Type string 537 Token string 538 Status string 539 Validated time.Time 540 Error *wireError 541 } 542 543 func (c *wireChallenge) challenge() *Challenge { 544 v := &Challenge{ 545 URI: c.URL, 546 Type: c.Type, 547 Token: c.Token, 548 Status: c.Status, 549 } 550 if v.URI == "" { 551 v.URI = c.URI // c.URL was empty; use legacy 552 } 553 if v.Status == "" { 554 v.Status = StatusPending 555 } 556 if c.Error != nil { 557 v.Error = c.Error.error(nil) 558 } 559 return v 560 } 561 562 // wireError is a subset of fields of the Problem Details object 563 // as described in https://tools.ietf.org/html/rfc7807#section-3.1. 564 type wireError struct { 565 Status int 566 Type string 567 Detail string 568 Instance string 569 Subproblems []Subproblem 570 } 571 572 func (e *wireError) error(h http.Header) *Error { 573 err := &Error{ 574 StatusCode: e.Status, 575 ProblemType: e.Type, 576 Detail: e.Detail, 577 Instance: e.Instance, 578 Header: h, 579 Subproblems: e.Subproblems, 580 } 581 return err 582 } 583 584 // CertOption is an optional argument type for the TLS ChallengeCert methods for 585 // customizing a temporary certificate for TLS-based challenges. 586 type CertOption interface { 587 privateCertOpt() 588 } 589 590 // WithKey creates an option holding a private/public key pair. 591 // The private part signs a certificate, and the public part represents the signee. 592 func WithKey(key crypto.Signer) CertOption { 593 return &certOptKey{key} 594 } 595 596 type certOptKey struct { 597 key crypto.Signer 598 } 599 600 func (*certOptKey) privateCertOpt() {} 601 602 // WithTemplate creates an option for specifying a certificate template. 603 // See x509.CreateCertificate for template usage details. 604 // 605 // In TLS ChallengeCert methods, the template is also used as parent, 606 // resulting in a self-signed certificate. 607 // The DNSNames field of t is always overwritten for tls-sni challenge certs. 608 func WithTemplate(t *x509.Certificate) CertOption { 609 return (*certOptTemplate)(t) 610 } 611 612 type certOptTemplate x509.Certificate 613 614 func (*certOptTemplate) privateCertOpt() {} 615