]> andersk Git - openssh.git/blob - serverloop.c
bafbfb0ac7c4943b8053c16aa3ec49a5f3021f4c
[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  * Server main loop for handling the interactive session.
6  *
7  * As far as I am concerned, the code I have written for this software
8  * can be used freely for any purpose.  Any derived versions of this
9  * software must be clearly marked as such, and if the derived work is
10  * incompatible with the protocol description in the RFC file, it must be
11  * called by a name other than "ssh" or "Secure Shell".
12  *
13  * SSH2 support by Markus Friedl.
14  * Copyright (c) 2000 Markus Friedl.  All rights reserved.
15  *
16  * Redistribution and use in source and binary forms, with or without
17  * modification, are permitted provided that the following conditions
18  * are met:
19  * 1. Redistributions of source code must retain the above copyright
20  *    notice, this list of conditions and the following disclaimer.
21  * 2. Redistributions in binary form must reproduce the above copyright
22  *    notice, this list of conditions and the following disclaimer in the
23  *    documentation and/or other materials provided with the distribution.
24  *
25  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
26  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
27  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
28  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
29  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
30  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
31  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
32  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
33  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
34  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35  */
36
37 #include "includes.h"
38 RCSID("$OpenBSD: serverloop.c,v 1.68 2001/06/04 23:07:20 markus Exp $");
39
40 #include "xmalloc.h"
41 #include "packet.h"
42 #include "buffer.h"
43 #include "log.h"
44 #include "servconf.h"
45 #include "sshpty.h"
46 #include "channels.h"
47 #include "compat.h"
48 #include "ssh1.h"
49 #include "ssh2.h"
50 #include "auth.h"
51 #include "session.h"
52 #include "dispatch.h"
53 #include "auth-options.h"
54 #include "serverloop.h"
55 #include "misc.h"
56 #include "kex.h"
57
58 extern ServerOptions options;
59
60 /* XXX */
61 extern Kex *xxx_kex;
62
63 static Buffer stdin_buffer;     /* Buffer for stdin data. */
64 static Buffer stdout_buffer;    /* Buffer for stdout data. */
65 static Buffer stderr_buffer;    /* Buffer for stderr data. */
66 static int fdin;                /* Descriptor for stdin (for writing) */
67 static int fdout;               /* Descriptor for stdout (for reading);
68                                    May be same number as fdin. */
69 static int fderr;               /* Descriptor for stderr.  May be -1. */
70 static long stdin_bytes = 0;    /* Number of bytes written to stdin. */
71 static long stdout_bytes = 0;   /* Number of stdout bytes sent to client. */
72 static long stderr_bytes = 0;   /* Number of stderr bytes sent to client. */
73 static long fdout_bytes = 0;    /* Number of stdout bytes read from program. */
74 static int stdin_eof = 0;       /* EOF message received from client. */
75 static int fdout_eof = 0;       /* EOF encountered reading from fdout. */
76 static int fderr_eof = 0;       /* EOF encountered readung from fderr. */
77 static int fdin_is_tty = 0;     /* fdin points to a tty. */
78 static int connection_in;       /* Connection to client (input). */
79 static int connection_out;      /* Connection to client (output). */
80 static int connection_closed = 0;       /* Connection to client closed. */
81 static u_int buffer_high;       /* "Soft" max buffer size. */
82
83 /*
84  * This SIGCHLD kludge is used to detect when the child exits.  The server
85  * will exit after that, as soon as forwarded connections have terminated.
86  */
87 static volatile int child_terminated;   /* The child has terminated. */
88
89 void    server_init_dispatch(void);
90
91 int client_alive_timeouts = 0;
92
93 void
94 sigchld_handler(int sig)
95 {
96         int save_errno = errno;
97         debug("Received SIGCHLD.");
98         child_terminated = 1;
99         mysignal(SIGCHLD, sigchld_handler);
100         errno = save_errno;
101 }
102
103 /*
104  * Make packets from buffered stderr data, and buffer it for sending
105  * to the client.
106  */
107 void
108 make_packets_from_stderr_data(void)
109 {
110         int len;
111
112         /* Send buffered stderr data to the client. */
113         while (buffer_len(&stderr_buffer) > 0 &&
114             packet_not_very_much_data_to_write()) {
115                 len = buffer_len(&stderr_buffer);
116                 if (packet_is_interactive()) {
117                         if (len > 512)
118                                 len = 512;
119                 } else {
120                         /* Keep the packets at reasonable size. */
121                         if (len > packet_get_maxsize())
122                                 len = packet_get_maxsize();
123                 }
124                 packet_start(SSH_SMSG_STDERR_DATA);
125                 packet_put_string(buffer_ptr(&stderr_buffer), len);
126                 packet_send();
127                 buffer_consume(&stderr_buffer, len);
128                 stderr_bytes += len;
129         }
130 }
131
132 /*
133  * Make packets from buffered stdout data, and buffer it for sending to the
134  * client.
135  */
136 void
137 make_packets_from_stdout_data(void)
138 {
139         int len;
140
141         /* Send buffered stdout data to the client. */
142         while (buffer_len(&stdout_buffer) > 0 &&
143             packet_not_very_much_data_to_write()) {
144                 len = buffer_len(&stdout_buffer);
145                 if (packet_is_interactive()) {
146                         if (len > 512)
147                                 len = 512;
148                 } else {
149                         /* Keep the packets at reasonable size. */
150                         if (len > packet_get_maxsize())
151                                 len = packet_get_maxsize();
152                 }
153                 packet_start(SSH_SMSG_STDOUT_DATA);
154                 packet_put_string(buffer_ptr(&stdout_buffer), len);
155                 packet_send();
156                 buffer_consume(&stdout_buffer, len);
157                 stdout_bytes += len;
158         }
159 }
160
161 /*
162  * Sleep in select() until we can do something.  This will initialize the
163  * select masks.  Upon return, the masks will indicate which descriptors
164  * have data or can accept data.  Optionally, a maximum time can be specified
165  * for the duration of the wait (0 = infinite).
166  */
167 void
168 wait_until_can_do_something(fd_set **readsetp, fd_set **writesetp, int *maxfdp,
169     u_int max_time_milliseconds)
170 {
171         struct timeval tv, *tvp;
172         int ret;
173         int client_alive_scheduled = 0;
174
175         /*
176          * if using client_alive, set the max timeout accordingly, 
177          * and indicate that this particular timeout was for client
178          * alive by setting the client_alive_scheduled flag.
179          *
180          * this could be randomized somewhat to make traffic
181          * analysis more difficult, but we're not doing it yet.  
182          */
183         if (max_time_milliseconds == 0 && options.client_alive_interval) {
184                 client_alive_scheduled = 1;
185                 max_time_milliseconds = options.client_alive_interval * 1000;
186         } else 
187                 client_alive_scheduled = 0;
188
189         /* When select fails we restart from here. */
190 retry_select:
191
192         /* Allocate and update select() masks for channel descriptors. */
193         channel_prepare_select(readsetp, writesetp, maxfdp, 0);
194
195         if (compat20) {
196                 /* wrong: bad condition XXX */
197                 if (channel_not_very_much_buffered_data())
198                         FD_SET(connection_in, *readsetp);
199         } else {
200                 /*
201                  * Read packets from the client unless we have too much
202                  * buffered stdin or channel data.
203                  */
204                 if (buffer_len(&stdin_buffer) < buffer_high &&
205                     channel_not_very_much_buffered_data())
206                         FD_SET(connection_in, *readsetp);
207                 /*
208                  * If there is not too much data already buffered going to
209                  * the client, try to get some more data from the program.
210                  */
211                 if (packet_not_very_much_data_to_write()) {
212                         if (!fdout_eof)
213                                 FD_SET(fdout, *readsetp);
214                         if (!fderr_eof)
215                                 FD_SET(fderr, *readsetp);
216                 }
217                 /*
218                  * If we have buffered data, try to write some of that data
219                  * to the program.
220                  */
221                 if (fdin != -1 && buffer_len(&stdin_buffer) > 0)
222                         FD_SET(fdin, *writesetp);
223         }
224
225         /*
226          * If we have buffered packet data going to the client, mark that
227          * descriptor.
228          */
229         if (packet_have_data_to_write())
230                 FD_SET(connection_out, *writesetp);
231
232         /*
233          * If child has terminated and there is enough buffer space to read
234          * from it, then read as much as is available and exit.
235          */
236         if (child_terminated && packet_not_very_much_data_to_write())
237                 if (max_time_milliseconds == 0 || client_alive_scheduled)
238                         max_time_milliseconds = 100;
239
240         if (max_time_milliseconds == 0)
241                 tvp = NULL;
242         else {
243                 tv.tv_sec = max_time_milliseconds / 1000;
244                 tv.tv_usec = 1000 * (max_time_milliseconds % 1000);
245                 tvp = &tv;
246         }
247         if (tvp!=NULL)
248                 debug3("tvp!=NULL kid %d mili %d", child_terminated, max_time_milliseconds);
249
250         /* Wait for something to happen, or the timeout to expire. */
251         ret = select((*maxfdp)+1, *readsetp, *writesetp, NULL, tvp);
252
253         if (ret == -1) {
254                 if (errno != EINTR)
255                         error("select: %.100s", strerror(errno));
256                 else
257                         goto retry_select;
258         }
259         if (ret == 0 && client_alive_scheduled) {
260                 /* timeout, check to see how many we have had */
261                 client_alive_timeouts++;
262
263                 if (client_alive_timeouts > options.client_alive_count_max ) {
264                         packet_disconnect(
265                                 "Timeout, your session not responding.");
266                 } else {
267                         /*
268                          * send a bogus channel request with "wantreply" 
269                          * we should get back a failure
270                          */
271                         int id;
272                         
273                         id = channel_find_open();
274                         if (id != -1) {
275                                 channel_request_start(id,
276                                   "keepalive@openssh.com", 1);
277                                 packet_send();
278                         } else 
279                                 packet_disconnect(
280                                         "No open channels after timeout!");
281                 }
282         } 
283 }
284
285 /*
286  * Processes input from the client and the program.  Input data is stored
287  * in buffers and processed later.
288  */
289 void
290 process_input(fd_set * readset)
291 {
292         int len;
293         char buf[16384];
294
295         /* Read and buffer any input data from the client. */
296         if (FD_ISSET(connection_in, readset)) {
297                 len = read(connection_in, buf, sizeof(buf));
298                 if (len == 0) {
299                         verbose("Connection closed by remote host.");
300                         connection_closed = 1;
301                         if (compat20)
302                                 return;
303                         fatal_cleanup();
304                 } else if (len < 0) {
305                         if (errno != EINTR && errno != EAGAIN) {
306                                 verbose("Read error from remote host: %.100s", strerror(errno));
307                                 fatal_cleanup();
308                         }
309                 } else {
310                         /* Buffer any received data. */
311                         packet_process_incoming(buf, len);
312                 }
313         }
314         if (compat20)
315                 return;
316
317         /* Read and buffer any available stdout data from the program. */
318         if (!fdout_eof && FD_ISSET(fdout, readset)) {
319                 len = read(fdout, buf, sizeof(buf));
320                 if (len < 0 && (errno == EINTR || errno == EAGAIN)) {
321                         /* do nothing */
322                 } else if (len <= 0) {
323                         fdout_eof = 1;
324                 } else {
325                         buffer_append(&stdout_buffer, buf, len);
326                         fdout_bytes += len;
327                 }
328         }
329         /* Read and buffer any available stderr data from the program. */
330         if (!fderr_eof && FD_ISSET(fderr, readset)) {
331                 len = read(fderr, buf, sizeof(buf));
332                 if (len < 0 && (errno == EINTR || errno == EAGAIN)) {
333                         /* do nothing */
334                 } else if (len <= 0) {
335                         fderr_eof = 1;
336                 } else {
337                         buffer_append(&stderr_buffer, buf, len);
338                 }
339         }
340 }
341
342 /*
343  * Sends data from internal buffers to client program stdin.
344  */
345 void
346 process_output(fd_set * writeset)
347 {
348         struct termios tio;
349         int len;
350
351         /* Write buffered data to program stdin. */
352         if (!compat20 && fdin != -1 && FD_ISSET(fdin, writeset)) {
353                 len = write(fdin, buffer_ptr(&stdin_buffer),
354                     buffer_len(&stdin_buffer));
355                 if (len < 0 && (errno == EINTR || errno == EAGAIN)) {
356                         /* do nothing */
357                 } else if (len <= 0) {
358 #ifdef USE_PIPES
359                         close(fdin);
360 #else
361                         if (fdin != fdout)
362                                 close(fdin);
363                         else
364                                 shutdown(fdin, SHUT_WR); /* We will no longer send. */
365 #endif
366                         fdin = -1;
367                 } else {
368                         /* Successful write. */
369                         if (fdin_is_tty && tcgetattr(fdin, &tio) == 0 &&
370                             !(tio.c_lflag & ECHO) && (tio.c_lflag & ICANON)) {
371                                 /*
372                                  * Simulate echo to reduce the impact of
373                                  * traffic analysis
374                                  */
375                                 packet_send_ignore(len);
376                                 packet_send();
377                         }
378                         /* Consume the data from the buffer. */
379                         buffer_consume(&stdin_buffer, len);
380                         /* Update the count of bytes written to the program. */
381                         stdin_bytes += len;
382                 }
383         }
384         /* Send any buffered packet data to the client. */
385         if (FD_ISSET(connection_out, writeset))
386                 packet_write_poll();
387 }
388
389 /*
390  * Wait until all buffered output has been sent to the client.
391  * This is used when the program terminates.
392  */
393 void
394 drain_output(void)
395 {
396         /* Send any buffered stdout data to the client. */
397         if (buffer_len(&stdout_buffer) > 0) {
398                 packet_start(SSH_SMSG_STDOUT_DATA);
399                 packet_put_string(buffer_ptr(&stdout_buffer),
400                                   buffer_len(&stdout_buffer));
401                 packet_send();
402                 /* Update the count of sent bytes. */
403                 stdout_bytes += buffer_len(&stdout_buffer);
404         }
405         /* Send any buffered stderr data to the client. */
406         if (buffer_len(&stderr_buffer) > 0) {
407                 packet_start(SSH_SMSG_STDERR_DATA);
408                 packet_put_string(buffer_ptr(&stderr_buffer),
409                                   buffer_len(&stderr_buffer));
410                 packet_send();
411                 /* Update the count of sent bytes. */
412                 stderr_bytes += buffer_len(&stderr_buffer);
413         }
414         /* Wait until all buffered data has been written to the client. */
415         packet_write_wait();
416 }
417
418 void
419 process_buffered_input_packets(void)
420 {
421         dispatch_run(DISPATCH_NONBLOCK, NULL, compat20 ? xxx_kex : NULL);
422 }
423
424 /*
425  * Performs the interactive session.  This handles data transmission between
426  * the client and the program.  Note that the notion of stdin, stdout, and
427  * stderr in this function is sort of reversed: this function writes to
428  * stdin (of the child program), and reads from stdout and stderr (of the
429  * child program).
430  */
431 void
432 server_loop(pid_t pid, int fdin_arg, int fdout_arg, int fderr_arg)
433 {
434         fd_set *readset = NULL, *writeset = NULL;
435         int max_fd;
436         int wait_status;        /* Status returned by wait(). */
437         pid_t wait_pid;         /* pid returned by wait(). */
438         int waiting_termination = 0;    /* Have displayed waiting close message. */
439         u_int max_time_milliseconds;
440         u_int previous_stdout_buffer_bytes;
441         u_int stdout_buffer_bytes;
442         int type;
443
444         debug("Entering interactive session.");
445
446         /* Initialize the SIGCHLD kludge. */
447         child_terminated = 0;
448         signal(SIGCHLD, sigchld_handler);
449
450         /* Initialize our global variables. */
451         fdin = fdin_arg;
452         fdout = fdout_arg;
453         fderr = fderr_arg;
454
455         /* nonblocking IO */
456         set_nonblock(fdin);
457         set_nonblock(fdout);
458         /* we don't have stderr for interactive terminal sessions, see below */
459         if (fderr != -1)
460                 set_nonblock(fderr);
461
462         if (!(datafellows & SSH_BUG_IGNOREMSG) && isatty(fdin))
463                 fdin_is_tty = 1;
464
465         connection_in = packet_get_connection_in();
466         connection_out = packet_get_connection_out();
467
468         previous_stdout_buffer_bytes = 0;
469
470         /* Set approximate I/O buffer size. */
471         if (packet_is_interactive())
472                 buffer_high = 4096;
473         else
474                 buffer_high = 64 * 1024;
475
476         /* Initialize max_fd to the maximum of the known file descriptors. */
477         max_fd = MAX(fdin, fdout);
478         if (fderr != -1)
479                 max_fd = MAX(max_fd, fderr);
480         max_fd = MAX(max_fd, connection_in);
481         max_fd = MAX(max_fd, connection_out);
482
483         /* Initialize Initialize buffers. */
484         buffer_init(&stdin_buffer);
485         buffer_init(&stdout_buffer);
486         buffer_init(&stderr_buffer);
487
488         /*
489          * If we have no separate fderr (which is the case when we have a pty
490          * - there we cannot make difference between data sent to stdout and
491          * stderr), indicate that we have seen an EOF from stderr.  This way
492          * we don\'t need to check the descriptor everywhere.
493          */
494         if (fderr == -1)
495                 fderr_eof = 1;
496
497         server_init_dispatch();
498
499         /* Main loop of the server for the interactive session mode. */
500         for (;;) {
501
502                 /* Process buffered packets from the client. */
503                 process_buffered_input_packets();
504
505                 /*
506                  * If we have received eof, and there is no more pending
507                  * input data, cause a real eof by closing fdin.
508                  */
509                 if (stdin_eof && fdin != -1 && buffer_len(&stdin_buffer) == 0) {
510 #ifdef USE_PIPES
511                         close(fdin);
512 #else
513                         if (fdin != fdout)
514                                 close(fdin);
515                         else
516                                 shutdown(fdin, SHUT_WR); /* We will no longer send. */
517 #endif
518                         fdin = -1;
519                 }
520                 /* Make packets from buffered stderr data to send to the client. */
521                 make_packets_from_stderr_data();
522
523                 /*
524                  * Make packets from buffered stdout data to send to the
525                  * client. If there is very little to send, this arranges to
526                  * not send them now, but to wait a short while to see if we
527                  * are getting more data. This is necessary, as some systems
528                  * wake up readers from a pty after each separate character.
529                  */
530                 max_time_milliseconds = 0;
531                 stdout_buffer_bytes = buffer_len(&stdout_buffer);
532                 if (stdout_buffer_bytes != 0 && stdout_buffer_bytes < 256 &&
533                     stdout_buffer_bytes != previous_stdout_buffer_bytes) {
534                         /* try again after a while */
535                         max_time_milliseconds = 10;
536                 } else {
537                         /* Send it now. */
538                         make_packets_from_stdout_data();
539                 }
540                 previous_stdout_buffer_bytes = buffer_len(&stdout_buffer);
541
542                 /* Send channel data to the client. */
543                 if (packet_not_very_much_data_to_write())
544                         channel_output_poll();
545
546                 /*
547                  * Bail out of the loop if the program has closed its output
548                  * descriptors, and we have no more data to send to the
549                  * client, and there is no pending buffered data.
550                  */
551                 if (fdout_eof && fderr_eof && !packet_have_data_to_write() &&
552                     buffer_len(&stdout_buffer) == 0 && buffer_len(&stderr_buffer) == 0) {
553                         if (!channel_still_open())
554                                 break;
555                         if (!waiting_termination) {
556                                 const char *s = "Waiting for forwarded connections to terminate...\r\n";
557                                 char *cp;
558                                 waiting_termination = 1;
559                                 buffer_append(&stderr_buffer, s, strlen(s));
560
561                                 /* Display list of open channels. */
562                                 cp = channel_open_message();
563                                 buffer_append(&stderr_buffer, cp, strlen(cp));
564                                 xfree(cp);
565                         }
566                 }
567                 /* Sleep in select() until we can do something. */
568                 wait_until_can_do_something(&readset, &writeset, &max_fd,
569                     max_time_milliseconds);
570
571                 /* Process any channel events. */
572                 channel_after_select(readset, writeset);
573
574                 /* Process input from the client and from program stdout/stderr. */
575                 process_input(readset);
576
577                 /* Process output to the client and to program stdin. */
578                 process_output(writeset);
579         }
580         if (readset)
581                 xfree(readset);
582         if (writeset)
583                 xfree(writeset);
584
585         /* Cleanup and termination code. */
586
587         /* Wait until all output has been sent to the client. */
588         drain_output();
589
590         debug("End of interactive session; stdin %ld, stdout (read %ld, sent %ld), stderr %ld bytes.",
591               stdin_bytes, fdout_bytes, stdout_bytes, stderr_bytes);
592
593         /* Free and clear the buffers. */
594         buffer_free(&stdin_buffer);
595         buffer_free(&stdout_buffer);
596         buffer_free(&stderr_buffer);
597
598         /* Close the file descriptors. */
599         if (fdout != -1)
600                 close(fdout);
601         fdout = -1;
602         fdout_eof = 1;
603         if (fderr != -1)
604                 close(fderr);
605         fderr = -1;
606         fderr_eof = 1;
607         if (fdin != -1)
608                 close(fdin);
609         fdin = -1;
610
611         /* Stop listening for channels; this removes unix domain sockets. */
612         channel_stop_listening();
613
614         /* We no longer want our SIGCHLD handler to be called. */
615         signal(SIGCHLD, SIG_DFL);
616
617         wait_pid = waitpid(-1, &wait_status, child_terminated ? WNOHANG : 0);
618         if (wait_pid == -1)
619                 packet_disconnect("wait: %.100s", strerror(errno));
620         else if (wait_pid != pid)
621                 error("Strange, wait returned pid %d, expected %d",
622                     wait_pid, pid);
623
624         /* Check if it exited normally. */
625         if (WIFEXITED(wait_status)) {
626                 /* Yes, normal exit.  Get exit status and send it to the client. */
627                 debug("Command exited with status %d.", WEXITSTATUS(wait_status));
628                 packet_start(SSH_SMSG_EXITSTATUS);
629                 packet_put_int(WEXITSTATUS(wait_status));
630                 packet_send();
631                 packet_write_wait();
632
633                 /*
634                  * Wait for exit confirmation.  Note that there might be
635                  * other packets coming before it; however, the program has
636                  * already died so we just ignore them.  The client is
637                  * supposed to respond with the confirmation when it receives
638                  * the exit status.
639                  */
640                 do {
641                         int plen;
642                         type = packet_read(&plen);
643                 }
644                 while (type != SSH_CMSG_EXIT_CONFIRMATION);
645
646                 debug("Received exit confirmation.");
647                 return;
648         }
649         /* Check if the program terminated due to a signal. */
650         if (WIFSIGNALED(wait_status))
651                 packet_disconnect("Command terminated on signal %d.",
652                                   WTERMSIG(wait_status));
653
654         /* Some weird exit cause.  Just exit. */
655         packet_disconnect("wait returned status %04x.", wait_status);
656         /* NOTREACHED */
657 }
658
659 void
660 server_loop2(void)
661 {
662         fd_set *readset = NULL, *writeset = NULL;
663         int rekeying = 0, max_fd, status;
664         pid_t pid;
665
666         debug("Entering interactive session for SSH2.");
667
668         mysignal(SIGCHLD, sigchld_handler);
669         child_terminated = 0;
670         connection_in = packet_get_connection_in();
671         connection_out = packet_get_connection_out();
672
673         max_fd = MAX(connection_in, connection_out);
674
675         server_init_dispatch();
676
677         for (;;) {
678                 process_buffered_input_packets();
679
680                 rekeying = (xxx_kex != NULL && !xxx_kex->done);
681
682                 if (!rekeying && packet_not_very_much_data_to_write())
683                         channel_output_poll();
684                 wait_until_can_do_something(&readset, &writeset, &max_fd,
685                     rekeying);
686                 if (child_terminated) {
687                         while ((pid = waitpid(-1, &status, WNOHANG)) > 0)
688                                 session_close_by_pid(pid, status);
689                         child_terminated = 0;
690                 }
691                 if (!rekeying)
692                         channel_after_select(readset, writeset);
693                 process_input(readset);
694                 if (connection_closed)
695                         break;
696                 process_output(writeset);
697         }
698         if (readset)
699                 xfree(readset);
700         if (writeset)
701                 xfree(writeset);
702
703         signal(SIGCHLD, SIG_DFL);
704         while ((pid = waitpid(-1, &status, WNOHANG)) > 0)
705                 session_close_by_pid(pid, status);
706         channel_stop_listening();
707 }
708
709 void
710 server_input_channel_failure(int type, int plen, void *ctxt)
711 {
712         debug("Got CHANNEL_FAILURE for keepalive");
713         /* 
714          * reset timeout, since we got a sane answer from the client.
715          * even if this was generated by something other than
716          * the bogus CHANNEL_REQUEST we send for keepalives.
717          */
718         client_alive_timeouts = 0; 
719 }
720
721
722 void
723 server_input_stdin_data(int type, int plen, void *ctxt)
724 {
725         char *data;
726         u_int data_len;
727
728         /* Stdin data from the client.  Append it to the buffer. */
729         /* Ignore any data if the client has closed stdin. */
730         if (fdin == -1)
731                 return;
732         data = packet_get_string(&data_len);
733         packet_integrity_check(plen, (4 + data_len), type);
734         buffer_append(&stdin_buffer, data, data_len);
735         memset(data, 0, data_len);
736         xfree(data);
737 }
738
739 void
740 server_input_eof(int type, int plen, void *ctxt)
741 {
742         /*
743          * Eof from the client.  The stdin descriptor to the
744          * program will be closed when all buffered data has
745          * drained.
746          */
747         debug("EOF received for stdin.");
748         packet_integrity_check(plen, 0, type);
749         stdin_eof = 1;
750 }
751
752 void
753 server_input_window_size(int type, int plen, void *ctxt)
754 {
755         int row = packet_get_int();
756         int col = packet_get_int();
757         int xpixel = packet_get_int();
758         int ypixel = packet_get_int();
759
760         debug("Window change received.");
761         packet_integrity_check(plen, 4 * 4, type);
762         if (fdin != -1)
763                 pty_change_window_size(fdin, row, col, xpixel, ypixel);
764 }
765
766 Channel *
767 server_request_direct_tcpip(char *ctype)
768 {
769         Channel *c;
770         int sock;
771         char *target, *originator;
772         int target_port, originator_port;
773
774         target = packet_get_string(NULL);
775         target_port = packet_get_int();
776         originator = packet_get_string(NULL);
777         originator_port = packet_get_int();
778         packet_done();
779
780         debug("server_request_direct_tcpip: originator %s port %d, target %s port %d",
781            originator, originator_port, target, target_port);
782
783         /* XXX check permission */
784         sock = channel_connect_to(target, target_port);
785         xfree(target);
786         xfree(originator);
787         if (sock < 0)
788                 return NULL;
789         c = channel_new(ctype, SSH_CHANNEL_CONNECTING,
790             sock, sock, -1, CHAN_TCP_WINDOW_DEFAULT,
791             CHAN_TCP_PACKET_DEFAULT, 0, xstrdup("direct-tcpip"), 1);
792         if (c == NULL) {
793                 error("server_request_direct_tcpip: channel_new failed");
794                 close(sock);
795         }
796         return c;
797 }
798
799 Channel *
800 server_request_session(char *ctype)
801 {
802         Channel *c;
803
804         debug("input_session_request");
805         packet_done();
806         /*
807          * A server session has no fd to read or write until a
808          * CHANNEL_REQUEST for a shell is made, so we set the type to
809          * SSH_CHANNEL_LARVAL.  Additionally, a callback for handling all
810          * CHANNEL_REQUEST messages is registered.
811          */
812         c = channel_new(ctype, SSH_CHANNEL_LARVAL,
813             -1, -1, -1, /*window size*/0, CHAN_SES_PACKET_DEFAULT,
814             0, xstrdup("server-session"), 1);
815         if (c == NULL) {
816                 error("server_request_session: channel_new failed");
817                 return NULL;
818         }
819         if (session_open(c->self) != 1) {
820                 debug("session open failed, free channel %d", c->self);
821                 channel_free(c);
822                 return NULL;
823         }
824         channel_register_callback(c->self, SSH2_MSG_CHANNEL_REQUEST,
825             session_input_channel_req, (void *)0);
826         channel_register_cleanup(c->self, session_close_by_channel);
827         return c;
828 }
829
830 void
831 server_input_channel_open(int type, int plen, void *ctxt)
832 {
833         Channel *c = NULL;
834         char *ctype;
835         u_int len;
836         int rchan;
837         int rmaxpack;
838         int rwindow;
839
840         ctype = packet_get_string(&len);
841         rchan = packet_get_int();
842         rwindow = packet_get_int();
843         rmaxpack = packet_get_int();
844
845         debug("server_input_channel_open: ctype %s rchan %d win %d max %d",
846             ctype, rchan, rwindow, rmaxpack);
847
848         if (strcmp(ctype, "session") == 0) {
849                 c = server_request_session(ctype);
850         } else if (strcmp(ctype, "direct-tcpip") == 0) {
851                 c = server_request_direct_tcpip(ctype);
852         }
853         if (c != NULL) {
854                 debug("server_input_channel_open: confirm %s", ctype);
855                 c->remote_id = rchan;
856                 c->remote_window = rwindow;
857                 c->remote_maxpacket = rmaxpack;
858                 if (c->type != SSH_CHANNEL_CONNECTING) {
859                         packet_start(SSH2_MSG_CHANNEL_OPEN_CONFIRMATION);
860                         packet_put_int(c->remote_id);
861                         packet_put_int(c->self);
862                         packet_put_int(c->local_window);
863                         packet_put_int(c->local_maxpacket);
864                         packet_send();
865                 }
866         } else {
867                 debug("server_input_channel_open: failure %s", ctype);
868                 packet_start(SSH2_MSG_CHANNEL_OPEN_FAILURE);
869                 packet_put_int(rchan);
870                 packet_put_int(SSH2_OPEN_ADMINISTRATIVELY_PROHIBITED);
871                 if (!(datafellows & SSH_BUG_OPENFAILURE)) {
872                         packet_put_cstring("open failed");
873                         packet_put_cstring("");
874                 }
875                 packet_send();
876         }
877         xfree(ctype);
878 }
879
880 void
881 server_input_global_request(int type, int plen, void *ctxt)
882 {
883         char *rtype;
884         int want_reply;
885         int success = 0;
886
887         rtype = packet_get_string(NULL);
888         want_reply = packet_get_char();
889         debug("server_input_global_request: rtype %s want_reply %d", rtype, want_reply);
890
891         /* -R style forwarding */
892         if (strcmp(rtype, "tcpip-forward") == 0) {
893                 struct passwd *pw;
894                 char *listen_address;
895                 u_short listen_port;
896
897                 pw = auth_get_user();
898                 if (pw == NULL)
899                         fatal("server_input_global_request: no user");
900                 listen_address = packet_get_string(NULL); /* XXX currently ignored */
901                 listen_port = (u_short)packet_get_int();
902                 debug("server_input_global_request: tcpip-forward listen %s port %d",
903                     listen_address, listen_port);
904
905                 /* check permissions */
906                 if (!options.allow_tcp_forwarding ||
907                     no_port_forwarding_flag ||
908                     (listen_port < IPPORT_RESERVED && pw->pw_uid != 0)) {
909                         success = 0;
910                         packet_send_debug("Server has disabled port forwarding.");
911                 } else {
912                         /* Start listening on the port */
913                         success = channel_request_forwarding(
914                             listen_address, listen_port,
915                             /*unspec host_to_connect*/ "<unspec host>",
916                             /*unspec port_to_connect*/ 0,
917                             options.gateway_ports, /*remote*/ 1);
918                 }
919                 xfree(listen_address);
920         }
921         if (want_reply) {
922                 packet_start(success ?
923                     SSH2_MSG_REQUEST_SUCCESS : SSH2_MSG_REQUEST_FAILURE);
924                 packet_send();
925                 packet_write_wait();
926         }
927         xfree(rtype);
928 }
929
930 void
931 server_init_dispatch_20(void)
932 {
933         debug("server_init_dispatch_20");
934         dispatch_init(&dispatch_protocol_error);
935         dispatch_set(SSH2_MSG_CHANNEL_CLOSE, &channel_input_oclose);
936         dispatch_set(SSH2_MSG_CHANNEL_DATA, &channel_input_data);
937         dispatch_set(SSH2_MSG_CHANNEL_EOF, &channel_input_ieof);
938         dispatch_set(SSH2_MSG_CHANNEL_EXTENDED_DATA, &channel_input_extended_data);
939         dispatch_set(SSH2_MSG_CHANNEL_OPEN, &server_input_channel_open);
940         dispatch_set(SSH2_MSG_CHANNEL_OPEN_CONFIRMATION, &channel_input_open_confirmation);
941         dispatch_set(SSH2_MSG_CHANNEL_OPEN_FAILURE, &channel_input_open_failure);
942         dispatch_set(SSH2_MSG_CHANNEL_REQUEST, &channel_input_channel_request);
943         dispatch_set(SSH2_MSG_CHANNEL_WINDOW_ADJUST, &channel_input_window_adjust);
944         dispatch_set(SSH2_MSG_GLOBAL_REQUEST, &server_input_global_request);
945         /* client_alive */
946         dispatch_set(SSH2_MSG_CHANNEL_FAILURE, &server_input_channel_failure);
947         /* rekeying */
948         dispatch_set(SSH2_MSG_KEXINIT, &kex_input_kexinit);
949 }
950 void
951 server_init_dispatch_13(void)
952 {
953         debug("server_init_dispatch_13");
954         dispatch_init(NULL);
955         dispatch_set(SSH_CMSG_EOF, &server_input_eof);
956         dispatch_set(SSH_CMSG_STDIN_DATA, &server_input_stdin_data);
957         dispatch_set(SSH_CMSG_WINDOW_SIZE, &server_input_window_size);
958         dispatch_set(SSH_MSG_CHANNEL_CLOSE, &channel_input_close);
959         dispatch_set(SSH_MSG_CHANNEL_CLOSE_CONFIRMATION, &channel_input_close_confirmation);
960         dispatch_set(SSH_MSG_CHANNEL_DATA, &channel_input_data);
961         dispatch_set(SSH_MSG_CHANNEL_OPEN_CONFIRMATION, &channel_input_open_confirmation);
962         dispatch_set(SSH_MSG_CHANNEL_OPEN_FAILURE, &channel_input_open_failure);
963         dispatch_set(SSH_MSG_PORT_OPEN, &channel_input_port_open);
964 }
965 void
966 server_init_dispatch_15(void)
967 {
968         server_init_dispatch_13();
969         debug("server_init_dispatch_15");
970         dispatch_set(SSH_MSG_CHANNEL_CLOSE, &channel_input_ieof);
971         dispatch_set(SSH_MSG_CHANNEL_CLOSE_CONFIRMATION, &channel_input_oclose);
972 }
973 void
974 server_init_dispatch(void)
975 {
976         if (compat20)
977                 server_init_dispatch_20();
978         else if (compat13)
979                 server_init_dispatch_13();
980         else
981                 server_init_dispatch_15();
982 }
983
This page took 0.477385 seconds and 3 git commands to generate.