From 8f943a50d63e73c5b544b66c370062a093cd1464 Mon Sep 17 00:00:00 2001 From: Alan Parra Date: Tue, 30 Aug 2022 16:57:03 -0300 Subject: [PATCH 1/2] Simulate Yubikey4 UP=false behavior --- lib/auth/webauthncli/fido2_test.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/lib/auth/webauthncli/fido2_test.go b/lib/auth/webauthncli/fido2_test.go index 5381493ae2475..4afb465249b1a 100644 --- a/lib/auth/webauthncli/fido2_test.go +++ b/lib/auth/webauthncli/fido2_test.go @@ -1967,6 +1967,11 @@ func (f *fakeFIDO2Device) Assertion( // "base" credential. Only add an assertion if explicitly requested. if _, ok := credIDs[string(f.key.KeyHandle)]; ok { + // Simulate Yubikey4 and require UP, even if UP==false is set. + if f.u2fOnly && opts.UP == libfido2.False { + return nil, libfido2.ErrUserPresenceRequired + } + assertions = append(assertions, &libfido2.Assertion{ AuthDataCBOR: assertionAuthDataCBOR, Sig: assertionSig, From c3014d5a960f013a1699ef48f4a57b5059db8564 Mon Sep 17 00:00:00 2001 From: Alan Parra Date: Tue, 30 Aug 2022 16:52:29 -0300 Subject: [PATCH 2/2] Avoid wrongly filtering Yubikey4 devices --- lib/auth/webauthncli/fido2.go | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/lib/auth/webauthncli/fido2.go b/lib/auth/webauthncli/fido2.go index 2d45501e39f1e..9fed2377c9c0b 100644 --- a/lib/auth/webauthncli/fido2.go +++ b/lib/auth/webauthncli/fido2.go @@ -145,7 +145,7 @@ func fido2Login( // Does the device have a suitable credential? const pin = "" - actualRPID, err := discoverRPID(dev, pin, rpID, appID, allowedCreds) + actualRPID, err := discoverRPID(dev, info, pin, rpID, appID, allowedCreds) if err != nil { log.Debugf("FIDO2: Device %v: filtered due to lack of allowed credential", info.path) return false, nil @@ -237,7 +237,7 @@ func fido2Login( }, actualUser, nil } -func discoverRPID(dev FIDODevice, pin, rpID, appID string, allowedCreds [][]byte) (string, error) { +func discoverRPID(dev FIDODevice, info *deviceInfo, pin, rpID, appID string, allowedCreds [][]byte) (string, error) { // The actual hash is not necessary here. const cdh = "00000000000000000000000000000000" @@ -248,8 +248,15 @@ func discoverRPID(dev FIDODevice, pin, rpID, appID string, allowedCreds [][]byte if id == "" { continue } - if _, err := dev.Assertion(id, []byte(cdh), allowedCreds, pin, opts); err == nil { + switch _, err := dev.Assertion(id, []byte(cdh), allowedCreds, pin, opts); { + // Yubikey4 returns ErrUserPresenceRequired if the credential exists, + // despite the UP=false opts above. + case err == nil, errors.Is(err, libfido2.ErrUserPresenceRequired): return id, nil + case errors.Is(err, libfido2.ErrNoCredentials): + // Device not registered for RPID=id, keep trying. + default: + log.WithError(err).Debugf("FIDO2: Device %v: attempt RPID = %v", info.path, id) } } return "", libfido2.ErrNoCredentials