-/* $OpenBSD: dns.c,v 1.7 2003/10/14 19:42:10 jakob Exp $ */
+/* $OpenBSD: dns.c,v 1.8 2003/11/12 16:39:58 jakob Exp $ */
/*
* Copyright (c) 2003 Wesley Griffin. All rights reserved.
#include "uuencode.h"
extern char *__progname;
-RCSID("$OpenBSD: dns.c,v 1.7 2003/10/14 19:42:10 jakob Exp $");
+RCSID("$OpenBSD: dns.c,v 1.8 2003/11/12 16:39:58 jakob Exp $");
#ifndef LWRES
static const char *errset_text[] = {
*/
static int
dns_read_key(u_int8_t *algorithm, u_int8_t *digest_type,
- u_char **digest, u_int *digest_len, Key *key)
+ u_char **digest, u_int *digest_len, const Key *key)
{
int success = 0;
/*
* Verify the given hostname, address and host key using DNS.
- * Returns 0 if key verifies or -1 if key does NOT verify
+ * Returns 0 if lookup succeeds, -1 otherwise
*/
int
verify_host_key_dns(const char *hostname, struct sockaddr *address,
- Key *hostkey)
+ const Key *hostkey, int *flags)
{
int counter;
int result;
struct rrsetinfo *fingerprints = NULL;
- int failures = 0;
u_int8_t hostkey_algorithm;
u_int8_t hostkey_digest_type;
u_char *dnskey_digest;
u_int dnskey_digest_len;
+ *flags = 0;
debug3("verify_hostkey_dns");
if (hostkey == NULL)
DNS_RDATATYPE_SSHFP, 0, &fingerprints);
if (result) {
verbose("DNS lookup error: %s", dns_result_totext(result));
- return DNS_VERIFY_ERROR;
+ return -1;
}
-#ifdef DNSSEC
- /* Only accept validated answers */
- if (!fingerprints->rri_flags & RRSET_VALIDATED) {
- error("Ignored unvalidated fingerprint from DNS.");
- freerrset(fingerprints);
- 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);
}
-#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 DNS_VERIFY_ERROR;
+ return -1;
}
+ 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
memcmp(hostkey_digest, dnskey_digest,
hostkey_digest_len) == 0) {
- /* 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++;
+ *flags |= DNS_VERIFY_MATCH;
}
}
}
freerrset(fingerprints);
- 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;
- }
-
- debug("fingerprints found in DNS, but none of them matched");
+ 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");
- return DNS_VERIFY_ERROR;
+ return 0;
}
* Export the fingerprint of a key as a DNS resource record
*/
int
-export_dns_rr(const char *hostname, Key *key, FILE *f, int generic)
+export_dns_rr(const char *hostname, const Key *key, FILE *f, int generic)
{
u_int8_t rdata_pubkey_algorithm = 0;
u_int8_t rdata_digest_type = SSHFP_HASH_SHA1;
-/* $OpenBSD: dns.h,v 1.4 2003/10/14 19:42:10 jakob Exp $ */
+/* $OpenBSD: dns.h,v 1.5 2003/11/12 16:39:58 jakob Exp $ */
/*
* Copyright (c) 2003 Wesley Griffin. All rights reserved.
#define DNS_RDATACLASS_IN 1
#define DNS_RDATATYPE_SSHFP 44
-#define DNS_VERIFY_FAILED -1
-#define DNS_VERIFY_OK 0
-#define DNS_VERIFY_ERROR 1
+#define DNS_VERIFY_FOUND 0x00000001
+#define DNS_VERIFY_MATCH 0x00000002
+#define DNS_VERIFY_SECURE 0x00000004
-int verify_host_key_dns(const char *, struct sockaddr *, Key *);
-int export_dns_rr(const char *, Key *, FILE *, int);
+
+int verify_host_key_dns(const char *, struct sockaddr *, const Key *, int *);
+int export_dns_rr(const char *, const Key *, FILE *, int);
#endif /* DNS_H */
*/
#include "includes.h"
-RCSID("$OpenBSD: sshconnect.c,v 1.152 2003/11/10 16:23:41 jakob Exp $");
+RCSID("$OpenBSD: sshconnect.c,v 1.153 2003/11/12 16:39:58 jakob Exp $");
#include <openssl/bn.h>
char *client_version_string = NULL;
char *server_version_string = NULL;
-int verified_host_key_dns = 0;
+int matching_host_key_dns = 0;
/* import */
extern Options options;
fp = key_fingerprint(host_key, SSH_FP_MD5, SSH_FP_HEX);
msg2[0] = '\0';
if (options.verify_host_key_dns) {
- if (verified_host_key_dns)
+ if (matching_host_key_dns)
snprintf(msg2, sizeof(msg2),
"Matching host key fingerprint"
" found in DNS.\n");
verify_host_key(char *host, struct sockaddr *hostaddr, Key *host_key)
{
struct stat st;
+ int flags = 0;
- if (options.verify_host_key_dns) {
- switch(verify_host_key_dns(host, hostaddr, host_key)) {
- case DNS_VERIFY_OK:
-#ifdef DNSSEC
- return 0;
-#else
- verified_host_key_dns = 1;
- break;
-#endif
- case DNS_VERIFY_FAILED:
- return -1;
- case DNS_VERIFY_ERROR:
- break;
- default:
- debug3("bad return value from verify_host_key_dns");
- break;
+ if (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.");
+ }
}
}