summaryrefslogtreecommitdiff
path: root/ssh-agent.c
diff options
context:
space:
mode:
Diffstat (limited to 'ssh-agent.c')
-rw-r--r--ssh-agent.c66
1 files changed, 41 insertions, 25 deletions
diff --git a/ssh-agent.c b/ssh-agent.c
index a3a867c33..c3d5e5a75 100644
--- a/ssh-agent.c
+++ b/ssh-agent.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: ssh-agent.c,v 1.154 2007/02/28 00:55:30 dtucker Exp $ */ 1/* $OpenBSD: ssh-agent.c,v 1.155 2007/03/19 12:16:42 dtucker Exp $ */
2/* 2/*
3 * Author: Tatu Ylonen <ylo@cs.hut.fi> 3 * Author: Tatu Ylonen <ylo@cs.hut.fi>
4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -120,6 +120,7 @@ int max_fd = 0;
120 120
121/* pid of shell == parent of agent */ 121/* pid of shell == parent of agent */
122pid_t parent_pid = -1; 122pid_t parent_pid = -1;
123u_int parent_alive_interval = 0;
123 124
124/* pathname and directory for AUTH_SOCKET */ 125/* pathname and directory for AUTH_SOCKET */
125char socket_name[MAXPATHLEN]; 126char socket_name[MAXPATHLEN];
@@ -421,10 +422,11 @@ process_remove_all_identities(SocketEntry *e, int version)
421 buffer_put_char(&e->output, SSH_AGENT_SUCCESS); 422 buffer_put_char(&e->output, SSH_AGENT_SUCCESS);
422} 423}
423 424
424static void 425/* removes expired keys and returns number of seconds until the next expiry */
426static u_int
425reaper(void) 427reaper(void)
426{ 428{
427 u_int now = time(NULL); 429 u_int deadline = 0, now = time(NULL);
428 Identity *id, *nxt; 430 Identity *id, *nxt;
429 int version; 431 int version;
430 Idtab *tab; 432 Idtab *tab;
@@ -433,14 +435,22 @@ reaper(void)
433 tab = idtab_lookup(version); 435 tab = idtab_lookup(version);
434 for (id = TAILQ_FIRST(&tab->idlist); id; id = nxt) { 436 for (id = TAILQ_FIRST(&tab->idlist); id; id = nxt) {
435 nxt = TAILQ_NEXT(id, next); 437 nxt = TAILQ_NEXT(id, next);
436 if (id->death != 0 && now >= id->death) { 438 if (id->death == 0)
439 continue;
440 if (now >= id->death) {
437 debug("expiring key '%s'", id->comment); 441 debug("expiring key '%s'", id->comment);
438 TAILQ_REMOVE(&tab->idlist, id, next); 442 TAILQ_REMOVE(&tab->idlist, id, next);
439 free_identity(id); 443 free_identity(id);
440 tab->nentries--; 444 tab->nentries--;
441 } 445 } else
446 deadline = (deadline == 0) ? id->death :
447 MIN(deadline, id->death);
442 } 448 }
443 } 449 }
450 if (deadline == 0 || deadline <= now)
451 return 0;
452 else
453 return (deadline - now);
444} 454}
445 455
446static void 456static void
@@ -826,10 +836,12 @@ new_socket(sock_type type, int fd)
826} 836}
827 837
828static int 838static int
829prepare_select(fd_set **fdrp, fd_set **fdwp, int *fdl, u_int *nallocp) 839prepare_select(fd_set **fdrp, fd_set **fdwp, int *fdl, u_int *nallocp,
840 struct timeval **tvpp)
830{ 841{
831 u_int i, sz; 842 u_int i, sz, deadline;
832 int n = 0; 843 int n = 0;
844 static struct timeval tv;
833 845
834 for (i = 0; i < sockets_alloc; i++) { 846 for (i = 0; i < sockets_alloc; i++) {
835 switch (sockets[i].type) { 847 switch (sockets[i].type) {
@@ -873,6 +885,17 @@ prepare_select(fd_set **fdrp, fd_set **fdwp, int *fdl, u_int *nallocp)
873 break; 885 break;
874 } 886 }
875 } 887 }
888 deadline = reaper();
889 if (parent_alive_interval != 0)
890 deadline = (deadline == 0) ? parent_alive_interval :
891 MIN(deadline, parent_alive_interval);
892 if (deadline == 0) {
893 *tvpp = NULL;
894 } else {
895 tv.tv_sec = deadline;
896 tv.tv_usec = 0;
897 *tvpp = &tv;
898 }
876 return (1); 899 return (1);
877} 900}
878 901
@@ -980,19 +1003,14 @@ cleanup_handler(int sig)
980 _exit(2); 1003 _exit(2);
981} 1004}
982 1005
983/*ARGSUSED*/
984static void 1006static void
985check_parent_exists(int sig) 1007check_parent_exists(void)
986{ 1008{
987 int save_errno = errno;
988
989 if (parent_pid != -1 && kill(parent_pid, 0) < 0) { 1009 if (parent_pid != -1 && kill(parent_pid, 0) < 0) {
990 /* printf("Parent has died - Authentication agent exiting.\n"); */ 1010 /* printf("Parent has died - Authentication agent exiting.\n"); */
991 cleanup_handler(sig); /* safe */ 1011 cleanup_socket();
1012 _exit(2);
992 } 1013 }
993 mysignal(SIGALRM, check_parent_exists);
994 alarm(10);
995 errno = save_errno;
996} 1014}
997 1015
998static void 1016static void
@@ -1027,7 +1045,7 @@ main(int ac, char **av)
1027 extern char *optarg; 1045 extern char *optarg;
1028 pid_t pid; 1046 pid_t pid;
1029 char pidstrbuf[1 + 3 * sizeof pid]; 1047 char pidstrbuf[1 + 3 * sizeof pid];
1030 struct timeval tv; 1048 struct timeval *tvp = NULL;
1031 1049
1032 /* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */ 1050 /* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */
1033 sanitise_stdfd(); 1051 sanitise_stdfd();
@@ -1228,10 +1246,8 @@ main(int ac, char **av)
1228 1246
1229skip: 1247skip:
1230 new_socket(AUTH_SOCKET, sock); 1248 new_socket(AUTH_SOCKET, sock);
1231 if (ac > 0) { 1249 if (ac > 0)
1232 mysignal(SIGALRM, check_parent_exists); 1250 parent_alive_interval = 10;
1233 alarm(10);
1234 }
1235 idtab_init(); 1251 idtab_init();
1236 if (!d_flag) 1252 if (!d_flag)
1237 signal(SIGINT, SIG_IGN); 1253 signal(SIGINT, SIG_IGN);
@@ -1241,12 +1257,12 @@ skip:
1241 nalloc = 0; 1257 nalloc = 0;
1242 1258
1243 while (1) { 1259 while (1) {
1244 tv.tv_sec = 10; 1260 prepare_select(&readsetp, &writesetp, &max_fd, &nalloc, &tvp);
1245 tv.tv_usec = 0; 1261 result = select(max_fd + 1, readsetp, writesetp, NULL, tvp);
1246 prepare_select(&readsetp, &writesetp, &max_fd, &nalloc);
1247 result = select(max_fd + 1, readsetp, writesetp, NULL, &tv);
1248 saved_errno = errno; 1262 saved_errno = errno;
1249 reaper(); /* remove expired keys */ 1263 if (parent_alive_interval != 0)
1264 check_parent_exists();
1265 (void) reaper(); /* remove expired keys */
1250 if (result < 0) { 1266 if (result < 0) {
1251 if (saved_errno == EINTR) 1267 if (saved_errno == EINTR)
1252 continue; 1268 continue;