diff options
author | Colin Watson <cjwatson@debian.org> | 2004-03-01 02:25:32 +0000 |
---|---|---|
committer | Colin Watson <cjwatson@debian.org> | 2004-03-01 02:25:32 +0000 |
commit | ea8116a11e3de70036dbc665ccb0d486cf89cac9 (patch) | |
tree | d73ccdff78d8608e156465af42e6a1b3527fb2d6 /sshconnect.c | |
parent | e39b311381a5609cc05acf298c42fba196dc524b (diff) | |
parent | f5bda272678ec6dccaa5f29379cf60cb855018e8 (diff) |
Merge 3.8p1 to the trunk. This builds and runs, but I haven't tested it
extensively yet.
ProtocolKeepAlives is now just a compatibility alias for
ServerAliveInterval.
Diffstat (limited to 'sshconnect.c')
-rw-r--r-- | sshconnect.c | 105 |
1 files changed, 56 insertions, 49 deletions
diff --git a/sshconnect.c b/sshconnect.c index 5c56f3178..e0d1a8c7e 100644 --- a/sshconnect.c +++ b/sshconnect.c | |||
@@ -13,7 +13,7 @@ | |||
13 | */ | 13 | */ |
14 | 14 | ||
15 | #include "includes.h" | 15 | #include "includes.h" |
16 | RCSID("$OpenBSD: sshconnect.c,v 1.148 2003/09/18 07:52:54 markus Exp $"); | 16 | RCSID("$OpenBSD: sshconnect.c,v 1.156 2004/01/25 03:49:09 djm Exp $"); |
17 | 17 | ||
18 | #include <openssl/bn.h> | 18 | #include <openssl/bn.h> |
19 | 19 | ||
@@ -33,16 +33,12 @@ RCSID("$OpenBSD: sshconnect.c,v 1.148 2003/09/18 07:52:54 markus Exp $"); | |||
33 | #include "misc.h" | 33 | #include "misc.h" |
34 | #include "readpass.h" | 34 | #include "readpass.h" |
35 | 35 | ||
36 | #ifdef DNS | ||
37 | #include "dns.h" | 36 | #include "dns.h" |
38 | #endif | ||
39 | 37 | ||
40 | char *client_version_string = NULL; | 38 | char *client_version_string = NULL; |
41 | char *server_version_string = NULL; | 39 | char *server_version_string = NULL; |
42 | 40 | ||
43 | #ifdef DNS | 41 | int matching_host_key_dns = 0; |
44 | int verified_host_key_dns = 0; | ||
45 | #endif | ||
46 | 42 | ||
47 | /* import */ | 43 | /* import */ |
48 | extern Options options; | 44 | extern Options options; |
@@ -63,6 +59,7 @@ static void banner_alarm_catch (int signum) | |||
63 | } | 59 | } |
64 | 60 | ||
65 | static int show_other_keys(const char *, Key *); | 61 | static int show_other_keys(const char *, Key *); |
62 | static void warn_changed_key(Key *); | ||
66 | 63 | ||
67 | /* | 64 | /* |
68 | * Connect to the given ssh server using a proxy command. | 65 | * Connect to the given ssh server using a proxy command. |
@@ -84,7 +81,7 @@ ssh_proxy_connect(const char *host, u_short port, const char *proxy_command) | |||
84 | * Build the final command string in the buffer by making the | 81 | * Build the final command string in the buffer by making the |
85 | * appropriate substitutions to the given proxy command. | 82 | * appropriate substitutions to the given proxy command. |
86 | * | 83 | * |
87 | * Use "exec" to avoid "sh -c" processes on some platforms | 84 | * Use "exec" to avoid "sh -c" processes on some platforms |
88 | * (e.g. Solaris) | 85 | * (e.g. Solaris) |
89 | */ | 86 | */ |
90 | buffer_init(&command); | 87 | buffer_init(&command); |
@@ -241,12 +238,12 @@ timeout_connect(int sockfd, const struct sockaddr *serv_addr, | |||
241 | if (timeout <= 0) | 238 | if (timeout <= 0) |
242 | return (connect(sockfd, serv_addr, addrlen)); | 239 | return (connect(sockfd, serv_addr, addrlen)); |
243 | 240 | ||
244 | if (fcntl(sockfd, F_SETFL, O_NONBLOCK) < 0) | 241 | set_nonblock(sockfd); |
245 | return (-1); | ||
246 | |||
247 | rc = connect(sockfd, serv_addr, addrlen); | 242 | rc = connect(sockfd, serv_addr, addrlen); |
248 | if (rc == 0) | 243 | if (rc == 0) { |
244 | unset_nonblock(sockfd); | ||
249 | return (0); | 245 | return (0); |
246 | } | ||
250 | if (errno != EINPROGRESS) | 247 | if (errno != EINPROGRESS) |
251 | return (-1); | 248 | return (-1); |
252 | 249 | ||
@@ -271,15 +268,15 @@ timeout_connect(int sockfd, const struct sockaddr *serv_addr, | |||
271 | break; | 268 | break; |
272 | case -1: | 269 | case -1: |
273 | /* Select error */ | 270 | /* Select error */ |
274 | debug("select: %s", strerror(errno)); | 271 | debug("select: %s", strerror(errno)); |
275 | break; | 272 | break; |
276 | case 1: | 273 | case 1: |
277 | /* Completed or failed */ | 274 | /* Completed or failed */ |
278 | optval = 0; | 275 | optval = 0; |
279 | optlen = sizeof(optval); | 276 | optlen = sizeof(optval); |
280 | if (getsockopt(sockfd, SOL_SOCKET, SO_ERROR, &optval, | 277 | if (getsockopt(sockfd, SOL_SOCKET, SO_ERROR, &optval, |
281 | &optlen) == -1) { | 278 | &optlen) == -1) { |
282 | debug("getsockopt: %s", strerror(errno)); | 279 | debug("getsockopt: %s", strerror(errno)); |
283 | break; | 280 | break; |
284 | } | 281 | } |
285 | if (optval != 0) { | 282 | if (optval != 0) { |
@@ -287,6 +284,7 @@ timeout_connect(int sockfd, const struct sockaddr *serv_addr, | |||
287 | break; | 284 | break; |
288 | } | 285 | } |
289 | result = 0; | 286 | result = 0; |
287 | unset_nonblock(sockfd); | ||
290 | break; | 288 | break; |
291 | default: | 289 | default: |
292 | /* Should not occur */ | 290 | /* Should not occur */ |
@@ -425,8 +423,8 @@ ssh_connect(const char *host, struct sockaddr_storage * hostaddr, | |||
425 | 423 | ||
426 | debug("Connection established."); | 424 | debug("Connection established."); |
427 | 425 | ||
428 | /* Set keepalives if requested. */ | 426 | /* Set SO_KEEPALIVE if requested. */ |
429 | if (options.keepalives && | 427 | if (options.tcp_keep_alive && |
430 | setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, (void *)&on, | 428 | setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, (void *)&on, |
431 | sizeof(on)) < 0) | 429 | sizeof(on)) < 0) |
432 | error("setsockopt SO_KEEPALIVE: %.100s", strerror(errno)); | 430 | error("setsockopt SO_KEEPALIVE: %.100s", strerror(errno)); |
@@ -598,7 +596,7 @@ check_host_key(char *host, struct sockaddr *hostaddr, Key *host_key, | |||
598 | int readonly, const char *user_hostfile, const char *system_hostfile) | 596 | int readonly, const char *user_hostfile, const char *system_hostfile) |
599 | { | 597 | { |
600 | Key *file_key; | 598 | Key *file_key; |
601 | char *type = key_type(host_key); | 599 | const char *type = key_type(host_key); |
602 | char *ip = NULL; | 600 | char *ip = NULL; |
603 | char hostline[1000], *hostp, *fp; | 601 | char hostline[1000], *hostp, *fp; |
604 | HostStatus host_status; | 602 | HostStatus host_status; |
@@ -762,9 +760,8 @@ check_host_key(char *host, struct sockaddr *hostaddr, Key *host_key, | |||
762 | /* The default */ | 760 | /* The default */ |
763 | fp = key_fingerprint(host_key, SSH_FP_MD5, SSH_FP_HEX); | 761 | fp = key_fingerprint(host_key, SSH_FP_MD5, SSH_FP_HEX); |
764 | msg2[0] = '\0'; | 762 | msg2[0] = '\0'; |
765 | #ifdef DNS | ||
766 | if (options.verify_host_key_dns) { | 763 | if (options.verify_host_key_dns) { |
767 | if (verified_host_key_dns) | 764 | if (matching_host_key_dns) |
768 | snprintf(msg2, sizeof(msg2), | 765 | snprintf(msg2, sizeof(msg2), |
769 | "Matching host key fingerprint" | 766 | "Matching host key fingerprint" |
770 | " found in DNS.\n"); | 767 | " found in DNS.\n"); |
@@ -773,7 +770,6 @@ check_host_key(char *host, struct sockaddr *hostaddr, Key *host_key, | |||
773 | "No matching host key fingerprint" | 770 | "No matching host key fingerprint" |
774 | " found in DNS.\n"); | 771 | " found in DNS.\n"); |
775 | } | 772 | } |
776 | #endif | ||
777 | snprintf(msg, sizeof(msg), | 773 | snprintf(msg, sizeof(msg), |
778 | "The authenticity of host '%.200s (%s)' can't be " | 774 | "The authenticity of host '%.200s (%s)' can't be " |
779 | "established%s\n" | 775 | "established%s\n" |
@@ -823,20 +819,10 @@ check_host_key(char *host, struct sockaddr *hostaddr, Key *host_key, | |||
823 | error("Offending key for IP in %s:%d", ip_file, ip_line); | 819 | error("Offending key for IP in %s:%d", ip_file, ip_line); |
824 | } | 820 | } |
825 | /* The host key has changed. */ | 821 | /* The host key has changed. */ |
826 | fp = key_fingerprint(host_key, SSH_FP_MD5, SSH_FP_HEX); | 822 | warn_changed_key(host_key); |
827 | error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"); | ||
828 | error("@ WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! @"); | ||
829 | error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"); | ||
830 | error("IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!"); | ||
831 | error("Someone could be eavesdropping on you right now (man-in-the-middle attack)!"); | ||
832 | error("It is also possible that the %s host key has just been changed.", type); | ||
833 | error("The fingerprint for the %s key sent by the remote host is\n%s.", | ||
834 | type, fp); | ||
835 | error("Please contact your system administrator."); | ||
836 | error("Add correct host key in %.100s to get rid of this message.", | 823 | error("Add correct host key in %.100s to get rid of this message.", |
837 | user_hostfile); | 824 | user_hostfile); |
838 | error("Offending key in %s:%d", host_file, host_line); | 825 | error("Offending key in %s:%d", host_file, host_line); |
839 | xfree(fp); | ||
840 | 826 | ||
841 | /* | 827 | /* |
842 | * If strict host key checking is in use, the user will have | 828 | * If strict host key checking is in use, the user will have |
@@ -939,27 +925,27 @@ int | |||
939 | verify_host_key(char *host, struct sockaddr *hostaddr, Key *host_key) | 925 | verify_host_key(char *host, struct sockaddr *hostaddr, Key *host_key) |
940 | { | 926 | { |
941 | struct stat st; | 927 | struct stat st; |
928 | int flags = 0; | ||
942 | 929 | ||
943 | #ifdef DNS | 930 | if (options.verify_host_key_dns && |
944 | if (options.verify_host_key_dns) { | 931 | verify_host_key_dns(host, hostaddr, host_key, &flags) == 0) { |
945 | switch(verify_host_key_dns(host, hostaddr, host_key)) { | 932 | |
946 | case DNS_VERIFY_OK: | 933 | if (flags & DNS_VERIFY_FOUND) { |
947 | #ifdef DNSSEC | 934 | |
948 | return 0; | 935 | if (options.verify_host_key_dns == 1 && |
949 | #else | 936 | flags & DNS_VERIFY_MATCH && |
950 | verified_host_key_dns = 1; | 937 | flags & DNS_VERIFY_SECURE) |
951 | break; | 938 | return 0; |
952 | #endif | 939 | |
953 | case DNS_VERIFY_FAILED: | 940 | if (flags & DNS_VERIFY_MATCH) { |
954 | return -1; | 941 | matching_host_key_dns = 1; |
955 | case DNS_VERIFY_ERROR: | 942 | } else { |
956 | break; | 943 | warn_changed_key(host_key); |
957 | default: | 944 | error("Update the SSHFP RR in DNS with the new " |
958 | debug3("bad return value from verify_host_key_dns"); | 945 | "host key to get rid of this message."); |
959 | break; | 946 | } |
960 | } | 947 | } |
961 | } | 948 | } |
962 | #endif /* DNS */ | ||
963 | 949 | ||
964 | /* return ok if the key can be found in an old keyfile */ | 950 | /* return ok if the key can be found in an old keyfile */ |
965 | if (stat(options.system_hostfile2, &st) == 0 || | 951 | if (stat(options.system_hostfile2, &st) == 0 || |
@@ -1085,3 +1071,24 @@ show_other_keys(const char *host, Key *key) | |||
1085 | } | 1071 | } |
1086 | return (found); | 1072 | return (found); |
1087 | } | 1073 | } |
1074 | |||
1075 | static void | ||
1076 | warn_changed_key(Key *host_key) | ||
1077 | { | ||
1078 | char *fp; | ||
1079 | const char *type = key_type(host_key); | ||
1080 | |||
1081 | fp = key_fingerprint(host_key, SSH_FP_MD5, SSH_FP_HEX); | ||
1082 | |||
1083 | error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"); | ||
1084 | error("@ WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! @"); | ||
1085 | error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"); | ||
1086 | error("IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!"); | ||
1087 | error("Someone could be eavesdropping on you right now (man-in-the-middle attack)!"); | ||
1088 | error("It is also possible that the %s host key has just been changed.", type); | ||
1089 | error("The fingerprint for the %s key sent by the remote host is\n%s.", | ||
1090 | type, fp); | ||
1091 | error("Please contact your system administrator."); | ||
1092 | |||
1093 | xfree(fp); | ||
1094 | } | ||