boulder/core/objects.go

218 lines
6.6 KiB
Go

// Copyright 2014 ISRG. All rights reserved
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
package core
import (
"crypto/x509"
"encoding/json"
"github.com/letsencrypt/boulder/jose"
"time"
)
type IdentifierType string
type AcmeStatus string
type Buffer []byte
const (
StatusUnknown = AcmeStatus("unknown") // Unknown status; the default
StatusPending = AcmeStatus("pending") // In process; client has next action
StatusProcessing = AcmeStatus("processing") // In process; server has next action
StatusValid = AcmeStatus("valid") // Validation succeeded
StatusInvalid = AcmeStatus("invalid") // Validation failed
StatusRevoked = AcmeStatus("revoked") // Object no longer valid
)
const (
ChallengeTypeSimpleHTTPS = "simpleHTTPS"
ChallengeTypeDVSNI = "dvsni"
ChallengeTypeDNS = "dns"
ChallengeTypeRecoveryToken = "recoveryToken"
)
const (
IdentifierDNS = IdentifierType("dns")
)
// An AcmeIdentifier encodes an identifier that can
// be validated by ACME. The protocol allows for different
// types of identifier to be supported (DNS names, IP
// addresses, etc.), but currently we only support
// domain names.
type AcmeIdentifier struct {
Type IdentifierType `json:"type"` // The type of identifier being encoded
Value string `json:"value"` // The identifier itself
}
// An ACME certificate request is just a CSR together with
// URIs pointing to authorizations that should collectively
// authorize the certificate being requsted.
//
// This type is never marshaled, since we only ever receive
// it from the client. So it carries some additional information
// that is useful internally. (We rely on Go's case-insensitive
// JSON unmarshal to properly unmarshal client requests.)
type CertificateRequest struct {
CSR *x509.CertificateRequest // The CSR
Authorizations []AcmeURL // Links to Authorization over the account key
}
type rawCertificateRequest struct {
CSR jose.JsonBuffer `json:"csr"` // The encoded CSR
Authorizations []AcmeURL `json:"authorizations"` // Authorizations
}
func (cr *CertificateRequest) UnmarshalJSON(data []byte) error {
var raw rawCertificateRequest
if err := json.Unmarshal(data, &raw); err != nil {
return err
}
csr, err := x509.ParseCertificateRequest(raw.CSR)
if err != nil {
return err
}
cr.CSR = csr
cr.Authorizations = raw.Authorizations
return nil
}
func (cr CertificateRequest) MarshalJSON() ([]byte, error) {
return json.Marshal(rawCertificateRequest{
CSR: cr.CSR.Raw,
Authorizations: cr.Authorizations,
})
}
// Registration objects represent non-public metadata attached
// to account keys.
type Registration struct {
// Unique identifier
ID string `json:"-"`
// Account key to which the details are attached
Key jose.JsonWebKey `json:"key"`
// Recovery Token is used to prove connection to an earlier transaction
RecoveryToken string `json:"recoveryToken"`
// Contact URIs
Contact []AcmeURL `json:"contact,omitempty"`
// Agreement with terms of service
Agreement string `json:"agreement,omitempty"`
}
func (r *Registration) MergeUpdate(input Registration) {
if len(input.Contact) > 0 {
r.Contact = input.Contact
}
// TODO: Test to make sure this has the proper value
if len(input.Agreement) > 0 {
r.Agreement = input.Agreement
}
}
// Rather than define individual types for different types of
// challenge, we just throw all the elements into one bucket,
// together with the common metadata elements.
type Challenge struct {
// The type of challenge
Type string `json:"type"`
// The status of this challenge
Status AcmeStatus `json:"status,omitempty"`
// If successful, the time at which this challenge
// was completed by the server.
Validated *time.Time `json:"validated,omitempty"`
// A URI to which a response can be POSTed
URI AcmeURL `json:"uri"`
// Used by simpleHTTPS, recoveryToken, and dns challenges
Token string `json:"token,omitempty"`
// Used by simpleHTTPS challenges
Path string `json:"path,omitempty"`
// Used by dvsni challenges
R string `json:"r,omitempty"`
S string `json:"s,omitempty"`
Nonce string `json:"nonce,omitempty"`
}
// Merge a client-provide response to a challenge with the issued challenge
// TODO: Remove return type from this method
func (ch Challenge) MergeResponse(resp Challenge) Challenge {
// Only override fields that are supposed to be client-provided
if len(ch.Path) == 0 {
ch.Path = resp.Path
}
if len(ch.S) == 0 {
ch.S = resp.S
}
return ch
}
// An ACME authorization object represents the authorization
// of an account key holder to act on behalf of a domain. This
// struct is intended to be used both internally and for JSON
// marshaling on the wire. Any fields that should be suppressed
// on the wire (e.g., ID) must be made empty before marshaling.
type Authorization struct {
// An identifier for this authorization, unique across
// authorizations and certificates within this instance.
ID string `json:"id,omitempty"`
// The identifier for which authorization is being given
Identifier AcmeIdentifier `json:"identifier,omitempty"`
// The account key that is authorized for the identifier
Key jose.JsonWebKey `json:"key,omitempty"`
// The status of the validation of this authorization
Status AcmeStatus `json:"status,omitempty"`
// The date after which this authorization will be no
// longer be considered valid
Expires time.Time `json:"expires,omitempty"`
// An array of challenges objects used to validate the
// applicant's control of the identifier. For authorizations
// in process, these are challenges to be fulfilled; for
// final authorizations, they describe the evidence that
// the server used in support of granting the authorization.
Challenges []Challenge `json:"challenges,omitempty"`
// The server may suggest combinations of challenges if it
// requires more than one challenge to be completed.
Combinations [][]int `json:"combinations,omitempty"`
// The client may provide contact URIs to allow the server
// to push information to it.
Contact []AcmeURL `json:"contact,omitempty"`
}
// Certificate objects are entirely internal to the server. The only
// thing exposed on the wire is the certificate itself.
type Certificate struct {
// An identifier for this authorization, unique across
// authorizations and certificates within this instance.
ID string
// The certificate itself
DER jose.JsonBuffer
// The revocation status of the certificate.
// * "valid" - not revoked
// * "revoked" - revoked
Status AcmeStatus
}