summaryrefslogtreecommitdiff
path: root/sshconnect.c
diff options
context:
space:
mode:
authorColin Watson <cjwatson@debian.org>2003-09-01 02:05:26 +0000
committerColin Watson <cjwatson@debian.org>2003-09-01 02:05:26 +0000
commit6d5a72bc1d98a42ba42f082e50a22e911c1d82d3 (patch)
tree1bf23174bdb6fc71e2846dda0eca195a418484e7 /sshconnect.c
parent2ee26b431f98cf1dc0e4fb9809ad1e0c879b8c08 (diff)
parent58657d96514cd6f16d82add8d6f4adbb36765758 (diff)
Debian release 3.5p1-1.
Diffstat (limited to 'sshconnect.c')
-rw-r--r--sshconnect.c120
1 files changed, 88 insertions, 32 deletions
diff --git a/sshconnect.c b/sshconnect.c
index 8eb5fda7d..95e0f6d77 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,6 +41,7 @@ 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
@@ -48,22 +49,13 @@ extern uid_t original_effective_uid;
48 49
49static sig_atomic_t banner_timedout; 50static sig_atomic_t banner_timedout;
50 51
51static const char *
52sockaddr_ntop(struct sockaddr *sa, socklen_t salen)
53{
54 static char addrbuf[NI_MAXHOST];
55
56 if (getnameinfo(sa, salen, addrbuf, sizeof(addrbuf), NULL, 0,
57 NI_NUMERICHOST) != 0)
58 fatal("sockaddr_ntop: getnameinfo NI_NUMERICHOST failed");
59 return addrbuf;
60}
61
62static void banner_alarm_catch (int signum) 52static void banner_alarm_catch (int signum)
63{ 53{
64 banner_timedout = 1; 54 banner_timedout = 1;
65} 55}
66 56
57static int show_other_keys(const char *, Key *);
58
67/* 59/*
68 * Connect to the given ssh server using a proxy command. 60 * Connect to the given ssh server using a proxy command.
69 */ 61 */
@@ -80,9 +72,16 @@ ssh_proxy_connect(const char *host, u_short port, const char *proxy_command)
80 /* Convert the port number into a string. */ 72 /* Convert the port number into a string. */
81 snprintf(strport, sizeof strport, "%hu", port); 73 snprintf(strport, sizeof strport, "%hu", port);
82 74
83 /* Build the final command string in the buffer by making the 75 /*
84 appropriate substitutions to the given proxy command. */ 76 * Build the final command string in the buffer by making the
77 * appropriate substitutions to the given proxy command.
78 *
79 * Use "exec" to avoid "sh -c" processes on some platforms
80 * (e.g. Solaris)
81 */
85 buffer_init(&command); 82 buffer_init(&command);
83 buffer_append(&command, "exec ", 5);
84
86 for (cp = proxy_command; *cp; cp++) { 85 for (cp = proxy_command; *cp; cp++) {
87 if (cp[0] == '%' && cp[1] == '%') { 86 if (cp[0] == '%' && cp[1] == '%') {
88 buffer_append(&command, "%", 1); 87 buffer_append(&command, "%", 1);
@@ -150,6 +149,8 @@ ssh_proxy_connect(const char *host, u_short port, const char *proxy_command)
150 /* Parent. */ 149 /* Parent. */
151 if (pid < 0) 150 if (pid < 0)
152 fatal("fork failed: %.100s", strerror(errno)); 151 fatal("fork failed: %.100s", strerror(errno));
152 else
153 proxy_command_pid = pid; /* save pid to clean up later */
153 154
154 /* Close child side of the descriptors. */ 155 /* Close child side of the descriptors. */
155 close(pin[0]); 156 close(pin[0]);
@@ -245,7 +246,6 @@ ssh_connect(const char *host, struct sockaddr_storage * hostaddr,
245 int sock = -1, attempt; 246 int sock = -1, attempt;
246 char ntop[NI_MAXHOST], strport[NI_MAXSERV]; 247 char ntop[NI_MAXHOST], strport[NI_MAXSERV];
247 struct addrinfo hints, *ai, *aitop; 248 struct addrinfo hints, *ai, *aitop;
248 struct linger linger;
249 struct servent *sp; 249 struct servent *sp;
250 /* 250 /*
251 * Did we get only other errors than "Connection refused" (which 251 * Did we get only other errors than "Connection refused" (which
@@ -314,9 +314,8 @@ ssh_connect(const char *host, struct sockaddr_storage * hostaddr,
314 } else { 314 } else {
315 if (errno == ECONNREFUSED) 315 if (errno == ECONNREFUSED)
316 full_failure = 0; 316 full_failure = 0;
317 log("ssh: connect to address %s port %s: %s", 317 debug("connect to address %s port %s: %s",
318 sockaddr_ntop(ai->ai_addr, ai->ai_addrlen), 318 ntop, strport, strerror(errno));
319 strport, strerror(errno));
320 /* 319 /*
321 * Close the failed socket; there appear to 320 * Close the failed socket; there appear to
322 * be some problems when reusing a socket for 321 * be some problems when reusing a socket for
@@ -339,20 +338,14 @@ ssh_connect(const char *host, struct sockaddr_storage * hostaddr,
339 freeaddrinfo(aitop); 338 freeaddrinfo(aitop);
340 339
341 /* Return failure if we didn't get a successful connection. */ 340 /* Return failure if we didn't get a successful connection. */
342 if (attempt >= connection_attempts) 341 if (attempt >= connection_attempts) {
342 log("ssh: connect to host %s port %s: %s",
343 host, strport, strerror(errno));
343 return full_failure ? ECONNABORTED : ECONNREFUSED; 344 return full_failure ? ECONNABORTED : ECONNREFUSED;
345 }
344 346
345 debug("Connection established."); 347 debug("Connection established.");
346 348
347 /*
348 * Set socket options. We would like the socket to disappear as soon
349 * as it has been closed for whatever reason.
350 */
351 /* setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (void *)&on, sizeof(on)); */
352 linger.l_onoff = 1;
353 linger.l_linger = 5;
354 setsockopt(sock, SOL_SOCKET, SO_LINGER, (void *)&linger, sizeof(linger));
355
356 /* Set keepalives if requested. */ 349 /* Set keepalives if requested. */
357 if (options.keepalives && 350 if (options.keepalives &&
358 setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, (void *)&on, 351 setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, (void *)&on,
@@ -508,7 +501,7 @@ confirm(const char *prompt)
508 (p[0] == '\0') || (p[0] == '\n') || 501 (p[0] == '\0') || (p[0] == '\n') ||
509 strncasecmp(p, "no", 2) == 0) 502 strncasecmp(p, "no", 2) == 0)
510 ret = 0; 503 ret = 0;
511 if (strncasecmp(p, "yes", 3) == 0) 504 if (p && strncasecmp(p, "yes", 3) == 0)
512 ret = 1; 505 ret = 1;
513 if (p) 506 if (p)
514 xfree(p); 507 xfree(p);
@@ -535,7 +528,7 @@ check_host_key(char *host, struct sockaddr *hostaddr, Key *host_key,
535 int salen; 528 int salen;
536 char ntop[NI_MAXHOST]; 529 char ntop[NI_MAXHOST];
537 char msg[1024]; 530 char msg[1024];
538 int len, host_line, ip_line; 531 int len, host_line, ip_line, has_keys;
539 const char *host_file = NULL, *ip_file = NULL; 532 const char *host_file = NULL, *ip_file = NULL;
540 533
541 /* 534 /*
@@ -679,14 +672,19 @@ check_host_key(char *host, struct sockaddr *hostaddr, Key *host_key,
679 "have requested strict checking.", type, host); 672 "have requested strict checking.", type, host);
680 goto fail; 673 goto fail;
681 } else if (options.strict_host_key_checking == 2) { 674 } else if (options.strict_host_key_checking == 2) {
675 has_keys = show_other_keys(host, host_key);
682 /* The default */ 676 /* The default */
683 fp = key_fingerprint(host_key, SSH_FP_MD5, SSH_FP_HEX); 677 fp = key_fingerprint(host_key, SSH_FP_MD5, SSH_FP_HEX);
684 snprintf(msg, sizeof(msg), 678 snprintf(msg, sizeof(msg),
685 "The authenticity of host '%.200s (%s)' can't be " 679 "The authenticity of host '%.200s (%s)' can't be "
686 "established.\n" 680 "established%s\n"
687 "%s key fingerprint is %s.\n" 681 "%s key fingerprint is %s.\n"
688 "Are you sure you want to continue connecting " 682 "Are you sure you want to continue connecting "
689 "(yes/no)? ", host, ip, type, fp); 683 "(yes/no)? ",
684 host, ip,
685 has_keys ? ",\nbut keys of different type are already "
686 "known for this host." : ".",
687 type, fp);
690 xfree(fp); 688 xfree(fp);
691 if (!confirm(msg)) 689 if (!confirm(msg))
692 goto fail; 690 goto fail;
@@ -789,6 +787,9 @@ check_host_key(char *host, struct sockaddr *hostaddr, Key *host_key,
789 * accept the authentication. 787 * accept the authentication.
790 */ 788 */
791 break; 789 break;
790 case HOST_FOUND:
791 fatal("internal error");
792 break;
792 } 793 }
793 794
794 if (options.check_host_ip && host_status != HOST_CHANGED && 795 if (options.check_host_ip && host_status != HOST_CHANGED &&
@@ -900,3 +901,58 @@ ssh_put_password(char *password)
900 memset(padded, 0, size); 901 memset(padded, 0, size);
901 xfree(padded); 902 xfree(padded);
902} 903}
904
905static int
906show_key_from_file(const char *file, const char *host, int keytype)
907{
908 Key *found;
909 char *fp;
910 int line, ret;
911
912 found = key_new(keytype);
913 if ((ret = lookup_key_in_hostfile_by_type(file, host,
914 keytype, found, &line))) {
915 fp = key_fingerprint(found, SSH_FP_MD5, SSH_FP_HEX);
916 log("WARNING: %s key found for host %s\n"
917 "in %s:%d\n"
918 "%s key fingerprint %s.",
919 key_type(found), host, file, line,
920 key_type(found), fp);
921 xfree(fp);
922 }
923 key_free(found);
924 return (ret);
925}
926
927/* print all known host keys for a given host, but skip keys of given type */
928static int
929show_other_keys(const char *host, Key *key)
930{
931 int type[] = { KEY_RSA1, KEY_RSA, KEY_DSA, -1};
932 int i, found = 0;
933
934 for (i = 0; type[i] != -1; i++) {
935 if (type[i] == key->type)
936 continue;
937 if (type[i] != KEY_RSA1 &&
938 show_key_from_file(options.user_hostfile2, host, type[i])) {
939 found = 1;
940 continue;
941 }
942 if (type[i] != KEY_RSA1 &&
943 show_key_from_file(options.system_hostfile2, host, type[i])) {
944 found = 1;
945 continue;
946 }
947 if (show_key_from_file(options.user_hostfile, host, type[i])) {
948 found = 1;
949 continue;
950 }
951 if (show_key_from_file(options.system_hostfile, host, type[i])) {
952 found = 1;
953 continue;
954 }
955 debug2("no key of type %d for host %s", type[i], host);
956 }
957 return (found);
958}