summaryrefslogtreecommitdiff
path: root/ssh-agent.c
diff options
context:
space:
mode:
Diffstat (limited to 'ssh-agent.c')
-rw-r--r--ssh-agent.c86
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"
38RCSID("$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;
99pid_t parent_pid = -1; 122pid_t parent_pid = -1;
100 123
101/* pathname and directory for AUTH_SOCKET */ 124/* pathname and directory for AUTH_SOCKET */
102char socket_name[1024]; 125char socket_name[MAXPATHLEN];
103char socket_dir[1024]; 126char socket_dir[MAXPATHLEN];
104 127
105/* locking */ 128/* locking */
106int locked = 0; 129int 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*/
957static void 976static void
958cleanup_handler(int sig) 977cleanup_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*/
964static void 984static void
965check_parent_exists(int sig) 985check_parent_exists(int sig)
966{ 986{
@@ -994,7 +1014,7 @@ int
994main(int ac, char **av) 1014main(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}