diff options
Diffstat (limited to 'ssh.c')
-rw-r--r-- | ssh.c | 89 |
1 files changed, 66 insertions, 23 deletions
@@ -40,7 +40,7 @@ | |||
40 | */ | 40 | */ |
41 | 41 | ||
42 | #include "includes.h" | 42 | #include "includes.h" |
43 | RCSID("$OpenBSD: ssh.c,v 1.249 2005/07/30 01:26:16 djm Exp $"); | 43 | RCSID("$OpenBSD: ssh.c,v 1.257 2005/12/20 04:41:07 dtucker Exp $"); |
44 | 44 | ||
45 | #include <openssl/evp.h> | 45 | #include <openssl/evp.h> |
46 | #include <openssl/err.h> | 46 | #include <openssl/err.h> |
@@ -158,13 +158,13 @@ usage(void) | |||
158 | { | 158 | { |
159 | fprintf(stderr, | 159 | fprintf(stderr, |
160 | "usage: ssh [-1246AaCfgkMNnqsTtVvXxY] [-b bind_address] [-c cipher_spec]\n" | 160 | "usage: ssh [-1246AaCfgkMNnqsTtVvXxY] [-b bind_address] [-c cipher_spec]\n" |
161 | " [-D port] [-e escape_char] [-F configfile]\n" | 161 | " [-D [bind_address:]port] [-e escape_char] [-F configfile]\n" |
162 | " [-i identity_file] [-L [bind_address:]port:host:hostport]\n" | 162 | " [-i identity_file] [-L [bind_address:]port:host:hostport]\n" |
163 | " [-l login_name] [-m mac_spec] [-O ctl_cmd] [-o option] [-p port]\n" | 163 | " [-l login_name] [-m mac_spec] [-O ctl_cmd] [-o option] [-p port]\n" |
164 | " [-R [bind_address:]port:host:hostport] [-S ctl_path]\n" | 164 | " [-R [bind_address:]port:host:hostport] [-S ctl_path]\n" |
165 | " [user@]hostname [command]\n" | 165 | " [-w tunnel:tunnel] [user@]hostname [command]\n" |
166 | ); | 166 | ); |
167 | exit(1); | 167 | exit(255); |
168 | } | 168 | } |
169 | 169 | ||
170 | static int ssh_session(void); | 170 | static int ssh_session(void); |
@@ -188,6 +188,9 @@ main(int ac, char **av) | |||
188 | struct servent *sp; | 188 | struct servent *sp; |
189 | Forward fwd; | 189 | Forward fwd; |
190 | 190 | ||
191 | /* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */ | ||
192 | sanitise_stdfd(); | ||
193 | |||
191 | __progname = ssh_get_progname(av[0]); | 194 | __progname = ssh_get_progname(av[0]); |
192 | init_rng(); | 195 | init_rng(); |
193 | 196 | ||
@@ -220,7 +223,7 @@ main(int ac, char **av) | |||
220 | pw = getpwuid(original_real_uid); | 223 | pw = getpwuid(original_real_uid); |
221 | if (!pw) { | 224 | if (!pw) { |
222 | logit("You don't exist, go away!"); | 225 | logit("You don't exist, go away!"); |
223 | exit(1); | 226 | exit(255); |
224 | } | 227 | } |
225 | /* Take a copy of the returned structure. */ | 228 | /* Take a copy of the returned structure. */ |
226 | pw = pwcopy(pw); | 229 | pw = pwcopy(pw); |
@@ -241,7 +244,7 @@ main(int ac, char **av) | |||
241 | 244 | ||
242 | again: | 245 | again: |
243 | while ((opt = getopt(ac, av, | 246 | while ((opt = getopt(ac, av, |
244 | "1246ab:c:e:fgi:kl:m:no:p:qstvxACD:F:I:L:MNO:PR:S:TVXY")) != -1) { | 247 | "1246ab:c:e:fgi:kl:m:no:p:qstvxACD:F:I:L:MNO:PR:S:TVw:XY")) != -1) { |
245 | switch (opt) { | 248 | switch (opt) { |
246 | case '1': | 249 | case '1': |
247 | options.protocol = SSH_PROTO_1; | 250 | options.protocol = SSH_PROTO_1; |
@@ -337,6 +340,15 @@ again: | |||
337 | if (opt == 'V') | 340 | if (opt == 'V') |
338 | exit(0); | 341 | exit(0); |
339 | break; | 342 | break; |
343 | case 'w': | ||
344 | if (options.tun_open == -1) | ||
345 | options.tun_open = SSH_TUNMODE_DEFAULT; | ||
346 | options.tun_local = a2tun(optarg, &options.tun_remote); | ||
347 | if (options.tun_local == SSH_TUNID_ERR) { | ||
348 | fprintf(stderr, "Bad tun device '%s'\n", optarg); | ||
349 | exit(255); | ||
350 | } | ||
351 | break; | ||
340 | case 'q': | 352 | case 'q': |
341 | if (options.log_level == SYSLOG_LEVEL_QUIET) { | 353 | if (options.log_level == SYSLOG_LEVEL_QUIET) { |
342 | options.log_level = SYSLOG_LEVEL_SILENT; | 354 | options.log_level = SYSLOG_LEVEL_SILENT; |
@@ -357,7 +369,7 @@ again: | |||
357 | else { | 369 | else { |
358 | fprintf(stderr, "Bad escape character '%s'.\n", | 370 | fprintf(stderr, "Bad escape character '%s'.\n", |
359 | optarg); | 371 | optarg); |
360 | exit(1); | 372 | exit(255); |
361 | } | 373 | } |
362 | break; | 374 | break; |
363 | case 'c': | 375 | case 'c': |
@@ -372,7 +384,7 @@ again: | |||
372 | fprintf(stderr, | 384 | fprintf(stderr, |
373 | "Unknown cipher type '%s'\n", | 385 | "Unknown cipher type '%s'\n", |
374 | optarg); | 386 | optarg); |
375 | exit(1); | 387 | exit(255); |
376 | } | 388 | } |
377 | if (options.cipher == SSH_CIPHER_3DES) | 389 | if (options.cipher == SSH_CIPHER_3DES) |
378 | options.ciphers = "3des-cbc"; | 390 | options.ciphers = "3des-cbc"; |
@@ -388,7 +400,7 @@ again: | |||
388 | else { | 400 | else { |
389 | fprintf(stderr, "Unknown mac type '%s'\n", | 401 | fprintf(stderr, "Unknown mac type '%s'\n", |
390 | optarg); | 402 | optarg); |
391 | exit(1); | 403 | exit(255); |
392 | } | 404 | } |
393 | break; | 405 | break; |
394 | case 'M': | 406 | case 'M': |
@@ -401,7 +413,7 @@ again: | |||
401 | options.port = a2port(optarg); | 413 | options.port = a2port(optarg); |
402 | if (options.port == 0) { | 414 | if (options.port == 0) { |
403 | fprintf(stderr, "Bad port '%s'\n", optarg); | 415 | fprintf(stderr, "Bad port '%s'\n", optarg); |
404 | exit(1); | 416 | exit(255); |
405 | } | 417 | } |
406 | break; | 418 | break; |
407 | case 'l': | 419 | case 'l': |
@@ -415,7 +427,7 @@ again: | |||
415 | fprintf(stderr, | 427 | fprintf(stderr, |
416 | "Bad local forwarding specification '%s'\n", | 428 | "Bad local forwarding specification '%s'\n", |
417 | optarg); | 429 | optarg); |
418 | exit(1); | 430 | exit(255); |
419 | } | 431 | } |
420 | break; | 432 | break; |
421 | 433 | ||
@@ -426,7 +438,7 @@ again: | |||
426 | fprintf(stderr, | 438 | fprintf(stderr, |
427 | "Bad remote forwarding specification " | 439 | "Bad remote forwarding specification " |
428 | "'%s'\n", optarg); | 440 | "'%s'\n", optarg); |
429 | exit(1); | 441 | exit(255); |
430 | } | 442 | } |
431 | break; | 443 | break; |
432 | 444 | ||
@@ -437,7 +449,7 @@ again: | |||
437 | if ((fwd.listen_host = hpdelim(&cp)) == NULL) { | 449 | if ((fwd.listen_host = hpdelim(&cp)) == NULL) { |
438 | fprintf(stderr, "Bad dynamic forwarding " | 450 | fprintf(stderr, "Bad dynamic forwarding " |
439 | "specification '%.100s'\n", optarg); | 451 | "specification '%.100s'\n", optarg); |
440 | exit(1); | 452 | exit(255); |
441 | } | 453 | } |
442 | if (cp != NULL) { | 454 | if (cp != NULL) { |
443 | fwd.listen_port = a2port(cp); | 455 | fwd.listen_port = a2port(cp); |
@@ -450,7 +462,7 @@ again: | |||
450 | if (fwd.listen_port == 0) { | 462 | if (fwd.listen_port == 0) { |
451 | fprintf(stderr, "Bad dynamic port '%s'\n", | 463 | fprintf(stderr, "Bad dynamic port '%s'\n", |
452 | optarg); | 464 | optarg); |
453 | exit(1); | 465 | exit(255); |
454 | } | 466 | } |
455 | add_local_forward(&options, &fwd); | 467 | add_local_forward(&options, &fwd); |
456 | xfree(p); | 468 | xfree(p); |
@@ -471,7 +483,7 @@ again: | |||
471 | line = xstrdup(optarg); | 483 | line = xstrdup(optarg); |
472 | if (process_config_line(&options, host ? host : "", | 484 | if (process_config_line(&options, host ? host : "", |
473 | line, "command-line", 0, &dummy) != 0) | 485 | line, "command-line", 0, &dummy) != 0) |
474 | exit(1); | 486 | exit(255); |
475 | xfree(line); | 487 | xfree(line); |
476 | break; | 488 | break; |
477 | case 's': | 489 | case 's': |
@@ -647,7 +659,7 @@ again: | |||
647 | original_effective_uid == 0 && options.use_privileged_port, | 659 | original_effective_uid == 0 && options.use_privileged_port, |
648 | #endif | 660 | #endif |
649 | options.proxy_command) != 0) | 661 | options.proxy_command) != 0) |
650 | exit(1); | 662 | exit(255); |
651 | 663 | ||
652 | /* | 664 | /* |
653 | * If we successfully made the connection, load the host private key | 665 | * If we successfully made the connection, load the host private key |
@@ -700,7 +712,7 @@ again: | |||
700 | 712 | ||
701 | /* | 713 | /* |
702 | * Now that we are back to our own permissions, create ~/.ssh | 714 | * Now that we are back to our own permissions, create ~/.ssh |
703 | * directory if it doesn\'t already exist. | 715 | * directory if it doesn't already exist. |
704 | */ | 716 | */ |
705 | snprintf(buf, sizeof buf, "%.100s%s%.100s", pw->pw_dir, strcmp(pw->pw_dir, "/") ? "/" : "", _PATH_SSH_USER_DIR); | 717 | snprintf(buf, sizeof buf, "%.100s%s%.100s", pw->pw_dir, strcmp(pw->pw_dir, "/") ? "/" : "", _PATH_SSH_USER_DIR); |
706 | if (stat(buf, &st) < 0) | 718 | if (stat(buf, &st) < 0) |
@@ -796,8 +808,7 @@ ssh_init_forwarding(void) | |||
796 | debug("Remote connections from %.200s:%d forwarded to " | 808 | debug("Remote connections from %.200s:%d forwarded to " |
797 | "local address %.200s:%d", | 809 | "local address %.200s:%d", |
798 | (options.remote_forwards[i].listen_host == NULL) ? | 810 | (options.remote_forwards[i].listen_host == NULL) ? |
799 | (options.gateway_ports ? "*" : "LOCALHOST") : | 811 | "LOCALHOST" : options.remote_forwards[i].listen_host, |
800 | options.remote_forwards[i].listen_host, | ||
801 | options.remote_forwards[i].listen_port, | 812 | options.remote_forwards[i].listen_port, |
802 | options.remote_forwards[i].connect_host, | 813 | options.remote_forwards[i].connect_host, |
803 | options.remote_forwards[i].connect_port); | 814 | options.remote_forwards[i].connect_port); |
@@ -813,7 +824,7 @@ static void | |||
813 | check_agent_present(void) | 824 | check_agent_present(void) |
814 | { | 825 | { |
815 | if (options.forward_agent) { | 826 | if (options.forward_agent) { |
816 | /* Clear agent forwarding if we don\'t have an agent. */ | 827 | /* Clear agent forwarding if we don't have an agent. */ |
817 | if (!ssh_agent_present()) | 828 | if (!ssh_agent_present()) |
818 | options.forward_agent = 0; | 829 | options.forward_agent = 0; |
819 | } | 830 | } |
@@ -1015,7 +1026,7 @@ ssh_control_listener(void) | |||
1015 | fatal("ControlPath too long"); | 1026 | fatal("ControlPath too long"); |
1016 | 1027 | ||
1017 | if ((control_fd = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) | 1028 | if ((control_fd = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) |
1018 | fatal("%s socket(): %s\n", __func__, strerror(errno)); | 1029 | fatal("%s socket(): %s", __func__, strerror(errno)); |
1019 | 1030 | ||
1020 | old_umask = umask(0177); | 1031 | old_umask = umask(0177); |
1021 | if (bind(control_fd, (struct sockaddr*)&addr, addr_len) == -1) { | 1032 | if (bind(control_fd, (struct sockaddr*)&addr, addr_len) == -1) { |
@@ -1024,12 +1035,12 @@ ssh_control_listener(void) | |||
1024 | fatal("ControlSocket %s already exists", | 1035 | fatal("ControlSocket %s already exists", |
1025 | options.control_path); | 1036 | options.control_path); |
1026 | else | 1037 | else |
1027 | fatal("%s bind(): %s\n", __func__, strerror(errno)); | 1038 | fatal("%s bind(): %s", __func__, strerror(errno)); |
1028 | } | 1039 | } |
1029 | umask(old_umask); | 1040 | umask(old_umask); |
1030 | 1041 | ||
1031 | if (listen(control_fd, 64) == -1) | 1042 | if (listen(control_fd, 64) == -1) |
1032 | fatal("%s listen(): %s\n", __func__, strerror(errno)); | 1043 | fatal("%s listen(): %s", __func__, strerror(errno)); |
1033 | 1044 | ||
1034 | set_nonblock(control_fd); | 1045 | set_nonblock(control_fd); |
1035 | } | 1046 | } |
@@ -1062,6 +1073,33 @@ ssh_session2_setup(int id, void *arg) | |||
1062 | packet_send(); | 1073 | packet_send(); |
1063 | } | 1074 | } |
1064 | 1075 | ||
1076 | if (options.tun_open != SSH_TUNMODE_NO) { | ||
1077 | Channel *c; | ||
1078 | int fd; | ||
1079 | |||
1080 | debug("Requesting tun."); | ||
1081 | if ((fd = tun_open(options.tun_local, | ||
1082 | options.tun_open)) >= 0) { | ||
1083 | c = channel_new("tun", SSH_CHANNEL_OPENING, fd, fd, -1, | ||
1084 | CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, | ||
1085 | 0, "tun", 1); | ||
1086 | c->datagram = 1; | ||
1087 | #if defined(SSH_TUN_FILTER) | ||
1088 | if (options.tun_open == SSH_TUNMODE_POINTOPOINT) | ||
1089 | channel_register_filter(c->self, sys_tun_infilter, | ||
1090 | sys_tun_outfilter); | ||
1091 | #endif | ||
1092 | packet_start(SSH2_MSG_CHANNEL_OPEN); | ||
1093 | packet_put_cstring("tun@openssh.com"); | ||
1094 | packet_put_int(c->self); | ||
1095 | packet_put_int(c->local_window_max); | ||
1096 | packet_put_int(c->local_maxpacket); | ||
1097 | packet_put_int(options.tun_open); | ||
1098 | packet_put_int(options.tun_remote); | ||
1099 | packet_send(); | ||
1100 | } | ||
1101 | } | ||
1102 | |||
1065 | client_session2_setup(id, tty_flag, subsystem_flag, getenv("TERM"), | 1103 | client_session2_setup(id, tty_flag, subsystem_flag, getenv("TERM"), |
1066 | NULL, fileno(stdin), &command, environ, &ssh_subsystem_reply); | 1104 | NULL, fileno(stdin), &command, environ, &ssh_subsystem_reply); |
1067 | 1105 | ||
@@ -1126,6 +1164,11 @@ ssh_session2(void) | |||
1126 | if (!no_shell_flag || (datafellows & SSH_BUG_DUMMYCHAN)) | 1164 | if (!no_shell_flag || (datafellows & SSH_BUG_DUMMYCHAN)) |
1127 | id = ssh_session2_open(); | 1165 | id = ssh_session2_open(); |
1128 | 1166 | ||
1167 | /* Execute a local command */ | ||
1168 | if (options.local_command != NULL && | ||
1169 | options.permit_local_command) | ||
1170 | ssh_local_cmd(options.local_command); | ||
1171 | |||
1129 | /* If requested, let ssh continue in the background. */ | 1172 | /* If requested, let ssh continue in the background. */ |
1130 | if (fork_after_authentication_flag) | 1173 | if (fork_after_authentication_flag) |
1131 | if (daemon(1, 1) < 0) | 1174 | if (daemon(1, 1) < 0) |