diff options
Diffstat (limited to 'ssh.c')
-rw-r--r-- | ssh.c | 96 |
1 files changed, 69 insertions, 27 deletions
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: ssh.c,v 1.346 2010/08/12 21:49:44 djm Exp $ */ | 1 | /* $OpenBSD: ssh.c,v 1.356 2011/01/06 22:23:53 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 |
@@ -50,6 +50,7 @@ | |||
50 | #include <sys/ioctl.h> | 50 | #include <sys/ioctl.h> |
51 | #include <sys/param.h> | 51 | #include <sys/param.h> |
52 | #include <sys/socket.h> | 52 | #include <sys/socket.h> |
53 | #include <sys/wait.h> | ||
53 | 54 | ||
54 | #include <ctype.h> | 55 | #include <ctype.h> |
55 | #include <errno.h> | 56 | #include <errno.h> |
@@ -182,9 +183,6 @@ int subsystem_flag = 0; | |||
182 | /* # of replies received for global requests */ | 183 | /* # of replies received for global requests */ |
183 | static int remote_forward_confirms_received = 0; | 184 | static int remote_forward_confirms_received = 0; |
184 | 185 | ||
185 | /* pid of proxycommand child process */ | ||
186 | pid_t proxy_command_pid = 0; | ||
187 | |||
188 | /* mux.c */ | 186 | /* mux.c */ |
189 | extern int muxserver_sock; | 187 | extern int muxserver_sock; |
190 | extern u_int muxclient_command; | 188 | extern u_int muxclient_command; |
@@ -210,6 +208,7 @@ usage(void) | |||
210 | static int ssh_session(void); | 208 | static int ssh_session(void); |
211 | static int ssh_session2(void); | 209 | static int ssh_session2(void); |
212 | static void load_public_identity_files(void); | 210 | static void load_public_identity_files(void); |
211 | static void main_sigchld_handler(int); | ||
213 | 212 | ||
214 | /* from muxclient.c */ | 213 | /* from muxclient.c */ |
215 | void muxclient(const char *); | 214 | void muxclient(const char *); |
@@ -222,7 +221,7 @@ int | |||
222 | main(int ac, char **av) | 221 | main(int ac, char **av) |
223 | { | 222 | { |
224 | int i, r, opt, exit_status, use_syslog; | 223 | int i, r, opt, exit_status, use_syslog; |
225 | char *p, *cp, *line, *argv0, buf[MAXPATHLEN]; | 224 | char *p, *cp, *line, *argv0, buf[MAXPATHLEN], *host_arg; |
226 | struct stat st; | 225 | struct stat st; |
227 | struct passwd *pw; | 226 | struct passwd *pw; |
228 | int dummy, timeout_ms; | 227 | int dummy, timeout_ms; |
@@ -599,7 +598,7 @@ main(int ac, char **av) | |||
599 | if (!host) | 598 | if (!host) |
600 | usage(); | 599 | usage(); |
601 | 600 | ||
602 | SSLeay_add_all_algorithms(); | 601 | OpenSSL_add_all_algorithms(); |
603 | ERR_load_crypto_strings(); | 602 | ERR_load_crypto_strings(); |
604 | 603 | ||
605 | /* Initialize the command to execute on remote host. */ | 604 | /* Initialize the command to execute on remote host. */ |
@@ -694,6 +693,8 @@ main(int ac, char **av) | |||
694 | options.port = sp ? ntohs(sp->s_port) : SSH_DEFAULT_PORT; | 693 | options.port = sp ? ntohs(sp->s_port) : SSH_DEFAULT_PORT; |
695 | } | 694 | } |
696 | 695 | ||
696 | /* preserve host name given on command line for %n expansion */ | ||
697 | host_arg = host; | ||
697 | if (options.hostname != NULL) { | 698 | if (options.hostname != NULL) { |
698 | host = percent_expand(options.hostname, | 699 | host = percent_expand(options.hostname, |
699 | "h", host, (char *)NULL); | 700 | "h", host, (char *)NULL); |
@@ -708,7 +709,7 @@ main(int ac, char **av) | |||
708 | debug3("expanding LocalCommand: %s", options.local_command); | 709 | debug3("expanding LocalCommand: %s", options.local_command); |
709 | cp = options.local_command; | 710 | cp = options.local_command; |
710 | options.local_command = percent_expand(cp, "d", pw->pw_dir, | 711 | options.local_command = percent_expand(cp, "d", pw->pw_dir, |
711 | "h", host, "l", thishost, "n", host, "r", options.user, | 712 | "h", host, "l", thishost, "n", host_arg, "r", options.user, |
712 | "p", buf, "u", pw->pw_name, (char *)NULL); | 713 | "p", buf, "u", pw->pw_name, (char *)NULL); |
713 | debug3("expanded LocalCommand: %s", options.local_command); | 714 | debug3("expanded LocalCommand: %s", options.local_command); |
714 | xfree(cp); | 715 | xfree(cp); |
@@ -780,34 +781,53 @@ main(int ac, char **av) | |||
780 | sensitive_data.external_keysign = 0; | 781 | sensitive_data.external_keysign = 0; |
781 | if (options.rhosts_rsa_authentication || | 782 | if (options.rhosts_rsa_authentication || |
782 | options.hostbased_authentication) { | 783 | options.hostbased_authentication) { |
783 | sensitive_data.nkeys = 5; | 784 | sensitive_data.nkeys = 7; |
784 | sensitive_data.keys = xcalloc(sensitive_data.nkeys, | 785 | sensitive_data.keys = xcalloc(sensitive_data.nkeys, |
785 | sizeof(Key)); | 786 | sizeof(Key)); |
787 | for (i = 0; i < sensitive_data.nkeys; i++) | ||
788 | sensitive_data.keys[i] = NULL; | ||
786 | 789 | ||
787 | PRIV_START; | 790 | PRIV_START; |
788 | sensitive_data.keys[0] = key_load_private_type(KEY_RSA1, | 791 | sensitive_data.keys[0] = key_load_private_type(KEY_RSA1, |
789 | _PATH_HOST_KEY_FILE, "", NULL, NULL); | 792 | _PATH_HOST_KEY_FILE, "", NULL, NULL); |
790 | sensitive_data.keys[1] = key_load_private_cert(KEY_DSA, | 793 | sensitive_data.keys[1] = key_load_private_cert(KEY_DSA, |
791 | _PATH_HOST_DSA_KEY_FILE, "", NULL); | 794 | _PATH_HOST_DSA_KEY_FILE, "", NULL); |
792 | sensitive_data.keys[2] = key_load_private_cert(KEY_RSA, | 795 | #ifdef OPENSSL_HAS_ECC |
796 | sensitive_data.keys[2] = key_load_private_cert(KEY_ECDSA, | ||
797 | _PATH_HOST_ECDSA_KEY_FILE, "", NULL); | ||
798 | #endif | ||
799 | sensitive_data.keys[3] = key_load_private_cert(KEY_RSA, | ||
793 | _PATH_HOST_RSA_KEY_FILE, "", NULL); | 800 | _PATH_HOST_RSA_KEY_FILE, "", NULL); |
794 | sensitive_data.keys[3] = key_load_private_type(KEY_DSA, | 801 | sensitive_data.keys[4] = key_load_private_type(KEY_DSA, |
795 | _PATH_HOST_DSA_KEY_FILE, "", NULL, NULL); | 802 | _PATH_HOST_DSA_KEY_FILE, "", NULL, NULL); |
796 | sensitive_data.keys[4] = key_load_private_type(KEY_RSA, | 803 | #ifdef OPENSSL_HAS_ECC |
804 | sensitive_data.keys[5] = key_load_private_type(KEY_ECDSA, | ||
805 | _PATH_HOST_ECDSA_KEY_FILE, "", NULL, NULL); | ||
806 | #endif | ||
807 | sensitive_data.keys[6] = key_load_private_type(KEY_RSA, | ||
797 | _PATH_HOST_RSA_KEY_FILE, "", NULL, NULL); | 808 | _PATH_HOST_RSA_KEY_FILE, "", NULL, NULL); |
798 | PRIV_END; | 809 | PRIV_END; |
799 | 810 | ||
800 | if (options.hostbased_authentication == 1 && | 811 | if (options.hostbased_authentication == 1 && |
801 | sensitive_data.keys[0] == NULL && | 812 | sensitive_data.keys[0] == NULL && |
802 | sensitive_data.keys[3] == NULL && | 813 | sensitive_data.keys[4] == NULL && |
803 | sensitive_data.keys[4] == NULL) { | 814 | sensitive_data.keys[5] == NULL && |
815 | sensitive_data.keys[6] == NULL) { | ||
804 | sensitive_data.keys[1] = key_load_cert( | 816 | sensitive_data.keys[1] = key_load_cert( |
805 | _PATH_HOST_DSA_KEY_FILE); | 817 | _PATH_HOST_DSA_KEY_FILE); |
818 | #ifdef OPENSSL_HAS_ECC | ||
806 | sensitive_data.keys[2] = key_load_cert( | 819 | sensitive_data.keys[2] = key_load_cert( |
820 | _PATH_HOST_ECDSA_KEY_FILE); | ||
821 | #endif | ||
822 | sensitive_data.keys[3] = key_load_cert( | ||
807 | _PATH_HOST_RSA_KEY_FILE); | 823 | _PATH_HOST_RSA_KEY_FILE); |
808 | sensitive_data.keys[3] = key_load_public( | ||
809 | _PATH_HOST_DSA_KEY_FILE, NULL); | ||
810 | sensitive_data.keys[4] = key_load_public( | 824 | sensitive_data.keys[4] = key_load_public( |
825 | _PATH_HOST_DSA_KEY_FILE, NULL); | ||
826 | #ifdef OPENSSL_HAS_ECC | ||
827 | sensitive_data.keys[5] = key_load_public( | ||
828 | _PATH_HOST_ECDSA_KEY_FILE, NULL); | ||
829 | #endif | ||
830 | sensitive_data.keys[6] = key_load_public( | ||
811 | _PATH_HOST_RSA_KEY_FILE, NULL); | 831 | _PATH_HOST_RSA_KEY_FILE, NULL); |
812 | sensitive_data.external_keysign = 1; | 832 | sensitive_data.external_keysign = 1; |
813 | } | 833 | } |
@@ -830,10 +850,19 @@ main(int ac, char **av) | |||
830 | */ | 850 | */ |
831 | r = snprintf(buf, sizeof buf, "%s%s%s", pw->pw_dir, | 851 | r = snprintf(buf, sizeof buf, "%s%s%s", pw->pw_dir, |
832 | strcmp(pw->pw_dir, "/") ? "/" : "", _PATH_SSH_USER_DIR); | 852 | strcmp(pw->pw_dir, "/") ? "/" : "", _PATH_SSH_USER_DIR); |
833 | if (r > 0 && (size_t)r < sizeof(buf) && stat(buf, &st) < 0) | 853 | if (r > 0 && (size_t)r < sizeof(buf) && stat(buf, &st) < 0) { |
854 | #ifdef WITH_SELINUX | ||
855 | char *scon; | ||
856 | |||
857 | matchpathcon(buf, 0700, &scon); | ||
858 | setfscreatecon(scon); | ||
859 | #endif | ||
834 | if (mkdir(buf, 0700) < 0) | 860 | if (mkdir(buf, 0700) < 0) |
835 | error("Could not create directory '%.200s'.", buf); | 861 | error("Could not create directory '%.200s'.", buf); |
836 | 862 | #ifdef WITH_SELINUX | |
863 | setfscreatecon(NULL); | ||
864 | #endif | ||
865 | } | ||
837 | /* load options.identity_files */ | 866 | /* load options.identity_files */ |
838 | load_public_identity_files(); | 867 | load_public_identity_files(); |
839 | 868 | ||
@@ -849,10 +878,11 @@ main(int ac, char **av) | |||
849 | tilde_expand_filename(options.user_hostfile2, original_real_uid); | 878 | tilde_expand_filename(options.user_hostfile2, original_real_uid); |
850 | 879 | ||
851 | signal(SIGPIPE, SIG_IGN); /* ignore SIGPIPE early */ | 880 | signal(SIGPIPE, SIG_IGN); /* ignore SIGPIPE early */ |
881 | signal(SIGCHLD, main_sigchld_handler); | ||
852 | 882 | ||
853 | /* Log into the remote system. Never returns if the login fails. */ | 883 | /* Log into the remote system. Never returns if the login fails. */ |
854 | ssh_login(&sensitive_data, host, (struct sockaddr *)&hostaddr, | 884 | ssh_login(&sensitive_data, host, (struct sockaddr *)&hostaddr, |
855 | pw, timeout_ms); | 885 | options.port, pw, timeout_ms); |
856 | 886 | ||
857 | if (packet_connection_is_on_socket()) { | 887 | if (packet_connection_is_on_socket()) { |
858 | verbose("Authenticated to %s ([%s]:%d).", host, | 888 | verbose("Authenticated to %s ([%s]:%d).", host, |
@@ -890,12 +920,8 @@ main(int ac, char **av) | |||
890 | if (options.control_path != NULL && muxserver_sock != -1) | 920 | if (options.control_path != NULL && muxserver_sock != -1) |
891 | unlink(options.control_path); | 921 | unlink(options.control_path); |
892 | 922 | ||
893 | /* | 923 | /* Kill ProxyCommand if it is running. */ |
894 | * Send SIGHUP to proxy command if used. We don't wait() in | 924 | ssh_kill_proxy_command(); |
895 | * case it hangs and instead rely on init to reap the child | ||
896 | */ | ||
897 | if (proxy_command_pid > 1) | ||
898 | kill(proxy_command_pid, SIGHUP); | ||
899 | 925 | ||
900 | return exit_status; | 926 | return exit_status; |
901 | } | 927 | } |
@@ -927,6 +953,7 @@ control_persist_detach(void) | |||
927 | tty_flag = otty_flag; | 953 | tty_flag = otty_flag; |
928 | close(muxserver_sock); | 954 | close(muxserver_sock); |
929 | muxserver_sock = -1; | 955 | muxserver_sock = -1; |
956 | options.control_master = SSHCTL_MASTER_NO; | ||
930 | muxclient(options.control_path); | 957 | muxclient(options.control_path); |
931 | /* muxclient() doesn't return on success. */ | 958 | /* muxclient() doesn't return on success. */ |
932 | fatal("Failed to connect to new control master"); | 959 | fatal("Failed to connect to new control master"); |
@@ -1199,7 +1226,8 @@ ssh_session(void) | |||
1199 | } | 1226 | } |
1200 | } | 1227 | } |
1201 | /* Tell the packet module whether this is an interactive session. */ | 1228 | /* Tell the packet module whether this is an interactive session. */ |
1202 | packet_set_interactive(interactive); | 1229 | packet_set_interactive(interactive, |
1230 | options.ip_qos_interactive, options.ip_qos_bulk); | ||
1203 | 1231 | ||
1204 | /* Request authentication agent forwarding if appropriate. */ | 1232 | /* Request authentication agent forwarding if appropriate. */ |
1205 | check_agent_present(); | 1233 | check_agent_present(); |
@@ -1297,8 +1325,6 @@ ssh_session2_setup(int id, int success, void *arg) | |||
1297 | 1325 | ||
1298 | client_session2_setup(id, tty_flag, subsystem_flag, getenv("TERM"), | 1326 | client_session2_setup(id, tty_flag, subsystem_flag, getenv("TERM"), |
1299 | NULL, fileno(stdin), &command, environ); | 1327 | NULL, fileno(stdin), &command, environ); |
1300 | |||
1301 | packet_set_interactive(interactive); | ||
1302 | } | 1328 | } |
1303 | 1329 | ||
1304 | /* open new channel for a session */ | 1330 | /* open new channel for a session */ |
@@ -1516,3 +1542,19 @@ load_public_identity_files(void) | |||
1516 | bzero(pwdir, strlen(pwdir)); | 1542 | bzero(pwdir, strlen(pwdir)); |
1517 | xfree(pwdir); | 1543 | xfree(pwdir); |
1518 | } | 1544 | } |
1545 | |||
1546 | static void | ||
1547 | main_sigchld_handler(int sig) | ||
1548 | { | ||
1549 | int save_errno = errno; | ||
1550 | pid_t pid; | ||
1551 | int status; | ||
1552 | |||
1553 | while ((pid = waitpid(-1, &status, WNOHANG)) > 0 || | ||
1554 | (pid < 0 && errno == EINTR)) | ||
1555 | ; | ||
1556 | |||
1557 | signal(sig, main_sigchld_handler); | ||
1558 | errno = save_errno; | ||
1559 | } | ||
1560 | |||