X-Git-Url: http://andersk.mit.edu/gitweb/gssapi-openssh.git/blobdiff_plain/7cac2b656d969b64094f20b40ddcaca5ac1ca924..9c0efabdc5f81e0d6ddd027ffb91e9e7ef57993a:/openssh/ssh-agent.c diff --git a/openssh/ssh-agent.c b/openssh/ssh-agent.c index c05c614..ef95eb8 100644 --- a/openssh/ssh-agent.c +++ b/openssh/ssh-agent.c @@ -1,3 +1,4 @@ +/* $OpenBSD: ssh-agent.c,v 1.153 2006/10/06 02:29:19 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -34,29 +35,54 @@ */ #include "includes.h" + +#include +#include +#include +#include +#include +#ifdef HAVE_SYS_TIME_H +# include +#endif +#ifdef HAVE_SYS_UN_H +# include +#endif #include "openbsd-compat/sys-queue.h" -RCSID("$OpenBSD: ssh-agent.c,v 1.111 2003/06/12 19:12:03 markus Exp $"); #include #include +#include +#include +#ifdef HAVE_PATHS_H +# include +#endif +#include +#include +#include +#include +#include +#include +#include + +#include "xmalloc.h" #include "ssh.h" #include "rsa.h" #include "buffer.h" -#include "bufaux.h" -#include "xmalloc.h" -#include "getput.h" #include "key.h" #include "authfd.h" #include "compat.h" #include "log.h" -#include "readpass.h" #include "misc.h" #ifdef SMARTCARD #include "scard.h" #endif +#if defined(HAVE_SYS_PRCTL_H) +#include /* For prctl() and PR_SET_DUMPABLE */ +#endif + typedef enum { AUTH_UNUSED, AUTH_SOCKET, @@ -96,18 +122,14 @@ int max_fd = 0; pid_t parent_pid = -1; /* pathname and directory for AUTH_SOCKET */ -char socket_name[1024]; -char socket_dir[1024]; +char socket_name[MAXPATHLEN]; +char socket_dir[MAXPATHLEN]; /* locking */ int locked = 0; char *lock_passwd = NULL; -#ifdef HAVE___PROGNAME extern char *__progname; -#else -char *__progname; -#endif /* Default lifetime (0 == forever) */ static int lifetime = 0; @@ -169,23 +191,15 @@ lookup_identity(Key *key, int version) static int confirm_key(Identity *id) { - char *p, prompt[1024]; + char *p; int ret = -1; p = key_fingerprint(id->key, SSH_FP_MD5, SSH_FP_HEX); - snprintf(prompt, sizeof(prompt), "Allow use of key %s?\n" - "Key fingerprint %s.", id->comment, p); + if (ask_permission("Allow use of key %s?\nKey fingerprint %s.", + id->comment, p)) + ret = 0; xfree(p); - p = read_passphrase(prompt, RP_ALLOW_EOF); - if (p != NULL) { - /* - * Accept empty responses and responses consisting - * of the word "yes" as affirmative. - */ - if (*p == '\0' || *p == '\n' || strcasecmp(p, "yes") == 0) - ret = 0; - xfree(p); - } + return (ret); } @@ -314,8 +328,8 @@ process_sign_request2(SocketEntry *e) Identity *id = lookup_identity(key, 2); if (id != NULL && (!id->confirm || confirm_key(id) == 0)) ok = key_sign(id->key, &signature, &slen, data, dlen); + key_free(key); } - key_free(key); buffer_init(&msg); if (ok == 0) { buffer_put_char(&msg, SSH2_AGENT_SIGN_RESPONSE); @@ -364,7 +378,7 @@ process_remove_identity(SocketEntry *e, int version) if (id != NULL) { /* * We have this key. Free the old key. Since we - * don\'t want to leave empty slots in the middle of + * don't want to leave empty slots in the middle of * the array, we actually free the key there and move * all the entries between the empty slot and the end * of the array. @@ -690,7 +704,7 @@ process_message(SocketEntry *e) if (buffer_len(&e->input) < 5) return; /* Incomplete message. */ cp = buffer_ptr(&e->input); - msg_len = GET_32BIT(cp); + msg_len = get_u32(cp); if (msg_len > 256 * 1024) { close_socket(e); return; @@ -784,10 +798,9 @@ process_message(SocketEntry *e) static void new_socket(sock_type type, int fd) { - u_int i, old_alloc; + u_int i, old_alloc, new_alloc; - if (fcntl(fd, F_SETFL, O_NONBLOCK) < 0) - error("fcntl O_NONBLOCK: %s", strerror(errno)); + set_nonblock(fd); if (fd > max_fd) max_fd = fd; @@ -795,29 +808,27 @@ new_socket(sock_type type, int fd) for (i = 0; i < sockets_alloc; i++) if (sockets[i].type == AUTH_UNUSED) { sockets[i].fd = fd; - sockets[i].type = type; buffer_init(&sockets[i].input); buffer_init(&sockets[i].output); buffer_init(&sockets[i].request); + sockets[i].type = type; return; } old_alloc = sockets_alloc; - sockets_alloc += 10; - if (sockets) - sockets = xrealloc(sockets, sockets_alloc * sizeof(sockets[0])); - else - sockets = xmalloc(sockets_alloc * sizeof(sockets[0])); - for (i = old_alloc; i < sockets_alloc; i++) + new_alloc = sockets_alloc + 10; + sockets = xrealloc(sockets, new_alloc, sizeof(sockets[0])); + for (i = old_alloc; i < new_alloc; i++) sockets[i].type = AUTH_UNUSED; - sockets[old_alloc].type = type; + sockets_alloc = new_alloc; sockets[old_alloc].fd = fd; buffer_init(&sockets[old_alloc].input); buffer_init(&sockets[old_alloc].output); buffer_init(&sockets[old_alloc].request); + sockets[old_alloc].type = type; } static int -prepare_select(fd_set **fdrp, fd_set **fdwp, int *fdl, int *nallocp) +prepare_select(fd_set **fdrp, fd_set **fdwp, int *fdl, u_int *nallocp) { u_int i, sz; int n = 0; @@ -886,7 +897,7 @@ after_select(fd_set *readset, fd_set *writeset) if (FD_ISSET(sockets[i].fd, readset)) { slen = sizeof(sunaddr); sock = accept(sockets[i].fd, - (struct sockaddr *) &sunaddr, &slen); + (struct sockaddr *)&sunaddr, &slen); if (sock < 0) { error("accept from AUTH_SOCKET: %s", strerror(errno)); @@ -948,7 +959,7 @@ after_select(fd_set *readset, fd_set *writeset) } static void -cleanup_socket(void *p) +cleanup_socket(void) { if (socket_name[0]) unlink(socket_name); @@ -956,20 +967,22 @@ cleanup_socket(void *p) rmdir(socket_dir); } -static void +void cleanup_exit(int i) { - cleanup_socket(NULL); - exit(i); + cleanup_socket(); + _exit(i); } +/*ARGSUSED*/ static void cleanup_handler(int sig) { - cleanup_socket(NULL); + cleanup_socket(); _exit(2); } +/*ARGSUSED*/ static void check_parent_exists(int sig) { @@ -1003,25 +1016,32 @@ int main(int ac, char **av) { int c_flag = 0, d_flag = 0, k_flag = 0, s_flag = 0; - int sock, fd, ch, nalloc; + int sock, fd, ch; + u_int nalloc; char *shell, *format, *pidstr, *agentsocket = NULL; fd_set *readsetp = NULL, *writesetp = NULL; struct sockaddr_un sunaddr; #ifdef HAVE_SETRLIMIT struct rlimit rlim; #endif -#ifdef HAVE_CYGWIN int prev_mask; -#endif extern int optind; extern char *optarg; pid_t pid; char pidstrbuf[1 + 3 * sizeof pid]; + /* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */ + sanitise_stdfd(); + /* drop */ setegid(getgid()); setgid(getgid()); +#if defined(HAVE_PRCTL) && defined(PR_SET_DUMPABLE) + /* Disable ptrace on Linux without sgid bit */ + prctl(PR_SET_DUMPABLE, 0); +#endif + SSLeay_add_all_algorithms(); __progname = ssh_get_progname(av[0]); @@ -1069,20 +1089,24 @@ main(int ac, char **av) if (ac == 0 && !c_flag && !s_flag) { shell = getenv("SHELL"); - if (shell != NULL && strncmp(shell + strlen(shell) - 3, "csh", 3) == 0) + if (shell != NULL && + strncmp(shell + strlen(shell) - 3, "csh", 3) == 0) c_flag = 1; } if (k_flag) { + const char *errstr = NULL; + pidstr = getenv(SSH_AGENTPID_ENV_NAME); if (pidstr == NULL) { fprintf(stderr, "%s not set, cannot kill agent\n", SSH_AGENTPID_ENV_NAME); exit(1); } - pid = atoi(pidstr); - if (pid < 1) { - fprintf(stderr, "%s=\"%s\", which is not a good PID\n", - SSH_AGENTPID_ENV_NAME, pidstr); + pid = (int)strtonum(pidstr, 2, INT_MAX, &errstr); + if (errstr) { + fprintf(stderr, + "%s=\"%s\", which is not a good PID: %s\n", + SSH_AGENTPID_ENV_NAME, pidstr, errstr); exit(1); } if (kill(pid, SIGTERM) == -1) { @@ -1099,7 +1123,7 @@ main(int ac, char **av) if (agentsocket == NULL) { /* Create private directory for agent socket */ - strlcpy(socket_dir, "/tmp/ssh-XXXXXXXX", sizeof socket_dir); + strlcpy(socket_dir, "/tmp/ssh-XXXXXXXXXX", sizeof socket_dir); if (mkdtemp(socket_dir) == NULL) { perror("mkdtemp: private socket dir"); exit(1); @@ -1119,25 +1143,21 @@ main(int ac, char **av) sock = socket(AF_UNIX, SOCK_STREAM, 0); if (sock < 0) { perror("socket"); + *socket_name = '\0'; /* Don't unlink any existing file */ cleanup_exit(1); } memset(&sunaddr, 0, sizeof(sunaddr)); sunaddr.sun_family = AF_UNIX; strlcpy(sunaddr.sun_path, socket_name, sizeof(sunaddr.sun_path)); -#ifdef HAVE_CYGWIN prev_mask = umask(0177); -#endif - if (bind(sock, (struct sockaddr *) & sunaddr, sizeof(sunaddr)) < 0) { + if (bind(sock, (struct sockaddr *) &sunaddr, sizeof(sunaddr)) < 0) { perror("bind"); -#ifdef HAVE_CYGWIN + *socket_name = '\0'; /* Don't unlink any existing file */ umask(prev_mask); -#endif cleanup_exit(1); } -#ifdef HAVE_CYGWIN umask(prev_mask); -#endif - if (listen(sock, 128) < 0) { + if (listen(sock, SSH_LISTEN_BACKLOG) < 0) { perror("listen"); cleanup_exit(1); } @@ -1208,7 +1228,6 @@ main(int ac, char **av) #endif skip: - fatal_add_cleanup(cleanup_socket, NULL); new_socket(AUTH_SOCKET, sock); if (ac > 0) { mysignal(SIGALRM, check_parent_exists);