aboutsummaryrefslogtreecommitdiff
path: root/crypto/openssh/ssh-agent.c
diff options
context:
space:
mode:
Diffstat (limited to 'crypto/openssh/ssh-agent.c')
-rw-r--r--crypto/openssh/ssh-agent.c134
1 files changed, 91 insertions, 43 deletions
diff --git a/crypto/openssh/ssh-agent.c b/crypto/openssh/ssh-agent.c
index 34ebc494337f..af3c944130f8 100644
--- a/crypto/openssh/ssh-agent.c
+++ b/crypto/openssh/ssh-agent.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ssh-agent.c,v 1.313 2025/08/29 03:50:38 djm Exp $ */
+/* $OpenBSD: ssh-agent.c,v 1.324 2026/03/10 07:27:14 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -37,13 +37,13 @@
#include "includes.h"
#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/queue.h>
#include <sys/resource.h>
-#include <sys/stat.h>
#include <sys/socket.h>
-#include <sys/wait.h>
-#include <sys/time.h>
+#include <sys/stat.h>
#include <sys/un.h>
-#include "openbsd-compat/sys-queue.h"
+#include <sys/wait.h>
#ifdef WITH_OPENSSL
#include <openssl/evp.h>
@@ -52,15 +52,15 @@
#include <errno.h>
#include <fcntl.h>
-#include <limits.h>
#include <paths.h>
#include <poll.h>
#include <signal.h>
-#include <stdarg.h>
-#include <stdio.h>
#include <stdlib.h>
-#include <time.h>
+#include <stdio.h>
#include <string.h>
+#include <stdarg.h>
+#include <limits.h>
+#include <time.h>
#include <unistd.h>
#include <util.h>
@@ -162,8 +162,8 @@ static sig_atomic_t signalled_keydrop;
pid_t cleanup_pid = 0;
/* pathname and directory for AUTH_SOCKET */
-char socket_name[PATH_MAX];
-char socket_dir[PATH_MAX];
+static char *socket_name;
+static char socket_dir[PATH_MAX];
/* Pattern-list of allowed PKCS#11/Security key paths */
static char *allowed_providers;
@@ -410,7 +410,7 @@ match_key_hop(const char *tag, const struct sshkey *key,
return -1; /* shouldn't happen */
if (!sshkey_equal(key->cert->signature_key, dch->keys[i]))
continue;
- if (sshkey_cert_check_host(key, hostname, 1,
+ if (sshkey_cert_check_host(key, hostname,
SSH_ALLOWED_CA_SIGALGS, &reason) != 0) {
debug_f("cert %s / hostname %s rejected: %s",
key->cert->key_id, hostname, reason);
@@ -616,16 +616,22 @@ confirm_key(Identity *id, const char *extra)
}
static void
-send_status(SocketEntry *e, int success)
+send_status_generic(SocketEntry *e, u_int code)
{
int r;
if ((r = sshbuf_put_u32(e->output, 1)) != 0 ||
- (r = sshbuf_put_u8(e->output, success ?
- SSH_AGENT_SUCCESS : SSH_AGENT_FAILURE)) != 0)
+ (r = sshbuf_put_u8(e->output, code)) != 0)
fatal_fr(r, "compose");
}
+static void
+send_status(SocketEntry *e, int success)
+{
+ return send_status_generic(e,
+ success ? SSH_AGENT_SUCCESS : SSH_AGENT_FAILURE);
+}
+
/* send list of supported public keys to 'client' */
static void
process_request_identities(SocketEntry *e)
@@ -1774,6 +1780,26 @@ process_ext_session_bind(SocketEntry *e)
return r == 0 ? 1 : 0;
}
+static int
+process_ext_query(SocketEntry *e)
+{
+ int r;
+ struct sshbuf *msg = NULL;
+
+ debug2_f("entering");
+ if ((msg = sshbuf_new()) == NULL)
+ fatal_f("sshbuf_new failed");
+ if ((r = sshbuf_put_u8(msg, SSH_AGENT_EXTENSION_RESPONSE)) != 0 ||
+ (r = sshbuf_put_cstring(msg, "query")) != 0 ||
+ /* string[] supported extension types */
+ (r = sshbuf_put_cstring(msg, "session-bind@openssh.com")) != 0)
+ fatal_fr(r, "compose");
+ if ((r = sshbuf_put_stringb(e->output, msg)) != 0)
+ fatal_fr(r, "enqueue");
+ sshbuf_free(msg);
+ return 1;
+}
+
static void
process_extension(SocketEntry *e)
{
@@ -1783,16 +1809,26 @@ process_extension(SocketEntry *e)
debug2_f("entering");
if ((r = sshbuf_get_cstring(e->request, &name, NULL)) != 0) {
error_fr(r, "parse");
- goto send;
+ send_status(e, 0);
+ return;
}
- if (strcmp(name, "session-bind@openssh.com") == 0)
+
+ if (strcmp(name, "query") == 0)
+ success = process_ext_query(e);
+ else if (strcmp(name, "session-bind@openssh.com") == 0)
success = process_ext_session_bind(e);
- else
+ else {
debug_f("unsupported extension \"%s\"", name);
+ free(name);
+ send_status(e, 0);
+ return;
+ }
free(name);
-send:
- send_status(e, success);
+ /* Agent failures are signalled with a different error code */
+ send_status_generic(e,
+ success ? SSH_AGENT_SUCCESS : SSH_AGENT_EXTENSION_FAILURE);
}
+
/*
* dispatch incoming message.
* returns 1 on success, 0 for incomplete messages or -1 on error.
@@ -2153,8 +2189,11 @@ cleanup_socket(void)
if (cleanup_pid != 0 && getpid() != cleanup_pid)
return;
debug_f("cleanup");
- if (socket_name[0])
+ if (socket_name != NULL) {
unlink(socket_name);
+ free(socket_name);
+ socket_name = NULL;
+ }
if (socket_dir[0])
rmdir(socket_dir);
}
@@ -2214,7 +2253,9 @@ main(int ac, char **av)
int c_flag = 0, d_flag = 0, D_flag = 0, k_flag = 0;
int s_flag = 0, T_flag = 0, u_flag = 0, U_flag = 0;
int sock = -1, ch, result, saved_errno;
- char *homedir = NULL, *shell, *format, *pidstr, *agentsocket = NULL;
+ pid_t pid;
+ char *homedir = NULL, *shell, *format, *pidstr, *agentsocket = NULL;
+ char *cp, pidstrbuf[1 + 3 * sizeof pid];
char *fdstr;
const char *errstr = NULL;
const char *ccp;
@@ -2223,8 +2264,6 @@ main(int ac, char **av)
#endif
extern int optind;
extern char *optarg;
- pid_t pid;
- char pidstrbuf[1 + 3 * sizeof pid];
size_t len;
mode_t prev_mask;
struct timespec timeout;
@@ -2419,16 +2458,9 @@ main(int ac, char **av)
fatal("Couldn't determine home directory");
if (!U_flag)
agent_cleanup_stale(homedir, 0);
- if (agent_listener(homedir, "agent", &sock, &agentsocket) != 0)
+ if (agent_listener(homedir, "agent", &sock, &socket_name) != 0)
fatal_f("Couldn't prepare agent socket");
- if (strlcpy(socket_name, agentsocket,
- sizeof(socket_name)) >= sizeof(socket_name)) {
- fatal_f("Socket path \"%s\" too long",
- agentsocket);
- }
free(homedir);
- free(agentsocket);
- agentsocket = NULL;
} else if (sock == -1) {
if (T_flag) {
/*
@@ -2440,16 +2472,12 @@ main(int ac, char **av)
perror("mkdtemp: private socket dir");
exit(1);
}
- snprintf(socket_name, sizeof(socket_name),
- "%s/agent.%ld", socket_dir, (long)parent_pid);
+ xasprintf(&socket_name, "%s/agent.%ld",
+ socket_dir, (long)parent_pid);
} else {
/* Try to use specified agent socket */
socket_dir[0] = '\0';
- if (strlcpy(socket_name, agentsocket,
- sizeof(socket_name)) >= sizeof(socket_name)) {
- fatal_f("Socket path \"%s\" too long",
- agentsocket);
- }
+ socket_name = xstrdup(agentsocket);
}
/* Listen on socket */
prev_mask = umask(0177);
@@ -2486,11 +2514,13 @@ main(int ac, char **av)
log_init(__progname,
d_flag ? SYSLOG_LEVEL_DEBUG3 : SYSLOG_LEVEL_INFO,
SYSLOG_FACILITY_AUTH, 1);
- if (socket_name[0] != '\0') {
+ if (socket_name != NULL) {
+ cp = argv_assemble(1, &socket_name);
format = c_flag ?
"setenv %s %s;\n" : "%s=%s; export %s;\n";
- printf(format, SSH_AUTHSOCKET_ENV_NAME, socket_name,
+ printf(format, SSH_AUTHSOCKET_ENV_NAME, cp,
SSH_AUTHSOCKET_ENV_NAME);
+ free(cp);
printf("echo Agent pid %ld;\n", (long)parent_pid);
fflush(stdout);
}
@@ -2506,10 +2536,12 @@ main(int ac, char **av)
snprintf(pidstrbuf, sizeof pidstrbuf, "%ld", (long)pid);
if (ac == 0) {
format = c_flag ? "setenv %s %s;\n" : "%s=%s; export %s;\n";
- printf(format, SSH_AUTHSOCKET_ENV_NAME, socket_name,
+ cp = argv_assemble(1, &socket_name);
+ printf(format, SSH_AUTHSOCKET_ENV_NAME, cp,
SSH_AUTHSOCKET_ENV_NAME);
printf(format, SSH_AGENTPID_ENV_NAME, pidstrbuf,
SSH_AGENTPID_ENV_NAME);
+ free(cp);
printf("echo Agent pid %ld;\n", (long)pid);
exit(0);
}
@@ -2566,7 +2598,23 @@ skip:
sigaddset(&nsigset, SIGTERM);
sigaddset(&nsigset, SIGUSR1);
- if (pledge("stdio rpath cpath unix id proc exec", NULL) == -1)
+ if (unveil("/", "r") == -1)
+ fatal("%s: unveil /: %s", __progname, strerror(errno));
+ if ((ccp = getenv("SSH_SK_HELPER")) == NULL || *ccp == '\0')
+ ccp = _PATH_SSH_SK_HELPER;
+ if (unveil(ccp, "x") == -1)
+ fatal("%s: unveil %s: %s", __progname, ccp, strerror(errno));
+ if ((ccp = getenv("SSH_PKCS11_HELPER")) == NULL || *ccp == '\0')
+ ccp = _PATH_SSH_PKCS11_HELPER;
+ if (unveil(ccp, "x") == -1)
+ fatal("%s: unveil %s: %s", __progname, ccp, strerror(errno));
+ if ((ccp = getenv("SSH_ASKPASS")) == NULL || *ccp == '\0')
+ ccp = _PATH_SSH_ASKPASS_DEFAULT;
+ if (unveil(ccp, "x") == -1)
+ fatal("%s: unveil %s: %s", __progname, ccp, strerror(errno));
+ if (unveil("/dev/null", "rw") == -1)
+ fatal("%s: unveil /dev/null: %s", __progname, strerror(errno));
+ if (pledge("stdio rpath cpath wpath unix id proc exec", NULL) == -1)
fatal("%s: pledge: %s", __progname, strerror(errno));
platform_pledge_agent();