summaryrefslogtreecommitdiff
path: root/serverloop.c
diff options
context:
space:
mode:
Diffstat (limited to 'serverloop.c')
-rw-r--r--serverloop.c195
1 files changed, 93 insertions, 102 deletions
diff --git a/serverloop.c b/serverloop.c
index 2afca7637..8bf448ceb 100644
--- a/serverloop.c
+++ b/serverloop.c
@@ -13,6 +13,10 @@
13#include "buffer.h" 13#include "buffer.h"
14#include "servconf.h" 14#include "servconf.h"
15#include "pty.h" 15#include "pty.h"
16#include "channels.h"
17
18#include "compat.h"
19#include "dispatch.h"
16 20
17static Buffer stdin_buffer; /* Buffer for stdin data. */ 21static Buffer stdin_buffer; /* Buffer for stdin data. */
18static Buffer stdout_buffer; /* Buffer for stdout data. */ 22static Buffer stdout_buffer; /* Buffer for stdout data. */
@@ -47,6 +51,8 @@ static volatile int child_terminated; /* The child has terminated. */
47static volatile int child_has_selected; /* Child has had chance to drain. */ 51static volatile int child_has_selected; /* Child has had chance to drain. */
48static volatile int child_wait_status; /* Status from wait(). */ 52static volatile int child_wait_status; /* Status from wait(). */
49 53
54void server_init_dispatch(void);
55
50void 56void
51sigchld_handler(int sig) 57sigchld_handler(int sig)
52{ 58{
@@ -68,104 +74,6 @@ sigchld_handler(int sig)
68} 74}
69 75
70/* 76/*
71 * Process any buffered packets that have been received from the client.
72 */
73void
74process_buffered_input_packets()
75{
76 int type;
77 char *data;
78 unsigned int data_len;
79 int row, col, xpixel, ypixel;
80 int payload_len;
81
82 /* Process buffered packets from the client. */
83 while ((type = packet_read_poll(&payload_len)) != SSH_MSG_NONE) {
84 switch (type) {
85 case SSH_CMSG_STDIN_DATA:
86 /* Stdin data from the client. Append it to the buffer. */
87 /* Ignore any data if the client has closed stdin. */
88 if (fdin == -1)
89 break;
90 data = packet_get_string(&data_len);
91 packet_integrity_check(payload_len, (4 + data_len), type);
92 buffer_append(&stdin_buffer, data, data_len);
93 memset(data, 0, data_len);
94 xfree(data);
95 break;
96
97 case SSH_CMSG_EOF:
98 /*
99 * Eof from the client. The stdin descriptor to the
100 * program will be closed when all buffered data has
101 * drained.
102 */
103 debug("EOF received for stdin.");
104 packet_integrity_check(payload_len, 0, type);
105 stdin_eof = 1;
106 break;
107
108 case SSH_CMSG_WINDOW_SIZE:
109 debug("Window change received.");
110 packet_integrity_check(payload_len, 4 * 4, type);
111 row = packet_get_int();
112 col = packet_get_int();
113 xpixel = packet_get_int();
114 ypixel = packet_get_int();
115 if (fdin != -1)
116 pty_change_window_size(fdin, row, col, xpixel, ypixel);
117 break;
118
119 case SSH_MSG_PORT_OPEN:
120 debug("Received port open request.");
121 channel_input_port_open(payload_len);
122 break;
123
124 case SSH_MSG_CHANNEL_OPEN_CONFIRMATION:
125 debug("Received channel open confirmation.");
126 packet_integrity_check(payload_len, 4 + 4, type);
127 channel_input_open_confirmation();
128 break;
129
130 case SSH_MSG_CHANNEL_OPEN_FAILURE:
131 debug("Received channel open failure.");
132 packet_integrity_check(payload_len, 4, type);
133 channel_input_open_failure();
134 break;
135
136 case SSH_MSG_CHANNEL_DATA:
137 channel_input_data(payload_len);
138 break;
139
140 case SSH_MSG_CHANNEL_CLOSE:
141 debug("Received channel close.");
142 packet_integrity_check(payload_len, 4, type);
143 channel_input_close();
144 break;
145
146 case SSH_MSG_CHANNEL_CLOSE_CONFIRMATION:
147 debug("Received channel close confirmation.");
148 packet_integrity_check(payload_len, 4, type);
149 channel_input_close_confirmation();
150 break;
151
152 default:
153 /*
154 * In this phase, any unexpected messages cause a
155 * protocol error. This is to ease debugging; also,
156 * since no confirmations are sent messages,
157 * unprocessed unknown messages could cause strange
158 * problems. Any compatible protocol extensions must
159 * be negotiated before entering the interactive
160 * session.
161 */
162 packet_disconnect("Protocol error during session: type %d",
163 type);
164 }
165 }
166}
167
168/*
169 * Make packets from buffered stderr data, and buffer it for sending 77 * Make packets from buffered stderr data, and buffer it for sending
170 * to the client. 78 * to the client.
171 */ 79 */
@@ -378,7 +286,7 @@ process_output(fd_set * writeset)
378#ifdef USE_PIPES 286#ifdef USE_PIPES
379 close(fdin); 287 close(fdin);
380#else 288#else
381 if (fdout == -1) 289 if (fdin != fdout)
382 close(fdin); 290 close(fdin);
383 else 291 else
384 shutdown(fdin, SHUT_WR); /* We will no longer send. */ 292 shutdown(fdin, SHUT_WR); /* We will no longer send. */
@@ -425,6 +333,12 @@ drain_output()
425 packet_write_wait(); 333 packet_write_wait();
426} 334}
427 335
336void
337process_buffered_input_packets()
338{
339 dispatch_run(DISPATCH_NONBLOCK, NULL);
340}
341
428/* 342/*
429 * Performs the interactive session. This handles data transmission between 343 * Performs the interactive session. This handles data transmission between
430 * the client and the program. Note that the notion of stdin, stdout, and 344 * the client and the program. Note that the notion of stdin, stdout, and
@@ -490,6 +404,8 @@ server_loop(int pid, int fdin_arg, int fdout_arg, int fderr_arg)
490 if (fderr == -1) 404 if (fderr == -1)
491 fderr_eof = 1; 405 fderr_eof = 1;
492 406
407 server_init_dispatch();
408
493 /* Main loop of the server for the interactive session mode. */ 409 /* Main loop of the server for the interactive session mode. */
494 for (;;) { 410 for (;;) {
495 fd_set readset, writeset; 411 fd_set readset, writeset;
@@ -505,7 +421,7 @@ server_loop(int pid, int fdin_arg, int fdout_arg, int fderr_arg)
505#ifdef USE_PIPES 421#ifdef USE_PIPES
506 close(fdin); 422 close(fdin);
507#else 423#else
508 if (fdout == -1) 424 if (fdin != fdout)
509 close(fdin); 425 close(fdin);
510 else 426 else
511 shutdown(fdin, SHUT_WR); /* We will no longer send. */ 427 shutdown(fdin, SHUT_WR); /* We will no longer send. */
@@ -549,7 +465,7 @@ server_loop(int pid, int fdin_arg, int fdout_arg, int fderr_arg)
549 (buffer_len(&stdout_buffer) == 0) && 465 (buffer_len(&stdout_buffer) == 0) &&
550 (buffer_len(&stderr_buffer) == 0)) { 466 (buffer_len(&stderr_buffer) == 0)) {
551 if (!channel_still_open()) 467 if (!channel_still_open())
552 goto quit; 468 break;
553 if (!waiting_termination) { 469 if (!waiting_termination) {
554 const char *s = "Waiting for forwarded connections to terminate...\r\n"; 470 const char *s = "Waiting for forwarded connections to terminate...\r\n";
555 char *cp; 471 char *cp;
@@ -576,7 +492,6 @@ server_loop(int pid, int fdin_arg, int fdout_arg, int fderr_arg)
576 process_output(&writeset); 492 process_output(&writeset);
577 } 493 }
578 494
579quit:
580 /* Cleanup and termination code. */ 495 /* Cleanup and termination code. */
581 496
582 /* Wait until all output has been sent to the client. */ 497 /* Wait until all output has been sent to the client. */
@@ -662,3 +577,79 @@ quit:
662 packet_disconnect("wait returned status %04x.", wait_status); 577 packet_disconnect("wait returned status %04x.", wait_status);
663 /* NOTREACHED */ 578 /* NOTREACHED */
664} 579}
580
581void
582server_input_stdin_data(int type, int plen)
583{
584 char *data;
585 unsigned int data_len;
586
587 /* Stdin data from the client. Append it to the buffer. */
588 /* Ignore any data if the client has closed stdin. */
589 if (fdin == -1)
590 return;
591 data = packet_get_string(&data_len);
592 packet_integrity_check(plen, (4 + data_len), type);
593 buffer_append(&stdin_buffer, data, data_len);
594 memset(data, 0, data_len);
595 xfree(data);
596}
597
598void
599server_input_eof(int type, int plen)
600{
601 /*
602 * Eof from the client. The stdin descriptor to the
603 * program will be closed when all buffered data has
604 * drained.
605 */
606 debug("EOF received for stdin.");
607 packet_integrity_check(plen, 0, type);
608 stdin_eof = 1;
609}
610
611void
612server_input_window_size(int type, int plen)
613{
614 int row = packet_get_int();
615 int col = packet_get_int();
616 int xpixel = packet_get_int();
617 int ypixel = packet_get_int();
618
619 debug("Window change received.");
620 packet_integrity_check(plen, 4 * 4, type);
621 if (fdin != -1)
622 pty_change_window_size(fdin, row, col, xpixel, ypixel);
623}
624
625void
626server_init_dispatch_13()
627{
628 debug("server_init_dispatch_13");
629 dispatch_init(NULL);
630 dispatch_set(SSH_CMSG_EOF, &server_input_eof);
631 dispatch_set(SSH_CMSG_STDIN_DATA, &server_input_stdin_data);
632 dispatch_set(SSH_CMSG_WINDOW_SIZE, &server_input_window_size);
633 dispatch_set(SSH_MSG_CHANNEL_CLOSE, &channel_input_close);
634 dispatch_set(SSH_MSG_CHANNEL_CLOSE_CONFIRMATION, &channel_input_close_confirmation);
635 dispatch_set(SSH_MSG_CHANNEL_DATA, &channel_input_data);
636 dispatch_set(SSH_MSG_CHANNEL_OPEN_CONFIRMATION, &channel_input_open_confirmation);
637 dispatch_set(SSH_MSG_CHANNEL_OPEN_FAILURE, &channel_input_open_failure);
638 dispatch_set(SSH_MSG_PORT_OPEN, &channel_input_port_open);
639}
640void
641server_init_dispatch_15()
642{
643 server_init_dispatch_13();
644 debug("server_init_dispatch_15");
645 dispatch_set(SSH_MSG_CHANNEL_CLOSE, &channel_input_ieof);
646 dispatch_set(SSH_MSG_CHANNEL_CLOSE_CONFIRMATION, &channel_input_oclose);
647}
648void
649server_init_dispatch()
650{
651 if (compat13)
652 server_init_dispatch_13();
653 else
654 server_init_dispatch_15();
655}