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