From ed29bfdce6ef8b1c6e14bb4e77e19e7048f35dd4 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 22 Dec 2015 18:22:19 +0100 Subject: resolved: if we accepted unauthenticated NSEC/NSEC3 RRs, use them for proofs But keep track that the proof is not authenticated. --- src/resolve/resolved-dns-dnssec.c | 23 +++++++++++++---------- src/resolve/resolved-dns-dnssec.h | 2 +- src/resolve/resolved-dns-transaction.c | 7 ++++--- 3 files changed, 18 insertions(+), 14 deletions(-) (limited to 'src') diff --git a/src/resolve/resolved-dns-dnssec.c b/src/resolve/resolved-dns-dnssec.c index f37f1d91be..14fa58c544 100644 --- a/src/resolve/resolved-dns-dnssec.c +++ b/src/resolve/resolved-dns-dnssec.c @@ -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; diff --git a/src/resolve/resolved-dns-dnssec.h b/src/resolve/resolved-dns-dnssec.h index d17d5142f5..9ad20c8c69 100644 --- a/src/resolve/resolved-dns-dnssec.h +++ b/src/resolve/resolved-dns-dnssec.h @@ -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_; diff --git a/src/resolve/resolved-dns-transaction.c b/src/resolve/resolved-dns-transaction.c index 9ac9de01ad..0f48f9bf81 100644 --- a/src/resolve/resolved-dns-transaction.c +++ b/src/resolve/resolved-dns-transaction.c @@ -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: -- cgit v1.2.3-54-g00ecf