]> andersk Git - openssh.git/blobdiff - dns.c
- djm@cvs.openbsd.org 2010/01/30 02:54:53
[openssh.git] / dns.c
diff --git a/dns.c b/dns.c
index 14ca13a48446c5da7d70e9f443f799994c0d0ccb..a7da03fa3efd14ce5feb2199995a2f344d01dbe0 100644 (file)
--- a/dns.c
+++ b/dns.c
@@ -1,4 +1,4 @@
-/*     $OpenBSD: dns.c,v 1.5 2003/05/15 02:27:15 jakob Exp $   */
+/* $OpenBSD: dns.c,v 1.25 2008/06/12 00:03:49 dtucker Exp $ */
 
 /*
  * Copyright (c) 2003 Wesley Griffin. All rights reserved.
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-
 #include "includes.h"
 
-#ifdef DNS
-#include <openssl/bn.h>
-#ifdef LWRES
-#include <lwres/netdb.h>
-#include <dns/result.h>
-#else /* LWRES */
+#include <sys/types.h>
+#include <sys/socket.h>
+
 #include <netdb.h>
-#endif /* LWRES */
+#include <stdarg.h>
+#include <stdio.h>
+#include <string.h>
 
 #include "xmalloc.h"
 #include "key.h"
 #include "dns.h"
 #include "log.h"
-#include "uuencode.h"
 
-extern char *__progname;
-RCSID("$OpenBSD: dns.c,v 1.5 2003/05/15 02:27:15 jakob Exp $");
-
-#ifndef LWRES
 static const char *errset_text[] = {
        "success",              /* 0 ERRSET_SUCCESS */
        "out of memory",        /* 1 ERRSET_NOMEMORY */
@@ -57,9 +50,9 @@ static const char *errset_text[] = {
 };
 
 static const char *
-dns_result_totext(unsigned int error)
+dns_result_totext(unsigned int res)
 {
-       switch (error) {
+       switch (res) {
        case ERRSET_SUCCESS:
                return errset_text[ERRSET_SUCCESS];
        case ERRSET_NOMEMORY:
@@ -76,15 +69,13 @@ dns_result_totext(unsigned int error)
                return "unknown error";
        }
 }
-#endif /* LWRES */
-
 
 /*
  * Read SSHFP parameters from key buffer.
  */
 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;
 
@@ -96,12 +87,14 @@ dns_read_key(u_int8_t *algorithm, u_int8_t *digest_type,
                *algorithm = SSHFP_KEY_DSA;
                break;
        default:
-               *algorithm = SSHFP_KEY_RESERVED;
+               *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;
        } else {
                *digest_type = SSHFP_HASH_RESERVED;
@@ -134,7 +127,7 @@ dns_read_rdata(u_int8_t *algorithm, u_int8_t *digest_type,
                        *digest = (u_char *) xmalloc(*digest_len);
                        memcpy(*digest, rdata + 2, *digest_len);
                } else {
-                       *digest = NULL;
+                       *digest = (u_char *)xstrdup("");
                }
 
                success = 1;
@@ -143,19 +136,47 @@ dns_read_rdata(u_int8_t *algorithm, u_int8_t *digest_type,
        return success;
 }
 
+/*
+ * Check if hostname is numerical.
+ * Returns -1 if hostname is numeric, 0 otherwise
+ */
+static int
+is_numeric_hostname(const char *hostname)
+{
+       struct addrinfo hints, *ai;
+
+       /*
+        * We shouldn't ever get a null host but if we do then log an error
+        * and return -1 which stops DNS key fingerprint processing.
+        */
+       if (hostname == NULL) {
+               error("is_numeric_hostname called with NULL hostname");
+               return -1;
+       }
+
+       memset(&hints, 0, sizeof(hints));
+       hints.ai_socktype = SOCK_DGRAM;
+       hints.ai_flags = AI_NUMERICHOST;
+
+       if (getaddrinfo(hostname, NULL, &hints, &ai) == 0) {
+               freeaddrinfo(ai);
+               return -1;
+       }
+
+       return 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;
+       u_int counter;
        int result;
        struct rrsetinfo *fingerprints = NULL;
-       int failures = 0;
 
        u_int8_t hostkey_algorithm;
        u_int8_t hostkey_digest_type;
@@ -167,38 +188,45 @@ verify_host_key_dns(const char *hostname, struct sockaddr *address,
        u_char *dnskey_digest;
        u_int dnskey_digest_len;
 
+       *flags = 0;
 
-       debug3("verify_hostkey_dns");
+       debug3("verify_host_key_dns");
        if (hostkey == NULL)
                fatal("No key to look up!");
 
+       if (is_numeric_hostname(hostname)) {
+               debug("skipped DNS lookup for numerical hostname");
+               return -1;
+       }
+
        result = getrrsetbyname(hostname, DNS_RDATACLASS_IN,
            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;
        }
 
-       for (counter = 0 ; counter < fingerprints->rri_nrdatas ; counter++)  {
+       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
                 * formatted fingerprints.
@@ -219,59 +247,42 @@ verify_host_key_dns(const char *hostname, struct sockaddr *address,
                            memcmp(hostkey_digest, dnskey_digest,
                            hostkey_digest_len) == 0) {
 
-                               /* Matching algoritm and digest. */
-                               freerrset(fingerprints);
-#ifdef DNSSEC
-                               debug("matching host key fingerprint found in DNS");
-                               return DNS_VERIFY_OK;
-#else
-                               logit("Matching host key fingerprint found in DNS.");
-                               return DNS_VERIFY_ERROR;
-#endif
-                       } else {
-                               /* Correct algorithm but bad digest */
-                               debug("verify_hostkey_dns: failed");
-                               failures++;
+                               *flags |= DNS_VERIFY_MATCH;
                        }
                }
+               xfree(dnskey_digest);
        }
 
+       xfree(hostkey_digest); /* from key_fingerprint_raw() */
        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;
        u_char *rdata_digest;
        u_int rdata_digest_len;
 
-       int i;
+       u_int i;
        int success = 0;
 
        if (dns_read_key(&rdata_pubkey_algorithm, &rdata_digest_type,
-                        &rdata_digest, &rdata_digest_len, key)) {
+           &rdata_digest, &rdata_digest_len, key)) {
 
                if (generic)
                        fprintf(f, "%s IN TYPE%d \\# %d %02x %02x ", hostname,
@@ -284,12 +295,11 @@ export_dns_rr(const char *hostname, Key *key, FILE *f, int generic)
                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("dns_export_rr: unsupported algorithm");
+               error("export_dns_rr: unsupported algorithm");
        }
 
        return success;
 }
-
-#endif /* DNS */
This page took 0.291181 seconds and 4 git commands to generate.