summaryrefslogtreecommitdiff
path: root/sshconnect.c
diff options
context:
space:
mode:
Diffstat (limited to 'sshconnect.c')
-rw-r--r--sshconnect.c118
1 files changed, 87 insertions, 31 deletions
diff --git a/sshconnect.c b/sshconnect.c
index b89321fb8..776d72065 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.126 2002/06/23 03:30:17 deraadt Exp $"); 16RCSID("$OpenBSD: sshconnect.c,v 1.135 2002/09/19 01:58:18 djm Exp $");
17 17
18#include <openssl/bn.h> 18#include <openssl/bn.h>
19 19
@@ -41,21 +41,13 @@ extern Options options;
41extern char *__progname; 41extern char *__progname;
42extern uid_t original_real_uid; 42extern uid_t original_real_uid;
43extern uid_t original_effective_uid; 43extern uid_t original_effective_uid;
44extern pid_t proxy_command_pid;
44 45
45#ifndef INET6_ADDRSTRLEN /* for non IPv6 machines */ 46#ifndef INET6_ADDRSTRLEN /* for non IPv6 machines */
46#define INET6_ADDRSTRLEN 46 47#define INET6_ADDRSTRLEN 46
47#endif 48#endif
48 49
49static const char * 50static int show_other_keys(const char *, Key *);
50sockaddr_ntop(struct sockaddr *sa, socklen_t salen)
51{
52 static char addrbuf[NI_MAXHOST];
53
54 if (getnameinfo(sa, salen, addrbuf, sizeof(addrbuf), NULL, 0,
55 NI_NUMERICHOST) != 0)
56 fatal("sockaddr_ntop: getnameinfo NI_NUMERICHOST failed");
57 return addrbuf;
58}
59 51
60/* 52/*
61 * Connect to the given ssh server using a proxy command. 53 * Connect to the given ssh server using a proxy command.
@@ -73,9 +65,16 @@ ssh_proxy_connect(const char *host, u_short port, const char *proxy_command)
73 /* Convert the port number into a string. */ 65 /* Convert the port number into a string. */
74 snprintf(strport, sizeof strport, "%hu", port); 66 snprintf(strport, sizeof strport, "%hu", port);
75 67
76 /* Build the final command string in the buffer by making the 68 /*
77 appropriate substitutions to the given proxy command. */ 69 * Build the final command string in the buffer by making the
70 * appropriate substitutions to the given proxy command.
71 *
72 * Use "exec" to avoid "sh -c" processes on some platforms
73 * (e.g. Solaris)
74 */
78 buffer_init(&command); 75 buffer_init(&command);
76 buffer_append(&command, "exec ", 5);
77
79 for (cp = proxy_command; *cp; cp++) { 78 for (cp = proxy_command; *cp; cp++) {
80 if (cp[0] == '%' && cp[1] == '%') { 79 if (cp[0] == '%' && cp[1] == '%') {
81 buffer_append(&command, "%", 1); 80 buffer_append(&command, "%", 1);
@@ -143,6 +142,8 @@ ssh_proxy_connect(const char *host, u_short port, const char *proxy_command)
143 /* Parent. */ 142 /* Parent. */
144 if (pid < 0) 143 if (pid < 0)
145 fatal("fork failed: %.100s", strerror(errno)); 144 fatal("fork failed: %.100s", strerror(errno));
145 else
146 proxy_command_pid = pid; /* save pid to clean up later */
146 147
147 /* Close child side of the descriptors. */ 148 /* Close child side of the descriptors. */
148 close(pin[0]); 149 close(pin[0]);
@@ -238,7 +239,6 @@ ssh_connect(const char *host, struct sockaddr_storage * hostaddr,
238 int sock = -1, attempt; 239 int sock = -1, attempt;
239 char ntop[NI_MAXHOST], strport[NI_MAXSERV]; 240 char ntop[NI_MAXHOST], strport[NI_MAXSERV];
240 struct addrinfo hints, *ai, *aitop; 241 struct addrinfo hints, *ai, *aitop;
241 struct linger linger;
242 struct servent *sp; 242 struct servent *sp;
243 /* 243 /*
244 * Did we get only other errors than "Connection refused" (which 244 * Did we get only other errors than "Connection refused" (which
@@ -307,9 +307,8 @@ ssh_connect(const char *host, struct sockaddr_storage * hostaddr,
307 } else { 307 } else {
308 if (errno == ECONNREFUSED) 308 if (errno == ECONNREFUSED)
309 full_failure = 0; 309 full_failure = 0;
310 log("ssh: connect to address %s port %s: %s", 310 debug("connect to address %s port %s: %s",
311 sockaddr_ntop(ai->ai_addr, ai->ai_addrlen), 311 ntop, strport, strerror(errno));
312 strport, strerror(errno));
313 /* 312 /*
314 * Close the failed socket; there appear to 313 * Close the failed socket; there appear to
315 * be some problems when reusing a socket for 314 * be some problems when reusing a socket for
@@ -332,20 +331,14 @@ ssh_connect(const char *host, struct sockaddr_storage * hostaddr,
332 freeaddrinfo(aitop); 331 freeaddrinfo(aitop);
333 332
334 /* Return failure if we didn't get a successful connection. */ 333 /* Return failure if we didn't get a successful connection. */
335 if (attempt >= connection_attempts) 334 if (attempt >= connection_attempts) {
335 log("ssh: connect to host %s port %s: %s",
336 host, strport, strerror(errno));
336 return full_failure ? ECONNABORTED : ECONNREFUSED; 337 return full_failure ? ECONNABORTED : ECONNREFUSED;
338 }
337 339
338 debug("Connection established."); 340 debug("Connection established.");
339 341
340 /*
341 * Set socket options. We would like the socket to disappear as soon
342 * as it has been closed for whatever reason.
343 */
344 /* setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (void *)&on, sizeof(on)); */
345 linger.l_onoff = 1;
346 linger.l_linger = 5;
347 setsockopt(sock, SOL_SOCKET, SO_LINGER, (void *)&linger, sizeof(linger));
348
349 /* Set keepalives if requested. */ 342 /* Set keepalives if requested. */
350 if (options.keepalives && 343 if (options.keepalives &&
351 setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, (void *)&on, 344 setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, (void *)&on,
@@ -476,7 +469,7 @@ confirm(const char *prompt)
476 (p[0] == '\0') || (p[0] == '\n') || 469 (p[0] == '\0') || (p[0] == '\n') ||
477 strncasecmp(p, "no", 2) == 0) 470 strncasecmp(p, "no", 2) == 0)
478 ret = 0; 471 ret = 0;
479 if (strncasecmp(p, "yes", 3) == 0) 472 if (p && strncasecmp(p, "yes", 3) == 0)
480 ret = 1; 473 ret = 1;
481 if (p) 474 if (p)
482 xfree(p); 475 xfree(p);
@@ -503,7 +496,7 @@ check_host_key(char *host, struct sockaddr *hostaddr, Key *host_key,
503 int salen; 496 int salen;
504 char ntop[NI_MAXHOST]; 497 char ntop[NI_MAXHOST];
505 char msg[1024]; 498 char msg[1024];
506 int len, host_line, ip_line; 499 int len, host_line, ip_line, has_keys;
507 const char *host_file = NULL, *ip_file = NULL; 500 const char *host_file = NULL, *ip_file = NULL;
508 501
509 /* 502 /*
@@ -647,14 +640,19 @@ check_host_key(char *host, struct sockaddr *hostaddr, Key *host_key,
647 "have requested strict checking.", type, host); 640 "have requested strict checking.", type, host);
648 goto fail; 641 goto fail;
649 } else if (options.strict_host_key_checking == 2) { 642 } else if (options.strict_host_key_checking == 2) {
643 has_keys = show_other_keys(host, host_key);
650 /* The default */ 644 /* The default */
651 fp = key_fingerprint(host_key, SSH_FP_MD5, SSH_FP_HEX); 645 fp = key_fingerprint(host_key, SSH_FP_MD5, SSH_FP_HEX);
652 snprintf(msg, sizeof(msg), 646 snprintf(msg, sizeof(msg),
653 "The authenticity of host '%.200s (%s)' can't be " 647 "The authenticity of host '%.200s (%s)' can't be "
654 "established.\n" 648 "established%s\n"
655 "%s key fingerprint is %s.\n" 649 "%s key fingerprint is %s.\n"
656 "Are you sure you want to continue connecting " 650 "Are you sure you want to continue connecting "
657 "(yes/no)? ", host, ip, type, fp); 651 "(yes/no)? ",
652 host, ip,
653 has_keys ? ",\nbut keys of different type are already "
654 "known for this host." : ".",
655 type, fp);
658 xfree(fp); 656 xfree(fp);
659 if (!confirm(msg)) 657 if (!confirm(msg))
660 goto fail; 658 goto fail;
@@ -757,6 +755,9 @@ check_host_key(char *host, struct sockaddr *hostaddr, Key *host_key,
757 * accept the authentication. 755 * accept the authentication.
758 */ 756 */
759 break; 757 break;
758 case HOST_FOUND:
759 fatal("internal error");
760 break;
760 } 761 }
761 762
762 if (options.check_host_ip && host_status != HOST_CHANGED && 763 if (options.check_host_ip && host_status != HOST_CHANGED &&
@@ -868,3 +869,58 @@ ssh_put_password(char *password)
868 memset(padded, 0, size); 869 memset(padded, 0, size);
869 xfree(padded); 870 xfree(padded);
870} 871}
872
873static int
874show_key_from_file(const char *file, const char *host, int keytype)
875{
876 Key *found;
877 char *fp;
878 int line, ret;
879
880 found = key_new(keytype);
881 if ((ret = lookup_key_in_hostfile_by_type(file, host,
882 keytype, found, &line))) {
883 fp = key_fingerprint(found, SSH_FP_MD5, SSH_FP_HEX);
884 log("WARNING: %s key found for host %s\n"
885 "in %s:%d\n"
886 "%s key fingerprint %s.",
887 key_type(found), host, file, line,
888 key_type(found), fp);
889 xfree(fp);
890 }
891 key_free(found);
892 return (ret);
893}
894
895/* print all known host keys for a given host, but skip keys of given type */
896static int
897show_other_keys(const char *host, Key *key)
898{
899 int type[] = { KEY_RSA1, KEY_RSA, KEY_DSA, -1};
900 int i, found = 0;
901
902 for (i = 0; type[i] != -1; i++) {
903 if (type[i] == key->type)
904 continue;
905 if (type[i] != KEY_RSA1 &&
906 show_key_from_file(options.user_hostfile2, host, type[i])) {
907 found = 1;
908 continue;
909 }
910 if (type[i] != KEY_RSA1 &&
911 show_key_from_file(options.system_hostfile2, host, type[i])) {
912 found = 1;
913 continue;
914 }
915 if (show_key_from_file(options.user_hostfile, host, type[i])) {
916 found = 1;
917 continue;
918 }
919 if (show_key_from_file(options.system_hostfile, host, type[i])) {
920 found = 1;
921 continue;
922 }
923 debug2("no key of type %d for host %s", type[i], host);
924 }
925 return (found);
926}