X-Git-Url: http://andersk.mit.edu/gitweb/openssh.git/blobdiff_plain/6f901f8e9002f969058557209a37c121b94bf045..0608f8a76d47cd2ad0269dfa506e040cce5454bd:/sshconnect.c diff --git a/sshconnect.c b/sshconnect.c index f4301be3..16db13fa 100644 --- a/sshconnect.c +++ b/sshconnect.c @@ -13,7 +13,7 @@ */ #include "includes.h" -RCSID("$OpenBSD: sshconnect.c,v 1.128 2002/07/09 11:56:50 itojun Exp $"); +RCSID("$OpenBSD: sshconnect.c,v 1.138 2003/04/08 20:21:29 itojun Exp $"); #include @@ -41,21 +41,13 @@ extern Options options; extern char *__progname; extern uid_t original_real_uid; extern uid_t original_effective_uid; +extern pid_t proxy_command_pid; #ifndef INET6_ADDRSTRLEN /* for non IPv6 machines */ #define INET6_ADDRSTRLEN 46 #endif -static const char * -sockaddr_ntop(struct sockaddr *sa, socklen_t salen) -{ - static char addrbuf[NI_MAXHOST]; - - if (getnameinfo(sa, salen, addrbuf, sizeof(addrbuf), NULL, 0, - NI_NUMERICHOST) != 0) - fatal("sockaddr_ntop: getnameinfo NI_NUMERICHOST failed"); - return addrbuf; -} +static int show_other_keys(const char *, Key *); /* * 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) /* Convert the port number into a string. */ snprintf(strport, sizeof strport, "%hu", port); - /* Build the final command string in the buffer by making the - appropriate substitutions to the given proxy command. */ + /* + * Build the final command string in the buffer by making the + * appropriate substitutions to the given proxy command. + * + * Use "exec" to avoid "sh -c" processes on some platforms + * (e.g. Solaris) + */ buffer_init(&command); + buffer_append(&command, "exec ", 5); + for (cp = proxy_command; *cp; cp++) { if (cp[0] == '%' && cp[1] == '%') { buffer_append(&command, "%", 1); @@ -143,6 +142,8 @@ ssh_proxy_connect(const char *host, u_short port, const char *proxy_command) /* Parent. */ if (pid < 0) fatal("fork failed: %.100s", strerror(errno)); + else + proxy_command_pid = pid; /* save pid to clean up later */ /* Close child side of the descriptors. */ close(pin[0]); @@ -238,7 +239,6 @@ ssh_connect(const char *host, struct sockaddr_storage * hostaddr, int sock = -1, attempt; char ntop[NI_MAXHOST], strport[NI_MAXSERV]; struct addrinfo hints, *ai, *aitop; - struct linger linger; struct servent *sp; /* * Did we get only other errors than "Connection refused" (which @@ -247,7 +247,7 @@ ssh_connect(const char *host, struct sockaddr_storage * hostaddr, */ int full_failure = 1; - debug("ssh_connect: needpriv %d", needpriv); + debug2("ssh_connect: needpriv %d", needpriv); /* Get default port if port has not been set. */ if (port == 0) { @@ -307,11 +307,8 @@ ssh_connect(const char *host, struct sockaddr_storage * hostaddr, } else { if (errno == ECONNREFUSED) full_failure = 0; -#if 0 - log("ssh: connect to address %s port %s: %s", - sockaddr_ntop(ai->ai_addr, ai->ai_addrlen), - strport, strerror(errno)); -#endif + debug("connect to address %s port %s: %s", + ntop, strport, strerror(errno)); /* * Close the failed socket; there appear to * be some problems when reusing a socket for @@ -334,20 +331,14 @@ ssh_connect(const char *host, struct sockaddr_storage * hostaddr, freeaddrinfo(aitop); /* Return failure if we didn't get a successful connection. */ - if (attempt >= connection_attempts) + if (attempt >= connection_attempts) { + logit("ssh: connect to host %s port %s: %s", + host, strport, strerror(errno)); return full_failure ? ECONNABORTED : ECONNREFUSED; + } debug("Connection established."); - /* - * Set socket options. We would like the socket to disappear as soon - * as it has been closed for whatever reason. - */ - /* setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (void *)&on, sizeof(on)); */ - linger.l_onoff = 1; - linger.l_linger = 5; - setsockopt(sock, SOL_SOCKET, SO_LINGER, (void *)&linger, sizeof(linger)); - /* Set keepalives if requested. */ if (options.keepalives && setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, (void *)&on, @@ -430,7 +421,7 @@ ssh_exchange_identification(void) enable_compat13(); minor1 = 3; if (options.forward_agent) { - log("Agent forwarding disabled for protocol 1.3"); + logit("Agent forwarding disabled for protocol 1.3"); options.forward_agent = 0; } } @@ -505,7 +496,7 @@ check_host_key(char *host, struct sockaddr *hostaddr, Key *host_key, int salen; char ntop[NI_MAXHOST]; char msg[1024]; - int len, host_line, ip_line; + int len, host_line, ip_line, has_keys; const char *host_file = NULL, *ip_file = NULL; /* @@ -621,16 +612,16 @@ check_host_key(char *host, struct sockaddr *hostaddr, Key *host_key, debug("Found key in %s:%d", host_file, host_line); if (options.check_host_ip && ip_status == HOST_NEW) { if (readonly) - log("%s host key for IP address " + logit("%s host key for IP address " "'%.128s' not in list of known hosts.", type, ip); else if (!add_host_to_hostfile(user_hostfile, ip, host_key)) - log("Failed to add the %s host key for IP " + logit("Failed to add the %s host key for IP " "address '%.128s' to the list of known " "hosts (%.30s).", type, ip, user_hostfile); else - log("Warning: Permanently added the %s host " + logit("Warning: Permanently added the %s host " "key for IP address '%.128s' to the list " "of known hosts.", type, ip); } @@ -649,14 +640,19 @@ check_host_key(char *host, struct sockaddr *hostaddr, Key *host_key, "have requested strict checking.", type, host); goto fail; } else if (options.strict_host_key_checking == 2) { + has_keys = show_other_keys(host, host_key); /* The default */ fp = key_fingerprint(host_key, SSH_FP_MD5, SSH_FP_HEX); snprintf(msg, sizeof(msg), "The authenticity of host '%.200s (%s)' can't be " - "established.\n" + "established%s\n" "%s key fingerprint is %s.\n" "Are you sure you want to continue connecting " - "(yes/no)? ", host, ip, type, fp); + "(yes/no)? ", + host, ip, + has_keys ? ",\nbut keys of different type are already " + "known for this host." : ".", + type, fp); xfree(fp); if (!confirm(msg)) goto fail; @@ -672,10 +668,10 @@ check_host_key(char *host, struct sockaddr *hostaddr, Key *host_key, * local known_hosts file. */ if (!add_host_to_hostfile(user_hostfile, hostp, host_key)) - log("Failed to add the host to the list of known " + logit("Failed to add the host to the list of known " "hosts (%.500s).", user_hostfile); else - log("Warning: Permanently added '%.200s' (%s) to the " + logit("Warning: Permanently added '%.200s' (%s) to the " "list of known hosts.", hostp, type); break; case HOST_CHANGED: @@ -759,6 +755,9 @@ check_host_key(char *host, struct sockaddr *hostaddr, Key *host_key, * accept the authentication. */ break; + case HOST_FOUND: + fatal("internal error"); + break; } if (options.check_host_ip && host_status != HOST_CHANGED && @@ -775,7 +774,7 @@ check_host_key(char *host, struct sockaddr *hostaddr, Key *host_key, host_file, host_line); } if (options.strict_host_key_checking == 1) { - log(msg); + logit(msg); error("Exiting, you have requested strict checking."); goto fail; } else if (options.strict_host_key_checking == 2) { @@ -784,7 +783,7 @@ check_host_key(char *host, struct sockaddr *hostaddr, Key *host_key, if (!confirm(msg)) goto fail; } else { - log(msg); + logit(msg); } } @@ -870,3 +869,58 @@ ssh_put_password(char *password) memset(padded, 0, size); xfree(padded); } + +static int +show_key_from_file(const char *file, const char *host, int keytype) +{ + Key *found; + char *fp; + int line, ret; + + found = key_new(keytype); + if ((ret = lookup_key_in_hostfile_by_type(file, host, + keytype, found, &line))) { + fp = key_fingerprint(found, SSH_FP_MD5, SSH_FP_HEX); + logit("WARNING: %s key found for host %s\n" + "in %s:%d\n" + "%s key fingerprint %s.", + key_type(found), host, file, line, + key_type(found), fp); + xfree(fp); + } + key_free(found); + return (ret); +} + +/* print all known host keys for a given host, but skip keys of given type */ +static int +show_other_keys(const char *host, Key *key) +{ + int type[] = { KEY_RSA1, KEY_RSA, KEY_DSA, -1}; + int i, found = 0; + + for (i = 0; type[i] != -1; i++) { + if (type[i] == key->type) + continue; + if (type[i] != KEY_RSA1 && + show_key_from_file(options.user_hostfile2, host, type[i])) { + found = 1; + continue; + } + if (type[i] != KEY_RSA1 && + show_key_from_file(options.system_hostfile2, host, type[i])) { + found = 1; + continue; + } + if (show_key_from_file(options.user_hostfile, host, type[i])) { + found = 1; + continue; + } + if (show_key_from_file(options.system_hostfile, host, type[i])) { + found = 1; + continue; + } + debug2("no key of type %d for host %s", type[i], host); + } + return (found); +}