[openssh-commits] [openssh] 03/17: upstream: ssh client side of binding

git+noreply at mindrot.org git+noreply at mindrot.org
Mon Dec 20 09:28:28 AEDT 2021


This is an automated email from the git hooks/post-receive script.

djm pushed a commit to branch master
in repository openssh.

commit e9497ecf73f3c16667288bce48d4e3d7e746fea1
Author: djm at openbsd.org <djm at openbsd.org>
Date:   Sun Dec 19 22:08:48 2021 +0000

    upstream: ssh client side of binding
    
    send session ID, hostkey, signature and a flag indicating whether the
    agent connection is being forwarded to ssh agent each time a connection
    is opened via a new "session-bind at openssh.com" agent extension.
    
    ok markus@
    
    OpenBSD-Commit-ID: 2f154844fe13167d3ab063f830d7455fcaa99135
---
 authfd.c      | 31 ++++++++++++++++++++++++++++++-
 authfd.h      | 11 ++++++++++-
 clientloop.c  |  8 +++++++-
 sshconnect2.c | 47 +++++++++++++++++++++++++++++++++++------------
 4 files changed, 82 insertions(+), 15 deletions(-)

diff --git a/authfd.c b/authfd.c
index 9f092f7c..df5533ac 100644
--- a/authfd.c
+++ b/authfd.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: authfd.c,v 1.127 2021/01/26 00:46:17 djm Exp $ */
+/* $OpenBSD: authfd.c,v 1.128 2021/12/19 22:08:48 djm Exp $ */
 /*
  * Author: Tatu Ylonen <ylo at cs.hut.fi>
  * Copyright (c) 1995 Tatu Ylonen <ylo at cs.hut.fi>, Espoo, Finland
@@ -650,3 +650,32 @@ ssh_remove_all_identities(int sock, int version)
 	sshbuf_free(msg);
 	return r;
 }
+
+/* Binds a session ID to a hostkey via the initial KEX signature. */
+int
+ssh_agent_bind_hostkey(int sock, const struct sshkey *key,
+    const struct sshbuf *session_id, const struct sshbuf *signature,
+    int forwarding)
+{
+	struct sshbuf *msg;
+	int r;
+
+	if (key == NULL || session_id == NULL || signature == NULL)
+		return SSH_ERR_INVALID_ARGUMENT;
+	if ((msg = sshbuf_new()) == NULL)
+		return SSH_ERR_ALLOC_FAIL;
+	if ((r = sshbuf_put_u8(msg, SSH_AGENTC_EXTENSION)) != 0 ||
+	    (r = sshbuf_put_cstring(msg, "session-bind at openssh.com")) != 0 ||
+	    (r = sshkey_puts(key, msg)) != 0 ||
+	    (r = sshbuf_put_stringb(msg, session_id)) != 0 ||
+	    (r = sshbuf_put_stringb(msg, signature)) != 0 ||
+	    (r = sshbuf_put_u8(msg, forwarding ? 1 : 0)) != 0)
+		goto out;
+	if ((r = ssh_request_reply_decode(sock, msg)) != 0)
+		goto out;
+	/* success */
+	r = 0;
+ out:
+	sshbuf_free(msg);
+	return r;
+}
diff --git a/authfd.h b/authfd.h
index 4fbf82f8..fe1ed8a1 100644
--- a/authfd.h
+++ b/authfd.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: authfd.h,v 1.49 2020/06/26 05:03:36 djm Exp $ */
+/* $OpenBSD: authfd.h,v 1.50 2021/12/19 22:08:48 djm Exp $ */
 
 /*
  * Author: Tatu Ylonen <ylo at cs.hut.fi>
@@ -16,6 +16,8 @@
 #ifndef AUTHFD_H
 #define AUTHFD_H
 
+struct sshbuf;
+
 /* List of identities returned by ssh_fetch_identitylist() */
 struct ssh_identitylist {
 	size_t nkeys;
@@ -43,6 +45,10 @@ int	ssh_agent_sign(int sock, const struct sshkey *key,
 	    u_char **sigp, size_t *lenp,
 	    const u_char *data, size_t datalen, const char *alg, u_int compat);
 
+int	ssh_agent_bind_hostkey(int sock, const struct sshkey *key,
+    const struct sshbuf *session_id, const struct sshbuf *signature,
+    int forwarding);
+
 /* Messages for the authentication agent connection. */
 #define SSH_AGENTC_REQUEST_RSA_IDENTITIES	1
 #define SSH_AGENT_RSA_IDENTITIES_ANSWER		2
@@ -76,6 +82,9 @@ int	ssh_agent_sign(int sock, const struct sshkey *key,
 #define SSH2_AGENTC_ADD_ID_CONSTRAINED		25
 #define SSH_AGENTC_ADD_SMARTCARD_KEY_CONSTRAINED 26
 
+/* generic extension mechanism */
+#define SSH_AGENTC_EXTENSION			27
+
 #define	SSH_AGENT_CONSTRAIN_LIFETIME		1
 #define	SSH_AGENT_CONSTRAIN_CONFIRM		2
 #define	SSH_AGENT_CONSTRAIN_MAXSIGN		3
diff --git a/clientloop.c b/clientloop.c
index 147dfd21..7652b35a 100644
--- a/clientloop.c
+++ b/clientloop.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: clientloop.c,v 1.371 2021/11/18 21:32:11 djm Exp $ */
+/* $OpenBSD: clientloop.c,v 1.372 2021/12/19 22:08:48 djm Exp $ */
 /*
  * Author: Tatu Ylonen <ylo at cs.hut.fi>
  * Copyright (c) 1995 Tatu Ylonen <ylo at cs.hut.fi>, Espoo, Finland
@@ -1597,6 +1597,12 @@ client_request_agent(struct ssh *ssh, const char *request_type, int rchan)
 			debug_fr(r, "ssh_get_authentication_socket");
 		return NULL;
 	}
+	if ((r = ssh_agent_bind_hostkey(sock, ssh->kex->initial_hostkey,
+	    ssh->kex->session_id, ssh->kex->initial_sig, 1)) == 0)
+		debug_f("bound agent to hostkey");
+	else
+		debug2_fr(r, "ssh_agent_bind_hostkey");
+
 	c = channel_new(ssh, "authentication agent connection",
 	    SSH_CHANNEL_OPEN, sock, sock, -1,
 	    CHAN_X11_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, 0,
diff --git a/sshconnect2.c b/sshconnect2.c
index fea50fab..672938a3 100644
--- a/sshconnect2.c
+++ b/sshconnect2.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: sshconnect2.c,v 1.351 2021/07/23 05:24:02 djm Exp $ */
+/* $OpenBSD: sshconnect2.c,v 1.352 2021/12/19 22:08:48 djm Exp $ */
 /*
  * Copyright (c) 2000 Markus Friedl.  All rights reserved.
  * Copyright (c) 2008 Damien Miller.  All rights reserved.
@@ -391,7 +391,7 @@ void	userauth(struct ssh *, char *);
 
 static void pubkey_cleanup(struct ssh *);
 static int sign_and_send_pubkey(struct ssh *ssh, Identity *);
-static void pubkey_prepare(Authctxt *);
+static void pubkey_prepare(struct ssh *, Authctxt *);
 static void pubkey_reset(Authctxt *);
 static struct sshkey *load_identity_file(Identity *);
 
@@ -465,7 +465,7 @@ ssh_userauth2(struct ssh *ssh, const char *local_user,
 	authctxt.mech_tried = 0;
 #endif
 	authctxt.agent_fd = -1;
-	pubkey_prepare(&authctxt);
+	pubkey_prepare(ssh, &authctxt);
 	if (authctxt.method == NULL) {
 		fatal_f("internal error: cannot send userauth none request");
 	}
@@ -1631,6 +1631,36 @@ key_type_allowed_by_config(struct sshkey *key)
 	return 0;
 }
 
+/* obtain a list of keys from the agent */
+static int
+get_agent_identities(struct ssh *ssh, int *agent_fdp,
+    struct ssh_identitylist **idlistp)
+{
+	int r, agent_fd;
+	struct ssh_identitylist *idlist;
+
+	if ((r = ssh_get_authentication_socket(&agent_fd)) != 0) {
+		if (r != SSH_ERR_AGENT_NOT_PRESENT)
+			debug_fr(r, "ssh_get_authentication_socket");
+		return r;
+	}
+	if ((r = ssh_agent_bind_hostkey(agent_fd, ssh->kex->initial_hostkey,
+	    ssh->kex->session_id, ssh->kex->initial_sig, 0)) == 0)
+		debug_f("bound agent to hostkey");
+	else
+		debug2_fr(r, "ssh_agent_bind_hostkey");
+
+	if ((r = ssh_fetch_identitylist(agent_fd, &idlist)) != 0) {
+		debug_fr(r, "ssh_fetch_identitylist");
+		close(agent_fd);
+		return r;
+	}
+	/* success */
+	*agent_fdp = agent_fd;
+	*idlistp = idlist;
+	debug_f("agent returned %zu keys", idlist->nkeys);
+	return 0;
+}
 
 /*
  * try keys in the following order:
@@ -1641,7 +1671,7 @@ key_type_allowed_by_config(struct sshkey *key)
  *	5. keys that are only listed in the config file
  */
 static void
-pubkey_prepare(Authctxt *authctxt)
+pubkey_prepare(struct ssh *ssh, Authctxt *authctxt)
 {
 	struct identity *id, *id2, *tmp;
 	struct idlist agent, files, *preferred;
@@ -1703,14 +1733,7 @@ pubkey_prepare(Authctxt *authctxt)
 		TAILQ_INSERT_TAIL(preferred, id, next);
 	}
 	/* list of keys supported by the agent */
-	if ((r = ssh_get_authentication_socket(&agent_fd)) != 0) {
-		if (r != SSH_ERR_AGENT_NOT_PRESENT)
-			debug_fr(r, "ssh_get_authentication_socket");
-	} else if ((r = ssh_fetch_identitylist(agent_fd, &idlist)) != 0) {
-		if (r != SSH_ERR_AGENT_NO_IDENTITIES)
-			debug_fr(r, "ssh_fetch_identitylist");
-		close(agent_fd);
-	} else {
+	if ((r = get_agent_identities(ssh, &agent_fd, &idlist)) == 0) {
 		for (j = 0; j < idlist->nkeys; j++) {
 			found = 0;
 			TAILQ_FOREACH(id, &files, next) {

-- 
To stop receiving notification emails like this one, please contact
djm at mindrot.org.


More information about the openssh-commits mailing list