]> andersk Git - openssh.git/blob - serverloop.c
- Merged OpenBSD CVS changes
[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 and there is enough buffer space to read from
273      it, then read as much as is available and exit. */
274   if (child_terminated && packet_not_very_much_data_to_write())
275     if (max_time_milliseconds == 0)
276       max_time_milliseconds = 100;
277   
278   if (max_time_milliseconds == 0)
279     tvp = NULL;
280   else
281     {
282       tv.tv_sec = max_time_milliseconds / 1000;
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
299 /* Processes input from the client and the program.  Input data is stored
300    in buffers and processed later. */
301
302 void process_input(fd_set *readset)
303 {
304   int len;
305   char buf[16384];
306
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         }
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 }
349
350 /* Sends data from internal buffers to client program stdin. */
351
352 void process_output(fd_set *writeset)
353 {
354   int len;
355
356   /* Write buffered data to program stdin. */
357   if (fdin != -1 && FD_ISSET(fdin, writeset))
358     {
359       len = write(fdin, buffer_ptr(&stdin_buffer),
360                   buffer_len(&stdin_buffer));
361       if (len <= 0)
362         {
363 #ifdef USE_PIPES
364           close(fdin); 
365 #else
366           if (fdout == -1)
367             close(fdin);
368           else
369             shutdown(fdin, SHUT_WR); /* We will no longer send. */
370 #endif
371           fdin = -1;
372         }
373       else
374         {
375           /* Successful write.  Consume the data from the buffer. */
376           buffer_consume(&stdin_buffer, len);
377           /* Update the count of bytes written to the program. */
378           stdin_bytes += len;
379         }
380     }
381   
382   /* Send any buffered packet data to the client. */
383   if (FD_ISSET(connection_out, writeset))
384     packet_write_poll();
385 }
386
387 /* Wait until all buffered output has been sent to the client.
388    This is used when the program terminates. */
389
390 void drain_output()
391 {
392   /* Send any buffered stdout data to the client. */
393   if (buffer_len(&stdout_buffer) > 0)
394     {
395       packet_start(SSH_SMSG_STDOUT_DATA);
396       packet_put_string(buffer_ptr(&stdout_buffer), 
397                         buffer_len(&stdout_buffer));
398       packet_send();
399       /* Update the count of sent bytes. */
400       stdout_bytes += buffer_len(&stdout_buffer);
401     }
402   
403   /* Send any buffered stderr data to the client. */
404   if (buffer_len(&stderr_buffer) > 0)
405     {
406       packet_start(SSH_SMSG_STDERR_DATA);
407       packet_put_string(buffer_ptr(&stderr_buffer), 
408                         buffer_len(&stderr_buffer));
409       packet_send();
410       /* Update the count of sent bytes. */
411       stderr_bytes += buffer_len(&stderr_buffer);
412     }
413   
414   /* Wait until all buffered data has been written to the client. */
415   packet_write_wait();
416 }
417
418 /* Performs the interactive session.  This handles data transmission between
419    the client and the program.  Note that the notion of stdin, stdout, and
420    stderr in this function is sort of reversed: this function writes to
421    stdin (of the child program), and reads from stdout and stderr (of the
422    child program). */
423
424 void server_loop(int pid, int fdin_arg, int fdout_arg, int fderr_arg)
425 {
426   int wait_status, wait_pid;    /* Status and pid returned by wait(). */
427   int waiting_termination = 0;  /* Have displayed waiting close message. */
428   unsigned int max_time_milliseconds;
429   unsigned int previous_stdout_buffer_bytes;
430   unsigned int stdout_buffer_bytes;
431   int type;
432
433   debug("Entering interactive session.");
434
435   /* Initialize the SIGCHLD kludge. */
436   child_pid = pid;
437   child_terminated = 0;
438   signal(SIGCHLD, sigchld_handler);
439
440   /* Initialize our global variables. */
441   fdin = fdin_arg;
442   fdout = fdout_arg;
443   fderr = fderr_arg;
444   connection_in = packet_get_connection_in();
445   connection_out = packet_get_connection_out();
446   
447   previous_stdout_buffer_bytes = 0;
448
449   /* Set approximate I/O buffer size. */
450   if (packet_is_interactive())
451     buffer_high = 4096;
452   else
453     buffer_high = 64 * 1024;
454
455   /* Initialize max_fd to the maximum of the known file descriptors. */
456   max_fd = fdin;
457   if (fdout > max_fd)
458     max_fd = fdout;
459   if (fderr != -1 && fderr > max_fd)
460     max_fd = fderr;
461   if (connection_in > max_fd)
462     max_fd = connection_in;
463   if (connection_out > max_fd)
464     max_fd = connection_out;
465
466   /* Initialize Initialize buffers. */
467   buffer_init(&stdin_buffer);
468   buffer_init(&stdout_buffer);
469   buffer_init(&stderr_buffer);
470
471   /* If we have no separate fderr (which is the case when we have a pty - there
472      we cannot make difference between data sent to stdout and stderr),
473      indicate that we have seen an EOF from stderr.  This way we don\'t
474      need to check the descriptor everywhere. */
475   if (fderr == -1)
476     fderr_eof = 1;
477
478   /* Main loop of the server for the interactive session mode. */
479   for (;;)
480     {
481       fd_set readset, writeset;
482
483       /* Process buffered packets from the client. */
484       process_buffered_input_packets();
485
486       /* If we have received eof, and there is no more pending input data,
487          cause a real eof by closing fdin. */
488       if (stdin_eof && fdin != -1 && buffer_len(&stdin_buffer) == 0)
489         {
490 #ifdef USE_PIPES
491           close(fdin);
492 #else
493           if (fdout == -1)
494             close(fdin);
495           else
496             shutdown(fdin, SHUT_WR); /* We will no longer send. */
497 #endif
498           fdin = -1;
499         }
500
501       /* Make packets from buffered stderr data to send to the client. */
502       make_packets_from_stderr_data();
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
545       /* Sleep in select() until we can do something. */
546       wait_until_can_do_something(&readset, &writeset,
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
632       debug("Received exit confirmation.");
633       return;
634     }
635
636   /* Check if the program terminated due to a signal. */
637   if (WIFSIGNALED(wait_status))
638     packet_disconnect("Command terminated on signal %d.", 
639                       WTERMSIG(wait_status));
640
641   /* Some weird exit cause.  Just exit. */
642   packet_disconnect("wait returned status %04x.", wait_status);
643   /*NOTREACHED*/
644 }
645
This page took 0.162498 seconds and 5 git commands to generate.