source: trunk/third/openssh/serverloop.c @ 18759

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