From a763690e44a22ee4fe2662cf8921eb3db8160f5a Mon Sep 17 00:00:00 2001 From: djm Date: Fri, 19 Aug 2022 06:07:47 +0000 Subject: [PATCH] attemp FIDO key signing without PIN and use the error code returned to fall back only if necessary. Avoids PIN prompts for FIDO tokens that don't require them; part of GHPR#302 --- usr.bin/ssh/sshconnect2.c | 42 +++++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 22 deletions(-) diff --git a/usr.bin/ssh/sshconnect2.c b/usr.bin/ssh/sshconnect2.c index 67f8e0309cf..56f3fe484cb 100644 --- a/usr.bin/ssh/sshconnect2.c +++ b/usr.bin/ssh/sshconnect2.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sshconnect2.c,v 1.359 2022/07/01 03:39:44 dtucker Exp $ */ +/* $OpenBSD: sshconnect2.c,v 1.360 2022/08/19 06:07:47 djm Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. * Copyright (c) 2008 Damien Miller. All rights reserved. @@ -1228,7 +1228,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 retried = 0, r = SSH_ERR_INTERNAL_ERROR; + int is_agent = 0, 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 (id->key != NULL && (id->isprivate || (id->key->flags & SSHKEY_FLAG_EXT))) { sign_key = id->key; + is_agent = 1; } else { /* Load the private key from the file. */ if ((prv = load_identity_file(id)) == NULL) @@ -1259,34 +1260,31 @@ identity_sign(struct identity *id, u_char **sigp, size_t *lenp, goto out; } sign_key = prv; - 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); - } - if ((sign_key->sk_flags & SSH_SK_USER_PRESENCE_REQD)) { - /* XXX should batch mode just skip these? */ - if ((fp = sshkey_fingerprint(sign_key, - options.fingerprint_hash, - SSH_FP_DEFAULT)) == NULL) - fatal_f("fingerprint failed"); - notifier = notify_start(options.batch_mode, - "Confirm user presence for key %s %s", - sshkey_type(sign_key), fp); - free(fp); - } - } + /* Prompt for touch for non-agent FIDO keys that request UP */ + if (!is_agent && sshkey_is_sk(sign_key) && + (sign_key->sk_flags & SSH_SK_USER_PRESENCE_REQD)) { + /* XXX should batch mode just skip these? */ + if ((fp = sshkey_fingerprint(sign_key, + options.fingerprint_hash, SSH_FP_DEFAULT)) == NULL) + fatal_f("fingerprint failed"); + notifier = notify_start(options.batch_mode, + "Confirm user presence for key %s %s", + sshkey_type(sign_key), fp); + free(fp); } 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) && + if (!retried && pin == NULL && !is_agent && + sshkey_is_sk(sign_key) && r == SSH_ERR_KEY_WRONG_PASSPHRASE) { notify_complete(notifier, NULL); notifier = NULL; + xasprintf(&prompt, "Enter PIN for %s key %s: ", + sshkey_type(sign_key), id->filename); + pin = read_passphrase(prompt, 0); retried = 1; goto retry_pin; } -- 2.20.1