diff options
author | Colin Watson <cjwatson@debian.org> | 2010-03-31 10:46:28 +0100 |
---|---|---|
committer | Colin Watson <cjwatson@debian.org> | 2010-03-31 10:46:28 +0100 |
commit | efd3d4522636ae029488c2e9730b60c88e257d2e (patch) | |
tree | 31e02ac3f16090ce8c53448677356b2b7f423683 /clientloop.c | |
parent | bbec4db36d464ea1d464a707625125f9fd5c7b5e (diff) | |
parent | d1a87e462e1db89f19cd960588d0c6b287cb5ccc (diff) |
* New upstream release (LP: #535029).
- After a transition period of about 10 years, this release disables SSH
protocol 1 by default. Clients and servers that need to use the
legacy protocol must explicitly enable it in ssh_config / sshd_config
or on the command-line.
- Remove the libsectok/OpenSC-based smartcard code and add support for
PKCS#11 tokens. This support is enabled by default in the Debian
packaging, since it now doesn't involve additional library
dependencies (closes: #231472, LP: #16918).
- Add support for certificate authentication of users and hosts using a
new, minimal OpenSSH certificate format (closes: #482806).
- Added a 'netcat mode' to ssh(1): "ssh -W host:port ...".
- Add the ability to revoke keys in sshd(8) and ssh(1). (For the Debian
package, this overlaps with the key blacklisting facility added in
openssh 1:4.7p1-9, but with different file formats and slightly
different scopes; for the moment, I've roughly merged the two.)
- Various multiplexing improvements, including support for requesting
port-forwardings via the multiplex protocol (closes: #360151).
- Allow setting an explicit umask on the sftp-server(8) commandline to
override whatever default the user has (closes: #496843).
- Many sftp client improvements, including tab-completion, more options,
and recursive transfer support for get/put (LP: #33378). The old
mget/mput commands never worked properly and have been removed
(closes: #270399, #428082).
- Do not prompt for a passphrase if we fail to open a keyfile, and log
the reason why the open failed to debug (closes: #431538).
- Prevent sftp from crashing when given a "-" without a command. Also,
allow whitespace to follow a "-" (closes: #531561).
Diffstat (limited to 'clientloop.c')
-rw-r--r-- | clientloop.c | 75 |
1 files changed, 40 insertions, 35 deletions
diff --git a/clientloop.c b/clientloop.c index cea0d617a..a55fe9995 100644 --- a/clientloop.c +++ b/clientloop.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: clientloop.c,v 1.213 2009/07/05 19:28:33 stevesk Exp $ */ | 1 | /* $OpenBSD: clientloop.c,v 1.218 2010/01/28 00:21:18 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 |
@@ -125,7 +125,7 @@ extern int stdin_null_flag; | |||
125 | extern int no_shell_flag; | 125 | extern int no_shell_flag; |
126 | 126 | ||
127 | /* Control socket */ | 127 | /* Control socket */ |
128 | extern int muxserver_sock; | 128 | extern int muxserver_sock; /* XXX use mux_client_cleanup() instead */ |
129 | 129 | ||
130 | /* | 130 | /* |
131 | * Name of the host we are connecting to. This is the name given on the | 131 | * Name of the host we are connecting to. This is the name given on the |
@@ -134,6 +134,9 @@ extern int muxserver_sock; | |||
134 | */ | 134 | */ |
135 | extern char *host; | 135 | extern char *host; |
136 | 136 | ||
137 | /* Force TTY allocation */ | ||
138 | extern int force_tty_flag; | ||
139 | |||
137 | /* | 140 | /* |
138 | * Flag to indicate that we have received a window change signal which has | 141 | * Flag to indicate that we have received a window change signal which has |
139 | * not yet been processed. This will cause a message indicating the new | 142 | * not yet been processed. This will cause a message indicating the new |
@@ -147,7 +150,7 @@ static volatile sig_atomic_t received_signal = 0; | |||
147 | static int in_non_blocking_mode = 0; | 150 | static int in_non_blocking_mode = 0; |
148 | 151 | ||
149 | /* Common data for the client loop code. */ | 152 | /* Common data for the client loop code. */ |
150 | static volatile sig_atomic_t quit_pending; /* Set non-zero to quit the loop. */ | 153 | volatile sig_atomic_t quit_pending; /* Set non-zero to quit the loop. */ |
151 | static int escape_char1; /* Escape character. (proto1 only) */ | 154 | static int escape_char1; /* Escape character. (proto1 only) */ |
152 | static int escape_pending1; /* Last character was an escape (proto1 only) */ | 155 | static int escape_pending1; /* Last character was an escape (proto1 only) */ |
153 | static int last_was_cr; /* Last character was a newline. */ | 156 | static int last_was_cr; /* Last character was a newline. */ |
@@ -165,6 +168,8 @@ static int session_closed = 0; /* In SSH2: login session closed. */ | |||
165 | static void client_init_dispatch(void); | 168 | static void client_init_dispatch(void); |
166 | int session_ident = -1; | 169 | int session_ident = -1; |
167 | 170 | ||
171 | int session_resumed = 0; | ||
172 | |||
168 | /* Track escape per proto2 channel */ | 173 | /* Track escape per proto2 channel */ |
169 | struct escape_filter_ctx { | 174 | struct escape_filter_ctx { |
170 | int escape_pending; | 175 | int escape_pending; |
@@ -568,9 +573,6 @@ client_wait_until_can_do_something(fd_set **readsetp, fd_set **writesetp, | |||
568 | if (packet_have_data_to_write()) | 573 | if (packet_have_data_to_write()) |
569 | FD_SET(connection_out, *writesetp); | 574 | FD_SET(connection_out, *writesetp); |
570 | 575 | ||
571 | if (muxserver_sock != -1) | ||
572 | FD_SET(muxserver_sock, *readsetp); | ||
573 | |||
574 | /* | 576 | /* |
575 | * Wait for something to happen. This will suspend the process until | 577 | * Wait for something to happen. This will suspend the process until |
576 | * some selected descriptor can be read, written, or has some other | 578 | * some selected descriptor can be read, written, or has some other |
@@ -617,7 +619,7 @@ client_suspend_self(Buffer *bin, Buffer *bout, Buffer *berr) | |||
617 | atomicio(vwrite, fileno(stderr), buffer_ptr(berr), | 619 | atomicio(vwrite, fileno(stderr), buffer_ptr(berr), |
618 | buffer_len(berr)); | 620 | buffer_len(berr)); |
619 | 621 | ||
620 | leave_raw_mode(); | 622 | leave_raw_mode(force_tty_flag); |
621 | 623 | ||
622 | /* | 624 | /* |
623 | * Free (and clear) the buffer to reduce the amount of data that gets | 625 | * Free (and clear) the buffer to reduce the amount of data that gets |
@@ -638,7 +640,7 @@ client_suspend_self(Buffer *bin, Buffer *bout, Buffer *berr) | |||
638 | buffer_init(bout); | 640 | buffer_init(bout); |
639 | buffer_init(berr); | 641 | buffer_init(berr); |
640 | 642 | ||
641 | enter_raw_mode(); | 643 | enter_raw_mode(force_tty_flag); |
642 | } | 644 | } |
643 | 645 | ||
644 | static void | 646 | static void |
@@ -699,7 +701,7 @@ client_status_confirm(int type, Channel *c, void *ctx) | |||
699 | 701 | ||
700 | /* XXX supress on mux _client_ quietmode */ | 702 | /* XXX supress on mux _client_ quietmode */ |
701 | tochan = options.log_level >= SYSLOG_LEVEL_ERROR && | 703 | tochan = options.log_level >= SYSLOG_LEVEL_ERROR && |
702 | c->ctl_fd != -1 && c->extended_usage == CHAN_EXTENDED_WRITE; | 704 | c->ctl_chan != -1 && c->extended_usage == CHAN_EXTENDED_WRITE; |
703 | 705 | ||
704 | if (type == SSH2_MSG_CHANNEL_SUCCESS) { | 706 | if (type == SSH2_MSG_CHANNEL_SUCCESS) { |
705 | debug2("%s request accepted on channel %d", | 707 | debug2("%s request accepted on channel %d", |
@@ -781,7 +783,7 @@ process_cmdline(void) | |||
781 | bzero(&fwd, sizeof(fwd)); | 783 | bzero(&fwd, sizeof(fwd)); |
782 | fwd.listen_host = fwd.connect_host = NULL; | 784 | fwd.listen_host = fwd.connect_host = NULL; |
783 | 785 | ||
784 | leave_raw_mode(); | 786 | leave_raw_mode(force_tty_flag); |
785 | handler = signal(SIGINT, SIG_IGN); | 787 | handler = signal(SIGINT, SIG_IGN); |
786 | cmd = s = read_passphrase("\r\nssh> ", RP_ECHO); | 788 | cmd = s = read_passphrase("\r\nssh> ", RP_ECHO); |
787 | if (s == NULL) | 789 | if (s == NULL) |
@@ -843,6 +845,7 @@ process_cmdline(void) | |||
843 | while (isspace(*++s)) | 845 | while (isspace(*++s)) |
844 | ; | 846 | ; |
845 | 847 | ||
848 | /* XXX update list of forwards in options */ | ||
846 | if (delete) { | 849 | if (delete) { |
847 | cancel_port = 0; | 850 | cancel_port = 0; |
848 | cancel_host = hpdelim(&s); /* may be NULL */ | 851 | cancel_host = hpdelim(&s); /* may be NULL */ |
@@ -884,7 +887,7 @@ process_cmdline(void) | |||
884 | 887 | ||
885 | out: | 888 | out: |
886 | signal(SIGINT, handler); | 889 | signal(SIGINT, handler); |
887 | enter_raw_mode(); | 890 | enter_raw_mode(force_tty_flag); |
888 | if (cmd) | 891 | if (cmd) |
889 | xfree(cmd); | 892 | xfree(cmd); |
890 | if (fwd.listen_host != NULL) | 893 | if (fwd.listen_host != NULL) |
@@ -940,7 +943,7 @@ process_escapes(Channel *c, Buffer *bin, Buffer *bout, Buffer *berr, | |||
940 | escape_char); | 943 | escape_char); |
941 | buffer_append(berr, string, strlen(string)); | 944 | buffer_append(berr, string, strlen(string)); |
942 | 945 | ||
943 | if (c && c->ctl_fd != -1) { | 946 | if (c && c->ctl_chan != -1) { |
944 | chan_read_failed(c); | 947 | chan_read_failed(c); |
945 | chan_write_failed(c); | 948 | chan_write_failed(c); |
946 | return 0; | 949 | return 0; |
@@ -950,7 +953,7 @@ process_escapes(Channel *c, Buffer *bin, Buffer *bout, Buffer *berr, | |||
950 | 953 | ||
951 | case 'Z' - 64: | 954 | case 'Z' - 64: |
952 | /* XXX support this for mux clients */ | 955 | /* XXX support this for mux clients */ |
953 | if (c && c->ctl_fd != -1) { | 956 | if (c && c->ctl_chan != -1) { |
954 | noescape: | 957 | noescape: |
955 | snprintf(string, sizeof string, | 958 | snprintf(string, sizeof string, |
956 | "%c%c escape not available to " | 959 | "%c%c escape not available to " |
@@ -995,7 +998,7 @@ process_escapes(Channel *c, Buffer *bin, Buffer *bout, Buffer *berr, | |||
995 | continue; | 998 | continue; |
996 | 999 | ||
997 | case '&': | 1000 | case '&': |
998 | if (c && c->ctl_fd != -1) | 1001 | if (c && c->ctl_chan != -1) |
999 | goto noescape; | 1002 | goto noescape; |
1000 | /* | 1003 | /* |
1001 | * Detach the program (continue to serve | 1004 | * Detach the program (continue to serve |
@@ -1003,7 +1006,7 @@ process_escapes(Channel *c, Buffer *bin, Buffer *bout, Buffer *berr, | |||
1003 | * more new connections). | 1006 | * more new connections). |
1004 | */ | 1007 | */ |
1005 | /* Restore tty modes. */ | 1008 | /* Restore tty modes. */ |
1006 | leave_raw_mode(); | 1009 | leave_raw_mode(force_tty_flag); |
1007 | 1010 | ||
1008 | /* Stop listening for new connections. */ | 1011 | /* Stop listening for new connections. */ |
1009 | channel_stop_listening(); | 1012 | channel_stop_listening(); |
@@ -1046,7 +1049,7 @@ process_escapes(Channel *c, Buffer *bin, Buffer *bout, Buffer *berr, | |||
1046 | continue; | 1049 | continue; |
1047 | 1050 | ||
1048 | case '?': | 1051 | case '?': |
1049 | if (c && c->ctl_fd != -1) { | 1052 | if (c && c->ctl_chan != -1) { |
1050 | snprintf(string, sizeof string, | 1053 | snprintf(string, sizeof string, |
1051 | "%c?\r\n\ | 1054 | "%c?\r\n\ |
1052 | Supported escape sequences:\r\n\ | 1055 | Supported escape sequences:\r\n\ |
@@ -1095,7 +1098,7 @@ Supported escape sequences:\r\n\ | |||
1095 | continue; | 1098 | continue; |
1096 | 1099 | ||
1097 | case 'C': | 1100 | case 'C': |
1098 | if (c && c->ctl_fd != -1) | 1101 | if (c && c->ctl_chan != -1) |
1099 | goto noescape; | 1102 | goto noescape; |
1100 | process_cmdline(); | 1103 | process_cmdline(); |
1101 | continue; | 1104 | continue; |
@@ -1298,7 +1301,7 @@ client_channel_closed(int id, void *arg) | |||
1298 | { | 1301 | { |
1299 | channel_cancel_cleanup(id); | 1302 | channel_cancel_cleanup(id); |
1300 | session_closed = 1; | 1303 | session_closed = 1; |
1301 | leave_raw_mode(); | 1304 | leave_raw_mode(force_tty_flag); |
1302 | } | 1305 | } |
1303 | 1306 | ||
1304 | /* | 1307 | /* |
@@ -1331,8 +1334,6 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id) | |||
1331 | connection_in = packet_get_connection_in(); | 1334 | connection_in = packet_get_connection_in(); |
1332 | connection_out = packet_get_connection_out(); | 1335 | connection_out = packet_get_connection_out(); |
1333 | max_fd = MAX(connection_in, connection_out); | 1336 | max_fd = MAX(connection_in, connection_out); |
1334 | if (muxserver_sock != -1) | ||
1335 | max_fd = MAX(max_fd, muxserver_sock); | ||
1336 | 1337 | ||
1337 | if (!compat20) { | 1338 | if (!compat20) { |
1338 | /* enable nonblocking unless tty */ | 1339 | /* enable nonblocking unless tty */ |
@@ -1371,7 +1372,7 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id) | |||
1371 | signal(SIGWINCH, window_change_handler); | 1372 | signal(SIGWINCH, window_change_handler); |
1372 | 1373 | ||
1373 | if (have_pty) | 1374 | if (have_pty) |
1374 | enter_raw_mode(); | 1375 | enter_raw_mode(force_tty_flag); |
1375 | 1376 | ||
1376 | if (compat20) { | 1377 | if (compat20) { |
1377 | session_ident = ssh2_chan_id; | 1378 | session_ident = ssh2_chan_id; |
@@ -1459,12 +1460,6 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id) | |||
1459 | /* Buffer input from the connection. */ | 1460 | /* Buffer input from the connection. */ |
1460 | client_process_net_input(readset); | 1461 | client_process_net_input(readset); |
1461 | 1462 | ||
1462 | /* Accept control connections. */ | ||
1463 | if (muxserver_sock != -1 &&FD_ISSET(muxserver_sock, readset)) { | ||
1464 | if (muxserver_accept_control()) | ||
1465 | quit_pending = 1; | ||
1466 | } | ||
1467 | |||
1468 | if (quit_pending) | 1463 | if (quit_pending) |
1469 | break; | 1464 | break; |
1470 | 1465 | ||
@@ -1478,6 +1473,14 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id) | |||
1478 | client_process_output(writeset); | 1473 | client_process_output(writeset); |
1479 | } | 1474 | } |
1480 | 1475 | ||
1476 | if (session_resumed) { | ||
1477 | connection_in = packet_get_connection_in(); | ||
1478 | connection_out = packet_get_connection_out(); | ||
1479 | max_fd = MAX(max_fd, connection_out); | ||
1480 | max_fd = MAX(max_fd, connection_in); | ||
1481 | session_resumed = 0; | ||
1482 | } | ||
1483 | |||
1481 | /* | 1484 | /* |
1482 | * Send as much buffered packet data as possible to the | 1485 | * Send as much buffered packet data as possible to the |
1483 | * sender. | 1486 | * sender. |
@@ -1506,7 +1509,7 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id) | |||
1506 | channel_free_all(); | 1509 | channel_free_all(); |
1507 | 1510 | ||
1508 | if (have_pty) | 1511 | if (have_pty) |
1509 | leave_raw_mode(); | 1512 | leave_raw_mode(force_tty_flag); |
1510 | 1513 | ||
1511 | /* restore blocking io */ | 1514 | /* restore blocking io */ |
1512 | if (!isatty(fileno(stdin))) | 1515 | if (!isatty(fileno(stdin))) |
@@ -1866,15 +1869,17 @@ client_input_channel_req(int type, u_int32_t seq, void *ctxt) | |||
1866 | chan_rcvd_eow(c); | 1869 | chan_rcvd_eow(c); |
1867 | } else if (strcmp(rtype, "exit-status") == 0) { | 1870 | } else if (strcmp(rtype, "exit-status") == 0) { |
1868 | exitval = packet_get_int(); | 1871 | exitval = packet_get_int(); |
1869 | if (id == session_ident) { | 1872 | if (c->ctl_chan != -1) { |
1873 | mux_exit_message(c, exitval); | ||
1874 | success = 1; | ||
1875 | } else if (id == session_ident) { | ||
1876 | /* Record exit value of local session */ | ||
1870 | success = 1; | 1877 | success = 1; |
1871 | exit_status = exitval; | 1878 | exit_status = exitval; |
1872 | } else if (c->ctl_fd == -1) { | ||
1873 | error("client_input_channel_req: unexpected channel %d", | ||
1874 | session_ident); | ||
1875 | } else { | 1879 | } else { |
1876 | atomicio(vwrite, c->ctl_fd, &exitval, sizeof(exitval)); | 1880 | /* Probably for a mux channel that has already closed */ |
1877 | success = 1; | 1881 | debug("%s: no sink for exit-status on channel %d", |
1882 | __func__, id); | ||
1878 | } | 1883 | } |
1879 | packet_check_eom(); | 1884 | packet_check_eom(); |
1880 | } | 1885 | } |
@@ -2070,7 +2075,7 @@ client_init_dispatch(void) | |||
2070 | void | 2075 | void |
2071 | cleanup_exit(int i) | 2076 | cleanup_exit(int i) |
2072 | { | 2077 | { |
2073 | leave_raw_mode(); | 2078 | leave_raw_mode(force_tty_flag); |
2074 | leave_non_blocking(); | 2079 | leave_non_blocking(); |
2075 | if (options.control_path != NULL && muxserver_sock != -1) | 2080 | if (options.control_path != NULL && muxserver_sock != -1) |
2076 | unlink(options.control_path); | 2081 | unlink(options.control_path); |