resolved: if we accepted unauthenticated NSEC/NSEC3 RRs, use them for proofs
authorLennart Poettering <lennart@poettering.net>
Tue, 22 Dec 2015 17:22:19 +0000 (18:22 +0100)
committerLennart Poettering <lennart@poettering.net>
Sat, 26 Dec 2015 18:09:10 +0000 (19:09 +0100)
But keep track that the proof is not authenticated.

src/resolve/resolved-dns-dnssec.c
src/resolve/resolved-dns-dnssec.h
src/resolve/resolved-dns-transaction.c

index f37f1d9..14fa58c 100644 (file)
@@ -924,9 +924,6 @@ static int nsec3_is_good(DnsResourceRecord *rr, DnsAnswerFlags flags, DnsResourc
 
         assert(rr);
 
-        if ((flags & DNS_ANSWER_AUTHENTICATED) == 0)
-                return 0;
-
         if (rr->key->type != DNS_TYPE_NSEC3)
                 return 0;
 
@@ -970,16 +967,18 @@ static int nsec3_is_good(DnsResourceRecord *rr, DnsAnswerFlags flags, DnsResourc
         return dns_name_equal(a, b);
 }
 
-static int dnssec_test_nsec3(DnsAnswer *answer, DnsResourceKey *key, DnssecNsecResult *result) {
+static int dnssec_test_nsec3(DnsAnswer *answer, DnsResourceKey *key, DnssecNsecResult *result, bool *authenticated) {
         _cleanup_free_ char *next_closer_domain = NULL, *l = NULL;
         uint8_t hashed[DNSSEC_HASH_SIZE_MAX];
         const char *suffix, *p, *pp = NULL;
         DnsResourceRecord *rr, *suffix_rr;
         DnsAnswerFlags flags;
         int hashed_size, r;
+        bool a;
 
         assert(key);
         assert(result);
+        assert(authenticated);
 
         /* First step, look for the longest common suffix we find with any NSEC3 RR in the response. */
         suffix = DNS_RESOURCE_KEY_NAME(key);
@@ -1047,8 +1046,10 @@ found_suffix:
                         r = dns_name_equal(DNS_RESOURCE_KEY_NAME(rr->key), hashed_domain);
                         if (r < 0)
                                 return r;
-                        if (r > 0)
+                        if (r > 0) {
+                                a = flags & DNS_ANSWER_AUTHENTICATED;
                                 goto found_closest_encloser;
+                        }
                 }
 
                 /* We didn't find the closest encloser with this name,
@@ -1086,6 +1087,7 @@ found_closest_encloser:
         if (!pp) {
                 /* No next closer NSEC3 RR. That means there's a direct NSEC3 RR for our key. */
                 *result = bitmap_isset(rr->nsec3.types, key->type) ? DNSSEC_NSEC_FOUND : DNSSEC_NSEC_NODATA;
+                *authenticated = a;
                 return 0;
         }
 
@@ -1129,6 +1131,7 @@ found_closest_encloser:
                         else
                                 *result = DNSSEC_NSEC_NXDOMAIN;
 
+                        *authenticated = a && (flags & DNS_ANSWER_AUTHENTICATED);
                         return 1;
                 }
         }
@@ -1137,7 +1140,7 @@ found_closest_encloser:
         return 0;
 }
 
-int dnssec_test_nsec(DnsAnswer *answer, DnsResourceKey *key, DnssecNsecResult *result) {
+int dnssec_test_nsec(DnsAnswer *answer, DnsResourceKey *key, DnssecNsecResult *result, bool *authenticated) {
         DnsResourceRecord *rr;
         bool have_nsec3 = false;
         DnsAnswerFlags flags;
@@ -1145,6 +1148,7 @@ int dnssec_test_nsec(DnsAnswer *answer, DnsResourceKey *key, DnssecNsecResult *r
 
         assert(key);
         assert(result);
+        assert(authenticated);
 
         /* Look for any NSEC/NSEC3 RRs that say something about the specified key. */
 
@@ -1153,9 +1157,6 @@ int dnssec_test_nsec(DnsAnswer *answer, DnsResourceKey *key, DnssecNsecResult *r
                 if (rr->key->class != key->class)
                         continue;
 
-                if ((flags & DNS_ANSWER_AUTHENTICATED) == 0)
-                        continue;
-
                 switch (rr->key->type) {
 
                 case DNS_TYPE_NSEC:
@@ -1165,6 +1166,7 @@ int dnssec_test_nsec(DnsAnswer *answer, DnsResourceKey *key, DnssecNsecResult *r
                                 return r;
                         if (r > 0) {
                                 *result = bitmap_isset(rr->nsec.types, key->type) ? DNSSEC_NSEC_FOUND : DNSSEC_NSEC_NODATA;
+                                *authenticated = flags & DNS_ANSWER_AUTHENTICATED;
                                 return 0;
                         }
 
@@ -1173,6 +1175,7 @@ int dnssec_test_nsec(DnsAnswer *answer, DnsResourceKey *key, DnssecNsecResult *r
                                 return r;
                         if (r > 0) {
                                 *result = DNSSEC_NSEC_NXDOMAIN;
+                                *authenticated = flags & DNS_ANSWER_AUTHENTICATED;
                                 return 0;
                         }
                         break;
@@ -1185,7 +1188,7 @@ int dnssec_test_nsec(DnsAnswer *answer, DnsResourceKey *key, DnssecNsecResult *r
 
         /* OK, this was not sufficient. Let's see if NSEC3 can help. */
         if (have_nsec3)
-                return dnssec_test_nsec3(answer, key, result);
+                return dnssec_test_nsec3(answer, key, result, authenticated);
 
         /* No approproate NSEC RR found, report this. */
         *result = DNSSEC_NSEC_NO_RR;
index d17d514..9ad20c8 100644 (file)
@@ -89,7 +89,7 @@ typedef enum DnssecNsecResult {
         DNSSEC_NSEC_OPTOUT,
 } DnssecNsecResult;
 
-int dnssec_test_nsec(DnsAnswer *answer, DnsResourceKey *key, DnssecNsecResult *result);
+int dnssec_test_nsec(DnsAnswer *answer, DnsResourceKey *key, DnssecNsecResult *result, bool *authenticated);
 
 const char* dnssec_mode_to_string(DnssecMode m) _const_;
 DnssecMode dnssec_mode_from_string(const char *s) _pure_;
index 9ac9de0..0f48f9b 100644 (file)
@@ -2112,9 +2112,10 @@ int dns_transaction_validate_dnssec(DnsTransaction *t) {
 
         } else if (r == 0) {
                 DnssecNsecResult nr;
+                bool authenticated = false;
 
                 /* Bummer! Let's check NSEC/NSEC3 */
-                r = dnssec_test_nsec(t->answer, t->key, &nr);
+                r = dnssec_test_nsec(t->answer, t->key, &nr, &authenticated);
                 if (r < 0)
                         return r;
 
@@ -2125,7 +2126,7 @@ int dns_transaction_validate_dnssec(DnsTransaction *t) {
                         log_debug("Proved NXDOMAIN via NSEC/NSEC3 for transaction %u (%s)", t->id, dns_transaction_key_string(t));
                         t->answer_dnssec_result = DNSSEC_VALIDATED;
                         t->answer_rcode = DNS_RCODE_NXDOMAIN;
-                        t->answer_authenticated = true;
+                        t->answer_authenticated = authenticated;
                         break;
 
                 case DNSSEC_NSEC_NODATA:
@@ -2133,7 +2134,7 @@ int dns_transaction_validate_dnssec(DnsTransaction *t) {
                         log_debug("Proved NODATA via NSEC/NSEC3 for transaction %u (%s)", t->id, dns_transaction_key_string(t));
                         t->answer_dnssec_result = DNSSEC_VALIDATED;
                         t->answer_rcode = DNS_RCODE_SUCCESS;
-                        t->answer_authenticated = true;
+                        t->answer_authenticated = authenticated;
                         break;
 
                 case DNSSEC_NSEC_OPTOUT: