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 | options.log_level = SYSLOG_LEVEL_QUIET; | 353 | options.log_level = SYSLOG_LEVEL_QUIET; |
342 | break; | 354 | break; |
@@ -352,7 +364,7 @@ again: | |||
352 | else { | 364 | else { |
353 | fprintf(stderr, "Bad escape character '%s'.\n", | 365 | fprintf(stderr, "Bad escape character '%s'.\n", |
354 | optarg); | 366 | optarg); |
355 | exit(1); | 367 | exit(255); |
356 | } | 368 | } |
357 | break; | 369 | break; |
358 | case 'c': | 370 | case 'c': |
@@ -367,7 +379,7 @@ again: | |||
367 | fprintf(stderr, | 379 | fprintf(stderr, |
368 | "Unknown cipher type '%s'\n", | 380 | "Unknown cipher type '%s'\n", |
369 | optarg); | 381 | optarg); |
370 | exit(1); | 382 | exit(255); |
371 | } | 383 | } |
372 | if (options.cipher == SSH_CIPHER_3DES) | 384 | if (options.cipher == SSH_CIPHER_3DES) |
373 | options.ciphers = "3des-cbc"; | 385 | options.ciphers = "3des-cbc"; |
@@ -383,7 +395,7 @@ again: | |||
383 | else { | 395 | else { |
384 | fprintf(stderr, "Unknown mac type '%s'\n", | 396 | fprintf(stderr, "Unknown mac type '%s'\n", |
385 | optarg); | 397 | optarg); |
386 | exit(1); | 398 | exit(255); |
387 | } | 399 | } |
388 | break; | 400 | break; |
389 | case 'M': | 401 | case 'M': |
@@ -396,7 +408,7 @@ again: | |||
396 | options.port = a2port(optarg); | 408 | options.port = a2port(optarg); |
397 | if (options.port == 0) { | 409 | if (options.port == 0) { |
398 | fprintf(stderr, "Bad port '%s'\n", optarg); | 410 | fprintf(stderr, "Bad port '%s'\n", optarg); |
399 | exit(1); | 411 | exit(255); |
400 | } | 412 | } |
401 | break; | 413 | break; |
402 | case 'l': | 414 | case 'l': |
@@ -410,7 +422,7 @@ again: | |||
410 | fprintf(stderr, | 422 | fprintf(stderr, |
411 | "Bad local forwarding specification '%s'\n", | 423 | "Bad local forwarding specification '%s'\n", |
412 | optarg); | 424 | optarg); |
413 | exit(1); | 425 | exit(255); |
414 | } | 426 | } |
415 | break; | 427 | break; |
416 | 428 | ||
@@ -421,7 +433,7 @@ again: | |||
421 | fprintf(stderr, | 433 | fprintf(stderr, |
422 | "Bad remote forwarding specification " | 434 | "Bad remote forwarding specification " |
423 | "'%s'\n", optarg); | 435 | "'%s'\n", optarg); |
424 | exit(1); | 436 | exit(255); |
425 | } | 437 | } |
426 | break; | 438 | break; |
427 | 439 | ||
@@ -432,7 +444,7 @@ again: | |||
432 | if ((fwd.listen_host = hpdelim(&cp)) == NULL) { | 444 | if ((fwd.listen_host = hpdelim(&cp)) == NULL) { |
433 | fprintf(stderr, "Bad dynamic forwarding " | 445 | fprintf(stderr, "Bad dynamic forwarding " |
434 | "specification '%.100s'\n", optarg); | 446 | "specification '%.100s'\n", optarg); |
435 | exit(1); | 447 | exit(255); |
436 | } | 448 | } |
437 | if (cp != NULL) { | 449 | if (cp != NULL) { |
438 | fwd.listen_port = a2port(cp); | 450 | fwd.listen_port = a2port(cp); |
@@ -445,7 +457,7 @@ again: | |||
445 | if (fwd.listen_port == 0) { | 457 | if (fwd.listen_port == 0) { |
446 | fprintf(stderr, "Bad dynamic port '%s'\n", | 458 | fprintf(stderr, "Bad dynamic port '%s'\n", |
447 | optarg); | 459 | optarg); |
448 | exit(1); | 460 | exit(255); |
449 | } | 461 | } |
450 | add_local_forward(&options, &fwd); | 462 | add_local_forward(&options, &fwd); |
451 | xfree(p); | 463 | xfree(p); |
@@ -466,7 +478,7 @@ again: | |||
466 | line = xstrdup(optarg); | 478 | line = xstrdup(optarg); |
467 | if (process_config_line(&options, host ? host : "", | 479 | if (process_config_line(&options, host ? host : "", |
468 | line, "command-line", 0, &dummy) != 0) | 480 | line, "command-line", 0, &dummy) != 0) |
469 | exit(1); | 481 | exit(255); |
470 | xfree(line); | 482 | xfree(line); |
471 | break; | 483 | break; |
472 | case 's': | 484 | case 's': |
@@ -642,7 +654,7 @@ again: | |||
642 | original_effective_uid == 0 && options.use_privileged_port, | 654 | original_effective_uid == 0 && options.use_privileged_port, |
643 | #endif | 655 | #endif |
644 | options.proxy_command) != 0) | 656 | options.proxy_command) != 0) |
645 | exit(1); | 657 | exit(255); |
646 | 658 | ||
647 | /* | 659 | /* |
648 | * If we successfully made the connection, load the host private key | 660 | * If we successfully made the connection, load the host private key |
@@ -695,7 +707,7 @@ again: | |||
695 | 707 | ||
696 | /* | 708 | /* |
697 | * Now that we are back to our own permissions, create ~/.ssh | 709 | * Now that we are back to our own permissions, create ~/.ssh |
698 | * directory if it doesn\'t already exist. | 710 | * directory if it doesn't already exist. |
699 | */ | 711 | */ |
700 | snprintf(buf, sizeof buf, "%.100s%s%.100s", pw->pw_dir, strcmp(pw->pw_dir, "/") ? "/" : "", _PATH_SSH_USER_DIR); | 712 | snprintf(buf, sizeof buf, "%.100s%s%.100s", pw->pw_dir, strcmp(pw->pw_dir, "/") ? "/" : "", _PATH_SSH_USER_DIR); |
701 | if (stat(buf, &st) < 0) | 713 | if (stat(buf, &st) < 0) |
@@ -791,8 +803,7 @@ ssh_init_forwarding(void) | |||
791 | debug("Remote connections from %.200s:%d forwarded to " | 803 | debug("Remote connections from %.200s:%d forwarded to " |
792 | "local address %.200s:%d", | 804 | "local address %.200s:%d", |
793 | (options.remote_forwards[i].listen_host == NULL) ? | 805 | (options.remote_forwards[i].listen_host == NULL) ? |
794 | (options.gateway_ports ? "*" : "LOCALHOST") : | 806 | "LOCALHOST" : options.remote_forwards[i].listen_host, |
795 | options.remote_forwards[i].listen_host, | ||
796 | options.remote_forwards[i].listen_port, | 807 | options.remote_forwards[i].listen_port, |
797 | options.remote_forwards[i].connect_host, | 808 | options.remote_forwards[i].connect_host, |
798 | options.remote_forwards[i].connect_port); | 809 | options.remote_forwards[i].connect_port); |
@@ -808,7 +819,7 @@ static void | |||
808 | check_agent_present(void) | 819 | check_agent_present(void) |
809 | { | 820 | { |
810 | if (options.forward_agent) { | 821 | if (options.forward_agent) { |
811 | /* Clear agent forwarding if we don\'t have an agent. */ | 822 | /* Clear agent forwarding if we don't have an agent. */ |
812 | if (!ssh_agent_present()) | 823 | if (!ssh_agent_present()) |
813 | options.forward_agent = 0; | 824 | options.forward_agent = 0; |
814 | } | 825 | } |
@@ -1010,7 +1021,7 @@ ssh_control_listener(void) | |||
1010 | fatal("ControlPath too long"); | 1021 | fatal("ControlPath too long"); |
1011 | 1022 | ||
1012 | if ((control_fd = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) | 1023 | if ((control_fd = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) |
1013 | fatal("%s socket(): %s\n", __func__, strerror(errno)); | 1024 | fatal("%s socket(): %s", __func__, strerror(errno)); |
1014 | 1025 | ||
1015 | old_umask = umask(0177); | 1026 | old_umask = umask(0177); |
1016 | if (bind(control_fd, (struct sockaddr*)&addr, addr_len) == -1) { | 1027 | if (bind(control_fd, (struct sockaddr*)&addr, addr_len) == -1) { |
@@ -1019,12 +1030,12 @@ ssh_control_listener(void) | |||
1019 | fatal("ControlSocket %s already exists", | 1030 | fatal("ControlSocket %s already exists", |
1020 | options.control_path); | 1031 | options.control_path); |
1021 | else | 1032 | else |
1022 | fatal("%s bind(): %s\n", __func__, strerror(errno)); | 1033 | fatal("%s bind(): %s", __func__, strerror(errno)); |
1023 | } | 1034 | } |
1024 | umask(old_umask); | 1035 | umask(old_umask); |
1025 | 1036 | ||
1026 | if (listen(control_fd, 64) == -1) | 1037 | if (listen(control_fd, 64) == -1) |
1027 | fatal("%s listen(): %s\n", __func__, strerror(errno)); | 1038 | fatal("%s listen(): %s", __func__, strerror(errno)); |
1028 | 1039 | ||
1029 | set_nonblock(control_fd); | 1040 | set_nonblock(control_fd); |
1030 | } | 1041 | } |
@@ -1057,6 +1068,33 @@ ssh_session2_setup(int id, void *arg) | |||
1057 | packet_send(); | 1068 | packet_send(); |
1058 | } | 1069 | } |
1059 | 1070 | ||
1071 | if (options.tun_open != SSH_TUNMODE_NO) { | ||
1072 | Channel *c; | ||
1073 | int fd; | ||
1074 | |||
1075 | debug("Requesting tun."); | ||
1076 | if ((fd = tun_open(options.tun_local, | ||
1077 | options.tun_open)) >= 0) { | ||
1078 | c = channel_new("tun", SSH_CHANNEL_OPENING, fd, fd, -1, | ||
1079 | CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, | ||
1080 | 0, "tun", 1); | ||
1081 | c->datagram = 1; | ||
1082 | #if defined(SSH_TUN_FILTER) | ||
1083 | if (options.tun_open == SSH_TUNMODE_POINTOPOINT) | ||
1084 | channel_register_filter(c->self, sys_tun_infilter, | ||
1085 | sys_tun_outfilter); | ||
1086 | #endif | ||
1087 | packet_start(SSH2_MSG_CHANNEL_OPEN); | ||
1088 | packet_put_cstring("tun@openssh.com"); | ||
1089 | packet_put_int(c->self); | ||
1090 | packet_put_int(c->local_window_max); | ||
1091 | packet_put_int(c->local_maxpacket); | ||
1092 | packet_put_int(options.tun_open); | ||
1093 | packet_put_int(options.tun_remote); | ||
1094 | packet_send(); | ||
1095 | } | ||
1096 | } | ||
1097 | |||
1060 | client_session2_setup(id, tty_flag, subsystem_flag, getenv("TERM"), | 1098 | client_session2_setup(id, tty_flag, subsystem_flag, getenv("TERM"), |
1061 | NULL, fileno(stdin), &command, environ, &ssh_subsystem_reply); | 1099 | NULL, fileno(stdin), &command, environ, &ssh_subsystem_reply); |
1062 | 1100 | ||
@@ -1121,6 +1159,11 @@ ssh_session2(void) | |||
1121 | if (!no_shell_flag || (datafellows & SSH_BUG_DUMMYCHAN)) | 1159 | if (!no_shell_flag || (datafellows & SSH_BUG_DUMMYCHAN)) |
1122 | id = ssh_session2_open(); | 1160 | id = ssh_session2_open(); |
1123 | 1161 | ||
1162 | /* Execute a local command */ | ||
1163 | if (options.local_command != NULL && | ||
1164 | options.permit_local_command) | ||
1165 | ssh_local_cmd(options.local_command); | ||
1166 | |||
1124 | /* If requested, let ssh continue in the background. */ | 1167 | /* If requested, let ssh continue in the background. */ |
1125 | if (fork_after_authentication_flag) | 1168 | if (fork_after_authentication_flag) |
1126 | if (daemon(1, 1) < 0) | 1169 | if (daemon(1, 1) < 0) |