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