summaryrefslogtreecommitdiff
path: root/sshconnect.c
diff options
context:
space:
mode:
authorColin Watson <cjwatson@debian.org>2004-03-01 02:25:32 +0000
committerColin Watson <cjwatson@debian.org>2004-03-01 02:25:32 +0000
commitea8116a11e3de70036dbc665ccb0d486cf89cac9 (patch)
treed73ccdff78d8608e156465af42e6a1b3527fb2d6 /sshconnect.c
parente39b311381a5609cc05acf298c42fba196dc524b (diff)
parentf5bda272678ec6dccaa5f29379cf60cb855018e8 (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.c105
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"
16RCSID("$OpenBSD: sshconnect.c,v 1.148 2003/09/18 07:52:54 markus Exp $"); 16RCSID("$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
40char *client_version_string = NULL; 38char *client_version_string = NULL;
41char *server_version_string = NULL; 39char *server_version_string = NULL;
42 40
43#ifdef DNS 41int matching_host_key_dns = 0;
44int verified_host_key_dns = 0;
45#endif
46 42
47/* import */ 43/* import */
48extern Options options; 44extern Options options;
@@ -63,6 +59,7 @@ static void banner_alarm_catch (int signum)
63} 59}
64 60
65static int show_other_keys(const char *, Key *); 61static int show_other_keys(const char *, Key *);
62static 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
939verify_host_key(char *host, struct sockaddr *hostaddr, Key *host_key) 925verify_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
1075static void
1076warn_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}