On Mon, 5 Oct 2020, John Heatherington wrote: > Hello, > > With the introduction of SSH_ASKPASS_REQUIRE in version 8.4, I've set > up a script for SSH_ASKPASS to query my local passwordstore > (https://www.passwordstore.org/) vault to retrieve the password for a > given key. This works for ssh-add as well as ssh (configured with > AddKeysToAgent set to 'yes'). My workflow effectively transforms into > entering the password for the GPG key used to encrypt my vault for any > given key. It works especially well now that I don't have to alter > DISPLAY and confuse gpg's pin input inference. Thanks for that > enhancement! > > The tricky part here is the way I have to figure out which key is > being unlocked. I was initially only working with ssh-add, so it > seemed trivial to just deal with the input to a script acting as a > wrapper and feed that to the askpass script as an environment > variable. When I realized I could also take advantage of > AddKeysToAgent and simply call ssh, I had to change my strategy given > that the path to the key being unlocked does not appear to get passed > separately to my script; rather it's just given a prompt that happens > to contain the path to the key. Using this knowledge I just have my > script infer the path using sed. > > This strategy works, but I noticed that when you call ssh (with > AddKeysToAgent set to 'yes') vs ssh-add, the prompts are slightly > different: > > $ ssh user@host > Enter passphrase for key '/home/user/.ssh/id_ed25519_somekey': > > $ ssh-add /home/user/.ssh/id_ed25519_somekey > Enter passphrase for /home/user/.ssh/id_ed25519_somekey: > > Notice the single quotes around the path in the prompt when calling > ssh. I'm not sure if that's a bug with regard to consistency. I was > able to modify the regex to account for this difference, but overall I > wondered if this couldn't be improved. For my usage, it would be great > to receive the path to the key as another askpass argument. > Alternatively I could also envision accessing this information as an > environment variable. Unfortunately the askpass convention is pretty old and baked-in to too many places to change radically. OTOH we could certainly harmonise the prompts, e.g. diff --git a/ssh-add.c b/ssh-add.c index 0ce989f..2a0b207 100644 --- a/ssh-add.c +++ b/ssh-add.c @@ -228,8 +228,7 @@ add_file(int agent_fd, const char *filename, int key_only, int qflag, const char *skprovider) { struct sshkey *private, *cert; - char *comment = NULL; - char msg[1024], *certpath = NULL; + char *comment = NULL, *msg = NULL, *certpath = NULL; int r, fd, ret = -1; size_t i; u_int32_t left; @@ -282,7 +281,8 @@ add_file(int agent_fd, const char *filename, int key_only, int qflag, if (private == NULL) { /* clear passphrase since it did not work */ clear_pass(); - snprintf(msg, sizeof msg, "Enter passphrase for %s%s: ", + free(msg); + xasprintf(&msg, "Enter passphrase for key '%s%s': ", filename, confirm ? " (will confirm each use)" : ""); for (;;) { pass = read_passphrase(msg, RP_ALLOW_STDIN); @@ -298,11 +298,13 @@ add_file(int agent_fd, const char *filename, int key_only, int qflag, fail_load: clear_pass(); sshbuf_free(keyblob); + free(msg); return -1; } clear_pass(); - snprintf(msg, sizeof msg, - "Bad passphrase, try again for %s%s: ", filename, + free(msg); + xasprintf(&msg, + "Bad passphrase, try again for '%s%s': ", filename, confirm ? " (will confirm each use)" : ""); } } @@ -435,6 +437,7 @@ add_file(int agent_fd, const char *filename, int key_only, int qflag, free(certpath); free(comment); sshkey_free(private); + free(msg); return ret; } diff --git a/sshconnect2.c b/sshconnect2.c index 2aca328..149eb11 100644 --- a/sshconnect2.c +++ b/sshconnect2.c @@ -1503,7 +1503,7 @@ static struct sshkey * load_identity_file(Identity *id) { struct sshkey *private = NULL; - char prompt[300], *passphrase, *comment; + char *prompt = NULL, *passphrase, *comment; int r, quit = 0, i; struct stat st; @@ -1512,8 +1512,7 @@ load_identity_file(Identity *id) id->filename, strerror(errno)); return NULL; } - snprintf(prompt, sizeof prompt, - "Enter passphrase for key '%.100s': ", id->filename); + xasprintf(&prompt, "Enter passphrase for key '%s': ", id->filename); for (i = 0; i <= options.number_of_password_prompts; i++) { if (i == 0) passphrase = ""; @@ -1568,6 +1567,7 @@ load_identity_file(Identity *id) if (private != NULL || quit) break; } + free(prompt); return private; } _______________________________________________ openssh-unix-dev mailing list openssh-unix-dev@xxxxxxxxxxx https://lists.mindrot.org/mailman/listinfo/openssh-unix-dev