summaryrefslogtreecommitdiff
path: root/usr.bin
diff options
context:
space:
mode:
authorDamien Miller <djm@cvs.openbsd.org>2021-12-19 22:08:49 +0000
committerDamien Miller <djm@cvs.openbsd.org>2021-12-19 22:08:49 +0000
commiteec0dfe621ac9831839a9be4e21c81f9d0746aaa (patch)
tree5d48b6b14610efb8570fe0a5588b69a406528406 /usr.bin
parent7df63077292dfb9396302e4a377dd6f67dd14ccb (diff)
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@openssh.com" agent extension. ok markus@
Diffstat (limited to 'usr.bin')
-rw-r--r--usr.bin/ssh/authfd.c31
-rw-r--r--usr.bin/ssh/authfd.h11
-rw-r--r--usr.bin/ssh/clientloop.c8
-rw-r--r--usr.bin/ssh/sshconnect2.c47
4 files changed, 82 insertions, 15 deletions
diff --git a/usr.bin/ssh/authfd.c b/usr.bin/ssh/authfd.c
index a7fe2cc7d67..18fa1f19c2b 100644
--- a/usr.bin/ssh/authfd.c
+++ b/usr.bin/ssh/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@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -649,3 +649,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@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/usr.bin/ssh/authfd.h b/usr.bin/ssh/authfd.h
index 4fbf82f8c00..fe1ed8a1abc 100644
--- a/usr.bin/ssh/authfd.h
+++ b/usr.bin/ssh/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@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/usr.bin/ssh/clientloop.c b/usr.bin/ssh/clientloop.c
index 782e967d151..f9533d6c44e 100644
--- a/usr.bin/ssh/clientloop.c
+++ b/usr.bin/ssh/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@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -1589,6 +1589,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/usr.bin/ssh/sshconnect2.c b/usr.bin/ssh/sshconnect2.c
index 7eda9a9fc4a..23e6162407f 100644
--- a/usr.bin/ssh/sshconnect2.c
+++ b/usr.bin/ssh/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.
@@ -384,7 +384,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 *);
@@ -458,7 +458,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");
}
@@ -1624,6 +1624,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:
@@ -1634,7 +1664,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;
@@ -1696,14 +1726,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) {