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} |
|