diff options
Diffstat (limited to 'ssh.c')
-rw-r--r-- | ssh.c | 143 |
1 files changed, 107 insertions, 36 deletions
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: ssh.c,v 1.401 2014/02/26 20:18:37 djm Exp $ */ | 1 | /* $OpenBSD: ssh.c,v 1.407 2014/07/17 07:22:19 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 |
@@ -71,8 +71,10 @@ | |||
71 | #include <netinet/in.h> | 71 | #include <netinet/in.h> |
72 | #include <arpa/inet.h> | 72 | #include <arpa/inet.h> |
73 | 73 | ||
74 | #ifdef WITH_OPENSSL | ||
74 | #include <openssl/evp.h> | 75 | #include <openssl/evp.h> |
75 | #include <openssl/err.h> | 76 | #include <openssl/err.h> |
77 | #endif | ||
76 | #include "openbsd-compat/openssl-compat.h" | 78 | #include "openbsd-compat/openssl-compat.h" |
77 | #include "openbsd-compat/sys-queue.h" | 79 | #include "openbsd-compat/sys-queue.h" |
78 | 80 | ||
@@ -83,6 +85,7 @@ | |||
83 | #include "canohost.h" | 85 | #include "canohost.h" |
84 | #include "compat.h" | 86 | #include "compat.h" |
85 | #include "cipher.h" | 87 | #include "cipher.h" |
88 | #include "digest.h" | ||
86 | #include "packet.h" | 89 | #include "packet.h" |
87 | #include "buffer.h" | 90 | #include "buffer.h" |
88 | #include "channels.h" | 91 | #include "channels.h" |
@@ -93,9 +96,9 @@ | |||
93 | #include "dispatch.h" | 96 | #include "dispatch.h" |
94 | #include "clientloop.h" | 97 | #include "clientloop.h" |
95 | #include "log.h" | 98 | #include "log.h" |
99 | #include "misc.h" | ||
96 | #include "readconf.h" | 100 | #include "readconf.h" |
97 | #include "sshconnect.h" | 101 | #include "sshconnect.h" |
98 | #include "misc.h" | ||
99 | #include "kex.h" | 102 | #include "kex.h" |
100 | #include "mac.h" | 103 | #include "mac.h" |
101 | #include "sshpty.h" | 104 | #include "sshpty.h" |
@@ -420,8 +423,11 @@ main(int ac, char **av) | |||
420 | int timeout_ms; | 423 | int timeout_ms; |
421 | extern int optind, optreset; | 424 | extern int optind, optreset; |
422 | extern char *optarg; | 425 | extern char *optarg; |
423 | Forward fwd; | 426 | struct Forward fwd; |
424 | struct addrinfo *addrs = NULL; | 427 | struct addrinfo *addrs = NULL; |
428 | struct ssh_digest_ctx *md; | ||
429 | u_char conn_hash[SSH_DIGEST_MAX_LENGTH]; | ||
430 | char *conn_hash_hex; | ||
425 | 431 | ||
426 | /* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */ | 432 | /* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */ |
427 | sanitise_stdfd(); | 433 | sanitise_stdfd(); |
@@ -539,7 +545,7 @@ main(int ac, char **av) | |||
539 | options.forward_x11_trusted = 1; | 545 | options.forward_x11_trusted = 1; |
540 | break; | 546 | break; |
541 | case 'g': | 547 | case 'g': |
542 | options.gateway_ports = 1; | 548 | options.fwd_opts.gateway_ports = 1; |
543 | break; | 549 | break; |
544 | case 'O': | 550 | case 'O': |
545 | if (stdio_forward_host != NULL) | 551 | if (stdio_forward_host != NULL) |
@@ -631,7 +637,13 @@ main(int ac, char **av) | |||
631 | break; | 637 | break; |
632 | case 'V': | 638 | case 'V': |
633 | fprintf(stderr, "%s, %s\n", | 639 | fprintf(stderr, "%s, %s\n", |
634 | SSH_RELEASE, SSLeay_version(SSLEAY_VERSION)); | 640 | SSH_RELEASE, |
641 | #ifdef WITH_OPENSSL | ||
642 | SSLeay_version(SSLEAY_VERSION) | ||
643 | #else | ||
644 | "without OpenSSL" | ||
645 | #endif | ||
646 | ); | ||
635 | if (opt == 'V') | 647 | if (opt == 'V') |
636 | exit(0); | 648 | exit(0); |
637 | break; | 649 | break; |
@@ -828,8 +840,10 @@ main(int ac, char **av) | |||
828 | 840 | ||
829 | host_arg = xstrdup(host); | 841 | host_arg = xstrdup(host); |
830 | 842 | ||
843 | #ifdef WITH_OPENSSL | ||
831 | OpenSSL_add_all_algorithms(); | 844 | OpenSSL_add_all_algorithms(); |
832 | ERR_load_crypto_strings(); | 845 | ERR_load_crypto_strings(); |
846 | #endif | ||
833 | 847 | ||
834 | /* Initialize the command to execute on remote host. */ | 848 | /* Initialize the command to execute on remote host. */ |
835 | buffer_init(&command); | 849 | buffer_init(&command); |
@@ -876,7 +890,13 @@ main(int ac, char **av) | |||
876 | SYSLOG_FACILITY_USER, !use_syslog); | 890 | SYSLOG_FACILITY_USER, !use_syslog); |
877 | 891 | ||
878 | if (debug_flag) | 892 | if (debug_flag) |
879 | logit("%s, %s", SSH_VERSION, SSLeay_version(SSLEAY_VERSION)); | 893 | logit("%s, %s", SSH_RELEASE, |
894 | #ifdef WITH_OPENSSL | ||
895 | SSLeay_version(SSLEAY_VERSION) | ||
896 | #else | ||
897 | "without OpenSSL" | ||
898 | #endif | ||
899 | ); | ||
880 | 900 | ||
881 | /* Parse the configuration files */ | 901 | /* Parse the configuration files */ |
882 | process_config_files(pw); | 902 | process_config_files(pw); |
@@ -914,10 +934,14 @@ main(int ac, char **av) | |||
914 | if (addrs == NULL && options.num_permitted_cnames != 0 && | 934 | if (addrs == NULL && options.num_permitted_cnames != 0 && |
915 | (option_clear_or_none(options.proxy_command) || | 935 | (option_clear_or_none(options.proxy_command) || |
916 | options.canonicalize_hostname == SSH_CANONICALISE_ALWAYS)) { | 936 | options.canonicalize_hostname == SSH_CANONICALISE_ALWAYS)) { |
917 | if ((addrs = resolve_host(host, options.port, 1, | 937 | if ((addrs = resolve_host(host, options.port, |
918 | cname, sizeof(cname))) == NULL) | 938 | option_clear_or_none(options.proxy_command), |
919 | cleanup_exit(255); /* resolve_host logs the error */ | 939 | cname, sizeof(cname))) == NULL) { |
920 | check_follow_cname(&host, cname); | 940 | /* Don't fatal proxied host names not in the DNS */ |
941 | if (option_clear_or_none(options.proxy_command)) | ||
942 | cleanup_exit(255); /* logged in resolve_host */ | ||
943 | } else | ||
944 | check_follow_cname(&host, cname); | ||
921 | } | 945 | } |
922 | 946 | ||
923 | /* | 947 | /* |
@@ -982,12 +1006,29 @@ main(int ac, char **av) | |||
982 | shorthost[strcspn(thishost, ".")] = '\0'; | 1006 | shorthost[strcspn(thishost, ".")] = '\0'; |
983 | snprintf(portstr, sizeof(portstr), "%d", options.port); | 1007 | snprintf(portstr, sizeof(portstr), "%d", options.port); |
984 | 1008 | ||
1009 | if ((md = ssh_digest_start(SSH_DIGEST_SHA1)) == NULL || | ||
1010 | ssh_digest_update(md, thishost, strlen(thishost)) < 0 || | ||
1011 | ssh_digest_update(md, host, strlen(host)) < 0 || | ||
1012 | ssh_digest_update(md, portstr, strlen(portstr)) < 0 || | ||
1013 | ssh_digest_update(md, options.user, strlen(options.user)) < 0 || | ||
1014 | ssh_digest_final(md, conn_hash, sizeof(conn_hash)) < 0) | ||
1015 | fatal("%s: mux digest failed", __func__); | ||
1016 | ssh_digest_free(md); | ||
1017 | conn_hash_hex = tohex(conn_hash, ssh_digest_bytes(SSH_DIGEST_SHA1)); | ||
1018 | |||
985 | if (options.local_command != NULL) { | 1019 | if (options.local_command != NULL) { |
986 | debug3("expanding LocalCommand: %s", options.local_command); | 1020 | debug3("expanding LocalCommand: %s", options.local_command); |
987 | cp = options.local_command; | 1021 | cp = options.local_command; |
988 | options.local_command = percent_expand(cp, "d", pw->pw_dir, | 1022 | options.local_command = percent_expand(cp, |
989 | "h", host, "l", thishost, "n", host_arg, "r", options.user, | 1023 | "C", conn_hash_hex, |
990 | "p", portstr, "u", pw->pw_name, "L", shorthost, | 1024 | "L", shorthost, |
1025 | "d", pw->pw_dir, | ||
1026 | "h", host, | ||
1027 | "l", thishost, | ||
1028 | "n", host_arg, | ||
1029 | "p", portstr, | ||
1030 | "r", options.user, | ||
1031 | "u", pw->pw_name, | ||
991 | (char *)NULL); | 1032 | (char *)NULL); |
992 | debug3("expanded LocalCommand: %s", options.local_command); | 1033 | debug3("expanded LocalCommand: %s", options.local_command); |
993 | free(cp); | 1034 | free(cp); |
@@ -997,12 +1038,20 @@ main(int ac, char **av) | |||
997 | cp = tilde_expand_filename(options.control_path, | 1038 | cp = tilde_expand_filename(options.control_path, |
998 | original_real_uid); | 1039 | original_real_uid); |
999 | free(options.control_path); | 1040 | free(options.control_path); |
1000 | options.control_path = percent_expand(cp, "h", host, | 1041 | options.control_path = percent_expand(cp, |
1001 | "l", thishost, "n", host_arg, "r", options.user, | 1042 | "C", conn_hash_hex, |
1002 | "p", portstr, "u", pw->pw_name, "L", shorthost, | 1043 | "L", shorthost, |
1044 | "h", host, | ||
1045 | "l", thishost, | ||
1046 | "n", host_arg, | ||
1047 | "p", portstr, | ||
1048 | "r", options.user, | ||
1049 | "u", pw->pw_name, | ||
1003 | (char *)NULL); | 1050 | (char *)NULL); |
1004 | free(cp); | 1051 | free(cp); |
1005 | } | 1052 | } |
1053 | free(conn_hash_hex); | ||
1054 | |||
1006 | if (muxclient_command != 0 && options.control_path == NULL) | 1055 | if (muxclient_command != 0 && options.control_path == NULL) |
1007 | fatal("No ControlPath specified for \"-O\" command"); | 1056 | fatal("No ControlPath specified for \"-O\" command"); |
1008 | if (options.control_path != NULL) | 1057 | if (options.control_path != NULL) |
@@ -1256,13 +1305,17 @@ fork_postauth(void) | |||
1256 | static void | 1305 | static void |
1257 | ssh_confirm_remote_forward(int type, u_int32_t seq, void *ctxt) | 1306 | ssh_confirm_remote_forward(int type, u_int32_t seq, void *ctxt) |
1258 | { | 1307 | { |
1259 | Forward *rfwd = (Forward *)ctxt; | 1308 | struct Forward *rfwd = (struct Forward *)ctxt; |
1260 | 1309 | ||
1261 | /* XXX verbose() on failure? */ | 1310 | /* XXX verbose() on failure? */ |
1262 | debug("remote forward %s for: listen %d, connect %s:%d", | 1311 | debug("remote forward %s for: listen %s%s%d, connect %s:%d", |
1263 | type == SSH2_MSG_REQUEST_SUCCESS ? "success" : "failure", | 1312 | type == SSH2_MSG_REQUEST_SUCCESS ? "success" : "failure", |
1264 | rfwd->listen_port, rfwd->connect_host, rfwd->connect_port); | 1313 | rfwd->listen_path ? rfwd->listen_path : |
1265 | if (rfwd->listen_port == 0) { | 1314 | rfwd->listen_host ? rfwd->listen_host : "", |
1315 | (rfwd->listen_path || rfwd->listen_host) ? ":" : "", | ||
1316 | rfwd->listen_port, rfwd->connect_path ? rfwd->connect_path : | ||
1317 | rfwd->connect_host, rfwd->connect_port); | ||
1318 | if (rfwd->listen_path == NULL && rfwd->listen_port == 0) { | ||
1266 | if (type == SSH2_MSG_REQUEST_SUCCESS) { | 1319 | if (type == SSH2_MSG_REQUEST_SUCCESS) { |
1267 | rfwd->allocated_port = packet_get_int(); | 1320 | rfwd->allocated_port = packet_get_int(); |
1268 | logit("Allocated port %u for remote forward to %s:%d", | 1321 | logit("Allocated port %u for remote forward to %s:%d", |
@@ -1276,12 +1329,21 @@ ssh_confirm_remote_forward(int type, u_int32_t seq, void *ctxt) | |||
1276 | } | 1329 | } |
1277 | 1330 | ||
1278 | if (type == SSH2_MSG_REQUEST_FAILURE) { | 1331 | if (type == SSH2_MSG_REQUEST_FAILURE) { |
1279 | if (options.exit_on_forward_failure) | 1332 | if (options.exit_on_forward_failure) { |
1280 | fatal("Error: remote port forwarding failed for " | 1333 | if (rfwd->listen_path != NULL) |
1281 | "listen port %d", rfwd->listen_port); | 1334 | fatal("Error: remote port forwarding failed " |
1282 | else | 1335 | "for listen path %s", rfwd->listen_path); |
1283 | logit("Warning: remote port forwarding failed for " | 1336 | else |
1284 | "listen port %d", rfwd->listen_port); | 1337 | fatal("Error: remote port forwarding failed " |
1338 | "for listen port %d", rfwd->listen_port); | ||
1339 | } else { | ||
1340 | if (rfwd->listen_path != NULL) | ||
1341 | logit("Warning: remote port forwarding failed " | ||
1342 | "for listen path %s", rfwd->listen_path); | ||
1343 | else | ||
1344 | logit("Warning: remote port forwarding failed " | ||
1345 | "for listen port %d", rfwd->listen_port); | ||
1346 | } | ||
1285 | } | 1347 | } |
1286 | if (++remote_forward_confirms_received == options.num_remote_forwards) { | 1348 | if (++remote_forward_confirms_received == options.num_remote_forwards) { |
1287 | debug("All remote forwarding requests processed"); | 1349 | debug("All remote forwarding requests processed"); |
@@ -1298,6 +1360,13 @@ client_cleanup_stdio_fwd(int id, void *arg) | |||
1298 | } | 1360 | } |
1299 | 1361 | ||
1300 | static void | 1362 | static void |
1363 | ssh_stdio_confirm(int id, int success, void *arg) | ||
1364 | { | ||
1365 | if (!success) | ||
1366 | fatal("stdio forwarding failed"); | ||
1367 | } | ||
1368 | |||
1369 | static void | ||
1301 | ssh_init_stdio_forwarding(void) | 1370 | ssh_init_stdio_forwarding(void) |
1302 | { | 1371 | { |
1303 | Channel *c; | 1372 | Channel *c; |
@@ -1317,6 +1386,7 @@ ssh_init_stdio_forwarding(void) | |||
1317 | stdio_forward_port, in, out)) == NULL) | 1386 | stdio_forward_port, in, out)) == NULL) |
1318 | fatal("%s: channel_connect_stdio_fwd failed", __func__); | 1387 | fatal("%s: channel_connect_stdio_fwd failed", __func__); |
1319 | channel_register_cleanup(c->self, client_cleanup_stdio_fwd, 0); | 1388 | channel_register_cleanup(c->self, client_cleanup_stdio_fwd, 0); |
1389 | channel_register_open_confirm(c->self, ssh_stdio_confirm, NULL); | ||
1320 | } | 1390 | } |
1321 | 1391 | ||
1322 | static void | 1392 | static void |
@@ -1329,18 +1399,18 @@ ssh_init_forwarding(void) | |||
1329 | for (i = 0; i < options.num_local_forwards; i++) { | 1399 | for (i = 0; i < options.num_local_forwards; i++) { |
1330 | debug("Local connections to %.200s:%d forwarded to remote " | 1400 | debug("Local connections to %.200s:%d forwarded to remote " |
1331 | "address %.200s:%d", | 1401 | "address %.200s:%d", |
1402 | (options.local_forwards[i].listen_path != NULL) ? | ||
1403 | options.local_forwards[i].listen_path : | ||
1332 | (options.local_forwards[i].listen_host == NULL) ? | 1404 | (options.local_forwards[i].listen_host == NULL) ? |
1333 | (options.gateway_ports ? "*" : "LOCALHOST") : | 1405 | (options.fwd_opts.gateway_ports ? "*" : "LOCALHOST") : |
1334 | options.local_forwards[i].listen_host, | 1406 | options.local_forwards[i].listen_host, |
1335 | options.local_forwards[i].listen_port, | 1407 | options.local_forwards[i].listen_port, |
1408 | (options.local_forwards[i].connect_path != NULL) ? | ||
1409 | options.local_forwards[i].connect_path : | ||
1336 | options.local_forwards[i].connect_host, | 1410 | options.local_forwards[i].connect_host, |
1337 | options.local_forwards[i].connect_port); | 1411 | options.local_forwards[i].connect_port); |
1338 | success += channel_setup_local_fwd_listener( | 1412 | success += channel_setup_local_fwd_listener( |
1339 | options.local_forwards[i].listen_host, | 1413 | &options.local_forwards[i], &options.fwd_opts); |
1340 | options.local_forwards[i].listen_port, | ||
1341 | options.local_forwards[i].connect_host, | ||
1342 | options.local_forwards[i].connect_port, | ||
1343 | options.gateway_ports); | ||
1344 | } | 1414 | } |
1345 | if (i > 0 && success != i && options.exit_on_forward_failure) | 1415 | if (i > 0 && success != i && options.exit_on_forward_failure) |
1346 | fatal("Could not request local forwarding."); | 1416 | fatal("Could not request local forwarding."); |
@@ -1351,17 +1421,18 @@ ssh_init_forwarding(void) | |||
1351 | for (i = 0; i < options.num_remote_forwards; i++) { | 1421 | for (i = 0; i < options.num_remote_forwards; i++) { |
1352 | debug("Remote connections from %.200s:%d forwarded to " | 1422 | debug("Remote connections from %.200s:%d forwarded to " |
1353 | "local address %.200s:%d", | 1423 | "local address %.200s:%d", |
1424 | (options.remote_forwards[i].listen_path != NULL) ? | ||
1425 | options.remote_forwards[i].listen_path : | ||
1354 | (options.remote_forwards[i].listen_host == NULL) ? | 1426 | (options.remote_forwards[i].listen_host == NULL) ? |
1355 | "LOCALHOST" : options.remote_forwards[i].listen_host, | 1427 | "LOCALHOST" : options.remote_forwards[i].listen_host, |
1356 | options.remote_forwards[i].listen_port, | 1428 | options.remote_forwards[i].listen_port, |
1429 | (options.remote_forwards[i].connect_path != NULL) ? | ||
1430 | options.remote_forwards[i].connect_path : | ||
1357 | options.remote_forwards[i].connect_host, | 1431 | options.remote_forwards[i].connect_host, |
1358 | options.remote_forwards[i].connect_port); | 1432 | options.remote_forwards[i].connect_port); |
1359 | options.remote_forwards[i].handle = | 1433 | options.remote_forwards[i].handle = |
1360 | channel_request_remote_forwarding( | 1434 | channel_request_remote_forwarding( |
1361 | options.remote_forwards[i].listen_host, | 1435 | &options.remote_forwards[i]); |
1362 | options.remote_forwards[i].listen_port, | ||
1363 | options.remote_forwards[i].connect_host, | ||
1364 | options.remote_forwards[i].connect_port); | ||
1365 | if (options.remote_forwards[i].handle < 0) { | 1436 | if (options.remote_forwards[i].handle < 0) { |
1366 | if (options.exit_on_forward_failure) | 1437 | if (options.exit_on_forward_failure) |
1367 | fatal("Could not request remote forwarding."); | 1438 | fatal("Could not request remote forwarding."); |