diff -r -U4 openssh-5.8p2/dns.c openssh-5.8p2+sshfp3/dns.c --- openssh-5.8p2/dns.c 2010-08-31 13:41:14.000000000 +0100 +++ openssh-5.8p2+sshfp3/dns.c 2011-08-16 20:49:14.000000000 +0100 @@ -33,8 +33,9 @@ #include #include #include #include +#include #include "xmalloc.h" #include "key.h" #include "dns.h" @@ -85,19 +86,32 @@ break; case KEY_DSA: *algorithm = SSHFP_KEY_DSA; break; - /* XXX KEY_ECDSA */ + case KEY_ECDSA: + *algorithm = SSHFP_KEY_ECDSA; + break; default: *algorithm = SSHFP_KEY_RESERVED; /* 0 */ } if (*algorithm) { - *digest_type = SSHFP_HASH_SHA1; - *digest = key_fingerprint_raw(key, SSH_FP_SHA1, digest_len); - if (*digest == NULL) - fatal("dns_read_key: null from key_fingerprint_raw()"); - success = 1; + if (*digest_type == SSHFP_HASH_SHA1) { + *digest = key_fingerprint_raw(key, SSH_FP_SHA1, digest_len); + if (*digest == NULL) + fatal("dns_read_key: null from key_fingerprint_raw()"); + success = 1; + } else if (*digest_type == SSHFP_HASH_SHA256) { + *digest = key_fingerprint_raw(key, SSH_FP_SHA256, digest_len); + if (*digest == NULL) + fatal("dns_read_key: null from key_fingerprint_raw()"); + success = 1; + } else { + *digest_type = SSHFP_HASH_RESERVED; + *digest = NULL; + *digest_len = 0; + success = 0; + } } else { *digest_type = SSHFP_HASH_RESERVED; *digest = NULL; *digest_len = 0; @@ -174,16 +188,17 @@ int verify_host_key_dns(const char *hostname, struct sockaddr *address, Key *hostkey, int *flags) { - u_int counter; + u_int counter, i; int result; struct rrsetinfo *fingerprints = NULL; + u_char *hex_tmp; - u_int8_t hostkey_algorithm; - u_int8_t hostkey_digest_type; - u_char *hostkey_digest; - u_int hostkey_digest_len; + u_int8_t hostkey_algorithm[2]; + u_int8_t hostkey_digest_type[2] = { SSHFP_HASH_SHA1, SSHFP_HASH_SHA256 }; + u_char *hostkey_digest[2]; + u_int hostkey_digest_len[2]; u_int8_t dnskey_algorithm; u_int8_t dnskey_digest_type; u_char *dnskey_digest; @@ -216,13 +231,19 @@ fingerprints->rri_nrdatas); } /* Initialize host key parameters */ - if (!dns_read_key(&hostkey_algorithm, &hostkey_digest_type, - &hostkey_digest, &hostkey_digest_len, hostkey)) { - error("Error calculating host key fingerprint."); - freerrset(fingerprints); - return -1; + for (i = 0; i < 2; i++) { + if (!dns_read_key(&hostkey_algorithm[i], &hostkey_digest_type[i], + &hostkey_digest[i], &hostkey_digest_len[i], hostkey)) { + error("Error calculating host key SHA1 fingerprint."); + freerrset(fingerprints); + return -1; + } + + hex_tmp = tohex(hostkey_digest[i], hostkey_digest_len[i]); + debug2("dns_read_key: %d %d %s", hostkey_algorithm[i], hostkey_digest_type[i], hex_tmp); + xfree(hex_tmp); } if (fingerprints->rri_nrdatas) *flags |= DNS_VERIFY_FOUND; @@ -239,27 +260,36 @@ verbose("Error parsing fingerprint from DNS."); continue; } - /* Check if the current key is the same as the given key */ - if (hostkey_algorithm == dnskey_algorithm && - hostkey_digest_type == dnskey_digest_type) { - - if (hostkey_digest_len == dnskey_digest_len && - memcmp(hostkey_digest, dnskey_digest, - hostkey_digest_len) == 0) { + hex_tmp = tohex(dnskey_digest, dnskey_digest_len); + debug2("dns_read_rdata: %d %d %s", dnskey_algorithm, dnskey_digest_type, hex_tmp); + xfree(hex_tmp); - *flags |= DNS_VERIFY_MATCH; + /* Check if the current key is the same as the given key */ + for (i = 0; i < 2; i++) { + if (hostkey_algorithm[i] == dnskey_algorithm && + hostkey_digest_type[i] == dnskey_digest_type) { + + if (hostkey_digest_len[i] == dnskey_digest_len && + memcmp(hostkey_digest[i], dnskey_digest, + hostkey_digest_len[i]) == 0) { + + *flags |= DNS_VERIFY_MATCH; + } else { + *flags |= DNS_VERIFY_MISMATCH; + } } } xfree(dnskey_digest); } - xfree(hostkey_digest); /* from key_fingerprint_raw() */ + for (i = 0; i < 2; i++) + xfree(hostkey_digest[i]); /* from key_fingerprint_raw() */ freerrset(fingerprints); if (*flags & DNS_VERIFY_FOUND) - if (*flags & DNS_VERIFY_MATCH) + if ((*flags & DNS_VERIFY_MATCH) && !(*flags & DNS_VERIFY_MISMATCH)) debug("matching host key fingerprint found in DNS"); else debug("mismatching host key fingerprint found in DNS"); else @@ -274,33 +304,35 @@ int export_dns_rr(const char *hostname, Key *key, FILE *f, int generic) { u_int8_t rdata_pubkey_algorithm = 0; - u_int8_t rdata_digest_type = SSHFP_HASH_SHA1; + u_int8_t rdata_digest_type[2] = { SSHFP_HASH_SHA1, SSHFP_HASH_SHA256 }; u_char *rdata_digest; u_int rdata_digest_len; - u_int i; + u_int i, j; int success = 0; - if (dns_read_key(&rdata_pubkey_algorithm, &rdata_digest_type, - &rdata_digest, &rdata_digest_len, key)) { - - if (generic) - fprintf(f, "%s IN TYPE%d \\# %d %02x %02x ", hostname, - DNS_RDATATYPE_SSHFP, 2 + rdata_digest_len, - rdata_pubkey_algorithm, rdata_digest_type); - else - fprintf(f, "%s IN SSHFP %d %d ", hostname, - rdata_pubkey_algorithm, rdata_digest_type); - - for (i = 0; i < rdata_digest_len; i++) - fprintf(f, "%02x", rdata_digest[i]); - fprintf(f, "\n"); - xfree(rdata_digest); /* from key_fingerprint_raw() */ - success = 1; - } else { - error("export_dns_rr: unsupported algorithm"); + for (i = 0; i < 2; i++) { + if (dns_read_key(&rdata_pubkey_algorithm, &rdata_digest_type[i], + &rdata_digest, &rdata_digest_len, key)) { + + if (generic) + fprintf(f, "%s IN TYPE%d \\# %d %02x %02x ", hostname, + DNS_RDATATYPE_SSHFP, 2 + rdata_digest_len, + rdata_pubkey_algorithm, rdata_digest_type[i]); + else + fprintf(f, "%s IN SSHFP %d %d ", hostname, + rdata_pubkey_algorithm, rdata_digest_type[i]); + + for (j = 0; j < rdata_digest_len; j++) + fprintf(f, "%02x", rdata_digest[j]); + fprintf(f, "\n"); + xfree(rdata_digest); /* from key_fingerprint_raw() */ + success = 1; + } else { + error("export_dns_rr: unsupported algorithm"); + } } return success; } diff -r -U4 openssh-5.8p2/dns.h openssh-5.8p2+sshfp3/dns.h --- openssh-5.8p2/dns.h 2010-02-26 20:55:05.000000000 +0000 +++ openssh-5.8p2+sshfp3/dns.h 2011-08-16 20:47:50.000000000 +0100 @@ -30,22 +30,25 @@ enum sshfp_types { SSHFP_KEY_RESERVED, SSHFP_KEY_RSA, - SSHFP_KEY_DSA + SSHFP_KEY_DSA, + SSHFP_KEY_ECDSA }; enum sshfp_hashes { SSHFP_HASH_RESERVED, - SSHFP_HASH_SHA1 + SSHFP_HASH_SHA1, + SSHFP_HASH_SHA256 }; #define DNS_RDATACLASS_IN 1 #define DNS_RDATATYPE_SSHFP 44 #define DNS_VERIFY_FOUND 0x00000001 #define DNS_VERIFY_MATCH 0x00000002 #define DNS_VERIFY_SECURE 0x00000004 +#define DNS_VERIFY_MISMATCH 0x00000008 int verify_host_key_dns(const char *, struct sockaddr *, Key *, int *); int export_dns_rr(const char *, Key *, FILE *, int); diff -r -U4 openssh-5.8p2/key.c openssh-5.8p2+sshfp3/key.c --- openssh-5.8p2/key.c 2011-02-04 00:48:34.000000000 +0000 +++ openssh-5.8p2+sshfp3/key.c 2011-08-16 19:28:38.000000000 +0100 @@ -341,8 +341,11 @@ break; case SSH_FP_SHA1: md = EVP_sha1(); break; + case SSH_FP_SHA256: + md = EVP_sha256(); + break; default: fatal("key_fingerprint_raw: bad digest type %d", dgst_type); } diff -r -U4 openssh-5.8p2/key.h openssh-5.8p2+sshfp3/key.h --- openssh-5.8p2/key.h 2010-11-04 23:19:49.000000000 +0000 +++ openssh-5.8p2+sshfp3/key.h 2011-08-16 19:28:44.000000000 +0100 @@ -47,9 +47,10 @@ KEY_UNSPEC }; enum fp_type { SSH_FP_SHA1, - SSH_FP_MD5 + SSH_FP_MD5, + SSH_FP_SHA256 }; enum fp_rep { SSH_FP_HEX, SSH_FP_BUBBLEBABBLE, diff -r -U4 openssh-5.8p2/ssh-keygen.c openssh-5.8p2+sshfp3/ssh-keygen.c --- openssh-5.8p2/ssh-keygen.c 2011-01-11 06:20:31.000000000 +0000 +++ openssh-5.8p2+sshfp3/ssh-keygen.c 2011-08-16 19:17:52.000000000 +0100 @@ -2061,8 +2061,10 @@ n += do_print_resource_record(pw, _PATH_HOST_RSA_KEY_FILE, rr_hostname); n += do_print_resource_record(pw, _PATH_HOST_DSA_KEY_FILE, rr_hostname); + n += do_print_resource_record(pw, + _PATH_HOST_ECDSA_KEY_FILE, rr_hostname); if (n == 0) fatal("no keys found."); exit(0);