File openssh-6.6p1-check_sshfp_for_certs.patch of Package openssh.890
# HG changeset patch
# Parent 407e4fb702d5d36a8e713c4528cccf3bb0f772d1
# 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 means that the ssh client will, if necessary, extract the
# server key from the proffered certificate, and attempt to verify it
# against the DNS.
#
# original patch by Mark Wooding <mdw@distorted.org.uk>
# modified and tested for Debian by Matthew Vernon <mcv21@cam.ac.uk>
#
# Bug-Debian: http://bugs.debian.org/742513
# CVE-2014-2653
# bnc#870532
diff --git a/openssh-6.6p1/sshconnect.c b/openssh-6.6p1/sshconnect.c
--- a/openssh-6.6p1/sshconnect.c
+++ b/openssh-6.6p1/sshconnect.c
@@ -1213,46 +1213,73 @@ fail:
free(host);
if (host_hostkeys != NULL)
free_hostkeys(host_hostkeys);
if (ip_hostkeys != NULL)
free_hostkeys(ip_hostkeys);
return -1;
}
+static int
+check_host_key_sshfp(char *host, struct sockaddr *hostaddr, Key *host_key)
+{
+ int rc = -1;
+ int flags = 0;
+ Key *raw_key = NULL;
+
+ if (!options.verify_host_key_dns)
+ goto done;
+
+ /* XXX certs are not yet supported for DNS; try looking the raw key
+ * up in the DNS anyway.
+ */
+ if (key_is_cert(host_key)) {
+ debug2("Extracting key from cert for SSHFP lookup");
+ raw_key = key_from_private(host_key);
+ if (key_drop_cert(raw_key))
+ fatal("Couldn't drop certificate");
+ host_key = raw_key;
+ }
+
+ if (verify_host_key_dns(host, hostaddr, host_key, &flags))
+ goto done;
+
+ if (flags & DNS_VERIFY_FOUND) {
+
+ if (options.verify_host_key_dns == 1 &&
+ flags & DNS_VERIFY_MATCH &&
+ flags & DNS_VERIFY_SECURE) {
+ rc = 0;
+ } else 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.");
+ }
+ }
+
+done:
+ if (raw_key)
+ key_free(raw_key);
+ return rc;
+}
+
/* returns 0 if key verifies or -1 if key does NOT verify */
int
verify_host_key(char *host, struct sockaddr *hostaddr, Key *host_key)
{
- int flags = 0;
char *fp;
fp = key_fingerprint(host_key, key_fp_type_select(), 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 (check_host_key_sshfp(host, hostaddr, host_key) == 0)
+ return 0;
return check_host_key(host, hostaddr, options.port, host_key, RDRW,
options.user_hostfiles, options.num_user_hostfiles,
options.system_hostfiles, options.num_system_hostfiles);
}
/*
* Starts a dialog with the server, and authenticates the current user on the