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 204// Directory is ACME server discovery data. 205// See https://tools.ietf.org/html/rfc8555#section-7.1.1 for more details. 206type Directory struct { 207 // NonceURL indicates an endpoint where to fetch fresh nonce values from. 208 NonceURL string 209 210 // RegURL is an account endpoint URL, allowing for creating new accounts. 211 // Pre-RFC 8555 CAs also allow modifying existing accounts at this URL. 212 RegURL string 213 214 // OrderURL is used to initiate the certificate issuance flow 215 // as described in RFC 8555. 216 OrderURL string 217 218 // AuthzURL is used to initiate identifier pre-authorization flow. 219 // Empty string indicates the flow is unsupported by the CA. 220 AuthzURL string 221 222 // CertURL is a new certificate issuance endpoint URL. 223 // It is non-RFC 8555 compliant and is obsoleted by OrderURL. 224 CertURL string 225 226 // RevokeURL is used to initiate a certificate revocation flow. 227 RevokeURL string 228 229 // KeyChangeURL allows to perform account key rollover flow. 230 KeyChangeURL string 231 232 // Term is a URI identifying the current terms of service. 233 Terms string 234 235 // Website is an HTTP or HTTPS URL locating a website 236 // providing more information about the ACME server. 237 Website string 238 239 // CAA consists of lowercase hostname elements, which the ACME server 240 // recognises as referring to itself for the purposes of CAA record validation 241 // as defined in RFC6844. 242 CAA []string 243 244 // ExternalAccountRequired indicates that the CA requires for all account-related 245 // requests to include external account binding information. 246 ExternalAccountRequired bool 247} 248 249// rfcCompliant reports whether the ACME server implements RFC 8555. 250// Note that some servers may have incomplete RFC implementation 251// even if the returned value is true. 252// If rfcCompliant reports false, the server most likely implements draft-02. 253func (d *Directory) rfcCompliant() bool { 254 return d.OrderURL != "" 255} 256 257// Order represents a client's request for a certificate. 258// It tracks the request flow progress through to issuance. 259type Order struct { 260 // URI uniquely identifies an order. 261 URI string 262 263 // Status represents the current status of the order. 264 // It indicates which action the client should take. 265 // 266 // Possible values are StatusPending, StatusReady, StatusProcessing, StatusValid and StatusInvalid. 267 // Pending means the CA does not believe that the client has fulfilled the requirements. 268 // Ready indicates that the client has fulfilled all the requirements and can submit a CSR 269 // to obtain a certificate. This is done with Client's CreateOrderCert. 270 // Processing means the certificate is being issued. 271 // Valid indicates the CA has issued the certificate. It can be downloaded 272 // from the Order's CertURL. This is done with Client's FetchCert. 273 // Invalid means the certificate will not be issued. Users should consider this order 274 // abandoned. 275 Status string 276 277 // Expires is the timestamp after which CA considers this order invalid. 278 Expires time.Time 279 280 // Identifiers contains all identifier objects which the order pertains to. 281 Identifiers []AuthzID 282 283 // NotBefore is the requested value of the notBefore field in the certificate. 284 NotBefore time.Time 285 286 // NotAfter is the requested value of the notAfter field in the certificate. 287 NotAfter time.Time 288 289 // AuthzURLs represents authorizations to complete before a certificate 290 // for identifiers specified in the order can be issued. 291 // It also contains unexpired authorizations that the client has completed 292 // in the past. 293 // 294 // Authorization objects can be fetched using Client's GetAuthorization method. 295 // 296 // The required authorizations are dictated by CA policies. 297 // There may not be a 1:1 relationship between the identifiers and required authorizations. 298 // Required authorizations can be identified by their StatusPending status. 299 // 300 // For orders in the StatusValid or StatusInvalid state these are the authorizations 301 // which were completed. 302 AuthzURLs []string 303 304 // FinalizeURL is the endpoint at which a CSR is submitted to obtain a certificate 305 // once all the authorizations are satisfied. 306 FinalizeURL string 307 308 // CertURL points to the certificate that has been issued in response to this order. 309 CertURL string 310 311 // The error that occurred while processing the order as received from a CA, if any. 312 Error *Error 313} 314 315// OrderOption allows customizing Client.AuthorizeOrder call. 316type OrderOption interface { 317 privateOrderOpt() 318} 319 320// WithOrderNotBefore sets order's NotBefore field. 321func WithOrderNotBefore(t time.Time) OrderOption { 322 return orderNotBeforeOpt(t) 323} 324 325// WithOrderNotAfter sets order's NotAfter field. 326func WithOrderNotAfter(t time.Time) OrderOption { 327 return orderNotAfterOpt(t) 328} 329 330type orderNotBeforeOpt time.Time 331 332func (orderNotBeforeOpt) privateOrderOpt() {} 333 334type orderNotAfterOpt time.Time 335 336func (orderNotAfterOpt) privateOrderOpt() {} 337 338// Authorization encodes an authorization response. 339type Authorization struct { 340 // URI uniquely identifies a authorization. 341 URI string 342 343 // Status is the current status of an authorization. 344 // Possible values are StatusPending, StatusValid, StatusInvalid, StatusDeactivated, 345 // StatusExpired and StatusRevoked. 346 Status string 347 348 // Identifier is what the account is authorized to represent. 349 Identifier AuthzID 350 351 // The timestamp after which the CA considers the authorization invalid. 352 Expires time.Time 353 354 // Wildcard is true for authorizations of a wildcard domain name. 355 Wildcard bool 356 357 // Challenges that the client needs to fulfill in order to prove possession 358 // of the identifier (for pending authorizations). 359 // For valid authorizations, the challenge that was validated. 360 // For invalid authorizations, the challenge that was attempted and failed. 361 // 362 // RFC 8555 compatible CAs require users to fuflfill only one of the challenges. 363 Challenges []*Challenge 364 365 // A collection of sets of challenges, each of which would be sufficient 366 // to prove possession of the identifier. 367 // Clients must complete a set of challenges that covers at least one set. 368 // Challenges are identified by their indices in the challenges array. 369 // If this field is empty, the client needs to complete all challenges. 370 // 371 // This field is unused in RFC 8555. 372 Combinations [][]int 373} 374 375// AuthzID is an identifier that an account is authorized to represent. 376type AuthzID struct { 377 Type string // The type of identifier, "dns" or "ip". 378 Value string // The identifier itself, e.g. "example.org". 379} 380 381// DomainIDs creates a slice of AuthzID with "dns" identifier type. 382func DomainIDs(names ...string) []AuthzID { 383 a := make([]AuthzID, len(names)) 384 for i, v := range names { 385 a[i] = AuthzID{Type: "dns", Value: v} 386 } 387 return a 388} 389 390// IPIDs creates a slice of AuthzID with "ip" identifier type. 391// Each element of addr is textual form of an address as defined 392// in RFC1123 Section 2.1 for IPv4 and in RFC5952 Section 4 for IPv6. 393func IPIDs(addr ...string) []AuthzID { 394 a := make([]AuthzID, len(addr)) 395 for i, v := range addr { 396 a[i] = AuthzID{Type: "ip", Value: v} 397 } 398 return a 399} 400 401// wireAuthzID is ACME JSON representation of authorization identifier objects. 402type wireAuthzID struct { 403 Type string `json:"type"` 404 Value string `json:"value"` 405} 406 407// wireAuthz is ACME JSON representation of Authorization objects. 408type wireAuthz struct { 409 Identifier wireAuthzID 410 Status string 411 Expires time.Time 412 Wildcard bool 413 Challenges []wireChallenge 414 Combinations [][]int 415 Error *wireError 416} 417 418func (z *wireAuthz) authorization(uri string) *Authorization { 419 a := &Authorization{ 420 URI: uri, 421 Status: z.Status, 422 Identifier: AuthzID{Type: z.Identifier.Type, Value: z.Identifier.Value}, 423 Expires: z.Expires, 424 Wildcard: z.Wildcard, 425 Challenges: make([]*Challenge, len(z.Challenges)), 426 Combinations: z.Combinations, // shallow copy 427 } 428 for i, v := range z.Challenges { 429 a.Challenges[i] = v.challenge() 430 } 431 return a 432} 433 434func (z *wireAuthz) error(uri string) *AuthorizationError { 435 err := &AuthorizationError{ 436 URI: uri, 437 Identifier: z.Identifier.Value, 438 } 439 440 if z.Error != nil { 441 err.Errors = append(err.Errors, z.Error.error(nil)) 442 } 443 444 for _, raw := range z.Challenges { 445 if raw.Error != nil { 446 err.Errors = append(err.Errors, raw.Error.error(nil)) 447 } 448 } 449 450 return err 451} 452 453// Challenge encodes a returned CA challenge. 454// Its Error field may be non-nil if the challenge is part of an Authorization 455// with StatusInvalid. 456type Challenge struct { 457 // Type is the challenge type, e.g. "http-01", "tls-alpn-01", "dns-01". 458 Type string 459 460 // URI is where a challenge response can be posted to. 461 URI string 462 463 // Token is a random value that uniquely identifies the challenge. 464 Token string 465 466 // Status identifies the status of this challenge. 467 // In RFC 8555, possible values are StatusPending, StatusProcessing, StatusValid, 468 // and StatusInvalid. 469 Status string 470 471 // Validated is the time at which the CA validated this challenge. 472 // Always zero value in pre-RFC 8555. 473 Validated time.Time 474 475 // Error indicates the reason for an authorization failure 476 // when this challenge was used. 477 // The type of a non-nil value is *Error. 478 Error error 479} 480 481// wireChallenge is ACME JSON challenge representation. 482type wireChallenge struct { 483 URL string `json:"url"` // RFC 484 URI string `json:"uri"` // pre-RFC 485 Type string 486 Token string 487 Status string 488 Validated time.Time 489 Error *wireError 490} 491 492func (c *wireChallenge) challenge() *Challenge { 493 v := &Challenge{ 494 URI: c.URL, 495 Type: c.Type, 496 Token: c.Token, 497 Status: c.Status, 498 } 499 if v.URI == "" { 500 v.URI = c.URI // c.URL was empty; use legacy 501 } 502 if v.Status == "" { 503 v.Status = StatusPending 504 } 505 if c.Error != nil { 506 v.Error = c.Error.error(nil) 507 } 508 return v 509} 510 511// wireError is a subset of fields of the Problem Details object 512// as described in https://tools.ietf.org/html/rfc7807#section-3.1. 513type wireError struct { 514 Status int 515 Type string 516 Detail string 517 Instance string 518} 519 520func (e *wireError) error(h http.Header) *Error { 521 return &Error{ 522 StatusCode: e.Status, 523 ProblemType: e.Type, 524 Detail: e.Detail, 525 Instance: e.Instance, 526 Header: h, 527 } 528} 529 530// CertOption is an optional argument type for the TLS ChallengeCert methods for 531// customizing a temporary certificate for TLS-based challenges. 532type CertOption interface { 533 privateCertOpt() 534} 535 536// WithKey creates an option holding a private/public key pair. 537// The private part signs a certificate, and the public part represents the signee. 538func WithKey(key crypto.Signer) CertOption { 539 return &certOptKey{key} 540} 541 542type certOptKey struct { 543 key crypto.Signer 544} 545 546func (*certOptKey) privateCertOpt() {} 547 548// WithTemplate creates an option for specifying a certificate template. 549// See x509.CreateCertificate for template usage details. 550// 551// In TLS ChallengeCert methods, the template is also used as parent, 552// resulting in a self-signed certificate. 553// The DNSNames field of t is always overwritten for tls-sni challenge certs. 554func WithTemplate(t *x509.Certificate) CertOption { 555 return (*certOptTemplate)(t) 556} 557 558type certOptTemplate x509.Certificate 559 560func (*certOptTemplate) privateCertOpt() {} 561