summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDamien Miller <djm@cvs.openbsd.org>2021-01-08 02:57:25 +0000
committerDamien Miller <djm@cvs.openbsd.org>2021-01-08 02:57:25 +0000
commitf2db2a7649c0e525982de42d5c7414b05bd6b8f9 (patch)
tree8be5d11f51026d8d0365f0c0a2e09d707b276106
parentdda383dd0815eb819931eb80a855a9c05de9a752 (diff)
If a signature operation on a FIDO key fails with a "incorrect PIN"
reason and no PIN was initially requested from the user, then request a PIN and retry the operation. This smoothes over a few corner cases including FIDO devices that require PINs for all hosted credentials, biometric FIDO devices that fall back to requiring PIN when reading the biometric failed, devices that don't implement reading credProtect status for downloaded keys and probably a few more cases that I haven't though of yet. ok dtucker@
-rw-r--r--usr.bin/ssh/sshconnect2.c15
1 files changed, 12 insertions, 3 deletions
diff --git a/usr.bin/ssh/sshconnect2.c b/usr.bin/ssh/sshconnect2.c
index b568b087d8d..87011733011 100644
--- a/usr.bin/ssh/sshconnect2.c
+++ b/usr.bin/ssh/sshconnect2.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: sshconnect2.c,v 1.340 2020/12/29 00:59:15 djm Exp $ */
+/* $OpenBSD: sshconnect2.c,v 1.341 2021/01/08 02:57:24 djm Exp $ */
/*
* Copyright (c) 2000 Markus Friedl. All rights reserved.
* Copyright (c) 2008 Damien Miller. All rights reserved.
@@ -1214,7 +1214,7 @@ identity_sign(struct identity *id, u_char **sigp, size_t *lenp,
const u_char *data, size_t datalen, u_int compat, const char *alg)
{
struct sshkey *sign_key = NULL, *prv = NULL;
- int r = SSH_ERR_INTERNAL_ERROR;
+ int retried = 0, r = SSH_ERR_INTERNAL_ERROR;
struct notifier_ctx *notifier = NULL;
char *fp = NULL, *pin = NULL, *prompt = NULL;
@@ -1248,6 +1248,7 @@ identity_sign(struct identity *id, u_char **sigp, size_t *lenp,
if (sshkey_is_sk(sign_key)) {
if ((sign_key->sk_flags &
SSH_SK_USER_VERIFICATION_REQD)) {
+ retry_pin:
xasprintf(&prompt, "Enter PIN for %s key %s: ",
sshkey_type(sign_key), id->filename);
pin = read_passphrase(prompt, 0);
@@ -1268,8 +1269,16 @@ identity_sign(struct identity *id, u_char **sigp, size_t *lenp,
if ((r = sshkey_sign(sign_key, sigp, lenp, data, datalen,
alg, options.sk_provider, pin, compat)) != 0) {
debug_fr(r, "sshkey_sign");
+ if (pin == NULL && !retried && sshkey_is_sk(sign_key) &&
+ r == SSH_ERR_KEY_WRONG_PASSPHRASE) {
+ notify_complete(notifier, NULL);
+ notifier = NULL;
+ retried = 1;
+ goto retry_pin;
+ }
goto out;
}
+
/*
* PKCS#11 tokens may not support all signature algorithms,
* so check what we get back.
@@ -1284,7 +1293,7 @@ identity_sign(struct identity *id, u_char **sigp, size_t *lenp,
free(prompt);
if (pin != NULL)
freezero(pin, strlen(pin));
- notify_complete(notifier, "User presence confirmed");
+ notify_complete(notifier, r == 0 ? "User presence confirmed" : NULL);
sshkey_free(prv);
return r;
}