=================================================================== RCS file: /cvsrepo/anoncvs/cvs/src/usr.bin/ssh/dns.c,v retrieving revision 1.6.4.2 retrieving revision 1.7 diff -u -r1.6.4.2 -r1.7 --- src/usr.bin/ssh/dns.c 2004/03/04 18:18:15 1.6.4.2 +++ src/usr.bin/ssh/dns.c 2003/10/14 19:42:10 1.7 @@ -1,4 +1,4 @@ -/* $OpenBSD: dns.c,v 1.6.4.2 2004/03/04 18:18:15 brad Exp $ */ +/* $OpenBSD: dns.c,v 1.7 2003/10/14 19:42:10 jakob Exp $ */ /* * Copyright (c) 2003 Wesley Griffin. All rights reserved. @@ -43,7 +43,7 @@ #include "uuencode.h" extern char *__progname; -RCSID("$OpenBSD: dns.c,v 1.6.4.2 2004/03/04 18:18:15 brad Exp $"); +RCSID("$OpenBSD: dns.c,v 1.7 2003/10/14 19:42:10 jakob Exp $"); #ifndef LWRES static const char *errset_text[] = { @@ -83,7 +83,7 @@ */ static int dns_read_key(u_int8_t *algorithm, u_int8_t *digest_type, - u_char **digest, u_int *digest_len, const Key *key) + u_char **digest, u_int *digest_len, Key *key) { int success = 0; @@ -145,15 +145,16 @@ /* * Verify the given hostname, address and host key using DNS. - * Returns 0 if lookup succeeds, -1 otherwise + * Returns 0 if key verifies or -1 if key does NOT verify */ int verify_host_key_dns(const char *hostname, struct sockaddr *address, - const Key *hostkey, int *flags) + Key *hostkey) { int counter; int result; struct rrsetinfo *fingerprints = NULL; + int failures = 0; u_int8_t hostkey_algorithm; u_int8_t hostkey_digest_type; @@ -165,7 +166,6 @@ u_char *dnskey_digest; u_int dnskey_digest_len; - *flags = 0; debug3("verify_hostkey_dns"); if (hostkey == NULL) @@ -175,29 +175,28 @@ DNS_RDATATYPE_SSHFP, 0, &fingerprints); if (result) { verbose("DNS lookup error: %s", dns_result_totext(result)); - return -1; + return DNS_VERIFY_ERROR; } - if (fingerprints->rri_flags & RRSET_VALIDATED) { - *flags |= DNS_VERIFY_SECURE; - debug("found %d secure fingerprints in DNS", - fingerprints->rri_nrdatas); - } else { - debug("found %d insecure fingerprints in DNS", - fingerprints->rri_nrdatas); +#ifdef DNSSEC + /* Only accept validated answers */ + if (!fingerprints->rri_flags & RRSET_VALIDATED) { + error("Ignored unvalidated fingerprint from DNS."); + freerrset(fingerprints); + return DNS_VERIFY_ERROR; } +#endif + debug("found %d fingerprints in DNS", 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; + return DNS_VERIFY_ERROR; } - if (fingerprints->rri_nrdatas) - *flags |= DNS_VERIFY_FOUND; - for (counter = 0 ; counter < fingerprints->rri_nrdatas ; counter++) { /* * Extract the key from the answer. Ignore any badly @@ -219,22 +218,35 @@ memcmp(hostkey_digest, dnskey_digest, hostkey_digest_len) == 0) { - *flags |= DNS_VERIFY_MATCH; + /* Matching algoritm and digest. */ + freerrset(fingerprints); + debug("matching host key fingerprint found in DNS"); + return DNS_VERIFY_OK; + } else { + /* Correct algorithm but bad digest */ + debug("verify_hostkey_dns: failed"); + failures++; } } } freerrset(fingerprints); - if (*flags & DNS_VERIFY_FOUND) - if (*flags & DNS_VERIFY_MATCH) - debug("matching host key fingerprint found in DNS"); - else - debug("mismatching host key fingerprint found in DNS"); - else - debug("no host key fingerprint found in DNS"); + if (failures) { + error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"); + error("@ WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! @"); + error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"); + error("IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!"); + error("Someone could be eavesdropping on you right now (man-in-the-middle attack)!"); + error("It is also possible that the %s host key has just been changed.", + key_type(hostkey)); + error("Please contact your system administrator."); + return DNS_VERIFY_FAILED; + } - return 0; + debug("fingerprints found in DNS, but none of them matched"); + + return DNS_VERIFY_ERROR; } @@ -242,7 +254,7 @@ * Export the fingerprint of a key as a DNS resource record */ int -export_dns_rr(const char *hostname, const Key *key, FILE *f, int generic) +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;