clientloop.c revision 137015
159024Sobrien/*
2130561Sobrien * Author: Tatu Ylonen <ylo@cs.hut.fi>
3218822Sdim * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
459024Sobrien *                    All rights reserved
5130561Sobrien * The main loop for the interactive session (client side).
659024Sobrien *
7130561Sobrien * As far as I am concerned, the code I have written for this software
8130561Sobrien * can be used freely for any purpose.  Any derived versions of this
9130561Sobrien * software must be clearly marked as such, and if the derived work is
10130561Sobrien * incompatible with the protocol description in the RFC file, it must be
1159024Sobrien * called by a name other than "ssh" or "Secure Shell".
12130561Sobrien *
13130561Sobrien *
14130561Sobrien * Copyright (c) 1999 Theo de Raadt.  All rights reserved.
15130561Sobrien *
1659024Sobrien * Redistribution and use in source and binary forms, with or without
17130561Sobrien * modification, are permitted provided that the following conditions
18130561Sobrien * are met:
19218822Sdim * 1. Redistributions of source code must retain the above copyright
2059024Sobrien *    notice, this list of conditions and the following disclaimer.
21218822Sdim * 2. Redistributions in binary form must reproduce the above copyright
2259024Sobrien *    notice, this list of conditions and the following disclaimer in the
2359024Sobrien *    documentation and/or other materials provided with the distribution.
2459024Sobrien *
2559024Sobrien * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
2659024Sobrien * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
2777298Sobrien * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
28218822Sdim * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
29218822Sdim * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
3059024Sobrien * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
31130561Sobrien * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
32130561Sobrien * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
33130561Sobrien * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
34130561Sobrien * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35130561Sobrien *
36130561Sobrien *
37130561Sobrien * SSH2 support added by Markus Friedl.
38130561Sobrien * Copyright (c) 1999, 2000, 2001 Markus Friedl.  All rights reserved.
39130561Sobrien *
40130561Sobrien * Redistribution and use in source and binary forms, with or without
41130561Sobrien * modification, are permitted provided that the following conditions
42130561Sobrien * are met:
43130561Sobrien * 1. Redistributions of source code must retain the above copyright
44130561Sobrien *    notice, this list of conditions and the following disclaimer.
45130561Sobrien * 2. Redistributions in binary form must reproduce the above copyright
46130561Sobrien *    notice, this list of conditions and the following disclaimer in the
47130561Sobrien *    documentation and/or other materials provided with the distribution.
48130561Sobrien *
49130561Sobrien * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
50130561Sobrien * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
51130561Sobrien * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
52130561Sobrien * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
53130561Sobrien * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
54130561Sobrien * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
55130561Sobrien * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
56130561Sobrien * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
57130561Sobrien * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
58130561Sobrien * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
5959024Sobrien */
6059024Sobrien
6159024Sobrien#include "includes.h"
6259024SobrienRCSID("$OpenBSD: clientloop.c,v 1.130 2004/08/11 21:43:04 avsm Exp $");
6359024Sobrien
6459024Sobrien#include "ssh.h"
6559024Sobrien#include "ssh1.h"
6659024Sobrien#include "ssh2.h"
6759024Sobrien#include "xmalloc.h"
6859024Sobrien#include "packet.h"
69130561Sobrien#include "buffer.h"
70218822Sdim#include "compat.h"
7159024Sobrien#include "channels.h"
72130561Sobrien#include "dispatch.h"
73218822Sdim#include "buffer.h"
7460484Sobrien#include "bufaux.h"
7560484Sobrien#include "key.h"
7659024Sobrien#include "kex.h"
7759024Sobrien#include "log.h"
7859024Sobrien#include "readconf.h"
79130561Sobrien#include "clientloop.h"
8059024Sobrien#include "authfd.h"
81130561Sobrien#include "atomicio.h"
8259024Sobrien#include "sshpty.h"
83218822Sdim#include "misc.h"
84218822Sdim#include "monitor_fdpass.h"
8559024Sobrien#include "match.h"
86130561Sobrien#include "msg.h"
8759024Sobrien
88218822Sdim/* import options */
8959024Sobrienextern Options options;
9060484Sobrien
9160484Sobrien/* Flag indicating that stdin should be redirected from /dev/null. */
92218822Sdimextern int stdin_null_flag;
93218822Sdim
9460484Sobrien/* Flag indicating that no shell has been requested */
9559024Sobrienextern int no_shell_flag;
9660484Sobrien
9760484Sobrien/* Control socket */
9860484Sobrienextern int control_fd;
9960484Sobrien
10060484Sobrien/*
101218822Sdim * Name of the host we are connecting to.  This is the name given on the
102130561Sobrien * command line, or the HostName specified for the user-supplied name in a
10360484Sobrien * configuration file.
10460484Sobrien */
10560484Sobrienextern char *host;
10659024Sobrien
10759024Sobrien/*
10859024Sobrien * Flag to indicate that we have received a window change signal which has
109130561Sobrien * not yet been processed.  This will cause a message indicating the new
11059024Sobrien * window size to be sent to the server a little later.  This is volatile
11159024Sobrien * because this is updated in a signal handler.
112130561Sobrien */
11359024Sobrienstatic volatile sig_atomic_t received_window_change_signal = 0;
11459024Sobrienstatic volatile sig_atomic_t received_signal = 0;
11559024Sobrien
11659024Sobrien/* Flag indicating whether the user\'s terminal is in non-blocking mode. */
11759024Sobrienstatic int in_non_blocking_mode = 0;
11859024Sobrien
119218822Sdim/* Common data for the client loop code. */
120218822Sdimstatic int quit_pending;	/* Set to non-zero to quit the client loop. */
12159024Sobrienstatic int escape_char;		/* Escape character. */
12259024Sobrienstatic int escape_pending;	/* Last character was the escape character */
12359024Sobrienstatic int last_was_cr;		/* Last character was a newline. */
12459024Sobrienstatic int exit_status;		/* Used to store the exit status of the command. */
125218822Sdimstatic int stdin_eof;		/* EOF has been encountered on standard error. */
126218822Sdimstatic Buffer stdin_buffer;	/* Buffer for stdin data. */
12759024Sobrienstatic Buffer stdout_buffer;	/* Buffer for stdout data. */
12859024Sobrienstatic Buffer stderr_buffer;	/* Buffer for stderr data. */
12959024Sobrienstatic u_long stdin_bytes, stdout_bytes, stderr_bytes;
13059024Sobrienstatic u_int buffer_high;/* Soft max buffer size. */
13159024Sobrienstatic int connection_in;	/* Connection to server (input). */
13259024Sobrienstatic int connection_out;	/* Connection to server (output). */
13359024Sobrienstatic int need_rekeying;	/* Set to non-zero if rekeying is requested. */
13459024Sobrienstatic int session_closed = 0;	/* In SSH2: login session closed. */
13559024Sobrienstatic int server_alive_timeouts = 0;
13659024Sobrien
13759024Sobrienstatic void client_init_dispatch(void);
13877298Sobrienint	session_ident = -1;
13977298Sobrien
14077298Sobrienstruct confirm_ctx {
14177298Sobrien	int want_tty;
14277298Sobrien	int want_subsys;
14377298Sobrien	Buffer cmd;
14460484Sobrien	char *term;
14560484Sobrien	struct termios tio;
14660484Sobrien	char **env;
14759024Sobrien};
14859024Sobrien
14960484Sobrien/*XXX*/
15059024Sobrienextern Kex *xxx_kex;
15159024Sobrien
15289857Sobrienvoid ssh_process_session2_setup(int, int, int, Buffer *);
15389857Sobrien
154218822Sdim/* Restores stdin to blocking mode. */
15589857Sobrien
15689857Sobrienstatic void
15789857Sobrienleave_non_blocking(void)
15889857Sobrien{
15989857Sobrien	if (in_non_blocking_mode) {
16089857Sobrien		unset_nonblock(fileno(stdin));
16189857Sobrien		in_non_blocking_mode = 0;
16289857Sobrien	}
16389857Sobrien}
16489857Sobrien
16589857Sobrien/* Puts stdin terminal in non-blocking mode. */
16689857Sobrien
16789857Sobrienstatic void
168218822Sdimenter_non_blocking(void)
16959024Sobrien{
17059024Sobrien	in_non_blocking_mode = 1;
17159024Sobrien	set_nonblock(fileno(stdin));
17259024Sobrien}
17359024Sobrien
17459024Sobrien/*
175218822Sdim * Signal handler for the window change signal (SIGWINCH).  This just sets a
17659024Sobrien * flag indicating that the window has changed.
177218822Sdim */
178218822Sdim
179218822Sdimstatic void
180218822Sdimwindow_change_handler(int sig)
181218822Sdim{
182218822Sdim	received_window_change_signal = 1;
183218822Sdim	signal(SIGWINCH, window_change_handler);
184218822Sdim}
185218822Sdim
186218822Sdim/*
187218822Sdim * Signal handler for signals that cause the program to terminate.  These
188130561Sobrien * signals must be trapped to restore terminal modes.
189218822Sdim */
190218822Sdim
191218822Sdimstatic void
192130561Sobriensignal_handler(int sig)
193218822Sdim{
19459024Sobrien	received_signal = sig;
195218822Sdim	quit_pending = 1;
196218822Sdim}
19759024Sobrien
198218822Sdim/*
199218822Sdim * Returns current time in seconds from Jan 1, 1970 with the maximum
20059024Sobrien * available resolution.
201218822Sdim */
202218822Sdim
20359024Sobrienstatic double
204218822Sdimget_current_time(void)
20559024Sobrien{
206218822Sdim	struct timeval tv;
207218822Sdim	gettimeofday(&tv, NULL);
208218822Sdim	return (double) tv.tv_sec + (double) tv.tv_usec / 1000000.0;
209218822Sdim}
210218822Sdim
211218822Sdim/*
212218822Sdim * This is called when the interactive is entered.  This checks if there is
21360484Sobrien * an EOF coming on stdin.  We must check this explicitly, as select() does
21460484Sobrien * not appear to wake up when redirecting from /dev/null.
215130561Sobrien */
21659024Sobrien
21759024Sobrienstatic void
21859024Sobrienclient_check_initial_eof_on_stdin(void)
21960484Sobrien{
220130561Sobrien	int len;
22159024Sobrien	char buf[1];
22259024Sobrien
223218822Sdim	/*
224218822Sdim	 * If standard input is to be "redirected from /dev/null", we simply
225218822Sdim	 * mark that we have seen an EOF and send an EOF message to the
226218822Sdim	 * server. Otherwise, we try to read a single character; it appears
227218822Sdim	 * that for some files, such /dev/null, select() never wakes up for
228218822Sdim	 * read for this descriptor, which means that we never get EOF.  This
229218822Sdim	 * way we will get the EOF if stdin comes from /dev/null or similar.
230218822Sdim	 */
231218822Sdim	if (stdin_null_flag) {
232218822Sdim		/* Fake EOF on stdin. */
233218822Sdim		debug("Sending eof.");
234218822Sdim		stdin_eof = 1;
235218822Sdim		packet_start(SSH_CMSG_EOF);
236218822Sdim		packet_send();
237218822Sdim	} else {
238218822Sdim		enter_non_blocking();
239218822Sdim
240218822Sdim		/* Check for immediate EOF on stdin. */
241218822Sdim		len = read(fileno(stdin), buf, 1);
242218822Sdim		if (len == 0) {
243218822Sdim			/* EOF.  Record that we have seen it and send EOF to server. */
244218822Sdim			debug("Sending eof.");
245218822Sdim			stdin_eof = 1;
246218822Sdim			packet_start(SSH_CMSG_EOF);
247218822Sdim			packet_send();
248218822Sdim		} else if (len > 0) {
249218822Sdim			/*
250218822Sdim			 * Got data.  We must store the data in the buffer,
251218822Sdim			 * and also process it as an escape character if
252218822Sdim			 * appropriate.
253218822Sdim			 */
254218822Sdim			if ((u_char) buf[0] == escape_char)
255218822Sdim				escape_pending = 1;
256218822Sdim			else
257218822Sdim				buffer_append(&stdin_buffer, buf, 1);
258218822Sdim		}
259218822Sdim		leave_non_blocking();
260218822Sdim	}
261218822Sdim}
262218822Sdim
263218822Sdim
264218822Sdim/*
265218822Sdim * Make packets from buffered stdin data, and buffer them for sending to the
266218822Sdim * connection.
267218822Sdim */
268218822Sdim
269218822Sdimstatic void
270218822Sdimclient_make_packets_from_stdin_data(void)
271218822Sdim{
272218822Sdim	u_int len;
273218822Sdim
274218822Sdim	/* Send buffered stdin data to the server. */
275218822Sdim	while (buffer_len(&stdin_buffer) > 0 &&
276218822Sdim	    packet_not_very_much_data_to_write()) {
277218822Sdim		len = buffer_len(&stdin_buffer);
278218822Sdim		/* Keep the packets at reasonable size. */
279218822Sdim		if (len > packet_get_maxsize())
280218822Sdim			len = packet_get_maxsize();
281218822Sdim		packet_start(SSH_CMSG_STDIN_DATA);
282218822Sdim		packet_put_string(buffer_ptr(&stdin_buffer), len);
283218822Sdim		packet_send();
284218822Sdim		buffer_consume(&stdin_buffer, len);
285218822Sdim		stdin_bytes += len;
286218822Sdim		/* If we have a pending EOF, send it now. */
287218822Sdim		if (stdin_eof && buffer_len(&stdin_buffer) == 0) {
288			packet_start(SSH_CMSG_EOF);
289			packet_send();
290		}
291	}
292}
293
294/*
295 * Checks if the client window has changed, and sends a packet about it to
296 * the server if so.  The actual change is detected elsewhere (by a software
297 * interrupt on Unix); this just checks the flag and sends a message if
298 * appropriate.
299 */
300
301static void
302client_check_window_change(void)
303{
304	struct winsize ws;
305
306	if (! received_window_change_signal)
307		return;
308	/** XXX race */
309	received_window_change_signal = 0;
310
311	debug2("client_check_window_change: changed");
312
313	if (compat20) {
314		channel_send_window_changes();
315	} else {
316		if (ioctl(fileno(stdin), TIOCGWINSZ, &ws) < 0)
317			return;
318		packet_start(SSH_CMSG_WINDOW_SIZE);
319		packet_put_int(ws.ws_row);
320		packet_put_int(ws.ws_col);
321		packet_put_int(ws.ws_xpixel);
322		packet_put_int(ws.ws_ypixel);
323		packet_send();
324	}
325}
326
327static void
328client_global_request_reply(int type, u_int32_t seq, void *ctxt)
329{
330	server_alive_timeouts = 0;
331	client_global_request_reply_fwd(type, seq, ctxt);
332}
333
334static void
335server_alive_check(void)
336{
337	if (++server_alive_timeouts > options.server_alive_count_max)
338		packet_disconnect("Timeout, server not responding.");
339	packet_start(SSH2_MSG_GLOBAL_REQUEST);
340	packet_put_cstring("keepalive@openssh.com");
341	packet_put_char(1);     /* boolean: want reply */
342	packet_send();
343}
344
345/*
346 * Waits until the client can do something (some data becomes available on
347 * one of the file descriptors).
348 */
349static void
350client_wait_until_can_do_something(fd_set **readsetp, fd_set **writesetp,
351    int *maxfdp, u_int *nallocp, int rekeying)
352{
353	struct timeval tv, *tvp;
354	int ret;
355
356	/* Add any selections by the channel mechanism. */
357	channel_prepare_select(readsetp, writesetp, maxfdp, nallocp, rekeying);
358
359	if (!compat20) {
360		/* Read from the connection, unless our buffers are full. */
361		if (buffer_len(&stdout_buffer) < buffer_high &&
362		    buffer_len(&stderr_buffer) < buffer_high &&
363		    channel_not_very_much_buffered_data())
364			FD_SET(connection_in, *readsetp);
365		/*
366		 * Read from stdin, unless we have seen EOF or have very much
367		 * buffered data to send to the server.
368		 */
369		if (!stdin_eof && packet_not_very_much_data_to_write())
370			FD_SET(fileno(stdin), *readsetp);
371
372		/* Select stdout/stderr if have data in buffer. */
373		if (buffer_len(&stdout_buffer) > 0)
374			FD_SET(fileno(stdout), *writesetp);
375		if (buffer_len(&stderr_buffer) > 0)
376			FD_SET(fileno(stderr), *writesetp);
377	} else {
378		/* channel_prepare_select could have closed the last channel */
379		if (session_closed && !channel_still_open() &&
380		    !packet_have_data_to_write()) {
381			/* clear mask since we did not call select() */
382			memset(*readsetp, 0, *nallocp);
383			memset(*writesetp, 0, *nallocp);
384			return;
385		} else {
386			FD_SET(connection_in, *readsetp);
387		}
388	}
389
390	/* Select server connection if have data to write to the server. */
391	if (packet_have_data_to_write())
392		FD_SET(connection_out, *writesetp);
393
394	if (control_fd != -1)
395		FD_SET(control_fd, *readsetp);
396
397	/*
398	 * Wait for something to happen.  This will suspend the process until
399	 * some selected descriptor can be read, written, or has some other
400	 * event pending.
401	 */
402
403	if (options.server_alive_interval == 0 || !compat20)
404		tvp = NULL;
405	else {
406		tv.tv_sec = options.server_alive_interval;
407		tv.tv_usec = 0;
408		tvp = &tv;
409	}
410	ret = select((*maxfdp)+1, *readsetp, *writesetp, NULL, tvp);
411	if (ret < 0) {
412		char buf[100];
413
414		/*
415		 * We have to clear the select masks, because we return.
416		 * We have to return, because the mainloop checks for the flags
417		 * set by the signal handlers.
418		 */
419		memset(*readsetp, 0, *nallocp);
420		memset(*writesetp, 0, *nallocp);
421
422		if (errno == EINTR)
423			return;
424		/* Note: we might still have data in the buffers. */
425		snprintf(buf, sizeof buf, "select: %s\r\n", strerror(errno));
426		buffer_append(&stderr_buffer, buf, strlen(buf));
427		quit_pending = 1;
428	} else if (ret == 0)
429		server_alive_check();
430}
431
432static void
433client_suspend_self(Buffer *bin, Buffer *bout, Buffer *berr)
434{
435	struct winsize oldws, newws;
436
437	/* Flush stdout and stderr buffers. */
438	if (buffer_len(bout) > 0)
439		atomicio(vwrite, fileno(stdout), buffer_ptr(bout), buffer_len(bout));
440	if (buffer_len(berr) > 0)
441		atomicio(vwrite, fileno(stderr), buffer_ptr(berr), buffer_len(berr));
442
443	leave_raw_mode();
444
445	/*
446	 * Free (and clear) the buffer to reduce the amount of data that gets
447	 * written to swap.
448	 */
449	buffer_free(bin);
450	buffer_free(bout);
451	buffer_free(berr);
452
453	/* Save old window size. */
454	ioctl(fileno(stdin), TIOCGWINSZ, &oldws);
455
456	/* Send the suspend signal to the program itself. */
457	kill(getpid(), SIGTSTP);
458
459	/* Check if the window size has changed. */
460	if (ioctl(fileno(stdin), TIOCGWINSZ, &newws) >= 0 &&
461	    (oldws.ws_row != newws.ws_row ||
462	    oldws.ws_col != newws.ws_col ||
463	    oldws.ws_xpixel != newws.ws_xpixel ||
464	    oldws.ws_ypixel != newws.ws_ypixel))
465		received_window_change_signal = 1;
466
467	/* OK, we have been continued by the user. Reinitialize buffers. */
468	buffer_init(bin);
469	buffer_init(bout);
470	buffer_init(berr);
471
472	enter_raw_mode();
473}
474
475static void
476client_process_net_input(fd_set * readset)
477{
478	int len;
479	char buf[8192];
480
481	/*
482	 * Read input from the server, and add any such data to the buffer of
483	 * the packet subsystem.
484	 */
485	if (FD_ISSET(connection_in, readset)) {
486		/* Read as much as possible. */
487		len = read(connection_in, buf, sizeof(buf));
488		if (len == 0) {
489			/* Received EOF.  The remote host has closed the connection. */
490			snprintf(buf, sizeof buf, "Connection to %.300s closed by remote host.\r\n",
491				 host);
492			buffer_append(&stderr_buffer, buf, strlen(buf));
493			quit_pending = 1;
494			return;
495		}
496		/*
497		 * There is a kernel bug on Solaris that causes select to
498		 * sometimes wake up even though there is no data available.
499		 */
500		if (len < 0 && (errno == EAGAIN || errno == EINTR))
501			len = 0;
502
503		if (len < 0) {
504			/* An error has encountered.  Perhaps there is a network problem. */
505			snprintf(buf, sizeof buf, "Read from remote host %.300s: %.100s\r\n",
506				 host, strerror(errno));
507			buffer_append(&stderr_buffer, buf, strlen(buf));
508			quit_pending = 1;
509			return;
510		}
511		packet_process_incoming(buf, len);
512	}
513}
514
515static void
516client_subsystem_reply(int type, u_int32_t seq, void *ctxt)
517{
518	int id;
519	Channel *c;
520
521	id = packet_get_int();
522	packet_check_eom();
523
524	if ((c = channel_lookup(id)) == NULL) {
525		error("%s: no channel for id %d", __func__, id);
526		return;
527	}
528
529	if (type == SSH2_MSG_CHANNEL_SUCCESS)
530		debug2("Request suceeded on channel %d", id);
531	else if (type == SSH2_MSG_CHANNEL_FAILURE) {
532		error("Request failed on channel %d", id);
533		channel_free(c);
534	}
535}
536
537static void
538client_extra_session2_setup(int id, void *arg)
539{
540	struct confirm_ctx *cctx = arg;
541	Channel *c;
542	int i;
543
544	if (cctx == NULL)
545		fatal("%s: cctx == NULL", __func__);
546	if ((c = channel_lookup(id)) == NULL)
547		fatal("%s: no channel for id %d", __func__, id);
548
549	client_session2_setup(id, cctx->want_tty, cctx->want_subsys,
550	    cctx->term, &cctx->tio, c->rfd, &cctx->cmd, cctx->env,
551	    client_subsystem_reply);
552
553	c->confirm_ctx = NULL;
554	buffer_free(&cctx->cmd);
555	xfree(cctx->term);
556	if (cctx->env != NULL) {
557		for (i = 0; cctx->env[i] != NULL; i++)
558			xfree(cctx->env[i]);
559		xfree(cctx->env);
560	}
561	xfree(cctx);
562}
563
564static void
565client_process_control(fd_set * readset)
566{
567	Buffer m;
568	Channel *c;
569	int client_fd, new_fd[3], ver, i, allowed;
570	socklen_t addrlen;
571	struct sockaddr_storage addr;
572	struct confirm_ctx *cctx;
573	char *cmd;
574	u_int len, env_len;
575	uid_t euid;
576	gid_t egid;
577
578	/*
579	 * Accept connection on control socket
580	 */
581	if (control_fd == -1 || !FD_ISSET(control_fd, readset))
582		return;
583
584	memset(&addr, 0, sizeof(addr));
585	addrlen = sizeof(addr);
586	if ((client_fd = accept(control_fd,
587	    (struct sockaddr*)&addr, &addrlen)) == -1) {
588		error("%s accept: %s", __func__, strerror(errno));
589		return;
590	}
591
592	if (getpeereid(client_fd, &euid, &egid) < 0) {
593		error("%s getpeereid failed: %s", __func__, strerror(errno));
594		close(client_fd);
595		return;
596	}
597	if ((euid != 0) && (getuid() != euid)) {
598		error("control mode uid mismatch: peer euid %u != uid %u",
599		    (u_int) euid, (u_int) getuid());
600		close(client_fd);
601		return;
602	}
603
604	allowed = 1;
605	if (options.control_master == 2) {
606		char *p, prompt[1024];
607
608		allowed = 0;
609		snprintf(prompt, sizeof(prompt),
610		    "Allow shared connection to %s? ", host);
611		p = read_passphrase(prompt, RP_USE_ASKPASS|RP_ALLOW_EOF);
612		if (p != NULL) {
613			/*
614			 * Accept empty responses and responses consisting
615			 * of the word "yes" as affirmative.
616			 */
617			if (*p == '\0' || *p == '\n' ||
618			    strcasecmp(p, "yes") == 0)
619				allowed = 1;
620			xfree(p);
621		}
622	}
623
624	unset_nonblock(client_fd);
625
626	buffer_init(&m);
627
628	buffer_put_int(&m, allowed);
629	buffer_put_int(&m, getpid());
630	if (ssh_msg_send(client_fd, /* version */0, &m) == -1) {
631		error("%s: client msg_send failed", __func__);
632		close(client_fd);
633		buffer_free(&m);
634		return;
635	}
636	buffer_clear(&m);
637
638	if (!allowed) {
639		error("Refused control connection");
640		close(client_fd);
641		buffer_free(&m);
642		return;
643	}
644
645	if (ssh_msg_recv(client_fd, &m) == -1) {
646		error("%s: client msg_recv failed", __func__);
647		close(client_fd);
648		buffer_free(&m);
649		return;
650	}
651
652	if ((ver = buffer_get_char(&m)) != 0) {
653		error("%s: wrong client version %d", __func__, ver);
654		buffer_free(&m);
655		close(client_fd);
656		return;
657	}
658
659	cctx = xmalloc(sizeof(*cctx));
660	memset(cctx, 0, sizeof(*cctx));
661
662	cctx->want_tty = buffer_get_int(&m);
663	cctx->want_subsys = buffer_get_int(&m);
664	cctx->term = buffer_get_string(&m, &len);
665
666	cmd = buffer_get_string(&m, &len);
667	buffer_init(&cctx->cmd);
668	buffer_append(&cctx->cmd, cmd, strlen(cmd));
669
670	env_len = buffer_get_int(&m);
671	env_len = MIN(env_len, 4096);
672	debug3("%s: receiving %d env vars", __func__, env_len);
673	if (env_len != 0) {
674		cctx->env = xmalloc(sizeof(*cctx->env) * (env_len + 1));
675		for (i = 0; i < env_len; i++)
676			cctx->env[i] = buffer_get_string(&m, &len);
677		cctx->env[i] = NULL;
678	}
679
680	debug2("%s: accepted tty %d, subsys %d, cmd %s", __func__,
681	    cctx->want_tty, cctx->want_subsys, cmd);
682
683	/* Gather fds from client */
684	new_fd[0] = mm_receive_fd(client_fd);
685	new_fd[1] = mm_receive_fd(client_fd);
686	new_fd[2] = mm_receive_fd(client_fd);
687
688	debug2("%s: got fds stdin %d, stdout %d, stderr %d", __func__,
689	    new_fd[0], new_fd[1], new_fd[2]);
690
691	/* Try to pick up ttymodes from client before it goes raw */
692	if (cctx->want_tty && tcgetattr(new_fd[0], &cctx->tio) == -1)
693		error("%s: tcgetattr: %s", __func__, strerror(errno));
694
695	buffer_clear(&m);
696	if (ssh_msg_send(client_fd, /* version */0, &m) == -1) {
697		error("%s: client msg_send failed", __func__);
698		close(client_fd);
699		close(new_fd[0]);
700		close(new_fd[1]);
701		close(new_fd[2]);
702		buffer_free(&m);
703		return;
704	}
705	buffer_free(&m);
706
707	/* enable nonblocking unless tty */
708	if (!isatty(new_fd[0]))
709		set_nonblock(new_fd[0]);
710	if (!isatty(new_fd[1]))
711		set_nonblock(new_fd[1]);
712	if (!isatty(new_fd[2]))
713		set_nonblock(new_fd[2]);
714
715	set_nonblock(client_fd);
716
717	c = channel_new("session", SSH_CHANNEL_OPENING,
718	    new_fd[0], new_fd[1], new_fd[2],
719	    CHAN_SES_WINDOW_DEFAULT, CHAN_SES_PACKET_DEFAULT,
720	    CHAN_EXTENDED_WRITE, "client-session", /*nonblock*/0);
721
722	/* XXX */
723	c->ctl_fd = client_fd;
724
725	debug3("%s: channel_new: %d", __func__, c->self);
726
727	channel_send_open(c->self);
728	channel_register_confirm(c->self, client_extra_session2_setup, cctx);
729}
730
731static void
732process_cmdline(void)
733{
734	void (*handler)(int);
735	char *s, *cmd;
736	u_short fwd_port, fwd_host_port;
737	char buf[1024], sfwd_port[6], sfwd_host_port[6];
738	int delete = 0;
739	int local = 0;
740
741	leave_raw_mode();
742	handler = signal(SIGINT, SIG_IGN);
743	cmd = s = read_passphrase("\r\nssh> ", RP_ECHO);
744	if (s == NULL)
745		goto out;
746	while (*s && isspace(*s))
747		s++;
748	if (*s == '-')
749		s++;	/* Skip cmdline '-', if any */
750	if (*s == '\0')
751		goto out;
752
753	if (*s == 'h' || *s == 'H' || *s == '?') {
754		logit("Commands:");
755		logit("      -Lport:host:hostport    Request local forward");
756		logit("      -Rport:host:hostport    Request remote forward");
757		logit("      -KRhostport             Cancel remote forward");
758		goto out;
759	}
760
761	if (*s == 'K') {
762		delete = 1;
763		s++;
764	}
765	if (*s != 'L' && *s != 'R') {
766		logit("Invalid command.");
767		goto out;
768	}
769	if (*s == 'L')
770		local = 1;
771	if (local && delete) {
772		logit("Not supported.");
773		goto out;
774	}
775	if ((!local || delete) && !compat20) {
776		logit("Not supported for SSH protocol version 1.");
777		goto out;
778	}
779
780	s++;
781	while (*s && isspace(*s))
782		s++;
783
784	if (delete) {
785		if (sscanf(s, "%5[0-9]", sfwd_host_port) != 1) {
786			logit("Bad forwarding specification.");
787			goto out;
788		}
789		if ((fwd_host_port = a2port(sfwd_host_port)) == 0) {
790			logit("Bad forwarding port(s).");
791			goto out;
792		}
793		channel_request_rforward_cancel(fwd_host_port);
794	} else {
795		if (sscanf(s, "%5[0-9]:%255[^:]:%5[0-9]",
796		    sfwd_port, buf, sfwd_host_port) != 3 &&
797		    sscanf(s, "%5[0-9]/%255[^/]/%5[0-9]",
798		    sfwd_port, buf, sfwd_host_port) != 3) {
799			logit("Bad forwarding specification.");
800			goto out;
801		}
802		if ((fwd_port = a2port(sfwd_port)) == 0 ||
803		    (fwd_host_port = a2port(sfwd_host_port)) == 0) {
804			logit("Bad forwarding port(s).");
805			goto out;
806		}
807		if (local) {
808			if (channel_setup_local_fwd_listener(fwd_port, buf,
809			    fwd_host_port, options.gateway_ports) < 0) {
810				logit("Port forwarding failed.");
811				goto out;
812			}
813		} else
814			channel_request_remote_forwarding(fwd_port, buf,
815			    fwd_host_port);
816		logit("Forwarding port.");
817	}
818
819out:
820	signal(SIGINT, handler);
821	enter_raw_mode();
822	if (cmd)
823		xfree(cmd);
824}
825
826/* process the characters one by one */
827static int
828process_escapes(Buffer *bin, Buffer *bout, Buffer *berr, char *buf, int len)
829{
830	char string[1024];
831	pid_t pid;
832	int bytes = 0;
833	u_int i;
834	u_char ch;
835	char *s;
836
837	for (i = 0; i < len; i++) {
838		/* Get one character at a time. */
839		ch = buf[i];
840
841		if (escape_pending) {
842			/* We have previously seen an escape character. */
843			/* Clear the flag now. */
844			escape_pending = 0;
845
846			/* Process the escaped character. */
847			switch (ch) {
848			case '.':
849				/* Terminate the connection. */
850				snprintf(string, sizeof string, "%c.\r\n", escape_char);
851				buffer_append(berr, string, strlen(string));
852
853				quit_pending = 1;
854				return -1;
855
856			case 'Z' - 64:
857				/* Suspend the program. */
858				/* Print a message to that effect to the user. */
859				snprintf(string, sizeof string, "%c^Z [suspend ssh]\r\n", escape_char);
860				buffer_append(berr, string, strlen(string));
861
862				/* Restore terminal modes and suspend. */
863				client_suspend_self(bin, bout, berr);
864
865				/* We have been continued. */
866				continue;
867
868			case 'B':
869				if (compat20) {
870					snprintf(string, sizeof string,
871					    "%cB\r\n", escape_char);
872					buffer_append(berr, string,
873					    strlen(string));
874					channel_request_start(session_ident,
875					    "break", 0);
876					packet_put_int(1000);
877					packet_send();
878				}
879				continue;
880
881			case 'R':
882				if (compat20) {
883					if (datafellows & SSH_BUG_NOREKEY)
884						logit("Server does not support re-keying");
885					else
886						need_rekeying = 1;
887				}
888				continue;
889
890			case '&':
891				/*
892				 * Detach the program (continue to serve connections,
893				 * but put in background and no more new connections).
894				 */
895				/* Restore tty modes. */
896				leave_raw_mode();
897
898				/* Stop listening for new connections. */
899				channel_stop_listening();
900
901				snprintf(string, sizeof string,
902				    "%c& [backgrounded]\n", escape_char);
903				buffer_append(berr, string, strlen(string));
904
905				/* Fork into background. */
906				pid = fork();
907				if (pid < 0) {
908					error("fork: %.100s", strerror(errno));
909					continue;
910				}
911				if (pid != 0) {	/* This is the parent. */
912					/* The parent just exits. */
913					exit(0);
914				}
915				/* The child continues serving connections. */
916				if (compat20) {
917					buffer_append(bin, "\004", 1);
918					/* fake EOF on stdin */
919					return -1;
920				} else if (!stdin_eof) {
921					/*
922					 * Sending SSH_CMSG_EOF alone does not always appear
923					 * to be enough.  So we try to send an EOF character
924					 * first.
925					 */
926					packet_start(SSH_CMSG_STDIN_DATA);
927					packet_put_string("\004", 1);
928					packet_send();
929					/* Close stdin. */
930					stdin_eof = 1;
931					if (buffer_len(bin) == 0) {
932						packet_start(SSH_CMSG_EOF);
933						packet_send();
934					}
935				}
936				continue;
937
938			case '?':
939				snprintf(string, sizeof string,
940"%c?\r\n\
941Supported escape sequences:\r\n\
942%c.  - terminate connection\r\n\
943%cB  - send a BREAK to the remote system\r\n\
944%cC  - open a command line\r\n\
945%cR  - Request rekey (SSH protocol 2 only)\r\n\
946%c^Z - suspend ssh\r\n\
947%c#  - list forwarded connections\r\n\
948%c&  - background ssh (when waiting for connections to terminate)\r\n\
949%c?  - this message\r\n\
950%c%c  - send the escape character by typing it twice\r\n\
951(Note that escapes are only recognized immediately after newline.)\r\n",
952				    escape_char, escape_char, escape_char, escape_char,
953				    escape_char, escape_char, escape_char, escape_char,
954				    escape_char, escape_char, escape_char);
955				buffer_append(berr, string, strlen(string));
956				continue;
957
958			case '#':
959				snprintf(string, sizeof string, "%c#\r\n", escape_char);
960				buffer_append(berr, string, strlen(string));
961				s = channel_open_message();
962				buffer_append(berr, s, strlen(s));
963				xfree(s);
964				continue;
965
966			case 'C':
967				process_cmdline();
968				continue;
969
970			default:
971				if (ch != escape_char) {
972					buffer_put_char(bin, escape_char);
973					bytes++;
974				}
975				/* Escaped characters fall through here */
976				break;
977			}
978		} else {
979			/*
980			 * The previous character was not an escape char. Check if this
981			 * is an escape.
982			 */
983			if (last_was_cr && ch == escape_char) {
984				/* It is. Set the flag and continue to next character. */
985				escape_pending = 1;
986				continue;
987			}
988		}
989
990		/*
991		 * Normal character.  Record whether it was a newline,
992		 * and append it to the buffer.
993		 */
994		last_was_cr = (ch == '\r' || ch == '\n');
995		buffer_put_char(bin, ch);
996		bytes++;
997	}
998	return bytes;
999}
1000
1001static void
1002client_process_input(fd_set * readset)
1003{
1004	int len;
1005	char buf[8192];
1006
1007	/* Read input from stdin. */
1008	if (FD_ISSET(fileno(stdin), readset)) {
1009		/* Read as much as possible. */
1010		len = read(fileno(stdin), buf, sizeof(buf));
1011		if (len < 0 && (errno == EAGAIN || errno == EINTR))
1012			return;		/* we'll try again later */
1013		if (len <= 0) {
1014			/*
1015			 * Received EOF or error.  They are treated
1016			 * similarly, except that an error message is printed
1017			 * if it was an error condition.
1018			 */
1019			if (len < 0) {
1020				snprintf(buf, sizeof buf, "read: %.100s\r\n", strerror(errno));
1021				buffer_append(&stderr_buffer, buf, strlen(buf));
1022			}
1023			/* Mark that we have seen EOF. */
1024			stdin_eof = 1;
1025			/*
1026			 * Send an EOF message to the server unless there is
1027			 * data in the buffer.  If there is data in the
1028			 * buffer, no message will be sent now.  Code
1029			 * elsewhere will send the EOF when the buffer
1030			 * becomes empty if stdin_eof is set.
1031			 */
1032			if (buffer_len(&stdin_buffer) == 0) {
1033				packet_start(SSH_CMSG_EOF);
1034				packet_send();
1035			}
1036		} else if (escape_char == SSH_ESCAPECHAR_NONE) {
1037			/*
1038			 * Normal successful read, and no escape character.
1039			 * Just append the data to buffer.
1040			 */
1041			buffer_append(&stdin_buffer, buf, len);
1042		} else {
1043			/*
1044			 * Normal, successful read.  But we have an escape character
1045			 * and have to process the characters one by one.
1046			 */
1047			if (process_escapes(&stdin_buffer, &stdout_buffer,
1048			    &stderr_buffer, buf, len) == -1)
1049				return;
1050		}
1051	}
1052}
1053
1054static void
1055client_process_output(fd_set * writeset)
1056{
1057	int len;
1058	char buf[100];
1059
1060	/* Write buffered output to stdout. */
1061	if (FD_ISSET(fileno(stdout), writeset)) {
1062		/* Write as much data as possible. */
1063		len = write(fileno(stdout), buffer_ptr(&stdout_buffer),
1064		    buffer_len(&stdout_buffer));
1065		if (len <= 0) {
1066			if (errno == EINTR || errno == EAGAIN)
1067				len = 0;
1068			else {
1069				/*
1070				 * An error or EOF was encountered.  Put an
1071				 * error message to stderr buffer.
1072				 */
1073				snprintf(buf, sizeof buf, "write stdout: %.50s\r\n", strerror(errno));
1074				buffer_append(&stderr_buffer, buf, strlen(buf));
1075				quit_pending = 1;
1076				return;
1077			}
1078		}
1079		/* Consume printed data from the buffer. */
1080		buffer_consume(&stdout_buffer, len);
1081		stdout_bytes += len;
1082	}
1083	/* Write buffered output to stderr. */
1084	if (FD_ISSET(fileno(stderr), writeset)) {
1085		/* Write as much data as possible. */
1086		len = write(fileno(stderr), buffer_ptr(&stderr_buffer),
1087		    buffer_len(&stderr_buffer));
1088		if (len <= 0) {
1089			if (errno == EINTR || errno == EAGAIN)
1090				len = 0;
1091			else {
1092				/* EOF or error, but can't even print error message. */
1093				quit_pending = 1;
1094				return;
1095			}
1096		}
1097		/* Consume printed characters from the buffer. */
1098		buffer_consume(&stderr_buffer, len);
1099		stderr_bytes += len;
1100	}
1101}
1102
1103/*
1104 * Get packets from the connection input buffer, and process them as long as
1105 * there are packets available.
1106 *
1107 * Any unknown packets received during the actual
1108 * session cause the session to terminate.  This is
1109 * intended to make debugging easier since no
1110 * confirmations are sent.  Any compatible protocol
1111 * extensions must be negotiated during the
1112 * preparatory phase.
1113 */
1114
1115static void
1116client_process_buffered_input_packets(void)
1117{
1118	dispatch_run(DISPATCH_NONBLOCK, &quit_pending, compat20 ? xxx_kex : NULL);
1119}
1120
1121/* scan buf[] for '~' before sending data to the peer */
1122
1123static int
1124simple_escape_filter(Channel *c, char *buf, int len)
1125{
1126	/* XXX we assume c->extended is writeable */
1127	return process_escapes(&c->input, &c->output, &c->extended, buf, len);
1128}
1129
1130static void
1131client_channel_closed(int id, void *arg)
1132{
1133	channel_cancel_cleanup(id);
1134	session_closed = 1;
1135	leave_raw_mode();
1136}
1137
1138/*
1139 * Implements the interactive session with the server.  This is called after
1140 * the user has been authenticated, and a command has been started on the
1141 * remote host.  If escape_char != SSH_ESCAPECHAR_NONE, it is the character
1142 * used as an escape character for terminating or suspending the session.
1143 */
1144
1145int
1146client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id)
1147{
1148	fd_set *readset = NULL, *writeset = NULL;
1149	double start_time, total_time;
1150	int max_fd = 0, max_fd2 = 0, len, rekeying = 0;
1151	u_int nalloc = 0;
1152	char buf[100];
1153
1154	debug("Entering interactive session.");
1155
1156	start_time = get_current_time();
1157
1158	/* Initialize variables. */
1159	escape_pending = 0;
1160	last_was_cr = 1;
1161	exit_status = -1;
1162	stdin_eof = 0;
1163	buffer_high = 64 * 1024;
1164	connection_in = packet_get_connection_in();
1165	connection_out = packet_get_connection_out();
1166	max_fd = MAX(connection_in, connection_out);
1167	if (control_fd != -1)
1168		max_fd = MAX(max_fd, control_fd);
1169
1170	if (!compat20) {
1171		/* enable nonblocking unless tty */
1172		if (!isatty(fileno(stdin)))
1173			set_nonblock(fileno(stdin));
1174		if (!isatty(fileno(stdout)))
1175			set_nonblock(fileno(stdout));
1176		if (!isatty(fileno(stderr)))
1177			set_nonblock(fileno(stderr));
1178		max_fd = MAX(max_fd, fileno(stdin));
1179		max_fd = MAX(max_fd, fileno(stdout));
1180		max_fd = MAX(max_fd, fileno(stderr));
1181	}
1182	stdin_bytes = 0;
1183	stdout_bytes = 0;
1184	stderr_bytes = 0;
1185	quit_pending = 0;
1186	escape_char = escape_char_arg;
1187
1188	/* Initialize buffers. */
1189	buffer_init(&stdin_buffer);
1190	buffer_init(&stdout_buffer);
1191	buffer_init(&stderr_buffer);
1192
1193	client_init_dispatch();
1194
1195	/*
1196	 * Set signal handlers, (e.g. to restore non-blocking mode)
1197	 * but don't overwrite SIG_IGN, matches behaviour from rsh(1)
1198	 */
1199	if (signal(SIGINT, SIG_IGN) != SIG_IGN)
1200		signal(SIGINT, signal_handler);
1201	if (signal(SIGQUIT, SIG_IGN) != SIG_IGN)
1202		signal(SIGQUIT, signal_handler);
1203	if (signal(SIGTERM, SIG_IGN) != SIG_IGN)
1204		signal(SIGTERM, signal_handler);
1205	if (have_pty)
1206		signal(SIGWINCH, window_change_handler);
1207
1208	if (have_pty)
1209		enter_raw_mode();
1210
1211	if (compat20) {
1212		session_ident = ssh2_chan_id;
1213		if (escape_char != SSH_ESCAPECHAR_NONE)
1214			channel_register_filter(session_ident,
1215			    simple_escape_filter);
1216		if (session_ident != -1)
1217			channel_register_cleanup(session_ident,
1218			    client_channel_closed);
1219	} else {
1220		/* Check if we should immediately send eof on stdin. */
1221		client_check_initial_eof_on_stdin();
1222	}
1223
1224	/* Main loop of the client for the interactive session mode. */
1225	while (!quit_pending) {
1226
1227		/* Process buffered packets sent by the server. */
1228		client_process_buffered_input_packets();
1229
1230		if (compat20 && session_closed && !channel_still_open())
1231			break;
1232
1233		rekeying = (xxx_kex != NULL && !xxx_kex->done);
1234
1235		if (rekeying) {
1236			debug("rekeying in progress");
1237		} else {
1238			/*
1239			 * Make packets of buffered stdin data, and buffer
1240			 * them for sending to the server.
1241			 */
1242			if (!compat20)
1243				client_make_packets_from_stdin_data();
1244
1245			/*
1246			 * Make packets from buffered channel data, and
1247			 * enqueue them for sending to the server.
1248			 */
1249			if (packet_not_very_much_data_to_write())
1250				channel_output_poll();
1251
1252			/*
1253			 * Check if the window size has changed, and buffer a
1254			 * message about it to the server if so.
1255			 */
1256			client_check_window_change();
1257
1258			if (quit_pending)
1259				break;
1260		}
1261		/*
1262		 * Wait until we have something to do (something becomes
1263		 * available on one of the descriptors).
1264		 */
1265		max_fd2 = max_fd;
1266		client_wait_until_can_do_something(&readset, &writeset,
1267		    &max_fd2, &nalloc, rekeying);
1268
1269		if (quit_pending)
1270			break;
1271
1272		/* Do channel operations unless rekeying in progress. */
1273		if (!rekeying) {
1274			channel_after_select(readset, writeset);
1275			if (need_rekeying || packet_need_rekeying()) {
1276				debug("need rekeying");
1277				xxx_kex->done = 0;
1278				kex_send_kexinit(xxx_kex);
1279				need_rekeying = 0;
1280			}
1281		}
1282
1283		/* Buffer input from the connection.  */
1284		client_process_net_input(readset);
1285
1286		/* Accept control connections.  */
1287		client_process_control(readset);
1288
1289		if (quit_pending)
1290			break;
1291
1292		if (!compat20) {
1293			/* Buffer data from stdin */
1294			client_process_input(readset);
1295			/*
1296			 * Process output to stdout and stderr.  Output to
1297			 * the connection is processed elsewhere (above).
1298			 */
1299			client_process_output(writeset);
1300		}
1301
1302		/* Send as much buffered packet data as possible to the sender. */
1303		if (FD_ISSET(connection_out, writeset))
1304			packet_write_poll();
1305	}
1306	if (readset)
1307		xfree(readset);
1308	if (writeset)
1309		xfree(writeset);
1310
1311	/* Terminate the session. */
1312
1313	/* Stop watching for window change. */
1314	if (have_pty)
1315		signal(SIGWINCH, SIG_DFL);
1316
1317	channel_free_all();
1318
1319	if (have_pty)
1320		leave_raw_mode();
1321
1322	/* restore blocking io */
1323	if (!isatty(fileno(stdin)))
1324		unset_nonblock(fileno(stdin));
1325	if (!isatty(fileno(stdout)))
1326		unset_nonblock(fileno(stdout));
1327	if (!isatty(fileno(stderr)))
1328		unset_nonblock(fileno(stderr));
1329
1330	/*
1331	 * If there was no shell or command requested, there will be no remote
1332	 * exit status to be returned.  In that case, clear error code if the
1333	 * connection was deliberately terminated at this end.
1334	 */
1335	if (no_shell_flag && received_signal == SIGTERM) {
1336		received_signal = 0;
1337		exit_status = 0;
1338	}
1339
1340	if (received_signal)
1341		fatal("Killed by signal %d.", (int) received_signal);
1342
1343	/*
1344	 * In interactive mode (with pseudo tty) display a message indicating
1345	 * that the connection has been closed.
1346	 */
1347	if (have_pty && options.log_level != SYSLOG_LEVEL_QUIET) {
1348		snprintf(buf, sizeof buf, "Connection to %.64s closed.\r\n", host);
1349		buffer_append(&stderr_buffer, buf, strlen(buf));
1350	}
1351
1352	/* Output any buffered data for stdout. */
1353	while (buffer_len(&stdout_buffer) > 0) {
1354		len = write(fileno(stdout), buffer_ptr(&stdout_buffer),
1355		    buffer_len(&stdout_buffer));
1356		if (len <= 0) {
1357			error("Write failed flushing stdout buffer.");
1358			break;
1359		}
1360		buffer_consume(&stdout_buffer, len);
1361		stdout_bytes += len;
1362	}
1363
1364	/* Output any buffered data for stderr. */
1365	while (buffer_len(&stderr_buffer) > 0) {
1366		len = write(fileno(stderr), buffer_ptr(&stderr_buffer),
1367		    buffer_len(&stderr_buffer));
1368		if (len <= 0) {
1369			error("Write failed flushing stderr buffer.");
1370			break;
1371		}
1372		buffer_consume(&stderr_buffer, len);
1373		stderr_bytes += len;
1374	}
1375
1376	/* Clear and free any buffers. */
1377	memset(buf, 0, sizeof(buf));
1378	buffer_free(&stdin_buffer);
1379	buffer_free(&stdout_buffer);
1380	buffer_free(&stderr_buffer);
1381
1382	/* Report bytes transferred, and transfer rates. */
1383	total_time = get_current_time() - start_time;
1384	debug("Transferred: stdin %lu, stdout %lu, stderr %lu bytes in %.1f seconds",
1385	    stdin_bytes, stdout_bytes, stderr_bytes, total_time);
1386	if (total_time > 0)
1387		debug("Bytes per second: stdin %.1f, stdout %.1f, stderr %.1f",
1388		    stdin_bytes / total_time, stdout_bytes / total_time,
1389		    stderr_bytes / total_time);
1390
1391	/* Return the exit status of the program. */
1392	debug("Exit status %d", exit_status);
1393	return exit_status;
1394}
1395
1396/*********/
1397
1398static void
1399client_input_stdout_data(int type, u_int32_t seq, void *ctxt)
1400{
1401	u_int data_len;
1402	char *data = packet_get_string(&data_len);
1403	packet_check_eom();
1404	buffer_append(&stdout_buffer, data, data_len);
1405	memset(data, 0, data_len);
1406	xfree(data);
1407}
1408static void
1409client_input_stderr_data(int type, u_int32_t seq, void *ctxt)
1410{
1411	u_int data_len;
1412	char *data = packet_get_string(&data_len);
1413	packet_check_eom();
1414	buffer_append(&stderr_buffer, data, data_len);
1415	memset(data, 0, data_len);
1416	xfree(data);
1417}
1418static void
1419client_input_exit_status(int type, u_int32_t seq, void *ctxt)
1420{
1421	exit_status = packet_get_int();
1422	packet_check_eom();
1423	/* Acknowledge the exit. */
1424	packet_start(SSH_CMSG_EXIT_CONFIRMATION);
1425	packet_send();
1426	/*
1427	 * Must wait for packet to be sent since we are
1428	 * exiting the loop.
1429	 */
1430	packet_write_wait();
1431	/* Flag that we want to exit. */
1432	quit_pending = 1;
1433}
1434static void
1435client_input_agent_open(int type, u_int32_t seq, void *ctxt)
1436{
1437	Channel *c = NULL;
1438	int remote_id, sock;
1439
1440	/* Read the remote channel number from the message. */
1441	remote_id = packet_get_int();
1442	packet_check_eom();
1443
1444	/*
1445	 * Get a connection to the local authentication agent (this may again
1446	 * get forwarded).
1447	 */
1448	sock = ssh_get_authentication_socket();
1449
1450	/*
1451	 * If we could not connect the agent, send an error message back to
1452	 * the server. This should never happen unless the agent dies,
1453	 * because authentication forwarding is only enabled if we have an
1454	 * agent.
1455	 */
1456	if (sock >= 0) {
1457		c = channel_new("", SSH_CHANNEL_OPEN, sock, sock,
1458		    -1, 0, 0, 0, "authentication agent connection", 1);
1459		c->remote_id = remote_id;
1460		c->force_drain = 1;
1461	}
1462	if (c == NULL) {
1463		packet_start(SSH_MSG_CHANNEL_OPEN_FAILURE);
1464		packet_put_int(remote_id);
1465	} else {
1466		/* Send a confirmation to the remote host. */
1467		debug("Forwarding authentication connection.");
1468		packet_start(SSH_MSG_CHANNEL_OPEN_CONFIRMATION);
1469		packet_put_int(remote_id);
1470		packet_put_int(c->self);
1471	}
1472	packet_send();
1473}
1474
1475static Channel *
1476client_request_forwarded_tcpip(const char *request_type, int rchan)
1477{
1478	Channel *c = NULL;
1479	char *listen_address, *originator_address;
1480	int listen_port, originator_port;
1481	int sock;
1482
1483	/* Get rest of the packet */
1484	listen_address = packet_get_string(NULL);
1485	listen_port = packet_get_int();
1486	originator_address = packet_get_string(NULL);
1487	originator_port = packet_get_int();
1488	packet_check_eom();
1489
1490	debug("client_request_forwarded_tcpip: listen %s port %d, originator %s port %d",
1491	    listen_address, listen_port, originator_address, originator_port);
1492
1493	sock = channel_connect_by_listen_address(listen_port);
1494	if (sock < 0) {
1495		xfree(originator_address);
1496		xfree(listen_address);
1497		return NULL;
1498	}
1499	c = channel_new("forwarded-tcpip",
1500	    SSH_CHANNEL_CONNECTING, sock, sock, -1,
1501	    CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_WINDOW_DEFAULT, 0,
1502	    originator_address, 1);
1503	xfree(originator_address);
1504	xfree(listen_address);
1505	return c;
1506}
1507
1508static Channel *
1509client_request_x11(const char *request_type, int rchan)
1510{
1511	Channel *c = NULL;
1512	char *originator;
1513	int originator_port;
1514	int sock;
1515
1516	if (!options.forward_x11) {
1517		error("Warning: ssh server tried X11 forwarding.");
1518		error("Warning: this is probably a break in attempt by a malicious server.");
1519		return NULL;
1520	}
1521	originator = packet_get_string(NULL);
1522	if (datafellows & SSH_BUG_X11FWD) {
1523		debug2("buggy server: x11 request w/o originator_port");
1524		originator_port = 0;
1525	} else {
1526		originator_port = packet_get_int();
1527	}
1528	packet_check_eom();
1529	/* XXX check permission */
1530	debug("client_request_x11: request from %s %d", originator,
1531	    originator_port);
1532	xfree(originator);
1533	sock = x11_connect_display();
1534	if (sock < 0)
1535		return NULL;
1536	c = channel_new("x11",
1537	    SSH_CHANNEL_X11_OPEN, sock, sock, -1,
1538	    CHAN_TCP_WINDOW_DEFAULT, CHAN_X11_PACKET_DEFAULT, 0, "x11", 1);
1539	c->force_drain = 1;
1540	return c;
1541}
1542
1543static Channel *
1544client_request_agent(const char *request_type, int rchan)
1545{
1546	Channel *c = NULL;
1547	int sock;
1548
1549	if (!options.forward_agent) {
1550		error("Warning: ssh server tried agent forwarding.");
1551		error("Warning: this is probably a break in attempt by a malicious server.");
1552		return NULL;
1553	}
1554	sock =  ssh_get_authentication_socket();
1555	if (sock < 0)
1556		return NULL;
1557	c = channel_new("authentication agent connection",
1558	    SSH_CHANNEL_OPEN, sock, sock, -1,
1559	    CHAN_X11_WINDOW_DEFAULT, CHAN_TCP_WINDOW_DEFAULT, 0,
1560	    "authentication agent connection", 1);
1561	c->force_drain = 1;
1562	return c;
1563}
1564
1565/* XXXX move to generic input handler */
1566static void
1567client_input_channel_open(int type, u_int32_t seq, void *ctxt)
1568{
1569	Channel *c = NULL;
1570	char *ctype;
1571	int rchan;
1572	u_int rmaxpack, rwindow, len;
1573
1574	ctype = packet_get_string(&len);
1575	rchan = packet_get_int();
1576	rwindow = packet_get_int();
1577	rmaxpack = packet_get_int();
1578
1579	debug("client_input_channel_open: ctype %s rchan %d win %d max %d",
1580	    ctype, rchan, rwindow, rmaxpack);
1581
1582	if (strcmp(ctype, "forwarded-tcpip") == 0) {
1583		c = client_request_forwarded_tcpip(ctype, rchan);
1584	} else if (strcmp(ctype, "x11") == 0) {
1585		c = client_request_x11(ctype, rchan);
1586	} else if (strcmp(ctype, "auth-agent@openssh.com") == 0) {
1587		c = client_request_agent(ctype, rchan);
1588	}
1589/* XXX duplicate : */
1590	if (c != NULL) {
1591		debug("confirm %s", ctype);
1592		c->remote_id = rchan;
1593		c->remote_window = rwindow;
1594		c->remote_maxpacket = rmaxpack;
1595		if (c->type != SSH_CHANNEL_CONNECTING) {
1596			packet_start(SSH2_MSG_CHANNEL_OPEN_CONFIRMATION);
1597			packet_put_int(c->remote_id);
1598			packet_put_int(c->self);
1599			packet_put_int(c->local_window);
1600			packet_put_int(c->local_maxpacket);
1601			packet_send();
1602		}
1603	} else {
1604		debug("failure %s", ctype);
1605		packet_start(SSH2_MSG_CHANNEL_OPEN_FAILURE);
1606		packet_put_int(rchan);
1607		packet_put_int(SSH2_OPEN_ADMINISTRATIVELY_PROHIBITED);
1608		if (!(datafellows & SSH_BUG_OPENFAILURE)) {
1609			packet_put_cstring("open failed");
1610			packet_put_cstring("");
1611		}
1612		packet_send();
1613	}
1614	xfree(ctype);
1615}
1616static void
1617client_input_channel_req(int type, u_int32_t seq, void *ctxt)
1618{
1619	Channel *c = NULL;
1620	int exitval, id, reply, success = 0;
1621	char *rtype;
1622
1623	id = packet_get_int();
1624	rtype = packet_get_string(NULL);
1625	reply = packet_get_char();
1626
1627	debug("client_input_channel_req: channel %d rtype %s reply %d",
1628	    id, rtype, reply);
1629
1630	if (id == -1) {
1631		error("client_input_channel_req: request for channel -1");
1632	} else if ((c = channel_lookup(id)) == NULL) {
1633		error("client_input_channel_req: channel %d: unknown channel", id);
1634	} else if (strcmp(rtype, "exit-status") == 0) {
1635		exitval = packet_get_int();
1636		if (id == session_ident) {
1637			success = 1;
1638			exit_status = exitval;
1639		} else if (c->ctl_fd == -1) {
1640			error("client_input_channel_req: unexpected channel %d",
1641			    session_ident);
1642		} else {
1643			atomicio(vwrite, c->ctl_fd, &exitval, sizeof(exitval));
1644			success = 1;
1645		}
1646		packet_check_eom();
1647	}
1648	if (reply) {
1649		packet_start(success ?
1650		    SSH2_MSG_CHANNEL_SUCCESS : SSH2_MSG_CHANNEL_FAILURE);
1651		packet_put_int(id);
1652		packet_send();
1653	}
1654	xfree(rtype);
1655}
1656static void
1657client_input_global_request(int type, u_int32_t seq, void *ctxt)
1658{
1659	char *rtype;
1660	int want_reply;
1661	int success = 0;
1662
1663	rtype = packet_get_string(NULL);
1664	want_reply = packet_get_char();
1665	debug("client_input_global_request: rtype %s want_reply %d",
1666	    rtype, want_reply);
1667	if (want_reply) {
1668		packet_start(success ?
1669		    SSH2_MSG_REQUEST_SUCCESS : SSH2_MSG_REQUEST_FAILURE);
1670		packet_send();
1671		packet_write_wait();
1672	}
1673	xfree(rtype);
1674}
1675
1676void
1677client_session2_setup(int id, int want_tty, int want_subsystem,
1678    const char *term, struct termios *tiop, int in_fd, Buffer *cmd, char **env,
1679    dispatch_fn *subsys_repl)
1680{
1681	int len;
1682
1683	debug2("%s: id %d", __func__, id);
1684
1685	if (want_tty) {
1686		struct winsize ws;
1687		struct termios tio;
1688
1689		/* Store window size in the packet. */
1690		if (ioctl(in_fd, TIOCGWINSZ, &ws) < 0)
1691			memset(&ws, 0, sizeof(ws));
1692
1693		channel_request_start(id, "pty-req", 0);
1694		packet_put_cstring(term != NULL ? term : "");
1695		packet_put_int(ws.ws_col);
1696		packet_put_int(ws.ws_row);
1697		packet_put_int(ws.ws_xpixel);
1698		packet_put_int(ws.ws_ypixel);
1699		tio = get_saved_tio();
1700		tty_make_modes(-1, tiop != NULL ? tiop : &tio);
1701		packet_send();
1702		/* XXX wait for reply */
1703	}
1704
1705	/* Transfer any environment variables from client to server */
1706	if (options.num_send_env != 0 && env != NULL) {
1707		int i, j, matched;
1708		char *name, *val;
1709
1710		debug("Sending environment.");
1711		for (i = 0; env[i] != NULL; i++) {
1712			/* Split */
1713			name = xstrdup(env[i]);
1714			if ((val = strchr(name, '=')) == NULL) {
1715				free(name);
1716				continue;
1717			}
1718			*val++ = '\0';
1719
1720			matched = 0;
1721			for (j = 0; j < options.num_send_env; j++) {
1722				if (match_pattern(name, options.send_env[j])) {
1723					matched = 1;
1724					break;
1725				}
1726			}
1727			if (!matched) {
1728				debug3("Ignored env %s", name);
1729				free(name);
1730				continue;
1731			}
1732
1733			debug("Sending env %s = %s", name, val);
1734			channel_request_start(id, "env", 0);
1735			packet_put_cstring(name);
1736			packet_put_cstring(val);
1737			packet_send();
1738			free(name);
1739		}
1740	}
1741
1742	len = buffer_len(cmd);
1743	if (len > 0) {
1744		if (len > 900)
1745			len = 900;
1746		if (want_subsystem) {
1747			debug("Sending subsystem: %.*s", len, (u_char*)buffer_ptr(cmd));
1748			channel_request_start(id, "subsystem", subsys_repl != NULL);
1749			if (subsys_repl != NULL) {
1750				/* register callback for reply */
1751				/* XXX we assume that client_loop has already been called */
1752				dispatch_set(SSH2_MSG_CHANNEL_FAILURE, subsys_repl);
1753				dispatch_set(SSH2_MSG_CHANNEL_SUCCESS, subsys_repl);
1754			}
1755		} else {
1756			debug("Sending command: %.*s", len, (u_char*)buffer_ptr(cmd));
1757			channel_request_start(id, "exec", 0);
1758		}
1759		packet_put_string(buffer_ptr(cmd), buffer_len(cmd));
1760		packet_send();
1761	} else {
1762		channel_request_start(id, "shell", 0);
1763		packet_send();
1764	}
1765}
1766
1767static void
1768client_init_dispatch_20(void)
1769{
1770	dispatch_init(&dispatch_protocol_error);
1771
1772	dispatch_set(SSH2_MSG_CHANNEL_CLOSE, &channel_input_oclose);
1773	dispatch_set(SSH2_MSG_CHANNEL_DATA, &channel_input_data);
1774	dispatch_set(SSH2_MSG_CHANNEL_EOF, &channel_input_ieof);
1775	dispatch_set(SSH2_MSG_CHANNEL_EXTENDED_DATA, &channel_input_extended_data);
1776	dispatch_set(SSH2_MSG_CHANNEL_OPEN, &client_input_channel_open);
1777	dispatch_set(SSH2_MSG_CHANNEL_OPEN_CONFIRMATION, &channel_input_open_confirmation);
1778	dispatch_set(SSH2_MSG_CHANNEL_OPEN_FAILURE, &channel_input_open_failure);
1779	dispatch_set(SSH2_MSG_CHANNEL_REQUEST, &client_input_channel_req);
1780	dispatch_set(SSH2_MSG_CHANNEL_WINDOW_ADJUST, &channel_input_window_adjust);
1781	dispatch_set(SSH2_MSG_GLOBAL_REQUEST, &client_input_global_request);
1782
1783	/* rekeying */
1784	dispatch_set(SSH2_MSG_KEXINIT, &kex_input_kexinit);
1785
1786	/* global request reply messages */
1787	dispatch_set(SSH2_MSG_REQUEST_FAILURE, &client_global_request_reply);
1788	dispatch_set(SSH2_MSG_REQUEST_SUCCESS, &client_global_request_reply);
1789}
1790static void
1791client_init_dispatch_13(void)
1792{
1793	dispatch_init(NULL);
1794	dispatch_set(SSH_MSG_CHANNEL_CLOSE, &channel_input_close);
1795	dispatch_set(SSH_MSG_CHANNEL_CLOSE_CONFIRMATION, &channel_input_close_confirmation);
1796	dispatch_set(SSH_MSG_CHANNEL_DATA, &channel_input_data);
1797	dispatch_set(SSH_MSG_CHANNEL_OPEN_CONFIRMATION, &channel_input_open_confirmation);
1798	dispatch_set(SSH_MSG_CHANNEL_OPEN_FAILURE, &channel_input_open_failure);
1799	dispatch_set(SSH_MSG_PORT_OPEN, &channel_input_port_open);
1800	dispatch_set(SSH_SMSG_EXITSTATUS, &client_input_exit_status);
1801	dispatch_set(SSH_SMSG_STDERR_DATA, &client_input_stderr_data);
1802	dispatch_set(SSH_SMSG_STDOUT_DATA, &client_input_stdout_data);
1803
1804	dispatch_set(SSH_SMSG_AGENT_OPEN, options.forward_agent ?
1805	    &client_input_agent_open : &deny_input_open);
1806	dispatch_set(SSH_SMSG_X11_OPEN, options.forward_x11 ?
1807	    &x11_input_open : &deny_input_open);
1808}
1809static void
1810client_init_dispatch_15(void)
1811{
1812	client_init_dispatch_13();
1813	dispatch_set(SSH_MSG_CHANNEL_CLOSE, &channel_input_ieof);
1814	dispatch_set(SSH_MSG_CHANNEL_CLOSE_CONFIRMATION, & channel_input_oclose);
1815}
1816static void
1817client_init_dispatch(void)
1818{
1819	if (compat20)
1820		client_init_dispatch_20();
1821	else if (compat13)
1822		client_init_dispatch_13();
1823	else
1824		client_init_dispatch_15();
1825}
1826
1827/* client specific fatal cleanup */
1828void
1829cleanup_exit(int i)
1830{
1831	leave_raw_mode();
1832	leave_non_blocking();
1833	if (options.control_path != NULL && control_fd != -1)
1834		unlink(options.control_path);
1835	_exit(i);
1836}
1837