Skip to content

Commit

Permalink
fix: use 2 separate identifiers for Wire
Browse files Browse the repository at this point in the history
  • Loading branch information
beltram committed Jan 19, 2024
1 parent 7e6356e commit a3de984
Show file tree
Hide file tree
Showing 2 changed files with 58 additions and 27 deletions.
36 changes: 29 additions & 7 deletions acme/api/order.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,12 @@ func (n *NewOrderRequest) Validate() error {
if id.Value == "" {
return acme.NewError(acme.ErrorMalformedType, "permanent identifier cannot be empty")
}
case acme.WireID:
case acme.WireUser:
_, err := wire.ParseID([]byte(id.Value))
if err != nil {
return acme.WrapError(acme.ErrorMalformedType, err, "failed parsing Wire ID")
}
case acme.WireDevice:
wireID, err := wire.ParseID([]byte(id.Value))
if err != nil {
return acme.WrapError(acme.ErrorMalformedType, err, "failed parsing Wire ID")
Expand Down Expand Up @@ -273,10 +278,27 @@ func newAuthorization(ctx context.Context, az *acme.Authorization) error {
}

var target string
if az.Identifier.Type == acme.WireID {
if az.Identifier.Type == acme.WireUser {
wireOptions, err := prov.GetOptions().GetWireOptions()
if err != nil {
return acme.WrapErrorISE(err, "failed getting Wire options")
}
var targetProvider interface{ EvaluateTarget(string) (string, error) }
switch typ {
case acme.WIREOIDC01:
targetProvider = wireOptions.GetOIDCOptions()
default:
return acme.NewError(acme.ErrorMalformedType, "unsupported type %q", typ)
}

target, err = targetProvider.EvaluateTarget("")
if err != nil {
return acme.WrapError(acme.ErrorMalformedType, err, "invalid Go template registered for 'target'")
}
} else if az.Identifier.Type == acme.WireDevice {
wireID, err := wire.ParseID([]byte(az.Identifier.Value))
if err != nil {
return acme.WrapError(acme.ErrorMalformedType, err, "failed parsing WireID")
return acme.WrapError(acme.ErrorMalformedType, err, "failed parsing WireUser")
}
clientID, err := wire.ParseClientID(wireID.ClientID)
if err != nil {
Expand All @@ -288,8 +310,6 @@ func newAuthorization(ctx context.Context, az *acme.Authorization) error {
}
var targetProvider interface{ EvaluateTarget(string) (string, error) }
switch typ {
case acme.WIREOIDC01:
targetProvider = wireOptions.GetOIDCOptions()
case acme.WIREDPOP01:
targetProvider = wireOptions.GetDPOPOptions()
default:
Expand Down Expand Up @@ -440,8 +460,10 @@ func challengeTypes(az *acme.Authorization) []acme.ChallengeType {
}
case acme.PermanentIdentifier:
chTypes = []acme.ChallengeType{acme.DEVICEATTEST01}
case acme.WireID:
chTypes = []acme.ChallengeType{acme.WIREOIDC01, acme.WIREDPOP01}
case acme.WireUser:
chTypes = []acme.ChallengeType{acme.WIREOIDC01}
case acme.WireDevice:
chTypes = []acme.ChallengeType{acme.WIREDPOP01}
default:
chTypes = []acme.ChallengeType{}
}
Expand Down
49 changes: 29 additions & 20 deletions acme/order.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,10 @@ const (
// PermanentIdentifier is the ACME permanent-identifier identifier type
// defined in https://datatracker.ietf.org/doc/html/draft-bweeks-acme-device-attest-00
PermanentIdentifier IdentifierType = "permanent-identifier"
// WireID is the Wire user identifier type
WireID IdentifierType = "wireapp-id"
// WireUser is the Wire user identifier type
WireUser IdentifierType = "wireapp-user"
// WireDevice is the Wire device identifier type
WireDevice IdentifierType = "wireapp-device"
)

// Identifier encodes the type that an order pertains to.
Expand Down Expand Up @@ -322,22 +324,22 @@ func (o *Order) Finalize(ctx context.Context, db DB, csr *x509.CertificateReques
}

// containsWireIdentifiers checks if [Order] contains ACME
// identifiers for the WireID type.
// identifiers for the WireUser type.
func (o *Order) containsWireIdentifiers() bool {
for _, i := range o.Identifiers {
if i.Type == WireID {
if i.Type == WireUser || i.Type == WireDevice {
return true
}
}
return false
}

// createWireSubject creates the subject for an [Order] with WireID identifiers.
// createWireSubject creates the subject for an [Order] with WireUser identifiers.
func createWireSubject(o *Order, csr *x509.CertificateRequest) (subject x509util.Subject, err error) {
wireIDs, otherIDs := 0, 0
wireUserIDs, wireDeviceIDs, otherIDs := 0, 0, 0
for _, identifier := range o.Identifiers {
switch identifier.Type {
case WireID:
case WireUser:
wireID, err := wire.ParseID([]byte(identifier.Value))
if err != nil {
return subject, NewErrorISE("unmarshal wireID: %s", err)
Expand All @@ -357,22 +359,24 @@ func createWireSubject(o *Order, csr *x509.CertificateRequest) (subject x509util
}
}
if !foundDisplayName {
return subject, NewErrorISE("CSR must contain the display name in 2.16.840.1.113730.3.1.241 OID")
return subject, NewErrorISE("CSR must contain the display name in '2.16.840.1.113730.3.1.241' OID")
}

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)
}
subject.CommonName = wireID.Name
subject.Organization = []string{wireID.Domain}
wireIDs++
wireUserIDs++
case WireDevice:
wireDeviceIDs++
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)
if otherIDs > 0 || wireUserIDs != 1 && wireDeviceIDs != 1 {
return subject, NewErrorISE("there must only be 1 WireUser & 1 WireDevice identifiers")
}

return
Expand All @@ -385,10 +389,10 @@ func (o *Order) sans(csr *x509.CertificateRequest) ([]x509util.SubjectAlternativ
}

// order the DNS names and IP addresses, so that they can be compared against the canonicalized CSR
orderNames := make([]string, numberOfIdentifierType(DNS, o.Identifiers)+2*numberOfIdentifierType(WireID, o.Identifiers))
orderNames := make([]string, numberOfIdentifierType(DNS, o.Identifiers))
orderIPs := make([]net.IP, numberOfIdentifierType(IP, o.Identifiers))
orderPIDs := make([]string, numberOfIdentifierType(PermanentIdentifier, o.Identifiers))
tmpOrderURIs := make([]*url.URL, 2*numberOfIdentifierType(WireID, o.Identifiers))
tmpOrderURIs := make([]*url.URL, numberOfIdentifierType(WireUser, o.Identifiers)+numberOfIdentifierType(WireDevice, o.Identifiers))
indexDNS, indexIP, indexPID, indexURI := 0, 0, 0, 0
for _, n := range o.Identifiers {
switch n.Type {
Expand All @@ -401,23 +405,28 @@ func (o *Order) sans(csr *x509.CertificateRequest) ([]x509util.SubjectAlternativ
case PermanentIdentifier:
orderPIDs[indexPID] = n.Value
indexPID++
case WireID:
case WireUser:
wireID, err := wire.ParseID([]byte(n.Value))
if err != nil {
return sans, NewErrorISE("unsupported identifier value in order: %s", n.Value)
}
clientID, err := url.Parse(wireID.ClientID)
if err != nil {
return sans, NewErrorISE("clientId must be a URI: %s", wireID.ClientID)
}
tmpOrderURIs[indexURI] = clientID
indexURI++
handle, err := url.Parse(wireID.Handle)
if err != nil {
return sans, NewErrorISE("handle must be a URI: %s", wireID.Handle)
}
tmpOrderURIs[indexURI] = handle
indexURI++
case WireDevice:
wireID, err := wire.ParseID([]byte(n.Value))
if err != nil {
return sans, NewErrorISE("unsupported identifier value in order: %s", n.Value)
}
clientID, err := url.Parse(wireID.ClientID)
if err != nil {
return sans, NewErrorISE("clientId must be a URI: %s", wireID.ClientID)
}
tmpOrderURIs[indexURI] = clientID
indexURI++
default:
return sans, NewErrorISE("unsupported identifier type in order: %s", n.Type)
}
Expand Down

0 comments on commit a3de984

Please sign in to comment.