version 1.6.2.2, 2004/08/19 22:37:31 |
version 1.7, 2003/10/14 19:42:10 |
|
|
}; |
}; |
|
|
static const char * |
static const char * |
dns_result_totext(unsigned int res) |
dns_result_totext(unsigned int error) |
{ |
{ |
switch (res) { |
switch (error) { |
case ERRSET_SUCCESS: |
case ERRSET_SUCCESS: |
return errset_text[ERRSET_SUCCESS]; |
return errset_text[ERRSET_SUCCESS]; |
case ERRSET_NOMEMORY: |
case ERRSET_NOMEMORY: |
|
|
*/ |
*/ |
static int |
static int |
dns_read_key(u_int8_t *algorithm, u_int8_t *digest_type, |
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; |
int success = 0; |
|
|
|
|
|
|
/* |
/* |
* Verify the given hostname, address and host key using DNS. |
* 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 |
int |
verify_host_key_dns(const char *hostname, struct sockaddr *address, |
verify_host_key_dns(const char *hostname, struct sockaddr *address, |
const Key *hostkey, int *flags) |
Key *hostkey) |
{ |
{ |
int counter; |
int counter; |
int result; |
int result; |
struct rrsetinfo *fingerprints = NULL; |
struct rrsetinfo *fingerprints = NULL; |
|
int failures = 0; |
|
|
u_int8_t hostkey_algorithm; |
u_int8_t hostkey_algorithm; |
u_int8_t hostkey_digest_type; |
u_int8_t hostkey_digest_type; |
|
|
u_char *dnskey_digest; |
u_char *dnskey_digest; |
u_int dnskey_digest_len; |
u_int dnskey_digest_len; |
|
|
*flags = 0; |
|
|
|
debug3("verify_hostkey_dns"); |
debug3("verify_hostkey_dns"); |
if (hostkey == NULL) |
if (hostkey == NULL) |
|
|
DNS_RDATATYPE_SSHFP, 0, &fingerprints); |
DNS_RDATATYPE_SSHFP, 0, &fingerprints); |
if (result) { |
if (result) { |
verbose("DNS lookup error: %s", dns_result_totext(result)); |
verbose("DNS lookup error: %s", dns_result_totext(result)); |
return -1; |
return DNS_VERIFY_ERROR; |
} |
} |
|
|
if (fingerprints->rri_flags & RRSET_VALIDATED) { |
#ifdef DNSSEC |
*flags |= DNS_VERIFY_SECURE; |
/* Only accept validated answers */ |
debug("found %d secure fingerprints in DNS", |
if (!fingerprints->rri_flags & RRSET_VALIDATED) { |
fingerprints->rri_nrdatas); |
error("Ignored unvalidated fingerprint from DNS."); |
} else { |
freerrset(fingerprints); |
debug("found %d insecure fingerprints in DNS", |
return DNS_VERIFY_ERROR; |
fingerprints->rri_nrdatas); |
|
} |
} |
|
#endif |
|
|
|
debug("found %d fingerprints in DNS", fingerprints->rri_nrdatas); |
|
|
/* Initialize host key parameters */ |
/* Initialize host key parameters */ |
if (!dns_read_key(&hostkey_algorithm, &hostkey_digest_type, |
if (!dns_read_key(&hostkey_algorithm, &hostkey_digest_type, |
&hostkey_digest, &hostkey_digest_len, hostkey)) { |
&hostkey_digest, &hostkey_digest_len, hostkey)) { |
error("Error calculating host key fingerprint."); |
error("Error calculating host key fingerprint."); |
freerrset(fingerprints); |
freerrset(fingerprints); |
return -1; |
return DNS_VERIFY_ERROR; |
} |
} |
|
|
if (fingerprints->rri_nrdatas) |
|
*flags |= DNS_VERIFY_FOUND; |
|
|
|
for (counter = 0 ; counter < fingerprints->rri_nrdatas ; counter++) { |
for (counter = 0 ; counter < fingerprints->rri_nrdatas ; counter++) { |
/* |
/* |
* Extract the key from the answer. Ignore any badly |
* Extract the key from the answer. Ignore any badly |
|
|
memcmp(hostkey_digest, dnskey_digest, |
memcmp(hostkey_digest, dnskey_digest, |
hostkey_digest_len) == 0) { |
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); |
freerrset(fingerprints); |
|
|
if (*flags & DNS_VERIFY_FOUND) |
if (failures) { |
if (*flags & DNS_VERIFY_MATCH) |
error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"); |
debug("matching host key fingerprint found in DNS"); |
error("@ WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! @"); |
else |
error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"); |
debug("mismatching host key fingerprint found in DNS"); |
error("IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!"); |
else |
error("Someone could be eavesdropping on you right now (man-in-the-middle attack)!"); |
debug("no host key fingerprint found in DNS"); |
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; |
} |
} |
|
|
|
|
|
|
* Export the fingerprint of a key as a DNS resource record |
* Export the fingerprint of a key as a DNS resource record |
*/ |
*/ |
int |
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_pubkey_algorithm = 0; |
u_int8_t rdata_digest_type = SSHFP_HASH_SHA1; |
u_int8_t rdata_digest_type = SSHFP_HASH_SHA1; |