Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix fallback on missing fido p1 #218

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should the Makefile version be bumped as well?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, thanks for the reminder. I will update and then land.

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
Loading