From 08a63152deb5deda168aaef870bdb9f56425acb3 Mon Sep 17 00:00:00 2001 From: Matthew Vernon Date: Wed, 26 Mar 2014 15:32:23 +0000 Subject: Attempt SSHFP lookup even if server presents a certificate If an ssh server presents a certificate to the client, then the client does not check the DNS for SSHFP records. This means that a malicious server can essentially disable DNS-host-key-checking, which means the client will fall back to asking the user (who will just say "yes" to the fingerprint, sadly). This patch is by Damien Miller (of openssh upstream). It's simpler than the patch by Mark Wooding which I applied yesterday; a copy is taken of the proffered key/cert, the key extracted from the cert (if necessary), and then the DNS consulted. Signed-off-by: Matthew Vernon Bug-Debian: http://bugs.debian.org/742513 Patch-Name: sshfp_with_server_cert_upstr --- sshconnect.c | 42 ++++++++++++++++++++++++++---------------- 1 file changed, 26 insertions(+), 16 deletions(-) diff --git a/sshconnect.c b/sshconnect.c index 87c3770..324f5e0 100644 --- a/sshconnect.c +++ b/sshconnect.c @@ -1224,29 +1224,39 @@ verify_host_key(char *host, struct sockaddr *hostaddr, Key *host_key) { int flags = 0; char *fp; + Key *plain = NULL; fp = key_fingerprint(host_key, SSH_FP_MD5, SSH_FP_HEX); debug("Server host key: %s %s", key_type(host_key), fp); free(fp); - /* XXX certs are not yet supported for DNS */ - if (!key_is_cert(host_key) && options.verify_host_key_dns && - verify_host_key_dns(host, hostaddr, host_key, &flags) == 0) { - if (flags & DNS_VERIFY_FOUND) { - - if (options.verify_host_key_dns == 1 && - flags & DNS_VERIFY_MATCH && - flags & DNS_VERIFY_SECURE) - return 0; - - if (flags & DNS_VERIFY_MATCH) { - matching_host_key_dns = 1; - } else { - warn_changed_key(host_key); - error("Update the SSHFP RR in DNS with the new " - "host key to get rid of this message."); + if (options.verify_host_key_dns) { + /* + * 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 (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); + return 0; + } + if (flags & DNS_VERIFY_MATCH) { + matching_host_key_dns = 1; + } else { + warn_changed_key(plain); + error("Update the SSHFP RR in DNS " + "with the new host key to get rid " + "of this message."); + } } } + key_free(plain); } return check_host_key(host, hostaddr, options.port, host_key, RDRW,