From eb9893bd21a46f937b00b46e9e5305bd5fa53c19 Mon Sep 17 00:00:00 2001 From: Herman Slatman Date: Tue, 9 Jan 2024 18:22:21 +0100 Subject: [PATCH] Refactor logic for processing `WireID` identifiers in Order Processing `WireID` identifiers, the Wire subject, and the Wire DPoP and OIDC tokens is now conditional. --- acme/db/nosql/nosql.go | 8 +++---- acme/db/nosql/wire.go | 8 +++---- acme/order.go | 52 ++++++++++++++++++++++++++++++------------ 3 files changed, 46 insertions(+), 22 deletions(-) diff --git a/acme/db/nosql/nosql.go b/acme/db/nosql/nosql.go index dc11584b..b2921f55 100644 --- a/acme/db/nosql/nosql.go +++ b/acme/db/nosql/nosql.go @@ -23,8 +23,8 @@ var ( externalAccountKeyTable = []byte("acme_external_account_keys") externalAccountKeyIDsByReferenceTable = []byte("acme_external_account_keyID_reference_index") externalAccountKeyIDsByProvisionerIDTable = []byte("acme_external_account_keyID_provisionerID_index") - dpopTokenTable = []byte("acme_dpop_token") - oidcTokenTable = []byte("oidc_token") + wireDpopTokenTable = []byte("wire_acme_dpop_token") + wireOidcTokenTable = []byte("wire_acme_oidc_token") ) // DB is a struct that implements the AcmeDB interface. @@ -38,11 +38,11 @@ func New(db nosqlDB.DB) (*DB, error) { challengeTable, nonceTable, orderTable, ordersByAccountIDTable, certTable, certBySerialTable, externalAccountKeyTable, externalAccountKeyIDsByReferenceTable, externalAccountKeyIDsByProvisionerIDTable, + wireDpopTokenTable, wireOidcTokenTable, } for _, b := range tables { if err := db.CreateTable(b); err != nil { - return nil, errors.Wrapf(err, "error creating table %s", - string(b)) + return nil, errors.Wrapf(err, "error creating table %s", string(b)) } } return &DB{db}, nil diff --git a/acme/db/nosql/wire.go b/acme/db/nosql/wire.go index 0dff5f42..cf8c5fa9 100644 --- a/acme/db/nosql/wire.go +++ b/acme/db/nosql/wire.go @@ -18,7 +18,7 @@ type dbDpopToken struct { // getDBDpopToken retrieves and unmarshals an DPoP type from the database. func (db *DB) getDBDpopToken(ctx context.Context, orderId string) (*dbDpopToken, error) { - b, err := db.db.Get(dpopTokenTable, []byte(orderId)) + b, err := db.db.Get(wireDpopTokenTable, []byte(orderId)) if nosql.IsErrNotFound(err) { return nil, acme.NewError(acme.ErrorMalformedType, "dpop %s not found", orderId) } else if err != nil { @@ -58,7 +58,7 @@ func (db *DB) CreateDpopToken(ctx context.Context, orderId string, dpop map[stri Content: content, CreatedAt: now, } - if err := db.save(ctx, orderId, dbDpop, nil, "dpop", dpopTokenTable); err != nil { + if err := db.save(ctx, orderId, dbDpop, nil, "dpop", wireDpopTokenTable); err != nil { return err } return nil @@ -72,7 +72,7 @@ type dbOidcToken struct { // getDBOidcToken retrieves and unmarshals an OIDC id token type from the database. func (db *DB) getDBOidcToken(ctx context.Context, orderId string) (*dbOidcToken, error) { - b, err := db.db.Get(oidcTokenTable, []byte(orderId)) + b, err := db.db.Get(wireOidcTokenTable, []byte(orderId)) if nosql.IsErrNotFound(err) { return nil, acme.NewError(acme.ErrorMalformedType, "oidc token %s not found", orderId) } else if err != nil { @@ -111,7 +111,7 @@ func (db *DB) CreateOidcToken(ctx context.Context, orderId string, idToken map[s Content: content, CreatedAt: now, } - if err := db.save(ctx, orderId, dbOidc, nil, "oidc", oidcTokenTable); err != nil { + if err := db.save(ctx, orderId, dbOidc, nil, "oidc", wireOidcTokenTable); err != nil { return err } return nil diff --git a/acme/order.go b/acme/order.go index fa345095..6e94ca6f 100644 --- a/acme/order.go +++ b/acme/order.go @@ -7,6 +7,7 @@ import ( "crypto/x509" "encoding/asn1" "encoding/json" + "fmt" "net" "net/url" "sort" @@ -204,17 +205,28 @@ func (o *Order) Finalize(ctx context.Context, db DB, csr *x509.CertificateReques // Template data data := x509util.NewTemplateData() - subject, err := o.subject(csr) - if err != nil { - return err - } - data.SetSubject(subject) + if o.containsWireIdentifiers() { + subject, err := createWireSubject(o, csr) + if err != nil { + return fmt.Errorf("failed creating Wire subject: %w", err) + } + data.SetSubject(subject) - // Inject Wire's custom challenges into the template once they have been validated - dpop, err := db.GetDpopToken(ctx, o.ID) - data.Set("Dpop", dpop) - oidc, err := db.GetOidcToken(ctx, o.ID) - data.Set("Oidc", oidc) + // Inject Wire's custom challenges into the template once they have been validated + dpop, err := db.GetDpopToken(ctx, o.ID) + if err != nil { + return fmt.Errorf("failed getting Wire DPoP token: %w", err) + } + data.Set("Dpop", dpop) + + oidc, err := db.GetOidcToken(ctx, o.ID) + if err != nil { + return fmt.Errorf("failed getting Wire OIDC token: %w", err) + } + data.Set("Oidc", oidc) + } else { + data.SetCommonName(csr.Subject.CommonName) + } // Custom sign options passed to authority.Sign var extraOptions []provisioner.SignOption @@ -309,7 +321,19 @@ func (o *Order) Finalize(ctx context.Context, db DB, csr *x509.CertificateReques return nil } -func (o *Order) subject(csr *x509.CertificateRequest) (subject x509util.Subject, err error) { +// containsWireIdentifiers checks if [Order] contains ACME +// identifiers for the WireID type. +func (o *Order) containsWireIdentifiers() bool { + for _, i := range o.Identifiers { + if i.Type == WireID { + return true + } + } + return false +} + +// createWireSubject creates the subject for an [Order] with WireID identifiers. +func createWireSubject(o *Order, csr *x509.CertificateRequest) (subject x509util.Subject, err error) { wireIDs, otherIDs := 0, 0 for _, identifier := range o.Identifiers { switch identifier.Type { @@ -335,9 +359,6 @@ func (o *Order) subject(csr *x509.CertificateRequest) (subject x509util.Subject, if !foundDisplayName { return subject, NewErrorISE("CSR must contain the display name in 2.16.840.1.113730.3.1.241 OID") } - /*if csr.Subject.CommonName != wireID.Name { - return subject, NewErrorISE("expected CN %v, found %v", wireID.Name, csr.Subject.CommonName) - }*/ if len(csr.Subject.Organization) == 0 || !strings.EqualFold(csr.Subject.Organization[0], wireID.Domain) { return subject, NewErrorISE("expected Organization [%s], found %v", wireID.Domain, csr.Subject.Organization) @@ -346,11 +367,14 @@ func (o *Order) subject(csr *x509.CertificateRequest) (subject x509util.Subject, subject.Organization = []string{wireID.Domain} wireIDs++ default: + otherIDs++ } } + if wireIDs > 0 && otherIDs > 0 || wireIDs > 1 { return subject, NewErrorISE("at most one WireID can be signed along with no other ID, found %d WireIDs and %d other IDs", wireIDs, otherIDs) } + return }