diff options
author | Damien Miller <djm@mindrot.org> | 1999-10-29 09:47:09 +1000 |
---|---|---|
committer | Damien Miller <djm@mindrot.org> | 1999-10-29 09:47:09 +1000 |
commit | 792c5113f1ba364680d294806ac0972b3deaceec (patch) | |
tree | 8b115d4108aec7423994efca34ec6a9f67c7b370 /ssh-agent.c | |
parent | a37010e4669933490c2347940bceba98ddfc2863 (diff) |
Update to OpenBSD ssh-19991029
Renamed init script and PAM config
Diffstat (limited to 'ssh-agent.c')
-rw-r--r-- | ssh-agent.c | 177 |
1 files changed, 139 insertions, 38 deletions
diff --git a/ssh-agent.c b/ssh-agent.c index 56618ade..a9d2a142 100644 --- a/ssh-agent.c +++ b/ssh-agent.c @@ -1,3 +1,5 @@ +/* $OpenBSD: ssh-agent.c,v 1.15 1999/10/28 08:43:10 markus Exp $ */ + /* ssh-agent.c @@ -15,7 +17,7 @@ The authentication agent program. #include "config.h" #include "includes.h" -RCSID("$Id: ssh-agent.c,v 1.3 1999/10/28 05:23:30 damien Exp $"); +RCSID("$OpenBSD: ssh-agent.c,v 1.15 1999/10/28 08:43:10 markus Exp $"); #include "ssh.h" #include "rsa.h" @@ -482,17 +484,39 @@ check_parent_exists(int sig) alarm(10); } -void cleanup_socket(void) { +void +cleanup_socket(void) +{ remove(socket_name); rmdir(socket_dir); } +void +cleanup_exit(int i) +{ + cleanup_socket(); + exit(i); +} + +void +usage() +{ + extern char *__progname; + + fprintf(stderr, "ssh-agent version %s\n", SSH_VERSION); + fprintf(stderr, "Usage: %s [-c | -s] [-k] [command {args...]]\n", + __progname); + exit(1); +} + int main(int ac, char **av) { fd_set readset, writeset; - int sock; + int sock, c_flag = 0, k_flag = 0, s_flag = 0, ch; struct sockaddr_un sunaddr; + pid_t pid; + char *shell, *format, *pidstr, pidstrbuf[1 + 3 * sizeof pid]; /* check if RSA support exists */ if (rsa_alive() == 0) { @@ -503,11 +527,66 @@ main(int ac, char **av) exit(1); } - if (ac < 2) + while ((ch = getopt(ac, av, "cks")) != -1) { - fprintf(stderr, "ssh-agent version %s\n", SSH_VERSION); - fprintf(stderr, "Usage: %s command\n", av[0]); - exit(1); + switch (ch) + { + case 'c': + if (s_flag) + usage(); + c_flag++; + break; + case 'k': + k_flag++; + break; + case 's': + if (c_flag) + usage(); + s_flag++; + break; + default: + usage(); + } + } + ac -= optind; + av += optind; + + if (ac > 0 && (c_flag || k_flag || s_flag)) + usage(); + + if (ac == 0 && !c_flag && !k_flag && !s_flag) + { + shell = getenv("SHELL"); + if (shell != NULL && strncmp(shell + strlen(shell) - 3, "csh", 3) == 0) + c_flag = 1; + } + + if (k_flag) + { + 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) /* XXX PID_MAX check too */ + { + fprintf(stderr, "%s=\"%s\", which is not a good PID\n", + SSH_AGENTPID_ENV_NAME, pidstr); + exit(1); + } + if (kill(pid, SIGTERM) == -1) + { + perror("kill"); + exit(1); + } + format = c_flag ? "unsetenv %s;\n" : "unset %s;\n"; + printf(format, SSH_AUTHSOCKET_ENV_NAME); + printf(format, SSH_AGENTPID_ENV_NAME); + printf("echo Agent pid %d killed;\n", pid); + exit(0); } parent_pid = getpid(); @@ -518,38 +597,16 @@ main(int ac, char **av) perror("mkdtemp: private socket dir"); exit(1); } - snprintf(socket_name, sizeof socket_name, "%s/agent.%d", socket_dir, parent_pid); - - /* Fork, and have the parent execute the command. The child continues as - the authentication agent. */ - if (fork() != 0) - { /* Parent - execute the given command. */ - setenv(SSH_AUTHSOCKET_ENV_NAME, socket_name, 1); - execvp(av[1], av + 1); - perror(av[1]); - exit(1); - } - - if (atexit(cleanup_socket) < 0) { - perror("atexit"); - cleanup_socket(); - exit(1); - } - - /* Create a new session and process group */ - if (setsid() < 0) { - perror("setsid failed"); - exit(1); - } - - /* Ignore if a client dies while we are sending a reply */ - signal(SIGPIPE, SIG_IGN); + snprintf(socket_name, sizeof socket_name, "%s/agent.%d", socket_dir, + parent_pid); + /* Create socket early so it will exist before command gets run from + the parent. */ sock = socket(AF_UNIX, SOCK_STREAM, 0); if (sock < 0) { perror("socket"); - exit(1); + cleanup_exit(1); } memset(&sunaddr, 0, sizeof(sunaddr)); sunaddr.sun_family = AF_UNIX; @@ -557,18 +614,63 @@ main(int ac, char **av) if (bind(sock, (struct sockaddr *)&sunaddr, sizeof(sunaddr)) < 0) { perror("bind"); - exit(1); + cleanup_exit(1); } if (listen(sock, 5) < 0) { perror("listen"); + cleanup_exit(1); + } + + /* Fork, and have the parent execute the command, if any, or present the + socket data. The child continues as the authentication agent. */ + pid = fork(); + if (pid == -1) + { + perror("fork"); exit(1); } + if (pid != 0) + { /* Parent - execute the given command. */ + close(sock); + snprintf(pidstrbuf, sizeof pidstrbuf, "%d", pid); + if (ac == 0) + { + format = c_flag ? "setenv %s %s;\n" : "%s=%s; export %s;\n"; + printf(format, SSH_AUTHSOCKET_ENV_NAME, socket_name, + SSH_AUTHSOCKET_ENV_NAME); + printf(format, SSH_AGENTPID_ENV_NAME, pidstrbuf, + SSH_AGENTPID_ENV_NAME); + printf("echo Agent pid %d;\n", pid); + exit(0); + } + + setenv(SSH_AUTHSOCKET_ENV_NAME, socket_name, 1); + setenv(SSH_AGENTPID_ENV_NAME, pidstrbuf, 1); + execvp(av[0], av); + perror(av[0]); + exit(1); + } + + close(0); + close(1); + close(2); + + if (ac == 0 && setsid() == -1) + cleanup_exit(1); + + if (atexit(cleanup_socket) < 0) + cleanup_exit(1); + new_socket(AUTH_SOCKET, sock); - signal(SIGALRM, check_parent_exists); - alarm(10); + if (ac > 0) + { + signal(SIGALRM, check_parent_exists); + alarm(10); + } signal(SIGINT, SIG_IGN); + signal(SIGPIPE, SIG_IGN); while (1) { FD_ZERO(&readset); @@ -578,7 +680,6 @@ main(int ac, char **av) { if (errno == EINTR) continue; - perror("select"); exit(1); } after_select(&readset, &writeset); |