]> andersk Git - openssh.git/blob - serverloop.c
- Big OpenBSD CVS update (mainly beginnings of SSH2 infrastructure)
[openssh.git] / serverloop.c
1 /*
2  * Author: Tatu Ylonen <ylo@cs.hut.fi>
3  * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
4  *                    All rights reserved
5  * Created: Sun Sep 10 00:30:37 1995 ylo
6  * Server main loop for handling the interactive session.
7  */
8
9 #include "includes.h"
10 #include "xmalloc.h"
11 #include "ssh.h"
12 #include "packet.h"
13 #include "buffer.h"
14 #include "servconf.h"
15 #include "pty.h"
16 #include "channels.h"
17
18 #include "compat.h"
19 #include "dispatch.h"
20
21 static Buffer stdin_buffer;     /* Buffer for stdin data. */
22 static Buffer stdout_buffer;    /* Buffer for stdout data. */
23 static Buffer stderr_buffer;    /* Buffer for stderr data. */
24 static int fdin;                /* Descriptor for stdin (for writing) */
25 static int fdout;               /* Descriptor for stdout (for reading);
26                                    May be same number as fdin. */
27 static int fderr;               /* Descriptor for stderr.  May be -1. */
28 static long stdin_bytes = 0;    /* Number of bytes written to stdin. */
29 static long stdout_bytes = 0;   /* Number of stdout bytes sent to client. */
30 static long stderr_bytes = 0;   /* Number of stderr bytes sent to client. */
31 static long fdout_bytes = 0;    /* Number of stdout bytes read from program. */
32 static int stdin_eof = 0;       /* EOF message received from client. */
33 static int fdout_eof = 0;       /* EOF encountered reading from fdout. */
34 static int fderr_eof = 0;       /* EOF encountered readung from fderr. */
35 static int connection_in;       /* Connection to client (input). */
36 static int connection_out;      /* Connection to client (output). */
37 static unsigned int buffer_high;/* "Soft" max buffer size. */
38 static int max_fd;              /* Max file descriptor number for select(). */
39
40 /*
41  * This SIGCHLD kludge is used to detect when the child exits.  The server
42  * will exit after that, as soon as forwarded connections have terminated.
43  *
44  * After SIGCHLD child_has_selected is set to 1 after the first pass
45  * through the wait_until_can_do_something() select(). This ensures
46  * that the child's output gets a chance to drain before it is yanked.
47  */
48
49 static int child_pid;                   /* Pid of the child. */
50 static volatile int child_terminated;   /* The child has terminated. */
51 static volatile int child_has_selected; /* Child has had chance to drain. */
52 static volatile int child_wait_status;  /* Status from wait(). */
53
54 void    server_init_dispatch(void);
55
56 void 
57 sigchld_handler(int sig)
58 {
59         int save_errno = errno;
60         int wait_pid;
61         debug("Received SIGCHLD.");
62         wait_pid = wait((int *) &child_wait_status);
63         if (wait_pid != -1) {
64                 if (wait_pid != child_pid)
65                         error("Strange, got SIGCHLD and wait returned pid %d but child is %d",
66                               wait_pid, child_pid);
67                 if (WIFEXITED(child_wait_status) ||
68                     WIFSIGNALED(child_wait_status))
69                         child_terminated = 1;
70                         child_has_selected = 0;
71         }
72         signal(SIGCHLD, sigchld_handler);
73         errno = save_errno;
74 }
75
76 /*
77  * Make packets from buffered stderr data, and buffer it for sending
78  * to the client.
79  */
80 void 
81 make_packets_from_stderr_data()
82 {
83         int len;
84
85         /* Send buffered stderr data to the client. */
86         while (buffer_len(&stderr_buffer) > 0 &&
87             packet_not_very_much_data_to_write()) {
88                 len = buffer_len(&stderr_buffer);
89                 if (packet_is_interactive()) {
90                         if (len > 512)
91                                 len = 512;
92                 } else {
93                         /* Keep the packets at reasonable size. */
94                         if (len > packet_get_maxsize())
95                                 len = packet_get_maxsize();
96                 }
97                 packet_start(SSH_SMSG_STDERR_DATA);
98                 packet_put_string(buffer_ptr(&stderr_buffer), len);
99                 packet_send();
100                 buffer_consume(&stderr_buffer, len);
101                 stderr_bytes += len;
102         }
103 }
104
105 /*
106  * Make packets from buffered stdout data, and buffer it for sending to the
107  * client.
108  */
109 void 
110 make_packets_from_stdout_data()
111 {
112         int len;
113
114         /* Send buffered stdout data to the client. */
115         while (buffer_len(&stdout_buffer) > 0 &&
116             packet_not_very_much_data_to_write()) {
117                 len = buffer_len(&stdout_buffer);
118                 if (packet_is_interactive()) {
119                         if (len > 512)
120                                 len = 512;
121                 } else {
122                         /* Keep the packets at reasonable size. */
123                         if (len > packet_get_maxsize())
124                                 len = packet_get_maxsize();     
125                 }
126                 packet_start(SSH_SMSG_STDOUT_DATA);
127                 packet_put_string(buffer_ptr(&stdout_buffer), len);
128                 packet_send();
129                 buffer_consume(&stdout_buffer, len);
130                 stdout_bytes += len;
131         }
132 }
133
134 /*
135  * Sleep in select() until we can do something.  This will initialize the
136  * select masks.  Upon return, the masks will indicate which descriptors
137  * have data or can accept data.  Optionally, a maximum time can be specified
138  * for the duration of the wait (0 = infinite).
139  */
140 void 
141 wait_until_can_do_something(fd_set * readset, fd_set * writeset,
142                             unsigned int max_time_milliseconds)
143 {
144         struct timeval tv, *tvp;
145         int ret;
146
147         /* When select fails we restart from here. */
148 retry_select:
149
150         /* Initialize select() masks. */
151         FD_ZERO(readset);
152
153         /*
154          * Read packets from the client unless we have too much buffered
155          * stdin or channel data.
156          */
157         if (buffer_len(&stdin_buffer) < 4096 &&
158             channel_not_very_much_buffered_data())
159                 FD_SET(connection_in, readset);
160
161         /*
162          * If there is not too much data already buffered going to the
163          * client, try to get some more data from the program.
164          */
165         if (packet_not_very_much_data_to_write()) {
166                 if (!fdout_eof)
167                         FD_SET(fdout, readset);
168                 if (!fderr_eof)
169                         FD_SET(fderr, readset);
170         }
171         FD_ZERO(writeset);
172
173         /* Set masks for channel descriptors. */
174         channel_prepare_select(readset, writeset);
175
176         /*
177          * If we have buffered packet data going to the client, mark that
178          * descriptor.
179          */
180         if (packet_have_data_to_write())
181                 FD_SET(connection_out, writeset);
182
183         /* If we have buffered data, try to write some of that data to the
184            program. */
185         if (fdin != -1 && buffer_len(&stdin_buffer) > 0)
186                 FD_SET(fdin, writeset);
187
188         /* Update the maximum descriptor number if appropriate. */
189         if (channel_max_fd() > max_fd)
190                 max_fd = channel_max_fd();
191
192         /*
193          * If child has terminated and there is enough buffer space to read
194          * from it, then read as much as is available and exit.
195          */
196         if (child_terminated && packet_not_very_much_data_to_write())
197                 if (max_time_milliseconds == 0)
198                         max_time_milliseconds = 100;
199
200         if (max_time_milliseconds == 0)
201                 tvp = NULL;
202         else {
203                 tv.tv_sec = max_time_milliseconds / 1000;
204                 tv.tv_usec = 1000 * (max_time_milliseconds % 1000);
205                 tvp = &tv;
206         }
207
208         /* Wait for something to happen, or the timeout to expire. */
209         ret = select(max_fd + 1, readset, writeset, NULL, tvp);
210
211         if (ret < 0) {
212                 if (errno != EINTR)
213                         error("select: %.100s", strerror(errno));
214                 else
215                         goto retry_select;
216         }
217         
218         if (child_terminated)
219                 child_has_selected = 1;
220 }
221
222 /*
223  * Processes input from the client and the program.  Input data is stored
224  * in buffers and processed later.
225  */
226 void 
227 process_input(fd_set * readset)
228 {
229         int len;
230         char buf[16384];
231
232         /* Read and buffer any input data from the client. */
233         if (FD_ISSET(connection_in, readset)) {
234                 len = read(connection_in, buf, sizeof(buf));
235                 if (len == 0) {
236                         verbose("Connection closed by remote host.");
237                         fatal_cleanup();
238                 }
239                 /*
240                  * There is a kernel bug on Solaris that causes select to
241                  * sometimes wake up even though there is no data available.
242                  */
243                 if (len < 0 && errno == EAGAIN)
244                         len = 0;
245
246                 if (len < 0) {
247                         verbose("Read error from remote host: %.100s", strerror(errno));
248                         fatal_cleanup();
249                 }
250                 /* Buffer any received data. */
251                 packet_process_incoming(buf, len);
252         }
253         /* Read and buffer any available stdout data from the program. */
254         if (!fdout_eof && FD_ISSET(fdout, readset)) {
255                 len = read(fdout, buf, sizeof(buf));
256                 if (len <= 0)
257                         fdout_eof = 1;
258                 else {
259                         buffer_append(&stdout_buffer, buf, len);
260                         fdout_bytes += len;
261                 }
262         }
263         /* Read and buffer any available stderr data from the program. */
264         if (!fderr_eof && FD_ISSET(fderr, readset)) {
265                 len = read(fderr, buf, sizeof(buf));
266                 if (len <= 0)
267                         fderr_eof = 1;
268                 else
269                         buffer_append(&stderr_buffer, buf, len);
270         }
271 }
272
273 /*
274  * Sends data from internal buffers to client program stdin.
275  */
276 void 
277 process_output(fd_set * writeset)
278 {
279         int len;
280
281         /* Write buffered data to program stdin. */
282         if (fdin != -1 && FD_ISSET(fdin, writeset)) {
283                 len = write(fdin, buffer_ptr(&stdin_buffer),
284                     buffer_len(&stdin_buffer));
285                 if (len <= 0) {
286 #ifdef USE_PIPES
287                         close(fdin);
288 #else
289                         if (fdin != fdout)
290                                 close(fdin);
291                         else
292                                 shutdown(fdin, SHUT_WR); /* We will no longer send. */
293 #endif
294                         fdin = -1;
295                 } else {
296                         /* Successful write.  Consume the data from the buffer. */
297                         buffer_consume(&stdin_buffer, len);
298                         /* Update the count of bytes written to the program. */
299                         stdin_bytes += len;
300                 }
301         }
302         /* Send any buffered packet data to the client. */
303         if (FD_ISSET(connection_out, writeset))
304                 packet_write_poll();
305 }
306
307 /*
308  * Wait until all buffered output has been sent to the client.
309  * This is used when the program terminates.
310  */
311 void 
312 drain_output()
313 {
314         /* Send any buffered stdout data to the client. */
315         if (buffer_len(&stdout_buffer) > 0) {
316                 packet_start(SSH_SMSG_STDOUT_DATA);
317                 packet_put_string(buffer_ptr(&stdout_buffer),
318                                   buffer_len(&stdout_buffer));
319                 packet_send();
320                 /* Update the count of sent bytes. */
321                 stdout_bytes += buffer_len(&stdout_buffer);
322         }
323         /* Send any buffered stderr data to the client. */
324         if (buffer_len(&stderr_buffer) > 0) {
325                 packet_start(SSH_SMSG_STDERR_DATA);
326                 packet_put_string(buffer_ptr(&stderr_buffer),
327                                   buffer_len(&stderr_buffer));
328                 packet_send();
329                 /* Update the count of sent bytes. */
330                 stderr_bytes += buffer_len(&stderr_buffer);
331         }
332         /* Wait until all buffered data has been written to the client. */
333         packet_write_wait();
334 }
335
336 void 
337 process_buffered_input_packets()
338 {
339         dispatch_run(DISPATCH_NONBLOCK, NULL);
340 }
341
342 /*
343  * Performs the interactive session.  This handles data transmission between
344  * the client and the program.  Note that the notion of stdin, stdout, and
345  * stderr in this function is sort of reversed: this function writes to
346  * stdin (of the child program), and reads from stdout and stderr (of the
347  * child program).
348  */
349 void 
350 server_loop(int pid, int fdin_arg, int fdout_arg, int fderr_arg)
351 {
352         int wait_status, wait_pid;      /* Status and pid returned by wait(). */
353         int waiting_termination = 0;    /* Have displayed waiting close message. */
354         unsigned int max_time_milliseconds;
355         unsigned int previous_stdout_buffer_bytes;
356         unsigned int stdout_buffer_bytes;
357         int type;
358
359         debug("Entering interactive session.");
360
361         /* Initialize the SIGCHLD kludge. */
362         child_pid = pid;
363         child_terminated = 0;
364         child_has_selected = 0;
365         signal(SIGCHLD, sigchld_handler);
366
367         /* Initialize our global variables. */
368         fdin = fdin_arg;
369         fdout = fdout_arg;
370         fderr = fderr_arg;
371         connection_in = packet_get_connection_in();
372         connection_out = packet_get_connection_out();
373
374         previous_stdout_buffer_bytes = 0;
375
376         /* Set approximate I/O buffer size. */
377         if (packet_is_interactive())
378                 buffer_high = 4096;
379         else
380                 buffer_high = 64 * 1024;
381
382         /* Initialize max_fd to the maximum of the known file descriptors. */
383         max_fd = fdin;
384         if (fdout > max_fd)
385                 max_fd = fdout;
386         if (fderr != -1 && fderr > max_fd)
387                 max_fd = fderr;
388         if (connection_in > max_fd)
389                 max_fd = connection_in;
390         if (connection_out > max_fd)
391                 max_fd = connection_out;
392
393         /* Initialize Initialize buffers. */
394         buffer_init(&stdin_buffer);
395         buffer_init(&stdout_buffer);
396         buffer_init(&stderr_buffer);
397
398         /*
399          * If we have no separate fderr (which is the case when we have a pty
400          * - there we cannot make difference between data sent to stdout and
401          * stderr), indicate that we have seen an EOF from stderr.  This way
402          * we don\'t need to check the descriptor everywhere.
403          */
404         if (fderr == -1)
405                 fderr_eof = 1;
406
407         server_init_dispatch();
408
409         /* Main loop of the server for the interactive session mode. */
410         for (;;) {
411                 fd_set readset, writeset;
412
413                 /* Process buffered packets from the client. */
414                 process_buffered_input_packets();
415
416                 /*
417                  * If we have received eof, and there is no more pending
418                  * input data, cause a real eof by closing fdin.
419                  */
420                 if (stdin_eof && fdin != -1 && buffer_len(&stdin_buffer) == 0) {
421 #ifdef USE_PIPES
422                         close(fdin);
423 #else
424                         if (fdin != fdout)
425                                 close(fdin);
426                         else
427                                 shutdown(fdin, SHUT_WR); /* We will no longer send. */
428 #endif
429                         fdin = -1;
430                 }
431                 /* Make packets from buffered stderr data to send to the client. */
432                 make_packets_from_stderr_data();
433
434                 /*
435                  * Make packets from buffered stdout data to send to the
436                  * client. If there is very little to send, this arranges to
437                  * not send them now, but to wait a short while to see if we
438                  * are getting more data. This is necessary, as some systems
439                  * wake up readers from a pty after each separate character.
440                  */
441                 max_time_milliseconds = 0;
442                 stdout_buffer_bytes = buffer_len(&stdout_buffer);
443                 if (stdout_buffer_bytes != 0 && stdout_buffer_bytes < 256 &&
444                     stdout_buffer_bytes != previous_stdout_buffer_bytes) {
445                         /* try again after a while */
446                         max_time_milliseconds = 10;
447                 } else {
448                         /* Send it now. */
449                         make_packets_from_stdout_data();
450                 }
451                 previous_stdout_buffer_bytes = buffer_len(&stdout_buffer);
452
453                 /* Send channel data to the client. */
454                 if (packet_not_very_much_data_to_write())
455                         channel_output_poll();
456
457                 /*
458                  * Bail out of the loop if the program has closed its output
459                  * descriptors, and we have no more data to send to the
460                  * client, and there is no pending buffered data.
461                  */
462                 if (((fdout_eof && fderr_eof) || 
463                     (child_terminated && child_has_selected)) && 
464                     !packet_have_data_to_write() &&
465                     (buffer_len(&stdout_buffer) == 0) && 
466                          (buffer_len(&stderr_buffer) == 0)) {
467                         if (!channel_still_open())
468                                 break;
469                         if (!waiting_termination) {
470                                 const char *s = "Waiting for forwarded connections to terminate...\r\n";
471                                 char *cp;
472                                 waiting_termination = 1;
473                                 buffer_append(&stderr_buffer, s, strlen(s));
474
475                                 /* Display list of open channels. */
476                                 cp = channel_open_message();
477                                 buffer_append(&stderr_buffer, cp, strlen(cp));
478                                 xfree(cp);
479                         }
480                 }
481                 /* Sleep in select() until we can do something. */
482                 wait_until_can_do_something(&readset, &writeset,
483                                             max_time_milliseconds);
484
485                 /* Process any channel events. */
486                 channel_after_select(&readset, &writeset);
487
488                 /* Process input from the client and from program stdout/stderr. */
489                 process_input(&readset);
490
491                 /* Process output to the client and to program stdin. */
492                 process_output(&writeset);
493         }
494
495         /* Cleanup and termination code. */
496
497         /* Wait until all output has been sent to the client. */
498         drain_output();
499
500         debug("End of interactive session; stdin %ld, stdout (read %ld, sent %ld), stderr %ld bytes.",
501               stdin_bytes, fdout_bytes, stdout_bytes, stderr_bytes);
502
503         /* Free and clear the buffers. */
504         buffer_free(&stdin_buffer);
505         buffer_free(&stdout_buffer);
506         buffer_free(&stderr_buffer);
507
508         /* Close the file descriptors. */
509         if (fdout != -1)
510                 close(fdout);
511         fdout = -1;
512         fdout_eof = 1;
513         if (fderr != -1)
514                 close(fderr);
515         fderr = -1;
516         fderr_eof = 1;
517         if (fdin != -1)
518                 close(fdin);
519         fdin = -1;
520
521         /* Stop listening for channels; this removes unix domain sockets. */
522         channel_stop_listening();
523
524         /* Wait for the child to exit.  Get its exit status. */
525         wait_pid = wait(&wait_status);
526         if (wait_pid < 0) {
527                 /*
528                  * It is possible that the wait was handled by SIGCHLD
529                  * handler.  This may result in either: this call
530                  * returning with EINTR, or: this call returning ECHILD.
531                  */
532                 if (child_terminated)
533                         wait_status = child_wait_status;
534                 else
535                         packet_disconnect("wait: %.100s", strerror(errno));
536         } else {
537                 /* Check if it matches the process we forked. */
538                 if (wait_pid != pid)
539                         error("Strange, wait returned pid %d, expected %d",
540                                wait_pid, pid);
541         }
542
543         /* We no longer want our SIGCHLD handler to be called. */
544         signal(SIGCHLD, SIG_DFL);
545
546         /* Check if it exited normally. */
547         if (WIFEXITED(wait_status)) {
548                 /* Yes, normal exit.  Get exit status and send it to the client. */
549                 debug("Command exited with status %d.", WEXITSTATUS(wait_status));
550                 packet_start(SSH_SMSG_EXITSTATUS);
551                 packet_put_int(WEXITSTATUS(wait_status));
552                 packet_send();
553                 packet_write_wait();
554
555                 /*
556                  * Wait for exit confirmation.  Note that there might be
557                  * other packets coming before it; however, the program has
558                  * already died so we just ignore them.  The client is
559                  * supposed to respond with the confirmation when it receives
560                  * the exit status.
561                  */
562                 do {
563                         int plen;
564                         type = packet_read(&plen);
565                 }
566                 while (type != SSH_CMSG_EXIT_CONFIRMATION);
567
568                 debug("Received exit confirmation.");
569                 return;
570         }
571         /* Check if the program terminated due to a signal. */
572         if (WIFSIGNALED(wait_status))
573                 packet_disconnect("Command terminated on signal %d.",
574                                   WTERMSIG(wait_status));
575
576         /* Some weird exit cause.  Just exit. */
577         packet_disconnect("wait returned status %04x.", wait_status);
578         /* NOTREACHED */
579 }
580
581 void
582 server_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
598 void
599 server_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
611 void
612 server_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
625 void 
626 server_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 }
640 void 
641 server_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 }
648 void 
649 server_init_dispatch()
650 {
651         if (compat13)
652                 server_init_dispatch_13();
653         else
654                 server_init_dispatch_15();
655 }
This page took 0.089765 seconds and 5 git commands to generate.