From 6fa6e1f237bc8c9e6be1dcfe976ca0043ed7f16f Mon Sep 17 00:00:00 2001
From: ale <ale@incal.net>
Date: Sat, 4 Dec 2021 16:04:51 +0000
Subject: [PATCH] Do not log unused webauthn credential

---
 server/authserver.go                          | 12 +---
 .../ldap/compositetypes/composite_types.go    | 59 ++++++++++++-------
 2 files changed, 41 insertions(+), 30 deletions(-)

diff --git a/server/authserver.go b/server/authserver.go
index 02b95f32..9b257450 100644
--- a/server/authserver.go
+++ b/server/authserver.go
@@ -548,18 +548,12 @@ func (s *Server) finishWebAuthnLogin(user *backend.User, sessionData *webauthn.S
 	wuser := newWebAuthnUser(user)
 
 	// Attempt non-legacy validation first.
-	cred, err := s.webAuthnHandler.ValidateLogin(wuser, *sessionData, parsedResponse)
+	_, err := s.webAuthnHandler.ValidateLogin(wuser, *sessionData, parsedResponse)
 	if err != nil {
-		cred, err = s.compatWebAuthnHandler.ValidateLogin(wuser, *sessionData, parsedResponse)
-		if err != nil {
-			return err
-		}
+		_, err = s.compatWebAuthnHandler.ValidateLogin(wuser, *sessionData, parsedResponse)
 	}
 
-	// What do we do with this credential?
-	log.Printf("cred: %v", cred)
-
-	return nil
+	return err
 }
 
 func checkPassword(password, hash []byte) bool {
diff --git a/vendor/git.autistici.org/ai3/go-common/ldap/compositetypes/composite_types.go b/vendor/git.autistici.org/ai3/go-common/ldap/compositetypes/composite_types.go
index 1ba73db9..25b1097f 100644
--- a/vendor/git.autistici.org/ai3/go-common/ldap/compositetypes/composite_types.go
+++ b/vendor/git.autistici.org/ai3/go-common/ldap/compositetypes/composite_types.go
@@ -106,17 +106,12 @@ func UnmarshalEncryptedKey(s string) (*EncryptedKey, error) {
 // U2FRegistration stores information on a single WebAuthN/U2F device
 // registration.
 //
-// This type supports both legacy U2F registrations, as well as newer
-// WebAuthN registrations. These have different serialization formats.
-// The legacy U2F serialized format follows part of the U2F standard
-// and just stores 64 bytes of the public key immediately followed by
-// the key handle data, with no encoding. Note that the public key
-// itself is a serialization of the elliptic curve parameters. The
-// newer serialization format is JSON, for extensibility. Marshaling
-// always happens in JSON, legacy format is read-only.
+// The public key is expected to be in raw COSE format. Note that on
+// the wire (i.e. when serialized as JSON) both the public key and the
+// key handle are base64-encoded.
 //
-// The data in U2FRegistration is still encoded, but it can be turned
-// into a usable run-time form by calling Decode().
+// It is possible to obtain a usable webauthn.Credential object at
+// run-time by calling Decode().
 type U2FRegistration struct {
 	KeyHandle []byte `json:"key_handle"`
 	PublicKey []byte `json:"public_key"`
@@ -133,6 +128,11 @@ func (r *U2FRegistration) Marshal() string {
 	return string(data)
 }
 
+const (
+	legacySerializedU2FKeySize = 65
+	minU2FKeySize              = 64
+)
+
 // UnmarshalU2FRegistration parses a U2FRegistration from its serialized format.
 func UnmarshalU2FRegistration(s string) (*U2FRegistration, error) {
 	// Try JSON first.
@@ -143,13 +143,13 @@ func UnmarshalU2FRegistration(s string) (*U2FRegistration, error) {
 
 	// Deserialize legacy format, and perform a conversion of the
 	// public key to COSE format.
-	if len(s) < 65 {
+	if len(s) < legacySerializedU2FKeySize {
 		return nil, errors.New("badly encoded u2f registration")
 	}
 	b := []byte(s)
 	return &U2FRegistration{
-		PublicKey: u2fToCOSE(b[:65]),
-		KeyHandle: b[65:],
+		PublicKey: u2fToCOSE(b[:legacySerializedU2FKeySize]),
+		KeyHandle: b[legacySerializedU2FKeySize:],
 		Legacy:    true,
 	}, nil
 }
@@ -171,6 +171,14 @@ func ParseLegacyU2FRegistrationFromStrings(keyHandle, publicKey string) (*U2FReg
 		return nil, fmt.Errorf("error decoding public key: %w", err)
 	}
 
+	// Simple sanity check for non-empty fields.
+	if len(kh) == 0 {
+		return nil, errors.New("missing key handle")
+	}
+	if len(pk) < minU2FKeySize {
+		return nil, errors.New("public key missing or too short")
+	}
+
 	return &U2FRegistration{
 		PublicKey: u2fToCOSE(pk),
 		KeyHandle: kh,
@@ -181,7 +189,7 @@ func ParseLegacyU2FRegistrationFromStrings(keyHandle, publicKey string) (*U2FReg
 // ParseU2FRegistrationFromStrings parses the U2F registration format
 // used in manual key specifications that is used by Fido2-aware
 // programs such as pamu2fcfg >= 1.0.0. Both parameters are
-// base64-encoded.
+// base64-encoded, public key should be in COSE format.
 func ParseU2FRegistrationFromStrings(keyHandle, publicKey string) (*U2FRegistration, error) {
 	kh, err := base64.StdEncoding.DecodeString(keyHandle)
 	if err != nil {
@@ -192,6 +200,14 @@ func ParseU2FRegistrationFromStrings(keyHandle, publicKey string) (*U2FRegistrat
 		return nil, fmt.Errorf("error decoding public key: %w", err)
 	}
 
+	// Simple sanity check for non-empty fields.
+	if len(kh) == 0 {
+		return nil, errors.New("missing key handle")
+	}
+	if len(pk) < minU2FKeySize {
+		return nil, errors.New("public key missing or too short")
+	}
+
 	return &U2FRegistration{
 		PublicKey: pk,
 		KeyHandle: kh,
@@ -207,17 +223,18 @@ func (r *U2FRegistration) Decode() (webauthn.Credential, error) {
 	}, nil
 }
 
+// Convert a legacy U2F public key to COSE format.
 func u2fToCOSE(pk []byte) []byte {
-	var parsed webauthncose.EC2PublicKeyData
-	parsed.KeyType = int64(webauthncose.EllipticKey)
-	parsed.Algorithm = int64(webauthncose.AlgES256)
-	parsed.XCoord = pk[1:33]
-	parsed.YCoord = pk[33:]
-	data, _ := cbor.Marshal(&parsed) // nolint: errcheck
+	var key webauthncose.EC2PublicKeyData
+	key.KeyType = int64(webauthncose.EllipticKey)
+	key.Algorithm = int64(webauthncose.AlgES256)
+	key.XCoord = pk[1:33]
+	key.YCoord = pk[33:]
+	data, _ := cbor.Marshal(&key) // nolint: errcheck
 	return data
 }
 
-// Faster, but more questionable, implementation:
+// Faster, but more questionable, implementation of the above:
 //
 // func u2fToCOSE(pk []byte) []byte {
 // 	x := pk[1:33]
-- 
GitLab