summaryrefslogtreecommitdiff
path: root/serverloop.c
diff options
context:
space:
mode:
Diffstat (limited to 'serverloop.c')
-rw-r--r--serverloop.c88
1 files changed, 85 insertions, 3 deletions
diff --git a/serverloop.c b/serverloop.c
index d2eff170a..3d8e7cfb5 100644
--- a/serverloop.c
+++ b/serverloop.c
@@ -35,7 +35,7 @@
35 */ 35 */
36 36
37#include "includes.h" 37#include "includes.h"
38RCSID("$OpenBSD: serverloop.c,v 1.118 2005/07/17 07:17:55 djm Exp $"); 38RCSID("$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 */
62extern Kex *xxx_kex; 62extern Kex *xxx_kex;
63extern Authctxt *the_authctxt; 63extern Authctxt *the_authctxt;
64extern int use_privsep;
64 65
65static Buffer stdin_buffer; /* Buffer for stdin data. */ 66static Buffer stdin_buffer; /* Buffer for stdin data. */
66static Buffer stdout_buffer; /* Buffer for stdout data. */ 67static Buffer stdout_buffer; /* Buffer for stdout data. */
@@ -90,6 +91,9 @@ static int client_alive_timeouts = 0;
90 91
91static volatile sig_atomic_t child_terminated = 0; /* The child has terminated. */ 92static volatile sig_atomic_t child_terminated = 0; /* The child has terminated. */
92 93
94/* Cleanup on signals (!use_privsep case only) */
95static volatile sig_atomic_t received_sigterm = 0;
96
93/* prototypes */ 97/* prototypes */
94static void server_init_dispatch(void); 98static 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
158static void
159sigterm_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
882static Channel * 916static Channel *
917server_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
962static Channel *
883server_request_session(void) 963server_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);