]> andersk Git - openssh.git/blobdiff - ssh-agent.c
- dtucker@cvs.openbsd.org 2007/03/19 12:16:42
[openssh.git] / ssh-agent.c
index a3a867c33b70e7a191c1608eb862f11b7ed34988..c3d5e5a757d9409a4e6289c8c43841ab44f2c6da 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: ssh-agent.c,v 1.154 2007/02/28 00:55:30 dtucker Exp $ */
+/* $OpenBSD: ssh-agent.c,v 1.155 2007/03/19 12:16:42 dtucker Exp $ */
 /*
  * Author: Tatu Ylonen <ylo@cs.hut.fi>
  * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -120,6 +120,7 @@ int max_fd = 0;
 
 /* pid of shell == parent of agent */
 pid_t parent_pid = -1;
+u_int parent_alive_interval = 0;
 
 /* pathname and directory for AUTH_SOCKET */
 char socket_name[MAXPATHLEN];
@@ -421,10 +422,11 @@ process_remove_all_identities(SocketEntry *e, int version)
        buffer_put_char(&e->output, SSH_AGENT_SUCCESS);
 }
 
-static void
+/* removes expired keys and returns number of seconds until the next expiry */
+static u_int
 reaper(void)
 {
-       u_int now = time(NULL);
+       u_int deadline = 0, now = time(NULL);
        Identity *id, *nxt;
        int version;
        Idtab *tab;
@@ -433,14 +435,22 @@ reaper(void)
                tab = idtab_lookup(version);
                for (id = TAILQ_FIRST(&tab->idlist); id; id = nxt) {
                        nxt = TAILQ_NEXT(id, next);
-                       if (id->death != 0 && now >= id->death) {
+                       if (id->death == 0)
+                               continue;
+                       if (now >= id->death) {
                                debug("expiring key '%s'", id->comment);
                                TAILQ_REMOVE(&tab->idlist, id, next);
                                free_identity(id);
                                tab->nentries--;
-                       }
+                       } else
+                               deadline = (deadline == 0) ? id->death :
+                                   MIN(deadline, id->death);
                }
        }
+       if (deadline == 0 || deadline <= now)
+               return 0;
+       else
+               return (deadline - now);
 }
 
 static void
@@ -826,10 +836,12 @@ new_socket(sock_type type, int fd)
 }
 
 static int
-prepare_select(fd_set **fdrp, fd_set **fdwp, int *fdl, u_int *nallocp)
+prepare_select(fd_set **fdrp, fd_set **fdwp, int *fdl, u_int *nallocp,
+    struct timeval **tvpp)
 {
-       u_int i, sz;
+       u_int i, sz, deadline;
        int n = 0;
+       static struct timeval tv;
 
        for (i = 0; i < sockets_alloc; i++) {
                switch (sockets[i].type) {
@@ -873,6 +885,17 @@ prepare_select(fd_set **fdrp, fd_set **fdwp, int *fdl, u_int *nallocp)
                        break;
                }
        }
+       deadline = reaper();
+       if (parent_alive_interval != 0)
+               deadline = (deadline == 0) ? parent_alive_interval :
+                   MIN(deadline, parent_alive_interval);
+       if (deadline == 0) {
+               *tvpp = NULL;
+       } else {
+               tv.tv_sec = deadline;
+               tv.tv_usec = 0;
+               *tvpp = &tv;
+       }
        return (1);
 }
 
@@ -980,19 +1003,14 @@ cleanup_handler(int sig)
        _exit(2);
 }
 
-/*ARGSUSED*/
 static void
-check_parent_exists(int sig)
+check_parent_exists(void)
 {
-       int save_errno = errno;
-
        if (parent_pid != -1 && kill(parent_pid, 0) < 0) {
                /* printf("Parent has died - Authentication agent exiting.\n"); */
-               cleanup_handler(sig); /* safe */
+               cleanup_socket();
+               _exit(2);
        }
-       mysignal(SIGALRM, check_parent_exists);
-       alarm(10);
-       errno = save_errno;
 }
 
 static void
@@ -1027,7 +1045,7 @@ main(int ac, char **av)
        extern char *optarg;
        pid_t pid;
        char pidstrbuf[1 + 3 * sizeof pid];
-       struct timeval tv;
+       struct timeval *tvp = NULL;
 
        /* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */
        sanitise_stdfd();
@@ -1228,10 +1246,8 @@ main(int ac, char **av)
 
 skip:
        new_socket(AUTH_SOCKET, sock);
-       if (ac > 0) {
-               mysignal(SIGALRM, check_parent_exists);
-               alarm(10);
-       }
+       if (ac > 0)
+               parent_alive_interval = 10;
        idtab_init();
        if (!d_flag)
                signal(SIGINT, SIG_IGN);
@@ -1241,12 +1257,12 @@ skip:
        nalloc = 0;
 
        while (1) {
-               tv.tv_sec = 10;
-               tv.tv_usec = 0;
-               prepare_select(&readsetp, &writesetp, &max_fd, &nalloc);
-               result = select(max_fd + 1, readsetp, writesetp, NULL, &tv);
+               prepare_select(&readsetp, &writesetp, &max_fd, &nalloc, &tvp);
+               result = select(max_fd + 1, readsetp, writesetp, NULL, tvp);
                saved_errno = errno;
-               reaper();       /* remove expired keys */
+               if (parent_alive_interval != 0)
+                       check_parent_exists();
+               (void) reaper();        /* remove expired keys */
                if (result < 0) {
                        if (saved_errno == EINTR)
                                continue;
This page took 0.148164 seconds and 4 git commands to generate.