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