summaryrefslogtreecommitdiff
path: root/serverloop.c
diff options
context:
space:
mode:
authorDamien Miller <djm@mindrot.org>1999-11-25 00:26:21 +1100
committerDamien Miller <djm@mindrot.org>1999-11-25 00:26:21 +1100
commit95def09838fc61b37b6ea7cd5c234a465b4b129b (patch)
tree042744f76f40a326b873cb1c3690a6d7d966bc3e /serverloop.c
parent4d2f15f895f4c795afc008aeff3fd2ceffbc44f4 (diff)
- Merged very large OpenBSD source code reformat
- OpenBSD CVS updates - [channels.c cipher.c compat.c log-client.c scp.c serverloop.c] [ssh.h sshd.8 sshd.c] syslog changes: * Unified Logmessage for all auth-types, for success and for failed * Standard connections get only ONE line in the LOG when level==LOG: Auth-attempts are logged only, if authentication is: a) successfull or b) with passwd or c) we had more than AUTH_FAIL_LOG failues * many log() became verbose() * old behaviour with level=VERBOSE - [readconf.c readconf.h ssh.1 ssh.h sshconnect.c sshd.c] tranfer s/key challenge/response data in SSH_SMSG_AUTH_TIS_CHALLENGE messages. allows use of s/key in windows (ttssh, securecrt) and ssh-1.2.27 clients without 'ssh -v', ok: niels@ - [sshd.8] -V, for fallback to openssh in SSH2 compatibility mode - [sshd.c] fix sigchld race; cjc5@po.cwru.edu
Diffstat (limited to 'serverloop.c')
-rw-r--r--serverloop.c1112
1 files changed, 548 insertions, 564 deletions
diff --git a/serverloop.c b/serverloop.c
index 9961170a5..fc959baef 100644
--- a/serverloop.c
+++ b/serverloop.c
@@ -1,17 +1,10 @@
1/* 1/*
2 2 * Author: Tatu Ylonen <ylo@cs.hut.fi>
3serverloop.c 3 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
4 4 * All rights reserved
5Author: Tatu Ylonen <ylo@cs.hut.fi> 5 * Created: Sun Sep 10 00:30:37 1995 ylo
6 6 * Server main loop for handling the interactive session.
7Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 7 */
8 All rights reserved
9
10Created: Sun Sep 10 00:30:37 1995 ylo
11
12Server main loop for handling the interactive session.
13
14*/
15 8
16#include "includes.h" 9#include "includes.h"
17#include "xmalloc.h" 10#include "xmalloc.h"
@@ -43,603 +36,594 @@ static int max_fd; /* Max file descriptor number for select(). */
43/* This SIGCHLD kludge is used to detect when the child exits. The server 36/* This SIGCHLD kludge is used to detect when the child exits. The server
44 will exit after that, as soon as forwarded connections have terminated. */ 37 will exit after that, as soon as forwarded connections have terminated. */
45 38
46static int child_pid; /* Pid of the child. */ 39static int child_pid; /* Pid of the child. */
47static volatile int child_terminated; /* The child has terminated. */ 40static volatile int child_terminated; /* The child has terminated. */
48static volatile int child_wait_status; /* Status from wait(). */ 41static volatile int child_wait_status; /* Status from wait(). */
49 42
50void sigchld_handler(int sig) 43void
44sigchld_handler(int sig)
51{ 45{
52 int save_errno = errno; 46 int save_errno = errno;
53 int wait_pid; 47 int wait_pid;
54 debug("Received SIGCHLD."); 48 debug("Received SIGCHLD.");
55 wait_pid = wait((int *)&child_wait_status); 49 wait_pid = wait((int *) &child_wait_status);
56 if (wait_pid != -1) 50 if (wait_pid != -1) {
57 { 51 if (wait_pid != child_pid)
58 if (wait_pid != child_pid) 52 error("Strange, got SIGCHLD and wait returned pid %d but child is %d",
59 error("Strange, got SIGCHLD and wait returned pid %d but child is %d", 53 wait_pid, child_pid);
60 wait_pid, child_pid); 54 if (WIFEXITED(child_wait_status) ||
61 if (WIFEXITED(child_wait_status) || 55 WIFSIGNALED(child_wait_status))
62 WIFSIGNALED(child_wait_status)) 56 child_terminated = 1;
63 child_terminated = 1; 57 }
64 } 58 signal(SIGCHLD, sigchld_handler);
65 signal(SIGCHLD, sigchld_handler); 59 errno = save_errno;
66 errno = save_errno;
67} 60}
68 61
69/* Process any buffered packets that have been received from the client. */ 62/*
70 63 * Process any buffered packets that have been received from the client.
71void process_buffered_input_packets() 64 */
65void
66process_buffered_input_packets()
72{ 67{
73 int type; 68 int type;
74 char *data; 69 char *data;
75 unsigned int data_len; 70 unsigned int data_len;
76 int row, col, xpixel, ypixel; 71 int row, col, xpixel, ypixel;
77 int payload_len; 72 int payload_len;
78 73
79 /* Process buffered packets from the client. */ 74 /* Process buffered packets from the client. */
80 while ((type = packet_read_poll(&payload_len)) != SSH_MSG_NONE) 75 while ((type = packet_read_poll(&payload_len)) != SSH_MSG_NONE) {
81 { 76 switch (type) {
82 switch (type) 77 case SSH_CMSG_STDIN_DATA:
83 { 78 /* Stdin data from the client. Append it to the buffer. */
84 case SSH_CMSG_STDIN_DATA: 79 /* Ignore any data if the client has closed stdin. */
85 /* Stdin data from the client. Append it to the buffer. */ 80 if (fdin == -1)
86 if (fdin == -1) 81 break;
87 break; /* Ignore any data if the client has closed stdin. */ 82 data = packet_get_string(&data_len);
88 data = packet_get_string(&data_len); 83 packet_integrity_check(payload_len, (4 + data_len), type);
89 packet_integrity_check(payload_len, (4 + data_len), type); 84 buffer_append(&stdin_buffer, data, data_len);
90 buffer_append(&stdin_buffer, data, data_len); 85 memset(data, 0, data_len);
91 memset(data, 0, data_len); 86 xfree(data);
92 xfree(data); 87 break;
93 break; 88
94 89 case SSH_CMSG_EOF:
95 case SSH_CMSG_EOF: 90 /* Eof from the client. The stdin descriptor to
96 /* Eof from the client. The stdin descriptor to the program 91 the program will be closed when all buffered
97 will be closed when all buffered data has drained. */ 92 data has drained. */
98 debug("EOF received for stdin."); 93 debug("EOF received for stdin.");
99 packet_integrity_check(payload_len, 0, type); 94 packet_integrity_check(payload_len, 0, type);
100 stdin_eof = 1; 95 stdin_eof = 1;
101 break; 96 break;
102 97
103 case SSH_CMSG_WINDOW_SIZE: 98 case SSH_CMSG_WINDOW_SIZE:
104 debug("Window change received."); 99 debug("Window change received.");
105 packet_integrity_check(payload_len, 4*4, type); 100 packet_integrity_check(payload_len, 4 * 4, type);
106 row = packet_get_int(); 101 row = packet_get_int();
107 col = packet_get_int(); 102 col = packet_get_int();
108 xpixel = packet_get_int(); 103 xpixel = packet_get_int();
109 ypixel = packet_get_int(); 104 ypixel = packet_get_int();
110 if (fdin != -1) 105 if (fdin != -1)
111 pty_change_window_size(fdin, row, col, xpixel, ypixel); 106 pty_change_window_size(fdin, row, col, xpixel, ypixel);
112 break; 107 break;
113 108
114 case SSH_MSG_PORT_OPEN: 109 case SSH_MSG_PORT_OPEN:
115 debug("Received port open request."); 110 debug("Received port open request.");
116 channel_input_port_open(payload_len); 111 channel_input_port_open(payload_len);
117 break; 112 break;
118 113
119 case SSH_MSG_CHANNEL_OPEN_CONFIRMATION: 114 case SSH_MSG_CHANNEL_OPEN_CONFIRMATION:
120 debug("Received channel open confirmation."); 115 debug("Received channel open confirmation.");
121 packet_integrity_check(payload_len, 4 + 4, type); 116 packet_integrity_check(payload_len, 4 + 4, type);
122 channel_input_open_confirmation(); 117 channel_input_open_confirmation();
123 break; 118 break;
124 119
125 case SSH_MSG_CHANNEL_OPEN_FAILURE: 120 case SSH_MSG_CHANNEL_OPEN_FAILURE:
126 debug("Received channel open failure."); 121 debug("Received channel open failure.");
127 packet_integrity_check(payload_len, 4, type); 122 packet_integrity_check(payload_len, 4, type);
128 channel_input_open_failure(); 123 channel_input_open_failure();
129 break; 124 break;
130 125
131 case SSH_MSG_CHANNEL_DATA: 126 case SSH_MSG_CHANNEL_DATA:
132 channel_input_data(payload_len); 127 channel_input_data(payload_len);
133 break; 128 break;
134 129
135 case SSH_MSG_CHANNEL_CLOSE: 130 case SSH_MSG_CHANNEL_CLOSE:
136 debug("Received channel close."); 131 debug("Received channel close.");
137 packet_integrity_check(payload_len, 4, type); 132 packet_integrity_check(payload_len, 4, type);
138 channel_input_close(); 133 channel_input_close();
139 break; 134 break;
140 135
141 case SSH_MSG_CHANNEL_CLOSE_CONFIRMATION: 136 case SSH_MSG_CHANNEL_CLOSE_CONFIRMATION:
142 debug("Received channel close confirmation."); 137 debug("Received channel close confirmation.");
143 packet_integrity_check(payload_len, 4, type); 138 packet_integrity_check(payload_len, 4, type);
144 channel_input_close_confirmation(); 139 channel_input_close_confirmation();
145 break; 140 break;
146 141
147 default: 142 default:
148 /* In this phase, any unexpected messages cause a protocol 143 /* In this phase, any unexpected messages cause a
149 error. This is to ease debugging; also, since no 144 protocol error. This is to ease debugging;
150 confirmations are sent messages, unprocessed unknown 145 also, since no confirmations are sent messages,
151 messages could cause strange problems. Any compatible 146 unprocessed unknown messages could cause
152 protocol extensions must be negotiated before entering the 147 strange problems. Any compatible protocol
153 interactive session. */ 148 extensions must be negotiated before entering
154 packet_disconnect("Protocol error during session: type %d", 149 the interactive session. */
155 type); 150 packet_disconnect("Protocol error during session: type %d",
151 type);
152 }
156 } 153 }
157 }
158} 154}
159 155
160/* Make packets from buffered stderr data, and buffer it for sending 156/*
161 to the client. */ 157 * Make packets from buffered stderr data, and buffer it for sending
162 158 * to the client.
163void make_packets_from_stderr_data() 159 */
160void
161make_packets_from_stderr_data()
164{ 162{
165 int len; 163 int len;
166 164
167 /* Send buffered stderr data to the client. */ 165 /* Send buffered stderr data to the client. */
168 while (buffer_len(&stderr_buffer) > 0 && 166 while (buffer_len(&stderr_buffer) > 0 &&
169 packet_not_very_much_data_to_write()) 167 packet_not_very_much_data_to_write()) {
170 { 168 len = buffer_len(&stderr_buffer);
171 len = buffer_len(&stderr_buffer); 169 if (packet_is_interactive()) {
172 if (packet_is_interactive()) 170 if (len > 512)
173 { 171 len = 512;
174 if (len > 512) 172 } else {
175 len = 512; 173 /* Keep the packets at reasonable size. */
176 } 174 if (len > packet_get_maxsize())
177 else 175 len = packet_get_maxsize();
178 { 176 }
179 if (len > packet_get_maxsize()) 177 packet_start(SSH_SMSG_STDERR_DATA);
180 len = packet_get_maxsize(); /* Keep the packets at reasonable size. */ 178 packet_put_string(buffer_ptr(&stderr_buffer), len);
179 packet_send();
180 buffer_consume(&stderr_buffer, len);
181 stderr_bytes += len;
181 } 182 }
182 packet_start(SSH_SMSG_STDERR_DATA);
183 packet_put_string(buffer_ptr(&stderr_buffer), len);
184 packet_send();
185 buffer_consume(&stderr_buffer, len);
186 stderr_bytes += len;
187 }
188} 183}
189 184
190/* Make packets from buffered stdout data, and buffer it for sending to the 185/*
191 client. */ 186 * Make packets from buffered stdout data, and buffer it for sending to the
192 187 * client.
193void make_packets_from_stdout_data() 188 */
189void
190make_packets_from_stdout_data()
194{ 191{
195 int len; 192 int len;
196 193
197 /* Send buffered stdout data to the client. */ 194 /* Send buffered stdout data to the client. */
198 while (buffer_len(&stdout_buffer) > 0 && 195 while (buffer_len(&stdout_buffer) > 0 &&
199 packet_not_very_much_data_to_write()) 196 packet_not_very_much_data_to_write()) {
200 { 197 len = buffer_len(&stdout_buffer);
201 len = buffer_len(&stdout_buffer); 198 if (packet_is_interactive()) {
202 if (packet_is_interactive()) 199 if (len > 512)
203 { 200 len = 512;
204 if (len > 512) 201 } else {
205 len = 512; 202 /* Keep the packets at reasonable size. */
206 } 203 if (len > packet_get_maxsize())
207 else 204 len = packet_get_maxsize();
208 { 205 }
209 if (len > packet_get_maxsize()) 206 packet_start(SSH_SMSG_STDOUT_DATA);
210 len = packet_get_maxsize(); /* Keep the packets at reasonable size. */ 207 packet_put_string(buffer_ptr(&stdout_buffer), len);
208 packet_send();
209 buffer_consume(&stdout_buffer, len);
210 stdout_bytes += len;
211 } 211 }
212 packet_start(SSH_SMSG_STDOUT_DATA);
213 packet_put_string(buffer_ptr(&stdout_buffer), len);
214 packet_send();
215 buffer_consume(&stdout_buffer, len);
216 stdout_bytes += len;
217 }
218} 212}
219 213
220/* Sleep in select() until we can do something. This will initialize the 214/*
221 select masks. Upon return, the masks will indicate which descriptors 215 * Sleep in select() until we can do something. This will initialize the
222 have data or can accept data. Optionally, a maximum time can be specified 216 * select masks. Upon return, the masks will indicate which descriptors
223 for the duration of the wait (0 = infinite). */ 217 * have data or can accept data. Optionally, a maximum time can be specified
224 218 * for the duration of the wait (0 = infinite).
225void wait_until_can_do_something(fd_set *readset, fd_set *writeset, 219 */
226 unsigned int max_time_milliseconds) 220void
221wait_until_can_do_something(fd_set * readset, fd_set * writeset,
222 unsigned int max_time_milliseconds)
227{ 223{
228 struct timeval tv, *tvp; 224 struct timeval tv, *tvp;
229 int ret; 225 int ret;
230 226
231 /* When select fails we restart from here. */ 227 /* When select fails we restart from here. */
232retry_select: 228retry_select:
233 229
234 /* Initialize select() masks. */ 230 /* Initialize select() masks. */
235 FD_ZERO(readset); 231 FD_ZERO(readset);
236 232
237 /* Read packets from the client unless we have too much buffered stdin 233 /* Read packets from the client unless we have too much buffered
238 or channel data. */ 234 stdin or channel data. */
239 if (buffer_len(&stdin_buffer) < 4096 && 235 if (buffer_len(&stdin_buffer) < 4096 &&
240 channel_not_very_much_buffered_data()) 236 channel_not_very_much_buffered_data())
241 FD_SET(connection_in, readset); 237 FD_SET(connection_in, readset);
242 238
243 /* If there is not too much data already buffered going to the client, 239 /* If there is not too much data already buffered going to the
244 try to get some more data from the program. */ 240 client, try to get some more data from the program. */
245 if (packet_not_very_much_data_to_write()) 241 if (packet_not_very_much_data_to_write()) {
246 { 242 if (!fdout_eof)
247 if (!fdout_eof) 243 FD_SET(fdout, readset);
248 FD_SET(fdout, readset); 244 if (!fderr_eof)
249 if (!fderr_eof) 245 FD_SET(fderr, readset);
250 FD_SET(fderr, readset); 246 }
251 } 247 FD_ZERO(writeset);
252 248
253 FD_ZERO(writeset); 249 /* Set masks for channel descriptors. */
254 250 channel_prepare_select(readset, writeset);
255 /* Set masks for channel descriptors. */ 251
256 channel_prepare_select(readset, writeset); 252 /* If we have buffered packet data going to the client, mark that
257 253 descriptor. */
258 /* If we have buffered packet data going to the client, mark that 254 if (packet_have_data_to_write())
259 descriptor. */ 255 FD_SET(connection_out, writeset);
260 if (packet_have_data_to_write()) 256
261 FD_SET(connection_out, writeset); 257 /* If we have buffered data, try to write some of that data to the
262 258 program. */
263 /* If we have buffered data, try to write some of that data to the 259 if (fdin != -1 && buffer_len(&stdin_buffer) > 0)
264 program. */ 260 FD_SET(fdin, writeset);
265 if (fdin != -1 && buffer_len(&stdin_buffer) > 0) 261
266 FD_SET(fdin, writeset); 262 /* Update the maximum descriptor number if appropriate. */
267 263 if (channel_max_fd() > max_fd)
268 /* Update the maximum descriptor number if appropriate. */ 264 max_fd = channel_max_fd();
269 if (channel_max_fd() > max_fd) 265
270 max_fd = channel_max_fd(); 266 /* If child has terminated and there is enough buffer space to
271 267 read from it, then read as much as is available and exit. */
272 /* If child has terminated and there is enough buffer space to read from 268 if (child_terminated && packet_not_very_much_data_to_write())
273 it, then read as much as is available and exit. */ 269 if (max_time_milliseconds == 0)
274 if (child_terminated && packet_not_very_much_data_to_write()) 270 max_time_milliseconds = 100;
275 if (max_time_milliseconds == 0) 271
276 max_time_milliseconds = 100; 272 if (max_time_milliseconds == 0)
277 273 tvp = NULL;
278 if (max_time_milliseconds == 0) 274 else {
279 tvp = NULL; 275 tv.tv_sec = max_time_milliseconds / 1000;
280 else 276 tv.tv_usec = 1000 * (max_time_milliseconds % 1000);
281 { 277 tvp = &tv;
282 tv.tv_sec = max_time_milliseconds / 1000; 278 }
283 tv.tv_usec = 1000 * (max_time_milliseconds % 1000);
284 tvp = &tv;
285 }
286
287 /* Wait for something to happen, or the timeout to expire. */
288 ret = select(max_fd + 1, readset, writeset, NULL, tvp);
289
290 if (ret < 0)
291 {
292 if (errno != EINTR)
293 error("select: %.100s", strerror(errno));
294 else
295 goto retry_select;
296 }
297}
298 279
299/* Processes input from the client and the program. Input data is stored 280 /* Wait for something to happen, or the timeout to expire. */
300 in buffers and processed later. */ 281 ret = select(max_fd + 1, readset, writeset, NULL, tvp);
301 282
302void process_input(fd_set *readset) 283 if (ret < 0) {
303{ 284 if (errno != EINTR)
304 int len; 285 error("select: %.100s", strerror(errno));
305 char buf[16384]; 286 else
306 287 goto retry_select;
307 /* Read and buffer any input data from the client. */
308 if (FD_ISSET(connection_in, readset))
309 {
310 len = read(connection_in, buf, sizeof(buf));
311 if (len == 0)
312 fatal("Connection closed by remote host.");
313
314 /* There is a kernel bug on Solaris that causes select to sometimes
315 wake up even though there is no data available. */
316 if (len < 0 && errno == EAGAIN)
317 len = 0;
318
319 if (len < 0)
320 fatal("Read error from remote host: %.100s", strerror(errno));
321
322 /* Buffer any received data. */
323 packet_process_incoming(buf, len);
324 }
325
326 /* Read and buffer any available stdout data from the program. */
327 if (!fdout_eof && FD_ISSET(fdout, readset))
328 {
329 len = read(fdout, buf, sizeof(buf));
330 if (len <= 0)
331 fdout_eof = 1;
332 else
333 {
334 buffer_append(&stdout_buffer, buf, len);
335 fdout_bytes += len;
336 } 288 }
337 }
338
339 /* Read and buffer any available stderr data from the program. */
340 if (!fderr_eof && FD_ISSET(fderr, readset))
341 {
342 len = read(fderr, buf, sizeof(buf));
343 if (len <= 0)
344 fderr_eof = 1;
345 else
346 buffer_append(&stderr_buffer, buf, len);
347 }
348} 289}
349 290
350/* Sends data from internal buffers to client program stdin. */ 291/*
292 * Processes input from the client and the program. Input data is stored
293 * in buffers and processed later.
294 */
295void
296process_input(fd_set * readset)
297{
298 int len;
299 char buf[16384];
300
301 /* Read and buffer any input data from the client. */
302 if (FD_ISSET(connection_in, readset)) {
303 len = read(connection_in, buf, sizeof(buf));
304 if (len == 0) {
305 verbose("Connection closed by remote host.");
306 fatal_cleanup();
307 }
308 /* There is a kernel bug on Solaris that causes select to
309 sometimes wake up even though there is no data
310 available. */
311 if (len < 0 && errno == EAGAIN)
312 len = 0;
313
314 if (len < 0) {
315 verbose("Read error from remote host: %.100s", strerror(errno));
316 fatal_cleanup();
317 }
318 /* Buffer any received data. */
319 packet_process_incoming(buf, len);
320 }
321 /* Read and buffer any available stdout data from the program. */
322 if (!fdout_eof && FD_ISSET(fdout, readset)) {
323 len = read(fdout, buf, sizeof(buf));
324 if (len <= 0)
325 fdout_eof = 1;
326 else {
327 buffer_append(&stdout_buffer, buf, len);
328 fdout_bytes += len;
329 }
330 }
331 /* Read and buffer any available stderr data from the program. */
332 if (!fderr_eof && FD_ISSET(fderr, readset)) {
333 len = read(fderr, buf, sizeof(buf));
334 if (len <= 0)
335 fderr_eof = 1;
336 else
337 buffer_append(&stderr_buffer, buf, len);
338 }
339}
351 340
352void process_output(fd_set *writeset) 341/*
342 * Sends data from internal buffers to client program stdin.
343 */
344void
345process_output(fd_set * writeset)
353{ 346{
354 int len; 347 int len;
355 348
356 /* Write buffered data to program stdin. */ 349 /* Write buffered data to program stdin. */
357 if (fdin != -1 && FD_ISSET(fdin, writeset)) 350 if (fdin != -1 && FD_ISSET(fdin, writeset)) {
358 { 351 len = write(fdin, buffer_ptr(&stdin_buffer),
359 len = write(fdin, buffer_ptr(&stdin_buffer), 352 buffer_len(&stdin_buffer));
360 buffer_len(&stdin_buffer)); 353 if (len <= 0) {
361 if (len <= 0)
362 {
363#ifdef USE_PIPES 354#ifdef USE_PIPES
364 close(fdin); 355 close(fdin);
365#else 356#else
366 if (fdout == -1) 357 if (fdout == -1)
367 close(fdin); 358 close(fdin);
368 else 359 else
369 shutdown(fdin, SHUT_WR); /* We will no longer send. */ 360 shutdown(fdin, SHUT_WR); /* We will no longer send. */
370#endif 361#endif
371 fdin = -1; 362 fdin = -1;
372 } 363 } else {
373 else 364 /* Successful write. Consume the data from the buffer. */
374 { 365 buffer_consume(&stdin_buffer, len);
375 /* Successful write. Consume the data from the buffer. */ 366 /* Update the count of bytes written to the program. */
376 buffer_consume(&stdin_buffer, len); 367 stdin_bytes += len;
377 /* Update the count of bytes written to the program. */ 368 }
378 stdin_bytes += len;
379 } 369 }
380 } 370 /* Send any buffered packet data to the client. */
381 371 if (FD_ISSET(connection_out, writeset))
382 /* Send any buffered packet data to the client. */ 372 packet_write_poll();
383 if (FD_ISSET(connection_out, writeset))
384 packet_write_poll();
385} 373}
386 374
387/* Wait until all buffered output has been sent to the client. 375/*
388 This is used when the program terminates. */ 376 * Wait until all buffered output has been sent to the client.
389 377 * This is used when the program terminates.
390void drain_output() 378 */
379void
380drain_output()
391{ 381{
392 /* Send any buffered stdout data to the client. */ 382 /* Send any buffered stdout data to the client. */
393 if (buffer_len(&stdout_buffer) > 0) 383 if (buffer_len(&stdout_buffer) > 0) {
394 { 384 packet_start(SSH_SMSG_STDOUT_DATA);
395 packet_start(SSH_SMSG_STDOUT_DATA); 385 packet_put_string(buffer_ptr(&stdout_buffer),
396 packet_put_string(buffer_ptr(&stdout_buffer), 386 buffer_len(&stdout_buffer));
397 buffer_len(&stdout_buffer)); 387 packet_send();
398 packet_send(); 388 /* Update the count of sent bytes. */
399 /* Update the count of sent bytes. */ 389 stdout_bytes += buffer_len(&stdout_buffer);
400 stdout_bytes += buffer_len(&stdout_buffer); 390 }
401 } 391 /* Send any buffered stderr data to the client. */
402 392 if (buffer_len(&stderr_buffer) > 0) {
403 /* Send any buffered stderr data to the client. */ 393 packet_start(SSH_SMSG_STDERR_DATA);
404 if (buffer_len(&stderr_buffer) > 0) 394 packet_put_string(buffer_ptr(&stderr_buffer),
405 { 395 buffer_len(&stderr_buffer));
406 packet_start(SSH_SMSG_STDERR_DATA); 396 packet_send();
407 packet_put_string(buffer_ptr(&stderr_buffer), 397 /* Update the count of sent bytes. */
408 buffer_len(&stderr_buffer)); 398 stderr_bytes += buffer_len(&stderr_buffer);
409 packet_send(); 399 }
410 /* Update the count of sent bytes. */ 400 /* Wait until all buffered data has been written to the client. */
411 stderr_bytes += buffer_len(&stderr_buffer); 401 packet_write_wait();
412 }
413
414 /* Wait until all buffered data has been written to the client. */
415 packet_write_wait();
416} 402}
417 403
418/* Performs the interactive session. This handles data transmission between 404/*
419 the client and the program. Note that the notion of stdin, stdout, and 405 * Performs the interactive session. This handles data transmission between
420 stderr in this function is sort of reversed: this function writes to 406 * the client and the program. Note that the notion of stdin, stdout, and
421 stdin (of the child program), and reads from stdout and stderr (of the 407 * stderr in this function is sort of reversed: this function writes to
422 child program). */ 408 * stdin (of the child program), and reads from stdout and stderr (of the
423 409 * child program).
424void server_loop(int pid, int fdin_arg, int fdout_arg, int fderr_arg) 410 */
411void
412server_loop(int pid, int fdin_arg, int fdout_arg, int fderr_arg)
425{ 413{
426 int wait_status, wait_pid; /* Status and pid returned by wait(). */ 414 int wait_status, wait_pid; /* Status and pid returned by wait(). */
427 int waiting_termination = 0; /* Have displayed waiting close message. */ 415 int waiting_termination = 0; /* Have displayed waiting close message. */
428 unsigned int max_time_milliseconds; 416 unsigned int max_time_milliseconds;
429 unsigned int previous_stdout_buffer_bytes; 417 unsigned int previous_stdout_buffer_bytes;
430 unsigned int stdout_buffer_bytes; 418 unsigned int stdout_buffer_bytes;
431 int type; 419 int type;
432 420
433 debug("Entering interactive session."); 421 debug("Entering interactive session.");
434 422
435 /* Initialize the SIGCHLD kludge. */ 423 /* Initialize the SIGCHLD kludge. */
436 child_pid = pid; 424 child_pid = pid;
437 child_terminated = 0; 425 child_terminated = 0;
438 signal(SIGCHLD, sigchld_handler); 426 signal(SIGCHLD, sigchld_handler);
439 427
440 /* Initialize our global variables. */ 428 /* Initialize our global variables. */
441 fdin = fdin_arg; 429 fdin = fdin_arg;
442 fdout = fdout_arg; 430 fdout = fdout_arg;
443 fderr = fderr_arg; 431 fderr = fderr_arg;
444 connection_in = packet_get_connection_in(); 432 connection_in = packet_get_connection_in();
445 connection_out = packet_get_connection_out(); 433 connection_out = packet_get_connection_out();
446 434
447 previous_stdout_buffer_bytes = 0; 435 previous_stdout_buffer_bytes = 0;
448 436
449 /* Set approximate I/O buffer size. */ 437 /* Set approximate I/O buffer size. */
450 if (packet_is_interactive()) 438 if (packet_is_interactive())
451 buffer_high = 4096; 439 buffer_high = 4096;
452 else 440 else
453 buffer_high = 64 * 1024; 441 buffer_high = 64 * 1024;
454 442
455 /* Initialize max_fd to the maximum of the known file descriptors. */ 443 /* Initialize max_fd to the maximum of the known file descriptors. */
456 max_fd = fdin; 444 max_fd = fdin;
457 if (fdout > max_fd) 445 if (fdout > max_fd)
458 max_fd = fdout; 446 max_fd = fdout;
459 if (fderr != -1 && fderr > max_fd) 447 if (fderr != -1 && fderr > max_fd)
460 max_fd = fderr; 448 max_fd = fderr;
461 if (connection_in > max_fd) 449 if (connection_in > max_fd)
462 max_fd = connection_in; 450 max_fd = connection_in;
463 if (connection_out > max_fd) 451 if (connection_out > max_fd)
464 max_fd = connection_out; 452 max_fd = connection_out;
465 453
466 /* Initialize Initialize buffers. */ 454 /* Initialize Initialize buffers. */
467 buffer_init(&stdin_buffer); 455 buffer_init(&stdin_buffer);
468 buffer_init(&stdout_buffer); 456 buffer_init(&stdout_buffer);
469 buffer_init(&stderr_buffer); 457 buffer_init(&stderr_buffer);
470 458
471 /* If we have no separate fderr (which is the case when we have a pty - there 459 /* If we have no separate fderr (which is the case when we have a
472 we cannot make difference between data sent to stdout and stderr), 460 pty - there we cannot make difference between data sent to
473 indicate that we have seen an EOF from stderr. This way we don\'t 461 stdout and stderr), indicate that we have seen an EOF from
474 need to check the descriptor everywhere. */ 462 stderr. This way we don\'t need to check the descriptor
475 if (fderr == -1) 463 everywhere. */
476 fderr_eof = 1; 464 if (fderr == -1)
477 465 fderr_eof = 1;
478 /* Main loop of the server for the interactive session mode. */ 466
479 for (;;) 467 /* Main loop of the server for the interactive session mode. */
480 { 468 for (;;) {
481 fd_set readset, writeset; 469 fd_set readset, writeset;
482 470
483 /* Process buffered packets from the client. */ 471 /* Process buffered packets from the client. */
484 process_buffered_input_packets(); 472 process_buffered_input_packets();
485 473
486 /* If we have received eof, and there is no more pending input data, 474 /* If we have received eof, and there is no more pending
487 cause a real eof by closing fdin. */ 475 input data, cause a real eof by closing fdin. */
488 if (stdin_eof && fdin != -1 && buffer_len(&stdin_buffer) == 0) 476 if (stdin_eof && fdin != -1 && buffer_len(&stdin_buffer) == 0) {
489 {
490#ifdef USE_PIPES 477#ifdef USE_PIPES
491 close(fdin); 478 close(fdin);
492#else 479#else
493 if (fdout == -1) 480 if (fdout == -1)
494 close(fdin); 481 close(fdin);
495 else 482 else
496 shutdown(fdin, SHUT_WR); /* We will no longer send. */ 483 shutdown(fdin, SHUT_WR); /* We will no longer send. */
497#endif 484#endif
498 fdin = -1; 485 fdin = -1;
486 }
487 /* Make packets from buffered stderr data to send to the
488 client. */
489 make_packets_from_stderr_data();
490
491 /* Make packets from buffered stdout data to send to the
492 client. If there is very little to send, this arranges
493 to not send them now, but to wait a short while to see
494 if we are getting more data. This is necessary, as some
495 systems wake up readers from a pty after each separate
496 character. */
497 max_time_milliseconds = 0;
498 stdout_buffer_bytes = buffer_len(&stdout_buffer);
499 if (stdout_buffer_bytes != 0 && stdout_buffer_bytes < 256 &&
500 stdout_buffer_bytes != previous_stdout_buffer_bytes) {
501 /* try again after a while */
502 max_time_milliseconds = 10;
503 } else {
504 /* Send it now. */
505 make_packets_from_stdout_data();
506 }
507 previous_stdout_buffer_bytes = buffer_len(&stdout_buffer);
508
509 /* Send channel data to the client. */
510 if (packet_not_very_much_data_to_write())
511 channel_output_poll();
512
513 /* Bail out of the loop if the program has closed its
514 output descriptors, and we have no more data to send to
515 the client, and there is no pending buffered data. */
516 if (fdout_eof && fderr_eof && !packet_have_data_to_write() &&
517 buffer_len(&stdout_buffer) == 0 && buffer_len(&stderr_buffer) == 0) {
518 if (!channel_still_open())
519 goto quit;
520 if (!waiting_termination) {
521 const char *s = "Waiting for forwarded connections to terminate...\r\n";
522 char *cp;
523 waiting_termination = 1;
524 buffer_append(&stderr_buffer, s, strlen(s));
525
526 /* Display list of open channels. */
527 cp = channel_open_message();
528 buffer_append(&stderr_buffer, cp, strlen(cp));
529 xfree(cp);
530 }
531 }
532 /* Sleep in select() until we can do something. */
533 wait_until_can_do_something(&readset, &writeset,
534 max_time_milliseconds);
535
536 /* Process any channel events. */
537 channel_after_select(&readset, &writeset);
538
539 /* Process input from the client and from program stdout/stderr. */
540 process_input(&readset);
541
542 /* Process output to the client and to program stdin. */
543 process_output(&writeset);
499 } 544 }
500 545
501 /* Make packets from buffered stderr data to send to the client. */ 546quit:
502 make_packets_from_stderr_data(); 547 /* Cleanup and termination code. */
503
504 /* Make packets from buffered stdout data to send to the client.
505 If there is very little to send, this arranges to not send them
506 now, but to wait a short while to see if we are getting more data.
507 This is necessary, as some systems wake up readers from a pty after
508 each separate character. */
509 max_time_milliseconds = 0;
510 stdout_buffer_bytes = buffer_len(&stdout_buffer);
511 if (stdout_buffer_bytes != 0 && stdout_buffer_bytes < 256 &&
512 stdout_buffer_bytes != previous_stdout_buffer_bytes)
513 max_time_milliseconds = 10; /* try again after a while */
514 else
515 make_packets_from_stdout_data(); /* Send it now. */
516 previous_stdout_buffer_bytes = buffer_len(&stdout_buffer);
517
518 /* Send channel data to the client. */
519 if (packet_not_very_much_data_to_write())
520 channel_output_poll();
521
522 /* Bail out of the loop if the program has closed its output descriptors,
523 and we have no more data to send to the client, and there is no
524 pending buffered data. */
525 if (fdout_eof && fderr_eof && !packet_have_data_to_write() &&
526 buffer_len(&stdout_buffer) == 0 && buffer_len(&stderr_buffer) == 0)
527 {
528 if (!channel_still_open())
529 goto quit;
530 if (!waiting_termination)
531 {
532 const char *s =
533 "Waiting for forwarded connections to terminate...\r\n";
534 char *cp;
535 waiting_termination = 1;
536 buffer_append(&stderr_buffer, s, strlen(s));
537
538 /* Display list of open channels. */
539 cp = channel_open_message();
540 buffer_append(&stderr_buffer, cp, strlen(cp));
541 xfree(cp);
542 }
543 }
544 548
545 /* Sleep in select() until we can do something. */ 549 /* Wait until all output has been sent to the client. */
546 wait_until_can_do_something(&readset, &writeset, 550 drain_output();
547 max_time_milliseconds);
548
549 /* Process any channel events. */
550 channel_after_select(&readset, &writeset);
551
552 /* Process input from the client and from program stdout/stderr. */
553 process_input(&readset);
554
555 /* Process output to the client and to program stdin. */
556 process_output(&writeset);
557 }
558
559 quit:
560 /* Cleanup and termination code. */
561
562 /* Wait until all output has been sent to the client. */
563 drain_output();
564
565 debug("End of interactive session; stdin %ld, stdout (read %ld, sent %ld), stderr %ld bytes.",
566 stdin_bytes, fdout_bytes, stdout_bytes, stderr_bytes);
567
568 /* Free and clear the buffers. */
569 buffer_free(&stdin_buffer);
570 buffer_free(&stdout_buffer);
571 buffer_free(&stderr_buffer);
572
573 /* Close the file descriptors. */
574 if (fdout != -1)
575 close(fdout);
576 fdout = -1;
577 fdout_eof = 1;
578 if (fderr != -1)
579 close(fderr);
580 fderr = -1;
581 fderr_eof = 1;
582 if (fdin != -1)
583 close(fdin);
584 fdin = -1;
585
586 /* Stop listening for channels; this removes unix domain sockets. */
587 channel_stop_listening();
588
589 /* Wait for the child to exit. Get its exit status. */
590 wait_pid = wait(&wait_status);
591 if (wait_pid < 0)
592 {
593 /* It is possible that the wait was handled by SIGCHLD handler. This
594 may result in either: this call returning with EINTR, or: this
595 call returning ECHILD. */
596 if (child_terminated)
597 wait_status = child_wait_status;
598 else
599 packet_disconnect("wait: %.100s", strerror(errno));
600 }
601 else
602 {
603 /* Check if it matches the process we forked. */
604 if (wait_pid != pid)
605 error("Strange, wait returned pid %d, expected %d", wait_pid, pid);
606 }
607
608 /* We no longer want our SIGCHLD handler to be called. */
609 signal(SIGCHLD, SIG_DFL);
610
611 /* Check if it exited normally. */
612 if (WIFEXITED(wait_status))
613 {
614 /* Yes, normal exit. Get exit status and send it to the client. */
615 debug("Command exited with status %d.", WEXITSTATUS(wait_status));
616 packet_start(SSH_SMSG_EXITSTATUS);
617 packet_put_int(WEXITSTATUS(wait_status));
618 packet_send();
619 packet_write_wait();
620
621 /* Wait for exit confirmation. Note that there might be other
622 packets coming before it; however, the program has already died
623 so we just ignore them. The client is supposed to respond with
624 the confirmation when it receives the exit status. */
625 do
626 {
627 int plen;
628 type = packet_read(&plen);
629 }
630 while (type != SSH_CMSG_EXIT_CONFIRMATION);
631 551
632 debug("Received exit confirmation."); 552 debug("End of interactive session; stdin %ld, stdout (read %ld, sent %ld), stderr %ld bytes.",
633 return; 553 stdin_bytes, fdout_bytes, stdout_bytes, stderr_bytes);
634 }
635 554
636 /* Check if the program terminated due to a signal. */ 555 /* Free and clear the buffers. */
637 if (WIFSIGNALED(wait_status)) 556 buffer_free(&stdin_buffer);
638 packet_disconnect("Command terminated on signal %d.", 557 buffer_free(&stdout_buffer);
639 WTERMSIG(wait_status)); 558 buffer_free(&stderr_buffer);
640 559
641 /* Some weird exit cause. Just exit. */ 560 /* Close the file descriptors. */
642 packet_disconnect("wait returned status %04x.", wait_status); 561 if (fdout != -1)
643 /*NOTREACHED*/ 562 close(fdout);
644} 563 fdout = -1;
564 fdout_eof = 1;
565 if (fderr != -1)
566 close(fderr);
567 fderr = -1;
568 fderr_eof = 1;
569 if (fdin != -1)
570 close(fdin);
571 fdin = -1;
572
573 /* Stop listening for channels; this removes unix domain sockets. */
574 channel_stop_listening();
575
576 /* Wait for the child to exit. Get its exit status. */
577 wait_pid = wait(&wait_status);
578 if (wait_pid < 0) {
579 /*
580 * It is possible that the wait was handled by SIGCHLD
581 * handler. This may result in either: this call
582 * returning with EINTR, or: this call returning ECHILD.
583 */
584 if (child_terminated)
585 wait_status = child_wait_status;
586 else
587 packet_disconnect("wait: %.100s", strerror(errno));
588 } else {
589 /* Check if it matches the process we forked. */
590 if (wait_pid != pid)
591 error("Strange, wait returned pid %d, expected %d",
592 wait_pid, pid);
593 }
645 594
595 /* We no longer want our SIGCHLD handler to be called. */
596 signal(SIGCHLD, SIG_DFL);
597
598 /* Check if it exited normally. */
599 if (WIFEXITED(wait_status)) {
600 /* Yes, normal exit. Get exit status and send it to the client. */
601 debug("Command exited with status %d.", WEXITSTATUS(wait_status));
602 packet_start(SSH_SMSG_EXITSTATUS);
603 packet_put_int(WEXITSTATUS(wait_status));
604 packet_send();
605 packet_write_wait();
606
607 /* Wait for exit confirmation. Note that there might be
608 other packets coming before it; however, the program
609 has already died so we just ignore them. The client is
610 supposed to respond with the confirmation when it
611 receives the exit status. */
612 do {
613 int plen;
614 type = packet_read(&plen);
615 }
616 while (type != SSH_CMSG_EXIT_CONFIRMATION);
617
618 debug("Received exit confirmation.");
619 return;
620 }
621 /* Check if the program terminated due to a signal. */
622 if (WIFSIGNALED(wait_status))
623 packet_disconnect("Command terminated on signal %d.",
624 WTERMSIG(wait_status));
625
626 /* Some weird exit cause. Just exit. */
627 packet_disconnect("wait returned status %04x.", wait_status);
628 /* NOTREACHED */
629}