Use hostkey parsed from hostbound userauth request
authordjm <djm@openbsd.org>
Sun, 19 Dec 2021 22:13:55 +0000 (22:13 +0000)
committerdjm <djm@openbsd.org>
Sun, 19 Dec 2021 22:13:55 +0000 (22:13 +0000)
Require host-bound userauth requests for forwarded SSH connections.

The hostkey parsed from the host-bound userauth request is now checked
against the most recently bound session ID / hostkey on the agent socket
and the signature refused if they do not match.

ok markus@

usr.bin/ssh/ssh-agent.c

index 80d189c..3e6a68e 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: ssh-agent.c,v 1.282 2021/12/19 22:13:33 djm Exp $ */
+/* $OpenBSD: ssh-agent.c,v 1.283 2021/12/19 22:13:55 djm Exp $ */
 /*
  * Author: Tatu Ylonen <ylo@cs.hut.fi>
  * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -714,7 +714,7 @@ process_sign_request2(SocketEntry *e)
        char *fp = NULL, *user = NULL, *sig_dest = NULL;
        const char *fwd_host = NULL, *dest_host = NULL;
        struct sshbuf *msg = NULL, *data = NULL, *sid = NULL;
-       struct sshkey *key = NULL;
+       struct sshkey *key = NULL, *hostkey = NULL;
        struct identity *id;
        struct notifier_ctx *notifier = NULL;
 
@@ -743,7 +743,8 @@ process_sign_request2(SocketEntry *e)
                            "to sign on unbound connection");
                        goto send;
                }
-               if (parse_userauth_request(data, key, &user, &sid, NULL) != 0) {
+               if (parse_userauth_request(data, key, &user, &sid,
+                   &hostkey) != 0) {
                        logit_f("refusing use of destination-constrained key "
                           "to sign an unidentified signature");
                        goto send;
@@ -766,6 +767,24 @@ process_sign_request2(SocketEntry *e)
                            sshkey_type(id->key), fp);
                        goto send;
                }
+               /*
+                * Ensure that the hostkey embedded in the signature matches
+                * the one most recently bound to the socket. An exception is
+                * made for the initial forwarding hop.
+                */
+               if (e->nsession_ids > 1 && hostkey == NULL) {
+                       error_f("refusing use of destination-constrained key: "
+                           "no hostkey recorded in signature for forwarded "
+                           "connection");
+                       goto send;
+               }
+               if (hostkey != NULL && !sshkey_equal(hostkey,
+                   e->session_ids[e->nsession_ids - 1].key)) {
+                       error_f("refusing use of destination-constrained key: "
+                           "mismatch between hostkey in request and most "
+                           "recently bound session");
+                       goto send;
+               }
                xasprintf(&sig_dest, "public key authentication request for "
                    "user \"%s\" to listed host", user);
        }
@@ -813,6 +832,7 @@ process_sign_request2(SocketEntry *e)
        sshbuf_free(data);
        sshbuf_free(msg);
        sshkey_free(key);
+       sshkey_free(hostkey);
        free(fp);
        free(signature);
        free(sig_dest);