11305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* $OpenBSD: clientloop.c,v 1.236 2011/06/22 22:08:42 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 * The main loop for the interactive session (client side).
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 *
151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Copyright (c) 1999 Theo de Raadt.  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 * SSH2 support added by Markus Friedl.
391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Copyright (c) 1999, 2000, 2001 Markus Friedl.  All rights reserved.
401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *
411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Redistribution and use in source and binary forms, with or without
421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * modification, are permitted provided that the following conditions
431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * are met:
441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * 1. Redistributions of source code must retain the above copyright
451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *    notice, this list of conditions and the following disclaimer.
461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * 2. Redistributions in binary form must reproduce the above copyright
471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *    notice, this list of conditions and the following disclaimer in the
481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *    documentation and/or other materials provided with the distribution.
491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *
501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood */
611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "includes.h"
631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <sys/types.h>
651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <sys/ioctl.h>
661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <sys/param.h>
671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifdef HAVE_SYS_STAT_H
681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood# include <sys/stat.h>
691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif
701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifdef HAVE_SYS_TIME_H
711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood# include <sys/time.h>
721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif
731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <sys/socket.h>
741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <ctype.h>
761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <errno.h>
771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifdef HAVE_PATHS_H
781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <paths.h>
791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif
801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <signal.h>
811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <stdarg.h>
821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <stdio.h>
831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <stdlib.h>
841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <string.h>
851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <termios.h>
861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <pwd.h>
871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <unistd.h>
881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "openbsd-compat/sys-queue.h"
901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "xmalloc.h"
911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "ssh.h"
921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "ssh1.h"
931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "ssh2.h"
941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "packet.h"
951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "buffer.h"
961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "compat.h"
971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "channels.h"
981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "dispatch.h"
991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "key.h"
1001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "cipher.h"
1011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "kex.h"
1021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "log.h"
1031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "readconf.h"
1041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "clientloop.h"
1051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "sshconnect.h"
1061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "authfd.h"
1071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "atomicio.h"
1081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "sshpty.h"
1091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "misc.h"
1101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "match.h"
1111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "msg.h"
1121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "roaming.h"
1131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* import options */
1151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodextern Options options;
1161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* Flag indicating that stdin should be redirected from /dev/null. */
1181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodextern int stdin_null_flag;
1191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* Flag indicating that no shell has been requested */
1211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodextern int no_shell_flag;
1221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* Control socket */
1241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodextern int muxserver_sock; /* XXX use mux_client_cleanup() instead */
1251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/*
1271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Name of the host we are connecting to.  This is the name given on the
1281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * command line, or the HostName specified for the user-supplied name in a
1291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * configuration file.
1301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood */
1311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodextern char *host;
1321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/*
1341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Flag to indicate that we have received a window change signal which has
1351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * not yet been processed.  This will cause a message indicating the new
1361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * window size to be sent to the server a little later.  This is volatile
1371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * because this is updated in a signal handler.
1381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood */
1391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic volatile sig_atomic_t received_window_change_signal = 0;
1401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic volatile sig_atomic_t received_signal = 0;
1411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* Flag indicating whether the user's terminal is in non-blocking mode. */
1431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic int in_non_blocking_mode = 0;
1441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* Time when backgrounded control master using ControlPersist should exit */
1461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic time_t control_persist_exit_time = 0;
1471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* Common data for the client loop code. */
1491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodvolatile sig_atomic_t quit_pending; /* Set non-zero to quit the loop. */
1501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic int escape_char1;	/* Escape character. (proto1 only) */
1511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic int escape_pending1;	/* Last character was an escape (proto1 only) */
1521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic int last_was_cr;		/* Last character was a newline. */
1531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic int exit_status;		/* Used to store the command exit status. */
1541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic int stdin_eof;		/* EOF has been encountered on stderr. */
1551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic Buffer stdin_buffer;	/* Buffer for stdin data. */
1561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic Buffer stdout_buffer;	/* Buffer for stdout data. */
1571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic Buffer stderr_buffer;	/* Buffer for stderr data. */
1581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic u_int buffer_high;	/* Soft max buffer size. */
1591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic int connection_in;	/* Connection to server (input). */
1601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic int connection_out;	/* Connection to server (output). */
1611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic int need_rekeying;	/* Set to non-zero if rekeying is requested. */
1621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic int session_closed;	/* In SSH2: login session closed. */
1631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic int x11_refuse_time;	/* If >0, refuse x11 opens after this time. */
1641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic void client_init_dispatch(void);
1661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodint	session_ident = -1;
1671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodint	session_resumed = 0;
1691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* Track escape per proto2 channel */
1711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstruct escape_filter_ctx {
1721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	int escape_pending;
1731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	int escape_char;
1741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood};
1751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* Context for channel confirmation replies */
1771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstruct channel_reply_ctx {
1781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	const char *request_type;
1791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	int id;
1801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	enum confirm_action action;
1811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood};
1821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* Global request success/failure callbacks */
1841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstruct global_confirm {
1851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	TAILQ_ENTRY(global_confirm) entry;
1861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	global_confirm_cb *cb;
1871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	void *ctx;
1881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	int ref_count;
1891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood};
1901305e95ba6ff9fa202d0818caf10405df4b0f648Mike LockwoodTAILQ_HEAD(global_confirms, global_confirm);
1911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic struct global_confirms global_confirms =
1921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood    TAILQ_HEAD_INITIALIZER(global_confirms);
1931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/*XXX*/
1951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodextern Kex *xxx_kex;
1961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodvoid ssh_process_session2_setup(int, int, int, Buffer *);
1981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* Restores stdin to blocking mode. */
2001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
2011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic void
2021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodleave_non_blocking(void)
2031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
2041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (in_non_blocking_mode) {
2051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		unset_nonblock(fileno(stdin));
2061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		in_non_blocking_mode = 0;
2071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
2081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
2091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
2101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* Puts stdin terminal in non-blocking mode. */
2111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
2121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic void
2131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodenter_non_blocking(void)
2141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
2151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	in_non_blocking_mode = 1;
2161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	set_nonblock(fileno(stdin));
2171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
2181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
2191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/*
2201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Signal handler for the window change signal (SIGWINCH).  This just sets a
2211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * flag indicating that the window has changed.
2221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood */
2231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/*ARGSUSED */
2241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic void
2251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodwindow_change_handler(int sig)
2261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
2271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	received_window_change_signal = 1;
2281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	signal(SIGWINCH, window_change_handler);
2291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
2301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
2311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/*
2321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Signal handler for signals that cause the program to terminate.  These
2331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * signals must be trapped to restore terminal modes.
2341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood */
2351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/*ARGSUSED */
2361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic void
2371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodsignal_handler(int sig)
2381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
2391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	received_signal = sig;
2401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	quit_pending = 1;
2411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
2421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
2431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/*
2441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Returns current time in seconds from Jan 1, 1970 with the maximum
2451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * available resolution.
2461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood */
2471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
2481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic double
2491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodget_current_time(void)
2501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
2511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	struct timeval tv;
2521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	gettimeofday(&tv, NULL);
2531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	return (double) tv.tv_sec + (double) tv.tv_usec / 1000000.0;
2541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
2551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
2561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/*
2571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Sets control_persist_exit_time to the absolute time when the
2581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * backgrounded control master should exit due to expiry of the
2591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * ControlPersist timeout.  Sets it to 0 if we are not a backgrounded
2601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * control master process, or if there is no ControlPersist timeout.
2611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood */
2621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic void
2631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodset_control_persist_exit_time(void)
2641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
2651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (muxserver_sock == -1 || !options.control_persist
2661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    || options.control_persist_timeout == 0) {
2671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		/* not using a ControlPersist timeout */
2681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		control_persist_exit_time = 0;
2691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	} else if (channel_still_open()) {
2701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		/* some client connections are still open */
2711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (control_persist_exit_time > 0)
2721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			debug2("%s: cancel scheduled exit", __func__);
2731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		control_persist_exit_time = 0;
2741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	} else if (control_persist_exit_time <= 0) {
2751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		/* a client connection has recently closed */
2761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		control_persist_exit_time = time(NULL) +
2771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			(time_t)options.control_persist_timeout;
2781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		debug2("%s: schedule exit in %d seconds", __func__,
2791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    options.control_persist_timeout);
2801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
2811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* else we are already counting down to the timeout */
2821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
2831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
2841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#define SSH_X11_PROTO "MIT-MAGIC-COOKIE-1"
2851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodvoid
2861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodclient_x11_get_proto(const char *display, const char *xauth_path,
2871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood    u_int trusted, u_int timeout, char **_proto, char **_data)
2881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
2891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	char cmd[1024];
2901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	char line[512];
2911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	char xdisplay[512];
2921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	static char proto[512], data[512];
2931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	FILE *f;
2941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	int got_data = 0, generated = 0, do_unlink = 0, i;
2951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	char *xauthdir, *xauthfile;
2961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	struct stat st;
2971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	u_int now;
2981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
2991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	xauthdir = xauthfile = NULL;
3001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	*_proto = proto;
3011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	*_data = data;
3021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	proto[0] = data[0] = '\0';
3031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
3041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (xauth_path == NULL ||(stat(xauth_path, &st) == -1)) {
3051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		debug("No xauth program.");
3061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	} else {
3071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (display == NULL) {
3081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			debug("x11_get_proto: DISPLAY not set");
3091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			return;
3101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
3111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		/*
3121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		 * Handle FamilyLocal case where $DISPLAY does
3131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		 * not match an authorization entry.  For this we
3141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		 * just try "xauth list unix:displaynum.screennum".
3151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		 * XXX: "localhost" match to determine FamilyLocal
3161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		 *      is not perfect.
3171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		 */
3181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (strncmp(display, "localhost:", 10) == 0) {
3191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			snprintf(xdisplay, sizeof(xdisplay), "unix:%s",
3201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			    display + 10);
3211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			display = xdisplay;
3221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
3231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (trusted == 0) {
3241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			xauthdir = xmalloc(MAXPATHLEN);
3251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			xauthfile = xmalloc(MAXPATHLEN);
3261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			mktemp_proto(xauthdir, MAXPATHLEN);
3271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			if (mkdtemp(xauthdir) != NULL) {
3281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				do_unlink = 1;
3291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				snprintf(xauthfile, MAXPATHLEN, "%s/xauthfile",
3301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				    xauthdir);
3311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				snprintf(cmd, sizeof(cmd),
3321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				    "%s -f %s generate %s " SSH_X11_PROTO
3331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				    " untrusted timeout %u 2>" _PATH_DEVNULL,
3341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				    xauth_path, xauthfile, display, timeout);
3351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				debug2("x11_get_proto: %s", cmd);
3361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				if (system(cmd) == 0)
3371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					generated = 1;
3381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				if (x11_refuse_time == 0) {
3391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					now = time(NULL) + 1;
3401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					if (UINT_MAX - timeout < now)
3411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood						x11_refuse_time = UINT_MAX;
3421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					else
3431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood						x11_refuse_time = now + timeout;
3441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				}
3451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			}
3461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
3471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
3481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		/*
3491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		 * When in untrusted mode, we read the cookie only if it was
3501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		 * successfully generated as an untrusted one in the step
3511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		 * above.
3521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		 */
3531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (trusted || generated) {
3541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			snprintf(cmd, sizeof(cmd),
3551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			    "%s %s%s list %s 2>" _PATH_DEVNULL,
3561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			    xauth_path,
3571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			    generated ? "-f " : "" ,
3581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			    generated ? xauthfile : "",
3591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			    display);
3601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			debug2("x11_get_proto: %s", cmd);
3611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			f = popen(cmd, "r");
3621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			if (f && fgets(line, sizeof(line), f) &&
3631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			    sscanf(line, "%*s %511s %511s", proto, data) == 2)
3641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				got_data = 1;
3651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			if (f)
3661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				pclose(f);
3671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		} else
3681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			error("Warning: untrusted X11 forwarding setup failed: "
3691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			    "xauth key data not generated");
3701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
3711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
3721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (do_unlink) {
3731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		unlink(xauthfile);
3741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		rmdir(xauthdir);
3751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
3761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (xauthdir)
3771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		xfree(xauthdir);
3781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (xauthfile)
3791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		xfree(xauthfile);
3801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
3811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/*
3821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 * If we didn't get authentication data, just make up some
3831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 * data.  The forwarding code will check the validity of the
3841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 * response anyway, and substitute this data.  The X11
3851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 * server, however, will ignore this fake data and use
3861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 * whatever authentication mechanisms it was using otherwise
3871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 * for the local connection.
3881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 */
3891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (!got_data) {
3901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		u_int32_t rnd = 0;
3911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
3921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		logit("Warning: No xauth data; "
3931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    "using fake authentication data for X11 forwarding.");
3941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		strlcpy(proto, SSH_X11_PROTO, sizeof proto);
3951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		for (i = 0; i < 16; i++) {
3961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			if (i % 4 == 0)
3971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				rnd = arc4random();
3981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			snprintf(data + 2 * i, sizeof data - 2 * i, "%02x",
3991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			    rnd & 0xff);
4001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			rnd >>= 8;
4011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
4021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
4031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
4041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
4051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/*
4061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * This is called when the interactive is entered.  This checks if there is
4071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * an EOF coming on stdin.  We must check this explicitly, as select() does
4081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * not appear to wake up when redirecting from /dev/null.
4091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood */
4101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
4111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic void
4121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodclient_check_initial_eof_on_stdin(void)
4131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
4141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	int len;
4151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	char buf[1];
4161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
4171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/*
4181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 * If standard input is to be "redirected from /dev/null", we simply
4191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 * mark that we have seen an EOF and send an EOF message to the
4201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 * server. Otherwise, we try to read a single character; it appears
4211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 * that for some files, such /dev/null, select() never wakes up for
4221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 * read for this descriptor, which means that we never get EOF.  This
4231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 * way we will get the EOF if stdin comes from /dev/null or similar.
4241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 */
4251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (stdin_null_flag) {
4261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		/* Fake EOF on stdin. */
4271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		debug("Sending eof.");
4281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		stdin_eof = 1;
4291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		packet_start(SSH_CMSG_EOF);
4301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		packet_send();
4311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	} else {
4321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		enter_non_blocking();
4331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
4341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		/* Check for immediate EOF on stdin. */
4351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		len = read(fileno(stdin), buf, 1);
4361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (len == 0) {
4371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			/*
4381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			 * EOF.  Record that we have seen it and send
4391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			 * EOF to server.
4401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			 */
4411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			debug("Sending eof.");
4421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			stdin_eof = 1;
4431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			packet_start(SSH_CMSG_EOF);
4441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			packet_send();
4451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		} else if (len > 0) {
4461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			/*
4471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			 * Got data.  We must store the data in the buffer,
4481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			 * and also process it as an escape character if
4491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			 * appropriate.
4501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			 */
4511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			if ((u_char) buf[0] == escape_char1)
4521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				escape_pending1 = 1;
4531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			else
4541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				buffer_append(&stdin_buffer, buf, 1);
4551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
4561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		leave_non_blocking();
4571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
4581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
4591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
4601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
4611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/*
4621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Make packets from buffered stdin data, and buffer them for sending to the
4631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * connection.
4641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood */
4651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
4661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic void
4671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodclient_make_packets_from_stdin_data(void)
4681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
4691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	u_int len;
4701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
4711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* Send buffered stdin data to the server. */
4721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	while (buffer_len(&stdin_buffer) > 0 &&
4731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    packet_not_very_much_data_to_write()) {
4741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		len = buffer_len(&stdin_buffer);
4751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		/* Keep the packets at reasonable size. */
4761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (len > packet_get_maxsize())
4771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			len = packet_get_maxsize();
4781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		packet_start(SSH_CMSG_STDIN_DATA);
4791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		packet_put_string(buffer_ptr(&stdin_buffer), len);
4801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		packet_send();
4811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		buffer_consume(&stdin_buffer, len);
4821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		/* If we have a pending EOF, send it now. */
4831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (stdin_eof && buffer_len(&stdin_buffer) == 0) {
4841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			packet_start(SSH_CMSG_EOF);
4851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			packet_send();
4861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
4871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
4881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
4891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
4901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/*
4911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Checks if the client window has changed, and sends a packet about it to
4921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * the server if so.  The actual change is detected elsewhere (by a software
4931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * interrupt on Unix); this just checks the flag and sends a message if
4941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * appropriate.
4951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood */
4961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
4971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic void
4981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodclient_check_window_change(void)
4991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
5001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	struct winsize ws;
5011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
5021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (! received_window_change_signal)
5031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return;
5041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/** XXX race */
5051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	received_window_change_signal = 0;
5061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
5071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	debug2("client_check_window_change: changed");
5081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
5091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (compat20) {
5101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		channel_send_window_changes();
5111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	} else {
5121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (ioctl(fileno(stdin), TIOCGWINSZ, &ws) < 0)
5131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			return;
5141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		packet_start(SSH_CMSG_WINDOW_SIZE);
5151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		packet_put_int((u_int)ws.ws_row);
5161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		packet_put_int((u_int)ws.ws_col);
5171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		packet_put_int((u_int)ws.ws_xpixel);
5181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		packet_put_int((u_int)ws.ws_ypixel);
5191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		packet_send();
5201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
5211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
5221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
5231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic void
5241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodclient_global_request_reply(int type, u_int32_t seq, void *ctxt)
5251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
5261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	struct global_confirm *gc;
5271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
5281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if ((gc = TAILQ_FIRST(&global_confirms)) == NULL)
5291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return;
5301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (gc->cb != NULL)
5311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		gc->cb(type, seq, gc->ctx);
5321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (--gc->ref_count <= 0) {
5331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		TAILQ_REMOVE(&global_confirms, gc, entry);
5341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		bzero(gc, sizeof(*gc));
5351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		xfree(gc);
5361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
5371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
5381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	packet_set_alive_timeouts(0);
5391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
5401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
5411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic void
5421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodserver_alive_check(void)
5431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
5441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (packet_inc_alive_timeouts() > options.server_alive_count_max) {
5451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		logit("Timeout, server %s not responding.", host);
5461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		cleanup_exit(255);
5471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
5481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	packet_start(SSH2_MSG_GLOBAL_REQUEST);
5491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	packet_put_cstring("keepalive@openssh.com");
5501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	packet_put_char(1);     /* boolean: want reply */
5511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	packet_send();
5521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* Insert an empty placeholder to maintain ordering */
5531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	client_register_global_confirm(NULL, NULL);
5541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
5551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
5561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/*
5571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Waits until the client can do something (some data becomes available on
5581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * one of the file descriptors).
5591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood */
5601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic void
5611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodclient_wait_until_can_do_something(fd_set **readsetp, fd_set **writesetp,
5621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood    int *maxfdp, u_int *nallocp, int rekeying)
5631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
5641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	struct timeval tv, *tvp;
5651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	int timeout_secs;
5661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	int ret;
5671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
5681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* Add any selections by the channel mechanism. */
5691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	channel_prepare_select(readsetp, writesetp, maxfdp, nallocp, rekeying);
5701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
5711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (!compat20) {
5721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		/* Read from the connection, unless our buffers are full. */
5731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (buffer_len(&stdout_buffer) < buffer_high &&
5741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    buffer_len(&stderr_buffer) < buffer_high &&
5751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    channel_not_very_much_buffered_data())
5761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			FD_SET(connection_in, *readsetp);
5771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		/*
5781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		 * Read from stdin, unless we have seen EOF or have very much
5791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		 * buffered data to send to the server.
5801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		 */
5811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (!stdin_eof && packet_not_very_much_data_to_write())
5821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			FD_SET(fileno(stdin), *readsetp);
5831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
5841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		/* Select stdout/stderr if have data in buffer. */
5851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (buffer_len(&stdout_buffer) > 0)
5861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			FD_SET(fileno(stdout), *writesetp);
5871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (buffer_len(&stderr_buffer) > 0)
5881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			FD_SET(fileno(stderr), *writesetp);
5891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	} else {
5901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		/* channel_prepare_select could have closed the last channel */
5911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (session_closed && !channel_still_open() &&
5921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    !packet_have_data_to_write()) {
5931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			/* clear mask since we did not call select() */
5941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			memset(*readsetp, 0, *nallocp);
5951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			memset(*writesetp, 0, *nallocp);
5961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			return;
5971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		} else {
5981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			FD_SET(connection_in, *readsetp);
5991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
6001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
6011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
6021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* Select server connection if have data to write to the server. */
6031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (packet_have_data_to_write())
6041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		FD_SET(connection_out, *writesetp);
6051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
6061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/*
6071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 * Wait for something to happen.  This will suspend the process until
6081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 * some selected descriptor can be read, written, or has some other
6091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 * event pending, or a timeout expires.
6101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 */
6111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
6121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	timeout_secs = INT_MAX; /* we use INT_MAX to mean no timeout */
6131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (options.server_alive_interval > 0 && compat20)
6141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		timeout_secs = options.server_alive_interval;
6151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	set_control_persist_exit_time();
6161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (control_persist_exit_time > 0) {
6171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		timeout_secs = MIN(timeout_secs,
6181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			control_persist_exit_time - time(NULL));
6191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (timeout_secs < 0)
6201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			timeout_secs = 0;
6211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
6221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (timeout_secs == INT_MAX)
6231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		tvp = NULL;
6241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	else {
6251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		tv.tv_sec = timeout_secs;
6261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		tv.tv_usec = 0;
6271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		tvp = &tv;
6281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
6291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
6301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	ret = select((*maxfdp)+1, *readsetp, *writesetp, NULL, tvp);
6311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (ret < 0) {
6321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		char buf[100];
6331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
6341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		/*
6351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		 * We have to clear the select masks, because we return.
6361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		 * We have to return, because the mainloop checks for the flags
6371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		 * set by the signal handlers.
6381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		 */
6391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		memset(*readsetp, 0, *nallocp);
6401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		memset(*writesetp, 0, *nallocp);
6411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
6421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (errno == EINTR)
6431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			return;
6441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		/* Note: we might still have data in the buffers. */
6451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		snprintf(buf, sizeof buf, "select: %s\r\n", strerror(errno));
6461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		buffer_append(&stderr_buffer, buf, strlen(buf));
6471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		quit_pending = 1;
6481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	} else if (ret == 0)
6491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		server_alive_check();
6501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
6511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
6521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic void
6531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodclient_suspend_self(Buffer *bin, Buffer *bout, Buffer *berr)
6541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
6551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* Flush stdout and stderr buffers. */
6561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (buffer_len(bout) > 0)
6571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		atomicio(vwrite, fileno(stdout), buffer_ptr(bout),
6581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    buffer_len(bout));
6591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (buffer_len(berr) > 0)
6601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		atomicio(vwrite, fileno(stderr), buffer_ptr(berr),
6611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    buffer_len(berr));
6621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
6631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	leave_raw_mode(options.request_tty == REQUEST_TTY_FORCE);
6641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
6651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/*
6661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 * Free (and clear) the buffer to reduce the amount of data that gets
6671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 * written to swap.
6681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 */
6691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	buffer_free(bin);
6701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	buffer_free(bout);
6711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	buffer_free(berr);
6721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
6731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* Send the suspend signal to the program itself. */
6741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	kill(getpid(), SIGTSTP);
6751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
6761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* Reset window sizes in case they have changed */
6771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	received_window_change_signal = 1;
6781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
6791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* OK, we have been continued by the user. Reinitialize buffers. */
6801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	buffer_init(bin);
6811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	buffer_init(bout);
6821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	buffer_init(berr);
6831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
6841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	enter_raw_mode(options.request_tty == REQUEST_TTY_FORCE);
6851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
6861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
6871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic void
6881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodclient_process_net_input(fd_set *readset)
6891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
6901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	int len, cont = 0;
6911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	char buf[SSH_IOBUFSZ];
6921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
6931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/*
6941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 * Read input from the server, and add any such data to the buffer of
6951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 * the packet subsystem.
6961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 */
6971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (FD_ISSET(connection_in, readset)) {
6981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		/* Read as much as possible. */
6991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		len = roaming_read(connection_in, buf, sizeof(buf), &cont);
7001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (len == 0 && cont == 0) {
7011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			/*
7021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			 * Received EOF.  The remote host has closed the
7031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			 * connection.
7041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			 */
7051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			snprintf(buf, sizeof buf,
7061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			    "Connection to %.300s closed by remote host.\r\n",
7071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			    host);
7081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			buffer_append(&stderr_buffer, buf, strlen(buf));
7091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			quit_pending = 1;
7101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			return;
7111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
7121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		/*
7131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		 * There is a kernel bug on Solaris that causes select to
7141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		 * sometimes wake up even though there is no data available.
7151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		 */
7161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (len < 0 &&
7171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    (errno == EAGAIN || errno == EINTR || errno == EWOULDBLOCK))
7181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			len = 0;
7191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
7201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (len < 0) {
7211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			/*
7221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			 * An error has encountered.  Perhaps there is a
7231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			 * network problem.
7241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			 */
7251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			snprintf(buf, sizeof buf,
7261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			    "Read from remote host %.300s: %.100s\r\n",
7271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			    host, strerror(errno));
7281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			buffer_append(&stderr_buffer, buf, strlen(buf));
7291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			quit_pending = 1;
7301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			return;
7311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
7321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		packet_process_incoming(buf, len);
7331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
7341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
7351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
7361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic void
7371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodclient_status_confirm(int type, Channel *c, void *ctx)
7381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
7391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	struct channel_reply_ctx *cr = (struct channel_reply_ctx *)ctx;
7401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	char errmsg[256];
7411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	int tochan;
7421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
7431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/*
7441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 * If a TTY was explicitly requested, then a failure to allocate
7451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 * one is fatal.
7461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 */
7471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (cr->action == CONFIRM_TTY &&
7481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    (options.request_tty == REQUEST_TTY_FORCE ||
7491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    options.request_tty == REQUEST_TTY_YES))
7501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		cr->action = CONFIRM_CLOSE;
7511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
7521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* XXX supress on mux _client_ quietmode */
7531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	tochan = options.log_level >= SYSLOG_LEVEL_ERROR &&
7541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    c->ctl_chan != -1 && c->extended_usage == CHAN_EXTENDED_WRITE;
7551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
7561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (type == SSH2_MSG_CHANNEL_SUCCESS) {
7571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		debug2("%s request accepted on channel %d",
7581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    cr->request_type, c->self);
7591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	} else if (type == SSH2_MSG_CHANNEL_FAILURE) {
7601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (tochan) {
7611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			snprintf(errmsg, sizeof(errmsg),
7621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			    "%s request failed\r\n", cr->request_type);
7631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		} else {
7641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			snprintf(errmsg, sizeof(errmsg),
7651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			    "%s request failed on channel %d",
7661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			    cr->request_type, c->self);
7671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
7681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		/* If error occurred on primary session channel, then exit */
7691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (cr->action == CONFIRM_CLOSE && c->self == session_ident)
7701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			fatal("%s", errmsg);
7711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		/*
7721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		 * If error occurred on mux client, append to
7731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		 * their stderr.
7741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		 */
7751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (tochan) {
7761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			buffer_append(&c->extended, errmsg,
7771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			    strlen(errmsg));
7781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		} else
7791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			error("%s", errmsg);
7801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (cr->action == CONFIRM_TTY) {
7811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			/*
7821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			 * If a TTY allocation error occurred, then arrange
7831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			 * for the correct TTY to leave raw mode.
7841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			 */
7851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			if (c->self == session_ident)
7861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				leave_raw_mode(0);
7871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			else
7881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				mux_tty_alloc_failed(c);
7891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		} else if (cr->action == CONFIRM_CLOSE) {
7901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			chan_read_failed(c);
7911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			chan_write_failed(c);
7921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
7931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
7941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	xfree(cr);
7951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
7961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
7971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic void
7981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodclient_abandon_status_confirm(Channel *c, void *ctx)
7991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
8001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	xfree(ctx);
8011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
8021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
8031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodvoid
8041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodclient_expect_confirm(int id, const char *request,
8051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood    enum confirm_action action)
8061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
8071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	struct channel_reply_ctx *cr = xmalloc(sizeof(*cr));
8081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
8091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	cr->request_type = request;
8101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	cr->action = action;
8111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
8121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	channel_register_status_confirm(id, client_status_confirm,
8131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    client_abandon_status_confirm, cr);
8141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
8151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
8161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodvoid
8171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodclient_register_global_confirm(global_confirm_cb *cb, void *ctx)
8181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
8191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	struct global_confirm *gc, *last_gc;
8201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
8211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* Coalesce identical callbacks */
8221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	last_gc = TAILQ_LAST(&global_confirms, global_confirms);
8231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (last_gc && last_gc->cb == cb && last_gc->ctx == ctx) {
8241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (++last_gc->ref_count >= INT_MAX)
8251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			fatal("%s: last_gc->ref_count = %d",
8261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			    __func__, last_gc->ref_count);
8271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return;
8281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
8291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
8301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	gc = xmalloc(sizeof(*gc));
8311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	gc->cb = cb;
8321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	gc->ctx = ctx;
8331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	gc->ref_count = 1;
8341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	TAILQ_INSERT_TAIL(&global_confirms, gc, entry);
8351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
8361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
8371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic void
8381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodprocess_cmdline(void)
8391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
8401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	void (*handler)(int);
8411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	char *s, *cmd, *cancel_host;
8421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	int delete = 0;
8431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	int local = 0, remote = 0, dynamic = 0;
8441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	int cancel_port;
8451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	Forward fwd;
8461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
8471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	bzero(&fwd, sizeof(fwd));
8481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	fwd.listen_host = fwd.connect_host = NULL;
8491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
8501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	leave_raw_mode(options.request_tty == REQUEST_TTY_FORCE);
8511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	handler = signal(SIGINT, SIG_IGN);
8521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	cmd = s = read_passphrase("\r\nssh> ", RP_ECHO);
8531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (s == NULL)
8541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		goto out;
8551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	while (isspace(*s))
8561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		s++;
8571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (*s == '-')
8581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		s++;	/* Skip cmdline '-', if any */
8591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (*s == '\0')
8601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		goto out;
8611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
8621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (*s == 'h' || *s == 'H' || *s == '?') {
8631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		logit("Commands:");
8641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		logit("      -L[bind_address:]port:host:hostport    "
8651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    "Request local forward");
8661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		logit("      -R[bind_address:]port:host:hostport    "
8671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    "Request remote forward");
8681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		logit("      -D[bind_address:]port                  "
8691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    "Request dynamic forward");
8701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		logit("      -KR[bind_address:]port                 "
8711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    "Cancel remote forward");
8721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (!options.permit_local_command)
8731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			goto out;
8741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		logit("      !args                                  "
8751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    "Execute local command");
8761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		goto out;
8771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
8781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
8791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (*s == '!' && options.permit_local_command) {
8801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		s++;
8811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		ssh_local_cmd(s);
8821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		goto out;
8831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
8841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
8851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (*s == 'K') {
8861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		delete = 1;
8871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		s++;
8881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
8891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (*s == 'L')
8901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		local = 1;
8911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	else if (*s == 'R')
8921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		remote = 1;
8931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	else if (*s == 'D')
8941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		dynamic = 1;
8951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	else {
8961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		logit("Invalid command.");
8971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		goto out;
8981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
8991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
9001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if ((local || dynamic) && delete) {
9011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		logit("Not supported.");
9021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		goto out;
9031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
9041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (remote && delete && !compat20) {
9051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		logit("Not supported for SSH protocol version 1.");
9061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		goto out;
9071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
9081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
9091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	while (isspace(*++s))
9101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		;
9111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
9121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* XXX update list of forwards in options */
9131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (delete) {
9141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		cancel_port = 0;
9151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		cancel_host = hpdelim(&s);	/* may be NULL */
9161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (s != NULL) {
9171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			cancel_port = a2port(s);
9181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			cancel_host = cleanhostname(cancel_host);
9191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		} else {
9201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			cancel_port = a2port(cancel_host);
9211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			cancel_host = NULL;
9221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
9231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (cancel_port <= 0) {
9241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			logit("Bad forwarding close port");
9251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			goto out;
9261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
9271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		channel_request_rforward_cancel(cancel_host, cancel_port);
9281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	} else {
9291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (!parse_forward(&fwd, s, dynamic, remote)) {
9301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			logit("Bad forwarding specification.");
9311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			goto out;
9321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
9331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (local || dynamic) {
9341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			if (channel_setup_local_fwd_listener(fwd.listen_host,
9351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			    fwd.listen_port, fwd.connect_host,
9361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			    fwd.connect_port, options.gateway_ports) < 0) {
9371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				logit("Port forwarding failed.");
9381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				goto out;
9391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			}
9401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		} else {
9411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			if (channel_request_remote_forwarding(fwd.listen_host,
9421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			    fwd.listen_port, fwd.connect_host,
9431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			    fwd.connect_port) < 0) {
9441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				logit("Port forwarding failed.");
9451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				goto out;
9461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			}
9471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
9481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
9491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		logit("Forwarding port.");
9501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
9511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
9521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodout:
9531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	signal(SIGINT, handler);
9541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	enter_raw_mode(options.request_tty == REQUEST_TTY_FORCE);
9551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (cmd)
9561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		xfree(cmd);
9571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (fwd.listen_host != NULL)
9581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		xfree(fwd.listen_host);
9591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (fwd.connect_host != NULL)
9601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		xfree(fwd.connect_host);
9611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
9621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
9631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/*
9641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Process the characters one by one, call with c==NULL for proto1 case.
9651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood */
9661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic int
9671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodprocess_escapes(Channel *c, Buffer *bin, Buffer *bout, Buffer *berr,
9681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood    char *buf, int len)
9691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
9701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	char string[1024];
9711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	pid_t pid;
9721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	int bytes = 0;
9731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	u_int i;
9741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	u_char ch;
9751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	char *s;
9761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	int *escape_pendingp, escape_char;
9771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	struct escape_filter_ctx *efc;
9781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
9791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (c == NULL) {
9801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		escape_pendingp = &escape_pending1;
9811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		escape_char = escape_char1;
9821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	} else {
9831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (c->filter_ctx == NULL)
9841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			return 0;
9851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		efc = (struct escape_filter_ctx *)c->filter_ctx;
9861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		escape_pendingp = &efc->escape_pending;
9871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		escape_char = efc->escape_char;
9881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
9891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
9901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (len <= 0)
9911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return (0);
9921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
9931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	for (i = 0; i < (u_int)len; i++) {
9941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		/* Get one character at a time. */
9951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		ch = buf[i];
9961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
9971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (*escape_pendingp) {
9981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			/* We have previously seen an escape character. */
9991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			/* Clear the flag now. */
10001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			*escape_pendingp = 0;
10011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
10021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			/* Process the escaped character. */
10031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			switch (ch) {
10041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			case '.':
10051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				/* Terminate the connection. */
10061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				snprintf(string, sizeof string, "%c.\r\n",
10071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				    escape_char);
10081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				buffer_append(berr, string, strlen(string));
10091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
10101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				if (c && c->ctl_chan != -1) {
10111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					chan_read_failed(c);
10121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					chan_write_failed(c);
10131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					return 0;
10141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				} else
10151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					quit_pending = 1;
10161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				return -1;
10171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
10181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			case 'Z' - 64:
10191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				/* XXX support this for mux clients */
10201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				if (c && c->ctl_chan != -1) {
10211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood noescape:
10221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					snprintf(string, sizeof string,
10231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					    "%c%c escape not available to "
10241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					    "multiplexed sessions\r\n",
10251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					    escape_char, ch);
10261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					buffer_append(berr, string,
10271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					    strlen(string));
10281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					continue;
10291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				}
10301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				/* Suspend the program. Inform the user */
10311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				snprintf(string, sizeof string,
10321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				    "%c^Z [suspend ssh]\r\n", escape_char);
10331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				buffer_append(berr, string, strlen(string));
10341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
10351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				/* Restore terminal modes and suspend. */
10361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				client_suspend_self(bin, bout, berr);
10371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
10381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				/* We have been continued. */
10391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				continue;
10401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
10411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			case 'B':
10421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				if (compat20) {
10431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					snprintf(string, sizeof string,
10441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					    "%cB\r\n", escape_char);
10451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					buffer_append(berr, string,
10461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					    strlen(string));
10471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					channel_request_start(session_ident,
10481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					    "break", 0);
10491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					packet_put_int(1000);
10501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					packet_send();
10511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				}
10521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				continue;
10531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
10541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			case 'R':
10551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				if (compat20) {
10561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					if (datafellows & SSH_BUG_NOREKEY)
10571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood						logit("Server does not "
10581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood						    "support re-keying");
10591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					else
10601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood						need_rekeying = 1;
10611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				}
10621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				continue;
10631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
10641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			case '&':
10651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				if (c && c->ctl_chan != -1)
10661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					goto noescape;
10671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				/*
10681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				 * Detach the program (continue to serve
10691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				 * connections, but put in background and no
10701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				 * more new connections).
10711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				 */
10721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				/* Restore tty modes. */
10731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				leave_raw_mode(
10741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				    options.request_tty == REQUEST_TTY_FORCE);
10751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
10761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				/* Stop listening for new connections. */
10771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				channel_stop_listening();
10781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
10791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				snprintf(string, sizeof string,
10801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				    "%c& [backgrounded]\n", escape_char);
10811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				buffer_append(berr, string, strlen(string));
10821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
10831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				/* Fork into background. */
10841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				pid = fork();
10851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				if (pid < 0) {
10861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					error("fork: %.100s", strerror(errno));
10871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					continue;
10881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				}
10891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				if (pid != 0) {	/* This is the parent. */
10901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					/* The parent just exits. */
10911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					exit(0);
10921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				}
10931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				/* The child continues serving connections. */
10941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				if (compat20) {
10951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					buffer_append(bin, "\004", 1);
10961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					/* fake EOF on stdin */
10971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					return -1;
10981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				} else if (!stdin_eof) {
10991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					/*
11001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					 * Sending SSH_CMSG_EOF alone does not
11011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					 * always appear to be enough.  So we
11021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					 * try to send an EOF character first.
11031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					 */
11041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					packet_start(SSH_CMSG_STDIN_DATA);
11051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					packet_put_string("\004", 1);
11061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					packet_send();
11071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					/* Close stdin. */
11081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					stdin_eof = 1;
11091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					if (buffer_len(bin) == 0) {
11101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood						packet_start(SSH_CMSG_EOF);
11111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood						packet_send();
11121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					}
11131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				}
11141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				continue;
11151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
11161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			case '?':
11171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				if (c && c->ctl_chan != -1) {
11181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					snprintf(string, sizeof string,
11191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood"%c?\r\n\
11201305e95ba6ff9fa202d0818caf10405df4b0f648Mike LockwoodSupported escape sequences:\r\n\
11211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood  %c.  - terminate session\r\n\
11221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood  %cB  - send a BREAK to the remote system\r\n\
11231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood  %cR  - Request rekey (SSH protocol 2 only)\r\n\
11241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood  %c#  - list forwarded connections\r\n\
11251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood  %c?  - this message\r\n\
11261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood  %c%c  - send the escape character by typing it twice\r\n\
11271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood(Note that escapes are only recognized immediately after newline.)\r\n",
11281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					    escape_char, escape_char,
11291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					    escape_char, escape_char,
11301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					    escape_char, escape_char,
11311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					    escape_char, escape_char);
11321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				} else {
11331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					snprintf(string, sizeof string,
11341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood"%c?\r\n\
11351305e95ba6ff9fa202d0818caf10405df4b0f648Mike LockwoodSupported escape sequences:\r\n\
11361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood  %c.  - terminate connection (and any multiplexed sessions)\r\n\
11371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood  %cB  - send a BREAK to the remote system\r\n\
11381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood  %cC  - open a command line\r\n\
11391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood  %cR  - Request rekey (SSH protocol 2 only)\r\n\
11401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood  %c^Z - suspend ssh\r\n\
11411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood  %c#  - list forwarded connections\r\n\
11421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood  %c&  - background ssh (when waiting for connections to terminate)\r\n\
11431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood  %c?  - this message\r\n\
11441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood  %c%c  - send the escape character by typing it twice\r\n\
11451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood(Note that escapes are only recognized immediately after newline.)\r\n",
11461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					    escape_char, escape_char,
11471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					    escape_char, escape_char,
11481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					    escape_char, escape_char,
11491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					    escape_char, escape_char,
11501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					    escape_char, escape_char,
11511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					    escape_char);
11521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				}
11531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				buffer_append(berr, string, strlen(string));
11541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				continue;
11551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
11561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			case '#':
11571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				snprintf(string, sizeof string, "%c#\r\n",
11581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				    escape_char);
11591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				buffer_append(berr, string, strlen(string));
11601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				s = channel_open_message();
11611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				buffer_append(berr, s, strlen(s));
11621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				xfree(s);
11631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				continue;
11641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
11651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			case 'C':
11661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				if (c && c->ctl_chan != -1)
11671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					goto noescape;
11681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				process_cmdline();
11691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				continue;
11701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
11711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			default:
11721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				if (ch != escape_char) {
11731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					buffer_put_char(bin, escape_char);
11741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					bytes++;
11751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				}
11761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				/* Escaped characters fall through here */
11771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				break;
11781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			}
11791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		} else {
11801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			/*
11811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			 * The previous character was not an escape char.
11821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			 * Check if this is an escape.
11831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			 */
11841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			if (last_was_cr && ch == escape_char) {
11851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				/*
11861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				 * It is. Set the flag and continue to
11871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				 * next character.
11881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				 */
11891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				*escape_pendingp = 1;
11901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				continue;
11911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			}
11921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
11931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
11941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		/*
11951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		 * Normal character.  Record whether it was a newline,
11961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		 * and append it to the buffer.
11971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		 */
11981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		last_was_cr = (ch == '\r' || ch == '\n');
11991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		buffer_put_char(bin, ch);
12001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		bytes++;
12011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
12021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	return bytes;
12031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
12041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
12051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic void
12061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodclient_process_input(fd_set *readset)
12071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
12081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	int len;
12091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	char buf[SSH_IOBUFSZ];
12101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
12111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* Read input from stdin. */
12121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (FD_ISSET(fileno(stdin), readset)) {
12131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		/* Read as much as possible. */
12141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		len = read(fileno(stdin), buf, sizeof(buf));
12151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (len < 0 &&
12161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    (errno == EAGAIN || errno == EINTR || errno == EWOULDBLOCK))
12171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			return;		/* we'll try again later */
12181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (len <= 0) {
12191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			/*
12201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			 * Received EOF or error.  They are treated
12211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			 * similarly, except that an error message is printed
12221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			 * if it was an error condition.
12231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			 */
12241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			if (len < 0) {
12251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				snprintf(buf, sizeof buf, "read: %.100s\r\n",
12261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				    strerror(errno));
12271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				buffer_append(&stderr_buffer, buf, strlen(buf));
12281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			}
12291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			/* Mark that we have seen EOF. */
12301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			stdin_eof = 1;
12311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			/*
12321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			 * Send an EOF message to the server unless there is
12331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			 * data in the buffer.  If there is data in the
12341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			 * buffer, no message will be sent now.  Code
12351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			 * elsewhere will send the EOF when the buffer
12361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			 * becomes empty if stdin_eof is set.
12371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			 */
12381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			if (buffer_len(&stdin_buffer) == 0) {
12391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				packet_start(SSH_CMSG_EOF);
12401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				packet_send();
12411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			}
12421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		} else if (escape_char1 == SSH_ESCAPECHAR_NONE) {
12431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			/*
12441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			 * Normal successful read, and no escape character.
12451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			 * Just append the data to buffer.
12461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			 */
12471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			buffer_append(&stdin_buffer, buf, len);
12481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		} else {
12491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			/*
12501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			 * Normal, successful read.  But we have an escape
12511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			 * character and have to process the characters one
12521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			 * by one.
12531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			 */
12541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			if (process_escapes(NULL, &stdin_buffer,
12551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			    &stdout_buffer, &stderr_buffer, buf, len) == -1)
12561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				return;
12571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
12581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
12591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
12601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
12611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic void
12621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodclient_process_output(fd_set *writeset)
12631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
12641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	int len;
12651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	char buf[100];
12661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
12671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* Write buffered output to stdout. */
12681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (FD_ISSET(fileno(stdout), writeset)) {
12691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		/* Write as much data as possible. */
12701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		len = write(fileno(stdout), buffer_ptr(&stdout_buffer),
12711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    buffer_len(&stdout_buffer));
12721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (len <= 0) {
12731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			if (errno == EINTR || errno == EAGAIN ||
12741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			    errno == EWOULDBLOCK)
12751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				len = 0;
12761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			else {
12771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				/*
12781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				 * An error or EOF was encountered.  Put an
12791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				 * error message to stderr buffer.
12801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				 */
12811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				snprintf(buf, sizeof buf,
12821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				    "write stdout: %.50s\r\n", strerror(errno));
12831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				buffer_append(&stderr_buffer, buf, strlen(buf));
12841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				quit_pending = 1;
12851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				return;
12861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			}
12871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
12881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		/* Consume printed data from the buffer. */
12891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		buffer_consume(&stdout_buffer, len);
12901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
12911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* Write buffered output to stderr. */
12921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (FD_ISSET(fileno(stderr), writeset)) {
12931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		/* Write as much data as possible. */
12941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		len = write(fileno(stderr), buffer_ptr(&stderr_buffer),
12951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    buffer_len(&stderr_buffer));
12961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (len <= 0) {
12971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			if (errno == EINTR || errno == EAGAIN ||
12981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			    errno == EWOULDBLOCK)
12991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				len = 0;
13001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			else {
13011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				/*
13021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				 * EOF or error, but can't even print
13031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				 * error message.
13041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				 */
13051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				quit_pending = 1;
13061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				return;
13071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			}
13081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
13091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		/* Consume printed characters from the buffer. */
13101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		buffer_consume(&stderr_buffer, len);
13111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
13121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
13131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
13141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/*
13151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Get packets from the connection input buffer, and process them as long as
13161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * there are packets available.
13171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *
13181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Any unknown packets received during the actual
13191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * session cause the session to terminate.  This is
13201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * intended to make debugging easier since no
13211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * confirmations are sent.  Any compatible protocol
13221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * extensions must be negotiated during the
13231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * preparatory phase.
13241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood */
13251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
13261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic void
13271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodclient_process_buffered_input_packets(void)
13281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
13291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	dispatch_run(DISPATCH_NONBLOCK, &quit_pending,
13301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    compat20 ? xxx_kex : NULL);
13311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
13321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
13331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* scan buf[] for '~' before sending data to the peer */
13341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
13351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* Helper: allocate a new escape_filter_ctx and fill in its escape char */
13361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodvoid *
13371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodclient_new_escape_filter_ctx(int escape_char)
13381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
13391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	struct escape_filter_ctx *ret;
13401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
13411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	ret = xmalloc(sizeof(*ret));
13421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	ret->escape_pending = 0;
13431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	ret->escape_char = escape_char;
13441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	return (void *)ret;
13451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
13461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
13471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* Free the escape filter context on channel free */
13481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodvoid
13491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodclient_filter_cleanup(int cid, void *ctx)
13501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
13511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	xfree(ctx);
13521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
13531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
13541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodint
13551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodclient_simple_escape_filter(Channel *c, char *buf, int len)
13561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
13571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (c->extended_usage != CHAN_EXTENDED_WRITE)
13581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return 0;
13591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
13601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	return process_escapes(c, &c->input, &c->output, &c->extended,
13611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    buf, len);
13621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
13631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
13641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic void
13651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodclient_channel_closed(int id, void *arg)
13661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
13671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	channel_cancel_cleanup(id);
13681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	session_closed = 1;
13691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	leave_raw_mode(options.request_tty == REQUEST_TTY_FORCE);
13701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
13711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
13721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/*
13731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Implements the interactive session with the server.  This is called after
13741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * the user has been authenticated, and a command has been started on the
13751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * remote host.  If escape_char != SSH_ESCAPECHAR_NONE, it is the character
13761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * used as an escape character for terminating or suspending the session.
13771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood */
13781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
13791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodint
13801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodclient_loop(int have_pty, int escape_char_arg, int ssh2_chan_id)
13811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
13821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	fd_set *readset = NULL, *writeset = NULL;
13831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	double start_time, total_time;
13841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	int max_fd = 0, max_fd2 = 0, len, rekeying = 0;
13851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	u_int64_t ibytes, obytes;
13861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	u_int nalloc = 0;
13871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	char buf[100];
13881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
13891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	debug("Entering interactive session.");
13901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
13911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	start_time = get_current_time();
13921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
13931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* Initialize variables. */
13941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	escape_pending1 = 0;
13951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	last_was_cr = 1;
13961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	exit_status = -1;
13971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	stdin_eof = 0;
13981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	buffer_high = 64 * 1024;
13991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	connection_in = packet_get_connection_in();
14001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	connection_out = packet_get_connection_out();
14011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	max_fd = MAX(connection_in, connection_out);
14021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
14031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (!compat20) {
14041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		/* enable nonblocking unless tty */
14051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (!isatty(fileno(stdin)))
14061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			set_nonblock(fileno(stdin));
14071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (!isatty(fileno(stdout)))
14081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			set_nonblock(fileno(stdout));
14091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (!isatty(fileno(stderr)))
14101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			set_nonblock(fileno(stderr));
14111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		max_fd = MAX(max_fd, fileno(stdin));
14121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		max_fd = MAX(max_fd, fileno(stdout));
14131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		max_fd = MAX(max_fd, fileno(stderr));
14141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
14151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	quit_pending = 0;
14161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	escape_char1 = escape_char_arg;
14171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
14181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* Initialize buffers. */
14191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	buffer_init(&stdin_buffer);
14201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	buffer_init(&stdout_buffer);
14211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	buffer_init(&stderr_buffer);
14221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
14231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	client_init_dispatch();
14241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
14251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/*
14261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 * Set signal handlers, (e.g. to restore non-blocking mode)
14271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 * but don't overwrite SIG_IGN, matches behaviour from rsh(1)
14281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 */
14291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (signal(SIGHUP, SIG_IGN) != SIG_IGN)
14301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		signal(SIGHUP, signal_handler);
14311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (signal(SIGINT, SIG_IGN) != SIG_IGN)
14321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		signal(SIGINT, signal_handler);
14331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (signal(SIGQUIT, SIG_IGN) != SIG_IGN)
14341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		signal(SIGQUIT, signal_handler);
14351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (signal(SIGTERM, SIG_IGN) != SIG_IGN)
14361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		signal(SIGTERM, signal_handler);
14371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	signal(SIGWINCH, window_change_handler);
14381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
14391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (have_pty)
14401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		enter_raw_mode(options.request_tty == REQUEST_TTY_FORCE);
14411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
14421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (compat20) {
14431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		session_ident = ssh2_chan_id;
14441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (session_ident != -1) {
14451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			if (escape_char_arg != SSH_ESCAPECHAR_NONE) {
14461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				channel_register_filter(session_ident,
14471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				    client_simple_escape_filter, NULL,
14481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				    client_filter_cleanup,
14491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				    client_new_escape_filter_ctx(
14501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				    escape_char_arg));
14511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			}
14521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			channel_register_cleanup(session_ident,
14531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			    client_channel_closed, 0);
14541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
14551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	} else {
14561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		/* Check if we should immediately send eof on stdin. */
14571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		client_check_initial_eof_on_stdin();
14581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
14591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
14601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* Main loop of the client for the interactive session mode. */
14611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	while (!quit_pending) {
14621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
14631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		/* Process buffered packets sent by the server. */
14641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		client_process_buffered_input_packets();
14651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
14661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (compat20 && session_closed && !channel_still_open())
14671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			break;
14681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
14691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		rekeying = (xxx_kex != NULL && !xxx_kex->done);
14701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
14711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (rekeying) {
14721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			debug("rekeying in progress");
14731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		} else {
14741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			/*
14751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			 * Make packets of buffered stdin data, and buffer
14761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			 * them for sending to the server.
14771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			 */
14781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			if (!compat20)
14791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				client_make_packets_from_stdin_data();
14801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
14811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			/*
14821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			 * Make packets from buffered channel data, and
14831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			 * enqueue them for sending to the server.
14841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			 */
14851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			if (packet_not_very_much_data_to_write())
14861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				channel_output_poll();
14871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
14881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			/*
14891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			 * Check if the window size has changed, and buffer a
14901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			 * message about it to the server if so.
14911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			 */
14921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			client_check_window_change();
14931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
14941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			if (quit_pending)
14951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				break;
14961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
14971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		/*
14981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		 * Wait until we have something to do (something becomes
14991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		 * available on one of the descriptors).
15001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		 */
15011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		max_fd2 = max_fd;
15021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		client_wait_until_can_do_something(&readset, &writeset,
15031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    &max_fd2, &nalloc, rekeying);
15041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
15051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (quit_pending)
15061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			break;
15071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
15081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		/* Do channel operations unless rekeying in progress. */
15091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (!rekeying) {
15101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			channel_after_select(readset, writeset);
15111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			if (need_rekeying || packet_need_rekeying()) {
15121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				debug("need rekeying");
15131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				xxx_kex->done = 0;
15141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				kex_send_kexinit(xxx_kex);
15151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				need_rekeying = 0;
15161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			}
15171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
15181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
15191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		/* Buffer input from the connection.  */
15201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		client_process_net_input(readset);
15211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
15221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (quit_pending)
15231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			break;
15241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
15251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (!compat20) {
15261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			/* Buffer data from stdin */
15271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			client_process_input(readset);
15281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			/*
15291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			 * Process output to stdout and stderr.  Output to
15301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			 * the connection is processed elsewhere (above).
15311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			 */
15321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			client_process_output(writeset);
15331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
15341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
15351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (session_resumed) {
15361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			connection_in = packet_get_connection_in();
15371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			connection_out = packet_get_connection_out();
15381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			max_fd = MAX(max_fd, connection_out);
15391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			max_fd = MAX(max_fd, connection_in);
15401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			session_resumed = 0;
15411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
15421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
15431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		/*
15441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		 * Send as much buffered packet data as possible to the
15451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		 * sender.
15461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		 */
15471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (FD_ISSET(connection_out, writeset))
15481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			packet_write_poll();
15491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
15501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		/*
15511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		 * If we are a backgrounded control master, and the
15521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		 * timeout has expired without any active client
15531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		 * connections, then quit.
15541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		 */
15551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (control_persist_exit_time > 0) {
15561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			if (time(NULL) >= control_persist_exit_time) {
15571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				debug("ControlPersist timeout expired");
15581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				break;
15591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			}
15601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
15611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
15621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (readset)
15631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		xfree(readset);
15641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (writeset)
15651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		xfree(writeset);
15661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
15671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* Terminate the session. */
15681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
15691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* Stop watching for window change. */
15701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	signal(SIGWINCH, SIG_DFL);
15711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
15721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (compat20) {
15731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		packet_start(SSH2_MSG_DISCONNECT);
15741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		packet_put_int(SSH2_DISCONNECT_BY_APPLICATION);
15751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		packet_put_cstring("disconnected by user");
15761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		packet_put_cstring(""); /* language tag */
15771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		packet_send();
15781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		packet_write_wait();
15791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
15801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
15811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	channel_free_all();
15821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
15831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (have_pty)
15841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		leave_raw_mode(options.request_tty == REQUEST_TTY_FORCE);
15851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
15861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* restore blocking io */
15871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (!isatty(fileno(stdin)))
15881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		unset_nonblock(fileno(stdin));
15891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (!isatty(fileno(stdout)))
15901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		unset_nonblock(fileno(stdout));
15911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (!isatty(fileno(stderr)))
15921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		unset_nonblock(fileno(stderr));
15931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
15941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/*
15951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 * If there was no shell or command requested, there will be no remote
15961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 * exit status to be returned.  In that case, clear error code if the
15971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 * connection was deliberately terminated at this end.
15981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 */
15991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (no_shell_flag && received_signal == SIGTERM) {
16001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		received_signal = 0;
16011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		exit_status = 0;
16021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
16031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
16041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (received_signal)
16051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		fatal("Killed by signal %d.", (int) received_signal);
16061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
16071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/*
16081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 * In interactive mode (with pseudo tty) display a message indicating
16091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 * that the connection has been closed.
16101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 */
16111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (have_pty && options.log_level != SYSLOG_LEVEL_QUIET) {
16121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		snprintf(buf, sizeof buf,
16131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    "Connection to %.64s closed.\r\n", host);
16141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		buffer_append(&stderr_buffer, buf, strlen(buf));
16151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
16161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
16171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* Output any buffered data for stdout. */
16181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (buffer_len(&stdout_buffer) > 0) {
16191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		len = atomicio(vwrite, fileno(stdout),
16201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    buffer_ptr(&stdout_buffer), buffer_len(&stdout_buffer));
16211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (len < 0 || (u_int)len != buffer_len(&stdout_buffer))
16221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			error("Write failed flushing stdout buffer.");
16231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		else
16241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			buffer_consume(&stdout_buffer, len);
16251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
16261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
16271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* Output any buffered data for stderr. */
16281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (buffer_len(&stderr_buffer) > 0) {
16291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		len = atomicio(vwrite, fileno(stderr),
16301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    buffer_ptr(&stderr_buffer), buffer_len(&stderr_buffer));
16311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (len < 0 || (u_int)len != buffer_len(&stderr_buffer))
16321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			error("Write failed flushing stderr buffer.");
16331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		else
16341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			buffer_consume(&stderr_buffer, len);
16351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
16361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
16371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* Clear and free any buffers. */
16381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	memset(buf, 0, sizeof(buf));
16391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	buffer_free(&stdin_buffer);
16401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	buffer_free(&stdout_buffer);
16411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	buffer_free(&stderr_buffer);
16421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
16431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* Report bytes transferred, and transfer rates. */
16441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	total_time = get_current_time() - start_time;
16451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	packet_get_state(MODE_IN, NULL, NULL, NULL, &ibytes);
16461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	packet_get_state(MODE_OUT, NULL, NULL, NULL, &obytes);
16471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	verbose("Transferred: sent %llu, received %llu bytes, in %.1f seconds",
16481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    (unsigned long long)obytes, (unsigned long long)ibytes, total_time);
16491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (total_time > 0)
16501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		verbose("Bytes per second: sent %.1f, received %.1f",
16511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    obytes / total_time, ibytes / total_time);
16521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* Return the exit status of the program. */
16531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	debug("Exit status %d", exit_status);
16541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	return exit_status;
16551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
16561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
16571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/*********/
16581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
16591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic void
16601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodclient_input_stdout_data(int type, u_int32_t seq, void *ctxt)
16611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
16621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	u_int data_len;
16631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	char *data = packet_get_string(&data_len);
16641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	packet_check_eom();
16651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	buffer_append(&stdout_buffer, data, data_len);
16661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	memset(data, 0, data_len);
16671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	xfree(data);
16681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
16691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic void
16701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodclient_input_stderr_data(int type, u_int32_t seq, void *ctxt)
16711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
16721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	u_int data_len;
16731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	char *data = packet_get_string(&data_len);
16741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	packet_check_eom();
16751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	buffer_append(&stderr_buffer, data, data_len);
16761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	memset(data, 0, data_len);
16771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	xfree(data);
16781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
16791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic void
16801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodclient_input_exit_status(int type, u_int32_t seq, void *ctxt)
16811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
16821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	exit_status = packet_get_int();
16831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	packet_check_eom();
16841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* Acknowledge the exit. */
16851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	packet_start(SSH_CMSG_EXIT_CONFIRMATION);
16861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	packet_send();
16871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/*
16881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 * Must wait for packet to be sent since we are
16891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 * exiting the loop.
16901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 */
16911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	packet_write_wait();
16921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* Flag that we want to exit. */
16931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	quit_pending = 1;
16941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
16951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic void
16961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodclient_input_agent_open(int type, u_int32_t seq, void *ctxt)
16971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
16981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	Channel *c = NULL;
16991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	int remote_id, sock;
17001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
17011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* Read the remote channel number from the message. */
17021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	remote_id = packet_get_int();
17031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	packet_check_eom();
17041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
17051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/*
17061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 * Get a connection to the local authentication agent (this may again
17071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 * get forwarded).
17081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 */
17091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	sock = ssh_get_authentication_socket();
17101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
17111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/*
17121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 * If we could not connect the agent, send an error message back to
17131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 * the server. This should never happen unless the agent dies,
17141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 * because authentication forwarding is only enabled if we have an
17151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 * agent.
17161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 */
17171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (sock >= 0) {
17181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		c = channel_new("", SSH_CHANNEL_OPEN, sock, sock,
17191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    -1, 0, 0, 0, "authentication agent connection", 1);
17201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		c->remote_id = remote_id;
17211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		c->force_drain = 1;
17221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
17231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (c == NULL) {
17241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		packet_start(SSH_MSG_CHANNEL_OPEN_FAILURE);
17251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		packet_put_int(remote_id);
17261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	} else {
17271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		/* Send a confirmation to the remote host. */
17281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		debug("Forwarding authentication connection.");
17291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		packet_start(SSH_MSG_CHANNEL_OPEN_CONFIRMATION);
17301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		packet_put_int(remote_id);
17311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		packet_put_int(c->self);
17321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
17331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	packet_send();
17341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
17351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
17361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic Channel *
17371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodclient_request_forwarded_tcpip(const char *request_type, int rchan)
17381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
17391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	Channel *c = NULL;
17401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	char *listen_address, *originator_address;
17411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	u_short listen_port, originator_port;
17421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
17431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* Get rest of the packet */
17441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	listen_address = packet_get_string(NULL);
17451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	listen_port = packet_get_int();
17461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	originator_address = packet_get_string(NULL);
17471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	originator_port = packet_get_int();
17481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	packet_check_eom();
17491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
17501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	debug("client_request_forwarded_tcpip: listen %s port %d, "
17511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    "originator %s port %d", listen_address, listen_port,
17521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    originator_address, originator_port);
17531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
17541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	c = channel_connect_by_listen_address(listen_port,
17551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    "forwarded-tcpip", originator_address);
17561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
17571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	xfree(originator_address);
17581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	xfree(listen_address);
17591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	return c;
17601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
17611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
17621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic Channel *
17631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodclient_request_x11(const char *request_type, int rchan)
17641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
17651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	Channel *c = NULL;
17661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	char *originator;
17671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	u_short originator_port;
17681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	int sock;
17691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
17701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (!options.forward_x11) {
17711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		error("Warning: ssh server tried X11 forwarding.");
17721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		error("Warning: this is probably a break-in attempt by a "
17731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    "malicious server.");
17741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return NULL;
17751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
17761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (x11_refuse_time != 0 && time(NULL) >= x11_refuse_time) {
17771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		verbose("Rejected X11 connection after ForwardX11Timeout "
17781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    "expired");
17791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return NULL;
17801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
17811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	originator = packet_get_string(NULL);
17821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (datafellows & SSH_BUG_X11FWD) {
17831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		debug2("buggy server: x11 request w/o originator_port");
17841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		originator_port = 0;
17851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	} else {
17861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		originator_port = packet_get_int();
17871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
17881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	packet_check_eom();
17891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* XXX check permission */
17901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	debug("client_request_x11: request from %s %d", originator,
17911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    originator_port);
17921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	xfree(originator);
17931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	sock = x11_connect_display();
17941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (sock < 0)
17951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return NULL;
17961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	c = channel_new("x11",
17971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    SSH_CHANNEL_X11_OPEN, sock, sock, -1,
17981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    CHAN_TCP_WINDOW_DEFAULT, CHAN_X11_PACKET_DEFAULT, 0, "x11", 1);
17991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	c->force_drain = 1;
18001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	return c;
18011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
18021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
18031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic Channel *
18041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodclient_request_agent(const char *request_type, int rchan)
18051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
18061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	Channel *c = NULL;
18071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	int sock;
18081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
18091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (!options.forward_agent) {
18101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		error("Warning: ssh server tried agent forwarding.");
18111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		error("Warning: this is probably a break-in attempt by a "
18121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    "malicious server.");
18131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return NULL;
18141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
18151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	sock = ssh_get_authentication_socket();
18161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (sock < 0)
18171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return NULL;
18181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	c = channel_new("authentication agent connection",
18191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    SSH_CHANNEL_OPEN, sock, sock, -1,
18201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    CHAN_X11_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, 0,
18211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    "authentication agent connection", 1);
18221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	c->force_drain = 1;
18231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	return c;
18241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
18251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
18261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodint
18271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodclient_request_tun_fwd(int tun_mode, int local_tun, int remote_tun)
18281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
18291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	Channel *c;
18301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	int fd;
18311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
18321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (tun_mode == SSH_TUNMODE_NO)
18331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return 0;
18341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
18351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (!compat20) {
18361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		error("Tunnel forwarding is not supported for protocol 1");
18371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return -1;
18381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
18391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
18401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	debug("Requesting tun unit %d in mode %d", local_tun, tun_mode);
18411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
18421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* Open local tunnel device */
18431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if ((fd = tun_open(local_tun, tun_mode)) == -1) {
18441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		error("Tunnel device open failed.");
18451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return -1;
18461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
18471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
18481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	c = channel_new("tun", SSH_CHANNEL_OPENING, fd, fd, -1,
18491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, 0, "tun", 1);
18501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	c->datagram = 1;
18511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
18521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#if defined(SSH_TUN_FILTER)
18531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (options.tun_open == SSH_TUNMODE_POINTOPOINT)
18541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		channel_register_filter(c->self, sys_tun_infilter,
18551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    sys_tun_outfilter, NULL, NULL);
18561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif
18571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
18581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	packet_start(SSH2_MSG_CHANNEL_OPEN);
18591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	packet_put_cstring("tun@openssh.com");
18601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	packet_put_int(c->self);
18611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	packet_put_int(c->local_window_max);
18621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	packet_put_int(c->local_maxpacket);
18631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	packet_put_int(tun_mode);
18641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	packet_put_int(remote_tun);
18651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	packet_send();
18661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
18671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	return 0;
18681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
18691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
18701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* XXXX move to generic input handler */
18711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic void
18721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodclient_input_channel_open(int type, u_int32_t seq, void *ctxt)
18731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
18741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	Channel *c = NULL;
18751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	char *ctype;
18761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	int rchan;
18771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	u_int rmaxpack, rwindow, len;
18781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
18791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	ctype = packet_get_string(&len);
18801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	rchan = packet_get_int();
18811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	rwindow = packet_get_int();
18821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	rmaxpack = packet_get_int();
18831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
18841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	debug("client_input_channel_open: ctype %s rchan %d win %d max %d",
18851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    ctype, rchan, rwindow, rmaxpack);
18861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
18871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (strcmp(ctype, "forwarded-tcpip") == 0) {
18881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		c = client_request_forwarded_tcpip(ctype, rchan);
18891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	} else if (strcmp(ctype, "x11") == 0) {
18901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		c = client_request_x11(ctype, rchan);
18911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	} else if (strcmp(ctype, "auth-agent@openssh.com") == 0) {
18921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		c = client_request_agent(ctype, rchan);
18931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
18941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* XXX duplicate : */
18951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (c != NULL) {
18961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		debug("confirm %s", ctype);
18971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		c->remote_id = rchan;
18981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		c->remote_window = rwindow;
18991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		c->remote_maxpacket = rmaxpack;
19001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (c->type != SSH_CHANNEL_CONNECTING) {
19011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			packet_start(SSH2_MSG_CHANNEL_OPEN_CONFIRMATION);
19021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			packet_put_int(c->remote_id);
19031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			packet_put_int(c->self);
19041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			packet_put_int(c->local_window);
19051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			packet_put_int(c->local_maxpacket);
19061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			packet_send();
19071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
19081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	} else {
19091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		debug("failure %s", ctype);
19101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		packet_start(SSH2_MSG_CHANNEL_OPEN_FAILURE);
19111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		packet_put_int(rchan);
19121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		packet_put_int(SSH2_OPEN_ADMINISTRATIVELY_PROHIBITED);
19131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (!(datafellows & SSH_BUG_OPENFAILURE)) {
19141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			packet_put_cstring("open failed");
19151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			packet_put_cstring("");
19161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
19171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		packet_send();
19181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
19191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	xfree(ctype);
19201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
19211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic void
19221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodclient_input_channel_req(int type, u_int32_t seq, void *ctxt)
19231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
19241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	Channel *c = NULL;
19251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	int exitval, id, reply, success = 0;
19261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	char *rtype;
19271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
19281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	id = packet_get_int();
19291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	rtype = packet_get_string(NULL);
19301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	reply = packet_get_char();
19311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
19321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	debug("client_input_channel_req: channel %d rtype %s reply %d",
19331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    id, rtype, reply);
19341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
19351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (id == -1) {
19361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		error("client_input_channel_req: request for channel -1");
19371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	} else if ((c = channel_lookup(id)) == NULL) {
19381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		error("client_input_channel_req: channel %d: "
19391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    "unknown channel", id);
19401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	} else if (strcmp(rtype, "eow@openssh.com") == 0) {
19411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		packet_check_eom();
19421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		chan_rcvd_eow(c);
19431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	} else if (strcmp(rtype, "exit-status") == 0) {
19441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		exitval = packet_get_int();
19451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (c->ctl_chan != -1) {
19461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			mux_exit_message(c, exitval);
19471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			success = 1;
19481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		} else if (id == session_ident) {
19491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			/* Record exit value of local session */
19501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			success = 1;
19511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			exit_status = exitval;
19521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		} else {
19531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			/* Probably for a mux channel that has already closed */
19541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			debug("%s: no sink for exit-status on channel %d",
19551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			    __func__, id);
19561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
19571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		packet_check_eom();
19581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
19591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (reply && c != NULL) {
19601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		packet_start(success ?
19611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    SSH2_MSG_CHANNEL_SUCCESS : SSH2_MSG_CHANNEL_FAILURE);
19621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		packet_put_int(c->remote_id);
19631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		packet_send();
19641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
19651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	xfree(rtype);
19661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
19671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic void
19681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodclient_input_global_request(int type, u_int32_t seq, void *ctxt)
19691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
19701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	char *rtype;
19711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	int want_reply;
19721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	int success = 0;
19731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
19741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	rtype = packet_get_string(NULL);
19751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	want_reply = packet_get_char();
19761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	debug("client_input_global_request: rtype %s want_reply %d",
19771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    rtype, want_reply);
19781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (want_reply) {
19791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		packet_start(success ?
19801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    SSH2_MSG_REQUEST_SUCCESS : SSH2_MSG_REQUEST_FAILURE);
19811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		packet_send();
19821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		packet_write_wait();
19831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
19841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	xfree(rtype);
19851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
19861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
19871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodvoid
19881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodclient_session2_setup(int id, int want_tty, int want_subsystem,
19891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood    const char *term, struct termios *tiop, int in_fd, Buffer *cmd, char **env)
19901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
19911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	int len;
19921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	Channel *c = NULL;
19931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
19941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	debug2("%s: id %d", __func__, id);
19951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
19961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if ((c = channel_lookup(id)) == NULL)
19971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		fatal("client_session2_setup: channel %d: unknown channel", id);
19981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
19991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	packet_set_interactive(want_tty,
20001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    options.ip_qos_interactive, options.ip_qos_bulk);
20011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
20021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (want_tty) {
20031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		struct winsize ws;
20041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
20051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		/* Store window size in the packet. */
20061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (ioctl(in_fd, TIOCGWINSZ, &ws) < 0)
20071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			memset(&ws, 0, sizeof(ws));
20081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
20091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		channel_request_start(id, "pty-req", 1);
20101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		client_expect_confirm(id, "PTY allocation", CONFIRM_TTY);
20111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		packet_put_cstring(term != NULL ? term : "");
20121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		packet_put_int((u_int)ws.ws_col);
20131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		packet_put_int((u_int)ws.ws_row);
20141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		packet_put_int((u_int)ws.ws_xpixel);
20151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		packet_put_int((u_int)ws.ws_ypixel);
20161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (tiop == NULL)
20171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			tiop = get_saved_tio();
20181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		tty_make_modes(-1, tiop);
20191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		packet_send();
20201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		/* XXX wait for reply */
20211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		c->client_tty = 1;
20221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
20231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
20241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* Transfer any environment variables from client to server */
20251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (options.num_send_env != 0 && env != NULL) {
20261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		int i, j, matched;
20271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		char *name, *val;
20281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
20291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		debug("Sending environment.");
20301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		for (i = 0; env[i] != NULL; i++) {
20311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			/* Split */
20321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			name = xstrdup(env[i]);
20331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			if ((val = strchr(name, '=')) == NULL) {
20341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				xfree(name);
20351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				continue;
20361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			}
20371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			*val++ = '\0';
20381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
20391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			matched = 0;
20401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			for (j = 0; j < options.num_send_env; j++) {
20411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				if (match_pattern(name, options.send_env[j])) {
20421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					matched = 1;
20431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					break;
20441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				}
20451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			}
20461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			if (!matched) {
20471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				debug3("Ignored env %s", name);
20481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				xfree(name);
20491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				continue;
20501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			}
20511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
20521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			debug("Sending env %s = %s", name, val);
20531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			channel_request_start(id, "env", 0);
20541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			packet_put_cstring(name);
20551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			packet_put_cstring(val);
20561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			packet_send();
20571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			xfree(name);
20581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
20591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
20601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
20611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	len = buffer_len(cmd);
20621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (len > 0) {
20631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (len > 900)
20641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			len = 900;
20651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (want_subsystem) {
20661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			debug("Sending subsystem: %.*s",
20671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			    len, (u_char*)buffer_ptr(cmd));
20681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			channel_request_start(id, "subsystem", 1);
20691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			client_expect_confirm(id, "subsystem", CONFIRM_CLOSE);
20701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		} else {
20711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			debug("Sending command: %.*s",
20721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			    len, (u_char*)buffer_ptr(cmd));
20731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			channel_request_start(id, "exec", 1);
20741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			client_expect_confirm(id, "exec", CONFIRM_CLOSE);
20751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
20761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		packet_put_string(buffer_ptr(cmd), buffer_len(cmd));
20771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		packet_send();
20781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	} else {
20791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		channel_request_start(id, "shell", 1);
20801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		client_expect_confirm(id, "shell", CONFIRM_CLOSE);
20811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		packet_send();
20821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
20831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
20841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
20851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic void
20861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodclient_init_dispatch_20(void)
20871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
20881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	dispatch_init(&dispatch_protocol_error);
20891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
20901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	dispatch_set(SSH2_MSG_CHANNEL_CLOSE, &channel_input_oclose);
20911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	dispatch_set(SSH2_MSG_CHANNEL_DATA, &channel_input_data);
20921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	dispatch_set(SSH2_MSG_CHANNEL_EOF, &channel_input_ieof);
20931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	dispatch_set(SSH2_MSG_CHANNEL_EXTENDED_DATA, &channel_input_extended_data);
20941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	dispatch_set(SSH2_MSG_CHANNEL_OPEN, &client_input_channel_open);
20951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	dispatch_set(SSH2_MSG_CHANNEL_OPEN_CONFIRMATION, &channel_input_open_confirmation);
20961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	dispatch_set(SSH2_MSG_CHANNEL_OPEN_FAILURE, &channel_input_open_failure);
20971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	dispatch_set(SSH2_MSG_CHANNEL_REQUEST, &client_input_channel_req);
20981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	dispatch_set(SSH2_MSG_CHANNEL_WINDOW_ADJUST, &channel_input_window_adjust);
20991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	dispatch_set(SSH2_MSG_CHANNEL_SUCCESS, &channel_input_status_confirm);
21001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	dispatch_set(SSH2_MSG_CHANNEL_FAILURE, &channel_input_status_confirm);
21011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	dispatch_set(SSH2_MSG_GLOBAL_REQUEST, &client_input_global_request);
21021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
21031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* rekeying */
21041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	dispatch_set(SSH2_MSG_KEXINIT, &kex_input_kexinit);
21051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
21061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* global request reply messages */
21071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	dispatch_set(SSH2_MSG_REQUEST_FAILURE, &client_global_request_reply);
21081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	dispatch_set(SSH2_MSG_REQUEST_SUCCESS, &client_global_request_reply);
21091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
21101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
21111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic void
21121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodclient_init_dispatch_13(void)
21131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
21141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	dispatch_init(NULL);
21151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	dispatch_set(SSH_MSG_CHANNEL_CLOSE, &channel_input_close);
21161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	dispatch_set(SSH_MSG_CHANNEL_CLOSE_CONFIRMATION, &channel_input_close_confirmation);
21171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	dispatch_set(SSH_MSG_CHANNEL_DATA, &channel_input_data);
21181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	dispatch_set(SSH_MSG_CHANNEL_OPEN_CONFIRMATION, &channel_input_open_confirmation);
21191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	dispatch_set(SSH_MSG_CHANNEL_OPEN_FAILURE, &channel_input_open_failure);
21201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	dispatch_set(SSH_MSG_PORT_OPEN, &channel_input_port_open);
21211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	dispatch_set(SSH_SMSG_EXITSTATUS, &client_input_exit_status);
21221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	dispatch_set(SSH_SMSG_STDERR_DATA, &client_input_stderr_data);
21231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	dispatch_set(SSH_SMSG_STDOUT_DATA, &client_input_stdout_data);
21241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
21251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	dispatch_set(SSH_SMSG_AGENT_OPEN, options.forward_agent ?
21261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    &client_input_agent_open : &deny_input_open);
21271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	dispatch_set(SSH_SMSG_X11_OPEN, options.forward_x11 ?
21281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    &x11_input_open : &deny_input_open);
21291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
21301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
21311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic void
21321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodclient_init_dispatch_15(void)
21331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
21341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	client_init_dispatch_13();
21351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	dispatch_set(SSH_MSG_CHANNEL_CLOSE, &channel_input_ieof);
21361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	dispatch_set(SSH_MSG_CHANNEL_CLOSE_CONFIRMATION, & channel_input_oclose);
21371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
21381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
21391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic void
21401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodclient_init_dispatch(void)
21411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
21421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (compat20)
21431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		client_init_dispatch_20();
21441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	else if (compat13)
21451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		client_init_dispatch_13();
21461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	else
21471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		client_init_dispatch_15();
21481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
21491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
21501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodvoid
21511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodclient_stop_mux(void)
21521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
21531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (options.control_path != NULL && muxserver_sock != -1)
21541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		unlink(options.control_path);
21551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/*
21561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 * If we are in persist mode, signal that we should close when all
21571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 * active channels are closed.
21581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 */
21591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (options.control_persist) {
21601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		session_closed = 1;
21611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		setproctitle("[stopped mux]");
21621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
21631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
21641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
21651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* client specific fatal cleanup */
21661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodvoid
21671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodcleanup_exit(int i)
21681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
21691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	leave_raw_mode(options.request_tty == REQUEST_TTY_FORCE);
21701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	leave_non_blocking();
21711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (options.control_path != NULL && muxserver_sock != -1)
21721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		unlink(options.control_path);
21731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	ssh_kill_proxy_command();
21741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	_exit(i);
21751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
2176