agent support for parsing hostkey-bound signatures
authordjm <djm@openbsd.org>
Sun, 19 Dec 2021 22:13:33 +0000 (22:13 +0000)
committerdjm <djm@openbsd.org>
Sun, 19 Dec 2021 22:13:33 +0000 (22:13 +0000)
Allow parse_userauth_request() to work with blobs from
publickey-hostbound-v00@openssh.com userauth attempts.

Extract hostkey from these blobs.

ok markus@

usr.bin/ssh/ssh-agent.c

index c55d88e..80d189c 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: ssh-agent.c,v 1.281 2021/12/19 22:11:39 djm Exp $ */
+/* $OpenBSD: ssh-agent.c,v 1.282 2021/12/19 22:13:33 djm Exp $ */
 /*
  * Author: Tatu Ylonen <ylo@cs.hut.fi>
  * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -553,22 +553,24 @@ agent_decode_alg(struct sshkey *key, u_int flags)
  * request, checking its contents for consistency and matching the embedded
  * key against the one that is being used for signing.
  * Note: does not modify msg buffer.
- * Optionally extract the username and session ID from the request.
+ * Optionally extract the username, session ID and/or hostkey from the request.
  */
 static int
 parse_userauth_request(struct sshbuf *msg, const struct sshkey *expected_key,
-    char **userp, struct sshbuf **sess_idp)
+    char **userp, struct sshbuf **sess_idp, struct sshkey **hostkeyp)
 {
        struct sshbuf *b = NULL, *sess_id = NULL;
        char *user = NULL, *service = NULL, *method = NULL, *pkalg = NULL;
        int r;
        u_char t, sig_follows;
-       struct sshkey *mkey = NULL;
+       struct sshkey *mkey = NULL, *hostkey = NULL;
 
        if (userp != NULL)
                *userp = NULL;
        if (sess_idp != NULL)
                *sess_idp = NULL;
+       if (hostkeyp != NULL)
+               *hostkeyp = NULL;
        if ((b = sshbuf_fromb(msg)) == NULL)
                fatal_f("sshbuf_fromb");
 
@@ -595,7 +597,10 @@ parse_userauth_request(struct sshbuf *msg, const struct sshkey *expected_key,
                r = SSH_ERR_INVALID_FORMAT;
                goto out;
        }
-       if (strcmp(method, "publickey") != 0) {
+       if (strcmp(method, "publickey-hostbound-v00@openssh.com") == 0) {
+               if ((r = sshkey_froms(b, &hostkey)) != 0)
+                       goto out;
+       } else if (strcmp(method, "publickey") != 0) {
                r = SSH_ERR_INVALID_FORMAT;
                goto out;
        }
@@ -614,6 +619,10 @@ parse_userauth_request(struct sshbuf *msg, const struct sshkey *expected_key,
                *sess_idp = sess_id;
                sess_id = NULL;
        }
+       if (hostkeyp != NULL) {
+               *hostkeyp = hostkey;
+               hostkey = NULL;
+       }
  out:
        sshbuf_free(b);
        sshbuf_free(sess_id);
@@ -622,6 +631,7 @@ parse_userauth_request(struct sshbuf *msg, const struct sshkey *expected_key,
        free(method);
        free(pkalg);
        sshkey_free(mkey);
+       sshkey_free(hostkey);
        return r;
 }
 
@@ -666,7 +676,7 @@ parse_sshsig_request(struct sshbuf *msg)
 static int
 check_websafe_message_contents(struct sshkey *key, struct sshbuf *data)
 {
-       if (parse_userauth_request(data, key, NULL, NULL) == 0) {
+       if (parse_userauth_request(data, key, NULL, NULL, NULL) == 0) {
                debug_f("signed data matches public key userauth request");
                return 1;
        }
@@ -733,7 +743,7 @@ process_sign_request2(SocketEntry *e)
                            "to sign on unbound connection");
                        goto send;
                }
-               if (parse_userauth_request(data, key, &user, &sid) != 0) {
+               if (parse_userauth_request(data, key, &user, &sid, NULL) != 0) {
                        logit_f("refusing use of destination-constrained key "
                           "to sign an unidentified signature");
                        goto send;