diff options
Diffstat (limited to 'clientloop.c')
-rw-r--r-- | clientloop.c | 106 |
1 files changed, 70 insertions, 36 deletions
diff --git a/clientloop.c b/clientloop.c index 37cecf5a6..663daae76 100644 --- a/clientloop.c +++ b/clientloop.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: clientloop.c,v 1.196 2008/06/12 04:06:00 djm Exp $ */ | 1 | /* $OpenBSD: clientloop.c,v 1.197 2008/06/12 04:17:47 djm Exp $ */ |
2 | /* | 2 | /* |
3 | * Author: Tatu Ylonen <ylo@cs.hut.fi> | 3 | * Author: Tatu Ylonen <ylo@cs.hut.fi> |
4 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland | 4 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland |
@@ -147,8 +147,8 @@ static volatile sig_atomic_t quit_pending; /* Set non-zero to quit the loop. */ | |||
147 | static int escape_char1; /* Escape character. (proto1 only) */ | 147 | static int escape_char1; /* Escape character. (proto1 only) */ |
148 | static int escape_pending1; /* Last character was an escape (proto1 only) */ | 148 | static int escape_pending1; /* Last character was an escape (proto1 only) */ |
149 | static int last_was_cr; /* Last character was a newline. */ | 149 | static int last_was_cr; /* Last character was a newline. */ |
150 | static int exit_status; /* Used to store the exit status of the command. */ | 150 | static int exit_status; /* Used to store the command exit status. */ |
151 | static int stdin_eof; /* EOF has been encountered on standard error. */ | 151 | static int stdin_eof; /* EOF has been encountered on stderr. */ |
152 | static Buffer stdin_buffer; /* Buffer for stdin data. */ | 152 | static Buffer stdin_buffer; /* Buffer for stdin data. */ |
153 | static Buffer stdout_buffer; /* Buffer for stdout data. */ | 153 | static Buffer stdout_buffer; /* Buffer for stdout data. */ |
154 | static Buffer stderr_buffer; /* Buffer for stderr data. */ | 154 | static Buffer stderr_buffer; /* Buffer for stderr data. */ |
@@ -392,7 +392,10 @@ client_check_initial_eof_on_stdin(void) | |||
392 | /* Check for immediate EOF on stdin. */ | 392 | /* Check for immediate EOF on stdin. */ |
393 | len = read(fileno(stdin), buf, 1); | 393 | len = read(fileno(stdin), buf, 1); |
394 | if (len == 0) { | 394 | if (len == 0) { |
395 | /* EOF. Record that we have seen it and send EOF to server. */ | 395 | /* |
396 | * EOF. Record that we have seen it and send | ||
397 | * EOF to server. | ||
398 | */ | ||
396 | debug("Sending eof."); | 399 | debug("Sending eof."); |
397 | stdin_eof = 1; | 400 | stdin_eof = 1; |
398 | packet_start(SSH_CMSG_EOF); | 401 | packet_start(SSH_CMSG_EOF); |
@@ -601,9 +604,11 @@ client_suspend_self(Buffer *bin, Buffer *bout, Buffer *berr) | |||
601 | { | 604 | { |
602 | /* Flush stdout and stderr buffers. */ | 605 | /* Flush stdout and stderr buffers. */ |
603 | if (buffer_len(bout) > 0) | 606 | if (buffer_len(bout) > 0) |
604 | atomicio(vwrite, fileno(stdout), buffer_ptr(bout), buffer_len(bout)); | 607 | atomicio(vwrite, fileno(stdout), buffer_ptr(bout), |
608 | buffer_len(bout)); | ||
605 | if (buffer_len(berr) > 0) | 609 | if (buffer_len(berr) > 0) |
606 | atomicio(vwrite, fileno(stderr), buffer_ptr(berr), buffer_len(berr)); | 610 | atomicio(vwrite, fileno(stderr), buffer_ptr(berr), |
611 | buffer_len(berr)); | ||
607 | 612 | ||
608 | leave_raw_mode(); | 613 | leave_raw_mode(); |
609 | 614 | ||
@@ -643,9 +648,13 @@ client_process_net_input(fd_set *readset) | |||
643 | /* Read as much as possible. */ | 648 | /* Read as much as possible. */ |
644 | len = read(connection_in, buf, sizeof(buf)); | 649 | len = read(connection_in, buf, sizeof(buf)); |
645 | if (len == 0) { | 650 | if (len == 0) { |
646 | /* Received EOF. The remote host has closed the connection. */ | 651 | /* |
647 | snprintf(buf, sizeof buf, "Connection to %.300s closed by remote host.\r\n", | 652 | * Received EOF. The remote host has closed the |
648 | host); | 653 | * connection. |
654 | */ | ||
655 | snprintf(buf, sizeof buf, | ||
656 | "Connection to %.300s closed by remote host.\r\n", | ||
657 | host); | ||
649 | buffer_append(&stderr_buffer, buf, strlen(buf)); | 658 | buffer_append(&stderr_buffer, buf, strlen(buf)); |
650 | quit_pending = 1; | 659 | quit_pending = 1; |
651 | return; | 660 | return; |
@@ -658,9 +667,13 @@ client_process_net_input(fd_set *readset) | |||
658 | len = 0; | 667 | len = 0; |
659 | 668 | ||
660 | if (len < 0) { | 669 | if (len < 0) { |
661 | /* An error has encountered. Perhaps there is a network problem. */ | 670 | /* |
662 | snprintf(buf, sizeof buf, "Read from remote host %.300s: %.100s\r\n", | 671 | * An error has encountered. Perhaps there is a |
663 | host, strerror(errno)); | 672 | * network problem. |
673 | */ | ||
674 | snprintf(buf, sizeof buf, | ||
675 | "Read from remote host %.300s: %.100s\r\n", | ||
676 | host, strerror(errno)); | ||
664 | buffer_append(&stderr_buffer, buf, strlen(buf)); | 677 | buffer_append(&stderr_buffer, buf, strlen(buf)); |
665 | quit_pending = 1; | 678 | quit_pending = 1; |
666 | return; | 679 | return; |
@@ -932,8 +945,7 @@ process_escapes(Channel *c, Buffer *bin, Buffer *bout, Buffer *berr, | |||
932 | strlen(string)); | 945 | strlen(string)); |
933 | continue; | 946 | continue; |
934 | } | 947 | } |
935 | /* Suspend the program. */ | 948 | /* Suspend the program. Inform the user */ |
936 | /* Print a message to that effect to the user. */ | ||
937 | snprintf(string, sizeof string, | 949 | snprintf(string, sizeof string, |
938 | "%c^Z [suspend ssh]\r\n", escape_char); | 950 | "%c^Z [suspend ssh]\r\n", escape_char); |
939 | buffer_append(berr, string, strlen(string)); | 951 | buffer_append(berr, string, strlen(string)); |
@@ -960,7 +972,8 @@ process_escapes(Channel *c, Buffer *bin, Buffer *bout, Buffer *berr, | |||
960 | case 'R': | 972 | case 'R': |
961 | if (compat20) { | 973 | if (compat20) { |
962 | if (datafellows & SSH_BUG_NOREKEY) | 974 | if (datafellows & SSH_BUG_NOREKEY) |
963 | logit("Server does not support re-keying"); | 975 | logit("Server does not " |
976 | "support re-keying"); | ||
964 | else | 977 | else |
965 | need_rekeying = 1; | 978 | need_rekeying = 1; |
966 | } | 979 | } |
@@ -970,8 +983,9 @@ process_escapes(Channel *c, Buffer *bin, Buffer *bout, Buffer *berr, | |||
970 | if (c && c->ctl_fd != -1) | 983 | if (c && c->ctl_fd != -1) |
971 | goto noescape; | 984 | goto noescape; |
972 | /* | 985 | /* |
973 | * Detach the program (continue to serve connections, | 986 | * Detach the program (continue to serve |
974 | * but put in background and no more new connections). | 987 | * connections, but put in background and no |
988 | * more new connections). | ||
975 | */ | 989 | */ |
976 | /* Restore tty modes. */ | 990 | /* Restore tty modes. */ |
977 | leave_raw_mode(); | 991 | leave_raw_mode(); |
@@ -1000,9 +1014,9 @@ process_escapes(Channel *c, Buffer *bin, Buffer *bout, Buffer *berr, | |||
1000 | return -1; | 1014 | return -1; |
1001 | } else if (!stdin_eof) { | 1015 | } else if (!stdin_eof) { |
1002 | /* | 1016 | /* |
1003 | * Sending SSH_CMSG_EOF alone does not always appear | 1017 | * Sending SSH_CMSG_EOF alone does not |
1004 | * to be enough. So we try to send an EOF character | 1018 | * always appear to be enough. So we |
1005 | * first. | 1019 | * try to send an EOF character first. |
1006 | */ | 1020 | */ |
1007 | packet_start(SSH_CMSG_STDIN_DATA); | 1021 | packet_start(SSH_CMSG_STDIN_DATA); |
1008 | packet_put_string("\004", 1); | 1022 | packet_put_string("\004", 1); |
@@ -1081,11 +1095,14 @@ Supported escape sequences:\r\n\ | |||
1081 | } | 1095 | } |
1082 | } else { | 1096 | } else { |
1083 | /* | 1097 | /* |
1084 | * The previous character was not an escape char. Check if this | 1098 | * The previous character was not an escape char. |
1085 | * is an escape. | 1099 | * Check if this is an escape. |
1086 | */ | 1100 | */ |
1087 | if (last_was_cr && ch == escape_char) { | 1101 | if (last_was_cr && ch == escape_char) { |
1088 | /* It is. Set the flag and continue to next character. */ | 1102 | /* |
1103 | * It is. Set the flag and continue to | ||
1104 | * next character. | ||
1105 | */ | ||
1089 | *escape_pendingp = 1; | 1106 | *escape_pendingp = 1; |
1090 | continue; | 1107 | continue; |
1091 | } | 1108 | } |
@@ -1121,7 +1138,8 @@ client_process_input(fd_set *readset) | |||
1121 | * if it was an error condition. | 1138 | * if it was an error condition. |
1122 | */ | 1139 | */ |
1123 | if (len < 0) { | 1140 | if (len < 0) { |
1124 | snprintf(buf, sizeof buf, "read: %.100s\r\n", strerror(errno)); | 1141 | snprintf(buf, sizeof buf, "read: %.100s\r\n", |
1142 | strerror(errno)); | ||
1125 | buffer_append(&stderr_buffer, buf, strlen(buf)); | 1143 | buffer_append(&stderr_buffer, buf, strlen(buf)); |
1126 | } | 1144 | } |
1127 | /* Mark that we have seen EOF. */ | 1145 | /* Mark that we have seen EOF. */ |
@@ -1145,8 +1163,9 @@ client_process_input(fd_set *readset) | |||
1145 | buffer_append(&stdin_buffer, buf, len); | 1163 | buffer_append(&stdin_buffer, buf, len); |
1146 | } else { | 1164 | } else { |
1147 | /* | 1165 | /* |
1148 | * Normal, successful read. But we have an escape character | 1166 | * Normal, successful read. But we have an escape |
1149 | * and have to process the characters one by one. | 1167 | * character and have to process the characters one |
1168 | * by one. | ||
1150 | */ | 1169 | */ |
1151 | if (process_escapes(NULL, &stdin_buffer, | 1170 | if (process_escapes(NULL, &stdin_buffer, |
1152 | &stdout_buffer, &stderr_buffer, buf, len) == -1) | 1171 | &stdout_buffer, &stderr_buffer, buf, len) == -1) |
@@ -1174,7 +1193,8 @@ client_process_output(fd_set *writeset) | |||
1174 | * An error or EOF was encountered. Put an | 1193 | * An error or EOF was encountered. Put an |
1175 | * error message to stderr buffer. | 1194 | * error message to stderr buffer. |
1176 | */ | 1195 | */ |
1177 | snprintf(buf, sizeof buf, "write stdout: %.50s\r\n", strerror(errno)); | 1196 | snprintf(buf, sizeof buf, |
1197 | "write stdout: %.50s\r\n", strerror(errno)); | ||
1178 | buffer_append(&stderr_buffer, buf, strlen(buf)); | 1198 | buffer_append(&stderr_buffer, buf, strlen(buf)); |
1179 | quit_pending = 1; | 1199 | quit_pending = 1; |
1180 | return; | 1200 | return; |
@@ -1193,7 +1213,10 @@ client_process_output(fd_set *writeset) | |||
1193 | if (errno == EINTR || errno == EAGAIN) | 1213 | if (errno == EINTR || errno == EAGAIN) |
1194 | len = 0; | 1214 | len = 0; |
1195 | else { | 1215 | else { |
1196 | /* EOF or error, but can't even print error message. */ | 1216 | /* |
1217 | * EOF or error, but can't even print | ||
1218 | * error message. | ||
1219 | */ | ||
1197 | quit_pending = 1; | 1220 | quit_pending = 1; |
1198 | return; | 1221 | return; |
1199 | } | 1222 | } |
@@ -1219,7 +1242,8 @@ client_process_output(fd_set *writeset) | |||
1219 | static void | 1242 | static void |
1220 | client_process_buffered_input_packets(void) | 1243 | client_process_buffered_input_packets(void) |
1221 | { | 1244 | { |
1222 | dispatch_run(DISPATCH_NONBLOCK, &quit_pending, compat20 ? xxx_kex : NULL); | 1245 | dispatch_run(DISPATCH_NONBLOCK, &quit_pending, |
1246 | compat20 ? xxx_kex : NULL); | ||
1223 | } | 1247 | } |
1224 | 1248 | ||
1225 | /* scan buf[] for '~' before sending data to the peer */ | 1249 | /* scan buf[] for '~' before sending data to the peer */ |
@@ -1423,7 +1447,10 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id) | |||
1423 | client_process_output(writeset); | 1447 | client_process_output(writeset); |
1424 | } | 1448 | } |
1425 | 1449 | ||
1426 | /* Send as much buffered packet data as possible to the sender. */ | 1450 | /* |
1451 | * Send as much buffered packet data as possible to the | ||
1452 | * sender. | ||
1453 | */ | ||
1427 | if (FD_ISSET(connection_out, writeset)) | 1454 | if (FD_ISSET(connection_out, writeset)) |
1428 | packet_write_poll(); | 1455 | packet_write_poll(); |
1429 | } | 1456 | } |
@@ -1468,7 +1495,8 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id) | |||
1468 | * that the connection has been closed. | 1495 | * that the connection has been closed. |
1469 | */ | 1496 | */ |
1470 | if (have_pty && options.log_level != SYSLOG_LEVEL_QUIET) { | 1497 | if (have_pty && options.log_level != SYSLOG_LEVEL_QUIET) { |
1471 | snprintf(buf, sizeof buf, "Connection to %.64s closed.\r\n", host); | 1498 | snprintf(buf, sizeof buf, |
1499 | "Connection to %.64s closed.\r\n", host); | ||
1472 | buffer_append(&stderr_buffer, buf, strlen(buf)); | 1500 | buffer_append(&stderr_buffer, buf, strlen(buf)); |
1473 | } | 1501 | } |
1474 | 1502 | ||
@@ -1504,8 +1532,8 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id) | |||
1504 | 1532 | ||
1505 | /* Report bytes transferred, and transfer rates. */ | 1533 | /* Report bytes transferred, and transfer rates. */ |
1506 | total_time = get_current_time() - start_time; | 1534 | total_time = get_current_time() - start_time; |
1507 | debug("Transferred: stdin %lu, stdout %lu, stderr %lu bytes in %.1f seconds", | 1535 | debug("Transferred: stdin %lu, stdout %lu, stderr %lu bytes in %.1f " |
1508 | stdin_bytes, stdout_bytes, stderr_bytes, total_time); | 1536 | "seconds", stdin_bytes, stdout_bytes, stderr_bytes, total_time); |
1509 | if (total_time > 0) | 1537 | if (total_time > 0) |
1510 | debug("Bytes per second: stdin %.1f, stdout %.1f, stderr %.1f", | 1538 | debug("Bytes per second: stdin %.1f, stdout %.1f, stderr %.1f", |
1511 | stdin_bytes / total_time, stdout_bytes / total_time, | 1539 | stdin_bytes / total_time, stdout_bytes / total_time, |
@@ -1631,7 +1659,8 @@ client_request_x11(const char *request_type, int rchan) | |||
1631 | 1659 | ||
1632 | if (!options.forward_x11) { | 1660 | if (!options.forward_x11) { |
1633 | error("Warning: ssh server tried X11 forwarding."); | 1661 | error("Warning: ssh server tried X11 forwarding."); |
1634 | error("Warning: this is probably a break-in attempt by a malicious server."); | 1662 | error("Warning: this is probably a break-in attempt by a " |
1663 | "malicious server."); | ||
1635 | return NULL; | 1664 | return NULL; |
1636 | } | 1665 | } |
1637 | originator = packet_get_string(NULL); | 1666 | originator = packet_get_string(NULL); |
@@ -1664,7 +1693,8 @@ client_request_agent(const char *request_type, int rchan) | |||
1664 | 1693 | ||
1665 | if (!options.forward_agent) { | 1694 | if (!options.forward_agent) { |
1666 | error("Warning: ssh server tried agent forwarding."); | 1695 | error("Warning: ssh server tried agent forwarding."); |
1667 | error("Warning: this is probably a break-in attempt by a malicious server."); | 1696 | error("Warning: this is probably a break-in attempt by a " |
1697 | "malicious server."); | ||
1668 | return NULL; | 1698 | return NULL; |
1669 | } | 1699 | } |
1670 | sock = ssh_get_authentication_socket(); | 1700 | sock = ssh_get_authentication_socket(); |
@@ -1790,7 +1820,8 @@ client_input_channel_req(int type, u_int32_t seq, void *ctxt) | |||
1790 | if (id == -1) { | 1820 | if (id == -1) { |
1791 | error("client_input_channel_req: request for channel -1"); | 1821 | error("client_input_channel_req: request for channel -1"); |
1792 | } else if ((c = channel_lookup(id)) == NULL) { | 1822 | } else if ((c = channel_lookup(id)) == NULL) { |
1793 | error("client_input_channel_req: channel %d: unknown channel", id); | 1823 | error("client_input_channel_req: channel %d: " |
1824 | "unknown channel", id); | ||
1794 | } else if (strcmp(rtype, "eow@openssh.com") == 0) { | 1825 | } else if (strcmp(rtype, "eow@openssh.com") == 0) { |
1795 | packet_check_eom(); | 1826 | packet_check_eom(); |
1796 | chan_rcvd_eow(c); | 1827 | chan_rcvd_eow(c); |
@@ -1956,6 +1987,7 @@ client_init_dispatch_20(void) | |||
1956 | dispatch_set(SSH2_MSG_REQUEST_FAILURE, &client_global_request_reply); | 1987 | dispatch_set(SSH2_MSG_REQUEST_FAILURE, &client_global_request_reply); |
1957 | dispatch_set(SSH2_MSG_REQUEST_SUCCESS, &client_global_request_reply); | 1988 | dispatch_set(SSH2_MSG_REQUEST_SUCCESS, &client_global_request_reply); |
1958 | } | 1989 | } |
1990 | |||
1959 | static void | 1991 | static void |
1960 | client_init_dispatch_13(void) | 1992 | client_init_dispatch_13(void) |
1961 | { | 1993 | { |
@@ -1975,6 +2007,7 @@ client_init_dispatch_13(void) | |||
1975 | dispatch_set(SSH_SMSG_X11_OPEN, options.forward_x11 ? | 2007 | dispatch_set(SSH_SMSG_X11_OPEN, options.forward_x11 ? |
1976 | &x11_input_open : &deny_input_open); | 2008 | &x11_input_open : &deny_input_open); |
1977 | } | 2009 | } |
2010 | |||
1978 | static void | 2011 | static void |
1979 | client_init_dispatch_15(void) | 2012 | client_init_dispatch_15(void) |
1980 | { | 2013 | { |
@@ -1982,6 +2015,7 @@ client_init_dispatch_15(void) | |||
1982 | dispatch_set(SSH_MSG_CHANNEL_CLOSE, &channel_input_ieof); | 2015 | dispatch_set(SSH_MSG_CHANNEL_CLOSE, &channel_input_ieof); |
1983 | dispatch_set(SSH_MSG_CHANNEL_CLOSE_CONFIRMATION, & channel_input_oclose); | 2016 | dispatch_set(SSH_MSG_CHANNEL_CLOSE_CONFIRMATION, & channel_input_oclose); |
1984 | } | 2017 | } |
2018 | |||
1985 | static void | 2019 | static void |
1986 | client_init_dispatch(void) | 2020 | client_init_dispatch(void) |
1987 | { | 2021 | { |