From ba36c60178a19761035f836d0842164a50d1ec65 Mon Sep 17 00:00:00 2001 From: Sebastian Kurfuerst Date: Tue, 23 Nov 2021 15:39:54 +0100 Subject: [PATCH] FEATURE: re-add "Save to Keychain" on OSX --- go.mod | 7 ++++++- go.sum | 12 ++++++++++++ prompt_darwin.go | 26 ++++++++++++++++++++++++-- 3 files changed, 42 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 5aca5df..a230bcf 100644 --- a/go.mod +++ b/go.mod @@ -9,4 +9,9 @@ require ( golang.org/x/term v0.0.0-20201210144234-2321bbc49cbf ) -require golang.org/x/sys v0.0.0-20210819135213-f52c844e1c1c // indirect +require ( + github.com/danieljoos/wincred v1.1.0 // indirect + github.com/godbus/dbus/v5 v5.0.3 // indirect + github.com/zalando/go-keyring v0.1.1 // indirect + golang.org/x/sys v0.0.0-20210819135213-f52c844e1c1c // indirect +) diff --git a/go.sum b/go.sum index 7eb9c2e..fe95628 100644 --- a/go.sum +++ b/go.sum @@ -1,7 +1,17 @@ +github.com/danieljoos/wincred v1.1.0 h1:3RNcEpBg4IhIChZdFRSdlQt1QjCp1sMAPIrOnm7Yf8g= +github.com/danieljoos/wincred v1.1.0/go.mod h1:XYlo+eRTsVA9aHGp7NGjFkPla4m+DCL7hqDjlFjiygg= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/go-piv/piv-go v1.9.0 h1:P6j2gjfP7zO7T3nCk/jwCgsvFRwB8shEqAJ4q85jgXc= github.com/go-piv/piv-go v1.9.0/go.mod h1:NZ2zmjVkfFaL/CF8cVQ/pXdXtuj110zEKGdJM6fJZZM= +github.com/godbus/dbus/v5 v5.0.3 h1:ZqHaoEF7TBzh4jzPmqVhE/5A1z9of6orkAe5uHoAeME= +github.com/godbus/dbus/v5 v5.0.3/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/gopasspw/pinentry v0.0.3-0.20211111080829-f73e4f2a12d3 h1:+zdLxUTwYgq/TstQIB0OyGkJBKARyRGqiuJ7wkkQC3M= github.com/gopasspw/pinentry v0.0.3-0.20211111080829-f73e4f2a12d3/go.mod h1:lR1WuNI96rXXBCgM601Ima3acnX3ZSPthIAuG6lHa68= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= +github.com/zalando/go-keyring v0.1.1 h1:w2V9lcx/Uj4l+dzAf1m9s+DJ1O8ROkEHnynonHjTcYE= +github.com/zalando/go-keyring v0.1.1/go.mod h1:OIC+OZ28XbmwFxU/Rp9V7eKzZjamBJwRzC8UFJH9+L8= golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b h1:7mWr3k41Qtv8XlltBkDkl8LoP3mpSgBW8BUoxtEdbXg= golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= @@ -13,3 +23,5 @@ golang.org/x/term v0.0.0-20201210144234-2321bbc49cbf h1:MZ2shdL+ZM/XzY3ZGOnh4Nlp golang.org/x/term v0.0.0-20201210144234-2321bbc49cbf/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= diff --git a/prompt_darwin.go b/prompt_darwin.go index 06311c1..ea0c774 100644 --- a/prompt_darwin.go +++ b/prompt_darwin.go @@ -10,6 +10,7 @@ import ( "bytes" "encoding/json" "fmt" + "github.com/zalando/go-keyring" "os/exec" "text/template" ) @@ -23,13 +24,27 @@ app.displayDialog( "Please enter your PIN:", { defaultAnswer: "", withTitle: "yubikey-agent PIN prompt", - buttons: ["Cancel", "OK"], + buttons: ["Cancel", "OK", "OK and save to keychain"], defaultButton: "OK", cancelButton: "Cancel", hiddenAnswer: true, })`)) +var keychainServiceName = "yubikey-agent" + func getPIN(serial uint32, retries int) (string, error) { + keychainUserName := fmt.Sprintf("yubikey-agent-%d", serial) + if retries >= 3 { + // get password + secret, err := keyring.Get(keychainServiceName, keychainUserName) + if err != nil && err != keyring.ErrNotFound { + return "", err + } + if err == nil { + return secret, nil + } + } + script := new(bytes.Buffer) if err := scriptTemplate.Execute(script, map[string]interface{}{ "Serial": serial, "Tries": retries, @@ -44,10 +59,17 @@ func getPIN(serial uint32, retries int) (string, error) { return "", fmt.Errorf("failed to execute osascript: %v", err) } var x struct { - PIN string `json:"textReturned"` + PIN string `json:"textReturned"` + PressedButtonLabel string `json:"buttonReturned"` } if err := json.Unmarshal(out, &x); err != nil { return "", fmt.Errorf("failed to parse osascript output: %v", err) } + if x.PressedButtonLabel == "OK and save to keychain" { + err := keyring.Set(keychainServiceName, keychainUserName, x.PIN) + if err != nil { + return "", err + } + } return x.PIN, nil }