summaryrefslogtreecommitdiff
path: root/ssh-agent.c
diff options
context:
space:
mode:
authorColin Watson <cjwatson@debian.org>2007-12-24 10:29:57 +0000
committerColin Watson <cjwatson@debian.org>2007-12-24 10:29:57 +0000
commitc3e531b12b2335b7fa5a6bcc9a309d3c523ff64b (patch)
treeb72c0867348e7e7914d64af6fc5e25c728922e03 /ssh-agent.c
parent6b222fdf3cb54c11a446df38e027fe7acf2220cb (diff)
parent70847d299887abb96f8703ca99db6d817b78960e (diff)
* New upstream release (closes: #453367).
- CVE-2007-4752: Prevent ssh(1) from using a trusted X11 cookie if creation of an untrusted cookie fails; found and fixed by Jan Pechanec (closes: #444738). - sshd(8) in new installations defaults to SSH Protocol 2 only. Existing installations are unchanged. - The SSH channel window size has been increased, and both ssh(1) sshd(8) now send window updates more aggressively. These improves performance on high-BDP (Bandwidth Delay Product) networks. - ssh(1) and sshd(8) now preserve MAC contexts between packets, which saves 2 hash calls per packet and results in 12-16% speedup for arcfour256/hmac-md5. - A new MAC algorithm has been added, UMAC-64 (RFC4418) as "umac-64@openssh.com". UMAC-64 has been measured to be approximately 20% faster than HMAC-MD5. - Failure to establish a ssh(1) TunnelForward is now treated as a fatal error when the ExitOnForwardFailure option is set. - ssh(1) returns a sensible exit status if the control master goes away without passing the full exit status. - When using a ProxyCommand in ssh(1), set the outgoing hostname with gethostname(2), allowing hostbased authentication to work. - Make scp(1) skip FIFOs rather than hanging (closes: #246774). - Encode non-printing characters in scp(1) filenames. These could cause copies to be aborted with a "protocol error". - Handle SIGINT in sshd(8) privilege separation child process to ensure that wtmp and lastlog records are correctly updated. - Report GSSAPI mechanism in errors, for libraries that support multiple mechanisms. - Improve documentation for ssh-add(1)'s -d option. - Rearrange and tidy GSSAPI code, removing server-only code being linked into the client. - Delay execution of ssh(1)'s LocalCommand until after all forwardings have been established. - In scp(1), do not truncate non-regular files. - Improve exit message from ControlMaster clients. - Prevent sftp-server(8) from reading until it runs out of buffer space, whereupon it would exit with a fatal error (closes: #365541). - pam_end() was not being called if authentication failed (closes: #405041). - Manual page datestamps updated (closes: #433181).
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;