diff options
Diffstat (limited to 'serverloop.c')
-rw-r--r-- | serverloop.c | 88 |
1 files changed, 85 insertions, 3 deletions
diff --git a/serverloop.c b/serverloop.c index 031847873..f72b73bf8 100644 --- a/serverloop.c +++ b/serverloop.c | |||
@@ -35,7 +35,7 @@ | |||
35 | */ | 35 | */ |
36 | 36 | ||
37 | #include "includes.h" | 37 | #include "includes.h" |
38 | RCSID("$OpenBSD: serverloop.c,v 1.118 2005/07/17 07:17:55 djm Exp $"); | 38 | RCSID("$OpenBSD: serverloop.c,v 1.124 2005/12/13 15:03:02 reyk Exp $"); |
39 | 39 | ||
40 | #include "xmalloc.h" | 40 | #include "xmalloc.h" |
41 | #include "packet.h" | 41 | #include "packet.h" |
@@ -61,6 +61,7 @@ extern ServerOptions options; | |||
61 | /* XXX */ | 61 | /* XXX */ |
62 | extern Kex *xxx_kex; | 62 | extern Kex *xxx_kex; |
63 | extern Authctxt *the_authctxt; | 63 | extern Authctxt *the_authctxt; |
64 | extern int use_privsep; | ||
64 | 65 | ||
65 | static Buffer stdin_buffer; /* Buffer for stdin data. */ | 66 | static Buffer stdin_buffer; /* Buffer for stdin data. */ |
66 | static Buffer stdout_buffer; /* Buffer for stdout data. */ | 67 | static Buffer stdout_buffer; /* Buffer for stdout data. */ |
@@ -90,6 +91,9 @@ static int client_alive_timeouts = 0; | |||
90 | 91 | ||
91 | static volatile sig_atomic_t child_terminated = 0; /* The child has terminated. */ | 92 | static volatile sig_atomic_t child_terminated = 0; /* The child has terminated. */ |
92 | 93 | ||
94 | /* Cleanup on signals (!use_privsep case only) */ | ||
95 | static volatile sig_atomic_t received_sigterm = 0; | ||
96 | |||
93 | /* prototypes */ | 97 | /* prototypes */ |
94 | static void server_init_dispatch(void); | 98 | static void server_init_dispatch(void); |
95 | 99 | ||
@@ -151,6 +155,12 @@ sigchld_handler(int sig) | |||
151 | errno = save_errno; | 155 | errno = save_errno; |
152 | } | 156 | } |
153 | 157 | ||
158 | static void | ||
159 | sigterm_handler(int sig) | ||
160 | { | ||
161 | received_sigterm = sig; | ||
162 | } | ||
163 | |||
154 | /* | 164 | /* |
155 | * Make packets from buffered stderr data, and buffer it for sending | 165 | * Make packets from buffered stderr data, and buffer it for sending |
156 | * to the client. | 166 | * to the client. |
@@ -502,6 +512,12 @@ server_loop(pid_t pid, int fdin_arg, int fdout_arg, int fderr_arg) | |||
502 | child_terminated = 0; | 512 | child_terminated = 0; |
503 | mysignal(SIGCHLD, sigchld_handler); | 513 | mysignal(SIGCHLD, sigchld_handler); |
504 | 514 | ||
515 | if (!use_privsep) { | ||
516 | signal(SIGTERM, sigterm_handler); | ||
517 | signal(SIGINT, sigterm_handler); | ||
518 | signal(SIGQUIT, sigterm_handler); | ||
519 | } | ||
520 | |||
505 | /* Initialize our global variables. */ | 521 | /* Initialize our global variables. */ |
506 | fdin = fdin_arg; | 522 | fdin = fdin_arg; |
507 | fdout = fdout_arg; | 523 | fdout = fdout_arg; |
@@ -548,7 +564,7 @@ server_loop(pid_t pid, int fdin_arg, int fdout_arg, int fderr_arg) | |||
548 | * If we have no separate fderr (which is the case when we have a pty | 564 | * If we have no separate fderr (which is the case when we have a pty |
549 | * - there we cannot make difference between data sent to stdout and | 565 | * - there we cannot make difference between data sent to stdout and |
550 | * stderr), indicate that we have seen an EOF from stderr. This way | 566 | * stderr), indicate that we have seen an EOF from stderr. This way |
551 | * we don\'t need to check the descriptor everywhere. | 567 | * we don't need to check the descriptor everywhere. |
552 | */ | 568 | */ |
553 | if (fderr == -1) | 569 | if (fderr == -1) |
554 | fderr_eof = 1; | 570 | fderr_eof = 1; |
@@ -629,6 +645,12 @@ server_loop(pid_t pid, int fdin_arg, int fdout_arg, int fderr_arg) | |||
629 | wait_until_can_do_something(&readset, &writeset, &max_fd, | 645 | wait_until_can_do_something(&readset, &writeset, &max_fd, |
630 | &nalloc, max_time_milliseconds); | 646 | &nalloc, max_time_milliseconds); |
631 | 647 | ||
648 | if (received_sigterm) { | ||
649 | logit("Exiting on signal %d", received_sigterm); | ||
650 | /* Clean up sessions, utmp, etc. */ | ||
651 | cleanup_exit(255); | ||
652 | } | ||
653 | |||
632 | /* Process any channel events. */ | 654 | /* Process any channel events. */ |
633 | channel_after_select(readset, writeset); | 655 | channel_after_select(readset, writeset); |
634 | 656 | ||
@@ -749,6 +771,12 @@ server_loop2(Authctxt *authctxt) | |||
749 | connection_in = packet_get_connection_in(); | 771 | connection_in = packet_get_connection_in(); |
750 | connection_out = packet_get_connection_out(); | 772 | connection_out = packet_get_connection_out(); |
751 | 773 | ||
774 | if (!use_privsep) { | ||
775 | signal(SIGTERM, sigterm_handler); | ||
776 | signal(SIGINT, sigterm_handler); | ||
777 | signal(SIGQUIT, sigterm_handler); | ||
778 | } | ||
779 | |||
752 | notify_setup(); | 780 | notify_setup(); |
753 | 781 | ||
754 | max_fd = MAX(connection_in, connection_out); | 782 | max_fd = MAX(connection_in, connection_out); |
@@ -766,6 +794,12 @@ server_loop2(Authctxt *authctxt) | |||
766 | wait_until_can_do_something(&readset, &writeset, &max_fd, | 794 | wait_until_can_do_something(&readset, &writeset, &max_fd, |
767 | &nalloc, 0); | 795 | &nalloc, 0); |
768 | 796 | ||
797 | if (received_sigterm) { | ||
798 | logit("Exiting on signal %d", received_sigterm); | ||
799 | /* Clean up sessions, utmp, etc. */ | ||
800 | cleanup_exit(255); | ||
801 | } | ||
802 | |||
769 | collect_children(); | 803 | collect_children(); |
770 | if (!rekeying) { | 804 | if (!rekeying) { |
771 | channel_after_select(readset, writeset); | 805 | channel_after_select(readset, writeset); |
@@ -880,6 +914,52 @@ server_request_direct_tcpip(void) | |||
880 | } | 914 | } |
881 | 915 | ||
882 | static Channel * | 916 | static Channel * |
917 | server_request_tun(void) | ||
918 | { | ||
919 | Channel *c = NULL; | ||
920 | int mode, tun; | ||
921 | int sock; | ||
922 | |||
923 | mode = packet_get_int(); | ||
924 | switch (mode) { | ||
925 | case SSH_TUNMODE_POINTOPOINT: | ||
926 | case SSH_TUNMODE_ETHERNET: | ||
927 | break; | ||
928 | default: | ||
929 | packet_send_debug("Unsupported tunnel device mode."); | ||
930 | return NULL; | ||
931 | } | ||
932 | if ((options.permit_tun & mode) == 0) { | ||
933 | packet_send_debug("Server has rejected tunnel device " | ||
934 | "forwarding"); | ||
935 | return NULL; | ||
936 | } | ||
937 | |||
938 | tun = packet_get_int(); | ||
939 | if (forced_tun_device != -1) { | ||
940 | if (tun != SSH_TUNID_ANY && forced_tun_device != tun) | ||
941 | goto done; | ||
942 | tun = forced_tun_device; | ||
943 | } | ||
944 | sock = tun_open(tun, mode); | ||
945 | if (sock < 0) | ||
946 | goto done; | ||
947 | c = channel_new("tun", SSH_CHANNEL_OPEN, sock, sock, -1, | ||
948 | CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, 0, "tun", 1); | ||
949 | c->datagram = 1; | ||
950 | #if defined(SSH_TUN_FILTER) | ||
951 | if (mode == SSH_TUNMODE_POINTOPOINT) | ||
952 | channel_register_filter(c->self, sys_tun_infilter, | ||
953 | sys_tun_outfilter); | ||
954 | #endif | ||
955 | |||
956 | done: | ||
957 | if (c == NULL) | ||
958 | packet_send_debug("Failed to open the tunnel device."); | ||
959 | return c; | ||
960 | } | ||
961 | |||
962 | static Channel * | ||
883 | server_request_session(void) | 963 | server_request_session(void) |
884 | { | 964 | { |
885 | Channel *c; | 965 | Channel *c; |
@@ -900,7 +980,7 @@ server_request_session(void) | |||
900 | channel_free(c); | 980 | channel_free(c); |
901 | return NULL; | 981 | return NULL; |
902 | } | 982 | } |
903 | channel_register_cleanup(c->self, session_close_by_channel); | 983 | channel_register_cleanup(c->self, session_close_by_channel, 0); |
904 | return c; | 984 | return c; |
905 | } | 985 | } |
906 | 986 | ||
@@ -924,6 +1004,8 @@ server_input_channel_open(int type, u_int32_t seq, void *ctxt) | |||
924 | c = server_request_session(); | 1004 | c = server_request_session(); |
925 | } else if (strcmp(ctype, "direct-tcpip") == 0) { | 1005 | } else if (strcmp(ctype, "direct-tcpip") == 0) { |
926 | c = server_request_direct_tcpip(); | 1006 | c = server_request_direct_tcpip(); |
1007 | } else if (strcmp(ctype, "tun@openssh.com") == 0) { | ||
1008 | c = server_request_tun(); | ||
927 | } | 1009 | } |
928 | if (c != NULL) { | 1010 | if (c != NULL) { |
929 | debug("server_input_channel_open: confirm %s", ctype); | 1011 | debug("server_input_channel_open: confirm %s", ctype); |