Skip to content

Commit

Permalink
resolved: add support NSEC3 proofs, as well as proofs for domains tha…
Browse files Browse the repository at this point in the history
…t are OK to be unsigned

This large patch adds a couple of mechanisms to ensure we get NSEC3 and
proof-of-unsigned support into place. Specifically:

- Each item in an DnsAnswer gets two bit flags now:
  DNS_ANSWER_AUTHENTICATED and DNS_ANSWER_CACHEABLE. The former is
  necessary since DNS responses might contain signed as well as unsigned
  RRsets in one, and we need to remember which ones are signed and which
  ones aren't. The latter is necessary, since not we need to keep track
  which RRsets may be cached and which ones may not be, even while
  manipulating DnsAnswer objects.

- The .n_answer_cachable of DnsTransaction is dropped now (it used to
  store how many of the first DnsAnswer entries are cachable), and
  replaced by the DNS_ANSWER_CACHABLE flag instead.

- NSEC3 proofs are implemented now (lacking support for the wildcard
  part, to be added in a later commit).

- Support for the "AD" bit has been dropped. It's unsafe, and now that
  we have end-to-end authentication we don't need it anymore.

- An auxiliary DnsTransaction of a DnsTransactions is now kept around as
  least as long as the latter stays around. We no longer remove the
  auxiliary DnsTransaction as soon as it completed. THis is necessary,
  as we now are interested not only in the RRsets it acquired but also
  in its authentication status.
  • Loading branch information
poettering committed Dec 18, 2015
1 parent aae6a86 commit 105e151
Show file tree
Hide file tree
Showing 16 changed files with 1,038 additions and 234 deletions.
156 changes: 125 additions & 31 deletions src/resolve/resolved-dns-answer.c
Expand Up @@ -74,7 +74,7 @@ DnsAnswer *dns_answer_unref(DnsAnswer *a) {
return NULL;
}

static int dns_answer_add_raw(DnsAnswer *a, DnsResourceRecord *rr, int ifindex) {
static int dns_answer_add_raw(DnsAnswer *a, DnsResourceRecord *rr, int ifindex, DnsAnswerFlags flags) {
assert(rr);

if (!a)
Expand All @@ -83,27 +83,30 @@ static int dns_answer_add_raw(DnsAnswer *a, DnsResourceRecord *rr, int ifindex)
if (a->n_rrs >= a->n_allocated)
return -ENOSPC;

a->items[a->n_rrs].rr = dns_resource_record_ref(rr);
a->items[a->n_rrs].ifindex = ifindex;
a->n_rrs++;
a->items[a->n_rrs++] = (DnsAnswerItem) {
.rr = dns_resource_record_ref(rr),
.ifindex = ifindex,
.flags = flags,
};

return 1;
}

static int dns_answer_add_raw_all(DnsAnswer *a, DnsAnswer *source) {
DnsResourceRecord *rr;
DnsAnswerFlags flags;
int ifindex, r;

DNS_ANSWER_FOREACH_IFINDEX(rr, ifindex, source) {
r = dns_answer_add_raw(a, rr, ifindex);
DNS_ANSWER_FOREACH_FULL(rr, ifindex, flags, source) {
r = dns_answer_add_raw(a, rr, ifindex, flags);
if (r < 0)
return r;
}

return 0;
}

int dns_answer_add(DnsAnswer *a, DnsResourceRecord *rr, int ifindex) {
int dns_answer_add(DnsAnswer *a, DnsResourceRecord *rr, int ifindex, DnsAnswerFlags flags) {
unsigned i;
int r;

Expand Down Expand Up @@ -131,27 +134,29 @@ int dns_answer_add(DnsAnswer *a, DnsResourceRecord *rr, int ifindex) {
a->items[i].rr = rr;
}

a->items[i].flags |= flags;
return 0;
}
}

return dns_answer_add_raw(a, rr, ifindex);
return dns_answer_add_raw(a, rr, ifindex, flags);
}

static int dns_answer_add_all(DnsAnswer *a, DnsAnswer *b) {
DnsResourceRecord *rr;
DnsAnswerFlags flags;
int ifindex, r;

DNS_ANSWER_FOREACH_IFINDEX(rr, ifindex, b) {
r = dns_answer_add(a, rr, ifindex);
DNS_ANSWER_FOREACH_FULL(rr, ifindex, flags, b) {
r = dns_answer_add(a, rr, ifindex, flags);
if (r < 0)
return r;
}

return 0;
}

int dns_answer_add_extend(DnsAnswer **a, DnsResourceRecord *rr, int ifindex) {
int dns_answer_add_extend(DnsAnswer **a, DnsResourceRecord *rr, int ifindex, DnsAnswerFlags flags) {
int r;

assert(a);
Expand All @@ -161,7 +166,7 @@ int dns_answer_add_extend(DnsAnswer **a, DnsResourceRecord *rr, int ifindex) {
if (r < 0)
return r;

return dns_answer_add(*a, rr, ifindex);
return dns_answer_add(*a, rr, ifindex, flags);
}

int dns_answer_add_soa(DnsAnswer *a, const char *name, uint32_t ttl) {
Expand All @@ -187,44 +192,114 @@ int dns_answer_add_soa(DnsAnswer *a, const char *name, uint32_t ttl) {
soa->soa.expire = 1;
soa->soa.minimum = ttl;

return dns_answer_add(a, soa, 0);
return dns_answer_add(a, soa, 0, DNS_ANSWER_AUTHENTICATED);
}

int dns_answer_match_key(DnsAnswer *a, const DnsResourceKey *key) {
int dns_answer_match_key(DnsAnswer *a, const DnsResourceKey *key, DnsAnswerFlags *ret_flags) {
DnsAnswerFlags flags = 0, i_flags;
DnsResourceRecord *i;
bool found = false;
int r;

assert(key);

if (!a)
return 0;

DNS_ANSWER_FOREACH(i, a) {
DNS_ANSWER_FOREACH_FLAGS(i, i_flags, a) {
r = dns_resource_key_match_rr(key, i, NULL);
if (r < 0)
return r;
if (r > 0)
if (r == 0)
continue;

if (!ret_flags)
return 1;

if (found)
flags &= i_flags;
else {
flags = i_flags;
found = true;
}
}

return 0;
if (ret_flags)
*ret_flags = flags;

return found;
}

int dns_answer_contains_rr(DnsAnswer *a, DnsResourceRecord *rr) {
int dns_answer_contains_rr(DnsAnswer *a, DnsResourceRecord *rr, DnsAnswerFlags *ret_flags) {
DnsAnswerFlags flags = 0, i_flags;
DnsResourceRecord *i;
bool found = false;
int r;

assert(rr);

DNS_ANSWER_FOREACH(i, a) {
DNS_ANSWER_FOREACH_FLAGS(i, i_flags, a) {
r = dns_resource_record_equal(i, rr);
if (r < 0)
return r;
if (r > 0)
if (r == 0)
continue;

if (!ret_flags)
return 1;

if (found)
flags &= i_flags;
else {
flags = i_flags;
found = true;
}
}

return 0;
if (ret_flags)
*ret_flags = flags;

return found;
}

int dns_answer_contains_key(DnsAnswer *a, const DnsResourceKey *key, DnsAnswerFlags *ret_flags) {
DnsAnswerFlags flags = 0, i_flags;
DnsResourceRecord *i;
bool found = false;
int r;

assert(key);

DNS_ANSWER_FOREACH_FLAGS(i, i_flags, a) {
r = dns_resource_key_equal(i->key, key);
if (r < 0)
return r;
if (r == 0)
continue;

if (!ret_flags)
return true;

if (found)
flags &= i_flags;
else {
flags = i_flags;
found = true;
}
}

if (ret_flags)
*ret_flags = flags;

return found;
}

int dns_answer_contains_nsec_or_nsec3(DnsAnswer *a) {
DnsResourceRecord *i;

DNS_ANSWER_FOREACH(i, a) {
if (IN_SET(i->key->type, DNS_TYPE_NSEC, DNS_TYPE_NSEC3))
return true;
}

return false;
}

int dns_answer_find_soa(DnsAnswer *a, const DnsResourceKey *key, DnsResourceRecord **ret) {
Expand All @@ -251,8 +326,9 @@ int dns_answer_find_soa(DnsAnswer *a, const DnsResourceKey *key, DnsResourceReco
return 0;
}

int dns_answer_find_cname_or_dname(DnsAnswer *a, const DnsResourceKey *key, DnsResourceRecord **ret) {
int dns_answer_find_cname_or_dname(DnsAnswer *a, const DnsResourceKey *key, DnsResourceRecord **ret, DnsAnswerFlags *flags) {
DnsResourceRecord *rr;
DnsAnswerFlags rr_flags;
int r;

assert(key);
Expand All @@ -261,13 +337,15 @@ int dns_answer_find_cname_or_dname(DnsAnswer *a, const DnsResourceKey *key, DnsR
if (key->type == DNS_TYPE_CNAME || key->type == DNS_TYPE_DNAME)
return 0;

DNS_ANSWER_FOREACH(rr, a) {
DNS_ANSWER_FOREACH_FLAGS(rr, rr_flags, a) {
r = dns_resource_key_match_cname_or_dname(key, rr->key, NULL);
if (r < 0)
return r;
if (r > 0) {
if (ret)
*ret = rr;
if (flags)
*flags = rr_flags;
return 1;
}
}
Expand Down Expand Up @@ -359,20 +437,21 @@ int dns_answer_remove_by_key(DnsAnswer **a, const DnsResourceKey *key) {

if ((*a)->n_ref > 1) {
_cleanup_(dns_answer_unrefp) DnsAnswer *copy = NULL;
DnsAnswerFlags flags;
int ifindex;

copy = dns_answer_new((*a)->n_rrs);
if (!copy)
return -ENOMEM;

DNS_ANSWER_FOREACH_IFINDEX(rr, ifindex, *a) {
DNS_ANSWER_FOREACH_FULL(rr, ifindex, flags, *a) {
r = dns_resource_key_equal(rr->key, key);
if (r < 0)
return r;
if (r > 0)
continue;

r = dns_answer_add_raw(copy, rr, ifindex);
r = dns_answer_add_raw(copy, rr, ifindex, flags);
if (r < 0)
return r;
}
Expand Down Expand Up @@ -410,16 +489,17 @@ int dns_answer_remove_by_key(DnsAnswer **a, const DnsResourceKey *key) {
return 1;
}

int dns_answer_copy_by_key(DnsAnswer **a, DnsAnswer *source, const DnsResourceKey *key) {
int dns_answer_copy_by_key(DnsAnswer **a, DnsAnswer *source, const DnsResourceKey *key, DnsAnswerFlags or_flags) {
DnsResourceRecord *rr_source;
int ifindex_source, r;
DnsAnswerFlags flags_source;

assert(a);
assert(key);

/* Copy all RRs matching the specified key from source into *a */

DNS_ANSWER_FOREACH_IFINDEX(rr_source, ifindex_source, source) {
DNS_ANSWER_FOREACH_FULL(rr_source, ifindex_source, flags_source, source) {

r = dns_resource_key_equal(rr_source->key, key);
if (r < 0)
Expand All @@ -432,14 +512,28 @@ int dns_answer_copy_by_key(DnsAnswer **a, DnsAnswer *source, const DnsResourceKe
if (r < 0)
return r;

r = dns_answer_add(*a, rr_source, ifindex_source);
r = dns_answer_add(*a, rr_source, ifindex_source, flags_source|or_flags);
if (r < 0)
return r;
}

return 0;
}

int dns_answer_move_by_key(DnsAnswer **to, DnsAnswer **from, const DnsResourceKey *key, DnsAnswerFlags or_flags) {
int r;

assert(to);
assert(from);
assert(key);

r = dns_answer_copy_by_key(to, *from, key, or_flags);
if (r < 0)
return r;

return dns_answer_remove_by_key(from, key);
}

void dns_answer_order_by_scope(DnsAnswer *a, bool prefer_link_local) {
DnsAnswerItem *items;
unsigned i, start, end;
Expand Down

0 comments on commit 105e151

Please sign in to comment.