diff options
Diffstat (limited to 'clientloop.c')
-rw-r--r-- | clientloop.c | 145 |
1 files changed, 100 insertions, 45 deletions
diff --git a/clientloop.c b/clientloop.c index 5b76b9893..1a16b2525 100644 --- a/clientloop.c +++ b/clientloop.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: clientloop.c,v 1.240 2012/06/20 04:42:58 djm Exp $ */ | 1 | /* $OpenBSD: clientloop.c,v 1.248 2013/01/02 00:32:07 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 |
@@ -977,9 +977,9 @@ process_cmdline(void) | |||
977 | goto out; | 977 | goto out; |
978 | } | 978 | } |
979 | if (local || dynamic) { | 979 | if (local || dynamic) { |
980 | if (channel_setup_local_fwd_listener(fwd.listen_host, | 980 | if (!channel_setup_local_fwd_listener(fwd.listen_host, |
981 | fwd.listen_port, fwd.connect_host, | 981 | fwd.listen_port, fwd.connect_host, |
982 | fwd.connect_port, options.gateway_ports) < 0) { | 982 | fwd.connect_port, options.gateway_ports)) { |
983 | logit("Port forwarding failed."); | 983 | logit("Port forwarding failed."); |
984 | goto out; | 984 | goto out; |
985 | } | 985 | } |
@@ -1005,6 +1005,63 @@ out: | |||
1005 | xfree(fwd.connect_host); | 1005 | xfree(fwd.connect_host); |
1006 | } | 1006 | } |
1007 | 1007 | ||
1008 | /* reasons to suppress output of an escape command in help output */ | ||
1009 | #define SUPPRESS_NEVER 0 /* never suppress, always show */ | ||
1010 | #define SUPPRESS_PROTO1 1 /* don't show in protocol 1 sessions */ | ||
1011 | #define SUPPRESS_MUXCLIENT 2 /* don't show in mux client sessions */ | ||
1012 | #define SUPPRESS_MUXMASTER 4 /* don't show in mux master sessions */ | ||
1013 | #define SUPPRESS_SYSLOG 8 /* don't show when logging to syslog */ | ||
1014 | struct escape_help_text { | ||
1015 | const char *cmd; | ||
1016 | const char *text; | ||
1017 | unsigned int flags; | ||
1018 | }; | ||
1019 | static struct escape_help_text esc_txt[] = { | ||
1020 | {".", "terminate session", SUPPRESS_MUXMASTER}, | ||
1021 | {".", "terminate connection (and any multiplexed sessions)", | ||
1022 | SUPPRESS_MUXCLIENT}, | ||
1023 | {"B", "send a BREAK to the remote system", SUPPRESS_PROTO1}, | ||
1024 | {"C", "open a command line", SUPPRESS_MUXCLIENT}, | ||
1025 | {"R", "request rekey", SUPPRESS_PROTO1}, | ||
1026 | {"V/v", "decrease/increase verbosity (LogLevel)", SUPPRESS_MUXCLIENT}, | ||
1027 | {"^Z", "suspend ssh", SUPPRESS_MUXCLIENT}, | ||
1028 | {"#", "list forwarded connections", SUPPRESS_NEVER}, | ||
1029 | {"&", "background ssh (when waiting for connections to terminate)", | ||
1030 | SUPPRESS_MUXCLIENT}, | ||
1031 | {"?", "this message", SUPPRESS_NEVER}, | ||
1032 | }; | ||
1033 | |||
1034 | static void | ||
1035 | print_escape_help(Buffer *b, int escape_char, int protocol2, int mux_client, | ||
1036 | int using_stderr) | ||
1037 | { | ||
1038 | unsigned int i, suppress_flags; | ||
1039 | char string[1024]; | ||
1040 | |||
1041 | snprintf(string, sizeof string, "%c?\r\n" | ||
1042 | "Supported escape sequences:\r\n", escape_char); | ||
1043 | buffer_append(b, string, strlen(string)); | ||
1044 | |||
1045 | suppress_flags = (protocol2 ? 0 : SUPPRESS_PROTO1) | | ||
1046 | (mux_client ? SUPPRESS_MUXCLIENT : 0) | | ||
1047 | (mux_client ? 0 : SUPPRESS_MUXMASTER) | | ||
1048 | (using_stderr ? 0 : SUPPRESS_SYSLOG); | ||
1049 | |||
1050 | for (i = 0; i < sizeof(esc_txt)/sizeof(esc_txt[0]); i++) { | ||
1051 | if (esc_txt[i].flags & suppress_flags) | ||
1052 | continue; | ||
1053 | snprintf(string, sizeof string, " %c%-3s - %s\r\n", | ||
1054 | escape_char, esc_txt[i].cmd, esc_txt[i].text); | ||
1055 | buffer_append(b, string, strlen(string)); | ||
1056 | } | ||
1057 | |||
1058 | snprintf(string, sizeof string, | ||
1059 | " %c%c - send the escape character by typing it twice\r\n" | ||
1060 | "(Note that escapes are only recognized immediately after " | ||
1061 | "newline.)\r\n", escape_char, escape_char); | ||
1062 | buffer_append(b, string, strlen(string)); | ||
1063 | } | ||
1064 | |||
1008 | /* | 1065 | /* |
1009 | * Process the characters one by one, call with c==NULL for proto1 case. | 1066 | * Process the characters one by one, call with c==NULL for proto1 case. |
1010 | */ | 1067 | */ |
@@ -1055,6 +1112,8 @@ process_escapes(Channel *c, Buffer *bin, Buffer *bout, Buffer *berr, | |||
1055 | if (c && c->ctl_chan != -1) { | 1112 | if (c && c->ctl_chan != -1) { |
1056 | chan_read_failed(c); | 1113 | chan_read_failed(c); |
1057 | chan_write_failed(c); | 1114 | chan_write_failed(c); |
1115 | mux_master_session_cleanup_cb(c->self, | ||
1116 | NULL); | ||
1058 | return 0; | 1117 | return 0; |
1059 | } else | 1118 | } else |
1060 | quit_pending = 1; | 1119 | quit_pending = 1; |
@@ -1063,11 +1122,16 @@ process_escapes(Channel *c, Buffer *bin, Buffer *bout, Buffer *berr, | |||
1063 | case 'Z' - 64: | 1122 | case 'Z' - 64: |
1064 | /* XXX support this for mux clients */ | 1123 | /* XXX support this for mux clients */ |
1065 | if (c && c->ctl_chan != -1) { | 1124 | if (c && c->ctl_chan != -1) { |
1125 | char b[16]; | ||
1066 | noescape: | 1126 | noescape: |
1127 | if (ch == 'Z' - 64) | ||
1128 | snprintf(b, sizeof b, "^Z"); | ||
1129 | else | ||
1130 | snprintf(b, sizeof b, "%c", ch); | ||
1067 | snprintf(string, sizeof string, | 1131 | snprintf(string, sizeof string, |
1068 | "%c%c escape not available to " | 1132 | "%c%s escape not available to " |
1069 | "multiplexed sessions\r\n", | 1133 | "multiplexed sessions\r\n", |
1070 | escape_char, ch); | 1134 | escape_char, b); |
1071 | buffer_append(berr, string, | 1135 | buffer_append(berr, string, |
1072 | strlen(string)); | 1136 | strlen(string)); |
1073 | continue; | 1137 | continue; |
@@ -1106,6 +1170,31 @@ process_escapes(Channel *c, Buffer *bin, Buffer *bout, Buffer *berr, | |||
1106 | } | 1170 | } |
1107 | continue; | 1171 | continue; |
1108 | 1172 | ||
1173 | case 'V': | ||
1174 | /* FALLTHROUGH */ | ||
1175 | case 'v': | ||
1176 | if (c && c->ctl_chan != -1) | ||
1177 | goto noescape; | ||
1178 | if (!log_is_on_stderr()) { | ||
1179 | snprintf(string, sizeof string, | ||
1180 | "%c%c [Logging to syslog]\r\n", | ||
1181 | escape_char, ch); | ||
1182 | buffer_append(berr, string, | ||
1183 | strlen(string)); | ||
1184 | continue; | ||
1185 | } | ||
1186 | if (ch == 'V' && options.log_level > | ||
1187 | SYSLOG_LEVEL_QUIET) | ||
1188 | log_change_level(--options.log_level); | ||
1189 | if (ch == 'v' && options.log_level < | ||
1190 | SYSLOG_LEVEL_DEBUG3) | ||
1191 | log_change_level(++options.log_level); | ||
1192 | snprintf(string, sizeof string, | ||
1193 | "%c%c [LogLevel %s]\r\n", escape_char, ch, | ||
1194 | log_level_name(options.log_level)); | ||
1195 | buffer_append(berr, string, strlen(string)); | ||
1196 | continue; | ||
1197 | |||
1109 | case '&': | 1198 | case '&': |
1110 | if (c && c->ctl_chan != -1) | 1199 | if (c && c->ctl_chan != -1) |
1111 | goto noescape; | 1200 | goto noescape; |
@@ -1159,43 +1248,9 @@ process_escapes(Channel *c, Buffer *bin, Buffer *bout, Buffer *berr, | |||
1159 | continue; | 1248 | continue; |
1160 | 1249 | ||
1161 | case '?': | 1250 | case '?': |
1162 | if (c && c->ctl_chan != -1) { | 1251 | print_escape_help(berr, escape_char, compat20, |
1163 | snprintf(string, sizeof string, | 1252 | (c && c->ctl_chan != -1), |
1164 | "%c?\r\n\ | 1253 | log_is_on_stderr()); |
1165 | Supported escape sequences:\r\n\ | ||
1166 | %c. - terminate session\r\n\ | ||
1167 | %cB - send a BREAK to the remote system\r\n\ | ||
1168 | %cR - Request rekey (SSH protocol 2 only)\r\n\ | ||
1169 | %c# - list forwarded connections\r\n\ | ||
1170 | %c? - this message\r\n\ | ||
1171 | %c%c - send the escape character by typing it twice\r\n\ | ||
1172 | (Note that escapes are only recognized immediately after newline.)\r\n", | ||
1173 | escape_char, escape_char, | ||
1174 | escape_char, escape_char, | ||
1175 | escape_char, escape_char, | ||
1176 | escape_char, escape_char); | ||
1177 | } else { | ||
1178 | snprintf(string, sizeof string, | ||
1179 | "%c?\r\n\ | ||
1180 | Supported escape sequences:\r\n\ | ||
1181 | %c. - terminate connection (and any multiplexed sessions)\r\n\ | ||
1182 | %cB - send a BREAK to the remote system\r\n\ | ||
1183 | %cC - open a command line\r\n\ | ||
1184 | %cR - Request rekey (SSH protocol 2 only)\r\n\ | ||
1185 | %c^Z - suspend ssh\r\n\ | ||
1186 | %c# - list forwarded connections\r\n\ | ||
1187 | %c& - background ssh (when waiting for connections to terminate)\r\n\ | ||
1188 | %c? - this message\r\n\ | ||
1189 | %c%c - send the escape character by typing it twice\r\n\ | ||
1190 | (Note that escapes are only recognized immediately after newline.)\r\n", | ||
1191 | escape_char, escape_char, | ||
1192 | escape_char, escape_char, | ||
1193 | escape_char, escape_char, | ||
1194 | escape_char, escape_char, | ||
1195 | escape_char, escape_char, | ||
1196 | escape_char); | ||
1197 | } | ||
1198 | buffer_append(berr, string, strlen(string)); | ||
1199 | continue; | 1254 | continue; |
1200 | 1255 | ||
1201 | case '#': | 1256 | case '#': |
@@ -2209,10 +2264,10 @@ client_stop_mux(void) | |||
2209 | if (options.control_path != NULL && muxserver_sock != -1) | 2264 | if (options.control_path != NULL && muxserver_sock != -1) |
2210 | unlink(options.control_path); | 2265 | unlink(options.control_path); |
2211 | /* | 2266 | /* |
2212 | * If we are in persist mode, signal that we should close when all | 2267 | * If we are in persist mode, or don't have a shell, signal that we |
2213 | * active channels are closed. | 2268 | * should close when all active channels are closed. |
2214 | */ | 2269 | */ |
2215 | if (options.control_persist) { | 2270 | if (options.control_persist || no_shell_flag) { |
2216 | session_closed = 1; | 2271 | session_closed = 1; |
2217 | setproctitle("[stopped mux]"); | 2272 | setproctitle("[stopped mux]"); |
2218 | } | 2273 | } |