diff options
Diffstat (limited to 'ssh-agent.c')
-rw-r--r-- | ssh-agent.c | 86 |
1 files changed, 58 insertions, 28 deletions
diff --git a/ssh-agent.c b/ssh-agent.c index a69c25eec..a3a867c33 100644 --- a/ssh-agent.c +++ b/ssh-agent.c | |||
@@ -1,3 +1,4 @@ | |||
1 | /* $OpenBSD: ssh-agent.c,v 1.154 2007/02/28 00:55:30 dtucker Exp $ */ | ||
1 | /* | 2 | /* |
2 | * Author: Tatu Ylonen <ylo@cs.hut.fi> | 3 | * Author: Tatu Ylonen <ylo@cs.hut.fi> |
3 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland | 4 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland |
@@ -34,18 +35,40 @@ | |||
34 | */ | 35 | */ |
35 | 36 | ||
36 | #include "includes.h" | 37 | #include "includes.h" |
38 | |||
39 | #include <sys/types.h> | ||
40 | #include <sys/param.h> | ||
41 | #include <sys/resource.h> | ||
42 | #include <sys/stat.h> | ||
43 | #include <sys/socket.h> | ||
44 | #ifdef HAVE_SYS_TIME_H | ||
45 | # include <sys/time.h> | ||
46 | #endif | ||
47 | #ifdef HAVE_SYS_UN_H | ||
48 | # include <sys/un.h> | ||
49 | #endif | ||
37 | #include "openbsd-compat/sys-queue.h" | 50 | #include "openbsd-compat/sys-queue.h" |
38 | RCSID("$OpenBSD: ssh-agent.c,v 1.124 2005/10/30 08:52:18 djm Exp $"); | ||
39 | 51 | ||
40 | #include <openssl/evp.h> | 52 | #include <openssl/evp.h> |
41 | #include <openssl/md5.h> | 53 | #include <openssl/md5.h> |
42 | 54 | ||
55 | #include <errno.h> | ||
56 | #include <fcntl.h> | ||
57 | #ifdef HAVE_PATHS_H | ||
58 | # include <paths.h> | ||
59 | #endif | ||
60 | #include <signal.h> | ||
61 | #include <stdarg.h> | ||
62 | #include <stdio.h> | ||
63 | #include <stdlib.h> | ||
64 | #include <time.h> | ||
65 | #include <string.h> | ||
66 | #include <unistd.h> | ||
67 | |||
68 | #include "xmalloc.h" | ||
43 | #include "ssh.h" | 69 | #include "ssh.h" |
44 | #include "rsa.h" | 70 | #include "rsa.h" |
45 | #include "buffer.h" | 71 | #include "buffer.h" |
46 | #include "bufaux.h" | ||
47 | #include "xmalloc.h" | ||
48 | #include "getput.h" | ||
49 | #include "key.h" | 72 | #include "key.h" |
50 | #include "authfd.h" | 73 | #include "authfd.h" |
51 | #include "compat.h" | 74 | #include "compat.h" |
@@ -99,8 +122,8 @@ int max_fd = 0; | |||
99 | pid_t parent_pid = -1; | 122 | pid_t parent_pid = -1; |
100 | 123 | ||
101 | /* pathname and directory for AUTH_SOCKET */ | 124 | /* pathname and directory for AUTH_SOCKET */ |
102 | char socket_name[1024]; | 125 | char socket_name[MAXPATHLEN]; |
103 | char socket_dir[1024]; | 126 | char socket_dir[MAXPATHLEN]; |
104 | 127 | ||
105 | /* locking */ | 128 | /* locking */ |
106 | int locked = 0; | 129 | int locked = 0; |
@@ -305,8 +328,8 @@ process_sign_request2(SocketEntry *e) | |||
305 | Identity *id = lookup_identity(key, 2); | 328 | Identity *id = lookup_identity(key, 2); |
306 | if (id != NULL && (!id->confirm || confirm_key(id) == 0)) | 329 | if (id != NULL && (!id->confirm || confirm_key(id) == 0)) |
307 | ok = key_sign(id->key, &signature, &slen, data, dlen); | 330 | ok = key_sign(id->key, &signature, &slen, data, dlen); |
331 | key_free(key); | ||
308 | } | 332 | } |
309 | key_free(key); | ||
310 | buffer_init(&msg); | 333 | buffer_init(&msg); |
311 | if (ok == 0) { | 334 | if (ok == 0) { |
312 | buffer_put_char(&msg, SSH2_AGENT_SIGN_RESPONSE); | 335 | buffer_put_char(&msg, SSH2_AGENT_SIGN_RESPONSE); |
@@ -411,6 +434,7 @@ reaper(void) | |||
411 | for (id = TAILQ_FIRST(&tab->idlist); id; id = nxt) { | 434 | for (id = TAILQ_FIRST(&tab->idlist); id; id = nxt) { |
412 | nxt = TAILQ_NEXT(id, next); | 435 | nxt = TAILQ_NEXT(id, next); |
413 | if (id->death != 0 && now >= id->death) { | 436 | if (id->death != 0 && now >= id->death) { |
437 | debug("expiring key '%s'", id->comment); | ||
414 | TAILQ_REMOVE(&tab->idlist, id, next); | 438 | TAILQ_REMOVE(&tab->idlist, id, next); |
415 | free_identity(id); | 439 | free_identity(id); |
416 | tab->nentries--; | 440 | tab->nentries--; |
@@ -675,13 +699,10 @@ process_message(SocketEntry *e) | |||
675 | u_int msg_len, type; | 699 | u_int msg_len, type; |
676 | u_char *cp; | 700 | u_char *cp; |
677 | 701 | ||
678 | /* kill dead keys */ | ||
679 | reaper(); | ||
680 | |||
681 | if (buffer_len(&e->input) < 5) | 702 | if (buffer_len(&e->input) < 5) |
682 | return; /* Incomplete message. */ | 703 | return; /* Incomplete message. */ |
683 | cp = buffer_ptr(&e->input); | 704 | cp = buffer_ptr(&e->input); |
684 | msg_len = GET_32BIT(cp); | 705 | msg_len = get_u32(cp); |
685 | if (msg_len > 256 * 1024) { | 706 | if (msg_len > 256 * 1024) { |
686 | close_socket(e); | 707 | close_socket(e); |
687 | return; | 708 | return; |
@@ -793,10 +814,7 @@ new_socket(sock_type type, int fd) | |||
793 | } | 814 | } |
794 | old_alloc = sockets_alloc; | 815 | old_alloc = sockets_alloc; |
795 | new_alloc = sockets_alloc + 10; | 816 | new_alloc = sockets_alloc + 10; |
796 | if (sockets) | 817 | sockets = xrealloc(sockets, new_alloc, sizeof(sockets[0])); |
797 | sockets = xrealloc(sockets, new_alloc * sizeof(sockets[0])); | ||
798 | else | ||
799 | sockets = xmalloc(new_alloc * sizeof(sockets[0])); | ||
800 | for (i = old_alloc; i < new_alloc; i++) | 818 | for (i = old_alloc; i < new_alloc; i++) |
801 | sockets[i].type = AUTH_UNUSED; | 819 | sockets[i].type = AUTH_UNUSED; |
802 | sockets_alloc = new_alloc; | 820 | sockets_alloc = new_alloc; |
@@ -877,7 +895,7 @@ after_select(fd_set *readset, fd_set *writeset) | |||
877 | if (FD_ISSET(sockets[i].fd, readset)) { | 895 | if (FD_ISSET(sockets[i].fd, readset)) { |
878 | slen = sizeof(sunaddr); | 896 | slen = sizeof(sunaddr); |
879 | sock = accept(sockets[i].fd, | 897 | sock = accept(sockets[i].fd, |
880 | (struct sockaddr *) &sunaddr, &slen); | 898 | (struct sockaddr *)&sunaddr, &slen); |
881 | if (sock < 0) { | 899 | if (sock < 0) { |
882 | error("accept from AUTH_SOCKET: %s", | 900 | error("accept from AUTH_SOCKET: %s", |
883 | strerror(errno)); | 901 | strerror(errno)); |
@@ -954,6 +972,7 @@ cleanup_exit(int i) | |||
954 | _exit(i); | 972 | _exit(i); |
955 | } | 973 | } |
956 | 974 | ||
975 | /*ARGSUSED*/ | ||
957 | static void | 976 | static void |
958 | cleanup_handler(int sig) | 977 | cleanup_handler(int sig) |
959 | { | 978 | { |
@@ -961,6 +980,7 @@ cleanup_handler(int sig) | |||
961 | _exit(2); | 980 | _exit(2); |
962 | } | 981 | } |
963 | 982 | ||
983 | /*ARGSUSED*/ | ||
964 | static void | 984 | static void |
965 | check_parent_exists(int sig) | 985 | check_parent_exists(int sig) |
966 | { | 986 | { |
@@ -994,7 +1014,7 @@ int | |||
994 | main(int ac, char **av) | 1014 | main(int ac, char **av) |
995 | { | 1015 | { |
996 | int c_flag = 0, d_flag = 0, k_flag = 0, s_flag = 0; | 1016 | int c_flag = 0, d_flag = 0, k_flag = 0, s_flag = 0; |
997 | int sock, fd, ch; | 1017 | int sock, fd, ch, result, saved_errno; |
998 | u_int nalloc; | 1018 | u_int nalloc; |
999 | char *shell, *format, *pidstr, *agentsocket = NULL; | 1019 | char *shell, *format, *pidstr, *agentsocket = NULL; |
1000 | fd_set *readsetp = NULL, *writesetp = NULL; | 1020 | fd_set *readsetp = NULL, *writesetp = NULL; |
@@ -1007,6 +1027,7 @@ main(int ac, char **av) | |||
1007 | extern char *optarg; | 1027 | extern char *optarg; |
1008 | pid_t pid; | 1028 | pid_t pid; |
1009 | char pidstrbuf[1 + 3 * sizeof pid]; | 1029 | char pidstrbuf[1 + 3 * sizeof pid]; |
1030 | struct timeval tv; | ||
1010 | 1031 | ||
1011 | /* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */ | 1032 | /* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */ |
1012 | sanitise_stdfd(); | 1033 | sanitise_stdfd(); |
@@ -1067,20 +1088,24 @@ main(int ac, char **av) | |||
1067 | 1088 | ||
1068 | if (ac == 0 && !c_flag && !s_flag) { | 1089 | if (ac == 0 && !c_flag && !s_flag) { |
1069 | shell = getenv("SHELL"); | 1090 | shell = getenv("SHELL"); |
1070 | if (shell != NULL && strncmp(shell + strlen(shell) - 3, "csh", 3) == 0) | 1091 | if (shell != NULL && |
1092 | strncmp(shell + strlen(shell) - 3, "csh", 3) == 0) | ||
1071 | c_flag = 1; | 1093 | c_flag = 1; |
1072 | } | 1094 | } |
1073 | if (k_flag) { | 1095 | if (k_flag) { |
1096 | const char *errstr = NULL; | ||
1097 | |||
1074 | pidstr = getenv(SSH_AGENTPID_ENV_NAME); | 1098 | pidstr = getenv(SSH_AGENTPID_ENV_NAME); |
1075 | if (pidstr == NULL) { | 1099 | if (pidstr == NULL) { |
1076 | fprintf(stderr, "%s not set, cannot kill agent\n", | 1100 | fprintf(stderr, "%s not set, cannot kill agent\n", |
1077 | SSH_AGENTPID_ENV_NAME); | 1101 | SSH_AGENTPID_ENV_NAME); |
1078 | exit(1); | 1102 | exit(1); |
1079 | } | 1103 | } |
1080 | pid = atoi(pidstr); | 1104 | pid = (int)strtonum(pidstr, 2, INT_MAX, &errstr); |
1081 | if (pid < 1) { | 1105 | if (errstr) { |
1082 | fprintf(stderr, "%s=\"%s\", which is not a good PID\n", | 1106 | fprintf(stderr, |
1083 | SSH_AGENTPID_ENV_NAME, pidstr); | 1107 | "%s=\"%s\", which is not a good PID: %s\n", |
1108 | SSH_AGENTPID_ENV_NAME, pidstr, errstr); | ||
1084 | exit(1); | 1109 | exit(1); |
1085 | } | 1110 | } |
1086 | if (kill(pid, SIGTERM) == -1) { | 1111 | if (kill(pid, SIGTERM) == -1) { |
@@ -1124,7 +1149,7 @@ main(int ac, char **av) | |||
1124 | sunaddr.sun_family = AF_UNIX; | 1149 | sunaddr.sun_family = AF_UNIX; |
1125 | strlcpy(sunaddr.sun_path, socket_name, sizeof(sunaddr.sun_path)); | 1150 | strlcpy(sunaddr.sun_path, socket_name, sizeof(sunaddr.sun_path)); |
1126 | prev_mask = umask(0177); | 1151 | prev_mask = umask(0177); |
1127 | if (bind(sock, (struct sockaddr *) & sunaddr, sizeof(sunaddr)) < 0) { | 1152 | if (bind(sock, (struct sockaddr *) &sunaddr, sizeof(sunaddr)) < 0) { |
1128 | perror("bind"); | 1153 | perror("bind"); |
1129 | *socket_name = '\0'; /* Don't unlink any existing file */ | 1154 | *socket_name = '\0'; /* Don't unlink any existing file */ |
1130 | umask(prev_mask); | 1155 | umask(prev_mask); |
@@ -1216,13 +1241,18 @@ skip: | |||
1216 | nalloc = 0; | 1241 | nalloc = 0; |
1217 | 1242 | ||
1218 | while (1) { | 1243 | while (1) { |
1244 | tv.tv_sec = 10; | ||
1245 | tv.tv_usec = 0; | ||
1219 | prepare_select(&readsetp, &writesetp, &max_fd, &nalloc); | 1246 | prepare_select(&readsetp, &writesetp, &max_fd, &nalloc); |
1220 | if (select(max_fd + 1, readsetp, writesetp, NULL, NULL) < 0) { | 1247 | result = select(max_fd + 1, readsetp, writesetp, NULL, &tv); |
1221 | if (errno == EINTR) | 1248 | saved_errno = errno; |
1249 | reaper(); /* remove expired keys */ | ||
1250 | if (result < 0) { | ||
1251 | if (saved_errno == EINTR) | ||
1222 | continue; | 1252 | continue; |
1223 | fatal("select: %s", strerror(errno)); | 1253 | fatal("select: %s", strerror(saved_errno)); |
1224 | } | 1254 | } else if (result > 0) |
1225 | after_select(readsetp, writesetp); | 1255 | after_select(readsetp, writesetp); |
1226 | } | 1256 | } |
1227 | /* NOTREACHED */ | 1257 | /* NOTREACHED */ |
1228 | } | 1258 | } |