diff options
Diffstat (limited to 'ssh-agent.c')
-rw-r--r-- | ssh-agent.c | 101 |
1 files changed, 67 insertions, 34 deletions
diff --git a/ssh-agent.c b/ssh-agent.c index 55704e492..bc577e76a 100644 --- a/ssh-agent.c +++ b/ssh-agent.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: ssh-agent.c,v 1.45 2000/12/19 23:17:58 markus Exp $ */ | 1 | /* $OpenBSD: ssh-agent.c,v 1.47 2001/01/21 19:05:56 markus Exp $ */ |
2 | 2 | ||
3 | /* | 3 | /* |
4 | * Author: Tatu Ylonen <ylo@cs.hut.fi> | 4 | * Author: Tatu Ylonen <ylo@cs.hut.fi> |
@@ -37,7 +37,10 @@ | |||
37 | */ | 37 | */ |
38 | 38 | ||
39 | #include "includes.h" | 39 | #include "includes.h" |
40 | RCSID("$OpenBSD: ssh-agent.c,v 1.45 2000/12/19 23:17:58 markus Exp $"); | 40 | RCSID("$OpenBSD: ssh-agent.c,v 1.47 2001/01/21 19:05:56 markus Exp $"); |
41 | |||
42 | #include <openssl/evp.h> | ||
43 | #include <openssl/md5.h> | ||
41 | 44 | ||
42 | #include "ssh.h" | 45 | #include "ssh.h" |
43 | #include "rsa.h" | 46 | #include "rsa.h" |
@@ -47,15 +50,12 @@ RCSID("$OpenBSD: ssh-agent.c,v 1.45 2000/12/19 23:17:58 markus Exp $"); | |||
47 | #include "packet.h" | 50 | #include "packet.h" |
48 | #include "getput.h" | 51 | #include "getput.h" |
49 | #include "mpaux.h" | 52 | #include "mpaux.h" |
50 | |||
51 | #include <openssl/evp.h> | ||
52 | #include <openssl/md5.h> | ||
53 | #include <openssl/dsa.h> | ||
54 | #include <openssl/rsa.h> | ||
55 | #include "key.h" | 53 | #include "key.h" |
56 | #include "authfd.h" | 54 | #include "authfd.h" |
55 | #include "cipher.h" | ||
57 | #include "kex.h" | 56 | #include "kex.h" |
58 | #include "compat.h" | 57 | #include "compat.h" |
58 | #include "log.h" | ||
59 | 59 | ||
60 | typedef struct { | 60 | typedef struct { |
61 | int fd; | 61 | int fd; |
@@ -97,6 +97,8 @@ extern char *__progname; | |||
97 | char *__progname; | 97 | char *__progname; |
98 | #endif | 98 | #endif |
99 | 99 | ||
100 | int prepare_select(fd_set **, fd_set **, int *); | ||
101 | |||
100 | void | 102 | void |
101 | idtab_init(void) | 103 | idtab_init(void) |
102 | { | 104 | { |
@@ -293,7 +295,7 @@ process_remove_identity(SocketEntry *e, int version) | |||
293 | 295 | ||
294 | if (bits != key_size(key)) | 296 | if (bits != key_size(key)) |
295 | log("Warning: identity keysize mismatch: actual %d, announced %d", | 297 | log("Warning: identity keysize mismatch: actual %d, announced %d", |
296 | key_size(key), bits); | 298 | key_size(key), bits); |
297 | break; | 299 | break; |
298 | case 2: | 300 | case 2: |
299 | blob = buffer_get_string(&e->input, &blen); | 301 | blob = buffer_get_string(&e->input, &blen); |
@@ -388,7 +390,7 @@ process_add_identity(SocketEntry *e, int version) | |||
388 | switch (version) { | 390 | switch (version) { |
389 | case 1: | 391 | case 1: |
390 | k = key_new_private(KEY_RSA1); | 392 | k = key_new_private(KEY_RSA1); |
391 | buffer_get_int(&e->input); /* ignored */ | 393 | buffer_get_int(&e->input); /* ignored */ |
392 | buffer_get_bignum(&e->input, k->rsa->n); | 394 | buffer_get_bignum(&e->input, k->rsa->n); |
393 | buffer_get_bignum(&e->input, k->rsa->e); | 395 | buffer_get_bignum(&e->input, k->rsa->e); |
394 | buffer_get_bignum(&e->input, k->rsa->d); | 396 | buffer_get_bignum(&e->input, k->rsa->d); |
@@ -403,7 +405,7 @@ process_add_identity(SocketEntry *e, int version) | |||
403 | break; | 405 | break; |
404 | case 2: | 406 | case 2: |
405 | type_name = buffer_get_string(&e->input, NULL); | 407 | type_name = buffer_get_string(&e->input, NULL); |
406 | type = key_type_from_name(type_name); | 408 | type = key_type_from_name(type_name); |
407 | xfree(type_name); | 409 | xfree(type_name); |
408 | switch(type) { | 410 | switch(type) { |
409 | case KEY_DSA: | 411 | case KEY_DSA: |
@@ -556,17 +558,17 @@ new_socket(int type, int fd) | |||
556 | buffer_init(&sockets[old_alloc].output); | 558 | buffer_init(&sockets[old_alloc].output); |
557 | } | 559 | } |
558 | 560 | ||
559 | void | 561 | int |
560 | prepare_select(fd_set *readset, fd_set *writeset) | 562 | prepare_select(fd_set **fdrp, fd_set **fdwp, int *fdl) |
561 | { | 563 | { |
562 | u_int i; | 564 | u_int i, sz; |
563 | for (i = 0; i < sockets_alloc; i++) | 565 | int n = 0; |
566 | |||
567 | for (i = 0; i < sockets_alloc; i++) { | ||
564 | switch (sockets[i].type) { | 568 | switch (sockets[i].type) { |
565 | case AUTH_SOCKET: | 569 | case AUTH_SOCKET: |
566 | case AUTH_CONNECTION: | 570 | case AUTH_CONNECTION: |
567 | FD_SET(sockets[i].fd, readset); | 571 | n = MAX(n, sockets[i].fd); |
568 | if (buffer_len(&sockets[i].output) > 0) | ||
569 | FD_SET(sockets[i].fd, writeset); | ||
570 | break; | 572 | break; |
571 | case AUTH_UNUSED: | 573 | case AUTH_UNUSED: |
572 | break; | 574 | break; |
@@ -574,6 +576,34 @@ prepare_select(fd_set *readset, fd_set *writeset) | |||
574 | fatal("Unknown socket type %d", sockets[i].type); | 576 | fatal("Unknown socket type %d", sockets[i].type); |
575 | break; | 577 | break; |
576 | } | 578 | } |
579 | } | ||
580 | |||
581 | sz = howmany(n+1, NFDBITS) * sizeof(fd_mask); | ||
582 | if (*fdrp == NULL || n > *fdl) { | ||
583 | if (*fdrp) | ||
584 | free(*fdrp); | ||
585 | if (*fdwp) | ||
586 | free(*fdwp); | ||
587 | *fdrp = xmalloc(sz); | ||
588 | *fdwp = xmalloc(sz); | ||
589 | *fdl = n; | ||
590 | } | ||
591 | memset(*fdrp, 0, sz); | ||
592 | memset(*fdwp, 0, sz); | ||
593 | |||
594 | for (i = 0; i < sockets_alloc; i++) { | ||
595 | switch (sockets[i].type) { | ||
596 | case AUTH_SOCKET: | ||
597 | case AUTH_CONNECTION: | ||
598 | FD_SET(sockets[i].fd, *fdrp); | ||
599 | if (buffer_len(&sockets[i].output) > 0) | ||
600 | FD_SET(sockets[i].fd, *fdwp); | ||
601 | break; | ||
602 | default: | ||
603 | break; | ||
604 | } | ||
605 | } | ||
606 | return (1); | ||
577 | } | 607 | } |
578 | 608 | ||
579 | void | 609 | void |
@@ -592,7 +622,8 @@ after_select(fd_set *readset, fd_set *writeset) | |||
592 | case AUTH_SOCKET: | 622 | case AUTH_SOCKET: |
593 | if (FD_ISSET(sockets[i].fd, readset)) { | 623 | if (FD_ISSET(sockets[i].fd, readset)) { |
594 | slen = sizeof(sunaddr); | 624 | slen = sizeof(sunaddr); |
595 | sock = accept(sockets[i].fd, (struct sockaddr *) & sunaddr, &slen); | 625 | sock = accept(sockets[i].fd, |
626 | (struct sockaddr *) &sunaddr, &slen); | ||
596 | if (sock < 0) { | 627 | if (sock < 0) { |
597 | perror("accept from AUTH_SOCKET"); | 628 | perror("accept from AUTH_SOCKET"); |
598 | break; | 629 | break; |
@@ -603,8 +634,9 @@ after_select(fd_set *readset, fd_set *writeset) | |||
603 | case AUTH_CONNECTION: | 634 | case AUTH_CONNECTION: |
604 | if (buffer_len(&sockets[i].output) > 0 && | 635 | if (buffer_len(&sockets[i].output) > 0 && |
605 | FD_ISSET(sockets[i].fd, writeset)) { | 636 | FD_ISSET(sockets[i].fd, writeset)) { |
606 | len = write(sockets[i].fd, buffer_ptr(&sockets[i].output), | 637 | len = write(sockets[i].fd, |
607 | buffer_len(&sockets[i].output)); | 638 | buffer_ptr(&sockets[i].output), |
639 | buffer_len(&sockets[i].output)); | ||
608 | if (len <= 0) { | 640 | if (len <= 0) { |
609 | shutdown(sockets[i].fd, SHUT_RDWR); | 641 | shutdown(sockets[i].fd, SHUT_RDWR); |
610 | close(sockets[i].fd); | 642 | close(sockets[i].fd); |
@@ -637,12 +669,15 @@ after_select(fd_set *readset, fd_set *writeset) | |||
637 | void | 669 | void |
638 | check_parent_exists(int sig) | 670 | check_parent_exists(int sig) |
639 | { | 671 | { |
672 | int save_errno = errno; | ||
673 | |||
640 | if (parent_pid != -1 && kill(parent_pid, 0) < 0) { | 674 | if (parent_pid != -1 && kill(parent_pid, 0) < 0) { |
641 | /* printf("Parent has died - Authentication agent exiting.\n"); */ | 675 | /* printf("Parent has died - Authentication agent exiting.\n"); */ |
642 | exit(1); | 676 | exit(1); |
643 | } | 677 | } |
644 | signal(SIGALRM, check_parent_exists); | 678 | signal(SIGALRM, check_parent_exists); |
645 | alarm(10); | 679 | alarm(10); |
680 | errno = save_errno; | ||
646 | } | 681 | } |
647 | 682 | ||
648 | void | 683 | void |
@@ -664,14 +699,13 @@ usage() | |||
664 | { | 699 | { |
665 | fprintf(stderr, "ssh-agent version %s\n", SSH_VERSION); | 700 | fprintf(stderr, "ssh-agent version %s\n", SSH_VERSION); |
666 | fprintf(stderr, "Usage: %s [-c | -s] [-k] [command {args...]]\n", | 701 | fprintf(stderr, "Usage: %s [-c | -s] [-k] [command {args...]]\n", |
667 | __progname); | 702 | __progname); |
668 | exit(1); | 703 | exit(1); |
669 | } | 704 | } |
670 | 705 | ||
671 | int | 706 | int |
672 | main(int ac, char **av) | 707 | main(int ac, char **av) |
673 | { | 708 | { |
674 | fd_set readset, writeset; | ||
675 | int sock, c_flag = 0, k_flag = 0, s_flag = 0, ch; | 709 | int sock, c_flag = 0, k_flag = 0, s_flag = 0, ch; |
676 | struct sockaddr_un sunaddr; | 710 | struct sockaddr_un sunaddr; |
677 | #ifdef HAVE_SETRLIMIT | 711 | #ifdef HAVE_SETRLIMIT |
@@ -680,6 +714,7 @@ main(int ac, char **av) | |||
680 | pid_t pid; | 714 | pid_t pid; |
681 | char *shell, *format, *pidstr, pidstrbuf[1 + 3 * sizeof pid]; | 715 | char *shell, *format, *pidstr, pidstrbuf[1 + 3 * sizeof pid]; |
682 | extern int optind; | 716 | extern int optind; |
717 | fd_set *readsetp = NULL, *writesetp = NULL; | ||
683 | 718 | ||
684 | __progname = get_progname(av[0]); | 719 | __progname = get_progname(av[0]); |
685 | init_rng(); | 720 | init_rng(); |
@@ -722,14 +757,13 @@ main(int ac, char **av) | |||
722 | pidstr = getenv(SSH_AGENTPID_ENV_NAME); | 757 | pidstr = getenv(SSH_AGENTPID_ENV_NAME); |
723 | if (pidstr == NULL) { | 758 | if (pidstr == NULL) { |
724 | fprintf(stderr, "%s not set, cannot kill agent\n", | 759 | fprintf(stderr, "%s not set, cannot kill agent\n", |
725 | SSH_AGENTPID_ENV_NAME); | 760 | SSH_AGENTPID_ENV_NAME); |
726 | exit(1); | 761 | exit(1); |
727 | } | 762 | } |
728 | pid = atoi(pidstr); | 763 | pid = atoi(pidstr); |
729 | if (pid < 1) { /* XXX PID_MAX check too */ | 764 | if (pid < 1) { |
730 | /* Yes, PID_MAX check please */ | ||
731 | fprintf(stderr, "%s=\"%s\", which is not a good PID\n", | 765 | fprintf(stderr, "%s=\"%s\", which is not a good PID\n", |
732 | SSH_AGENTPID_ENV_NAME, pidstr); | 766 | SSH_AGENTPID_ENV_NAME, pidstr); |
733 | exit(1); | 767 | exit(1); |
734 | } | 768 | } |
735 | if (kill(pid, SIGTERM) == -1) { | 769 | if (kill(pid, SIGTERM) == -1) { |
@@ -751,7 +785,7 @@ main(int ac, char **av) | |||
751 | exit(1); | 785 | exit(1); |
752 | } | 786 | } |
753 | snprintf(socket_name, sizeof socket_name, "%s/agent.%d", socket_dir, | 787 | snprintf(socket_name, sizeof socket_name, "%s/agent.%d", socket_dir, |
754 | parent_pid); | 788 | parent_pid); |
755 | 789 | ||
756 | /* | 790 | /* |
757 | * Create socket early so it will exist before command gets run from | 791 | * Create socket early so it will exist before command gets run from |
@@ -773,6 +807,7 @@ main(int ac, char **av) | |||
773 | perror("listen"); | 807 | perror("listen"); |
774 | cleanup_exit(1); | 808 | cleanup_exit(1); |
775 | } | 809 | } |
810 | |||
776 | /* | 811 | /* |
777 | * Fork, and have the parent execute the command, if any, or present | 812 | * Fork, and have the parent execute the command, if any, or present |
778 | * the socket data. The child continues as the authentication agent. | 813 | * the socket data. The child continues as the authentication agent. |
@@ -788,9 +823,9 @@ main(int ac, char **av) | |||
788 | if (ac == 0) { | 823 | if (ac == 0) { |
789 | format = c_flag ? "setenv %s %s;\n" : "%s=%s; export %s;\n"; | 824 | format = c_flag ? "setenv %s %s;\n" : "%s=%s; export %s;\n"; |
790 | printf(format, SSH_AUTHSOCKET_ENV_NAME, socket_name, | 825 | printf(format, SSH_AUTHSOCKET_ENV_NAME, socket_name, |
791 | SSH_AUTHSOCKET_ENV_NAME); | 826 | SSH_AUTHSOCKET_ENV_NAME); |
792 | printf(format, SSH_AGENTPID_ENV_NAME, pidstrbuf, | 827 | printf(format, SSH_AGENTPID_ENV_NAME, pidstrbuf, |
793 | SSH_AGENTPID_ENV_NAME); | 828 | SSH_AGENTPID_ENV_NAME); |
794 | printf("echo Agent pid %d;\n", pid); | 829 | printf("echo Agent pid %d;\n", pid); |
795 | exit(0); | 830 | exit(0); |
796 | } | 831 | } |
@@ -834,15 +869,13 @@ main(int ac, char **av) | |||
834 | signal(SIGHUP, cleanup_exit); | 869 | signal(SIGHUP, cleanup_exit); |
835 | signal(SIGTERM, cleanup_exit); | 870 | signal(SIGTERM, cleanup_exit); |
836 | while (1) { | 871 | while (1) { |
837 | FD_ZERO(&readset); | 872 | prepare_select(&readsetp, &writesetp, &max_fd); |
838 | FD_ZERO(&writeset); | 873 | if (select(max_fd + 1, readsetp, writesetp, NULL, NULL) < 0) { |
839 | prepare_select(&readset, &writeset); | ||
840 | if (select(max_fd + 1, &readset, &writeset, NULL, NULL) < 0) { | ||
841 | if (errno == EINTR) | 874 | if (errno == EINTR) |
842 | continue; | 875 | continue; |
843 | exit(1); | 876 | exit(1); |
844 | } | 877 | } |
845 | after_select(&readset, &writeset); | 878 | after_select(readsetp, writesetp); |
846 | } | 879 | } |
847 | /* NOTREACHED */ | 880 | /* NOTREACHED */ |
848 | } | 881 | } |