diff options
author | Colin Watson <cjwatson@debian.org> | 2011-09-06 14:56:29 +0100 |
---|---|---|
committer | Colin Watson <cjwatson@debian.org> | 2011-09-06 14:56:29 +0100 |
commit | 978e62d6f14c60747bddef2cc72d66a9c8b83b54 (patch) | |
tree | 89400a44e42d84937deba7864e4964d6c7734da5 /clientloop.c | |
parent | 87c685b8c6a49814fd782288097b3093f975aa72 (diff) | |
parent | 3a7e89697ca363de0f64e0d5704c57219294e41c (diff) |
* New upstream release (http://www.openssh.org/txt/release-5.9).
- Introduce sandboxing of the pre-auth privsep child using an optional
sshd_config(5) "UsePrivilegeSeparation=sandbox" mode that enables
mandatory restrictions on the syscalls the privsep child can perform.
- Add new SHA256-based HMAC transport integrity modes from
http://www.ietf.org/id/draft-dbider-sha2-mac-for-ssh-02.txt.
- The pre-authentication sshd(8) privilege separation slave process now
logs via a socket shared with the master process, avoiding the need to
maintain /dev/log inside the chroot (closes: #75043, #429243,
#599240).
- ssh(1) now warns when a server refuses X11 forwarding (closes:
#504757).
- sshd_config(5)'s AuthorizedKeysFile now accepts multiple paths,
separated by whitespace (closes: #76312). The authorized_keys2
fallback is deprecated but documented (closes: #560156).
- ssh(1) and sshd(8): set IPv6 traffic class from IPQoS, as well as IPv4
ToS/DSCP (closes: #498297).
- ssh-add(1) now accepts keys piped from standard input. E.g. "ssh-add
- < /path/to/key" (closes: #229124).
- Clean up lost-passphrase text in ssh-keygen(1) (closes: #444691).
- Say "required" rather than "recommended" in unprotected-private-key
warning (LP: #663455).
Diffstat (limited to 'clientloop.c')
-rw-r--r-- | clientloop.c | 110 |
1 files changed, 75 insertions, 35 deletions
diff --git a/clientloop.c b/clientloop.c index 97032e6a8..18a85c56c 100644 --- a/clientloop.c +++ b/clientloop.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: clientloop.c,v 1.231 2011/01/16 12:05:59 djm Exp $ */ | 1 | /* $OpenBSD: clientloop.c,v 1.236 2011/06/22 22:08:42 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 |
@@ -134,9 +134,6 @@ extern int muxserver_sock; /* XXX use mux_client_cleanup() instead */ | |||
134 | */ | 134 | */ |
135 | extern char *host; | 135 | extern char *host; |
136 | 136 | ||
137 | /* Force TTY allocation */ | ||
138 | extern int force_tty_flag; | ||
139 | |||
140 | /* | 137 | /* |
141 | * Flag to indicate that we have received a window change signal which has | 138 | * Flag to indicate that we have received a window change signal which has |
142 | * not yet been processed. This will cause a message indicating the new | 139 | * not yet been processed. This will cause a message indicating the new |
@@ -183,7 +180,8 @@ struct escape_filter_ctx { | |||
183 | /* Context for channel confirmation replies */ | 180 | /* Context for channel confirmation replies */ |
184 | struct channel_reply_ctx { | 181 | struct channel_reply_ctx { |
185 | const char *request_type; | 182 | const char *request_type; |
186 | int id, do_close; | 183 | int id; |
184 | enum confirm_action action; | ||
187 | }; | 185 | }; |
188 | 186 | ||
189 | /* Global request success/failure callbacks */ | 187 | /* Global request success/failure callbacks */ |
@@ -269,10 +267,10 @@ static void | |||
269 | set_control_persist_exit_time(void) | 267 | set_control_persist_exit_time(void) |
270 | { | 268 | { |
271 | if (muxserver_sock == -1 || !options.control_persist | 269 | if (muxserver_sock == -1 || !options.control_persist |
272 | || options.control_persist_timeout == 0) | 270 | || options.control_persist_timeout == 0) { |
273 | /* not using a ControlPersist timeout */ | 271 | /* not using a ControlPersist timeout */ |
274 | control_persist_exit_time = 0; | 272 | control_persist_exit_time = 0; |
275 | else if (channel_still_open()) { | 273 | } else if (channel_still_open()) { |
276 | /* some client connections are still open */ | 274 | /* some client connections are still open */ |
277 | if (control_persist_exit_time > 0) | 275 | if (control_persist_exit_time > 0) |
278 | debug2("%s: cancel scheduled exit", __func__); | 276 | debug2("%s: cancel scheduled exit", __func__); |
@@ -671,7 +669,7 @@ client_suspend_self(Buffer *bin, Buffer *bout, Buffer *berr) | |||
671 | atomicio(vwrite, fileno(stderr), buffer_ptr(berr), | 669 | atomicio(vwrite, fileno(stderr), buffer_ptr(berr), |
672 | buffer_len(berr)); | 670 | buffer_len(berr)); |
673 | 671 | ||
674 | leave_raw_mode(force_tty_flag); | 672 | leave_raw_mode(options.request_tty == REQUEST_TTY_FORCE); |
675 | 673 | ||
676 | /* | 674 | /* |
677 | * Free (and clear) the buffer to reduce the amount of data that gets | 675 | * Free (and clear) the buffer to reduce the amount of data that gets |
@@ -692,7 +690,7 @@ client_suspend_self(Buffer *bin, Buffer *bout, Buffer *berr) | |||
692 | buffer_init(bout); | 690 | buffer_init(bout); |
693 | buffer_init(berr); | 691 | buffer_init(berr); |
694 | 692 | ||
695 | enter_raw_mode(force_tty_flag); | 693 | enter_raw_mode(options.request_tty == REQUEST_TTY_FORCE); |
696 | } | 694 | } |
697 | 695 | ||
698 | static void | 696 | static void |
@@ -751,6 +749,15 @@ client_status_confirm(int type, Channel *c, void *ctx) | |||
751 | char errmsg[256]; | 749 | char errmsg[256]; |
752 | int tochan; | 750 | int tochan; |
753 | 751 | ||
752 | /* | ||
753 | * If a TTY was explicitly requested, then a failure to allocate | ||
754 | * one is fatal. | ||
755 | */ | ||
756 | if (cr->action == CONFIRM_TTY && | ||
757 | (options.request_tty == REQUEST_TTY_FORCE || | ||
758 | options.request_tty == REQUEST_TTY_YES)) | ||
759 | cr->action = CONFIRM_CLOSE; | ||
760 | |||
754 | /* XXX supress on mux _client_ quietmode */ | 761 | /* XXX supress on mux _client_ quietmode */ |
755 | tochan = options.log_level >= SYSLOG_LEVEL_ERROR && | 762 | tochan = options.log_level >= SYSLOG_LEVEL_ERROR && |
756 | c->ctl_chan != -1 && c->extended_usage == CHAN_EXTENDED_WRITE; | 763 | c->ctl_chan != -1 && c->extended_usage == CHAN_EXTENDED_WRITE; |
@@ -768,14 +775,27 @@ client_status_confirm(int type, Channel *c, void *ctx) | |||
768 | cr->request_type, c->self); | 775 | cr->request_type, c->self); |
769 | } | 776 | } |
770 | /* If error occurred on primary session channel, then exit */ | 777 | /* If error occurred on primary session channel, then exit */ |
771 | if (cr->do_close && c->self == session_ident) | 778 | if (cr->action == CONFIRM_CLOSE && c->self == session_ident) |
772 | fatal("%s", errmsg); | 779 | fatal("%s", errmsg); |
773 | /* If error occurred on mux client, append to their stderr */ | 780 | /* |
774 | if (tochan) | 781 | * If error occurred on mux client, append to |
775 | buffer_append(&c->extended, errmsg, strlen(errmsg)); | 782 | * their stderr. |
776 | else | 783 | */ |
784 | if (tochan) { | ||
785 | buffer_append(&c->extended, errmsg, | ||
786 | strlen(errmsg)); | ||
787 | } else | ||
777 | error("%s", errmsg); | 788 | error("%s", errmsg); |
778 | if (cr->do_close) { | 789 | if (cr->action == CONFIRM_TTY) { |
790 | /* | ||
791 | * If a TTY allocation error occurred, then arrange | ||
792 | * for the correct TTY to leave raw mode. | ||
793 | */ | ||
794 | if (c->self == session_ident) | ||
795 | leave_raw_mode(0); | ||
796 | else | ||
797 | mux_tty_alloc_failed(c); | ||
798 | } else if (cr->action == CONFIRM_CLOSE) { | ||
779 | chan_read_failed(c); | 799 | chan_read_failed(c); |
780 | chan_write_failed(c); | 800 | chan_write_failed(c); |
781 | } | 801 | } |
@@ -789,13 +809,14 @@ client_abandon_status_confirm(Channel *c, void *ctx) | |||
789 | xfree(ctx); | 809 | xfree(ctx); |
790 | } | 810 | } |
791 | 811 | ||
792 | static void | 812 | void |
793 | client_expect_confirm(int id, const char *request, int do_close) | 813 | client_expect_confirm(int id, const char *request, |
814 | enum confirm_action action) | ||
794 | { | 815 | { |
795 | struct channel_reply_ctx *cr = xmalloc(sizeof(*cr)); | 816 | struct channel_reply_ctx *cr = xmalloc(sizeof(*cr)); |
796 | 817 | ||
797 | cr->request_type = request; | 818 | cr->request_type = request; |
798 | cr->do_close = do_close; | 819 | cr->action = action; |
799 | 820 | ||
800 | channel_register_status_confirm(id, client_status_confirm, | 821 | channel_register_status_confirm(id, client_status_confirm, |
801 | client_abandon_status_confirm, cr); | 822 | client_abandon_status_confirm, cr); |
@@ -835,7 +856,7 @@ process_cmdline(void) | |||
835 | bzero(&fwd, sizeof(fwd)); | 856 | bzero(&fwd, sizeof(fwd)); |
836 | fwd.listen_host = fwd.connect_host = NULL; | 857 | fwd.listen_host = fwd.connect_host = NULL; |
837 | 858 | ||
838 | leave_raw_mode(force_tty_flag); | 859 | leave_raw_mode(options.request_tty == REQUEST_TTY_FORCE); |
839 | handler = signal(SIGINT, SIG_IGN); | 860 | handler = signal(SIGINT, SIG_IGN); |
840 | cmd = s = read_passphrase("\r\nssh> ", RP_ECHO); | 861 | cmd = s = read_passphrase("\r\nssh> ", RP_ECHO); |
841 | if (s == NULL) | 862 | if (s == NULL) |
@@ -939,7 +960,7 @@ process_cmdline(void) | |||
939 | 960 | ||
940 | out: | 961 | out: |
941 | signal(SIGINT, handler); | 962 | signal(SIGINT, handler); |
942 | enter_raw_mode(force_tty_flag); | 963 | enter_raw_mode(options.request_tty == REQUEST_TTY_FORCE); |
943 | if (cmd) | 964 | if (cmd) |
944 | xfree(cmd); | 965 | xfree(cmd); |
945 | if (fwd.listen_host != NULL) | 966 | if (fwd.listen_host != NULL) |
@@ -1058,7 +1079,8 @@ process_escapes(Channel *c, Buffer *bin, Buffer *bout, Buffer *berr, | |||
1058 | * more new connections). | 1079 | * more new connections). |
1059 | */ | 1080 | */ |
1060 | /* Restore tty modes. */ | 1081 | /* Restore tty modes. */ |
1061 | leave_raw_mode(force_tty_flag); | 1082 | leave_raw_mode( |
1083 | options.request_tty == REQUEST_TTY_FORCE); | ||
1062 | 1084 | ||
1063 | /* Stop listening for new connections. */ | 1085 | /* Stop listening for new connections. */ |
1064 | channel_stop_listening(); | 1086 | channel_stop_listening(); |
@@ -1353,7 +1375,7 @@ client_channel_closed(int id, void *arg) | |||
1353 | { | 1375 | { |
1354 | channel_cancel_cleanup(id); | 1376 | channel_cancel_cleanup(id); |
1355 | session_closed = 1; | 1377 | session_closed = 1; |
1356 | leave_raw_mode(force_tty_flag); | 1378 | leave_raw_mode(options.request_tty == REQUEST_TTY_FORCE); |
1357 | } | 1379 | } |
1358 | 1380 | ||
1359 | /* | 1381 | /* |
@@ -1424,18 +1446,21 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id) | |||
1424 | signal(SIGWINCH, window_change_handler); | 1446 | signal(SIGWINCH, window_change_handler); |
1425 | 1447 | ||
1426 | if (have_pty) | 1448 | if (have_pty) |
1427 | enter_raw_mode(force_tty_flag); | 1449 | enter_raw_mode(options.request_tty == REQUEST_TTY_FORCE); |
1428 | 1450 | ||
1429 | if (compat20) { | 1451 | if (compat20) { |
1430 | session_ident = ssh2_chan_id; | 1452 | session_ident = ssh2_chan_id; |
1431 | if (escape_char_arg != SSH_ESCAPECHAR_NONE) | 1453 | if (session_ident != -1) { |
1432 | channel_register_filter(session_ident, | 1454 | if (escape_char_arg != SSH_ESCAPECHAR_NONE) { |
1433 | client_simple_escape_filter, NULL, | 1455 | channel_register_filter(session_ident, |
1434 | client_filter_cleanup, | 1456 | client_simple_escape_filter, NULL, |
1435 | client_new_escape_filter_ctx(escape_char_arg)); | 1457 | client_filter_cleanup, |
1436 | if (session_ident != -1) | 1458 | client_new_escape_filter_ctx( |
1459 | escape_char_arg)); | ||
1460 | } | ||
1437 | channel_register_cleanup(session_ident, | 1461 | channel_register_cleanup(session_ident, |
1438 | client_channel_closed, 0); | 1462 | client_channel_closed, 0); |
1463 | } | ||
1439 | } else { | 1464 | } else { |
1440 | /* Check if we should immediately send eof on stdin. */ | 1465 | /* Check if we should immediately send eof on stdin. */ |
1441 | client_check_initial_eof_on_stdin(); | 1466 | client_check_initial_eof_on_stdin(); |
@@ -1574,7 +1599,7 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id) | |||
1574 | channel_free_all(); | 1599 | channel_free_all(); |
1575 | 1600 | ||
1576 | if (have_pty) | 1601 | if (have_pty) |
1577 | leave_raw_mode(force_tty_flag); | 1602 | leave_raw_mode(options.request_tty == REQUEST_TTY_FORCE); |
1578 | 1603 | ||
1579 | /* restore blocking io */ | 1604 | /* restore blocking io */ |
1580 | if (!isatty(fileno(stdin))) | 1605 | if (!isatty(fileno(stdin))) |
@@ -2002,7 +2027,7 @@ client_session2_setup(int id, int want_tty, int want_subsystem, | |||
2002 | memset(&ws, 0, sizeof(ws)); | 2027 | memset(&ws, 0, sizeof(ws)); |
2003 | 2028 | ||
2004 | channel_request_start(id, "pty-req", 1); | 2029 | channel_request_start(id, "pty-req", 1); |
2005 | client_expect_confirm(id, "PTY allocation", 1); | 2030 | client_expect_confirm(id, "PTY allocation", CONFIRM_TTY); |
2006 | packet_put_cstring(term != NULL ? term : ""); | 2031 | packet_put_cstring(term != NULL ? term : ""); |
2007 | packet_put_int((u_int)ws.ws_col); | 2032 | packet_put_int((u_int)ws.ws_col); |
2008 | packet_put_int((u_int)ws.ws_row); | 2033 | packet_put_int((u_int)ws.ws_row); |
@@ -2061,18 +2086,18 @@ client_session2_setup(int id, int want_tty, int want_subsystem, | |||
2061 | debug("Sending subsystem: %.*s", | 2086 | debug("Sending subsystem: %.*s", |
2062 | len, (u_char*)buffer_ptr(cmd)); | 2087 | len, (u_char*)buffer_ptr(cmd)); |
2063 | channel_request_start(id, "subsystem", 1); | 2088 | channel_request_start(id, "subsystem", 1); |
2064 | client_expect_confirm(id, "subsystem", 1); | 2089 | client_expect_confirm(id, "subsystem", CONFIRM_CLOSE); |
2065 | } else { | 2090 | } else { |
2066 | debug("Sending command: %.*s", | 2091 | debug("Sending command: %.*s", |
2067 | len, (u_char*)buffer_ptr(cmd)); | 2092 | len, (u_char*)buffer_ptr(cmd)); |
2068 | channel_request_start(id, "exec", 1); | 2093 | channel_request_start(id, "exec", 1); |
2069 | client_expect_confirm(id, "exec", 1); | 2094 | client_expect_confirm(id, "exec", CONFIRM_CLOSE); |
2070 | } | 2095 | } |
2071 | packet_put_string(buffer_ptr(cmd), buffer_len(cmd)); | 2096 | packet_put_string(buffer_ptr(cmd), buffer_len(cmd)); |
2072 | packet_send(); | 2097 | packet_send(); |
2073 | } else { | 2098 | } else { |
2074 | channel_request_start(id, "shell", 1); | 2099 | channel_request_start(id, "shell", 1); |
2075 | client_expect_confirm(id, "shell", 1); | 2100 | client_expect_confirm(id, "shell", CONFIRM_CLOSE); |
2076 | packet_send(); | 2101 | packet_send(); |
2077 | } | 2102 | } |
2078 | } | 2103 | } |
@@ -2142,11 +2167,26 @@ client_init_dispatch(void) | |||
2142 | client_init_dispatch_15(); | 2167 | client_init_dispatch_15(); |
2143 | } | 2168 | } |
2144 | 2169 | ||
2170 | void | ||
2171 | client_stop_mux(void) | ||
2172 | { | ||
2173 | if (options.control_path != NULL && muxserver_sock != -1) | ||
2174 | unlink(options.control_path); | ||
2175 | /* | ||
2176 | * If we are in persist mode, signal that we should close when all | ||
2177 | * active channels are closed. | ||
2178 | */ | ||
2179 | if (options.control_persist) { | ||
2180 | session_closed = 1; | ||
2181 | setproctitle("[stopped mux]"); | ||
2182 | } | ||
2183 | } | ||
2184 | |||
2145 | /* client specific fatal cleanup */ | 2185 | /* client specific fatal cleanup */ |
2146 | void | 2186 | void |
2147 | cleanup_exit(int i) | 2187 | cleanup_exit(int i) |
2148 | { | 2188 | { |
2149 | leave_raw_mode(force_tty_flag); | 2189 | leave_raw_mode(options.request_tty == REQUEST_TTY_FORCE); |
2150 | leave_non_blocking(); | 2190 | leave_non_blocking(); |
2151 | if (options.control_path != NULL && muxserver_sock != -1) | 2191 | if (options.control_path != NULL && muxserver_sock != -1) |
2152 | unlink(options.control_path); | 2192 | unlink(options.control_path); |