diff options
Diffstat (limited to 'ssh.c')
-rw-r--r-- | ssh.c | 98 |
1 files changed, 57 insertions, 41 deletions
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: ssh.c,v 1.364 2011/08/02 23:15:03 djm Exp $ */ | 1 | /* $OpenBSD: ssh.c,v 1.368 2011/10/24 02:10:46 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 |
@@ -377,6 +377,8 @@ main(int ac, char **av) | |||
377 | muxclient_command = SSHMUX_COMMAND_TERMINATE; | 377 | muxclient_command = SSHMUX_COMMAND_TERMINATE; |
378 | else if (strcmp(optarg, "stop") == 0) | 378 | else if (strcmp(optarg, "stop") == 0) |
379 | muxclient_command = SSHMUX_COMMAND_STOP; | 379 | muxclient_command = SSHMUX_COMMAND_STOP; |
380 | else if (strcmp(optarg, "cancel") == 0) | ||
381 | muxclient_command = SSHMUX_COMMAND_CANCEL_FWD; | ||
380 | else | 382 | else |
381 | fatal("Invalid multiplex command."); | 383 | fatal("Invalid multiplex command."); |
382 | break; | 384 | break; |
@@ -884,17 +886,20 @@ main(int ac, char **av) | |||
884 | * Now that we are back to our own permissions, create ~/.ssh | 886 | * Now that we are back to our own permissions, create ~/.ssh |
885 | * directory if it doesn't already exist. | 887 | * directory if it doesn't already exist. |
886 | */ | 888 | */ |
887 | r = snprintf(buf, sizeof buf, "%s%s%s", pw->pw_dir, | 889 | if (config == NULL) { |
888 | strcmp(pw->pw_dir, "/") ? "/" : "", _PATH_SSH_USER_DIR); | 890 | r = snprintf(buf, sizeof buf, "%s%s%s", pw->pw_dir, |
889 | if (r > 0 && (size_t)r < sizeof(buf) && stat(buf, &st) < 0) { | 891 | strcmp(pw->pw_dir, "/") ? "/" : "", _PATH_SSH_USER_DIR); |
892 | if (r > 0 && (size_t)r < sizeof(buf) && stat(buf, &st) < 0) { | ||
890 | #ifdef WITH_SELINUX | 893 | #ifdef WITH_SELINUX |
891 | ssh_selinux_setfscreatecon(buf); | 894 | ssh_selinux_setfscreatecon(buf); |
892 | #endif | 895 | #endif |
893 | if (mkdir(buf, 0700) < 0) | 896 | if (mkdir(buf, 0700) < 0) |
894 | error("Could not create directory '%.200s'.", buf); | 897 | error("Could not create directory '%.200s'.", |
898 | buf); | ||
895 | #ifdef WITH_SELINUX | 899 | #ifdef WITH_SELINUX |
896 | ssh_selinux_setfscreatecon(NULL); | 900 | ssh_selinux_setfscreatecon(NULL); |
897 | #endif | 901 | #endif |
902 | } | ||
898 | } | 903 | } |
899 | /* load options.identity_files */ | 904 | /* load options.identity_files */ |
900 | load_public_identity_files(); | 905 | load_public_identity_files(); |
@@ -1019,11 +1024,17 @@ ssh_confirm_remote_forward(int type, u_int32_t seq, void *ctxt) | |||
1019 | debug("remote forward %s for: listen %d, connect %s:%d", | 1024 | debug("remote forward %s for: listen %d, connect %s:%d", |
1020 | type == SSH2_MSG_REQUEST_SUCCESS ? "success" : "failure", | 1025 | type == SSH2_MSG_REQUEST_SUCCESS ? "success" : "failure", |
1021 | rfwd->listen_port, rfwd->connect_host, rfwd->connect_port); | 1026 | rfwd->listen_port, rfwd->connect_host, rfwd->connect_port); |
1022 | if (type == SSH2_MSG_REQUEST_SUCCESS && rfwd->listen_port == 0) { | 1027 | if (rfwd->listen_port == 0) { |
1023 | rfwd->allocated_port = packet_get_int(); | 1028 | if (type == SSH2_MSG_REQUEST_SUCCESS) { |
1024 | logit("Allocated port %u for remote forward to %s:%d", | 1029 | rfwd->allocated_port = packet_get_int(); |
1025 | rfwd->allocated_port, | 1030 | logit("Allocated port %u for remote forward to %s:%d", |
1026 | rfwd->connect_host, rfwd->connect_port); | 1031 | rfwd->allocated_port, |
1032 | rfwd->connect_host, rfwd->connect_port); | ||
1033 | channel_update_permitted_opens(rfwd->handle, | ||
1034 | rfwd->allocated_port); | ||
1035 | } else { | ||
1036 | channel_update_permitted_opens(rfwd->handle, -1); | ||
1037 | } | ||
1027 | } | 1038 | } |
1028 | 1039 | ||
1029 | if (type == SSH2_MSG_REQUEST_FAILURE) { | 1040 | if (type == SSH2_MSG_REQUEST_FAILURE) { |
@@ -1048,25 +1059,26 @@ client_cleanup_stdio_fwd(int id, void *arg) | |||
1048 | cleanup_exit(0); | 1059 | cleanup_exit(0); |
1049 | } | 1060 | } |
1050 | 1061 | ||
1051 | static int | 1062 | static void |
1052 | client_setup_stdio_fwd(const char *host_to_connect, u_short port_to_connect) | 1063 | ssh_init_stdio_forwarding(void) |
1053 | { | 1064 | { |
1054 | Channel *c; | 1065 | Channel *c; |
1055 | int in, out; | 1066 | int in, out; |
1056 | 1067 | ||
1057 | debug3("client_setup_stdio_fwd %s:%d", host_to_connect, | 1068 | if (stdio_forward_host == NULL) |
1058 | port_to_connect); | 1069 | return; |
1070 | if (!compat20) | ||
1071 | fatal("stdio forwarding require Protocol 2"); | ||
1059 | 1072 | ||
1060 | in = dup(STDIN_FILENO); | 1073 | debug3("%s: %s:%d", __func__, stdio_forward_host, stdio_forward_port); |
1061 | out = dup(STDOUT_FILENO); | ||
1062 | if (in < 0 || out < 0) | ||
1063 | fatal("channel_connect_stdio_fwd: dup() in/out failed"); | ||
1064 | 1074 | ||
1065 | if ((c = channel_connect_stdio_fwd(host_to_connect, port_to_connect, | 1075 | if ((in = dup(STDIN_FILENO)) < 0 || |
1066 | in, out)) == NULL) | 1076 | (out = dup(STDOUT_FILENO)) < 0) |
1067 | return 0; | 1077 | fatal("channel_connect_stdio_fwd: dup() in/out failed"); |
1078 | if ((c = channel_connect_stdio_fwd(stdio_forward_host, | ||
1079 | stdio_forward_port, in, out)) == NULL) | ||
1080 | fatal("%s: channel_connect_stdio_fwd failed", __func__); | ||
1068 | channel_register_cleanup(c->self, client_cleanup_stdio_fwd, 0); | 1081 | channel_register_cleanup(c->self, client_cleanup_stdio_fwd, 0); |
1069 | return 1; | ||
1070 | } | 1082 | } |
1071 | 1083 | ||
1072 | static void | 1084 | static void |
@@ -1075,15 +1087,6 @@ ssh_init_forwarding(void) | |||
1075 | int success = 0; | 1087 | int success = 0; |
1076 | int i; | 1088 | int i; |
1077 | 1089 | ||
1078 | if (stdio_forward_host != NULL) { | ||
1079 | if (!compat20) { | ||
1080 | fatal("stdio forwarding require Protocol 2"); | ||
1081 | } | ||
1082 | if (!client_setup_stdio_fwd(stdio_forward_host, | ||
1083 | stdio_forward_port)) | ||
1084 | fatal("Failed to connect in stdio forward mode."); | ||
1085 | } | ||
1086 | |||
1087 | /* Initiate local TCP/IP port forwardings. */ | 1090 | /* Initiate local TCP/IP port forwardings. */ |
1088 | for (i = 0; i < options.num_local_forwards; i++) { | 1091 | for (i = 0; i < options.num_local_forwards; i++) { |
1089 | debug("Local connections to %.200s:%d forwarded to remote " | 1092 | debug("Local connections to %.200s:%d forwarded to remote " |
@@ -1115,19 +1118,22 @@ ssh_init_forwarding(void) | |||
1115 | options.remote_forwards[i].listen_port, | 1118 | options.remote_forwards[i].listen_port, |
1116 | options.remote_forwards[i].connect_host, | 1119 | options.remote_forwards[i].connect_host, |
1117 | options.remote_forwards[i].connect_port); | 1120 | options.remote_forwards[i].connect_port); |
1118 | if (channel_request_remote_forwarding( | 1121 | options.remote_forwards[i].handle = |
1122 | channel_request_remote_forwarding( | ||
1119 | options.remote_forwards[i].listen_host, | 1123 | options.remote_forwards[i].listen_host, |
1120 | options.remote_forwards[i].listen_port, | 1124 | options.remote_forwards[i].listen_port, |
1121 | options.remote_forwards[i].connect_host, | 1125 | options.remote_forwards[i].connect_host, |
1122 | options.remote_forwards[i].connect_port) < 0) { | 1126 | options.remote_forwards[i].connect_port); |
1127 | if (options.remote_forwards[i].handle < 0) { | ||
1123 | if (options.exit_on_forward_failure) | 1128 | if (options.exit_on_forward_failure) |
1124 | fatal("Could not request remote forwarding."); | 1129 | fatal("Could not request remote forwarding."); |
1125 | else | 1130 | else |
1126 | logit("Warning: Could not request remote " | 1131 | logit("Warning: Could not request remote " |
1127 | "forwarding."); | 1132 | "forwarding."); |
1133 | } else { | ||
1134 | client_register_global_confirm(ssh_confirm_remote_forward, | ||
1135 | &options.remote_forwards[i]); | ||
1128 | } | 1136 | } |
1129 | client_register_global_confirm(ssh_confirm_remote_forward, | ||
1130 | &options.remote_forwards[i]); | ||
1131 | } | 1137 | } |
1132 | 1138 | ||
1133 | /* Initiate tunnel forwarding. */ | 1139 | /* Initiate tunnel forwarding. */ |
@@ -1271,6 +1277,7 @@ ssh_session(void) | |||
1271 | } | 1277 | } |
1272 | 1278 | ||
1273 | /* Initiate port forwardings. */ | 1279 | /* Initiate port forwardings. */ |
1280 | ssh_init_stdio_forwarding(); | ||
1274 | ssh_init_forwarding(); | 1281 | ssh_init_forwarding(); |
1275 | 1282 | ||
1276 | /* Execute a local command */ | 1283 | /* Execute a local command */ |
@@ -1409,15 +1416,18 @@ ssh_session2(void) | |||
1409 | int id = -1; | 1416 | int id = -1; |
1410 | 1417 | ||
1411 | /* XXX should be pre-session */ | 1418 | /* XXX should be pre-session */ |
1419 | if (!options.control_persist) | ||
1420 | ssh_init_stdio_forwarding(); | ||
1412 | ssh_init_forwarding(); | 1421 | ssh_init_forwarding(); |
1413 | 1422 | ||
1414 | /* Start listening for multiplex clients */ | 1423 | /* Start listening for multiplex clients */ |
1415 | muxserver_listen(); | 1424 | muxserver_listen(); |
1416 | 1425 | ||
1417 | /* | 1426 | /* |
1418 | * If we are in control persist mode, then prepare to background | 1427 | * If we are in control persist mode and have a working mux listen |
1419 | * ourselves and have a foreground client attach as a control | 1428 | * socket, then prepare to background ourselves and have a foreground |
1420 | * slave. NB. we must save copies of the flags that we override for | 1429 | * client attach as a control slave. |
1430 | * NB. we must save copies of the flags that we override for | ||
1421 | * the backgrounding, since we defer attachment of the slave until | 1431 | * the backgrounding, since we defer attachment of the slave until |
1422 | * after the connection is fully established (in particular, | 1432 | * after the connection is fully established (in particular, |
1423 | * async rfwd replies have been received for ExitOnForwardFailure). | 1433 | * async rfwd replies have been received for ExitOnForwardFailure). |
@@ -1434,6 +1444,12 @@ ssh_session2(void) | |||
1434 | need_controlpersist_detach = 1; | 1444 | need_controlpersist_detach = 1; |
1435 | fork_after_authentication_flag = 1; | 1445 | fork_after_authentication_flag = 1; |
1436 | } | 1446 | } |
1447 | /* | ||
1448 | * ControlPersist mux listen socket setup failed, attempt the | ||
1449 | * stdio forward setup that we skipped earlier. | ||
1450 | */ | ||
1451 | if (options.control_persist && muxserver_sock == -1) | ||
1452 | ssh_init_stdio_forwarding(); | ||
1437 | 1453 | ||
1438 | if (!no_shell_flag || (datafellows & SSH_BUG_DUMMYCHAN)) | 1454 | if (!no_shell_flag || (datafellows & SSH_BUG_DUMMYCHAN)) |
1439 | id = ssh_session2_open(); | 1455 | id = ssh_session2_open(); |