LCOV - code coverage report
Current view: top level - openssh-6.6p1 - serverloop.c (source / functions) Hit Total Coverage
Test: lcov_coverage_final.info Lines: 415 580 71.6 %
Date: 2014-08-01 Functions: 25 31 80.6 %
Branches: 200 418 47.8 %

           Branch data     Line data    Source code
       1                 :            : /* $OpenBSD: serverloop.c,v 1.170 2014/02/02 03:44:31 djm Exp $ */
       2                 :            : /*
       3                 :            :  * Author: Tatu Ylonen <ylo@cs.hut.fi>
       4                 :            :  * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
       5                 :            :  *                    All rights reserved
       6                 :            :  * Server main loop for handling the interactive session.
       7                 :            :  *
       8                 :            :  * As far as I am concerned, the code I have written for this software
       9                 :            :  * can be used freely for any purpose.  Any derived versions of this
      10                 :            :  * software must be clearly marked as such, and if the derived work is
      11                 :            :  * incompatible with the protocol description in the RFC file, it must be
      12                 :            :  * called by a name other than "ssh" or "Secure Shell".
      13                 :            :  *
      14                 :            :  * SSH2 support by Markus Friedl.
      15                 :            :  * Copyright (c) 2000, 2001 Markus Friedl.  All rights reserved.
      16                 :            :  *
      17                 :            :  * Redistribution and use in source and binary forms, with or without
      18                 :            :  * modification, are permitted provided that the following conditions
      19                 :            :  * are met:
      20                 :            :  * 1. Redistributions of source code must retain the above copyright
      21                 :            :  *    notice, this list of conditions and the following disclaimer.
      22                 :            :  * 2. Redistributions in binary form must reproduce the above copyright
      23                 :            :  *    notice, this list of conditions and the following disclaimer in the
      24                 :            :  *    documentation and/or other materials provided with the distribution.
      25                 :            :  *
      26                 :            :  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
      27                 :            :  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
      28                 :            :  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
      29                 :            :  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
      30                 :            :  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
      31                 :            :  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
      32                 :            :  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
      33                 :            :  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
      34                 :            :  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
      35                 :            :  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
      36                 :            :  */
      37                 :            : 
      38                 :            : #include "includes.h"
      39                 :            : 
      40                 :            : #include <sys/types.h>
      41                 :            : #include <sys/param.h>
      42                 :            : #include <sys/wait.h>
      43                 :            : #include <sys/socket.h>
      44                 :            : #ifdef HAVE_SYS_TIME_H
      45                 :            : # include <sys/time.h>
      46                 :            : #endif
      47                 :            : 
      48                 :            : #include <netinet/in.h>
      49                 :            : 
      50                 :            : #include <errno.h>
      51                 :            : #include <fcntl.h>
      52                 :            : #include <pwd.h>
      53                 :            : #include <signal.h>
      54                 :            : #include <string.h>
      55                 :            : #include <termios.h>
      56                 :            : #include <unistd.h>
      57                 :            : #include <stdarg.h>
      58                 :            : 
      59                 :            : #include "openbsd-compat/sys-queue.h"
      60                 :            : #include "xmalloc.h"
      61                 :            : #include "packet.h"
      62                 :            : #include "buffer.h"
      63                 :            : #include "log.h"
      64                 :            : #include "servconf.h"
      65                 :            : #include "canohost.h"
      66                 :            : #include "sshpty.h"
      67                 :            : #include "channels.h"
      68                 :            : #include "compat.h"
      69                 :            : #include "ssh1.h"
      70                 :            : #include "ssh2.h"
      71                 :            : #include "key.h"
      72                 :            : #include "cipher.h"
      73                 :            : #include "kex.h"
      74                 :            : #include "hostfile.h"
      75                 :            : #include "auth.h"
      76                 :            : #include "session.h"
      77                 :            : #include "dispatch.h"
      78                 :            : #include "auth-options.h"
      79                 :            : #include "serverloop.h"
      80                 :            : #include "misc.h"
      81                 :            : #include "roaming.h"
      82                 :            : 
      83                 :            : extern ServerOptions options;
      84                 :            : 
      85                 :            : /* XXX */
      86                 :            : extern Kex *xxx_kex;
      87                 :            : extern Authctxt *the_authctxt;
      88                 :            : extern int use_privsep;
      89                 :            : 
      90                 :            : static Buffer stdin_buffer;     /* Buffer for stdin data. */
      91                 :            : static Buffer stdout_buffer;    /* Buffer for stdout data. */
      92                 :            : static Buffer stderr_buffer;    /* Buffer for stderr data. */
      93                 :            : static int fdin;                /* Descriptor for stdin (for writing) */
      94                 :            : static int fdout;               /* Descriptor for stdout (for reading);
      95                 :            :                                    May be same number as fdin. */
      96                 :            : static int fderr;               /* Descriptor for stderr.  May be -1. */
      97                 :            : static long stdin_bytes = 0;    /* Number of bytes written to stdin. */
      98                 :            : static long stdout_bytes = 0;   /* Number of stdout bytes sent to client. */
      99                 :            : static long stderr_bytes = 0;   /* Number of stderr bytes sent to client. */
     100                 :            : static long fdout_bytes = 0;    /* Number of stdout bytes read from program. */
     101                 :            : static int stdin_eof = 0;       /* EOF message received from client. */
     102                 :            : static int fdout_eof = 0;       /* EOF encountered reading from fdout. */
     103                 :            : static int fderr_eof = 0;       /* EOF encountered readung from fderr. */
     104                 :            : static int fdin_is_tty = 0;     /* fdin points to a tty. */
     105                 :            : static int connection_in;       /* Connection to client (input). */
     106                 :            : static int connection_out;      /* Connection to client (output). */
     107                 :            : static int connection_closed = 0;       /* Connection to client closed. */
     108                 :            : static u_int buffer_high;       /* "Soft" max buffer size. */
     109                 :            : static int no_more_sessions = 0; /* Disallow further sessions. */
     110                 :            : 
     111                 :            : /*
     112                 :            :  * This SIGCHLD kludge is used to detect when the child exits.  The server
     113                 :            :  * will exit after that, as soon as forwarded connections have terminated.
     114                 :            :  */
     115                 :            : 
     116                 :            : static volatile sig_atomic_t child_terminated = 0;      /* The child has terminated. */
     117                 :            : 
     118                 :            : /* Cleanup on signals (!use_privsep case only) */
     119                 :            : static volatile sig_atomic_t received_sigterm = 0;
     120                 :            : 
     121                 :            : /* prototypes */
     122                 :            : static void server_init_dispatch(void);
     123                 :            : 
     124                 :            : /*
     125                 :            :  * we write to this pipe if a SIGCHLD is caught in order to avoid
     126                 :            :  * the race between select() and child_terminated
     127                 :            :  */
     128                 :            : static int notify_pipe[2];
     129                 :            : static void
     130                 :        739 : notify_setup(void)
     131                 :            : {
     132         [ -  + ]:        739 :         if (pipe(notify_pipe) < 0) {
     133                 :          0 :                 error("pipe(notify_pipe) failed %s", strerror(errno));
     134   [ +  -  -  + ]:       1478 :         } else if ((fcntl(notify_pipe[0], F_SETFD, FD_CLOEXEC) == -1) ||
     135                 :        739 :             (fcntl(notify_pipe[1], F_SETFD, FD_CLOEXEC) == -1)) {
     136                 :          0 :                 error("fcntl(notify_pipe, F_SETFD) failed %s", strerror(errno));
     137                 :          0 :                 close(notify_pipe[0]);
     138                 :          0 :                 close(notify_pipe[1]);
     139                 :            :         } else {
     140                 :        739 :                 set_nonblock(notify_pipe[0]);
     141                 :        739 :                 set_nonblock(notify_pipe[1]);
     142                 :        739 :                 return;
     143                 :            :         }
     144                 :          0 :         notify_pipe[0] = -1;    /* read end */
     145                 :          0 :         notify_pipe[1] = -1;    /* write end */
     146                 :            : }
     147                 :            : static void
     148                 :         37 : notify_parent(void)
     149                 :            : {
     150         [ +  - ]:         37 :         if (notify_pipe[1] != -1)
     151                 :         37 :                 (void)write(notify_pipe[1], "", 1);
     152                 :         37 : }
     153                 :            : static void
     154                 :       4457 : notify_prepare(fd_set *readset)
     155                 :            : {
     156         [ +  - ]:       4457 :         if (notify_pipe[0] != -1)
     157 [ -  + ][ #  # ]:       4457 :                 FD_SET(notify_pipe[0], readset);
     158                 :       4457 : }
     159                 :            : static void
     160                 :       4457 : notify_done(fd_set *readset)
     161                 :            : {
     162                 :            :         char c;
     163                 :            : 
     164 [ +  - ][ -  + ]:       4457 :         if (notify_pipe[0] != -1 && FD_ISSET(notify_pipe[0], readset))
         [ #  # ][ +  + ]
     165         [ +  + ]:         52 :                 while (read(notify_pipe[0], &c, 1) != -1)
     166                 :         26 :                         debug2("notify_done: reading");
     167                 :       4457 : }
     168                 :            : 
     169                 :            : /*ARGSUSED*/
     170                 :            : static void
     171                 :         37 : sigchld_handler(int sig)
     172                 :            : {
     173                 :         37 :         int save_errno = errno;
     174                 :         37 :         child_terminated = 1;
     175                 :            : #ifndef _UNICOS
     176                 :         37 :         mysignal(SIGCHLD, sigchld_handler);
     177                 :            : #endif
     178                 :         37 :         notify_parent();
     179                 :         37 :         errno = save_errno;
     180                 :         37 : }
     181                 :            : 
     182                 :            : /*ARGSUSED*/
     183                 :            : static void
     184                 :          0 : sigterm_handler(int sig)
     185                 :            : {
     186                 :          0 :         received_sigterm = sig;
     187                 :          0 : }
     188                 :            : 
     189                 :            : /*
     190                 :            :  * Make packets from buffered stderr data, and buffer it for sending
     191                 :            :  * to the client.
     192                 :            :  */
     193                 :            : static void
     194                 :       1811 : make_packets_from_stderr_data(void)
     195                 :            : {
     196                 :            :         u_int len;
     197                 :            : 
     198                 :            :         /* Send buffered stderr data to the client. */
     199   [ +  +  +  - ]:       2387 :         while (buffer_len(&stderr_buffer) > 0 &&
     200                 :        288 :             packet_not_very_much_data_to_write()) {
     201                 :        288 :                 len = buffer_len(&stderr_buffer);
     202         [ -  + ]:        288 :                 if (packet_is_interactive()) {
     203         [ #  # ]:          0 :                         if (len > 512)
     204                 :          0 :                                 len = 512;
     205                 :            :                 } else {
     206                 :            :                         /* Keep the packets at reasonable size. */
     207         [ -  + ]:        288 :                         if (len > packet_get_maxsize())
     208                 :          0 :                                 len = packet_get_maxsize();
     209                 :            :                 }
     210                 :        288 :                 packet_start(SSH_SMSG_STDERR_DATA);
     211                 :        288 :                 packet_put_string(buffer_ptr(&stderr_buffer), len);
     212                 :        288 :                 packet_send();
     213                 :        288 :                 buffer_consume(&stderr_buffer, len);
     214                 :        288 :                 stderr_bytes += len;
     215                 :            :         }
     216                 :       1811 : }
     217                 :            : 
     218                 :            : /*
     219                 :            :  * Make packets from buffered stdout data, and buffer it for sending to the
     220                 :            :  * client.
     221                 :            :  */
     222                 :            : static void
     223                 :       1807 : make_packets_from_stdout_data(void)
     224                 :            : {
     225                 :            :         u_int len;
     226                 :            : 
     227                 :            :         /* Send buffered stdout data to the client. */
     228   [ +  +  +  - ]:       2405 :         while (buffer_len(&stdout_buffer) > 0 &&
     229                 :        299 :             packet_not_very_much_data_to_write()) {
     230                 :        299 :                 len = buffer_len(&stdout_buffer);
     231         [ -  + ]:        299 :                 if (packet_is_interactive()) {
     232         [ #  # ]:          0 :                         if (len > 512)
     233                 :          0 :                                 len = 512;
     234                 :            :                 } else {
     235                 :            :                         /* Keep the packets at reasonable size. */
     236         [ -  + ]:        299 :                         if (len > packet_get_maxsize())
     237                 :          0 :                                 len = packet_get_maxsize();
     238                 :            :                 }
     239                 :        299 :                 packet_start(SSH_SMSG_STDOUT_DATA);
     240                 :        299 :                 packet_put_string(buffer_ptr(&stdout_buffer), len);
     241                 :        299 :                 packet_send();
     242                 :        299 :                 buffer_consume(&stdout_buffer, len);
     243                 :        299 :                 stdout_bytes += len;
     244                 :            :         }
     245                 :       1807 : }
     246                 :            : 
     247                 :            : static void
     248                 :          0 : client_alive_check(void)
     249                 :            : {
     250                 :            :         int channel_id;
     251                 :            : 
     252                 :            :         /* timeout, check to see how many we have had */
     253         [ #  # ]:          0 :         if (packet_inc_alive_timeouts() > options.client_alive_count_max) {
     254                 :          0 :                 logit("Timeout, client not responding.");
     255                 :          0 :                 cleanup_exit(255);
     256                 :            :         }
     257                 :            : 
     258                 :            :         /*
     259                 :            :          * send a bogus global/channel request with "wantreply",
     260                 :            :          * we should get back a failure
     261                 :            :          */
     262         [ #  # ]:          0 :         if ((channel_id = channel_find_open()) == -1) {
     263                 :          0 :                 packet_start(SSH2_MSG_GLOBAL_REQUEST);
     264                 :          0 :                 packet_put_cstring("keepalive@openssh.com");
     265                 :          0 :                 packet_put_char(1);     /* boolean: want reply */
     266                 :            :         } else {
     267                 :          0 :                 channel_request_start(channel_id, "keepalive@openssh.com", 1);
     268                 :            :         }
     269                 :          0 :         packet_send();
     270                 :          0 : }
     271                 :            : 
     272                 :            : /*
     273                 :            :  * Sleep in select() until we can do something.  This will initialize the
     274                 :            :  * select masks.  Upon return, the masks will indicate which descriptors
     275                 :            :  * have data or can accept data.  Optionally, a maximum time can be specified
     276                 :            :  * for the duration of the wait (0 = infinite).
     277                 :            :  */
     278                 :            : static void
     279                 :       4457 : wait_until_can_do_something(fd_set **readsetp, fd_set **writesetp, int *maxfdp,
     280                 :            :     u_int *nallocp, u_int64_t max_time_milliseconds)
     281                 :            : {
     282                 :            :         struct timeval tv, *tvp;
     283                 :            :         int ret;
     284                 :       4457 :         time_t minwait_secs = 0;
     285                 :       4457 :         int client_alive_scheduled = 0;
     286                 :       4457 :         int program_alive_scheduled = 0;
     287                 :            : 
     288                 :            :         /* Allocate and update select() masks for channel descriptors. */
     289                 :       4457 :         channel_prepare_select(readsetp, writesetp, maxfdp, nallocp,
     290                 :            :             &minwait_secs, 0);
     291                 :            : 
     292         [ -  + ]:       4457 :         if (minwait_secs != 0)
     293                 :          0 :                 max_time_milliseconds = MIN(max_time_milliseconds,
     294                 :            :                     (u_int)minwait_secs * 1000);
     295                 :            : 
     296                 :            :         /*
     297                 :            :          * if using client_alive, set the max timeout accordingly,
     298                 :            :          * and indicate that this particular timeout was for client
     299                 :            :          * alive by setting the client_alive_scheduled flag.
     300                 :            :          *
     301                 :            :          * this could be randomized somewhat to make traffic
     302                 :            :          * analysis more difficult, but we're not doing it yet.
     303                 :            :          */
     304 [ +  + ][ +  + ]:       4457 :         if (compat20 &&
     305         [ -  + ]:       2663 :             max_time_milliseconds == 0 && options.client_alive_interval) {
     306                 :          0 :                 client_alive_scheduled = 1;
     307                 :          0 :                 max_time_milliseconds =
     308                 :          0 :                     (u_int64_t)options.client_alive_interval * 1000;
     309                 :            :         }
     310                 :            : 
     311         [ +  + ]:       4457 :         if (compat20) {
     312                 :            : #if 0
     313                 :            :                 /* wrong: bad condition XXX */
     314                 :            :                 if (channel_not_very_much_buffered_data())
     315                 :            : #endif
     316 [ -  + ][ #  # ]:       2669 :                 FD_SET(connection_in, *readsetp);
     317                 :            :         } else {
     318                 :            :                 /*
     319                 :            :                  * Read packets from the client unless we have too much
     320                 :            :                  * buffered stdin or channel data.
     321                 :            :                  */
     322   [ +  -  +  - ]:       3576 :                 if (buffer_len(&stdin_buffer) < buffer_high &&
     323                 :       1788 :                     channel_not_very_much_buffered_data())
     324 [ -  + ][ #  # ]:       1788 :                         FD_SET(connection_in, *readsetp);
     325                 :            :                 /*
     326                 :            :                  * If there is not too much data already buffered going to
     327                 :            :                  * the client, try to get some more data from the program.
     328                 :            :                  */
     329         [ +  - ]:       1788 :                 if (packet_not_very_much_data_to_write()) {
     330                 :       1788 :                         program_alive_scheduled = child_terminated;
     331         [ +  + ]:       1788 :                         if (!fdout_eof)
     332 [ -  + ][ #  # ]:       1489 :                                 FD_SET(fdout, *readsetp);
     333         [ +  + ]:       1788 :                         if (!fderr_eof)
     334 [ -  + ][ #  # ]:       1762 :                                 FD_SET(fderr, *readsetp);
     335                 :            :                 }
     336                 :            :                 /*
     337                 :            :                  * If we have buffered data, try to write some of that data
     338                 :            :                  * to the program.
     339                 :            :                  */
     340 [ +  + ][ -  + ]:       1788 :                 if (fdin != -1 && buffer_len(&stdin_buffer) > 0)
     341 [ #  # ][ #  # ]:          0 :                         FD_SET(fdin, *writesetp);
     342                 :            :         }
     343                 :       4457 :         notify_prepare(*readsetp);
     344                 :            : 
     345                 :            :         /*
     346                 :            :          * If we have buffered packet data going to the client, mark that
     347                 :            :          * descriptor.
     348                 :            :          */
     349         [ +  + ]:       4457 :         if (packet_have_data_to_write())
     350 [ -  + ][ #  # ]:       2012 :                 FD_SET(connection_out, *writesetp);
     351                 :            : 
     352                 :            :         /*
     353                 :            :          * If child has terminated and there is enough buffer space to read
     354                 :            :          * from it, then read as much as is available and exit.
     355                 :            :          */
     356 [ +  + ][ +  - ]:       4457 :         if (child_terminated && packet_not_very_much_data_to_write())
     357         [ +  + ]:         54 :                 if (max_time_milliseconds == 0 || client_alive_scheduled)
     358                 :         52 :                         max_time_milliseconds = 100;
     359                 :            : 
     360         [ +  + ]:       4457 :         if (max_time_milliseconds == 0)
     361                 :            :                 tvp = NULL;
     362                 :            :         else {
     363                 :         62 :                 tv.tv_sec = max_time_milliseconds / 1000;
     364                 :         62 :                 tv.tv_usec = 1000 * (max_time_milliseconds % 1000);
     365                 :         62 :                 tvp = &tv;
     366                 :            :         }
     367                 :            : 
     368                 :            :         /* Wait for something to happen, or the timeout to expire. */
     369                 :       4457 :         ret = select((*maxfdp)+1, *readsetp, *writesetp, NULL, tvp);
     370                 :            : 
     371         [ +  + ]:       4457 :         if (ret == -1) {
     372                 :          4 :                 memset(*readsetp, 0, *nallocp);
     373                 :          4 :                 memset(*writesetp, 0, *nallocp);
     374         [ -  + ]:          4 :                 if (errno != EINTR)
     375                 :          0 :                         error("select: %.100s", strerror(errno));
     376                 :            :         } else {
     377         [ -  + ]:       4453 :                 if (ret == 0 && client_alive_scheduled)
     378                 :          0 :                         client_alive_check();
     379 [ +  + ][ +  + ]:       4453 :                 if (!compat20 && program_alive_scheduled && fdin_is_tty) {
                 [ -  + ]
     380         [ #  # ]:          0 :                         if (!fdout_eof)
     381 [ #  # ][ #  # ]:          0 :                                 FD_SET(fdout, *readsetp);
     382         [ #  # ]:          0 :                         if (!fderr_eof)
     383 [ #  # ][ #  # ]:          0 :                                 FD_SET(fderr, *readsetp);
     384                 :            :                 }
     385                 :            :         }
     386                 :            : 
     387                 :       4457 :         notify_done(*readsetp);
     388                 :       4457 : }
     389                 :            : 
     390                 :            : /*
     391                 :            :  * Processes input from the client and the program.  Input data is stored
     392                 :            :  * in buffers and processed later.
     393                 :            :  */
     394                 :            : static void
     395                 :       4457 : process_input(fd_set *readset)
     396                 :            : {
     397                 :            :         int len;
     398                 :            :         char buf[16384];
     399                 :            : 
     400                 :            :         /* Read and buffer any input data from the client. */
     401 [ -  + ][ #  # ]:       4457 :         if (FD_ISSET(connection_in, readset)) {
                 [ +  + ]
     402                 :       1889 :                 int cont = 0;
     403                 :       1889 :                 len = roaming_read(connection_in, buf, sizeof(buf), &cont);
     404         [ +  + ]:       1889 :                 if (len == 0) {
     405         [ +  - ]:          3 :                         if (cont)
     406                 :          3 :                                 return;
     407                 :          3 :                         verbose("Connection closed by %.100s",
     408                 :            :                             get_remote_ipaddr());
     409                 :          3 :                         connection_closed = 1;
     410         [ -  + ]:          3 :                         if (compat20)
     411                 :            :                                 return;
     412                 :          0 :                         cleanup_exit(255);
     413         [ -  + ]:       1886 :                 } else if (len < 0) {
     414 [ #  # ][ #  # ]:          0 :                         if (errno != EINTR && errno != EAGAIN &&
     415                 :            :                             errno != EWOULDBLOCK) {
     416                 :          0 :                                 verbose("Read error from remote host "
     417                 :            :                                     "%.100s: %.100s",
     418                 :            :                                     get_remote_ipaddr(), strerror(errno));
     419                 :          0 :                                 cleanup_exit(255);
     420                 :            :                         }
     421                 :            :                 } else {
     422                 :            :                         /* Buffer any received data. */
     423                 :       1886 :                         packet_process_incoming(buf, len);
     424                 :            :                 }
     425                 :            :         }
     426         [ +  + ]:       4454 :         if (compat20)
     427                 :            :                 return;
     428                 :            : 
     429                 :            :         /* Read and buffer any available stdout data from the program. */
     430 [ +  + ][ -  + ]:       1788 :         if (!fdout_eof && FD_ISSET(fdout, readset)) {
         [ #  # ][ +  + ]
     431                 :        322 :                 errno = 0;
     432                 :        644 :                 len = read(fdout, buf, sizeof(buf));
     433 [ -  + ][ #  # ]:        322 :                 if (len < 0 && (errno == EINTR || ((errno == EAGAIN ||
                 [ #  # ]
     434         [ #  # ]:          0 :                     errno == EWOULDBLOCK) && !child_terminated))) {
     435                 :            :                         /* do nothing */
     436                 :            : #ifndef PTY_ZEROREAD
     437         [ +  + ]:        322 :                 } else if (len <= 0) {
     438                 :            : #else
     439                 :            :                 } else if ((!isatty(fdout) && len <= 0) ||
     440                 :            :                     (isatty(fdout) && (len < 0 || (len == 0 && errno != 0)))) {
     441                 :            : #endif
     442                 :         23 :                         fdout_eof = 1;
     443                 :            :                 } else {
     444                 :        299 :                         buffer_append(&stdout_buffer, buf, len);
     445                 :        299 :                         fdout_bytes += len;
     446                 :            :                 }
     447                 :            :         }
     448                 :            :         /* Read and buffer any available stderr data from the program. */
     449 [ +  + ][ -  + ]:       1788 :         if (!fderr_eof && FD_ISSET(fderr, readset)) {
         [ #  # ][ +  + ]
     450                 :        311 :                 errno = 0;
     451                 :        622 :                 len = read(fderr, buf, sizeof(buf));
     452 [ -  + ][ #  # ]:        311 :                 if (len < 0 && (errno == EINTR || ((errno == EAGAIN ||
                 [ #  # ]
     453         [ #  # ]:          0 :                     errno == EWOULDBLOCK) && !child_terminated))) {
     454                 :            :                         /* do nothing */
     455                 :            : #ifndef PTY_ZEROREAD
     456         [ +  + ]:        311 :                 } else if (len <= 0) {
     457                 :            : #else
     458                 :            :                 } else if ((!isatty(fderr) && len <= 0) ||
     459                 :            :                     (isatty(fderr) && (len < 0 || (len == 0 && errno != 0)))) {
     460                 :            : #endif
     461                 :         23 :                         fderr_eof = 1;
     462                 :            :                 } else {
     463                 :       4457 :                         buffer_append(&stderr_buffer, buf, len);
     464                 :            :                 }
     465                 :            :         }
     466                 :            : }
     467                 :            : 
     468                 :            : /*
     469                 :            :  * Sends data from internal buffers to client program stdin.
     470                 :            :  */
     471                 :            : static void
     472                 :       4454 : process_output(fd_set *writeset)
     473                 :            : {
     474                 :            :         struct termios tio;
     475                 :            :         u_char *data;
     476                 :            :         u_int dlen;
     477                 :            :         int len;
     478                 :            : 
     479                 :            :         /* Write buffered data to program stdin. */
     480 [ +  + ][ +  + ]:       4454 :         if (!compat20 && fdin != -1 && FD_ISSET(fdin, writeset)) {
         [ -  + ][ #  # ]
                 [ -  + ]
     481                 :          0 :                 data = buffer_ptr(&stdin_buffer);
     482                 :          0 :                 dlen = buffer_len(&stdin_buffer);
     483                 :          0 :                 len = write(fdin, data, dlen);
     484   [ #  #  #  # ]:          0 :                 if (len < 0 &&
     485         [ #  # ]:          0 :                     (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK)) {
     486                 :            :                         /* do nothing */
     487         [ #  # ]:          0 :                 } else if (len <= 0) {
     488         [ #  # ]:          0 :                         if (fdin != fdout)
     489                 :          0 :                                 close(fdin);
     490                 :            :                         else
     491                 :          0 :                                 shutdown(fdin, SHUT_WR); /* We will no longer send. */
     492                 :          0 :                         fdin = -1;
     493                 :            :                 } else {
     494                 :            :                         /* Successful write. */
     495 [ #  # ][ #  # ]:          0 :                         if (fdin_is_tty && dlen >= 1 && data[0] != '\r' &&
           [ #  #  #  # ]
     496                 :          0 :                             tcgetattr(fdin, &tio) == 0 &&
     497         [ #  # ]:          0 :                             !(tio.c_lflag & ECHO) && (tio.c_lflag & ICANON)) {
     498                 :            :                                 /*
     499                 :            :                                  * Simulate echo to reduce the impact of
     500                 :            :                                  * traffic analysis
     501                 :            :                                  */
     502                 :          0 :                                 packet_send_ignore(len);
     503                 :          0 :                                 packet_send();
     504                 :            :                         }
     505                 :            :                         /* Consume the data from the buffer. */
     506                 :          0 :                         buffer_consume(&stdin_buffer, len);
     507                 :            :                         /* Update the count of bytes written to the program. */
     508                 :          0 :                         stdin_bytes += len;
     509                 :            :                 }
     510                 :            :         }
     511                 :            :         /* Send any buffered packet data to the client. */
     512 [ -  + ][ #  # ]:       4454 :         if (FD_ISSET(connection_out, writeset))
                 [ +  + ]
     513                 :       2007 :                 packet_write_poll();
     514                 :       4454 : }
     515                 :            : 
     516                 :            : /*
     517                 :            :  * Wait until all buffered output has been sent to the client.
     518                 :            :  * This is used when the program terminates.
     519                 :            :  */
     520                 :            : static void
     521                 :         23 : drain_output(void)
     522                 :            : {
     523                 :            :         /* Send any buffered stdout data to the client. */
     524         [ -  + ]:         23 :         if (buffer_len(&stdout_buffer) > 0) {
     525                 :          0 :                 packet_start(SSH_SMSG_STDOUT_DATA);
     526                 :          0 :                 packet_put_string(buffer_ptr(&stdout_buffer),
     527                 :            :                                   buffer_len(&stdout_buffer));
     528                 :          0 :                 packet_send();
     529                 :            :                 /* Update the count of sent bytes. */
     530                 :          0 :                 stdout_bytes += buffer_len(&stdout_buffer);
     531                 :            :         }
     532                 :            :         /* Send any buffered stderr data to the client. */
     533         [ -  + ]:         23 :         if (buffer_len(&stderr_buffer) > 0) {
     534                 :          0 :                 packet_start(SSH_SMSG_STDERR_DATA);
     535                 :          0 :                 packet_put_string(buffer_ptr(&stderr_buffer),
     536                 :            :                                   buffer_len(&stderr_buffer));
     537                 :          0 :                 packet_send();
     538                 :            :                 /* Update the count of sent bytes. */
     539                 :          0 :                 stderr_bytes += buffer_len(&stderr_buffer);
     540                 :            :         }
     541                 :            :         /* Wait until all buffered data has been written to the client. */
     542                 :         23 :         packet_write_wait();
     543                 :         23 : }
     544                 :            : 
     545                 :            : static void
     546                 :       5193 : process_buffered_input_packets(void)
     547                 :            : {
     548         [ +  + ]:       5193 :         dispatch_run(DISPATCH_NONBLOCK, NULL, compat20 ? xxx_kex : NULL);
     549                 :       4480 : }
     550                 :            : 
     551                 :            : /*
     552                 :            :  * Performs the interactive session.  This handles data transmission between
     553                 :            :  * the client and the program.  Note that the notion of stdin, stdout, and
     554                 :            :  * stderr in this function is sort of reversed: this function writes to
     555                 :            :  * stdin (of the child program), and reads from stdout and stderr (of the
     556                 :            :  * child program).
     557                 :            :  */
     558                 :            : void
     559                 :         23 : server_loop(pid_t pid, int fdin_arg, int fdout_arg, int fderr_arg)
     560                 :            : {
     561                 :         23 :         fd_set *readset = NULL, *writeset = NULL;
     562                 :         23 :         int max_fd = 0;
     563                 :         23 :         u_int nalloc = 0;
     564                 :            :         int wait_status;        /* Status returned by wait(). */
     565                 :            :         pid_t wait_pid;         /* pid returned by wait(). */
     566                 :         23 :         int waiting_termination = 0;    /* Have displayed waiting close message. */
     567                 :            :         u_int64_t max_time_milliseconds;
     568                 :            :         u_int previous_stdout_buffer_bytes;
     569                 :            :         u_int stdout_buffer_bytes;
     570                 :            :         int type;
     571                 :            : 
     572                 :         23 :         debug("Entering interactive session.");
     573                 :            : 
     574                 :            :         /* Initialize the SIGCHLD kludge. */
     575                 :         23 :         child_terminated = 0;
     576                 :         23 :         mysignal(SIGCHLD, sigchld_handler);
     577                 :            : 
     578         [ +  + ]:         23 :         if (!use_privsep) {
     579                 :          1 :                 signal(SIGTERM, sigterm_handler);
     580                 :          1 :                 signal(SIGINT, sigterm_handler);
     581                 :          1 :                 signal(SIGQUIT, sigterm_handler);
     582                 :            :         }
     583                 :            : 
     584                 :            :         /* Initialize our global variables. */
     585                 :         23 :         fdin = fdin_arg;
     586                 :         23 :         fdout = fdout_arg;
     587                 :         23 :         fderr = fderr_arg;
     588                 :            : 
     589                 :            :         /* nonblocking IO */
     590                 :         23 :         set_nonblock(fdin);
     591                 :         23 :         set_nonblock(fdout);
     592                 :            :         /* we don't have stderr for interactive terminal sessions, see below */
     593         [ +  - ]:         23 :         if (fderr != -1)
     594                 :         23 :                 set_nonblock(fderr);
     595                 :            : 
     596 [ +  - ][ -  + ]:         23 :         if (!(datafellows & SSH_BUG_IGNOREMSG) && isatty(fdin))
     597                 :          0 :                 fdin_is_tty = 1;
     598                 :            : 
     599                 :         23 :         connection_in = packet_get_connection_in();
     600                 :         23 :         connection_out = packet_get_connection_out();
     601                 :            : 
     602                 :         23 :         notify_setup();
     603                 :            : 
     604                 :         23 :         previous_stdout_buffer_bytes = 0;
     605                 :            : 
     606                 :            :         /* Set approximate I/O buffer size. */
     607         [ -  + ]:         23 :         if (packet_is_interactive())
     608                 :          0 :                 buffer_high = 4096;
     609                 :            :         else
     610                 :         23 :                 buffer_high = 64 * 1024;
     611                 :            : 
     612                 :            : #if 0
     613                 :            :         /* Initialize max_fd to the maximum of the known file descriptors. */
     614                 :            :         max_fd = MAX(connection_in, connection_out);
     615                 :            :         max_fd = MAX(max_fd, fdin);
     616                 :            :         max_fd = MAX(max_fd, fdout);
     617                 :            :         if (fderr != -1)
     618                 :            :                 max_fd = MAX(max_fd, fderr);
     619                 :            : #endif
     620                 :            : 
     621                 :            :         /* Initialize Initialize buffers. */
     622                 :         23 :         buffer_init(&stdin_buffer);
     623                 :         23 :         buffer_init(&stdout_buffer);
     624                 :         23 :         buffer_init(&stderr_buffer);
     625                 :            : 
     626                 :            :         /*
     627                 :            :          * If we have no separate fderr (which is the case when we have a pty
     628                 :            :          * - there we cannot make difference between data sent to stdout and
     629                 :            :          * stderr), indicate that we have seen an EOF from stderr.  This way
     630                 :            :          * we don't need to check the descriptor everywhere.
     631                 :            :          */
     632         [ -  + ]:         23 :         if (fderr == -1)
     633                 :          0 :                 fderr_eof = 1;
     634                 :            : 
     635                 :         23 :         server_init_dispatch();
     636                 :            : 
     637                 :            :         /* Main loop of the server for the interactive session mode. */
     638                 :            :         for (;;) {
     639                 :            : 
     640                 :            :                 /* Process buffered packets from the client. */
     641                 :       1811 :                 process_buffered_input_packets();
     642                 :            : 
     643                 :            :                 /*
     644                 :            :                  * If we have received eof, and there is no more pending
     645                 :            :                  * input data, cause a real eof by closing fdin.
     646                 :            :                  */
     647 [ +  + ][ +  + ]:       1811 :                 if (stdin_eof && fdin != -1 && buffer_len(&stdin_buffer) == 0) {
                 [ +  - ]
     648         [ +  - ]:         10 :                         if (fdin != fdout)
     649                 :         10 :                                 close(fdin);
     650                 :            :                         else
     651                 :          0 :                                 shutdown(fdin, SHUT_WR); /* We will no longer send. */
     652                 :         10 :                         fdin = -1;
     653                 :            :                 }
     654                 :            :                 /* Make packets from buffered stderr data to send to the client. */
     655                 :       1811 :                 make_packets_from_stderr_data();
     656                 :            : 
     657                 :            :                 /*
     658                 :            :                  * Make packets from buffered stdout data to send to the
     659                 :            :                  * client. If there is very little to send, this arranges to
     660                 :            :                  * not send them now, but to wait a short while to see if we
     661                 :            :                  * are getting more data. This is necessary, as some systems
     662                 :            :                  * wake up readers from a pty after each separate character.
     663                 :            :                  */
     664                 :       1811 :                 max_time_milliseconds = 0;
     665                 :       1811 :                 stdout_buffer_bytes = buffer_len(&stdout_buffer);
     666 [ +  + ][ +  + ]:       1811 :                 if (stdout_buffer_bytes != 0 && stdout_buffer_bytes < 256 &&
     667                 :            :                     stdout_buffer_bytes != previous_stdout_buffer_bytes) {
     668                 :            :                         /* try again after a while */
     669                 :            :                         max_time_milliseconds = 10;
     670                 :            :                 } else {
     671                 :            :                         /* Send it now. */
     672                 :       1807 :                         make_packets_from_stdout_data();
     673                 :            :                 }
     674                 :       1811 :                 previous_stdout_buffer_bytes = buffer_len(&stdout_buffer);
     675                 :            : 
     676                 :            :                 /* Send channel data to the client. */
     677         [ +  - ]:       1811 :                 if (packet_not_very_much_data_to_write())
     678                 :       1811 :                         channel_output_poll();
     679                 :            : 
     680                 :            :                 /*
     681                 :            :                  * Bail out of the loop if the program has closed its output
     682                 :            :                  * descriptors, and we have no more data to send to the
     683                 :            :                  * client, and there is no pending buffered data.
     684                 :            :                  */
     685 [ +  + ][ +  + ]:       1834 :                 if (fdout_eof && fderr_eof && !packet_have_data_to_write() &&
           [ +  +  +  - ]
     686         [ +  - ]:         46 :                     buffer_len(&stdout_buffer) == 0 && buffer_len(&stderr_buffer) == 0) {
     687         [ -  + ]:         23 :                         if (!channel_still_open())
     688                 :            :                                 break;
     689         [ #  # ]:          0 :                         if (!waiting_termination) {
     690                 :          0 :                                 const char *s = "Waiting for forwarded connections to terminate...\r\n";
     691                 :            :                                 char *cp;
     692                 :          0 :                                 waiting_termination = 1;
     693                 :          0 :                                 buffer_append(&stderr_buffer, s, strlen(s));
     694                 :            : 
     695                 :            :                                 /* Display list of open channels. */
     696                 :          0 :                                 cp = channel_open_message();
     697                 :          0 :                                 buffer_append(&stderr_buffer, cp, strlen(cp));
     698                 :          0 :                                 free(cp);
     699                 :            :                         }
     700                 :            :                 }
     701                 :       1788 :                 max_fd = MAX(connection_in, connection_out);
     702                 :       1788 :                 max_fd = MAX(max_fd, fdin);
     703                 :       1788 :                 max_fd = MAX(max_fd, fdout);
     704                 :       1788 :                 max_fd = MAX(max_fd, fderr);
     705                 :       1788 :                 max_fd = MAX(max_fd, notify_pipe[0]);
     706                 :            : 
     707                 :            :                 /* Sleep in select() until we can do something. */
     708                 :       1788 :                 wait_until_can_do_something(&readset, &writeset, &max_fd,
     709                 :            :                     &nalloc, max_time_milliseconds);
     710                 :            : 
     711         [ -  + ]:       1788 :                 if (received_sigterm) {
     712                 :          0 :                         logit("Exiting on signal %d", (int)received_sigterm);
     713                 :            :                         /* Clean up sessions, utmp, etc. */
     714                 :          0 :                         cleanup_exit(255);
     715                 :            :                 }
     716                 :            : 
     717                 :            :                 /* Process any channel events. */
     718                 :       1788 :                 channel_after_select(readset, writeset);
     719                 :            : 
     720                 :            :                 /* Process input from the client and from program stdout/stderr. */
     721                 :       1788 :                 process_input(readset);
     722                 :            : 
     723                 :            :                 /* Process output to the client and to program stdin. */
     724                 :       1788 :                 process_output(writeset);
     725                 :       1788 :         }
     726                 :         23 :         free(readset);
     727                 :         23 :         free(writeset);
     728                 :            : 
     729                 :            :         /* Cleanup and termination code. */
     730                 :            : 
     731                 :            :         /* Wait until all output has been sent to the client. */
     732                 :         23 :         drain_output();
     733                 :            : 
     734                 :         23 :         debug("End of interactive session; stdin %ld, stdout (read %ld, sent %ld), stderr %ld bytes.",
     735                 :            :             stdin_bytes, fdout_bytes, stdout_bytes, stderr_bytes);
     736                 :            : 
     737                 :            :         /* Free and clear the buffers. */
     738                 :         23 :         buffer_free(&stdin_buffer);
     739                 :         23 :         buffer_free(&stdout_buffer);
     740                 :         23 :         buffer_free(&stderr_buffer);
     741                 :            : 
     742                 :            :         /* Close the file descriptors. */
     743         [ +  - ]:         23 :         if (fdout != -1)
     744                 :         23 :                 close(fdout);
     745                 :         23 :         fdout = -1;
     746                 :         23 :         fdout_eof = 1;
     747         [ +  - ]:         23 :         if (fderr != -1)
     748                 :         23 :                 close(fderr);
     749                 :         23 :         fderr = -1;
     750                 :         23 :         fderr_eof = 1;
     751         [ +  + ]:         23 :         if (fdin != -1)
     752                 :         13 :                 close(fdin);
     753                 :         23 :         fdin = -1;
     754                 :            : 
     755                 :         23 :         channel_free_all();
     756                 :            : 
     757                 :            :         /* We no longer want our SIGCHLD handler to be called. */
     758                 :         23 :         mysignal(SIGCHLD, SIG_DFL);
     759                 :            : 
     760         [ -  + ]:         23 :         while ((wait_pid = waitpid(-1, &wait_status, 0)) < 0)
     761         [ #  # ]:          0 :                 if (errno != EINTR)
     762                 :          0 :                         packet_disconnect("wait: %.100s", strerror(errno));
     763         [ -  + ]:         23 :         if (wait_pid != pid)
     764                 :          0 :                 error("Strange, wait returned pid %ld, expected %ld",
     765                 :            :                     (long)wait_pid, (long)pid);
     766                 :            : 
     767                 :            :         /* Check if it exited normally. */
     768         [ +  - ]:         23 :         if (WIFEXITED(wait_status)) {
     769                 :            :                 /* Yes, normal exit.  Get exit status and send it to the client. */
     770                 :         23 :                 debug("Command exited with status %d.", WEXITSTATUS(wait_status));
     771                 :         23 :                 packet_start(SSH_SMSG_EXITSTATUS);
     772                 :         23 :                 packet_put_int(WEXITSTATUS(wait_status));
     773                 :         23 :                 packet_send();
     774                 :         23 :                 packet_write_wait();
     775                 :            : 
     776                 :            :                 /*
     777                 :            :                  * Wait for exit confirmation.  Note that there might be
     778                 :            :                  * other packets coming before it; however, the program has
     779                 :            :                  * already died so we just ignore them.  The client is
     780                 :            :                  * supposed to respond with the confirmation when it receives
     781                 :            :                  * the exit status.
     782                 :            :                  */
     783                 :            :                 do {
     784                 :         23 :                         type = packet_read();
     785                 :            :                 }
     786         [ -  + ]:         23 :                 while (type != SSH_CMSG_EXIT_CONFIRMATION);
     787                 :            : 
     788                 :         23 :                 debug("Received exit confirmation.");
     789                 :         23 :                 return;
     790                 :            :         }
     791                 :            :         /* Check if the program terminated due to a signal. */
     792         [ #  # ]:          0 :         if (WIFSIGNALED(wait_status))
     793                 :          0 :                 packet_disconnect("Command terminated on signal %d.",
     794                 :          0 :                                   WTERMSIG(wait_status));
     795                 :            : 
     796                 :            :         /* Some weird exit cause.  Just exit. */
     797                 :          0 :         packet_disconnect("wait returned status %04x.", wait_status);
     798                 :            :         /* NOTREACHED */
     799                 :            : }
     800                 :            : 
     801                 :            : static void
     802                 :       2672 : collect_children(void)
     803                 :            : {
     804                 :            :         pid_t pid;
     805                 :            :         sigset_t oset, nset;
     806                 :            :         int status;
     807                 :            : 
     808                 :            :         /* block SIGCHLD while we check for dead children */
     809                 :       2672 :         sigemptyset(&nset);
     810                 :       2672 :         sigaddset(&nset, SIGCHLD);
     811                 :       2672 :         sigprocmask(SIG_BLOCK, &nset, &oset);
     812         [ +  + ]:       2672 :         if (child_terminated) {
     813                 :         15 :                 debug("Received SIGCHLD.");
     814 [ +  + ][ +  - ]:         45 :                 while ((pid = waitpid(-1, &status, WNOHANG)) > 0 ||
     815         [ -  + ]:         15 :                     (pid < 0 && errno == EINTR))
     816         [ +  - ]:         15 :                         if (pid > 0)
     817                 :         30 :                                 session_close_by_pid(pid, status);
     818                 :         15 :                 child_terminated = 0;
     819                 :            :         }
     820                 :       2672 :         sigprocmask(SIG_SETMASK, &oset, NULL);
     821                 :       2672 : }
     822                 :            : 
     823                 :            : void
     824                 :        716 : server_loop2(Authctxt *authctxt)
     825                 :            : {
     826                 :        716 :         fd_set *readset = NULL, *writeset = NULL;
     827                 :        716 :         int rekeying = 0, max_fd;
     828                 :        716 :         u_int nalloc = 0;
     829                 :        716 :         u_int64_t rekey_timeout_ms = 0;
     830                 :            : 
     831                 :        716 :         debug("Entering interactive session for SSH2.");
     832                 :            : 
     833                 :        716 :         mysignal(SIGCHLD, sigchld_handler);
     834                 :        716 :         child_terminated = 0;
     835                 :        716 :         connection_in = packet_get_connection_in();
     836                 :        716 :         connection_out = packet_get_connection_out();
     837                 :            : 
     838         [ +  + ]:        716 :         if (!use_privsep) {
     839                 :         74 :                 signal(SIGTERM, sigterm_handler);
     840                 :         74 :                 signal(SIGINT, sigterm_handler);
     841                 :         74 :                 signal(SIGQUIT, sigterm_handler);
     842                 :            :         }
     843                 :            : 
     844                 :        716 :         notify_setup();
     845                 :            : 
     846                 :        716 :         max_fd = MAX(connection_in, connection_out);
     847                 :        716 :         max_fd = MAX(max_fd, notify_pipe[0]);
     848                 :            : 
     849                 :        716 :         server_init_dispatch();
     850                 :            : 
     851                 :            :         for (;;) {
     852                 :       3382 :                 process_buffered_input_packets();
     853                 :            : 
     854 [ +  - ][ +  - ]:       2669 :                 rekeying = (xxx_kex != NULL && !xxx_kex->done);
     855                 :            : 
     856 [ +  - ][ +  - ]:       2669 :                 if (!rekeying && packet_not_very_much_data_to_write())
     857                 :       2669 :                         channel_output_poll();
     858 [ +  + ][ +  - ]:       2669 :                 if (options.rekey_interval > 0 && compat20 && !rekeying)
                 [ +  - ]
     859                 :          6 :                         rekey_timeout_ms = packet_get_rekey_timeout() * 1000;
     860                 :            :                 else
     861                 :            :                         rekey_timeout_ms = 0;
     862                 :            : 
     863                 :       2669 :                 wait_until_can_do_something(&readset, &writeset, &max_fd,
     864                 :            :                     &nalloc, rekey_timeout_ms);
     865                 :            : 
     866         [ -  + ]:       2669 :                 if (received_sigterm) {
     867                 :          0 :                         logit("Exiting on signal %d", (int)received_sigterm);
     868                 :            :                         /* Clean up sessions, utmp, etc. */
     869                 :          0 :                         cleanup_exit(255);
     870                 :            :                 }
     871                 :            : 
     872                 :       2669 :                 collect_children();
     873         [ +  - ]:       2669 :                 if (!rekeying) {
     874                 :       2669 :                         channel_after_select(readset, writeset);
     875         [ -  + ]:       2669 :                         if (packet_need_rekeying()) {
     876                 :          0 :                                 debug("need rekeying");
     877                 :          0 :                                 xxx_kex->done = 0;
     878                 :          0 :                                 kex_send_kexinit(xxx_kex);
     879                 :            :                         }
     880                 :            :                 }
     881                 :       2669 :                 process_input(readset);
     882         [ +  + ]:       2669 :                 if (connection_closed)
     883                 :            :                         break;
     884                 :       2666 :                 process_output(writeset);
     885                 :       2666 :         }
     886                 :          3 :         collect_children();
     887                 :            : 
     888                 :          3 :         free(readset);
     889                 :          3 :         free(writeset);
     890                 :            : 
     891                 :            :         /* free all channels, no more reads and writes */
     892                 :          3 :         channel_free_all();
     893                 :            : 
     894                 :            :         /* free remaining sessions, e.g. remove wtmp entries */
     895                 :          3 :         session_destroy_all(NULL);
     896                 :          3 : }
     897                 :            : 
     898                 :            : static void
     899                 :          0 : server_input_keep_alive(int type, u_int32_t seq, void *ctxt)
     900                 :            : {
     901                 :          0 :         debug("Got %d/%u for keepalive", type, seq);
     902                 :            :         /*
     903                 :            :          * reset timeout, since we got a sane answer from the client.
     904                 :            :          * even if this was generated by something other than
     905                 :            :          * the bogus CHANNEL_REQUEST we send for keepalives.
     906                 :            :          */
     907                 :          0 :         packet_set_alive_timeouts(0);
     908                 :          0 : }
     909                 :            : 
     910                 :            : static void
     911                 :          0 : server_input_stdin_data(int type, u_int32_t seq, void *ctxt)
     912                 :            : {
     913                 :            :         char *data;
     914                 :            :         u_int data_len;
     915                 :            : 
     916                 :            :         /* Stdin data from the client.  Append it to the buffer. */
     917                 :            :         /* Ignore any data if the client has closed stdin. */
     918         [ #  # ]:          0 :         if (fdin == -1)
     919                 :          0 :                 return;
     920                 :          0 :         data = packet_get_string(&data_len);
     921         [ #  # ]:          0 :         packet_check_eom();
     922                 :          0 :         buffer_append(&stdin_buffer, data, data_len);
     923                 :          0 :         explicit_bzero(data, data_len);
     924                 :          0 :         free(data);
     925                 :            : }
     926                 :            : 
     927                 :            : static void
     928                 :         10 : server_input_eof(int type, u_int32_t seq, void *ctxt)
     929                 :            : {
     930                 :            :         /*
     931                 :            :          * Eof from the client.  The stdin descriptor to the
     932                 :            :          * program will be closed when all buffered data has
     933                 :            :          * drained.
     934                 :            :          */
     935                 :         10 :         debug("EOF received for stdin.");
     936         [ -  + ]:         10 :         packet_check_eom();
     937                 :         10 :         stdin_eof = 1;
     938                 :         10 : }
     939                 :            : 
     940                 :            : static void
     941                 :          0 : server_input_window_size(int type, u_int32_t seq, void *ctxt)
     942                 :            : {
     943                 :          0 :         u_int row = packet_get_int();
     944                 :          0 :         u_int col = packet_get_int();
     945                 :          0 :         u_int xpixel = packet_get_int();
     946                 :          0 :         u_int ypixel = packet_get_int();
     947                 :            : 
     948                 :          0 :         debug("Window change received.");
     949         [ #  # ]:          0 :         packet_check_eom();
     950         [ #  # ]:          0 :         if (fdin != -1)
     951                 :          0 :                 pty_change_window_size(fdin, row, col, xpixel, ypixel);
     952                 :          0 : }
     953                 :            : 
     954                 :            : static Channel *
     955                 :          1 : server_request_direct_tcpip(void)
     956                 :            : {
     957                 :          1 :         Channel *c = NULL;
     958                 :            :         char *target, *originator;
     959                 :            :         u_short target_port, originator_port;
     960                 :            : 
     961                 :          1 :         target = packet_get_string(NULL);
     962                 :          1 :         target_port = packet_get_int();
     963                 :          1 :         originator = packet_get_string(NULL);
     964                 :          1 :         originator_port = packet_get_int();
     965         [ -  + ]:          1 :         packet_check_eom();
     966                 :            : 
     967                 :          1 :         debug("server_request_direct_tcpip: originator %s port %d, target %s "
     968                 :            :             "port %d", originator, originator_port, target, target_port);
     969                 :            : 
     970                 :            :         /* XXX fine grained permissions */
     971 [ +  - ][ +  - ]:          1 :         if ((options.allow_tcp_forwarding & FORWARD_LOCAL) != 0 &&
     972                 :          1 :             !no_port_forwarding_flag) {
     973                 :          1 :                 c = channel_connect_to(target, target_port,
     974                 :            :                     "direct-tcpip", "direct-tcpip");
     975                 :            :         } else {
     976                 :          0 :                 logit("refused local port forward: "
     977                 :            :                     "originator %s port %d, target %s port %d",
     978                 :            :                     originator, originator_port, target, target_port);
     979                 :            :         }
     980                 :            : 
     981                 :          1 :         free(originator);
     982                 :          1 :         free(target);
     983                 :            : 
     984                 :          1 :         return c;
     985                 :            : }
     986                 :            : 
     987                 :            : static Channel *
     988                 :          0 : server_request_tun(void)
     989                 :            : {
     990                 :          0 :         Channel *c = NULL;
     991                 :            :         int mode, tun;
     992                 :            :         int sock;
     993                 :            : 
     994                 :          0 :         mode = packet_get_int();
     995         [ #  # ]:          0 :         switch (mode) {
     996                 :            :         case SSH_TUNMODE_POINTOPOINT:
     997                 :            :         case SSH_TUNMODE_ETHERNET:
     998                 :            :                 break;
     999                 :            :         default:
    1000                 :          0 :                 packet_send_debug("Unsupported tunnel device mode.");
    1001                 :          0 :                 return NULL;
    1002                 :            :         }
    1003         [ #  # ]:          0 :         if ((options.permit_tun & mode) == 0) {
    1004                 :          0 :                 packet_send_debug("Server has rejected tunnel device "
    1005                 :            :                     "forwarding");
    1006                 :          0 :                 return NULL;
    1007                 :            :         }
    1008                 :            : 
    1009                 :          0 :         tun = packet_get_int();
    1010         [ #  # ]:          0 :         if (forced_tun_device != -1) {
    1011 [ #  # ][ #  # ]:          0 :                 if (tun != SSH_TUNID_ANY && forced_tun_device != tun)
    1012                 :            :                         goto done;
    1013                 :            :                 tun = forced_tun_device;
    1014                 :            :         }
    1015                 :          0 :         sock = tun_open(tun, mode);
    1016         [ #  # ]:          0 :         if (sock < 0)
    1017                 :            :                 goto done;
    1018                 :          0 :         c = channel_new("tun", SSH_CHANNEL_OPEN, sock, sock, -1,
    1019                 :            :             CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, 0, "tun", 1);
    1020                 :          0 :         c->datagram = 1;
    1021                 :            : #if defined(SSH_TUN_FILTER)
    1022         [ #  # ]:          0 :         if (mode == SSH_TUNMODE_POINTOPOINT)
    1023                 :          0 :                 channel_register_filter(c->self, sys_tun_infilter,
    1024                 :            :                     sys_tun_outfilter, NULL, NULL);
    1025                 :            : #endif
    1026                 :            : 
    1027                 :            :  done:
    1028         [ #  # ]:          0 :         if (c == NULL)
    1029                 :          0 :                 packet_send_debug("Failed to open the tunnel device.");
    1030                 :          0 :         return c;
    1031                 :            : }
    1032                 :            : 
    1033                 :            : static Channel *
    1034                 :        729 : server_request_session(void)
    1035                 :            : {
    1036                 :            :         Channel *c;
    1037                 :            : 
    1038                 :        729 :         debug("input_session_request");
    1039         [ -  + ]:        729 :         packet_check_eom();
    1040                 :            : 
    1041         [ -  + ]:        729 :         if (no_more_sessions) {
    1042                 :          0 :                 packet_disconnect("Possible attack: attempt to open a session "
    1043                 :            :                     "after additional sessions disabled");
    1044                 :            :         }
    1045                 :            : 
    1046                 :            :         /*
    1047                 :            :          * A server session has no fd to read or write until a
    1048                 :            :          * CHANNEL_REQUEST for a shell is made, so we set the type to
    1049                 :            :          * SSH_CHANNEL_LARVAL.  Additionally, a callback for handling all
    1050                 :            :          * CHANNEL_REQUEST messages is registered.
    1051                 :            :          */
    1052                 :        729 :         c = channel_new("session", SSH_CHANNEL_LARVAL,
    1053                 :            :             -1, -1, -1, /*window size*/0, CHAN_SES_PACKET_DEFAULT,
    1054                 :            :             0, "server-session", 1);
    1055         [ -  + ]:        729 :         if (session_open(the_authctxt, c->self) != 1) {
    1056                 :          0 :                 debug("session open failed, free channel %d", c->self);
    1057                 :          0 :                 channel_free(c);
    1058                 :          0 :                 return NULL;
    1059                 :            :         }
    1060                 :        729 :         channel_register_cleanup(c->self, session_close_by_channel, 0);
    1061                 :        729 :         return c;
    1062                 :            : }
    1063                 :            : 
    1064                 :            : static void
    1065                 :        730 : server_input_channel_open(int type, u_int32_t seq, void *ctxt)
    1066                 :            : {
    1067                 :        730 :         Channel *c = NULL;
    1068                 :            :         char *ctype;
    1069                 :            :         int rchan;
    1070                 :            :         u_int rmaxpack, rwindow, len;
    1071                 :            : 
    1072                 :        730 :         ctype = packet_get_string(&len);
    1073                 :        730 :         rchan = packet_get_int();
    1074                 :        730 :         rwindow = packet_get_int();
    1075                 :        730 :         rmaxpack = packet_get_int();
    1076                 :            : 
    1077                 :        730 :         debug("server_input_channel_open: ctype %s rchan %d win %d max %d",
    1078                 :            :             ctype, rchan, rwindow, rmaxpack);
    1079                 :            : 
    1080         [ +  + ]:        730 :         if (strcmp(ctype, "session") == 0) {
    1081                 :        729 :                 c = server_request_session();
    1082         [ +  - ]:          1 :         } else if (strcmp(ctype, "direct-tcpip") == 0) {
    1083                 :          1 :                 c = server_request_direct_tcpip();
    1084         [ #  # ]:          0 :         } else if (strcmp(ctype, "tun@openssh.com") == 0) {
    1085                 :          0 :                 c = server_request_tun();
    1086                 :            :         }
    1087         [ +  - ]:        730 :         if (c != NULL) {
    1088                 :        730 :                 debug("server_input_channel_open: confirm %s", ctype);
    1089                 :        730 :                 c->remote_id = rchan;
    1090                 :        730 :                 c->remote_window = rwindow;
    1091                 :        730 :                 c->remote_maxpacket = rmaxpack;
    1092         [ +  + ]:        730 :                 if (c->type != SSH_CHANNEL_CONNECTING) {
    1093                 :        729 :                         packet_start(SSH2_MSG_CHANNEL_OPEN_CONFIRMATION);
    1094                 :        729 :                         packet_put_int(c->remote_id);
    1095                 :        729 :                         packet_put_int(c->self);
    1096                 :        729 :                         packet_put_int(c->local_window);
    1097                 :        729 :                         packet_put_int(c->local_maxpacket);
    1098                 :        729 :                         packet_send();
    1099                 :            :                 }
    1100                 :            :         } else {
    1101                 :          0 :                 debug("server_input_channel_open: failure %s", ctype);
    1102                 :          0 :                 packet_start(SSH2_MSG_CHANNEL_OPEN_FAILURE);
    1103                 :          0 :                 packet_put_int(rchan);
    1104                 :          0 :                 packet_put_int(SSH2_OPEN_ADMINISTRATIVELY_PROHIBITED);
    1105         [ #  # ]:          0 :                 if (!(datafellows & SSH_BUG_OPENFAILURE)) {
    1106                 :          0 :                         packet_put_cstring("open failed");
    1107                 :          0 :                         packet_put_cstring("");
    1108                 :            :                 }
    1109                 :          0 :                 packet_send();
    1110                 :            :         }
    1111                 :        730 :         free(ctype);
    1112                 :        730 : }
    1113                 :            : 
    1114                 :            : static void
    1115                 :        746 : server_input_global_request(int type, u_int32_t seq, void *ctxt)
    1116                 :            : {
    1117                 :            :         char *rtype;
    1118                 :            :         int want_reply;
    1119                 :        746 :         int success = 0, allocated_listen_port = 0;
    1120                 :            : 
    1121                 :        746 :         rtype = packet_get_string(NULL);
    1122                 :        746 :         want_reply = packet_get_char();
    1123                 :        746 :         debug("server_input_global_request: rtype %s want_reply %d", rtype, want_reply);
    1124                 :            : 
    1125                 :            :         /* -R style forwarding */
    1126         [ +  + ]:        746 :         if (strcmp(rtype, "tcpip-forward") == 0) {
    1127                 :            :                 struct passwd *pw;
    1128                 :            :                 char *listen_address;
    1129                 :            :                 u_short listen_port;
    1130                 :            : 
    1131                 :         33 :                 pw = the_authctxt->pw;
    1132 [ +  - ][ -  + ]:         33 :                 if (pw == NULL || !the_authctxt->valid)
    1133                 :          0 :                         fatal("server_input_global_request: no/invalid user");
    1134                 :         33 :                 listen_address = packet_get_string(NULL);
    1135                 :         33 :                 listen_port = (u_short)packet_get_int();
    1136                 :         33 :                 debug("server_input_global_request: tcpip-forward listen %s port %d",
    1137                 :            :                     listen_address, listen_port);
    1138                 :            : 
    1139                 :            :                 /* check permissions */
    1140 [ +  - ][ +  - ]:         33 :                 if ((options.allow_tcp_forwarding & FORWARD_REMOTE) == 0 ||
    1141         [ +  - ]:         33 :                     no_port_forwarding_flag ||
    1142                 :         33 :                     (!want_reply && listen_port == 0)
    1143                 :            : #ifndef NO_IPPORT_RESERVED_CONCEPT
    1144 [ -  + ][ #  # ]:         33 :                     || (listen_port != 0 && listen_port < IPPORT_RESERVED &&
    1145                 :          0 :                     pw->pw_uid != 0)
    1146                 :            : #endif
    1147                 :            :                     ) {
    1148                 :          0 :                         success = 0;
    1149                 :          0 :                         packet_send_debug("Server has disabled port forwarding.");
    1150                 :            :                 } else {
    1151                 :            :                         /* Start listening on the port */
    1152                 :         33 :                         success = channel_setup_remote_fwd_listener(
    1153                 :            :                             listen_address, listen_port,
    1154                 :            :                             &allocated_listen_port, options.gateway_ports);
    1155                 :            :                 }
    1156                 :         33 :                 free(listen_address);
    1157         [ -  + ]:        713 :         } else if (strcmp(rtype, "cancel-tcpip-forward") == 0) {
    1158                 :            :                 char *cancel_address;
    1159                 :            :                 u_short cancel_port;
    1160                 :            : 
    1161                 :          0 :                 cancel_address = packet_get_string(NULL);
    1162                 :          0 :                 cancel_port = (u_short)packet_get_int();
    1163                 :          0 :                 debug("%s: cancel-tcpip-forward addr %s port %d", __func__,
    1164                 :            :                     cancel_address, cancel_port);
    1165                 :            : 
    1166                 :          0 :                 success = channel_cancel_rport_listener(cancel_address,
    1167                 :            :                     cancel_port);
    1168                 :          0 :                 free(cancel_address);
    1169         [ +  - ]:        713 :         } else if (strcmp(rtype, "no-more-sessions@openssh.com") == 0) {
    1170                 :        713 :                 no_more_sessions = 1;
    1171                 :        713 :                 success = 1;
    1172                 :            :         }
    1173         [ +  + ]:        746 :         if (want_reply) {
    1174         [ +  + ]:         33 :                 packet_start(success ?
    1175                 :            :                     SSH2_MSG_REQUEST_SUCCESS : SSH2_MSG_REQUEST_FAILURE);
    1176 [ +  + ][ -  + ]:         33 :                 if (success && allocated_listen_port > 0)
    1177                 :          0 :                         packet_put_int(allocated_listen_port);
    1178                 :         33 :                 packet_send();
    1179                 :         33 :                 packet_write_wait();
    1180                 :            :         }
    1181                 :        746 :         free(rtype);
    1182                 :        746 : }
    1183                 :            : 
    1184                 :            : static void
    1185                 :        790 : server_input_channel_req(int type, u_int32_t seq, void *ctxt)
    1186                 :            : {
    1187                 :            :         Channel *c;
    1188                 :        790 :         int id, reply, success = 0;
    1189                 :            :         char *rtype;
    1190                 :            : 
    1191                 :        790 :         id = packet_get_int();
    1192                 :        790 :         rtype = packet_get_string(NULL);
    1193                 :        790 :         reply = packet_get_char();
    1194                 :            : 
    1195                 :        790 :         debug("server_input_channel_req: channel %d request %s reply %d",
    1196                 :            :             id, rtype, reply);
    1197                 :            : 
    1198         [ -  + ]:        790 :         if ((c = channel_lookup(id)) == NULL)
    1199                 :          0 :                 packet_disconnect("server_input_channel_req: "
    1200                 :            :                     "unknown channel %d", id);
    1201         [ -  + ]:        790 :         if (!strcmp(rtype, "eow@openssh.com")) {
    1202         [ #  # ]:          0 :                 packet_check_eom();
    1203                 :          0 :                 chan_rcvd_eow(c);
    1204         [ +  - ]:        790 :         } else if ((c->type == SSH_CHANNEL_LARVAL ||
    1205         [ +  - ]:        790 :             c->type == SSH_CHANNEL_OPEN) && strcmp(c->ctype, "session") == 0)
    1206                 :        790 :                 success = session_input_channel_req(c, rtype);
    1207         [ +  + ]:         77 :         if (reply) {
    1208         [ -  + ]:         15 :                 packet_start(success ?
    1209                 :            :                     SSH2_MSG_CHANNEL_SUCCESS : SSH2_MSG_CHANNEL_FAILURE);
    1210                 :         15 :                 packet_put_int(c->remote_id);
    1211                 :         15 :                 packet_send();
    1212                 :            :         }
    1213                 :         77 :         free(rtype);
    1214                 :         77 : }
    1215                 :            : 
    1216                 :            : static void
    1217                 :        716 : server_init_dispatch_20(void)
    1218                 :            : {
    1219                 :        716 :         debug("server_init_dispatch_20");
    1220                 :        716 :         dispatch_init(&dispatch_protocol_error);
    1221                 :        716 :         dispatch_set(SSH2_MSG_CHANNEL_CLOSE, &channel_input_oclose);
    1222                 :        716 :         dispatch_set(SSH2_MSG_CHANNEL_DATA, &channel_input_data);
    1223                 :        716 :         dispatch_set(SSH2_MSG_CHANNEL_EOF, &channel_input_ieof);
    1224                 :        716 :         dispatch_set(SSH2_MSG_CHANNEL_EXTENDED_DATA, &channel_input_extended_data);
    1225                 :        716 :         dispatch_set(SSH2_MSG_CHANNEL_OPEN, &server_input_channel_open);
    1226                 :        716 :         dispatch_set(SSH2_MSG_CHANNEL_OPEN_CONFIRMATION, &channel_input_open_confirmation);
    1227                 :        716 :         dispatch_set(SSH2_MSG_CHANNEL_OPEN_FAILURE, &channel_input_open_failure);
    1228                 :        716 :         dispatch_set(SSH2_MSG_CHANNEL_REQUEST, &server_input_channel_req);
    1229                 :        716 :         dispatch_set(SSH2_MSG_CHANNEL_WINDOW_ADJUST, &channel_input_window_adjust);
    1230                 :        716 :         dispatch_set(SSH2_MSG_GLOBAL_REQUEST, &server_input_global_request);
    1231                 :            :         /* client_alive */
    1232                 :        716 :         dispatch_set(SSH2_MSG_CHANNEL_SUCCESS, &server_input_keep_alive);
    1233                 :        716 :         dispatch_set(SSH2_MSG_CHANNEL_FAILURE, &server_input_keep_alive);
    1234                 :        716 :         dispatch_set(SSH2_MSG_REQUEST_SUCCESS, &server_input_keep_alive);
    1235                 :        716 :         dispatch_set(SSH2_MSG_REQUEST_FAILURE, &server_input_keep_alive);
    1236                 :            :         /* rekeying */
    1237                 :        716 :         dispatch_set(SSH2_MSG_KEXINIT, &kex_input_kexinit);
    1238                 :        716 : }
    1239                 :            : static void
    1240                 :         23 : server_init_dispatch_13(void)
    1241                 :            : {
    1242                 :         23 :         debug("server_init_dispatch_13");
    1243                 :         23 :         dispatch_init(NULL);
    1244                 :         23 :         dispatch_set(SSH_CMSG_EOF, &server_input_eof);
    1245                 :         23 :         dispatch_set(SSH_CMSG_STDIN_DATA, &server_input_stdin_data);
    1246                 :         23 :         dispatch_set(SSH_CMSG_WINDOW_SIZE, &server_input_window_size);
    1247                 :         23 :         dispatch_set(SSH_MSG_CHANNEL_CLOSE, &channel_input_close);
    1248                 :         23 :         dispatch_set(SSH_MSG_CHANNEL_CLOSE_CONFIRMATION, &channel_input_close_confirmation);
    1249                 :         23 :         dispatch_set(SSH_MSG_CHANNEL_DATA, &channel_input_data);
    1250                 :         23 :         dispatch_set(SSH_MSG_CHANNEL_OPEN_CONFIRMATION, &channel_input_open_confirmation);
    1251                 :         23 :         dispatch_set(SSH_MSG_CHANNEL_OPEN_FAILURE, &channel_input_open_failure);
    1252                 :         23 :         dispatch_set(SSH_MSG_PORT_OPEN, &channel_input_port_open);
    1253                 :         23 : }
    1254                 :            : static void
    1255                 :         23 : server_init_dispatch_15(void)
    1256                 :            : {
    1257                 :         23 :         server_init_dispatch_13();
    1258                 :         23 :         debug("server_init_dispatch_15");
    1259                 :         23 :         dispatch_set(SSH_MSG_CHANNEL_CLOSE, &channel_input_ieof);
    1260                 :         23 :         dispatch_set(SSH_MSG_CHANNEL_CLOSE_CONFIRMATION, &channel_input_oclose);
    1261                 :         23 : }
    1262                 :            : static void
    1263                 :        739 : server_init_dispatch(void)
    1264                 :            : {
    1265         [ +  + ]:        739 :         if (compat20)
    1266                 :        716 :                 server_init_dispatch_20();
    1267         [ -  + ]:         23 :         else if (compat13)
    1268                 :          0 :                 server_init_dispatch_13();
    1269                 :            :         else
    1270                 :         23 :                 server_init_dispatch_15();
    1271                 :        739 : }

Generated by: LCOV version 1.9