Download raw body.
ssh-add: add no-pin flag
Hi,
Some FIDO and PKCS#11 tokens have alternate ways of entering PINs or
performing PIN-equivalent authentication, such as biometrics and on-
device PIN entry hardware.
To better support these, this adds a ssh-add -P flag to make PIN entry
optional.
ok?
commit 36b8ed7e63a3ad340f590ad846354b2f8bb1b1f1
Author: Damien Miller <djm@mindrot.org>
Date: Mon Nov 20 14:31:22 2023 +1100
Add -P flag to suppress requesting FIDO/p11 PIN
diff --git a/ssh-add.1 b/ssh-add.1
index af5f8f7..e761d21 100644
--- a/ssh-add.1
+++ b/ssh-add.1
@@ -43,7 +43,7 @@
.Nd adds private key identities to the OpenSSH authentication agent
.Sh SYNOPSIS
.Nm ssh-add
-.Op Fl CcDdKkLlNqvXx
+.Op Fl CcDdKkLlNPqvXx
.Op Fl E Ar fingerprint_hash
.Op Fl H Ar hostkey_file
.Op Fl h Ar destination_constraint
@@ -235,6 +235,11 @@ certificates added to an agent.
.It Fl Q
Query the agent for the list of protocol extensions it supports.
Note: not all agents support this query.
+.It Fl P
+When loading PKCS#11 or FIDO keys from a token, do not request a PIN.
+This will cause the operation to fail if the token requires additional
+authentication and has no other way to obtain it, such as a keypad or
+biometric reader.
.It Fl q
Be quiet after a successful operation.
.It Fl S Ar provider
diff --git a/ssh-add.c b/ssh-add.c
index 2788f7e..2fead57 100644
--- a/ssh-add.c
+++ b/ssh-add.c
@@ -452,7 +452,7 @@ add_file(int agent_fd, const char *filename, int key_only, int cert_only,
}
static int
-update_card(int agent_fd, int add, const char *id, int qflag,
+update_card(int agent_fd, int add, const char *id, int qflag, int no_pin,
int key_only, int cert_only,
struct dest_constraint **dest_constraints, size_t ndest_constraints,
struct sshkey **certs, size_t ncerts)
@@ -463,7 +463,7 @@ update_card(int agent_fd, int add, const char *id, int qflag,
if (key_only)
ncerts = 0;
- if (add) {
+ if (add && !no_pin) {
if ((pin = read_passphrase("Enter passphrase for PKCS#11: ",
RP_ALLOW_STDIN)) == NULL)
return -1;
@@ -589,20 +589,24 @@ lock_agent(int agent_fd, int lock)
}
static int
-load_resident_keys(int agent_fd, const char *skprovider, int qflag,
+load_resident_keys(int agent_fd, const char *skprovider, int qflag, int no_pin,
struct dest_constraint **dest_constraints, size_t ndest_constraints)
{
struct sshsk_resident_key **srks;
size_t nsrks, i;
struct sshkey *key;
- int r, ok = 0;
- char *fp;
+ int r, ret = -1;
+ char *fp, *pin = NULL;
- pass = read_passphrase("Enter PIN for authenticator: ", RP_ALLOW_STDIN);
- if ((r = sshsk_load_resident(skprovider, NULL, pass, 0,
- &srks, &nsrks)) != 0) {
+ if (!no_pin) {
+ pin = read_passphrase("Enter PIN for authenticator: ",
+ RP_ALLOW_STDIN);
+ }
+ if ((r = sshsk_load_resident(skprovider, NULL, pin = NULL ? "" : pin,
+ 0, &srks, &nsrks)) != 0) {
error_r(r, "Unable to load resident keys");
- return r;
+ ret = r;
+ goto out;
}
for (i = 0; i < nsrks; i++) {
key = srks[i]->key;
@@ -615,11 +619,9 @@ load_resident_keys(int agent_fd, const char *skprovider, int qflag,
error("Unable to add key %s %s",
sshkey_type(key), fp);
free(fp);
- ok = r;
+ ret = r;
continue;
}
- if (ok == 0)
- ok = 1;
if (!qflag) {
fprintf(stderr, "Resident identity added: %s %s\n",
sshkey_type(key), fp);
@@ -633,11 +635,17 @@ load_resident_keys(int agent_fd, const char *skprovider, int qflag,
}
}
free(fp);
+ if (ret == -1)
+ ret = 0;
}
sshsk_free_resident_keys(srks, nsrks);
- if (nsrks == 0)
- return SSH_ERR_KEY_NOT_FOUND;
- return ok == 1 ? 0 : ok;
+ if (nsrks == 0) {
+ fprintf(stderr, "No keys loaded from authenticator\n");
+ ret = SSH_ERR_KEY_NOT_FOUND;
+ }
+ out:
+ free(pin);
+ return ret;
}
static int
@@ -811,7 +819,7 @@ main(int argc, char **argv)
char **dest_constraint_strings = NULL, **hostkey_files = NULL;
int r, i, ch, deleting = 0, ret = 0, key_only = 0, cert_only = 0;
int do_download = 0, xflag = 0, lflag = 0, Dflag = 0;
- int Qflag = 0, qflag = 0, Tflag = 0, Nflag = 0;
+ int Qflag = 0, qflag = 0, Tflag = 0, Nflag = 0, no_pin = 0;
SyslogFacility log_facility = SYSLOG_FACILITY_AUTH;
LogLevel log_level = SYSLOG_LEVEL_INFO;
struct sshkey *k, **certs = NULL;
@@ -840,7 +848,7 @@ main(int argc, char **argv)
skprovider = getenv("SSH_SK_PROVIDER");
- while ((ch = getopt(argc, argv, "vkKlLNCcdDTxXE:e:h:H:M:m:Qqs:S:t:")) != -1) {
+ while ((ch = getopt(argc, argv, "vkKlLNPCcdDTxXE:e:h:H:M:m:Qqs:S:t:")) != -1) {
switch (ch) {
case 'v':
if (log_level == SYSLOG_LEVEL_INFO)
@@ -893,6 +901,9 @@ main(int argc, char **argv)
case 'd':
deleting = 1;
break;
+ case 'P':
+ no_pin = 1;
+ break;
case 'D':
Dflag = 1;
break;
@@ -988,7 +999,7 @@ main(int argc, char **argv)
}
debug2_f("loaded %zu certificates", ncerts);
if (update_card(agent_fd, !deleting, pkcs11provider,
- qflag, key_only, cert_only,
+ qflag, no_pin, key_only, cert_only,
dest_constraints, ndest_constraints,
certs, ncerts) == -1)
ret = 1;
@@ -1000,7 +1011,7 @@ main(int argc, char **argv)
if (do_download) {
if (skprovider == NULL)
fatal("Cannot download keys without provider");
- if (load_resident_keys(agent_fd, skprovider, qflag,
+ if (load_resident_keys(agent_fd, skprovider, qflag, no_pin,
dest_constraints, ndest_constraints) != 0)
ret = 1;
goto done;
ssh-add: add no-pin flag