diff options
author | Damien Miller <djm@mindrot.org> | 2000-07-11 17:31:38 +1000 |
---|---|---|
committer | Damien Miller <djm@mindrot.org> | 2000-07-11 17:31:38 +1000 |
commit | 3702396526a2569402696ff7d7c6d0fe2e5a447b (patch) | |
tree | 3ab056c59cd0c732ec179bd91be88d4e05b087fa /sshd.c | |
parent | bc33bd44a2ef165dea1d974fc2d80b822ae08c2a (diff) |
- (djm) OpenBSD CVS updates:
- markus@cvs.openbsd.org 2000/06/26 03:22:29
[authfd.c]
cleanup, less cut&paste
- markus@cvs.openbsd.org 2000/06/26 15:59:19
[servconf.c servconf.h session.c sshd.8 sshd.c]
MaxStartups: limit number of unauthenticated connections, work by
theo and me
- deraadt@cvs.openbsd.org 2000/07/05 14:18:07
[session.c]
use no_x11_forwarding_flag correctly; provos ok
- provos@cvs.openbsd.org 2000/07/05 15:35:57
[sshd.c]
typo
- aaron@cvs.openbsd.org 2000/07/05 22:06:58
[scp.1 ssh-agent.1 ssh-keygen.1 sshd.8]
Insert more missing .El directives. Our troff really should identify
these and spit out a warning.
- todd@cvs.openbsd.org 2000/07/06 21:55:04
[auth-rsa.c auth2.c ssh-keygen.c]
clean code is good code
- deraadt@cvs.openbsd.org 2000/07/07 02:14:29
[serverloop.c]
sense of port forwarding flag test was backwards
- provos@cvs.openbsd.org 2000/07/08 17:17:31
[compat.c readconf.c]
replace strtok with strsep; from David Young <dyoung@onthejob.net>
- deraadt@cvs.openbsd.org 2000/07/08 19:21:15
[auth.h]
KNF
- ho@cvs.openbsd.org 2000/07/08 19:27:33
[compat.c readconf.c]
Better conditions for strsep() ending.
- ho@cvs.openbsd.org 2000/07/10 10:27:05
[readconf.c]
Get the correct message on errors. (niels@ ok)
- ho@cvs.openbsd.org 2000/07/10 10:30:25
[cipher.c kex.c servconf.c]
strtok() --> strsep(). (niels@ ok)
Diffstat (limited to 'sshd.c')
-rw-r--r-- | sshd.c | 167 |
1 files changed, 112 insertions, 55 deletions
@@ -14,7 +14,7 @@ | |||
14 | */ | 14 | */ |
15 | 15 | ||
16 | #include "includes.h" | 16 | #include "includes.h" |
17 | RCSID("$OpenBSD: sshd.c,v 1.119 2000/06/22 16:32:27 markus Exp $"); | 17 | RCSID("$OpenBSD: sshd.c,v 1.121 2000/07/05 21:35:56 provos Exp $"); |
18 | 18 | ||
19 | #include "xmalloc.h" | 19 | #include "xmalloc.h" |
20 | #include "rsa.h" | 20 | #include "rsa.h" |
@@ -350,7 +350,7 @@ sshd_exchange_identification(int sock_in, int sock_out) | |||
350 | break; | 350 | break; |
351 | } | 351 | } |
352 | if (remote_minor < 3) { | 352 | if (remote_minor < 3) { |
353 | packet_disconnect("Your ssh version is too old and" | 353 | packet_disconnect("Your ssh version is too old and " |
354 | "is no longer supported. Please install a newer version."); | 354 | "is no longer supported. Please install a newer version."); |
355 | } else if (remote_minor == 3) { | 355 | } else if (remote_minor == 3) { |
356 | /* note that this disables agent-forwarding */ | 356 | /* note that this disables agent-forwarding */ |
@@ -400,6 +400,9 @@ destroy_sensitive_data(void) | |||
400 | key_free(sensitive_data.dsa_host_key); | 400 | key_free(sensitive_data.dsa_host_key); |
401 | } | 401 | } |
402 | 402 | ||
403 | int *startup_pipes = NULL; /* options.max_startup sized array of fd ints */ | ||
404 | int startup_pipe; /* in child */ | ||
405 | |||
403 | /* | 406 | /* |
404 | * Main program for the daemon. | 407 | * Main program for the daemon. |
405 | */ | 408 | */ |
@@ -408,7 +411,7 @@ main(int ac, char **av) | |||
408 | { | 411 | { |
409 | extern char *optarg; | 412 | extern char *optarg; |
410 | extern int optind; | 413 | extern int optind; |
411 | int opt, sock_in = 0, sock_out = 0, newsock, i, fdsetsz, on = 1; | 414 | int opt, sock_in = 0, sock_out = 0, newsock, j, i, fdsetsz, on = 1; |
412 | pid_t pid; | 415 | pid_t pid; |
413 | socklen_t fromlen; | 416 | socklen_t fromlen; |
414 | int silent = 0; | 417 | int silent = 0; |
@@ -421,6 +424,8 @@ main(int ac, char **av) | |||
421 | struct addrinfo *ai; | 424 | struct addrinfo *ai; |
422 | char ntop[NI_MAXHOST], strport[NI_MAXSERV]; | 425 | char ntop[NI_MAXHOST], strport[NI_MAXSERV]; |
423 | int listen_sock, maxfd; | 426 | int listen_sock, maxfd; |
427 | int startup_p[2]; | ||
428 | int startups = 0; | ||
424 | 429 | ||
425 | init_rng(); | 430 | init_rng(); |
426 | 431 | ||
@@ -746,6 +751,7 @@ main(int ac, char **av) | |||
746 | 751 | ||
747 | /* Arrange to restart on SIGHUP. The handler needs listen_sock. */ | 752 | /* Arrange to restart on SIGHUP. The handler needs listen_sock. */ |
748 | signal(SIGHUP, sighup_handler); | 753 | signal(SIGHUP, sighup_handler); |
754 | |||
749 | signal(SIGTERM, sigterm_handler); | 755 | signal(SIGTERM, sigterm_handler); |
750 | signal(SIGQUIT, sigterm_handler); | 756 | signal(SIGQUIT, sigterm_handler); |
751 | 757 | ||
@@ -753,12 +759,15 @@ main(int ac, char **av) | |||
753 | signal(SIGCHLD, main_sigchld_handler); | 759 | signal(SIGCHLD, main_sigchld_handler); |
754 | 760 | ||
755 | /* setup fd set for listen */ | 761 | /* setup fd set for listen */ |
762 | fdset = NULL; | ||
756 | maxfd = 0; | 763 | maxfd = 0; |
757 | for (i = 0; i < num_listen_socks; i++) | 764 | for (i = 0; i < num_listen_socks; i++) |
758 | if (listen_socks[i] > maxfd) | 765 | if (listen_socks[i] > maxfd) |
759 | maxfd = listen_socks[i]; | 766 | maxfd = listen_socks[i]; |
760 | fdsetsz = howmany(maxfd, NFDBITS) * sizeof(fd_mask); | 767 | /* pipes connected to unauthenticated childs */ |
761 | fdset = (fd_set *)xmalloc(fdsetsz); | 768 | startup_pipes = xmalloc(options.max_startups * sizeof(int)); |
769 | for (i = 0; i < options.max_startups; i++) | ||
770 | startup_pipes[i] = -1; | ||
762 | 771 | ||
763 | /* | 772 | /* |
764 | * Stay listening for connections until the system crashes or | 773 | * Stay listening for connections until the system crashes or |
@@ -767,80 +776,128 @@ main(int ac, char **av) | |||
767 | for (;;) { | 776 | for (;;) { |
768 | if (received_sighup) | 777 | if (received_sighup) |
769 | sighup_restart(); | 778 | sighup_restart(); |
770 | /* Wait in select until there is a connection. */ | 779 | if (fdset != NULL) |
780 | xfree(fdset); | ||
781 | fdsetsz = howmany(maxfd, NFDBITS) * sizeof(fd_mask); | ||
782 | fdset = (fd_set *)xmalloc(fdsetsz); | ||
771 | memset(fdset, 0, fdsetsz); | 783 | memset(fdset, 0, fdsetsz); |
784 | |||
772 | for (i = 0; i < num_listen_socks; i++) | 785 | for (i = 0; i < num_listen_socks; i++) |
773 | FD_SET(listen_socks[i], fdset); | 786 | FD_SET(listen_socks[i], fdset); |
787 | for (i = 0; i < options.max_startups; i++) | ||
788 | if (startup_pipes[i] != -1) | ||
789 | FD_SET(startup_pipes[i], fdset); | ||
790 | |||
791 | /* Wait in select until there is a connection. */ | ||
774 | if (select(maxfd + 1, fdset, NULL, NULL, NULL) < 0) { | 792 | if (select(maxfd + 1, fdset, NULL, NULL, NULL) < 0) { |
775 | if (errno != EINTR) | 793 | if (errno != EINTR) |
776 | error("select: %.100s", strerror(errno)); | 794 | error("select: %.100s", strerror(errno)); |
777 | continue; | 795 | continue; |
778 | } | 796 | } |
797 | for (i = 0; i < options.max_startups; i++) | ||
798 | if (startup_pipes[i] != -1 && | ||
799 | FD_ISSET(startup_pipes[i], fdset)) { | ||
800 | /* | ||
801 | * the read end of the pipe is ready | ||
802 | * if the child has closed the pipe | ||
803 | * after successfull authentication | ||
804 | * or if the child has died | ||
805 | */ | ||
806 | close(startup_pipes[i]); | ||
807 | startup_pipes[i] = -1; | ||
808 | startups--; | ||
809 | } | ||
779 | for (i = 0; i < num_listen_socks; i++) { | 810 | for (i = 0; i < num_listen_socks; i++) { |
780 | if (!FD_ISSET(listen_socks[i], fdset)) | 811 | if (!FD_ISSET(listen_socks[i], fdset)) |
781 | continue; | 812 | continue; |
782 | fromlen = sizeof(from); | 813 | fromlen = sizeof(from); |
783 | newsock = accept(listen_socks[i], (struct sockaddr *)&from, | 814 | newsock = accept(listen_socks[i], (struct sockaddr *)&from, |
784 | &fromlen); | 815 | &fromlen); |
785 | if (newsock < 0) { | 816 | if (newsock < 0) { |
786 | if (errno != EINTR && errno != EWOULDBLOCK) | 817 | if (errno != EINTR && errno != EWOULDBLOCK) |
787 | error("accept: %.100s", strerror(errno)); | 818 | error("accept: %.100s", strerror(errno)); |
788 | continue; | 819 | continue; |
789 | } | 820 | } |
790 | if (fcntl(newsock, F_SETFL, 0) < 0) { | 821 | if (fcntl(newsock, F_SETFL, 0) < 0) { |
791 | error("newsock del O_NONBLOCK: %s", strerror(errno)); | 822 | error("newsock del O_NONBLOCK: %s", strerror(errno)); |
792 | continue; | 823 | continue; |
793 | } | 824 | } |
794 | /* | 825 | if (startups >= options.max_startups) { |
795 | * Got connection. Fork a child to handle it, unless | 826 | close(newsock); |
796 | * we are in debugging mode. | 827 | continue; |
797 | */ | 828 | } |
798 | if (debug_flag) { | 829 | if (pipe(startup_p) == -1) { |
799 | /* | 830 | close(newsock); |
800 | * In debugging mode. Close the listening | 831 | continue; |
801 | * socket, and start processing the | 832 | } |
802 | * connection without forking. | 833 | |
803 | */ | 834 | for (j = 0; j < options.max_startups; j++) |
804 | debug("Server will not fork when running in debugging mode."); | 835 | if (startup_pipes[j] == -1) { |
805 | close_listen_socks(); | 836 | startup_pipes[j] = startup_p[0]; |
806 | sock_in = newsock; | 837 | if (maxfd < startup_p[0]) |
807 | sock_out = newsock; | 838 | maxfd = startup_p[0]; |
808 | pid = getpid(); | 839 | startups++; |
809 | break; | 840 | break; |
810 | } else { | 841 | } |
842 | |||
811 | /* | 843 | /* |
812 | * Normal production daemon. Fork, and have | 844 | * Got connection. Fork a child to handle it, unless |
813 | * the child process the connection. The | 845 | * we are in debugging mode. |
814 | * parent continues listening. | ||
815 | */ | 846 | */ |
816 | if ((pid = fork()) == 0) { | 847 | if (debug_flag) { |
817 | /* | 848 | /* |
818 | * Child. Close the listening socket, and start using the | 849 | * In debugging mode. Close the listening |
819 | * accepted socket. Reinitialize logging (since our pid has | 850 | * socket, and start processing the |
820 | * changed). We break out of the loop to handle the connection. | 851 | * connection without forking. |
821 | */ | 852 | */ |
853 | debug("Server will not fork when running in debugging mode."); | ||
822 | close_listen_socks(); | 854 | close_listen_socks(); |
823 | sock_in = newsock; | 855 | sock_in = newsock; |
824 | sock_out = newsock; | 856 | sock_out = newsock; |
825 | log_init(av0, options.log_level, options.log_facility, log_stderr); | 857 | pid = getpid(); |
826 | break; | 858 | break; |
859 | } else { | ||
860 | /* | ||
861 | * Normal production daemon. Fork, and have | ||
862 | * the child process the connection. The | ||
863 | * parent continues listening. | ||
864 | */ | ||
865 | if ((pid = fork()) == 0) { | ||
866 | /* | ||
867 | * Child. Close the listening and max_startup | ||
868 | * sockets. Start using the accepted socket. | ||
869 | * Reinitialize logging (since our pid has | ||
870 | * changed). We break out of the loop to handle | ||
871 | * the connection. | ||
872 | */ | ||
873 | startup_pipe = startup_p[1]; | ||
874 | for (j = 0; j < options.max_startups; j++) | ||
875 | if (startup_pipes[j] != -1) | ||
876 | close(startup_pipes[j]); | ||
877 | close_listen_socks(); | ||
878 | sock_in = newsock; | ||
879 | sock_out = newsock; | ||
880 | log_init(av0, options.log_level, options.log_facility, log_stderr); | ||
881 | break; | ||
882 | } | ||
827 | } | 883 | } |
828 | } | ||
829 | 884 | ||
830 | /* Parent. Stay in the loop. */ | 885 | /* Parent. Stay in the loop. */ |
831 | if (pid < 0) | 886 | if (pid < 0) |
832 | error("fork: %.100s", strerror(errno)); | 887 | error("fork: %.100s", strerror(errno)); |
833 | else | 888 | else |
834 | debug("Forked child %d.", pid); | 889 | debug("Forked child %d.", pid); |
835 | 890 | ||
836 | /* Mark that the key has been used (it was "given" to the child). */ | 891 | close(startup_p[1]); |
837 | key_used = 1; | ||
838 | 892 | ||
839 | arc4random_stir(); | 893 | /* Mark that the key has been used (it was "given" to the child). */ |
894 | key_used = 1; | ||
840 | 895 | ||
841 | /* Close the new socket (the child is now taking care of it). */ | 896 | arc4random_stir(); |
842 | close(newsock); | 897 | |
843 | } /* for (i = 0; i < num_listen_socks; i++) */ | 898 | /* Close the new socket (the child is now taking care of it). */ |
899 | close(newsock); | ||
900 | } | ||
844 | /* child process check (or debug mode) */ | 901 | /* child process check (or debug mode) */ |
845 | if (num_listen_socks < 0) | 902 | if (num_listen_socks < 0) |
846 | break; | 903 | break; |