1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
|
--- UTC
r110506 | des | 2003-02-07 09:48:27 -0600 (Fri, 07 Feb 2003) | 4 lines
Set the ruid to the euid at startup as a workaround for a bug in pam_ssh.
r226103 | des | 2011-10-07 08:10:16 -0500 (Fri, 07 Oct 2011) | 5 lines
Add a -x option that causes ssh-agent(1) to exit when all clients have
disconnected.
--- ssh-agent.c.orig 2015-05-29 03:27:21.000000000 -0500
+++ ssh-agent.c 2015-06-02 09:46:54.719580000 -0500
@@ -157,15 +157,34 @@ static long lifetime = 0;
static int fingerprint_hash = SSH_FP_HASH_DEFAULT;
+/*
+ * Client connection count; incremented in new_socket() and decremented in
+ * close_socket(). When it reaches 0, ssh-agent will exit. Since it is
+ * normally initialized to 1, it will never reach 0. However, if the -x
+ * option is specified, it is initialized to 0 in main(); in that case,
+ * ssh-agent will exit as soon as it has had at least one client but no
+ * longer has any.
+ */
+static int xcount = 1;
+
static void
close_socket(SocketEntry *e)
{
+ int last = 0;
+
+ if (e->type == AUTH_CONNECTION) {
+ debug("xcount %d -> %d", xcount, xcount - 1);
+ if (--xcount == 0)
+ last = 1;
+ }
close(e->fd);
e->fd = -1;
e->type = AUTH_UNUSED;
sshbuf_free(e->input);
sshbuf_free(e->output);
sshbuf_free(e->request);
+ if (last)
+ cleanup_exit(0);
}
static void
@@ -939,6 +958,10 @@ new_socket(sock_type type, int fd)
{
u_int i, old_alloc, new_alloc;
+ if (type == AUTH_CONNECTION) {
+ debug("xcount %d -> %d", xcount, xcount + 1);
+ ++xcount;
+ }
set_nonblock(fd);
if (fd > max_fd)
@@ -1166,7 +1189,7 @@ static void
usage(void)
{
fprintf(stderr,
- "usage: ssh-agent [-c | -s] [-Dd] [-a bind_address] [-E fingerprint_hash]\n"
+ "usage: ssh-agent [-c | -s] [-Ddx] [-a bind_address] [-E fingerprint_hash]\n"
" [-t life] [command [arg ...]]\n"
" ssh-agent [-c | -s] -k\n");
exit(1);
@@ -1197,6 +1220,7 @@ main(int ac, char **av)
/* drop */
setegid(getgid());
setgid(getgid());
+ setuid(geteuid());
#if defined(HAVE_PRCTL) && defined(PR_SET_DUMPABLE)
/* Disable ptrace on Linux without sgid bit */
@@ -1210,7 +1234,7 @@ main(int ac, char **av)
__progname = ssh_get_progname(av[0]);
seed_rng();
- while ((ch = getopt(ac, av, "cDdksE:a:t:")) != -1) {
+ while ((ch = getopt(ac, av, "cDdksE:a:t:x")) != -1) {
switch (ch) {
case 'E':
fingerprint_hash = ssh_digest_alg_by_name(optarg);
@@ -1249,6 +1273,9 @@ main(int ac, char **av)
usage();
}
break;
+ case 'x':
+ xcount = 0;
+ break;
default:
usage();
}
|