11305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* $OpenBSD: serverloop.c,v 1.160 2011/05/15 08:09:01 djm Exp $ */ 21305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* 31305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Author: Tatu Ylonen <ylo@cs.hut.fi> 41305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 51305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * All rights reserved 61305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Server main loop for handling the interactive session. 71305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * 81305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * As far as I am concerned, the code I have written for this software 91305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * can be used freely for any purpose. Any derived versions of this 101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * software must be clearly marked as such, and if the derived work is 111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * incompatible with the protocol description in the RFC file, it must be 121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * called by a name other than "ssh" or "Secure Shell". 131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * 141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * SSH2 support by Markus Friedl. 151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. 161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * 171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Redistribution and use in source and binary forms, with or without 181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * modification, are permitted provided that the following conditions 191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * are met: 201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * 1. Redistributions of source code must retain the above copyright 211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * notice, this list of conditions and the following disclaimer. 221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * 2. Redistributions in binary form must reproduce the above copyright 231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * notice, this list of conditions and the following disclaimer in the 241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * documentation and/or other materials provided with the distribution. 251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * 261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood */ 371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "includes.h" 391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <sys/types.h> 411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <sys/param.h> 421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <sys/wait.h> 431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <sys/socket.h> 441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifdef HAVE_SYS_TIME_H 451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood# include <sys/time.h> 461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif 471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <netinet/in.h> 491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <errno.h> 511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <fcntl.h> 521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <pwd.h> 531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <signal.h> 541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <string.h> 551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <termios.h> 561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <unistd.h> 571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <stdarg.h> 581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "openbsd-compat/sys-queue.h" 601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "xmalloc.h" 611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "packet.h" 621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "buffer.h" 631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "log.h" 641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "servconf.h" 651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "canohost.h" 661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "sshpty.h" 671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "channels.h" 681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "compat.h" 691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "ssh1.h" 701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "ssh2.h" 711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "key.h" 721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "cipher.h" 731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "kex.h" 741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "hostfile.h" 751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "auth.h" 761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "session.h" 771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "dispatch.h" 781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "auth-options.h" 791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "serverloop.h" 801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "misc.h" 811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "roaming.h" 821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodextern ServerOptions options; 841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* XXX */ 861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodextern Kex *xxx_kex; 871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodextern Authctxt *the_authctxt; 881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodextern int use_privsep; 891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic Buffer stdin_buffer; /* Buffer for stdin data. */ 911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic Buffer stdout_buffer; /* Buffer for stdout data. */ 921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic Buffer stderr_buffer; /* Buffer for stderr data. */ 931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic int fdin; /* Descriptor for stdin (for writing) */ 941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic int fdout; /* Descriptor for stdout (for reading); 951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood May be same number as fdin. */ 961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic int fderr; /* Descriptor for stderr. May be -1. */ 971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic long stdin_bytes = 0; /* Number of bytes written to stdin. */ 981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic long stdout_bytes = 0; /* Number of stdout bytes sent to client. */ 991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic long stderr_bytes = 0; /* Number of stderr bytes sent to client. */ 1001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic long fdout_bytes = 0; /* Number of stdout bytes read from program. */ 1011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic int stdin_eof = 0; /* EOF message received from client. */ 1021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic int fdout_eof = 0; /* EOF encountered reading from fdout. */ 1031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic int fderr_eof = 0; /* EOF encountered readung from fderr. */ 1041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic int fdin_is_tty = 0; /* fdin points to a tty. */ 1051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic int connection_in; /* Connection to client (input). */ 1061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic int connection_out; /* Connection to client (output). */ 1071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic int connection_closed = 0; /* Connection to client closed. */ 1081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic u_int buffer_high; /* "Soft" max buffer size. */ 1091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic int no_more_sessions = 0; /* Disallow further sessions. */ 1101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 1111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* 1121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * This SIGCHLD kludge is used to detect when the child exits. The server 1131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * will exit after that, as soon as forwarded connections have terminated. 1141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood */ 1151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 1161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic volatile sig_atomic_t child_terminated = 0; /* The child has terminated. */ 1171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 1181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* Cleanup on signals (!use_privsep case only) */ 1191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic volatile sig_atomic_t received_sigterm = 0; 1201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 1211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* prototypes */ 1221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic void server_init_dispatch(void); 1231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 1241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* 1251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * we write to this pipe if a SIGCHLD is caught in order to avoid 1261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * the race between select() and child_terminated 1271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood */ 1281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic int notify_pipe[2]; 1291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic void 1301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodnotify_setup(void) 1311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{ 1321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (pipe(notify_pipe) < 0) { 1331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood error("pipe(notify_pipe) failed %s", strerror(errno)); 1341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } else if ((fcntl(notify_pipe[0], F_SETFD, FD_CLOEXEC) == -1) || 1351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood (fcntl(notify_pipe[1], F_SETFD, FD_CLOEXEC) == -1)) { 1361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood error("fcntl(notify_pipe, F_SETFD) failed %s", strerror(errno)); 1371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood close(notify_pipe[0]); 1381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood close(notify_pipe[1]); 1391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } else { 1401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood set_nonblock(notify_pipe[0]); 1411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood set_nonblock(notify_pipe[1]); 1421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood return; 1431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 1441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood notify_pipe[0] = -1; /* read end */ 1451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood notify_pipe[1] = -1; /* write end */ 1461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood} 1471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic void 1481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodnotify_parent(void) 1491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{ 1501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (notify_pipe[1] != -1) 1511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood write(notify_pipe[1], "", 1); 1521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood} 1531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic void 1541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodnotify_prepare(fd_set *readset) 1551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{ 1561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (notify_pipe[0] != -1) 1571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood FD_SET(notify_pipe[0], readset); 1581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood} 1591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic void 1601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodnotify_done(fd_set *readset) 1611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{ 1621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood char c; 1631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 1641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (notify_pipe[0] != -1 && FD_ISSET(notify_pipe[0], readset)) 1651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood while (read(notify_pipe[0], &c, 1) != -1) 1661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood debug2("notify_done: reading"); 1671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood} 1681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 1691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/*ARGSUSED*/ 1701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic void 1711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodsigchld_handler(int sig) 1721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{ 1731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood int save_errno = errno; 1741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood child_terminated = 1; 1751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifndef _UNICOS 1761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood mysignal(SIGCHLD, sigchld_handler); 1771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif 1781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood notify_parent(); 1791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood errno = save_errno; 1801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood} 1811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 1821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/*ARGSUSED*/ 1831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic void 1841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodsigterm_handler(int sig) 1851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{ 1861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood received_sigterm = sig; 1871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood} 1881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 1891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* 1901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Make packets from buffered stderr data, and buffer it for sending 1911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * to the client. 1921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood */ 1931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic void 1941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodmake_packets_from_stderr_data(void) 1951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{ 1961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood u_int len; 1971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 1981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* Send buffered stderr data to the client. */ 1991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood while (buffer_len(&stderr_buffer) > 0 && 2001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood packet_not_very_much_data_to_write()) { 2011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood len = buffer_len(&stderr_buffer); 2021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (packet_is_interactive()) { 2031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (len > 512) 2041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood len = 512; 2051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } else { 2061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* Keep the packets at reasonable size. */ 2071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (len > packet_get_maxsize()) 2081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood len = packet_get_maxsize(); 2091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 2101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood packet_start(SSH_SMSG_STDERR_DATA); 2111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood packet_put_string(buffer_ptr(&stderr_buffer), len); 2121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood packet_send(); 2131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood buffer_consume(&stderr_buffer, len); 2141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood stderr_bytes += len; 2151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 2161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood} 2171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 2181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* 2191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Make packets from buffered stdout data, and buffer it for sending to the 2201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * client. 2211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood */ 2221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic void 2231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodmake_packets_from_stdout_data(void) 2241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{ 2251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood u_int len; 2261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 2271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* Send buffered stdout data to the client. */ 2281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood while (buffer_len(&stdout_buffer) > 0 && 2291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood packet_not_very_much_data_to_write()) { 2301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood len = buffer_len(&stdout_buffer); 2311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (packet_is_interactive()) { 2321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (len > 512) 2331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood len = 512; 2341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } else { 2351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* Keep the packets at reasonable size. */ 2361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (len > packet_get_maxsize()) 2371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood len = packet_get_maxsize(); 2381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 2391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood packet_start(SSH_SMSG_STDOUT_DATA); 2401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood packet_put_string(buffer_ptr(&stdout_buffer), len); 2411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood packet_send(); 2421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood buffer_consume(&stdout_buffer, len); 2431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood stdout_bytes += len; 2441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 2451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood} 2461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 2471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic void 2481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodclient_alive_check(void) 2491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{ 2501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood int channel_id; 2511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 2521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* timeout, check to see how many we have had */ 2531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (packet_inc_alive_timeouts() > options.client_alive_count_max) { 2541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood logit("Timeout, client not responding."); 2551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood cleanup_exit(255); 2561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 2571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 2581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* 2591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * send a bogus global/channel request with "wantreply", 2601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * we should get back a failure 2611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood */ 2621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if ((channel_id = channel_find_open()) == -1) { 2631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood packet_start(SSH2_MSG_GLOBAL_REQUEST); 2641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood packet_put_cstring("keepalive@openssh.com"); 2651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood packet_put_char(1); /* boolean: want reply */ 2661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } else { 2671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood channel_request_start(channel_id, "keepalive@openssh.com", 1); 2681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 2691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood packet_send(); 2701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood} 2711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 2721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* 2731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Sleep in select() until we can do something. This will initialize the 2741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * select masks. Upon return, the masks will indicate which descriptors 2751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * have data or can accept data. Optionally, a maximum time can be specified 2761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * for the duration of the wait (0 = infinite). 2771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood */ 2781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic void 2791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodwait_until_can_do_something(fd_set **readsetp, fd_set **writesetp, int *maxfdp, 2801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood u_int *nallocp, u_int max_time_milliseconds) 2811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{ 2821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood struct timeval tv, *tvp; 2831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood int ret; 2841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood int client_alive_scheduled = 0; 2851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood int program_alive_scheduled = 0; 2861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 2871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* 2881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * if using client_alive, set the max timeout accordingly, 2891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * and indicate that this particular timeout was for client 2901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * alive by setting the client_alive_scheduled flag. 2911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * 2921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * this could be randomized somewhat to make traffic 2931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * analysis more difficult, but we're not doing it yet. 2941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood */ 2951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (compat20 && 2961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood max_time_milliseconds == 0 && options.client_alive_interval) { 2971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood client_alive_scheduled = 1; 2981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood max_time_milliseconds = options.client_alive_interval * 1000; 2991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 3001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 3011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* Allocate and update select() masks for channel descriptors. */ 3021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood channel_prepare_select(readsetp, writesetp, maxfdp, nallocp, 0); 3031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 3041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (compat20) { 3051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#if 0 3061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* wrong: bad condition XXX */ 3071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (channel_not_very_much_buffered_data()) 3081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif 3091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood FD_SET(connection_in, *readsetp); 3101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } else { 3111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* 3121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Read packets from the client unless we have too much 3131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * buffered stdin or channel data. 3141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood */ 3151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (buffer_len(&stdin_buffer) < buffer_high && 3161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood channel_not_very_much_buffered_data()) 3171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood FD_SET(connection_in, *readsetp); 3181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* 3191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * If there is not too much data already buffered going to 3201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * the client, try to get some more data from the program. 3211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood */ 3221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (packet_not_very_much_data_to_write()) { 3231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood program_alive_scheduled = child_terminated; 3241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (!fdout_eof) 3251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood FD_SET(fdout, *readsetp); 3261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (!fderr_eof) 3271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood FD_SET(fderr, *readsetp); 3281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 3291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* 3301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * If we have buffered data, try to write some of that data 3311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * to the program. 3321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood */ 3331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (fdin != -1 && buffer_len(&stdin_buffer) > 0) 3341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood FD_SET(fdin, *writesetp); 3351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 3361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood notify_prepare(*readsetp); 3371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 3381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* 3391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * If we have buffered packet data going to the client, mark that 3401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * descriptor. 3411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood */ 3421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (packet_have_data_to_write()) 3431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood FD_SET(connection_out, *writesetp); 3441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 3451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* 3461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * If child has terminated and there is enough buffer space to read 3471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * from it, then read as much as is available and exit. 3481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood */ 3491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (child_terminated && packet_not_very_much_data_to_write()) 3501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (max_time_milliseconds == 0 || client_alive_scheduled) 3511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood max_time_milliseconds = 100; 3521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 3531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (max_time_milliseconds == 0) 3541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood tvp = NULL; 3551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood else { 3561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood tv.tv_sec = max_time_milliseconds / 1000; 3571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood tv.tv_usec = 1000 * (max_time_milliseconds % 1000); 3581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood tvp = &tv; 3591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 3601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 3611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* Wait for something to happen, or the timeout to expire. */ 3621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood ret = select((*maxfdp)+1, *readsetp, *writesetp, NULL, tvp); 3631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 3641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (ret == -1) { 3651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood memset(*readsetp, 0, *nallocp); 3661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood memset(*writesetp, 0, *nallocp); 3671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (errno != EINTR) 3681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood error("select: %.100s", strerror(errno)); 3691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } else { 3701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (ret == 0 && client_alive_scheduled) 3711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood client_alive_check(); 3721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (!compat20 && program_alive_scheduled && fdin_is_tty) { 3731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (!fdout_eof) 3741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood FD_SET(fdout, *readsetp); 3751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (!fderr_eof) 3761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood FD_SET(fderr, *readsetp); 3771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 3781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 3791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 3801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood notify_done(*readsetp); 3811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood} 3821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 3831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* 3841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Processes input from the client and the program. Input data is stored 3851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * in buffers and processed later. 3861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood */ 3871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic void 3881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodprocess_input(fd_set *readset) 3891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{ 3901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood int len; 3911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood char buf[16384]; 3921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 3931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* Read and buffer any input data from the client. */ 3941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (FD_ISSET(connection_in, readset)) { 3951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood int cont = 0; 3961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood len = roaming_read(connection_in, buf, sizeof(buf), &cont); 3971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (len == 0) { 3981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (cont) 3991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood return; 4001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood verbose("Connection closed by %.100s", 4011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood get_remote_ipaddr()); 4021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood connection_closed = 1; 4031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (compat20) 4041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood return; 4051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood cleanup_exit(255); 4061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } else if (len < 0) { 4071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (errno != EINTR && errno != EAGAIN && 4081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood errno != EWOULDBLOCK) { 4091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood verbose("Read error from remote host " 4101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood "%.100s: %.100s", 4111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood get_remote_ipaddr(), strerror(errno)); 4121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood cleanup_exit(255); 4131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 4141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } else { 4151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* Buffer any received data. */ 4161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood packet_process_incoming(buf, len); 4171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 4181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 4191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (compat20) 4201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood return; 4211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 4221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* Read and buffer any available stdout data from the program. */ 4231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (!fdout_eof && FD_ISSET(fdout, readset)) { 4241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood errno = 0; 4251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood len = read(fdout, buf, sizeof(buf)); 4261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (len < 0 && (errno == EINTR || ((errno == EAGAIN || 4271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood errno == EWOULDBLOCK) && !child_terminated))) { 4281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* do nothing */ 4291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifndef PTY_ZEROREAD 4301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } else if (len <= 0) { 4311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#else 4321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } else if ((!isatty(fdout) && len <= 0) || 4331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood (isatty(fdout) && (len < 0 || (len == 0 && errno != 0)))) { 4341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif 4351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood fdout_eof = 1; 4361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } else { 4371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood buffer_append(&stdout_buffer, buf, len); 4381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood fdout_bytes += len; 4391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 4401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 4411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* Read and buffer any available stderr data from the program. */ 4421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (!fderr_eof && FD_ISSET(fderr, readset)) { 4431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood errno = 0; 4441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood len = read(fderr, buf, sizeof(buf)); 4451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (len < 0 && (errno == EINTR || ((errno == EAGAIN || 4461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood errno == EWOULDBLOCK) && !child_terminated))) { 4471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* do nothing */ 4481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifndef PTY_ZEROREAD 4491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } else if (len <= 0) { 4501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#else 4511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } else if ((!isatty(fderr) && len <= 0) || 4521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood (isatty(fderr) && (len < 0 || (len == 0 && errno != 0)))) { 4531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif 4541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood fderr_eof = 1; 4551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } else { 4561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood buffer_append(&stderr_buffer, buf, len); 4571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 4581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 4591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood} 4601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 4611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* 4621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Sends data from internal buffers to client program stdin. 4631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood */ 4641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic void 4651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodprocess_output(fd_set *writeset) 4661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{ 4671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood struct termios tio; 4681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood u_char *data; 4691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood u_int dlen; 4701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood int len; 4711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 4721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* Write buffered data to program stdin. */ 4731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (!compat20 && fdin != -1 && FD_ISSET(fdin, writeset)) { 4741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood data = buffer_ptr(&stdin_buffer); 4751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood dlen = buffer_len(&stdin_buffer); 4761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood len = write(fdin, data, dlen); 4771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (len < 0 && 4781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK)) { 4791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* do nothing */ 4801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } else if (len <= 0) { 4811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (fdin != fdout) 4821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood close(fdin); 4831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood else 4841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood shutdown(fdin, SHUT_WR); /* We will no longer send. */ 4851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood fdin = -1; 4861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } else { 4871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* Successful write. */ 4881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (fdin_is_tty && dlen >= 1 && data[0] != '\r' && 4891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood tcgetattr(fdin, &tio) == 0 && 4901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood !(tio.c_lflag & ECHO) && (tio.c_lflag & ICANON)) { 4911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* 4921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Simulate echo to reduce the impact of 4931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * traffic analysis 4941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood */ 4951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood packet_send_ignore(len); 4961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood packet_send(); 4971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 4981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* Consume the data from the buffer. */ 4991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood buffer_consume(&stdin_buffer, len); 5001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* Update the count of bytes written to the program. */ 5011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood stdin_bytes += len; 5021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 5031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 5041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* Send any buffered packet data to the client. */ 5051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (FD_ISSET(connection_out, writeset)) 5061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood packet_write_poll(); 5071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood} 5081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 5091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* 5101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Wait until all buffered output has been sent to the client. 5111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * This is used when the program terminates. 5121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood */ 5131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic void 5141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwooddrain_output(void) 5151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{ 5161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* Send any buffered stdout data to the client. */ 5171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (buffer_len(&stdout_buffer) > 0) { 5181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood packet_start(SSH_SMSG_STDOUT_DATA); 5191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood packet_put_string(buffer_ptr(&stdout_buffer), 5201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood buffer_len(&stdout_buffer)); 5211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood packet_send(); 5221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* Update the count of sent bytes. */ 5231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood stdout_bytes += buffer_len(&stdout_buffer); 5241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 5251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* Send any buffered stderr data to the client. */ 5261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (buffer_len(&stderr_buffer) > 0) { 5271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood packet_start(SSH_SMSG_STDERR_DATA); 5281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood packet_put_string(buffer_ptr(&stderr_buffer), 5291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood buffer_len(&stderr_buffer)); 5301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood packet_send(); 5311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* Update the count of sent bytes. */ 5321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood stderr_bytes += buffer_len(&stderr_buffer); 5331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 5341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* Wait until all buffered data has been written to the client. */ 5351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood packet_write_wait(); 5361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood} 5371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 5381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic void 5391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodprocess_buffered_input_packets(void) 5401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{ 5411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood dispatch_run(DISPATCH_NONBLOCK, NULL, compat20 ? xxx_kex : NULL); 5421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood} 5431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 5441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* 5451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Performs the interactive session. This handles data transmission between 5461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * the client and the program. Note that the notion of stdin, stdout, and 5471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * stderr in this function is sort of reversed: this function writes to 5481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * stdin (of the child program), and reads from stdout and stderr (of the 5491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * child program). 5501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood */ 5511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodvoid 5521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodserver_loop(pid_t pid, int fdin_arg, int fdout_arg, int fderr_arg) 5531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{ 5541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood fd_set *readset = NULL, *writeset = NULL; 5551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood int max_fd = 0; 5561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood u_int nalloc = 0; 5571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood int wait_status; /* Status returned by wait(). */ 5581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood pid_t wait_pid; /* pid returned by wait(). */ 5591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood int waiting_termination = 0; /* Have displayed waiting close message. */ 5601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood u_int max_time_milliseconds; 5611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood u_int previous_stdout_buffer_bytes; 5621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood u_int stdout_buffer_bytes; 5631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood int type; 5641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 5651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood debug("Entering interactive session."); 5661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 5671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* Initialize the SIGCHLD kludge. */ 5681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood child_terminated = 0; 5691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood mysignal(SIGCHLD, sigchld_handler); 5701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 5711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (!use_privsep) { 5721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood signal(SIGTERM, sigterm_handler); 5731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood signal(SIGINT, sigterm_handler); 5741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood signal(SIGQUIT, sigterm_handler); 5751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 5761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 5771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* Initialize our global variables. */ 5781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood fdin = fdin_arg; 5791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood fdout = fdout_arg; 5801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood fderr = fderr_arg; 5811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 5821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* nonblocking IO */ 5831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood set_nonblock(fdin); 5841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood set_nonblock(fdout); 5851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* we don't have stderr for interactive terminal sessions, see below */ 5861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (fderr != -1) 5871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood set_nonblock(fderr); 5881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 5891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (!(datafellows & SSH_BUG_IGNOREMSG) && isatty(fdin)) 5901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood fdin_is_tty = 1; 5911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 5921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood connection_in = packet_get_connection_in(); 5931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood connection_out = packet_get_connection_out(); 5941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 5951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood notify_setup(); 5961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 5971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood previous_stdout_buffer_bytes = 0; 5981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 5991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* Set approximate I/O buffer size. */ 6001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (packet_is_interactive()) 6011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood buffer_high = 4096; 6021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood else 6031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood buffer_high = 64 * 1024; 6041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 6051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#if 0 6061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* Initialize max_fd to the maximum of the known file descriptors. */ 6071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood max_fd = MAX(connection_in, connection_out); 6081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood max_fd = MAX(max_fd, fdin); 6091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood max_fd = MAX(max_fd, fdout); 6101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (fderr != -1) 6111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood max_fd = MAX(max_fd, fderr); 6121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif 6131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 6141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* Initialize Initialize buffers. */ 6151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood buffer_init(&stdin_buffer); 6161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood buffer_init(&stdout_buffer); 6171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood buffer_init(&stderr_buffer); 6181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 6191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* 6201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * If we have no separate fderr (which is the case when we have a pty 6211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * - there we cannot make difference between data sent to stdout and 6221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * stderr), indicate that we have seen an EOF from stderr. This way 6231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * we don't need to check the descriptor everywhere. 6241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood */ 6251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (fderr == -1) 6261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood fderr_eof = 1; 6271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 6281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood server_init_dispatch(); 6291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 6301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* Main loop of the server for the interactive session mode. */ 6311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood for (;;) { 6321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 6331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* Process buffered packets from the client. */ 6341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood process_buffered_input_packets(); 6351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 6361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* 6371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * If we have received eof, and there is no more pending 6381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * input data, cause a real eof by closing fdin. 6391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood */ 6401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (stdin_eof && fdin != -1 && buffer_len(&stdin_buffer) == 0) { 6411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (fdin != fdout) 6421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood close(fdin); 6431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood else 6441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood shutdown(fdin, SHUT_WR); /* We will no longer send. */ 6451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood fdin = -1; 6461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 6471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* Make packets from buffered stderr data to send to the client. */ 6481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood make_packets_from_stderr_data(); 6491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 6501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* 6511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Make packets from buffered stdout data to send to the 6521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * client. If there is very little to send, this arranges to 6531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * not send them now, but to wait a short while to see if we 6541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * are getting more data. This is necessary, as some systems 6551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * wake up readers from a pty after each separate character. 6561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood */ 6571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood max_time_milliseconds = 0; 6581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood stdout_buffer_bytes = buffer_len(&stdout_buffer); 6591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (stdout_buffer_bytes != 0 && stdout_buffer_bytes < 256 && 6601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood stdout_buffer_bytes != previous_stdout_buffer_bytes) { 6611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* try again after a while */ 6621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood max_time_milliseconds = 10; 6631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } else { 6641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* Send it now. */ 6651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood make_packets_from_stdout_data(); 6661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 6671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood previous_stdout_buffer_bytes = buffer_len(&stdout_buffer); 6681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 6691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* Send channel data to the client. */ 6701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (packet_not_very_much_data_to_write()) 6711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood channel_output_poll(); 6721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 6731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* 6741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Bail out of the loop if the program has closed its output 6751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * descriptors, and we have no more data to send to the 6761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * client, and there is no pending buffered data. 6771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood */ 6781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (fdout_eof && fderr_eof && !packet_have_data_to_write() && 6791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood buffer_len(&stdout_buffer) == 0 && buffer_len(&stderr_buffer) == 0) { 6801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (!channel_still_open()) 6811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood break; 6821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (!waiting_termination) { 6831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood const char *s = "Waiting for forwarded connections to terminate...\r\n"; 6841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood char *cp; 6851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood waiting_termination = 1; 6861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood buffer_append(&stderr_buffer, s, strlen(s)); 6871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 6881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* Display list of open channels. */ 6891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood cp = channel_open_message(); 6901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood buffer_append(&stderr_buffer, cp, strlen(cp)); 6911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood xfree(cp); 6921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 6931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 6941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood max_fd = MAX(connection_in, connection_out); 6951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood max_fd = MAX(max_fd, fdin); 6961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood max_fd = MAX(max_fd, fdout); 6971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood max_fd = MAX(max_fd, fderr); 6981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood max_fd = MAX(max_fd, notify_pipe[0]); 6991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 7001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* Sleep in select() until we can do something. */ 7011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood wait_until_can_do_something(&readset, &writeset, &max_fd, 7021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood &nalloc, max_time_milliseconds); 7031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 7041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (received_sigterm) { 7051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood logit("Exiting on signal %d", received_sigterm); 7061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* Clean up sessions, utmp, etc. */ 7071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood cleanup_exit(255); 7081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 7091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 7101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* Process any channel events. */ 7111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood channel_after_select(readset, writeset); 7121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 7131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* Process input from the client and from program stdout/stderr. */ 7141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood process_input(readset); 7151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 7161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* Process output to the client and to program stdin. */ 7171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood process_output(writeset); 7181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 7191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (readset) 7201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood xfree(readset); 7211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (writeset) 7221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood xfree(writeset); 7231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 7241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* Cleanup and termination code. */ 7251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 7261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* Wait until all output has been sent to the client. */ 7271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood drain_output(); 7281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 7291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood debug("End of interactive session; stdin %ld, stdout (read %ld, sent %ld), stderr %ld bytes.", 7301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood stdin_bytes, fdout_bytes, stdout_bytes, stderr_bytes); 7311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 7321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* Free and clear the buffers. */ 7331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood buffer_free(&stdin_buffer); 7341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood buffer_free(&stdout_buffer); 7351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood buffer_free(&stderr_buffer); 7361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 7371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* Close the file descriptors. */ 7381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (fdout != -1) 7391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood close(fdout); 7401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood fdout = -1; 7411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood fdout_eof = 1; 7421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (fderr != -1) 7431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood close(fderr); 7441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood fderr = -1; 7451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood fderr_eof = 1; 7461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (fdin != -1) 7471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood close(fdin); 7481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood fdin = -1; 7491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 7501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood channel_free_all(); 7511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 7521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* We no longer want our SIGCHLD handler to be called. */ 7531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood mysignal(SIGCHLD, SIG_DFL); 7541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 7551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood while ((wait_pid = waitpid(-1, &wait_status, 0)) < 0) 7561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (errno != EINTR) 7571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood packet_disconnect("wait: %.100s", strerror(errno)); 7581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (wait_pid != pid) 7591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood error("Strange, wait returned pid %ld, expected %ld", 7601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood (long)wait_pid, (long)pid); 7611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 7621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* Check if it exited normally. */ 7631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (WIFEXITED(wait_status)) { 7641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* Yes, normal exit. Get exit status and send it to the client. */ 7651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood debug("Command exited with status %d.", WEXITSTATUS(wait_status)); 7661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood packet_start(SSH_SMSG_EXITSTATUS); 7671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood packet_put_int(WEXITSTATUS(wait_status)); 7681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood packet_send(); 7691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood packet_write_wait(); 7701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 7711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* 7721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Wait for exit confirmation. Note that there might be 7731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * other packets coming before it; however, the program has 7741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * already died so we just ignore them. The client is 7751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * supposed to respond with the confirmation when it receives 7761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * the exit status. 7771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood */ 7781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood do { 7791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood type = packet_read(); 7801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 7811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood while (type != SSH_CMSG_EXIT_CONFIRMATION); 7821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 7831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood debug("Received exit confirmation."); 7841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood return; 7851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 7861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* Check if the program terminated due to a signal. */ 7871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (WIFSIGNALED(wait_status)) 7881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood packet_disconnect("Command terminated on signal %d.", 7891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood WTERMSIG(wait_status)); 7901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 7911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* Some weird exit cause. Just exit. */ 7921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood packet_disconnect("wait returned status %04x.", wait_status); 7931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* NOTREACHED */ 7941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood} 7951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 7961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic void 7971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodcollect_children(void) 7981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{ 7991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood pid_t pid; 8001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood sigset_t oset, nset; 8011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood int status; 8021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 8031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* block SIGCHLD while we check for dead children */ 8041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood sigemptyset(&nset); 8051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood sigaddset(&nset, SIGCHLD); 8061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood sigprocmask(SIG_BLOCK, &nset, &oset); 8071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (child_terminated) { 8081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood debug("Received SIGCHLD."); 8091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood while ((pid = waitpid(-1, &status, WNOHANG)) > 0 || 8101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood (pid < 0 && errno == EINTR)) 8111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (pid > 0) 8121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood session_close_by_pid(pid, status); 8131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood child_terminated = 0; 8141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 8151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood sigprocmask(SIG_SETMASK, &oset, NULL); 8161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood} 8171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 8181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodvoid 8191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodserver_loop2(Authctxt *authctxt) 8201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{ 8211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood fd_set *readset = NULL, *writeset = NULL; 8221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood int rekeying = 0, max_fd, nalloc = 0; 8231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 8241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood debug("Entering interactive session for SSH2."); 8251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 8261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood mysignal(SIGCHLD, sigchld_handler); 8271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood child_terminated = 0; 8281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood connection_in = packet_get_connection_in(); 8291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood connection_out = packet_get_connection_out(); 8301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 8311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (!use_privsep) { 8321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood signal(SIGTERM, sigterm_handler); 8331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood signal(SIGINT, sigterm_handler); 8341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood signal(SIGQUIT, sigterm_handler); 8351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 8361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 8371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood notify_setup(); 8381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 8391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood max_fd = MAX(connection_in, connection_out); 8401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood max_fd = MAX(max_fd, notify_pipe[0]); 8411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 8421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood server_init_dispatch(); 8431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 8441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood for (;;) { 8451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood process_buffered_input_packets(); 8461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 8471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood rekeying = (xxx_kex != NULL && !xxx_kex->done); 8481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 8491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (!rekeying && packet_not_very_much_data_to_write()) 8501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood channel_output_poll(); 8511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood wait_until_can_do_something(&readset, &writeset, &max_fd, 8521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood &nalloc, 0); 8531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 8541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (received_sigterm) { 8551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood logit("Exiting on signal %d", received_sigterm); 8561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* Clean up sessions, utmp, etc. */ 8571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood cleanup_exit(255); 8581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 8591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 8601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood collect_children(); 8611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (!rekeying) { 8621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood channel_after_select(readset, writeset); 8631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (packet_need_rekeying()) { 8641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood debug("need rekeying"); 8651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood xxx_kex->done = 0; 8661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood kex_send_kexinit(xxx_kex); 8671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 8681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 8691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood process_input(readset); 8701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (connection_closed) 8711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood break; 8721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood process_output(writeset); 8731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 8741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood collect_children(); 8751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 8761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (readset) 8771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood xfree(readset); 8781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (writeset) 8791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood xfree(writeset); 8801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 8811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* free all channels, no more reads and writes */ 8821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood channel_free_all(); 8831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 8841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* free remaining sessions, e.g. remove wtmp entries */ 8851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood session_destroy_all(NULL); 8861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood} 8871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 8881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic void 8891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodserver_input_keep_alive(int type, u_int32_t seq, void *ctxt) 8901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{ 8911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood debug("Got %d/%u for keepalive", type, seq); 8921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* 8931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * reset timeout, since we got a sane answer from the client. 8941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * even if this was generated by something other than 8951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * the bogus CHANNEL_REQUEST we send for keepalives. 8961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood */ 8971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood packet_set_alive_timeouts(0); 8981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood} 8991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 9001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic void 9011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodserver_input_stdin_data(int type, u_int32_t seq, void *ctxt) 9021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{ 9031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood char *data; 9041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood u_int data_len; 9051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 9061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* Stdin data from the client. Append it to the buffer. */ 9071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* Ignore any data if the client has closed stdin. */ 9081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (fdin == -1) 9091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood return; 9101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood data = packet_get_string(&data_len); 9111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood packet_check_eom(); 9121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood buffer_append(&stdin_buffer, data, data_len); 9131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood memset(data, 0, data_len); 9141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood xfree(data); 9151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood} 9161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 9171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic void 9181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodserver_input_eof(int type, u_int32_t seq, void *ctxt) 9191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{ 9201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* 9211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Eof from the client. The stdin descriptor to the 9221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * program will be closed when all buffered data has 9231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * drained. 9241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood */ 9251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood debug("EOF received for stdin."); 9261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood packet_check_eom(); 9271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood stdin_eof = 1; 9281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood} 9291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 9301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic void 9311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodserver_input_window_size(int type, u_int32_t seq, void *ctxt) 9321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{ 9331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood u_int row = packet_get_int(); 9341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood u_int col = packet_get_int(); 9351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood u_int xpixel = packet_get_int(); 9361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood u_int ypixel = packet_get_int(); 9371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 9381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood debug("Window change received."); 9391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood packet_check_eom(); 9401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (fdin != -1) 9411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood pty_change_window_size(fdin, row, col, xpixel, ypixel); 9421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood} 9431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 9441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic Channel * 9451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodserver_request_direct_tcpip(void) 9461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{ 9471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood Channel *c; 9481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood char *target, *originator; 9491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood u_short target_port, originator_port; 9501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 9511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood target = packet_get_string(NULL); 9521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood target_port = packet_get_int(); 9531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood originator = packet_get_string(NULL); 9541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood originator_port = packet_get_int(); 9551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood packet_check_eom(); 9561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 9571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood debug("server_request_direct_tcpip: originator %s port %d, target %s " 9581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood "port %d", originator, originator_port, target, target_port); 9591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 9601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* XXX check permission */ 9611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood c = channel_connect_to(target, target_port, 9621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood "direct-tcpip", "direct-tcpip"); 9631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 9641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood xfree(originator); 9651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood xfree(target); 9661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 9671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood return c; 9681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood} 9691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 9701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic Channel * 9711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodserver_request_tun(void) 9721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{ 9731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood Channel *c = NULL; 9741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood int mode, tun; 9751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood int sock; 9761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 9771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood mode = packet_get_int(); 9781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood switch (mode) { 9791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood case SSH_TUNMODE_POINTOPOINT: 9801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood case SSH_TUNMODE_ETHERNET: 9811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood break; 9821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood default: 9831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood packet_send_debug("Unsupported tunnel device mode."); 9841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood return NULL; 9851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 9861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if ((options.permit_tun & mode) == 0) { 9871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood packet_send_debug("Server has rejected tunnel device " 9881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood "forwarding"); 9891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood return NULL; 9901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 9911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 9921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood tun = packet_get_int(); 9931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (forced_tun_device != -1) { 9941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (tun != SSH_TUNID_ANY && forced_tun_device != tun) 9951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood goto done; 9961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood tun = forced_tun_device; 9971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 9981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood sock = tun_open(tun, mode); 9991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (sock < 0) 10001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood goto done; 10011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood c = channel_new("tun", SSH_CHANNEL_OPEN, sock, sock, -1, 10021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, 0, "tun", 1); 10031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood c->datagram = 1; 10041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#if defined(SSH_TUN_FILTER) 10051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (mode == SSH_TUNMODE_POINTOPOINT) 10061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood channel_register_filter(c->self, sys_tun_infilter, 10071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood sys_tun_outfilter, NULL, NULL); 10081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif 10091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 10101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood done: 10111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (c == NULL) 10121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood packet_send_debug("Failed to open the tunnel device."); 10131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood return c; 10141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood} 10151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 10161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic Channel * 10171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodserver_request_session(void) 10181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{ 10191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood Channel *c; 10201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 10211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood debug("input_session_request"); 10221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood packet_check_eom(); 10231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 10241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (no_more_sessions) { 10251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood packet_disconnect("Possible attack: attempt to open a session " 10261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood "after additional sessions disabled"); 10271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 10281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 10291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* 10301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * A server session has no fd to read or write until a 10311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * CHANNEL_REQUEST for a shell is made, so we set the type to 10321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * SSH_CHANNEL_LARVAL. Additionally, a callback for handling all 10331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * CHANNEL_REQUEST messages is registered. 10341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood */ 10351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood c = channel_new("session", SSH_CHANNEL_LARVAL, 10361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood -1, -1, -1, /*window size*/0, CHAN_SES_PACKET_DEFAULT, 10371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 0, "server-session", 1); 10381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (session_open(the_authctxt, c->self) != 1) { 10391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood debug("session open failed, free channel %d", c->self); 10401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood channel_free(c); 10411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood return NULL; 10421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 10431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood channel_register_cleanup(c->self, session_close_by_channel, 0); 10441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood return c; 10451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood} 10461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 10471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic void 10481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodserver_input_channel_open(int type, u_int32_t seq, void *ctxt) 10491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{ 10501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood Channel *c = NULL; 10511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood char *ctype; 10521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood int rchan; 10531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood u_int rmaxpack, rwindow, len; 10541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 10551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood ctype = packet_get_string(&len); 10561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood rchan = packet_get_int(); 10571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood rwindow = packet_get_int(); 10581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood rmaxpack = packet_get_int(); 10591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 10601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood debug("server_input_channel_open: ctype %s rchan %d win %d max %d", 10611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood ctype, rchan, rwindow, rmaxpack); 10621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 10631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (strcmp(ctype, "session") == 0) { 10641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood c = server_request_session(); 10651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } else if (strcmp(ctype, "direct-tcpip") == 0) { 10661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood c = server_request_direct_tcpip(); 10671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } else if (strcmp(ctype, "tun@openssh.com") == 0) { 10681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood c = server_request_tun(); 10691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 10701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (c != NULL) { 10711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood debug("server_input_channel_open: confirm %s", ctype); 10721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood c->remote_id = rchan; 10731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood c->remote_window = rwindow; 10741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood c->remote_maxpacket = rmaxpack; 10751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (c->type != SSH_CHANNEL_CONNECTING) { 10761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood packet_start(SSH2_MSG_CHANNEL_OPEN_CONFIRMATION); 10771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood packet_put_int(c->remote_id); 10781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood packet_put_int(c->self); 10791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood packet_put_int(c->local_window); 10801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood packet_put_int(c->local_maxpacket); 10811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood packet_send(); 10821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 10831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } else { 10841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood debug("server_input_channel_open: failure %s", ctype); 10851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood packet_start(SSH2_MSG_CHANNEL_OPEN_FAILURE); 10861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood packet_put_int(rchan); 10871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood packet_put_int(SSH2_OPEN_ADMINISTRATIVELY_PROHIBITED); 10881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (!(datafellows & SSH_BUG_OPENFAILURE)) { 10891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood packet_put_cstring("open failed"); 10901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood packet_put_cstring(""); 10911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 10921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood packet_send(); 10931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 10941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood xfree(ctype); 10951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood} 10961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 10971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic void 10981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodserver_input_global_request(int type, u_int32_t seq, void *ctxt) 10991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{ 11001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood char *rtype; 11011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood int want_reply; 11021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood int success = 0, allocated_listen_port = 0; 11031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 11041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood rtype = packet_get_string(NULL); 11051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood want_reply = packet_get_char(); 11061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood debug("server_input_global_request: rtype %s want_reply %d", rtype, want_reply); 11071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 11081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* -R style forwarding */ 11091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (strcmp(rtype, "tcpip-forward") == 0) { 11101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood struct passwd *pw; 11111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood char *listen_address; 11121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood u_short listen_port; 11131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 11141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood pw = the_authctxt->pw; 11151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (pw == NULL || !the_authctxt->valid) 11161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood fatal("server_input_global_request: no/invalid user"); 11171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood listen_address = packet_get_string(NULL); 11181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood listen_port = (u_short)packet_get_int(); 11191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood debug("server_input_global_request: tcpip-forward listen %s port %d", 11201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood listen_address, listen_port); 11211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 11221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* check permissions */ 11231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (!options.allow_tcp_forwarding || 11241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood no_port_forwarding_flag || 11251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood (!want_reply && listen_port == 0) 11261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifndef NO_IPPORT_RESERVED_CONCEPT 11271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood || (listen_port != 0 && listen_port < IPPORT_RESERVED && 11281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood pw->pw_uid != 0) 11291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif 11301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood ) { 11311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood success = 0; 11321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood packet_send_debug("Server has disabled port forwarding."); 11331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } else { 11341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* Start listening on the port */ 11351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood success = channel_setup_remote_fwd_listener( 11361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood listen_address, listen_port, 11371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood &allocated_listen_port, options.gateway_ports); 11381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 11391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood xfree(listen_address); 11401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } else if (strcmp(rtype, "cancel-tcpip-forward") == 0) { 11411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood char *cancel_address; 11421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood u_short cancel_port; 11431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 11441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood cancel_address = packet_get_string(NULL); 11451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood cancel_port = (u_short)packet_get_int(); 11461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood debug("%s: cancel-tcpip-forward addr %s port %d", __func__, 11471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood cancel_address, cancel_port); 11481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 11491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood success = channel_cancel_rport_listener(cancel_address, 11501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood cancel_port); 11511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood xfree(cancel_address); 11521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } else if (strcmp(rtype, "no-more-sessions@openssh.com") == 0) { 11531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood no_more_sessions = 1; 11541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood success = 1; 11551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 11561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (want_reply) { 11571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood packet_start(success ? 11581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood SSH2_MSG_REQUEST_SUCCESS : SSH2_MSG_REQUEST_FAILURE); 11591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (success && allocated_listen_port > 0) 11601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood packet_put_int(allocated_listen_port); 11611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood packet_send(); 11621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood packet_write_wait(); 11631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 11641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood xfree(rtype); 11651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood} 11661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 11671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic void 11681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodserver_input_channel_req(int type, u_int32_t seq, void *ctxt) 11691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{ 11701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood Channel *c; 11711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood int id, reply, success = 0; 11721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood char *rtype; 11731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 11741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood id = packet_get_int(); 11751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood rtype = packet_get_string(NULL); 11761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood reply = packet_get_char(); 11771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 11781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood debug("server_input_channel_req: channel %d request %s reply %d", 11791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood id, rtype, reply); 11801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 11811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if ((c = channel_lookup(id)) == NULL) 11821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood packet_disconnect("server_input_channel_req: " 11831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood "unknown channel %d", id); 11841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (!strcmp(rtype, "eow@openssh.com")) { 11851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood packet_check_eom(); 11861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood chan_rcvd_eow(c); 11871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } else if ((c->type == SSH_CHANNEL_LARVAL || 11881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood c->type == SSH_CHANNEL_OPEN) && strcmp(c->ctype, "session") == 0) 11891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood success = session_input_channel_req(c, rtype); 11901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (reply) { 11911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood packet_start(success ? 11921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood SSH2_MSG_CHANNEL_SUCCESS : SSH2_MSG_CHANNEL_FAILURE); 11931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood packet_put_int(c->remote_id); 11941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood packet_send(); 11951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 11961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood xfree(rtype); 11971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood} 11981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 11991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic void 12001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodserver_init_dispatch_20(void) 12011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{ 12021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood debug("server_init_dispatch_20"); 12031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood dispatch_init(&dispatch_protocol_error); 12041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood dispatch_set(SSH2_MSG_CHANNEL_CLOSE, &channel_input_oclose); 12051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood dispatch_set(SSH2_MSG_CHANNEL_DATA, &channel_input_data); 12061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood dispatch_set(SSH2_MSG_CHANNEL_EOF, &channel_input_ieof); 12071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood dispatch_set(SSH2_MSG_CHANNEL_EXTENDED_DATA, &channel_input_extended_data); 12081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood dispatch_set(SSH2_MSG_CHANNEL_OPEN, &server_input_channel_open); 12091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood dispatch_set(SSH2_MSG_CHANNEL_OPEN_CONFIRMATION, &channel_input_open_confirmation); 12101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood dispatch_set(SSH2_MSG_CHANNEL_OPEN_FAILURE, &channel_input_open_failure); 12111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood dispatch_set(SSH2_MSG_CHANNEL_REQUEST, &server_input_channel_req); 12121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood dispatch_set(SSH2_MSG_CHANNEL_WINDOW_ADJUST, &channel_input_window_adjust); 12131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood dispatch_set(SSH2_MSG_GLOBAL_REQUEST, &server_input_global_request); 12141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* client_alive */ 12151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood dispatch_set(SSH2_MSG_CHANNEL_SUCCESS, &server_input_keep_alive); 12161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood dispatch_set(SSH2_MSG_CHANNEL_FAILURE, &server_input_keep_alive); 12171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood dispatch_set(SSH2_MSG_REQUEST_SUCCESS, &server_input_keep_alive); 12181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood dispatch_set(SSH2_MSG_REQUEST_FAILURE, &server_input_keep_alive); 12191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* rekeying */ 12201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood dispatch_set(SSH2_MSG_KEXINIT, &kex_input_kexinit); 12211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood} 12221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic void 12231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodserver_init_dispatch_13(void) 12241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{ 12251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood debug("server_init_dispatch_13"); 12261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood dispatch_init(NULL); 12271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood dispatch_set(SSH_CMSG_EOF, &server_input_eof); 12281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood dispatch_set(SSH_CMSG_STDIN_DATA, &server_input_stdin_data); 12291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood dispatch_set(SSH_CMSG_WINDOW_SIZE, &server_input_window_size); 12301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood dispatch_set(SSH_MSG_CHANNEL_CLOSE, &channel_input_close); 12311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood dispatch_set(SSH_MSG_CHANNEL_CLOSE_CONFIRMATION, &channel_input_close_confirmation); 12321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood dispatch_set(SSH_MSG_CHANNEL_DATA, &channel_input_data); 12331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood dispatch_set(SSH_MSG_CHANNEL_OPEN_CONFIRMATION, &channel_input_open_confirmation); 12341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood dispatch_set(SSH_MSG_CHANNEL_OPEN_FAILURE, &channel_input_open_failure); 12351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood dispatch_set(SSH_MSG_PORT_OPEN, &channel_input_port_open); 12361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood} 12371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic void 12381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodserver_init_dispatch_15(void) 12391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{ 12401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood server_init_dispatch_13(); 12411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood debug("server_init_dispatch_15"); 12421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood dispatch_set(SSH_MSG_CHANNEL_CLOSE, &channel_input_ieof); 12431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood dispatch_set(SSH_MSG_CHANNEL_CLOSE_CONFIRMATION, &channel_input_oclose); 12441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood} 12451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic void 12461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodserver_init_dispatch(void) 12471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{ 12481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (compat20) 12491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood server_init_dispatch_20(); 12501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood else if (compat13) 12511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood server_init_dispatch_13(); 12521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood else 12531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood server_init_dispatch_15(); 12541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood} 1255