From 3f861dc328753e3787ca5fe91cc69ca865991252 Mon Sep 17 00:00:00 2001 From: Ari Palo Date: Fri, 1 Apr 2022 07:21:49 +0300 Subject: [PATCH] feat: IsAvailable --- oath.go | 18 +++++++++++++++--- ykman.go | 5 +++-- ykman_test.go | 24 ++++++++++++++++++------ 3 files changed, 36 insertions(+), 11 deletions(-) diff --git a/oath.go b/oath.go index 4ae57b6..2543fde 100644 --- a/oath.go +++ b/oath.go @@ -34,12 +34,24 @@ func (oa *OathAccounts) GetSerial() string { return oa.serial } +// IsAvailable checks whether the Yubikey device is connected & available +func (oa *OathAccounts) IsAvailable() bool { + queryOptions := ykmanOptions{ + serial: oa.serial, + password: "", + args: []string{"info"}, + } + + _, err := executeYkman(oa.ctx, queryOptions) + return err == ErrOathAccountPasswordProtected +} + // IsPasswordProtected checks whether the OATH application is password protected func (oa *OathAccounts) IsPasswordProtected() bool { queryOptions := ykmanOptions{ serial: oa.serial, password: "", - args: []string{"list"}, + args: []string{"oath", "accounts", "list"}, } _, err := executeYkman(oa.ctx, queryOptions) @@ -80,7 +92,7 @@ func (oa *OathAccounts) List() ([]string, error) { queryOptions := ykmanOptions{ serial: oa.serial, password: oa.password, - args: []string{"list"}, + args: []string{"oath", "accounts", "list"}, } oa.ensurePrompt() @@ -99,7 +111,7 @@ func (oa *OathAccounts) Code(account string) (string, error) { queryOptions := ykmanOptions{ serial: oa.serial, password: oa.password, - args: []string{"code", "--single", account}, + args: []string{"oath", "accounts", "code", "--single", account}, } oa.ensurePrompt() diff --git a/ykman.go b/ykman.go index 3843e15..1ad76cf 100644 --- a/ykman.go +++ b/ykman.go @@ -69,8 +69,6 @@ func defineYkmanArgs(options ykmanOptions) []string { args = append(args, "--device", options.serial) } - // setup oath application arguments - args = append(args, "oath", "accounts") args = append(args, options.args...) return args @@ -103,6 +101,9 @@ func processYkmanErrors(err error, outputStderr string, password string) error { if strings.Contains(outputStderr, "Failed connecting to the YubiKey") { return ErrDeviceNotFound } + if strings.Contains(outputStderr, "Failed to open device for communication") { + return ErrDeviceNotFound + } // check for yubikey device removal if strings.Contains(outputStderr, "Failed to transmit with protocol") { diff --git a/ykman_test.go b/ykman_test.go index 79239b8..ef2f713 100644 --- a/ykman_test.go +++ b/ykman_test.go @@ -17,28 +17,33 @@ func TestDefineYkmanArgs(t *testing.T) { received []string }{ { - name: "empty options", - input: ykmanOptions{}, + name: "defaults", + input: ykmanOptions{args: []string{"oath", "accounts"}}, received: []string{"oath", "accounts"}, }, + { + name: "info", + input: ykmanOptions{args: []string{"info"}}, + received: []string{"info"}, + }, { name: "with serial", - input: ykmanOptions{serial: "12345678"}, + input: ykmanOptions{serial: "12345678", args: []string{"oath", "accounts"}}, received: []string{"--device", "12345678", "oath", "accounts"}, }, { name: "list accounts", - input: ykmanOptions{args: []string{"list"}}, + input: ykmanOptions{args: []string{"oath", "accounts", "list"}}, received: []string{"oath", "accounts", "list"}, }, { name: "code for account", - input: ykmanOptions{args: []string{"code", "--single", "Amazon Web Services:john.doe@example"}}, + input: ykmanOptions{args: []string{"oath", "accounts", "code", "--single", "Amazon Web Services:john.doe@example"}}, received: []string{"oath", "accounts", "code", "--single", "Amazon Web Services:john.doe@example"}, }, { name: "code for account with all options", - input: ykmanOptions{serial: "12345678", args: []string{"code", "--single", "Amazon Web Services:john.doe@example"}}, + input: ykmanOptions{serial: "12345678", args: []string{"oath", "accounts", "code", "--single", "Amazon Web Services:john.doe@example"}}, received: []string{"--device", "12345678", "oath", "accounts", "code", "--single", "Amazon Web Services:john.doe@example"}, }, } @@ -83,6 +88,13 @@ func TestProcessYkmanErrors(t *testing.T) { password: "", received: ErrDeviceNotFound, }, + { + name: "yubikey not found", + err: genericErr, + outputStderr: "Failed to open device for communication", + password: "", + received: ErrDeviceNotFound, + }, { name: "yubikey removed while in-use", err: genericErr,