diff options
Diffstat (limited to 'crypto/openssh/sshconnect.c')
-rw-r--r-- | crypto/openssh/sshconnect.c | 110 |
1 files changed, 82 insertions, 28 deletions
diff --git a/crypto/openssh/sshconnect.c b/crypto/openssh/sshconnect.c index 88ea7be..44bfa2d 100644 --- a/crypto/openssh/sshconnect.c +++ b/crypto/openssh/sshconnect.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sshconnect.c,v 1.251 2014/07/15 15:54:14 millert Exp $ */ +/* $OpenBSD: sshconnect.c,v 1.259 2015/01/28 22:36:00 djm Exp $ */ /* * Author: Tatu Ylonen <ylo@cs.hut.fi> * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland @@ -16,6 +16,7 @@ #include "includes.h" __RCSID("$FreeBSD$"); +#include <sys/param.h> /* roundup */ #include <sys/types.h> #include <sys/wait.h> #include <sys/stat.h> @@ -64,6 +65,8 @@ __RCSID("$FreeBSD$"); #include "monitor_fdpass.h" #include "ssh2.h" #include "version.h" +#include "authfile.h" +#include "ssherr.h" char *client_version_string = NULL; char *server_version_string = NULL; @@ -626,7 +629,7 @@ ssh_exchange_identification(int timeout_ms) debug("Remote protocol version %d.%d, remote software version %.100s", remote_major, remote_minor, remote_version); - compat_datafellows(remote_version); + active_state->compat = compat_datafellows(remote_version); mismatch = 0; switch (remote_major) { @@ -768,7 +771,7 @@ get_hostfile_hostname_ipaddr(char *hostname, struct sockaddr *hostaddr, if (options.proxy_command == NULL) { if (getnameinfo(hostaddr, addrlen, ntop, sizeof(ntop), NULL, 0, NI_NUMERICHOST) != 0) - fatal("check_host_key: getnameinfo failed"); + fatal("%s: getnameinfo failed", __func__); *hostfile_ipaddr = put_host_port(ntop, port); } else { *hostfile_ipaddr = xstrdup("<no hostip for proxy " @@ -816,6 +819,7 @@ check_host_key(char *hostname, struct sockaddr *hostaddr, u_short port, int len, cancelled_forwarding = 0; int local = sockaddr_is_local(hostaddr); int r, want_cert = key_is_cert(host_key), host_ip_differ = 0; + int hostkey_trusted = 0; /* Known or explicitly accepted by user */ struct hostkeys *host_hostkeys, *ip_hostkeys; u_int i; @@ -916,13 +920,17 @@ check_host_key(char *hostname, struct sockaddr *hostaddr, u_short port, "key for IP address '%.128s' to the list " "of known hosts.", type, ip); } else if (options.visual_host_key) { - fp = key_fingerprint(host_key, SSH_FP_MD5, SSH_FP_HEX); - ra = key_fingerprint(host_key, SSH_FP_MD5, - SSH_FP_RANDOMART); + fp = sshkey_fingerprint(host_key, + options.fingerprint_hash, SSH_FP_DEFAULT); + ra = sshkey_fingerprint(host_key, + options.fingerprint_hash, SSH_FP_RANDOMART); + if (fp == NULL || ra == NULL) + fatal("%s: sshkey_fingerprint fail", __func__); logit("Host key fingerprint is %s\n%s\n", fp, ra); free(ra); free(fp); } + hostkey_trusted = 1; break; case HOST_NEW: if (options.host_key_alias == NULL && port != 0 && @@ -957,9 +965,12 @@ check_host_key(char *hostname, struct sockaddr *hostaddr, u_short port, else snprintf(msg1, sizeof(msg1), "."); /* The default */ - fp = key_fingerprint(host_key, SSH_FP_MD5, SSH_FP_HEX); - ra = key_fingerprint(host_key, SSH_FP_MD5, - SSH_FP_RANDOMART); + fp = sshkey_fingerprint(host_key, + options.fingerprint_hash, SSH_FP_DEFAULT); + ra = sshkey_fingerprint(host_key, + options.fingerprint_hash, SSH_FP_RANDOMART); + if (fp == NULL || ra == NULL) + fatal("%s: sshkey_fingerprint fail", __func__); msg2[0] = '\0'; if (options.verify_host_key_dns) { if (matching_host_key_dns) @@ -985,6 +996,7 @@ check_host_key(char *hostname, struct sockaddr *hostaddr, u_short port, free(fp); if (!confirm(msg)) goto fail; + hostkey_trusted = 1; /* user explicitly confirmed */ } /* * If not in strict mode, add the key automatically to the @@ -1183,6 +1195,12 @@ check_host_key(char *hostname, struct sockaddr *hostaddr, u_short port, } } + if (!hostkey_trusted && options.update_hostkeys) { + debug("%s: hostkey not known or explicitly trusted: " + "disabling UpdateHostkeys", __func__); + options.update_hostkeys = 0; + } + free(ip); free(host); if (host_hostkeys != NULL) @@ -1220,16 +1238,45 @@ int verify_host_key(char *host, struct sockaddr *hostaddr, Key *host_key) { int r = -1, flags = 0; - char *fp; - Key *plain = NULL; + char *fp = NULL; + struct sshkey *plain = NULL; + + if ((fp = sshkey_fingerprint(host_key, + options.fingerprint_hash, SSH_FP_DEFAULT)) == NULL) { + error("%s: fingerprint host key: %s", __func__, ssh_err(r)); + r = -1; + goto out; + } - fp = key_fingerprint(host_key, SSH_FP_MD5, SSH_FP_HEX); - debug("Server host key: %s %s", key_type(host_key), fp); - free(fp); + debug("Server host key: %s %s", + compat20 ? sshkey_ssh_name(host_key) : sshkey_type(host_key), fp); - if (key_equal(previous_host_key, host_key)) { - debug("%s: server host key matches cached key", __func__); - return 0; + if (sshkey_equal(previous_host_key, host_key)) { + debug2("%s: server host key %s %s matches cached key", + __func__, sshkey_type(host_key), fp); + r = 0; + goto out; + } + + /* Check in RevokedHostKeys file if specified */ + if (options.revoked_host_keys != NULL) { + r = sshkey_check_revoked(host_key, options.revoked_host_keys); + switch (r) { + case 0: + break; /* not revoked */ + case SSH_ERR_KEY_REVOKED: + error("Host key %s %s revoked by file %s", + sshkey_type(host_key), fp, + options.revoked_host_keys); + r = -1; + goto out; + default: + error("Error checking host key %s %s in " + "revoked keys file %s: %s", sshkey_type(host_key), + fp, options.revoked_host_keys, ssh_err(r)); + r = -1; + goto out; + } } if (options.verify_host_key_dns) { @@ -1237,17 +1284,17 @@ verify_host_key(char *host, struct sockaddr *hostaddr, Key *host_key) * XXX certs are not yet supported for DNS, so downgrade * them and try the plain key. */ - plain = key_from_private(host_key); - if (key_is_cert(plain)) - key_drop_cert(plain); + if ((r = sshkey_from_private(host_key, &plain)) != 0) + goto out; + if (sshkey_is_cert(plain)) + sshkey_drop_cert(plain); if (verify_host_key_dns(host, hostaddr, plain, &flags) == 0) { if (flags & DNS_VERIFY_FOUND) { if (options.verify_host_key_dns == 1 && flags & DNS_VERIFY_MATCH && flags & DNS_VERIFY_SECURE) { - key_free(plain); r = 0; - goto done; + goto out; } if (flags & DNS_VERIFY_MATCH) { matching_host_key_dns = 1; @@ -1259,14 +1306,14 @@ verify_host_key(char *host, struct sockaddr *hostaddr, Key *host_key) } } } - key_free(plain); } - r = check_host_key(host, hostaddr, options.port, host_key, RDRW, options.user_hostfiles, options.num_user_hostfiles, options.system_hostfiles, options.num_system_hostfiles); -done: +out: + sshkey_free(plain); + free(fp); if (r == 0 && host_key != NULL) { key_free(previous_host_key); previous_host_key = key_from_private(host_key); @@ -1357,8 +1404,12 @@ show_other_keys(struct hostkeys *hostkeys, Key *key) continue; if (!lookup_key_in_hostkeys_by_type(hostkeys, type[i], &found)) continue; - fp = key_fingerprint(found->key, SSH_FP_MD5, SSH_FP_HEX); - ra = key_fingerprint(found->key, SSH_FP_MD5, SSH_FP_RANDOMART); + fp = sshkey_fingerprint(found->key, + options.fingerprint_hash, SSH_FP_DEFAULT); + ra = sshkey_fingerprint(found->key, + options.fingerprint_hash, SSH_FP_RANDOMART); + if (fp == NULL || ra == NULL) + fatal("%s: sshkey_fingerprint fail", __func__); logit("WARNING: %s key found for host %s\n" "in %s:%lu\n" "%s key fingerprint %s.", @@ -1379,7 +1430,10 @@ warn_changed_key(Key *host_key) { char *fp; - fp = key_fingerprint(host_key, SSH_FP_MD5, SSH_FP_HEX); + fp = sshkey_fingerprint(host_key, options.fingerprint_hash, + SSH_FP_DEFAULT); + if (fp == NULL) + fatal("%s: sshkey_fingerprint fail", __func__); error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"); error("@ WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! @"); |