export public key to environment

David Newall openssh at davidnewall.com
Wed Nov 14 12:29:35 AEDT 2018


Hello all,

Some while ago I developed a small patch for sshd, for internal 
consumption, so that, when a client uses a private key, the 
corresponding public key is exported in the environment.  I use it to 
identify which of a multitude of devices is logged in to a shared 
account, but I'm sure there are many uses to which it could be put.  
Now, I wonder whether there already was a way of achieving the same 
result.  I need to be able to identify previously unseen devices, so I 
cannot just store the public key (c.f. authorized_keys) before use.

If this patch does indeed provide a new function (could not otherwise 
achieve the desired outcome), is it something which would be welcomed 
for inclusion in the official source?  I've attached the patch so that 
you can see what's involved.

Regards,

David

-------------- next part --------------
Description: Put client's public key in environment for pubkey authentication
Author: David Newall <davidn at davidnewall.com>

diff -ru openssh-7.2p2/auth.h openssh-7.2p2.DN/auth.h
--- openssh-7.2p2/auth.h	2017-02-25 01:36:59.000000000 +1030
+++ openssh-7.2p2.DN/auth.h	2017-02-25 00:40:15.036779000 +1030
@@ -79,6 +79,7 @@
 #endif
 	Buffer		*loginmsg;
 	void		*methoddata;
+	char		*authkey;	/* client's authentication key */
 
 	struct sshkey	**prev_userkeys;
 	u_int		 nprev_userkeys;
diff -ru openssh-7.2p2/auth2-pubkey.c openssh-7.2p2.DN/auth2-pubkey.c
--- openssh-7.2p2/auth2-pubkey.c	2017-02-25 01:36:59.000000000 +1030
+++ openssh-7.2p2.DN/auth2-pubkey.c	2017-02-25 01:34:43.208779000 +1030
@@ -85,6 +85,11 @@
 	int have_sig, pktype;
 	int authenticated = 0;
 
+	if (authctxt->authkey) {
+debug("**********freeing key at %p in pid %d", authctxt->authkey, getpid());
+		free(authctxt->authkey);
+		authctxt->authkey = NULL;
+	}
 	if (!authctxt->valid) {
 		debug2("%s: disabled because of invalid user", __func__);
 		return 0;
@@ -211,8 +216,19 @@
 		auth_clear_options();
 done:
 	debug2("%s: authenticated %d pkalg %s", __func__, authenticated, pkalg);
-	if (key != NULL)
+	if (key != NULL) {
+		struct sshbuf *b = sshbuf_new();
+		if (b != NULL && sshkey_format_text(key, b) == 0) {
+			authctxt->authkey = malloc(sshbuf_len(b) + 1);
+			if (authctxt->authkey != NULL) {
+				memcpy(authctxt->authkey, sshbuf_ptr(b), sshbuf_len(b));
+				authctxt->authkey[sshbuf_len(b)] = '\0';
+debug("**********stored key at %p in pid %d", authctxt->authkey, getpid());
+			}
+		}
+		sshbuf_free(b);
 		key_free(key);
+	}
 	free(pkalg);
 	free(pkblob);
 	free(fp);
diff -ru openssh-7.2p2/monitor.c openssh-7.2p2.DN/monitor.c
--- openssh-7.2p2/monitor.c	2017-02-25 01:36:59.000000000 +1030
+++ openssh-7.2p2.DN/monitor.c	2017-02-25 01:38:39.900779000 +1030
@@ -1231,6 +1231,12 @@
 
 	debug3("%s entering", __func__);
 
+	if (authctxt->authkey) {
+debug("**********freeing key at %p in pid %d", authctxt->authkey, getpid());
+		free(authctxt->authkey);
+		authctxt->authkey = NULL;
+	}
+
 	type = buffer_get_int(m);
 	cuser = buffer_get_string(m, NULL);
 	chost = buffer_get_string(m, NULL);
@@ -1292,8 +1298,19 @@
 			break;
 		}
 	}
-	if (key != NULL)
+	if (key != NULL) {
+		struct sshbuf *b = sshbuf_new();
+		if (b != NULL && sshkey_format_text(key, b) == 0) {
+			authctxt->authkey = malloc(sshbuf_len(b) + 1);
+			if (authctxt->authkey != NULL) {
+				memcpy(authctxt->authkey, sshbuf_ptr(b), sshbuf_len(b));
+				authctxt->authkey[sshbuf_len(b)] = '\0';
+debug("**********stored key at %p in pid %d", authctxt->authkey, getpid());
+			}
+		}
+		sshbuf_free(b);
 		key_free(key);
+	}
 
 	/* clear temporarily storage (used by verify) */
 	monitor_reset_key_state();
diff -ru openssh-7.2p2/session.c openssh-7.2p2.DN/session.c
--- openssh-7.2p2/session.c	2017-02-25 01:36:59.000000000 +1030
+++ openssh-7.2p2.DN/session.c	2017-02-25 00:32:43.944779000 +1030
@@ -1334,6 +1334,10 @@
 		child_set_env(&env, &envsize, SSH_AUTHSOCKET_ENV_NAME,
 		    auth_sock_name);
 
+	if (s->authctxt->authkey)
+		child_set_env(&env, &envsize, "SSH_AUTHKEY",
+		    s->authctxt->authkey);
+
 	/* read $HOME/.ssh/environment. */
 	if (options.permit_user_env && !options.use_login) {
 		snprintf(buf, sizeof buf, "%.200s/.ssh/environment",
diff -ru openssh-7.2p2/sshkey.c openssh-7.2p2.DN/sshkey.c
--- openssh-7.2p2/sshkey.c	2017-02-25 01:36:59.000000000 +1030
+++ openssh-7.2p2.DN/sshkey.c	2017-02-25 01:22:35.072779000 +1030
@@ -1449,7 +1449,7 @@
 	return r;
 }
 
-static int
+int
 sshkey_format_text(const struct sshkey *key, struct sshbuf *b)
 {
 	int r = SSH_ERR_INTERNAL_ERROR;
diff -ru openssh-7.2p2/sshkey.h openssh-7.2p2.DN/sshkey.h
--- openssh-7.2p2/sshkey.h	2017-02-25 01:36:59.000000000 +1030
+++ openssh-7.2p2.DN/sshkey.h	2017-02-25 01:25:11.900779000 +1030
@@ -126,6 +126,7 @@
     int, u_char **retp, size_t *lenp);
 const char	*sshkey_type(const struct sshkey *);
 const char	*sshkey_cert_type(const struct sshkey *);
+int		 sshkey_format_text(const struct sshkey *key, struct sshbuf *b);
 int		 sshkey_write(const struct sshkey *, FILE *);
 int		 sshkey_read(struct sshkey *, char **);
 u_int		 sshkey_size(const struct sshkey *);


More information about the openssh-unix-dev mailing list