summaryrefslogtreecommitdiff
path: root/sshd.c
diff options
context:
space:
mode:
authorDamien Miller <djm@mindrot.org>2000-07-11 17:31:38 +1000
committerDamien Miller <djm@mindrot.org>2000-07-11 17:31:38 +1000
commit3702396526a2569402696ff7d7c6d0fe2e5a447b (patch)
tree3ab056c59cd0c732ec179bd91be88d4e05b087fa /sshd.c
parentbc33bd44a2ef165dea1d974fc2d80b822ae08c2a (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.c167
1 files changed, 112 insertions, 55 deletions
diff --git a/sshd.c b/sshd.c
index 93d68404f..fc8b17b9e 100644
--- a/sshd.c
+++ b/sshd.c
@@ -14,7 +14,7 @@
14 */ 14 */
15 15
16#include "includes.h" 16#include "includes.h"
17RCSID("$OpenBSD: sshd.c,v 1.119 2000/06/22 16:32:27 markus Exp $"); 17RCSID("$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
403int *startup_pipes = NULL; /* options.max_startup sized array of fd ints */
404int 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;