Skip to content

Commit e067ccd

Browse files
committed
upstream: ssh-agent supports a "query" extension that allows a
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
1 parent 4fe2786 commit e067ccd

File tree

4 files changed

+90
-8
lines changed

4 files changed

+90
-8
lines changed

authfd.c

Lines changed: 54 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* $OpenBSD: authfd.c,v 1.140 2026/03/05 05:35:44 djm Exp $ */
1+
/* $OpenBSD: authfd.c,v 1.141 2026/03/05 05:44:15 djm Exp $ */
22
/*
33
* Author: Tatu Ylonen <[email protected]>
44
* Copyright (c) 1995 Tatu Ylonen <[email protected]>, Espoo, Finland
@@ -53,8 +53,10 @@
5353
#include "sshkey.h"
5454
#include "authfd.h"
5555
#include "log.h"
56+
#include "misc.h"
5657
#include "atomicio.h"
5758
#include "ssherr.h"
59+
#include "xmalloc.h"
5860

5961
#define MAX_AGENT_IDENTITIES 2048 /* Max keys in agent reply */
6062
#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,
769771
sshbuf_free(msg);
770772
return r;
771773
}
774+
775+
/* Queries supported extension request types */
776+
int
777+
ssh_agent_query_extensions(int sock, char ***exts)
778+
{
779+
struct sshbuf *msg;
780+
int r;
781+
u_char type;
782+
char *cp = NULL, **ret = NULL;
783+
size_t i = 0;
784+
785+
*exts = NULL;
786+
if ((msg = sshbuf_new()) == NULL)
787+
return SSH_ERR_ALLOC_FAIL;
788+
if ((r = sshbuf_put_u8(msg, SSH_AGENTC_EXTENSION)) != 0 ||
789+
(r = sshbuf_put_cstring(msg, "query")) != 0)
790+
goto out;
791+
if ((r = ssh_request_reply(sock, msg, msg)) != 0)
792+
goto out;
793+
if ((r = sshbuf_get_u8(msg, &type)) != 0)
794+
goto out;
795+
if (agent_failed(type)) {
796+
r = SSH_ERR_AGENT_FAILURE;
797+
goto out;
798+
}
799+
/* Reply should start with "query" */
800+
if (type != SSH_AGENT_EXTENSION_RESPONSE ||
801+
(r = sshbuf_get_cstring(msg, &cp, NULL)) != 0 ||
802+
strcmp(cp, "query") != 0) {
803+
r = SSH_ERR_INVALID_FORMAT;
804+
goto out;
805+
}
806+
ret = calloc(1, sizeof(*ret));
807+
while (sshbuf_len(msg)) {
808+
ret = xrecallocarray(ret, i + 1, i + 2, sizeof(*ret));
809+
if ((r = sshbuf_get_cstring(msg, ret + i, NULL)) != 0) {
810+
r = SSH_ERR_INVALID_FORMAT;
811+
goto out;
812+
}
813+
i++;
814+
}
815+
/* success */
816+
r = 0;
817+
*exts = ret;
818+
ret = NULL; /* transferred */
819+
out:
820+
free(cp);
821+
stringlist_free(ret);
822+
sshbuf_free(msg);
823+
return r;
824+
}

authfd.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* $OpenBSD: authfd.h,v 1.54 2026/01/27 06:48:29 djm Exp $ */
1+
/* $OpenBSD: authfd.h,v 1.55 2026/03/05 05:44:15 djm Exp $ */
22

33
/*
44
* Author: Tatu Ylonen <[email protected]>
@@ -67,6 +67,8 @@ int ssh_agent_bind_hostkey(int sock, const struct sshkey *key,
6767
const struct sshbuf *session_id, const struct sshbuf *signature,
6868
int forwarding);
6969

70+
int ssh_agent_query_extensions(int sock, char ***exts);
71+
7072
/* Messages for the authentication agent connection. */
7173
#define SSH_AGENTC_REQUEST_RSA_IDENTITIES 1
7274
#define SSH_AGENT_RSA_IDENTITIES_ANSWER 2

ssh-add.1

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
.\" $OpenBSD: ssh-add.1,v 1.88 2025/09/11 02:54:42 djm Exp $
1+
.\" $OpenBSD: ssh-add.1,v 1.89 2026/03/05 05:44:15 djm Exp $
22
.\"
33
.\" Author: Tatu Ylonen <[email protected]>
44
.\" Copyright (c) 1995 Tatu Ylonen <[email protected]>, Espoo, Finland
@@ -35,7 +35,7 @@
3535
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
3636
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3737
.\"
38-
.Dd $Mdocdate: September 11 2025 $
38+
.Dd $Mdocdate: March 5 2026 $
3939
.Dt SSH-ADD 1
4040
.Os
4141
.Sh NAME
@@ -59,6 +59,8 @@
5959
.Nm ssh-add
6060
.Fl T
6161
.Ar pubkey ...
62+
.Nm ssh-add
63+
.Fl Q
6264
.Sh DESCRIPTION
6365
.Nm
6466
adds private key identities to the authentication agent,
@@ -230,6 +232,9 @@ will request that the agent automatically delete the certificate shortly
230232
after the certificate's expiry date.
231233
This flag suppresses this behaviour and does not specify a lifetime for
232234
certificates added to an agent.
235+
.It Fl Q
236+
Query the agent for the list of protocol extensions it supports.
237+
Note: not all agents support this query.
233238
.It Fl q
234239
Be quiet after a successful operation.
235240
.It Fl S Ar provider

ssh-add.c

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* $OpenBSD: ssh-add.c,v 1.185 2026/02/11 17:01:34 dtucker Exp $ */
1+
/* $OpenBSD: ssh-add.c,v 1.186 2026/03/05 05:44:15 djm Exp $ */
22
/*
33
* Author: Tatu Ylonen <[email protected]>
44
* Copyright (c) 1995 Tatu Ylonen <[email protected]>, Espoo, Finland
@@ -237,6 +237,21 @@ delete_all(int agent_fd, int qflag)
237237
return ret;
238238
}
239239

240+
static int
241+
query_exts(int agent_fd)
242+
{
243+
int r;
244+
char **exts = NULL;
245+
size_t i;
246+
247+
if ((r = ssh_agent_query_extensions(agent_fd, &exts)) != 0)
248+
fatal_r(r, "unable to query supported extensions");
249+
for (i = 0; exts != NULL && exts[i] != NULL; i++)
250+
puts(exts[i]);
251+
stringlist_free(exts);
252+
return 0;
253+
}
254+
240255
static int
241256
check_cert_lifetime(const struct sshkey *cert, int cert_lifetime)
242257
{
@@ -803,7 +818,7 @@ main(int argc, char **argv)
803818
char **dest_constraint_strings = NULL, **hostkey_files = NULL;
804819
int r, i, ch, deleting = 0, ret = 0, key_only = 0, cert_only = 0;
805820
int do_download = 0, xflag = 0, lflag = 0, Dflag = 0;
806-
int qflag = 0, Tflag = 0, Nflag = 0;
821+
int Qflag = 0, qflag = 0, Tflag = 0, Nflag = 0;
807822
SyslogFacility log_facility = SYSLOG_FACILITY_AUTH;
808823
LogLevel log_level = SYSLOG_LEVEL_INFO;
809824
struct sshkey *k, **certs = NULL;
@@ -835,7 +850,7 @@ main(int argc, char **argv)
835850

836851
skprovider = getenv("SSH_SK_PROVIDER");
837852

838-
while ((ch = getopt(argc, argv, "vkKlLNCcdDTxXE:e:h:H:M:m:qs:S:t:")) != -1) {
853+
while ((ch = getopt(argc, argv, "vkKlLNCcdDTxXE:e:h:H:M:m:Qqs:S:t:")) != -1) {
839854
switch (ch) {
840855
case 'v':
841856
if (log_level == SYSLOG_LEVEL_INFO)
@@ -912,6 +927,9 @@ main(int argc, char **argv)
912927
case 'q':
913928
qflag = 1;
914929
break;
930+
case 'Q':
931+
Qflag = 1;
932+
break;
915933
case 'T':
916934
Tflag = 1;
917935
break;
@@ -923,7 +941,7 @@ main(int argc, char **argv)
923941
}
924942
log_init(__progname, log_level, log_facility, 1);
925943

926-
if ((xflag != 0) + (lflag != 0) + (Dflag != 0) > 1)
944+
if ((xflag != 0) + (lflag != 0) + (Dflag != 0) + (Qflag != 0) > 1)
927945
fatal("Invalid combination of actions");
928946
else if (xflag) {
929947
if (lock_agent(agent_fd, xflag == 'x' ? 1 : 0) == -1)
@@ -937,6 +955,10 @@ main(int argc, char **argv)
937955
if (delete_all(agent_fd, qflag) == -1)
938956
ret = 1;
939957
goto done;
958+
} else if (Qflag) {
959+
if (query_exts(agent_fd) == -1)
960+
ret = 1;
961+
goto done;
940962
}
941963

942964
#ifdef ENABLE_SK_INTERNAL

0 commit comments

Comments
 (0)