Accessing SSH key path using SSH_ASKPASS and passwordstore

Damien Miller djm at mindrot.org
Tue Oct 6 13:18:05 AEDT 2020


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 at 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;
 }
 


More information about the openssh-unix-dev mailing list