resolved: if we accepted unauthenticated NSEC/NSEC3 RRs, use them for proofs

But keep track that the proof is not authenticated.
This commit is contained in:
Lennart Poettering 2015-12-22 18:22:19 +01:00
parent 94aa707129
commit ed29bfdce6
3 changed files with 18 additions and 14 deletions

View File

@ -924,9 +924,6 @@ static int nsec3_is_good(DnsResourceRecord *rr, DnsAnswerFlags flags, DnsResourc
assert(rr); assert(rr);
if ((flags & DNS_ANSWER_AUTHENTICATED) == 0)
return 0;
if (rr->key->type != DNS_TYPE_NSEC3) if (rr->key->type != DNS_TYPE_NSEC3)
return 0; return 0;
@ -970,16 +967,18 @@ static int nsec3_is_good(DnsResourceRecord *rr, DnsAnswerFlags flags, DnsResourc
return dns_name_equal(a, b); 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; _cleanup_free_ char *next_closer_domain = NULL, *l = NULL;
uint8_t hashed[DNSSEC_HASH_SIZE_MAX]; uint8_t hashed[DNSSEC_HASH_SIZE_MAX];
const char *suffix, *p, *pp = NULL; const char *suffix, *p, *pp = NULL;
DnsResourceRecord *rr, *suffix_rr; DnsResourceRecord *rr, *suffix_rr;
DnsAnswerFlags flags; DnsAnswerFlags flags;
int hashed_size, r; int hashed_size, r;
bool a;
assert(key); assert(key);
assert(result); assert(result);
assert(authenticated);
/* First step, look for the longest common suffix we find with any NSEC3 RR in the response. */ /* First step, look for the longest common suffix we find with any NSEC3 RR in the response. */
suffix = DNS_RESOURCE_KEY_NAME(key); suffix = DNS_RESOURCE_KEY_NAME(key);
@ -1047,8 +1046,10 @@ found_suffix:
r = dns_name_equal(DNS_RESOURCE_KEY_NAME(rr->key), hashed_domain); r = dns_name_equal(DNS_RESOURCE_KEY_NAME(rr->key), hashed_domain);
if (r < 0) if (r < 0)
return r; return r;
if (r > 0) if (r > 0) {
a = flags & DNS_ANSWER_AUTHENTICATED;
goto found_closest_encloser; goto found_closest_encloser;
}
} }
/* We didn't find the closest encloser with this name, /* We didn't find the closest encloser with this name,
@ -1086,6 +1087,7 @@ found_closest_encloser:
if (!pp) { if (!pp) {
/* No next closer NSEC3 RR. That means there's a direct NSEC3 RR for our key. */ /* 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; *result = bitmap_isset(rr->nsec3.types, key->type) ? DNSSEC_NSEC_FOUND : DNSSEC_NSEC_NODATA;
*authenticated = a;
return 0; return 0;
} }
@ -1129,6 +1131,7 @@ found_closest_encloser:
else else
*result = DNSSEC_NSEC_NXDOMAIN; *result = DNSSEC_NSEC_NXDOMAIN;
*authenticated = a && (flags & DNS_ANSWER_AUTHENTICATED);
return 1; return 1;
} }
} }
@ -1137,7 +1140,7 @@ found_closest_encloser:
return 0; 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; DnsResourceRecord *rr;
bool have_nsec3 = false; bool have_nsec3 = false;
DnsAnswerFlags flags; DnsAnswerFlags flags;
@ -1145,6 +1148,7 @@ int dnssec_test_nsec(DnsAnswer *answer, DnsResourceKey *key, DnssecNsecResult *r
assert(key); assert(key);
assert(result); assert(result);
assert(authenticated);
/* Look for any NSEC/NSEC3 RRs that say something about the specified key. */ /* 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) if (rr->key->class != key->class)
continue; continue;
if ((flags & DNS_ANSWER_AUTHENTICATED) == 0)
continue;
switch (rr->key->type) { switch (rr->key->type) {
case DNS_TYPE_NSEC: case DNS_TYPE_NSEC:
@ -1165,6 +1166,7 @@ int dnssec_test_nsec(DnsAnswer *answer, DnsResourceKey *key, DnssecNsecResult *r
return r; return r;
if (r > 0) { if (r > 0) {
*result = bitmap_isset(rr->nsec.types, key->type) ? DNSSEC_NSEC_FOUND : DNSSEC_NSEC_NODATA; *result = bitmap_isset(rr->nsec.types, key->type) ? DNSSEC_NSEC_FOUND : DNSSEC_NSEC_NODATA;
*authenticated = flags & DNS_ANSWER_AUTHENTICATED;
return 0; return 0;
} }
@ -1173,6 +1175,7 @@ int dnssec_test_nsec(DnsAnswer *answer, DnsResourceKey *key, DnssecNsecResult *r
return r; return r;
if (r > 0) { if (r > 0) {
*result = DNSSEC_NSEC_NXDOMAIN; *result = DNSSEC_NSEC_NXDOMAIN;
*authenticated = flags & DNS_ANSWER_AUTHENTICATED;
return 0; return 0;
} }
break; 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. */ /* OK, this was not sufficient. Let's see if NSEC3 can help. */
if (have_nsec3) 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. */ /* No approproate NSEC RR found, report this. */
*result = DNSSEC_NSEC_NO_RR; *result = DNSSEC_NSEC_NO_RR;

View File

@ -89,7 +89,7 @@ typedef enum DnssecNsecResult {
DNSSEC_NSEC_OPTOUT, DNSSEC_NSEC_OPTOUT,
} DnssecNsecResult; } 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_; const char* dnssec_mode_to_string(DnssecMode m) _const_;
DnssecMode dnssec_mode_from_string(const char *s) _pure_; DnssecMode dnssec_mode_from_string(const char *s) _pure_;

View File

@ -2112,9 +2112,10 @@ int dns_transaction_validate_dnssec(DnsTransaction *t) {
} else if (r == 0) { } else if (r == 0) {
DnssecNsecResult nr; DnssecNsecResult nr;
bool authenticated = false;
/* Bummer! Let's check NSEC/NSEC3 */ /* 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) if (r < 0)
return r; 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)); 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_dnssec_result = DNSSEC_VALIDATED;
t->answer_rcode = DNS_RCODE_NXDOMAIN; t->answer_rcode = DNS_RCODE_NXDOMAIN;
t->answer_authenticated = true; t->answer_authenticated = authenticated;
break; break;
case DNSSEC_NSEC_NODATA: 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)); 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_dnssec_result = DNSSEC_VALIDATED;
t->answer_rcode = DNS_RCODE_SUCCESS; t->answer_rcode = DNS_RCODE_SUCCESS;
t->answer_authenticated = true; t->answer_authenticated = authenticated;
break; break;
case DNSSEC_NSEC_OPTOUT: case DNSSEC_NSEC_OPTOUT: