diff options
Diffstat (limited to 'ssh.c')
-rw-r--r-- | ssh.c | 125 |
1 files changed, 78 insertions, 47 deletions
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: ssh.c,v 1.356 2011/01/06 22:23:53 djm Exp $ */ | 1 | /* $OpenBSD: ssh.c,v 1.364 2011/08/02 23:15:03 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 |
@@ -111,13 +111,16 @@ | |||
111 | 111 | ||
112 | extern char *__progname; | 112 | extern char *__progname; |
113 | 113 | ||
114 | /* Saves a copy of argv for setproctitle emulation */ | ||
115 | #ifndef HAVE_SETPROCTITLE | ||
116 | static char **saved_av; | ||
117 | #endif | ||
118 | |||
114 | /* Flag indicating whether debug mode is on. May be set on the command line. */ | 119 | /* Flag indicating whether debug mode is on. May be set on the command line. */ |
115 | int debug_flag = 0; | 120 | int debug_flag = 0; |
116 | 121 | ||
117 | /* Flag indicating whether a tty should be allocated */ | 122 | /* Flag indicating whether a tty should be requested */ |
118 | int tty_flag = 0; | 123 | int tty_flag = 0; |
119 | int no_tty_flag = 0; | ||
120 | int force_tty_flag = 0; | ||
121 | 124 | ||
122 | /* don't exec a shell */ | 125 | /* don't exec a shell */ |
123 | int no_shell_flag = 0; | 126 | int no_shell_flag = 0; |
@@ -135,7 +138,7 @@ int stdin_null_flag = 0; | |||
135 | int need_controlpersist_detach = 0; | 138 | int need_controlpersist_detach = 0; |
136 | 139 | ||
137 | /* Copies of flags for ControlPersist foreground slave */ | 140 | /* Copies of flags for ControlPersist foreground slave */ |
138 | int ostdin_null_flag, ono_shell_flag, ono_tty_flag, otty_flag; | 141 | int ostdin_null_flag, ono_shell_flag, otty_flag, orequest_tty; |
139 | 142 | ||
140 | /* | 143 | /* |
141 | * Flag indicating that ssh should fork after authentication. This is useful | 144 | * Flag indicating that ssh should fork after authentication. This is useful |
@@ -214,6 +217,20 @@ static void main_sigchld_handler(int); | |||
214 | void muxclient(const char *); | 217 | void muxclient(const char *); |
215 | void muxserver_listen(void); | 218 | void muxserver_listen(void); |
216 | 219 | ||
220 | /* ~/ expand a list of paths. NB. assumes path[n] is heap-allocated. */ | ||
221 | static void | ||
222 | tilde_expand_paths(char **paths, u_int num_paths) | ||
223 | { | ||
224 | u_int i; | ||
225 | char *cp; | ||
226 | |||
227 | for (i = 0; i < num_paths; i++) { | ||
228 | cp = tilde_expand_filename(paths[i], original_real_uid); | ||
229 | xfree(paths[i]); | ||
230 | paths[i] = cp; | ||
231 | } | ||
232 | } | ||
233 | |||
217 | /* | 234 | /* |
218 | * Main program for the ssh client. | 235 | * Main program for the ssh client. |
219 | */ | 236 | */ |
@@ -222,11 +239,13 @@ main(int ac, char **av) | |||
222 | { | 239 | { |
223 | int i, r, opt, exit_status, use_syslog; | 240 | int i, r, opt, exit_status, use_syslog; |
224 | char *p, *cp, *line, *argv0, buf[MAXPATHLEN], *host_arg; | 241 | char *p, *cp, *line, *argv0, buf[MAXPATHLEN], *host_arg; |
242 | char thishost[NI_MAXHOST], shorthost[NI_MAXHOST], portstr[NI_MAXSERV]; | ||
225 | struct stat st; | 243 | struct stat st; |
226 | struct passwd *pw; | 244 | struct passwd *pw; |
227 | int dummy, timeout_ms; | 245 | int dummy, timeout_ms; |
228 | extern int optind, optreset; | 246 | extern int optind, optreset; |
229 | extern char *optarg; | 247 | extern char *optarg; |
248 | |||
230 | struct servent *sp; | 249 | struct servent *sp; |
231 | Forward fwd; | 250 | Forward fwd; |
232 | 251 | ||
@@ -234,7 +253,17 @@ main(int ac, char **av) | |||
234 | sanitise_stdfd(); | 253 | sanitise_stdfd(); |
235 | 254 | ||
236 | __progname = ssh_get_progname(av[0]); | 255 | __progname = ssh_get_progname(av[0]); |
237 | init_rng(); | 256 | |
257 | #ifndef HAVE_SETPROCTITLE | ||
258 | /* Prepare for later setproctitle emulation */ | ||
259 | /* Save argv so it isn't clobbered by setproctitle() emulation */ | ||
260 | saved_av = xcalloc(ac + 1, sizeof(*saved_av)); | ||
261 | for (i = 0; i < ac; i++) | ||
262 | saved_av[i] = xstrdup(av[i]); | ||
263 | saved_av[i] = NULL; | ||
264 | compat_init_setproctitle(ac, av); | ||
265 | av = saved_av; | ||
266 | #endif | ||
238 | 267 | ||
239 | /* | 268 | /* |
240 | * Discard other fds that are hanging around. These can cause problem | 269 | * Discard other fds that are hanging around. These can cause problem |
@@ -346,6 +375,8 @@ main(int ac, char **av) | |||
346 | muxclient_command = SSHMUX_COMMAND_FORWARD; | 375 | muxclient_command = SSHMUX_COMMAND_FORWARD; |
347 | else if (strcmp(optarg, "exit") == 0) | 376 | else if (strcmp(optarg, "exit") == 0) |
348 | muxclient_command = SSHMUX_COMMAND_TERMINATE; | 377 | muxclient_command = SSHMUX_COMMAND_TERMINATE; |
378 | else if (strcmp(optarg, "stop") == 0) | ||
379 | muxclient_command = SSHMUX_COMMAND_STOP; | ||
349 | else | 380 | else |
350 | fatal("Invalid multiplex command."); | 381 | fatal("Invalid multiplex command."); |
351 | break; | 382 | break; |
@@ -387,9 +418,10 @@ main(int ac, char **av) | |||
387 | #endif | 418 | #endif |
388 | break; | 419 | break; |
389 | case 't': | 420 | case 't': |
390 | if (tty_flag) | 421 | if (options.request_tty == REQUEST_TTY_YES) |
391 | force_tty_flag = 1; | 422 | options.request_tty = REQUEST_TTY_FORCE; |
392 | tty_flag = 1; | 423 | else |
424 | options.request_tty = REQUEST_TTY_YES; | ||
393 | break; | 425 | break; |
394 | case 'v': | 426 | case 'v': |
395 | if (debug_flag == 0) { | 427 | if (debug_flag == 0) { |
@@ -432,7 +464,7 @@ main(int ac, char **av) | |||
432 | optarg); | 464 | optarg); |
433 | exit(255); | 465 | exit(255); |
434 | } | 466 | } |
435 | no_tty_flag = 1; | 467 | options.request_tty = REQUEST_TTY_NO; |
436 | no_shell_flag = 1; | 468 | no_shell_flag = 1; |
437 | options.clear_forwardings = 1; | 469 | options.clear_forwardings = 1; |
438 | options.exit_on_forward_failure = 1; | 470 | options.exit_on_forward_failure = 1; |
@@ -541,10 +573,10 @@ main(int ac, char **av) | |||
541 | break; | 573 | break; |
542 | case 'N': | 574 | case 'N': |
543 | no_shell_flag = 1; | 575 | no_shell_flag = 1; |
544 | no_tty_flag = 1; | 576 | options.request_tty = REQUEST_TTY_NO; |
545 | break; | 577 | break; |
546 | case 'T': | 578 | case 'T': |
547 | no_tty_flag = 1; | 579 | options.request_tty = REQUEST_TTY_NO; |
548 | break; | 580 | break; |
549 | case 'o': | 581 | case 'o': |
550 | dummy = 1; | 582 | dummy = 1; |
@@ -604,6 +636,10 @@ main(int ac, char **av) | |||
604 | /* Initialize the command to execute on remote host. */ | 636 | /* Initialize the command to execute on remote host. */ |
605 | buffer_init(&command); | 637 | buffer_init(&command); |
606 | 638 | ||
639 | if (options.request_tty == REQUEST_TTY_YES || | ||
640 | options.request_tty == REQUEST_TTY_FORCE) | ||
641 | tty_flag = 1; | ||
642 | |||
607 | /* | 643 | /* |
608 | * Save the command to execute on the remote host in a buffer. There | 644 | * Save the command to execute on the remote host in a buffer. There |
609 | * is no limit on the length of the command, except by the maximum | 645 | * is no limit on the length of the command, except by the maximum |
@@ -611,7 +647,7 @@ main(int ac, char **av) | |||
611 | */ | 647 | */ |
612 | if (!ac) { | 648 | if (!ac) { |
613 | /* No command specified - execute shell on a tty. */ | 649 | /* No command specified - execute shell on a tty. */ |
614 | tty_flag = 1; | 650 | tty_flag = options.request_tty != REQUEST_TTY_NO; |
615 | if (subsystem_flag) { | 651 | if (subsystem_flag) { |
616 | fprintf(stderr, | 652 | fprintf(stderr, |
617 | "You must specify a subsystem to invoke.\n"); | 653 | "You must specify a subsystem to invoke.\n"); |
@@ -634,13 +670,14 @@ main(int ac, char **av) | |||
634 | 670 | ||
635 | /* Allocate a tty by default if no command specified. */ | 671 | /* Allocate a tty by default if no command specified. */ |
636 | if (buffer_len(&command) == 0) | 672 | if (buffer_len(&command) == 0) |
637 | tty_flag = 1; | 673 | tty_flag = options.request_tty != REQUEST_TTY_NO; |
638 | 674 | ||
639 | /* Force no tty */ | 675 | /* Force no tty */ |
640 | if (no_tty_flag || muxclient_command != 0) | 676 | if (options.request_tty == REQUEST_TTY_NO || muxclient_command != 0) |
641 | tty_flag = 0; | 677 | tty_flag = 0; |
642 | /* Do not allocate a tty if stdin is not a tty. */ | 678 | /* Do not allocate a tty if stdin is not a tty. */ |
643 | if ((!isatty(fileno(stdin)) || stdin_null_flag) && !force_tty_flag) { | 679 | if ((!isatty(fileno(stdin)) || stdin_null_flag) && |
680 | options.request_tty != REQUEST_TTY_FORCE) { | ||
644 | if (tty_flag && options.log_level != SYSLOG_LEVEL_QUIET) | 681 | if (tty_flag && options.log_level != SYSLOG_LEVEL_QUIET) |
645 | logit("Pseudo-terminal will not be allocated because " | 682 | logit("Pseudo-terminal will not be allocated because " |
646 | "stdin is not a terminal."); | 683 | "stdin is not a terminal."); |
@@ -669,7 +706,7 @@ main(int ac, char **av) | |||
669 | if (r > 0 && (size_t)r < sizeof(buf)) | 706 | if (r > 0 && (size_t)r < sizeof(buf)) |
670 | (void)read_config_file(buf, host, &options, 1); | 707 | (void)read_config_file(buf, host, &options, 1); |
671 | 708 | ||
672 | /* Read systemwide configuration file after use config. */ | 709 | /* Read systemwide configuration file after user config. */ |
673 | (void)read_config_file(_PATH_HOST_CONFIG_FILE, host, | 710 | (void)read_config_file(_PATH_HOST_CONFIG_FILE, host, |
674 | &options, 0); | 711 | &options, 0); |
675 | } | 712 | } |
@@ -700,17 +737,19 @@ main(int ac, char **av) | |||
700 | "h", host, (char *)NULL); | 737 | "h", host, (char *)NULL); |
701 | } | 738 | } |
702 | 739 | ||
703 | if (options.local_command != NULL) { | 740 | if (gethostname(thishost, sizeof(thishost)) == -1) |
704 | char thishost[NI_MAXHOST]; | 741 | fatal("gethostname: %s", strerror(errno)); |
742 | strlcpy(shorthost, thishost, sizeof(shorthost)); | ||
743 | shorthost[strcspn(thishost, ".")] = '\0'; | ||
744 | snprintf(portstr, sizeof(portstr), "%d", options.port); | ||
705 | 745 | ||
706 | if (gethostname(thishost, sizeof(thishost)) == -1) | 746 | if (options.local_command != NULL) { |
707 | fatal("gethostname: %s", strerror(errno)); | ||
708 | snprintf(buf, sizeof(buf), "%d", options.port); | ||
709 | debug3("expanding LocalCommand: %s", options.local_command); | 747 | debug3("expanding LocalCommand: %s", options.local_command); |
710 | cp = options.local_command; | 748 | cp = options.local_command; |
711 | options.local_command = percent_expand(cp, "d", pw->pw_dir, | 749 | options.local_command = percent_expand(cp, "d", pw->pw_dir, |
712 | "h", host, "l", thishost, "n", host_arg, "r", options.user, | 750 | "h", host, "l", thishost, "n", host_arg, "r", options.user, |
713 | "p", buf, "u", pw->pw_name, (char *)NULL); | 751 | "p", portstr, "u", pw->pw_name, "L", shorthost, |
752 | (char *)NULL); | ||
714 | debug3("expanded LocalCommand: %s", options.local_command); | 753 | debug3("expanded LocalCommand: %s", options.local_command); |
715 | xfree(cp); | 754 | xfree(cp); |
716 | } | 755 | } |
@@ -734,16 +773,13 @@ main(int ac, char **av) | |||
734 | } | 773 | } |
735 | 774 | ||
736 | if (options.control_path != NULL) { | 775 | if (options.control_path != NULL) { |
737 | char thishost[NI_MAXHOST]; | ||
738 | |||
739 | if (gethostname(thishost, sizeof(thishost)) == -1) | ||
740 | fatal("gethostname: %s", strerror(errno)); | ||
741 | snprintf(buf, sizeof(buf), "%d", options.port); | ||
742 | cp = tilde_expand_filename(options.control_path, | 776 | cp = tilde_expand_filename(options.control_path, |
743 | original_real_uid); | 777 | original_real_uid); |
744 | xfree(options.control_path); | 778 | xfree(options.control_path); |
745 | options.control_path = percent_expand(cp, "p", buf, "h", host, | 779 | options.control_path = percent_expand(cp, "h", host, |
746 | "r", options.user, "l", thishost, (char *)NULL); | 780 | "l", thishost, "n", host_arg, "r", options.user, |
781 | "p", portstr, "u", pw->pw_name, "L", shorthost, | ||
782 | (char *)NULL); | ||
747 | xfree(cp); | 783 | xfree(cp); |
748 | } | 784 | } |
749 | if (muxclient_command != 0 && options.control_path == NULL) | 785 | if (muxclient_command != 0 && options.control_path == NULL) |
@@ -864,15 +900,9 @@ main(int ac, char **av) | |||
864 | load_public_identity_files(); | 900 | load_public_identity_files(); |
865 | 901 | ||
866 | /* Expand ~ in known host file names. */ | 902 | /* Expand ~ in known host file names. */ |
867 | /* XXX mem-leaks: */ | 903 | tilde_expand_paths(options.system_hostfiles, |
868 | options.system_hostfile = | 904 | options.num_system_hostfiles); |
869 | tilde_expand_filename(options.system_hostfile, original_real_uid); | 905 | tilde_expand_paths(options.user_hostfiles, options.num_user_hostfiles); |
870 | options.user_hostfile = | ||
871 | tilde_expand_filename(options.user_hostfile, original_real_uid); | ||
872 | options.system_hostfile2 = | ||
873 | tilde_expand_filename(options.system_hostfile2, original_real_uid); | ||
874 | options.user_hostfile2 = | ||
875 | tilde_expand_filename(options.user_hostfile2, original_real_uid); | ||
876 | 906 | ||
877 | signal(SIGPIPE, SIG_IGN); /* ignore SIGPIPE early */ | 907 | signal(SIGPIPE, SIG_IGN); /* ignore SIGPIPE early */ |
878 | signal(SIGCHLD, main_sigchld_handler); | 908 | signal(SIGCHLD, main_sigchld_handler); |
@@ -945,8 +975,7 @@ control_persist_detach(void) | |||
945 | /* Parent: set up mux slave to connect to backgrounded master */ | 975 | /* Parent: set up mux slave to connect to backgrounded master */ |
946 | debug2("%s: background process is %ld", __func__, (long)pid); | 976 | debug2("%s: background process is %ld", __func__, (long)pid); |
947 | stdin_null_flag = ostdin_null_flag; | 977 | stdin_null_flag = ostdin_null_flag; |
948 | no_shell_flag = ono_shell_flag; | 978 | options.request_tty = orequest_tty; |
949 | no_tty_flag = ono_tty_flag; | ||
950 | tty_flag = otty_flag; | 979 | tty_flag = otty_flag; |
951 | close(muxserver_sock); | 980 | close(muxserver_sock); |
952 | muxserver_sock = -1; | 981 | muxserver_sock = -1; |
@@ -965,6 +994,7 @@ control_persist_detach(void) | |||
965 | if (devnull > STDERR_FILENO) | 994 | if (devnull > STDERR_FILENO) |
966 | close(devnull); | 995 | close(devnull); |
967 | } | 996 | } |
997 | setproctitle("%s [mux]", options.control_path); | ||
968 | } | 998 | } |
969 | 999 | ||
970 | /* Do fork() after authentication. Used by "ssh -f" */ | 1000 | /* Do fork() after authentication. Used by "ssh -f" */ |
@@ -1209,8 +1239,8 @@ ssh_session(void) | |||
1209 | /* Request forwarding with authentication spoofing. */ | 1239 | /* Request forwarding with authentication spoofing. */ |
1210 | debug("Requesting X11 forwarding with authentication " | 1240 | debug("Requesting X11 forwarding with authentication " |
1211 | "spoofing."); | 1241 | "spoofing."); |
1212 | x11_request_forwarding_with_spoofing(0, display, proto, data); | 1242 | x11_request_forwarding_with_spoofing(0, display, proto, |
1213 | 1243 | data, 0); | |
1214 | /* Read response from the server. */ | 1244 | /* Read response from the server. */ |
1215 | type = packet_read(); | 1245 | type = packet_read(); |
1216 | if (type == SSH_SMSG_SUCCESS) { | 1246 | if (type == SSH_SMSG_SUCCESS) { |
@@ -1308,9 +1338,11 @@ ssh_session2_setup(int id, int success, void *arg) | |||
1308 | /* Request forwarding with authentication spoofing. */ | 1338 | /* Request forwarding with authentication spoofing. */ |
1309 | debug("Requesting X11 forwarding with authentication " | 1339 | debug("Requesting X11 forwarding with authentication " |
1310 | "spoofing."); | 1340 | "spoofing."); |
1311 | x11_request_forwarding_with_spoofing(id, display, proto, data); | 1341 | x11_request_forwarding_with_spoofing(id, display, proto, |
1342 | data, 1); | ||
1343 | client_expect_confirm(id, "X11 forwarding", CONFIRM_WARN); | ||
1344 | /* XXX exit_on_forward_failure */ | ||
1312 | interactive = 1; | 1345 | interactive = 1; |
1313 | /* XXX wait for reply */ | ||
1314 | } | 1346 | } |
1315 | 1347 | ||
1316 | check_agent_present(); | 1348 | check_agent_present(); |
@@ -1393,11 +1425,10 @@ ssh_session2(void) | |||
1393 | if (options.control_persist && muxserver_sock != -1) { | 1425 | if (options.control_persist && muxserver_sock != -1) { |
1394 | ostdin_null_flag = stdin_null_flag; | 1426 | ostdin_null_flag = stdin_null_flag; |
1395 | ono_shell_flag = no_shell_flag; | 1427 | ono_shell_flag = no_shell_flag; |
1396 | ono_tty_flag = no_tty_flag; | 1428 | orequest_tty = options.request_tty; |
1397 | otty_flag = tty_flag; | 1429 | otty_flag = tty_flag; |
1398 | stdin_null_flag = 1; | 1430 | stdin_null_flag = 1; |
1399 | no_shell_flag = 1; | 1431 | no_shell_flag = 1; |
1400 | no_tty_flag = 1; | ||
1401 | tty_flag = 0; | 1432 | tty_flag = 0; |
1402 | if (!fork_after_authentication_flag) | 1433 | if (!fork_after_authentication_flag) |
1403 | need_controlpersist_detach = 1; | 1434 | need_controlpersist_detach = 1; |