]> git.ipfire.org Git - thirdparty/openssh-portable.git/commitdiff
upstream: ssh-agent supports a "query" extension that allows a
authordjm@openbsd.org <djm@openbsd.org>
Thu, 5 Mar 2026 05:44:15 +0000 (05:44 +0000)
committerDamien Miller <djm@mindrot.org>
Thu, 5 Mar 2026 05:45:28 +0000 (16:45 +1100)
client to request a list of extensions it support. This makes this capability
available to ssh-add via the -Q flag.

ok markus@

OpenBSD-Commit-ID: f211630568ff1a7d6bb4983a94f05ddac1c2d4eb

authfd.c
authfd.h
ssh-add.1
ssh-add.c

index 07925be44400619f661e9019c73beae3c6bfc17f..fe3226140c01dac1d2729a369dc46545fed7b619 100644 (file)
--- a/authfd.c
+++ b/authfd.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: authfd.c,v 1.140 2026/03/05 05:35:44 djm Exp $ */
+/* $OpenBSD: authfd.c,v 1.141 2026/03/05 05:44:15 djm Exp $ */
 /*
  * Author: Tatu Ylonen <ylo@cs.hut.fi>
  * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
 #include "sshkey.h"
 #include "authfd.h"
 #include "log.h"
+#include "misc.h"
 #include "atomicio.h"
 #include "ssherr.h"
+#include "xmalloc.h"
 
 #define MAX_AGENT_IDENTITIES   2048            /* Max keys in agent reply */
 #define MAX_AGENT_REPLY_LEN    (256 * 1024)    /* Max bytes in agent reply */
@@ -769,3 +771,54 @@ ssh_agent_bind_hostkey(int sock, const struct sshkey *key,
        sshbuf_free(msg);
        return r;
 }
+
+/* Queries supported extension request types */
+int
+ssh_agent_query_extensions(int sock, char ***exts)
+{
+       struct sshbuf *msg;
+       int r;
+       u_char type;
+       char *cp = NULL, **ret = NULL;
+       size_t i = 0;
+
+       *exts = NULL;
+       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, "query")) != 0)
+               goto out;
+       if ((r = ssh_request_reply(sock, msg, msg)) != 0)
+               goto out;
+       if ((r = sshbuf_get_u8(msg, &type)) != 0)
+               goto out;
+       if (agent_failed(type)) {
+               r = SSH_ERR_AGENT_FAILURE;
+               goto out;
+       }
+       /* Reply should start with "query" */
+       if (type != SSH_AGENT_EXTENSION_RESPONSE ||
+          (r = sshbuf_get_cstring(msg, &cp, NULL)) != 0 ||
+          strcmp(cp, "query") != 0) {
+               r = SSH_ERR_INVALID_FORMAT;
+               goto out;
+       }
+       ret = calloc(1, sizeof(*ret));
+       while (sshbuf_len(msg)) {
+               ret = xrecallocarray(ret, i + 1, i + 2, sizeof(*ret));
+               if ((r = sshbuf_get_cstring(msg, ret + i, NULL)) != 0) {
+                       r = SSH_ERR_INVALID_FORMAT;
+                       goto out;
+               }
+               i++;
+       }
+       /* success */
+       r = 0;
+       *exts = ret;
+       ret = NULL; /* transferred */
+ out:
+       free(cp);
+       stringlist_free(ret);
+       sshbuf_free(msg);
+       return r;
+}
index da4830a9664f45364a0e8fa84953217e43d55764..b2e07bcf285f2224ddb728508297311c15c8db5f 100644 (file)
--- a/authfd.h
+++ b/authfd.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: authfd.h,v 1.54 2026/01/27 06:48:29 djm Exp $ */
+/* $OpenBSD: authfd.h,v 1.55 2026/03/05 05:44:15 djm Exp $ */
 
 /*
  * Author: Tatu Ylonen <ylo@cs.hut.fi>
@@ -67,6 +67,8 @@ int   ssh_agent_bind_hostkey(int sock, const struct sshkey *key,
     const struct sshbuf *session_id, const struct sshbuf *signature,
     int forwarding);
 
+int    ssh_agent_query_extensions(int sock, char ***exts);
+
 /* Messages for the authentication agent connection. */
 #define SSH_AGENTC_REQUEST_RSA_IDENTITIES      1
 #define SSH_AGENT_RSA_IDENTITIES_ANSWER                2
index babe78040f3dd0fef1cb4c67f932ce8c7194a025..af5f8f7b055c3be4c3edb3ce8e3750cc7259e792 100644 (file)
--- a/ssh-add.1
+++ b/ssh-add.1
@@ -1,4 +1,4 @@
-.\"    $OpenBSD: ssh-add.1,v 1.88 2025/09/11 02:54:42 djm Exp $
+.\"    $OpenBSD: ssh-add.1,v 1.89 2026/03/05 05:44:15 djm Exp $
 .\"
 .\" Author: Tatu Ylonen <ylo@cs.hut.fi>
 .\" Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -35,7 +35,7 @@
 .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 .\"
-.Dd $Mdocdate: September 11 2025 $
+.Dd $Mdocdate: March 5 2026 $
 .Dt SSH-ADD 1
 .Os
 .Sh NAME
@@ -59,6 +59,8 @@
 .Nm ssh-add
 .Fl T
 .Ar pubkey ...
+.Nm ssh-add
+.Fl Q
 .Sh DESCRIPTION
 .Nm
 adds private key identities to the authentication agent,
@@ -230,6 +232,9 @@ will request that the agent automatically delete the certificate shortly
 after the certificate's expiry date.
 This flag suppresses this behaviour and does not specify a lifetime for
 certificates added to an agent.
+.It Fl Q
+Query the agent for the list of protocol extensions it supports.
+Note: not all agents support this query.
 .It Fl q
 Be quiet after a successful operation.
 .It Fl S Ar provider
index dcdbbfeca06bc7f9d69856319fa7b5d9c74f6815..1e9eddf9048ef6faa327e0d8daf337a620b26d3e 100644 (file)
--- a/ssh-add.c
+++ b/ssh-add.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ssh-add.c,v 1.185 2026/02/11 17:01:34 dtucker Exp $ */
+/* $OpenBSD: ssh-add.c,v 1.186 2026/03/05 05:44:15 djm Exp $ */
 /*
  * Author: Tatu Ylonen <ylo@cs.hut.fi>
  * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -237,6 +237,21 @@ delete_all(int agent_fd, int qflag)
        return ret;
 }
 
+static int
+query_exts(int agent_fd)
+{
+       int r;
+       char **exts = NULL;
+       size_t i;
+
+       if ((r = ssh_agent_query_extensions(agent_fd, &exts)) != 0)
+               fatal_r(r, "unable to query supported extensions");
+       for (i = 0; exts != NULL && exts[i] != NULL; i++)
+               puts(exts[i]);
+       stringlist_free(exts);
+       return 0;
+}
+
 static int
 check_cert_lifetime(const struct sshkey *cert, int cert_lifetime)
 {
@@ -803,7 +818,7 @@ main(int argc, char **argv)
        char **dest_constraint_strings = NULL, **hostkey_files = NULL;
        int r, i, ch, deleting = 0, ret = 0, key_only = 0, cert_only = 0;
        int do_download = 0, xflag = 0, lflag = 0, Dflag = 0;
-       int qflag = 0, Tflag = 0, Nflag = 0;
+       int Qflag = 0, qflag = 0, Tflag = 0, Nflag = 0;
        SyslogFacility log_facility = SYSLOG_FACILITY_AUTH;
        LogLevel log_level = SYSLOG_LEVEL_INFO;
        struct sshkey *k, **certs = NULL;
@@ -835,7 +850,7 @@ main(int argc, char **argv)
 
        skprovider = getenv("SSH_SK_PROVIDER");
 
-       while ((ch = getopt(argc, argv, "vkKlLNCcdDTxXE:e:h:H:M:m:qs:S:t:")) != -1) {
+       while ((ch = getopt(argc, argv, "vkKlLNCcdDTxXE:e:h:H:M:m:Qqs:S:t:")) != -1) {
                switch (ch) {
                case 'v':
                        if (log_level == SYSLOG_LEVEL_INFO)
@@ -912,6 +927,9 @@ main(int argc, char **argv)
                case 'q':
                        qflag = 1;
                        break;
+               case 'Q':
+                       Qflag = 1;
+                       break;
                case 'T':
                        Tflag = 1;
                        break;
@@ -923,7 +941,7 @@ main(int argc, char **argv)
        }
        log_init(__progname, log_level, log_facility, 1);
 
-       if ((xflag != 0) + (lflag != 0) + (Dflag != 0) > 1)
+       if ((xflag != 0) + (lflag != 0) + (Dflag != 0) + (Qflag != 0) > 1)
                fatal("Invalid combination of actions");
        else if (xflag) {
                if (lock_agent(agent_fd, xflag == 'x' ? 1 : 0) == -1)
@@ -937,6 +955,10 @@ main(int argc, char **argv)
                if (delete_all(agent_fd, qflag) == -1)
                        ret = 1;
                goto done;
+       } else if (Qflag) {
+               if (query_exts(agent_fd) == -1)
+                       ret = 1;
+               goto done;
        }
 
 #ifdef ENABLE_SK_INTERNAL