Skip to content

Commit

Permalink
Fix fallback on missing fido p1 (#218)
Browse files Browse the repository at this point in the history
* fixing fallback-p1
* removal of log.Fatal calls in client library
  • Loading branch information
cviecco authored Apr 13, 2024
1 parent 4080b92 commit aa3dd74
Show file tree
Hide file tree
Showing 6 changed files with 63 additions and 44 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ endif
BINARY=keymaster

# These are the values we want to pass for Version and BuildTime
VERSION=1.15.1
VERSION=1.15.2
#BUILD_TIME=`date +%FT%T%z`

# keymaster client requires special tags on linux
Expand Down
15 changes: 14 additions & 1 deletion cmd/keymaster/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,16 @@ func preConnectToHost(baseUrl string, client *http.Client, logger log.DebugLogge
logger.Debugf(1, "bad response code on pre-connect status=%d", response.StatusCode)
return err
}
logger.Debugf(3, "Success pre-connecting to: '%s'\n", baseUrl)
if response.TLS != nil {
logger.Debugf(3, "Preconnect is https")
for chainIndex, chainList := range response.TLS.VerifiedChains {
for index, cert := range chainList {
logger.Debugf(3, "Pre-connect VerifiedChain[%d]Subject[%d] = %s",
chainIndex, index, cert.Subject.String())
}
}
}
return nil
}

Expand Down Expand Up @@ -493,7 +503,10 @@ func main() {
logger.Fatal(err)
}
if *checkDevices {
u2f.CheckU2FDevices(logger)
err = u2f.CheckU2FDevices(logger)
if err != nil {
logger.Fatal(err)
}
return
}
computeUserAgent()
Expand Down
2 changes: 1 addition & 1 deletion keymaster.spec
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
Name: keymaster
Version: 1.15.1
Version: 1.15.2
Release: 1%{?dist}
Summary: Short term access certificate generator and client

Expand Down
5 changes: 2 additions & 3 deletions lib/client/twofa/twofa.go
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,7 @@ func tryFidoMFA(
err = u2f.WithDevicesDoWebAuthnAuthenticate(devices,
client, baseURL, userAgentString, logger)
if err != nil {
logger.Printf("Error doing hid webathentication err=%s", err)
logger.Debugf(1, "Error doing hid webathentication err=%s", err)
return false, err
}
return true, nil
Expand Down Expand Up @@ -297,14 +297,13 @@ func authenticateUser(
if allowU2F {
successful2fa, err = tryFidoMFA(baseURL, client, userAgentString, logger)
if err != nil {
return err
logger.Printf("Warning: fido2 configured, but Error doing Fido Auth: %s", err)
}
}
if allowTOTP && !successful2fa {
err = totp.DoTOTPAuthenticate(
client, baseURL, userAgentString, logger)
if err != nil {

return err
}
successful2fa = true
Expand Down
4 changes: 2 additions & 2 deletions lib/client/twofa/u2f/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ import (

// CheckU2FDevices checks the U2F devices and terminates the application by
// calling Fatal on the passed logger if the U2F devices cannot be read.
func CheckU2FDevices(logger log.DebugLogger) {
checkU2FDevices(logger)
func CheckU2FDevices(logger log.DebugLogger) error {
return checkU2FDevices(logger)
}

// DoU2FAuthenticate does U2F authentication
Expand Down
79 changes: 43 additions & 36 deletions lib/client/twofa/u2f/u2f.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,15 +59,15 @@ type WebAuthnAuthenticationResponse struct {
var u2fHostTestUserPresenceError u2fhost.TestOfUserPresenceRequiredError
var u2fHostBadKeyHandleError u2fhost.BadKeyHandleError

func checkU2FDevices(logger log.DebugLogger) {
func checkU2FDevices(logger log.DebugLogger) error {
// TODO: move this to initialization code, ans pass the device list to this function?
// or maybe pass the token?...
devices, err := u2fhid.Devices()
if err != nil {
logger.Fatal(err)
return err
}
if len(devices) == 0 {
logger.Fatal("no U2F tokens found")
return fmt.Errorf("no U2F tokens found")
}

// TODO: transform this into an iteration over all found devices
Expand All @@ -77,7 +77,7 @@ func checkU2FDevices(logger log.DebugLogger) {

dev, err := u2fhid.Open(d)
if err != nil {
logger.Fatal(err)
return err
}
defer dev.Close()
}
Expand All @@ -94,11 +94,10 @@ func checkU2FDevices(logger log.DebugLogger) {
logger.Printf("%+v", d2)
}
if len(devices2) == 0 {
logger.Fatal("no U2F (u2fHost) tokens found")
} else {
logger.Printf("u2fHost %d devices found", len(devices2))
return fmt.Errorf("no U2F (u2fHost) tokens found")
}

logger.Printf("u2fHost %d devices found", len(devices2))
return nil
}

func doU2FAuthenticate(
Expand All @@ -110,7 +109,7 @@ func doU2FAuthenticate(
url := baseURL + "/u2f/SignRequest"
signRequest, err := http.NewRequest("GET", url, nil)
if err != nil {
logger.Fatal(err)
return err
}
signRequest.Header.Set("User-Agent", userAgentString)
signRequestResp, err := client.Do(signRequest) // Client.Get(targetUrl)
Expand All @@ -130,7 +129,7 @@ func doU2FAuthenticate(
var webSignRequest u2f.WebSignRequest
err = json.NewDecoder(signRequestResp.Body).Decode(&webSignRequest)
if err != nil {
logger.Fatal(err)
return err
}
io.Copy(ioutil.Discard, signRequestResp.Body)
signRequestResp.Body.Close()
Expand All @@ -139,7 +138,7 @@ func doU2FAuthenticate(
// or maybe pass the token?...
devices, err := u2fhid.Devices()
if err != nil {
logger.Fatal(err)
logger.Println(err)
return err
}
if len(devices) == 0 {
Expand All @@ -153,13 +152,13 @@ func doU2FAuthenticate(
d.Manufacturer, d.Product, d.ProductID, d.VendorID)
dev, err := u2fhid.Open(d)
if err != nil {
logger.Fatal(err)
return err
}
defer dev.Close()
t := u2ftoken.NewToken(dev)
version, err := t.Version()
if err != nil {
logger.Fatal(err)
return err
}
// TODO: Maybe use Debugf()?
logger.Println("version:", version)
Expand All @@ -172,7 +171,7 @@ func doU2FAuthenticate(
err = json.NewEncoder(tokenAuthenticationBuf).Encode(
tokenAuthenticationClientData)
if err != nil {
logger.Fatal(err)
return err
}
reqSignChallenge := sha256.Sum256(tokenAuthenticationBuf.Bytes())
// TODO: update creation to silence linter
Expand All @@ -189,7 +188,8 @@ func doU2FAuthenticate(
decodedHandle, err := base64.RawURLEncoding.DecodeString(
registeredKey.KeyHandle)
if err != nil {
logger.Fatal(err)
logger.Println(err)
return err
}
keyHandle = decodedHandle
req = u2ftoken.AuthenticateRequest{
Expand Down Expand Up @@ -233,7 +233,7 @@ func doU2FAuthenticate(
}

}
logger.Fatal(err)
return err
}
rawBytes = res.RawResponse
logger.Printf("counter = %d, signature = %x",
Expand All @@ -252,7 +252,8 @@ func doU2FAuthenticate(
webSignRequestBuf := &bytes.Buffer{}
err = json.NewEncoder(webSignRequestBuf).Encode(signRequestResponse)
if err != nil {
logger.Fatal(err)
logger.Println(err)
return err
}
url = baseURL + "/u2f/SignResponse"
webSignRequest2, err := http.NewRequest("POST", url, webSignRequestBuf)
Expand Down Expand Up @@ -306,7 +307,7 @@ func checkDeviceAuthSuccess(req *u2fhost.AuthenticateRequest, device u2fhost.Dev
}
}

func authenticateHelper(req *u2fhost.AuthenticateRequest, devices []*u2fhost.HidDevice, keyHandles []string, logger log.DebugLogger) *u2fhost.AuthenticateResponse {
func authenticateHelper(req *u2fhost.AuthenticateRequest, devices []*u2fhost.HidDevice, keyHandles []string, logger log.DebugLogger) (*u2fhost.AuthenticateResponse, error) {
logger.Debugf(1, "Authenticating with request %+v", req)
openDevices := []u2fhost.Device{}
registeredDevices := make(map[u2fhost.AuthenticateRequest]u2fhost.Device)
Expand Down Expand Up @@ -382,10 +383,10 @@ func authenticateHelper(req *u2fhost.AuthenticateRequest, devices []*u2fhost.Hid
// Now we actually try to get users touch for devices that are found on the
// device list
if len(openDevices) == 0 {
logger.Fatalf("Failed to find any devices")
return nil, fmt.Errorf("Failed to find any devices")
}
if len(registeredDevices) == 0 {
logger.Fatalf("No registered devices found")
return nil, fmt.Errorf("No registered devices found")
}
prompted := false
timeout := time.After(time.Second * 25)
Expand All @@ -396,13 +397,13 @@ func authenticateHelper(req *u2fhost.AuthenticateRequest, devices []*u2fhost.Hid
select {
case <-timeout:
fmt.Println("Failed to get authentication response after 25 seconds")
return nil
return nil, fmt.Errorf("Authentication timeout")
case <-interval.C:
for handleReq, device := range registeredDevices {
response, err := device.Authenticate(&handleReq)
if err == nil {
logger.Debugf(1, "device.Authenticate retured non error %s", err)
return response
return response, nil
} else if err.Error() == u2fHostTestUserPresenceError.Error() && !prompted {
logger.Printf("\nTouch the flashing U2F device to authenticate...")
prompted = true
Expand All @@ -412,7 +413,7 @@ func authenticateHelper(req *u2fhost.AuthenticateRequest, devices []*u2fhost.Hid
}
}
}
return nil
return nil, fmt.Errorf("impossible Error")
}

// This ensures the hostname matches...at this moment we do NOT check port number
Expand Down Expand Up @@ -449,7 +450,7 @@ func withDevicesDoU2FAuthenticate(
url := baseURL + "/u2f/SignRequest"
signRequest, err := http.NewRequest("GET", url, nil)
if err != nil {
logger.Fatal(err)
return err
}
signRequest.Header.Set("User-Agent", userAgentString)
signRequestResp, err := client.Do(signRequest) // Client.Get(targetUrl)
Expand All @@ -469,7 +470,7 @@ func withDevicesDoU2FAuthenticate(
var webSignRequest u2f.WebSignRequest
err = json.NewDecoder(signRequestResp.Body).Decode(&webSignRequest)
if err != nil {
logger.Fatal(err)
return err
}
io.Copy(ioutil.Discard, signRequestResp.Body)
signRequestResp.Body.Close()
Expand All @@ -485,9 +486,12 @@ func withDevicesDoU2FAuthenticate(
Facet: webSignRequest.AppID, //TODO: FIX this is actually Provided by client, so extract from baseURL
KeyHandle: webSignRequest.RegisteredKeys[0].KeyHandle, // TODO we should actually iterate over this?
}
deviceResponse := authenticateHelper(&req, devices, keyHandles, logger)
deviceResponse, err := authenticateHelper(&req, devices, keyHandles, logger)
if err != nil {
return err
}
if deviceResponse == nil {
logger.Fatal("nil response from device?")
return fmt.Errorf("nil response from device?")
}
logger.Debugf(1, "signResponse authenticateHelper done")

Expand All @@ -496,7 +500,7 @@ func withDevicesDoU2FAuthenticate(
webSignRequestBuf := &bytes.Buffer{}
err = json.NewEncoder(webSignRequestBuf).Encode(deviceResponse)
if err != nil {
logger.Fatal(err)
return err
}
url = baseURL + "/u2f/SignResponse"
webSignRequest2, err := http.NewRequest("POST", url, webSignRequestBuf)
Expand Down Expand Up @@ -534,7 +538,7 @@ func withDevicesDoWebAuthnAuthenticate(
targetURL := baseURL + "/webauthn/AuthBegin/" // TODO: this should be grabbed from the webauthn definition as a const
signRequest, err := http.NewRequest("GET", targetURL, nil)
if err != nil {
logger.Fatal(err)
return err
}
signRequest.Header.Set("User-Agent", userAgentString)
signRequestResp, err := client.Do(signRequest) // Client.Get(targetUrl)
Expand All @@ -553,7 +557,7 @@ func withDevicesDoWebAuthnAuthenticate(
var credentialAssertion protocol.CredentialAssertion
err = json.NewDecoder(signRequestResp.Body).Decode(&credentialAssertion)
if err != nil {
logger.Fatal(err)
return err
}
io.Copy(ioutil.Discard, signRequestResp.Body)
signRequestResp.Body.Close()
Expand Down Expand Up @@ -595,9 +599,12 @@ func withDevicesDoWebAuthnAuthenticate(
WebAuthn: true,
}

deviceResponse := authenticateHelper(&req, devices, keyHandles, logger)
deviceResponse, err := authenticateHelper(&req, devices, keyHandles, logger)
if err != nil {
return err
}
if deviceResponse == nil {
logger.Fatal("nil response from device?")
return fmt.Errorf("nil response from device?")
}
logger.Debugf(2, "signResponse authenticateHelper done")

Expand All @@ -616,11 +623,11 @@ func withDevicesDoWebAuthnAuthenticate(
var clientData ClientData
clientDataBytes, err := base64.RawURLEncoding.DecodeString(deviceResponse.ClientData)
if err != nil {
logger.Fatal("Cant base64 decode ClientData")
return fmt.Errorf("Cant base64 decode ClientData")
}
err = json.Unmarshal(clientDataBytes, &clientData)
if err != nil {
logger.Fatal("unmarshall clientData")
return fmt.Errorf("unmarshall clientData")
}
logger.Debugf(2, "clientData =%+v", clientData)
if clientData.Typ == clientDataAuthenticationTypeValue {
Expand All @@ -629,7 +636,7 @@ func withDevicesDoWebAuthnAuthenticate(
webSignRequestBuf := &bytes.Buffer{}
err = json.NewEncoder(webSignRequestBuf).Encode(deviceResponse)
if err != nil {
logger.Fatal(err)
return err
}
targetURL = baseURL + "/u2f/SignResponse"
webSignRequest2, err := http.NewRequest("POST", targetURL, webSignRequestBuf)
Expand Down Expand Up @@ -668,7 +675,7 @@ func withDevicesDoWebAuthnAuthenticate(
// Now we write the output data:
responseBytes, err := json.Marshal(webResponse)
if err != nil {
logger.Fatal(err)
return err
}
logger.Debugf(3, "responseBytes=%s", string(responseBytes))
webSignRequestBuf := bytes.NewReader(responseBytes)
Expand Down

0 comments on commit aa3dd74

Please sign in to comment.