summaryrefslogtreecommitdiff
path: root/ssh-agent.c
diff options
context:
space:
mode:
Diffstat (limited to 'ssh-agent.c')
-rw-r--r--ssh-agent.c137
1 files changed, 82 insertions, 55 deletions
diff --git a/ssh-agent.c b/ssh-agent.c
index c27c5a956f2c..df241379c0b1 100644
--- a/ssh-agent.c
+++ b/ssh-agent.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ssh-agent.c,v 1.310 2025/02/18 08:02:48 djm Exp $ */
+/* $OpenBSD: ssh-agent.c,v 1.313 2025/08/29 03:50:38 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -41,12 +41,8 @@
#include <sys/stat.h>
#include <sys/socket.h>
#include <sys/wait.h>
-#ifdef HAVE_SYS_TIME_H
-# include <sys/time.h>
-#endif
-#ifdef HAVE_SYS_UN_H
-# include <sys/un.h>
-#endif
+#include <sys/time.h>
+#include <sys/un.h>
#include "openbsd-compat/sys-queue.h"
#ifdef WITH_OPENSSL
@@ -57,12 +53,8 @@
#include <errno.h>
#include <fcntl.h>
#include <limits.h>
-#ifdef HAVE_PATHS_H
-# include <paths.h>
-#endif
-#ifdef HAVE_POLL_H
-# include <poll.h>
-#endif
+#include <paths.h>
+#include <poll.h>
#include <signal.h>
#include <stdarg.h>
#include <stdio.h>
@@ -70,9 +62,7 @@
#include <time.h>
#include <string.h>
#include <unistd.h>
-#ifdef HAVE_UTIL_H
-# include <util.h>
-#endif
+#include <util.h>
#include "xmalloc.h"
#include "ssh.h"
@@ -644,8 +634,7 @@ process_request_identities(SocketEntry *e)
/* identity not visible, don't include in response */
if (identity_permitted(id, e, NULL, NULL, NULL) != 0)
continue;
- if ((r = sshkey_puts_opts(id->key, keys,
- SSHKEY_SERIALIZE_INFO)) != 0 ||
+ if ((r = sshkey_puts(id->key, keys)) != 0 ||
(r = sshbuf_put_cstring(keys, id->comment)) != 0) {
error_fr(r, "compose key/comment");
continue;
@@ -1292,7 +1281,7 @@ parse_key_constraints(struct sshbuf *m, struct sshkey *k, time_t *deathp,
{
u_char ctype;
int r;
- u_int seconds, maxsign = 0;
+ u_int seconds;
while (sshbuf_len(m)) {
if ((r = sshbuf_get_u8(m, &ctype)) != 0) {
@@ -1321,26 +1310,6 @@ parse_key_constraints(struct sshbuf *m, struct sshkey *k, time_t *deathp,
}
*confirmp = 1;
break;
- case SSH_AGENT_CONSTRAIN_MAXSIGN:
- if (k == NULL) {
- error_f("maxsign not valid here");
- r = SSH_ERR_INVALID_FORMAT;
- goto out;
- }
- if (maxsign != 0) {
- error_f("maxsign already set");
- r = SSH_ERR_INVALID_FORMAT;
- goto out;
- }
- if ((r = sshbuf_get_u32(m, &maxsign)) != 0) {
- error_fr(r, "parse maxsign constraint");
- goto out;
- }
- if ((r = sshkey_enable_maxsign(k, maxsign)) != 0) {
- error_fr(r, "enable maxsign");
- goto out;
- }
- break;
case SSH_AGENT_CONSTRAIN_EXTENSION:
if ((r = parse_key_constraint_extension(m,
sk_providerp, dcsp, ndcsp,
@@ -2208,20 +2177,23 @@ static void
usage(void)
{
fprintf(stderr,
- "usage: ssh-agent [-c | -s] [-Dd] [-a bind_address] [-E fingerprint_hash]\n"
+ "usage: ssh-agent [-c | -s] [-DdTU] [-a bind_address] [-E fingerprint_hash]\n"
" [-O option] [-P allowed_providers] [-t life]\n"
- " ssh-agent [-a bind_address] [-E fingerprint_hash] [-O option]\n"
+ " ssh-agent [-TU] [-a bind_address] [-E fingerprint_hash] [-O option]\n"
" [-P allowed_providers] [-t life] command [arg ...]\n"
- " ssh-agent [-c | -s] -k\n");
+ " ssh-agent [-c | -s] -k\n"
+ " ssh-agent -u\n");
exit(1);
}
int
main(int ac, char **av)
{
- int c_flag = 0, d_flag = 0, D_flag = 0, k_flag = 0, s_flag = 0;
+ 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 *shell, *format, *fdstr, *pidstr, *agentsocket = NULL;
+ char *homedir = NULL, *shell, *format, *pidstr, *agentsocket = NULL;
+ char *fdstr;
const char *errstr = NULL;
const char *ccp;
#ifdef HAVE_SETRLIMIT
@@ -2238,6 +2210,7 @@ main(int ac, char **av)
size_t npfd = 0;
u_int maxfds;
sigset_t nsigset, osigset;
+ int socket_activated = 0;
/* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */
sanitise_stdfd();
@@ -2256,7 +2229,7 @@ main(int ac, char **av)
__progname = ssh_get_progname(av[0]);
seed_rng();
- while ((ch = getopt(ac, av, "cDdksE:a:O:P:t:")) != -1) {
+ while ((ch = getopt(ac, av, "cDdksTuUE:a:O:P:t:")) != -1) {
switch (ch) {
case 'E':
fingerprint_hash = ssh_digest_alg_by_name(optarg);
@@ -2313,6 +2286,15 @@ main(int ac, char **av)
usage();
}
break;
+ case 'T':
+ T_flag++;
+ break;
+ case 'u':
+ u_flag++;
+ break;
+ case 'U':
+ U_flag++;
+ break;
default:
usage();
}
@@ -2320,9 +2302,14 @@ main(int ac, char **av)
ac -= optind;
av += optind;
- if (ac > 0 && (c_flag || k_flag || s_flag || d_flag || D_flag))
+ if (ac > 0 &&
+ (c_flag || k_flag || s_flag || d_flag || D_flag || u_flag))
usage();
+ log_init(__progname,
+ d_flag ? SYSLOG_LEVEL_DEBUG3 : SYSLOG_LEVEL_INFO,
+ SYSLOG_FACILITY_AUTH, 1);
+
if (allowed_providers == NULL)
allowed_providers = xstrdup(DEFAULT_ALLOWED_PROVIDERS);
if (websafe_allowlist == NULL)
@@ -2358,6 +2345,14 @@ main(int ac, char **av)
printf("echo Agent pid %ld killed;\n", (long)pid);
exit(0);
}
+ if (u_flag) {
+ if ((homedir = get_homedir()) == NULL)
+ fatal("Couldn't determine home directory");
+ agent_cleanup_stale(homedir, u_flag > 1);
+ printf("Deleted stale agent sockets in ~/%s\n",
+ _PATH_SSH_AGENT_SOCKET_DIR);
+ exit(0);
+ }
/*
* Minimum file descriptors:
@@ -2389,24 +2384,55 @@ main(int ac, char **av)
fatal("bad LISTEN_PID: %d vs pid %d", pid, getpid());
debug("using socket activation on fd=3");
sock = 3;
+ socket_activated = 1;
}
- /* Otherwise, create private directory for agent socket */
- if (sock == -1) {
- if (agentsocket == NULL) {
+ if (sock == -1 && agentsocket == NULL && !T_flag) {
+ /* Default case: ~/.ssh/agent/[socket] */
+ if ((homedir = get_homedir()) == NULL)
+ fatal("Couldn't determine home directory");
+ if (!U_flag)
+ agent_cleanup_stale(homedir, 0);
+ if (agent_listener(homedir, "agent", &sock, &agentsocket) != 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) {
+ /*
+ * Create private directory for agent socket
+ * in $TMPDIR.
+ */
mktemp_proto(socket_dir, sizeof(socket_dir));
if (mkdtemp(socket_dir) == NULL) {
perror("mkdtemp: private socket dir");
exit(1);
}
- snprintf(socket_name, sizeof socket_name,
- "%s/agent.%ld", socket_dir,
- (long)parent_pid);
+ snprintf(socket_name, sizeof(socket_name),
+ "%s/agent.%ld", socket_dir, (long)parent_pid);
} else {
/* Try to use specified agent socket */
socket_dir[0] = '\0';
- strlcpy(socket_name, agentsocket, sizeof socket_name);
+ if (strlcpy(socket_name, agentsocket,
+ sizeof(socket_name)) >= sizeof(socket_name)) {
+ fatal_f("Socket path \"%s\" too long",
+ agentsocket);
+ }
+ }
+ /* Listen on socket */
+ prev_mask = umask(0177);
+ if ((sock = unix_listener(socket_name,
+ SSH_LISTEN_BACKLOG, 0)) < 0) {
+ *socket_name = '\0'; /* Don't unlink existing file */
+ cleanup_exit(1);
}
+ umask(prev_mask);
}
closefrom(sock == -1 ? STDERR_FILENO + 1 : sock + 1);
@@ -2522,11 +2548,12 @@ skip:
sigprocmask(SIG_BLOCK, &nsigset, &osigset);
if (signalled_exit != 0) {
logit("exiting on signal %d", (int)signalled_exit);
- cleanup_exit(2);
+ cleanup_exit((signalled_exit == SIGTERM &&
+ socket_activated) ? 0 : 2);
}
if (signalled_keydrop) {
logit("signal %d received; removing all keys",
- signalled_keydrop);
+ (int)signalled_keydrop);
remove_all_identities();
signalled_keydrop = 0;
}