Deleted Added
full compact
clientloop.c (124208) clientloop.c (126274)
1/*
2 * Author: Tatu Ylonen <ylo@cs.hut.fi>
3 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
4 * All rights reserved
5 * The main loop for the interactive session (client side).
6 *
7 * As far as I am concerned, the code I have written for this software
8 * can be used freely for any purpose. Any derived versions of this

--- 45 unchanged lines hidden (view full) ---

54 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
55 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
56 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
57 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
58 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
59 */
60
61#include "includes.h"
1/*
2 * Author: Tatu Ylonen <ylo@cs.hut.fi>
3 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
4 * All rights reserved
5 * The main loop for the interactive session (client side).
6 *
7 * As far as I am concerned, the code I have written for this software
8 * can be used freely for any purpose. Any derived versions of this

--- 45 unchanged lines hidden (view full) ---

54 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
55 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
56 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
57 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
58 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
59 */
60
61#include "includes.h"
62RCSID("$OpenBSD: clientloop.c,v 1.112 2003/06/28 16:23:06 deraadt Exp $");
62RCSID("$OpenBSD: clientloop.c,v 1.117 2003/12/16 15:49:51 markus Exp $");
63
64#include "ssh.h"
65#include "ssh1.h"
66#include "ssh2.h"
67#include "xmalloc.h"
68#include "packet.h"
69#include "buffer.h"
70#include "compat.h"

--- 13 unchanged lines hidden (view full) ---

84#include "readpass.h"
85
86/* import options */
87extern Options options;
88
89/* Flag indicating that stdin should be redirected from /dev/null. */
90extern int stdin_null_flag;
91
63
64#include "ssh.h"
65#include "ssh1.h"
66#include "ssh2.h"
67#include "xmalloc.h"
68#include "packet.h"
69#include "buffer.h"
70#include "compat.h"

--- 13 unchanged lines hidden (view full) ---

84#include "readpass.h"
85
86/* import options */
87extern Options options;
88
89/* Flag indicating that stdin should be redirected from /dev/null. */
90extern int stdin_null_flag;
91
92/* Flag indicating that no shell has been requested */
93extern int no_shell_flag;
94
92/*
93 * Name of the host we are connecting to. This is the name given on the
94 * command line, or the HostName specified for the user-supplied name in a
95 * configuration file.
96 */
97extern char *host;
98
99/*

--- 19 unchanged lines hidden (view full) ---

119static Buffer stdout_buffer; /* Buffer for stdout data. */
120static Buffer stderr_buffer; /* Buffer for stderr data. */
121static u_long stdin_bytes, stdout_bytes, stderr_bytes;
122static u_int buffer_high;/* Soft max buffer size. */
123static int connection_in; /* Connection to server (input). */
124static int connection_out; /* Connection to server (output). */
125static int need_rekeying; /* Set to non-zero if rekeying is requested. */
126static int session_closed = 0; /* In SSH2: login session closed. */
95/*
96 * Name of the host we are connecting to. This is the name given on the
97 * command line, or the HostName specified for the user-supplied name in a
98 * configuration file.
99 */
100extern char *host;
101
102/*

--- 19 unchanged lines hidden (view full) ---

122static Buffer stdout_buffer; /* Buffer for stdout data. */
123static Buffer stderr_buffer; /* Buffer for stderr data. */
124static u_long stdin_bytes, stdout_bytes, stderr_bytes;
125static u_int buffer_high;/* Soft max buffer size. */
126static int connection_in; /* Connection to server (input). */
127static int connection_out; /* Connection to server (output). */
128static int need_rekeying; /* Set to non-zero if rekeying is requested. */
129static int session_closed = 0; /* In SSH2: login session closed. */
130static int server_alive_timeouts = 0;
127
128static void client_init_dispatch(void);
129int session_ident = -1;
130
131/*XXX*/
132extern Kex *xxx_kex;
133
134/* Restores stdin to blocking mode. */
135
136static void
137leave_non_blocking(void)
138{
139 if (in_non_blocking_mode) {
140 (void) fcntl(fileno(stdin), F_SETFL, 0);
141 in_non_blocking_mode = 0;
131
132static void client_init_dispatch(void);
133int session_ident = -1;
134
135/*XXX*/
136extern Kex *xxx_kex;
137
138/* Restores stdin to blocking mode. */
139
140static void
141leave_non_blocking(void)
142{
143 if (in_non_blocking_mode) {
144 (void) fcntl(fileno(stdin), F_SETFL, 0);
145 in_non_blocking_mode = 0;
142 fatal_remove_cleanup((void (*) (void *)) leave_non_blocking, NULL);
143 }
144}
145
146/* Puts stdin terminal in non-blocking mode. */
147
148static void
149enter_non_blocking(void)
150{
151 in_non_blocking_mode = 1;
152 (void) fcntl(fileno(stdin), F_SETFL, O_NONBLOCK);
146 }
147}
148
149/* Puts stdin terminal in non-blocking mode. */
150
151static void
152enter_non_blocking(void)
153{
154 in_non_blocking_mode = 1;
155 (void) fcntl(fileno(stdin), F_SETFL, O_NONBLOCK);
153 fatal_add_cleanup((void (*) (void *)) leave_non_blocking, NULL);
154}
155
156/*
157 * Signal handler for the window change signal (SIGWINCH). This just sets a
158 * flag indicating that the window has changed.
159 */
160
161static void

--- 145 unchanged lines hidden (view full) ---

307 packet_put_int(ws.ws_row);
308 packet_put_int(ws.ws_col);
309 packet_put_int(ws.ws_xpixel);
310 packet_put_int(ws.ws_ypixel);
311 packet_send();
312 }
313}
314
156}
157
158/*
159 * Signal handler for the window change signal (SIGWINCH). This just sets a
160 * flag indicating that the window has changed.
161 */
162
163static void

--- 145 unchanged lines hidden (view full) ---

309 packet_put_int(ws.ws_row);
310 packet_put_int(ws.ws_col);
311 packet_put_int(ws.ws_xpixel);
312 packet_put_int(ws.ws_ypixel);
313 packet_send();
314 }
315}
316
317static void
318client_global_request_reply(int type, u_int32_t seq, void *ctxt)
319{
320 server_alive_timeouts = 0;
321 client_global_request_reply_fwd(type, seq, ctxt);
322}
323
324static void
325server_alive_check(void)
326{
327 if (++server_alive_timeouts > options.server_alive_count_max)
328 packet_disconnect("Timeout, server not responding.");
329 packet_start(SSH2_MSG_GLOBAL_REQUEST);
330 packet_put_cstring("keepalive@openssh.com");
331 packet_put_char(1); /* boolean: want reply */
332 packet_send();
333}
334
315/*
316 * Waits until the client can do something (some data becomes available on
317 * one of the file descriptors).
318 */
319
320static void
321client_wait_until_can_do_something(fd_set **readsetp, fd_set **writesetp,
322 int *maxfdp, int *nallocp, int rekeying)
323{
335/*
336 * Waits until the client can do something (some data becomes available on
337 * one of the file descriptors).
338 */
339
340static void
341client_wait_until_can_do_something(fd_set **readsetp, fd_set **writesetp,
342 int *maxfdp, int *nallocp, int rekeying)
343{
344 struct timeval tv, *tvp;
345 int ret;
346
324 /* Add any selections by the channel mechanism. */
325 channel_prepare_select(readsetp, writesetp, maxfdp, nallocp, rekeying);
326
327 if (!compat20) {
328 /* Read from the connection, unless our buffers are full. */
329 if (buffer_len(&stdout_buffer) < buffer_high &&
330 buffer_len(&stderr_buffer) < buffer_high &&
331 channel_not_very_much_buffered_data())

--- 25 unchanged lines hidden (view full) ---

357
358 /* Select server connection if have data to write to the server. */
359 if (packet_have_data_to_write())
360 FD_SET(connection_out, *writesetp);
361
362 /*
363 * Wait for something to happen. This will suspend the process until
364 * some selected descriptor can be read, written, or has some other
347 /* Add any selections by the channel mechanism. */
348 channel_prepare_select(readsetp, writesetp, maxfdp, nallocp, rekeying);
349
350 if (!compat20) {
351 /* Read from the connection, unless our buffers are full. */
352 if (buffer_len(&stdout_buffer) < buffer_high &&
353 buffer_len(&stderr_buffer) < buffer_high &&
354 channel_not_very_much_buffered_data())

--- 25 unchanged lines hidden (view full) ---

380
381 /* Select server connection if have data to write to the server. */
382 if (packet_have_data_to_write())
383 FD_SET(connection_out, *writesetp);
384
385 /*
386 * Wait for something to happen. This will suspend the process until
387 * some selected descriptor can be read, written, or has some other
365 * event pending. Note: if you want to implement SSH_MSG_IGNORE
366 * messages to fool traffic analysis, this might be the place to do
367 * it: just have a random timeout for the select, and send a random
368 * SSH_MSG_IGNORE packet when the timeout expires.
388 * event pending.
369 */
370
389 */
390
371 if (select((*maxfdp)+1, *readsetp, *writesetp, NULL, NULL) < 0) {
391 if (options.server_alive_interval == 0 || !compat20)
392 tvp = NULL;
393 else {
394 tv.tv_sec = options.server_alive_interval;
395 tv.tv_usec = 0;
396 tvp = &tv;
397 }
398 ret = select((*maxfdp)+1, *readsetp, *writesetp, NULL, tvp);
399 if (ret < 0) {
372 char buf[100];
373
374 /*
375 * We have to clear the select masks, because we return.
376 * We have to return, because the mainloop checks for the flags
377 * set by the signal handlers.
378 */
379 memset(*readsetp, 0, *nallocp);
380 memset(*writesetp, 0, *nallocp);
381
382 if (errno == EINTR)
383 return;
384 /* Note: we might still have data in the buffers. */
385 snprintf(buf, sizeof buf, "select: %s\r\n", strerror(errno));
386 buffer_append(&stderr_buffer, buf, strlen(buf));
387 quit_pending = 1;
400 char buf[100];
401
402 /*
403 * We have to clear the select masks, because we return.
404 * We have to return, because the mainloop checks for the flags
405 * set by the signal handlers.
406 */
407 memset(*readsetp, 0, *nallocp);
408 memset(*writesetp, 0, *nallocp);
409
410 if (errno == EINTR)
411 return;
412 /* Note: we might still have data in the buffers. */
413 snprintf(buf, sizeof buf, "select: %s\r\n", strerror(errno));
414 buffer_append(&stderr_buffer, buf, strlen(buf));
415 quit_pending = 1;
388 }
416 } else if (ret == 0)
417 server_alive_check();
389}
390
391static void
392client_suspend_self(Buffer *bin, Buffer *bout, Buffer *berr)
393{
394 struct winsize oldws, newws;
395
396 /* Flush stdout and stderr buffers. */

--- 442 unchanged lines hidden (view full) ---

839static void
840client_channel_closed(int id, void *arg)
841{
842 if (id != session_ident)
843 error("client_channel_closed: id %d != session_ident %d",
844 id, session_ident);
845 channel_cancel_cleanup(id);
846 session_closed = 1;
418}
419
420static void
421client_suspend_self(Buffer *bin, Buffer *bout, Buffer *berr)
422{
423 struct winsize oldws, newws;
424
425 /* Flush stdout and stderr buffers. */

--- 442 unchanged lines hidden (view full) ---

868static void
869client_channel_closed(int id, void *arg)
870{
871 if (id != session_ident)
872 error("client_channel_closed: id %d != session_ident %d",
873 id, session_ident);
874 channel_cancel_cleanup(id);
875 session_closed = 1;
847 if (in_raw_mode())
848 leave_raw_mode();
876 leave_raw_mode();
849}
850
851/*
852 * Implements the interactive session with the server. This is called after
853 * the user has been authenticated, and a command has been started on the
854 * remote host. If escape_char != SSH_ESCAPECHAR_NONE, it is the character
855 * used as an escape character for terminating or suspending the session.
856 */

--- 172 unchanged lines hidden (view full) ---

1029 /* restore blocking io */
1030 if (!isatty(fileno(stdin)))
1031 unset_nonblock(fileno(stdin));
1032 if (!isatty(fileno(stdout)))
1033 unset_nonblock(fileno(stdout));
1034 if (!isatty(fileno(stderr)))
1035 unset_nonblock(fileno(stderr));
1036
877}
878
879/*
880 * Implements the interactive session with the server. This is called after
881 * the user has been authenticated, and a command has been started on the
882 * remote host. If escape_char != SSH_ESCAPECHAR_NONE, it is the character
883 * used as an escape character for terminating or suspending the session.
884 */

--- 172 unchanged lines hidden (view full) ---

1057 /* restore blocking io */
1058 if (!isatty(fileno(stdin)))
1059 unset_nonblock(fileno(stdin));
1060 if (!isatty(fileno(stdout)))
1061 unset_nonblock(fileno(stdout));
1062 if (!isatty(fileno(stderr)))
1063 unset_nonblock(fileno(stderr));
1064
1037 if (received_signal) {
1038 if (in_non_blocking_mode) /* XXX */
1039 leave_non_blocking();
1040 fatal("Killed by signal %d.", (int) received_signal);
1065 /*
1066 * If there was no shell or command requested, there will be no remote
1067 * exit status to be returned. In that case, clear error code if the
1068 * connection was deliberately terminated at this end.
1069 */
1070 if (no_shell_flag && received_signal == SIGTERM) {
1071 received_signal = 0;
1072 exit_status = 0;
1041 }
1042
1073 }
1074
1075 if (received_signal)
1076 fatal("Killed by signal %d.", (int) received_signal);
1077
1043 /*
1044 * In interactive mode (with pseudo tty) display a message indicating
1045 * that the connection has been closed.
1046 */
1047 if (have_pty && options.log_level != SYSLOG_LEVEL_QUIET) {
1048 snprintf(buf, sizeof buf, "Connection to %.64s closed.\r\n", host);
1049 buffer_append(&stderr_buffer, buf, strlen(buf));
1050 }

--- 75 unchanged lines hidden (view full) ---

1126 /*
1127 * Must wait for packet to be sent since we are
1128 * exiting the loop.
1129 */
1130 packet_write_wait();
1131 /* Flag that we want to exit. */
1132 quit_pending = 1;
1133}
1078 /*
1079 * In interactive mode (with pseudo tty) display a message indicating
1080 * that the connection has been closed.
1081 */
1082 if (have_pty && options.log_level != SYSLOG_LEVEL_QUIET) {
1083 snprintf(buf, sizeof buf, "Connection to %.64s closed.\r\n", host);
1084 buffer_append(&stderr_buffer, buf, strlen(buf));
1085 }

--- 75 unchanged lines hidden (view full) ---

1161 /*
1162 * Must wait for packet to be sent since we are
1163 * exiting the loop.
1164 */
1165 packet_write_wait();
1166 /* Flag that we want to exit. */
1167 quit_pending = 1;
1168}
1169static void
1170client_input_agent_open(int type, u_int32_t seq, void *ctxt)
1171{
1172 Channel *c = NULL;
1173 int remote_id, sock;
1134
1174
1175 /* Read the remote channel number from the message. */
1176 remote_id = packet_get_int();
1177 packet_check_eom();
1178
1179 /*
1180 * Get a connection to the local authentication agent (this may again
1181 * get forwarded).
1182 */
1183 sock = ssh_get_authentication_socket();
1184
1185 /*
1186 * If we could not connect the agent, send an error message back to
1187 * the server. This should never happen unless the agent dies,
1188 * because authentication forwarding is only enabled if we have an
1189 * agent.
1190 */
1191 if (sock >= 0) {
1192 c = channel_new("", SSH_CHANNEL_OPEN, sock, sock,
1193 -1, 0, 0, 0, "authentication agent connection", 1);
1194 c->remote_id = remote_id;
1195 c->force_drain = 1;
1196 }
1197 if (c == NULL) {
1198 packet_start(SSH_MSG_CHANNEL_OPEN_FAILURE);
1199 packet_put_int(remote_id);
1200 } else {
1201 /* Send a confirmation to the remote host. */
1202 debug("Forwarding authentication connection.");
1203 packet_start(SSH_MSG_CHANNEL_OPEN_CONFIRMATION);
1204 packet_put_int(remote_id);
1205 packet_put_int(c->self);
1206 }
1207 packet_send();
1208}
1209
1135static Channel *
1136client_request_forwarded_tcpip(const char *request_type, int rchan)
1137{
1138 Channel *c = NULL;
1139 char *listen_address, *originator_address;
1140 int listen_port, originator_port;
1141 int sock;
1142

--- 170 unchanged lines hidden (view full) ---

1313client_input_global_request(int type, u_int32_t seq, void *ctxt)
1314{
1315 char *rtype;
1316 int want_reply;
1317 int success = 0;
1318
1319 rtype = packet_get_string(NULL);
1320 want_reply = packet_get_char();
1210static Channel *
1211client_request_forwarded_tcpip(const char *request_type, int rchan)
1212{
1213 Channel *c = NULL;
1214 char *listen_address, *originator_address;
1215 int listen_port, originator_port;
1216 int sock;
1217

--- 170 unchanged lines hidden (view full) ---

1388client_input_global_request(int type, u_int32_t seq, void *ctxt)
1389{
1390 char *rtype;
1391 int want_reply;
1392 int success = 0;
1393
1394 rtype = packet_get_string(NULL);
1395 want_reply = packet_get_char();
1321 debug("client_input_global_request: rtype %s want_reply %d", rtype, want_reply);
1396 debug("client_input_global_request: rtype %s want_reply %d",
1397 rtype, want_reply);
1322 if (want_reply) {
1323 packet_start(success ?
1324 SSH2_MSG_REQUEST_SUCCESS : SSH2_MSG_REQUEST_FAILURE);
1325 packet_send();
1326 packet_write_wait();
1327 }
1328 xfree(rtype);
1329}

--- 31 unchanged lines hidden (view full) ---

1361 dispatch_set(SSH_MSG_CHANNEL_OPEN_CONFIRMATION, &channel_input_open_confirmation);
1362 dispatch_set(SSH_MSG_CHANNEL_OPEN_FAILURE, &channel_input_open_failure);
1363 dispatch_set(SSH_MSG_PORT_OPEN, &channel_input_port_open);
1364 dispatch_set(SSH_SMSG_EXITSTATUS, &client_input_exit_status);
1365 dispatch_set(SSH_SMSG_STDERR_DATA, &client_input_stderr_data);
1366 dispatch_set(SSH_SMSG_STDOUT_DATA, &client_input_stdout_data);
1367
1368 dispatch_set(SSH_SMSG_AGENT_OPEN, options.forward_agent ?
1398 if (want_reply) {
1399 packet_start(success ?
1400 SSH2_MSG_REQUEST_SUCCESS : SSH2_MSG_REQUEST_FAILURE);
1401 packet_send();
1402 packet_write_wait();
1403 }
1404 xfree(rtype);
1405}

--- 31 unchanged lines hidden (view full) ---

1437 dispatch_set(SSH_MSG_CHANNEL_OPEN_CONFIRMATION, &channel_input_open_confirmation);
1438 dispatch_set(SSH_MSG_CHANNEL_OPEN_FAILURE, &channel_input_open_failure);
1439 dispatch_set(SSH_MSG_PORT_OPEN, &channel_input_port_open);
1440 dispatch_set(SSH_SMSG_EXITSTATUS, &client_input_exit_status);
1441 dispatch_set(SSH_SMSG_STDERR_DATA, &client_input_stderr_data);
1442 dispatch_set(SSH_SMSG_STDOUT_DATA, &client_input_stdout_data);
1443
1444 dispatch_set(SSH_SMSG_AGENT_OPEN, options.forward_agent ?
1369 &auth_input_open_request : &deny_input_open);
1445 &client_input_agent_open : &deny_input_open);
1370 dispatch_set(SSH_SMSG_X11_OPEN, options.forward_x11 ?
1371 &x11_input_open : &deny_input_open);
1372}
1373static void
1374client_init_dispatch_15(void)
1375{
1376 client_init_dispatch_13();
1377 dispatch_set(SSH_MSG_CHANNEL_CLOSE, &channel_input_ieof);

--- 4 unchanged lines hidden (view full) ---

1382{
1383 if (compat20)
1384 client_init_dispatch_20();
1385 else if (compat13)
1386 client_init_dispatch_13();
1387 else
1388 client_init_dispatch_15();
1389}
1446 dispatch_set(SSH_SMSG_X11_OPEN, options.forward_x11 ?
1447 &x11_input_open : &deny_input_open);
1448}
1449static void
1450client_init_dispatch_15(void)
1451{
1452 client_init_dispatch_13();
1453 dispatch_set(SSH_MSG_CHANNEL_CLOSE, &channel_input_ieof);

--- 4 unchanged lines hidden (view full) ---

1458{
1459 if (compat20)
1460 client_init_dispatch_20();
1461 else if (compat13)
1462 client_init_dispatch_13();
1463 else
1464 client_init_dispatch_15();
1465}
1466
1467/* client specific fatal cleanup */
1468void
1469cleanup_exit(int i)
1470{
1471 leave_raw_mode();
1472 leave_non_blocking();
1473 _exit(i);
1474}