[openssh-commits] [openssh] 01/04: upstream: Add a "ssh -Z user at host" mode that dumps the pubkeys that
git+noreply at mindrot.org
git+noreply at mindrot.org
Mon Aug 3 16:54:23 AEST 2026
This is an automated email from the git hooks/post-receive script.
djm pushed a commit to branch master
in repository openssh.
commit 29f1b46e0f6fb4aba9ae34e4b46532b5748f395e
Author: djm at openbsd.org <djm at openbsd.org>
AuthorDate: Mon Aug 3 06:47:24 2026 +0000
upstream: Add a "ssh -Z user at host" mode that dumps the pubkeys that
will be tried for authentication in the order that they will be used.
feedback tb@ ok dtucker@
OpenBSD-Commit-ID: 617a7f149d1410980eac551e4780280190a5f218
---
ssh.1 | 10 +++++---
ssh.c | 73 +++++++++++++++++++++++++++++++++--------------------------
sshconnect.h | 4 +++-
sshconnect2.c | 38 +++++++++++++++++++++++++------
4 files changed, 82 insertions(+), 43 deletions(-)
diff --git a/ssh.1 b/ssh.1
index 747a126a1..ba24650e8 100644
--- a/ssh.1
+++ b/ssh.1
@@ -33,8 +33,8 @@
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
.\"
-.\" $OpenBSD: ssh.1,v 1.452 2026/07/11 11:15:03 naddy Exp $
-.Dd $Mdocdate: July 11 2026 $
+.\" $OpenBSD: ssh.1,v 1.453 2026/08/03 06:47:24 djm Exp $
+.Dd $Mdocdate: August 3 2026 $
.Dt SSH 1
.Os
.Sh NAME
@@ -42,7 +42,7 @@
.Nd OpenSSH remote login client
.Sh SYNOPSIS
.Nm ssh
-.Op Fl 46AaCfGgKkMNnqsTtVvXxYy
+.Op Fl 46AaCfGgKkMNnqsTtVvZXxYy
.Op Fl B Ar bind_interface
.Op Fl b Ar bind_address
.Op Fl c Ar cipher_spec
@@ -781,6 +781,10 @@ Send log information using the
.Xr syslog 3
system module.
By default this information is sent to stderr.
+.Pp
+.It Fl Z
+Dump the public keys that would be attempted for authentication to the specified
+destination in preferred order and exit.
.El
.Pp
.Nm
diff --git a/ssh.c b/ssh.c
index 7c644c23c..a4ebd11a4 100644
--- a/ssh.c
+++ b/ssh.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ssh.c,v 1.634 2026/07/06 07:49:58 djm Exp $ */
+/* $OpenBSD: ssh.c,v 1.635 2026/08/03 06:47:24 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo at cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo at cs.hut.fi>, Espoo, Finland
@@ -168,7 +168,7 @@ static void
usage(void)
{
fprintf(stderr,
-"usage: ssh [-46AaCfGgKkMNnqsTtVvXxYy] [-B bind_interface] [-b bind_address]\n"
+"usage: ssh [-46AaCfGgKkMNnqsTtVvZXxYyZ] [-B bind_interface] [-b bind_address]\n"
" [-c cipher_spec] [-D [bind_address:]port] [-E log_file]\n"
" [-e escape_char] [-F configfile] [-I pkcs11] [-i identity_file]\n"
" [-J destination] [-L address] [-l login_name] [-m mac_spec]\n"
@@ -621,7 +621,7 @@ main(int ac, char **av)
{
struct ssh *ssh = NULL;
int i, r, opt, exit_status, use_syslog, direct, timeout_ms;
- int was_addr, config_test = 0, opt_terminated = 0, want_final_pass = 0;
+ int was_addr, config_test = 0, dump_pubkeys = 0, opt_terminated = 0, want_final_pass = 0;
int user_on_commandline = 0, user_was_default = 0, user_expanded = 0;
char *p, *cp, *line, *argv0, *logfile, *args;
char cname[NI_MAXHOST], thishost[NI_MAXHOST];
@@ -700,8 +700,9 @@ main(int ac, char **av)
argv0 = av[0];
again:
- while ((opt = getopt(ac, av, "1246ab:c:e:fgi:kl:m:no:p:qstvx"
- "AB:CD:E:F:GI:J:KL:MNO:P:Q:R:S:TVw:W:XYy")) != -1) { /* HUZdhjruz */
+ /* remaining: HUdhjruz */
+ while ((opt = getopt(ac, av, "1246ACGKMNTVXYZafgknqstvxy"
+ "B:D:E:F:I:J:L:O:P:Q:R:S:W:b:c:e:i:l:m:o:p:w:")) != -1) {
switch (opt) {
case '1':
fatal("SSH protocol v.1 is no longer supported");
@@ -741,6 +742,9 @@ main(int ac, char **av)
options.forward_x11 = 1;
options.forward_x11_trusted = 1;
break;
+ case 'Z':
+ dump_pubkeys = 1;
+ break;
case 'g':
options.fwd_opts.gateway_ports = 1;
break;
@@ -1638,6 +1642,38 @@ main(int ac, char **av)
}
}
+ /* load options.identity_files */
+ load_public_identity_files(cinfo);
+
+ /* optionally set the SSH_AUTHSOCKET_ENV_NAME variable */
+ if (options.identity_agent &&
+ strcmp(options.identity_agent, SSH_AUTHSOCKET_ENV_NAME) != 0) {
+ if (strcmp(options.identity_agent, "none") == 0) {
+ unsetenv(SSH_AUTHSOCKET_ENV_NAME);
+ } else {
+ cp = options.identity_agent;
+ /* legacy (limited) format */
+ if (cp[0] == '$' && cp[1] != '{') {
+ if (!valid_env_name(cp + 1)) {
+ fatal("Invalid IdentityAgent "
+ "environment variable name %s", cp);
+ }
+ if ((p = getenv(cp + 1)) == NULL)
+ unsetenv(SSH_AUTHSOCKET_ENV_NAME);
+ else
+ setenv(SSH_AUTHSOCKET_ENV_NAME, p, 1);
+ } else {
+ /* identity_agent specifies a path directly */
+ setenv(SSH_AUTHSOCKET_ENV_NAME, cp, 1);
+ }
+ }
+ }
+
+ if (dump_pubkeys) {
+ pubkey_dump(ssh);
+ exit(0);
+ }
+
/*
* If hostname canonicalisation was not enabled, then we may not
* have yet resolved the hostname. Do so now.
@@ -1732,33 +1768,6 @@ main(int ac, char **av)
}
}
- /* load options.identity_files */
- load_public_identity_files(cinfo);
-
- /* optionally set the SSH_AUTHSOCKET_ENV_NAME variable */
- if (options.identity_agent &&
- strcmp(options.identity_agent, SSH_AUTHSOCKET_ENV_NAME) != 0) {
- if (strcmp(options.identity_agent, "none") == 0) {
- unsetenv(SSH_AUTHSOCKET_ENV_NAME);
- } else {
- cp = options.identity_agent;
- /* legacy (limited) format */
- if (cp[0] == '$' && cp[1] != '{') {
- if (!valid_env_name(cp + 1)) {
- fatal("Invalid IdentityAgent "
- "environment variable name %s", cp);
- }
- if ((p = getenv(cp + 1)) == NULL)
- unsetenv(SSH_AUTHSOCKET_ENV_NAME);
- else
- setenv(SSH_AUTHSOCKET_ENV_NAME, p, 1);
- } else {
- /* identity_agent specifies a path directly */
- setenv(SSH_AUTHSOCKET_ENV_NAME, cp, 1);
- }
- }
- }
-
if (options.forward_agent && options.forward_agent_sock_path != NULL) {
cp = options.forward_agent_sock_path;
if (cp[0] == '$') {
diff --git a/sshconnect.h b/sshconnect.h
index 2ac2c07e0..aad13c20c 100644
--- a/sshconnect.h
+++ b/sshconnect.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: sshconnect.h,v 1.51 2026/07/06 07:49:58 djm Exp $ */
+/* $OpenBSD: sshconnect.h,v 1.52 2026/08/03 06:47:24 djm Exp $ */
/*
* Copyright (c) 2000 Markus Friedl. All rights reserved.
@@ -91,6 +91,8 @@ void ssh_kex2(struct ssh *ssh, char *, struct sockaddr_storage *, u_short,
void ssh_userauth2(struct ssh *ssh, const char *, const char *,
char *, Sensitive *);
+void pubkey_dump(struct ssh *);
+
int ssh_local_cmd(const char *);
void maybe_add_key_to_agent(const char *, struct sshkey *,
diff --git a/sshconnect2.c b/sshconnect2.c
index 3ff05a578..b2eb17bd4 100644
--- a/sshconnect2.c
+++ b/sshconnect2.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: sshconnect2.c,v 1.390 2026/07/27 12:28:52 markus Exp $ */
+/* $OpenBSD: sshconnect2.c,v 1.391 2026/08/03 06:47:24 djm Exp $ */
/*
* Copyright (c) 2000 Markus Friedl. All rights reserved.
* Copyright (c) 2008 Damien Miller. All rights reserved.
@@ -1648,11 +1648,13 @@ get_agent_identities(struct ssh *ssh, int *agent_fdp,
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 (ssh != NULL && ssh->kex != NULL) {
+ 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");
@@ -1810,7 +1812,8 @@ pubkey_prepare(struct ssh *ssh, Authctxt *authctxt)
"not in PubkeyAcceptedAlgorithms",
sshkey_ssh_name(id->key), id->filename);
disallowed = 1;
- } else if (ssh->kex->server_sig_algs != NULL &&
+ } else if (ssh != NULL && ssh->kex != NULL &&
+ ssh->kex->server_sig_algs != NULL &&
(cp = key_sig_algorithm(ssh, id->key)) == NULL) {
debug("Skipping %s key %s - corresponding algorithm "
"not supported by server",
@@ -1854,6 +1857,27 @@ pubkey_cleanup(struct ssh *ssh)
}
}
+void
+pubkey_dump(struct ssh *ssh)
+{
+ Authctxt authctxt;
+ Identity *id;
+ char *ident;
+
+ memset(&authctxt, 0, sizeof(authctxt));
+ authctxt.agent_fd = -1;
+ ssh->authctxt = &authctxt;
+
+ pubkey_prepare(ssh, &authctxt);
+ TAILQ_FOREACH(id, &authctxt.keys, next) {
+ ident = format_identity(id);
+ fprintf(stdout, "%s\n", ident);
+ free(ident);
+ }
+ pubkey_cleanup(ssh);
+ ssh->authctxt = NULL;
+}
+
static void
pubkey_reset(Authctxt *authctxt)
{
--
To stop receiving notification emails like this one, please contact
djm at mindrot.org.
More information about the openssh-commits
mailing list