Let's use dns_cache_remove() rather than
dns_cache_item_remove_and_free() to destroy the cache, since the former
requires far fewer hash table lookups.
resolved: when receiving a TTL=0 RR, only flush that specific RR
When we receieve a TTL=0 RR, then let's only flush that specific RR and
not the whole RRset.
On mDNS with RRsets that a shared-owner this is how specific RRs are
removed from the set, hence support this. And on non-mDNS the whole
RRset will already be removed much earlier in dns_cache_put() hence
there's no reason remove it again.
resolved: move DNS class utilities to dns-type.c and add more helpers
Let's make DNS class helpers more like DNS type helpers, let's move them
from resolved-dns-rr.[ch] into dns-type.[ch].
This also adds two new calls dns_class_is_pseudo() and
dns_class_is_valid_rr() which operate similar to dns_type_is_pseudo()
and dns_type_is_valid_rr() but for classes instead of types.
This should hopefully make handling of DNS classes and DNS types more
alike.
resolved: add support NSEC3 proofs, as well as proofs for domains that 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.
resolved: make sure we don't get confused when notifying transactions while they are destroyed
A failing transaction might cause other transactions to fail too, and
thus the set of transactions to notify for a transaction might change
while we are notifying them. Protect against that.
resolved: cache stringified transaction key once per transaction
We end up needing the stringified transaction key in many log messages,
hence let's simplify the logic and cache it inside of the transaction:
generate it the first time we need it, and reuse it afterwards. Free it
when the transaction goes away.
This also updated a couple of log messages to make use of this.
Output the same message when a request to change the log level is
received over dbus and through a signal. From the user point of view
those two operations are very similar and it's easy to think that the
dbus operation didn't work when the expected message is not emitted.
Also "downgrade" the message level to info, since this is a normal
user initiated action.
manager: move status output change debug messages to set function
This way we can only print the debug message when the status actually
changes. We also means we don't print anything when running in --user
mode, where status output is always disabled.
This changes answer validation to be more accepting to unordered RRs in
responses. The agorithm we now implement goes something like this:
1. populate validated keys list for this transaction from DS RRs
2. as long as the following changes the unvalidated answer list:
2a. try to validate the first RRset we find in unvalidated answer
list
2b. if that worked: add to validated answer; if DNSKEY also add to
validated keys list; remove from unvalidated answer.
2c. continue at 2a, with the next RRset, or restart from the
beginning when we hit the end
3. as long as the following changes the unvalidated answer list:
3a. try to validate the first RRset again. This will necessarily
fail, but we learn the precise error
3b. If this was a "primary" response to the question, fail the
entire transaction. "Primary" in this context means that it is
directly a response to the query, or a CNAME/DNAME for it.
3c. Otherwise, remove the RRset from the unvalidated answer list.
Note that we the too loops in 2 + 3 are actually coded as a single one,
but the dnskeys_finalized bool indicates which loop we are currently
processing.
Note that loop 2 does not drop any invalidated RRsets yet, that's
something only loop 3 does. This is because loop 2 might still encounter
additional DNSKEYS which might validate more stuff, and if we'd already
have dropped those RRsets we couldn't validate those anymore. The first
loop is hence a "constructive" loop, the second loop a "destructive"
one: the first one validates whatever is possible, the second one then
deletes whatever still isn't.
This adds a new validation result DNSSEC_UNSUPPORTED_ALGORITHM which is
returned when we encounter an unsupported crypto algorithm when trying
to validate RRSIG/DNSKEY combinations. Previously we'd return ENOTSUPP
in this case, but it's better to consider this a non-error DNSSEC
validation result, since our reaction to this case needs to be more like
in cases such as expired or missing keys: we need to keep continue
validation looking for another RRSIG/DNSKEY combination that works
better for us.
This also reworks how dnssec_validate_rrsig_search() propagates errors
from dnssec_validate_rrsig(). Previously, errors such as unsupported
algorithms or expired signatures would not be propagated, but simply be
returned as "missing-key".
resolved: rework how and when the number of answer RRs to cache is determined
Instead of figuring out how many RRs to cache right before we do so,
determine this at the time we install the answer RRs, so that we can
still alter this as we manipulate the answer during validation.
The primary purpose of this is to pave the way so that we can drop
unsigned RRsets from the answer and invalidate the number of RRs to
cache at the same time.
resolved: refuse OPT RRs in incoming packets that are not in the additional section
We later rely that the DnsAnswer object contains all RRs from the
original packet, at least when it comes to the answer and authorization
sections, hence we better make sure we don#t silently end up removing an
OPT RR from these two sections.
Tom Gundersen [Thu, 10 Dec 2015 18:57:41 +0000 (19:57 +0100)]
resolved: cache - don't flush the cache of mDNS records unneccesarily
When the DNS_RESOURCE_KEY_CACHE_FLUSH flag is not set for an mDNS packet, we should not flush
the cache for RRs with matching keys. However, we were unconditionally flushing the cache
also for these packets.
Now mark all packets as cache_flush by default, except for these mDNS packets, and respect
that flag in the cache handling.
Tom Gundersen [Thu, 3 Dec 2015 20:40:06 +0000 (21:40 +0100)]
resolved: cache - rework which RR types we apply redirection to
The logic of dns_cache_get() is now:
- look up the precise key;
- look up NXDOMAIN item;
- if an RR type that may be redirected
(i.e., not CNAME, DNAME, RRSIG, NSEC, NSEC3, SIG, KEY, or
NXT) look up a correpsonding CNAME or DNAME record;
- look up a corresponding NSEC record;
Before this change we would give up before potentially finding
negative cache entries for DNAME, CNAME and NSEC records, we
would return NSEC records for aliases where we had DNAME or CNAME
records available and we would incorrectly try to redirect DNSSEC RRs.
Tom Gundersen [Wed, 2 Dec 2015 17:46:32 +0000 (18:46 +0100)]
resolved: cache - do negative caching only on the canonical name
Apart from dropping redundant information, this fixes an issue
where, due to broken DNS servers, we can only be certain of whether
an apparent NODATA response is in fact an NXDOMAIN response after
explicitly resolving the canonical name. This issue is outlined in
RFC2308. Moreover, by caching NXDOMAIN for an existing name, we
would mistakenly return NXDOMAIN for types which should not be
redirected. I.e., a query for AAAA on test-nx-1.jklm.no correctly
returns NXDOMAIN, but a query for CNAME should return the record
and a query for DNAME should return NODATA.
Note that this means we will not cache an NXDOMAIN response in the
presence of redirection, meaning one redundant roundtrip in case the
name is queried again.
The current code is not compatible with current dkr protocols anyway,
and dkr has a different focus ("microservices") than nspawn anyway
("whole machine containers"), hence drop support for it, we cannot
reasonably keep this up to date, and it creates the impression we'd
actually care for the microservices usecase.
Jorgen Schaefer [Thu, 10 Dec 2015 12:24:45 +0000 (13:24 +0100)]
Use /proc/net/sockstat6 to detect IPv6 support
The file /sys/module/ipv6 does not exist in all container
implementations (e.g. Virtuozzo). Using /proc/net/sockstat6
detects IPv6 support reliably in these environments, too.
This file does not exist when the kernel is not compiled with
IPv6 support, or if IPv6 support is disabled, so simply checking
for existence should be a suitable check.
resolved: chase DNSKEY/DS RRs when doing look-ups with DNSSEC enabled
This adds initial support for validating RRSIG/DNSKEY/DS chains when
doing lookups. Proof-of-non-existance, or proof-of-unsigned-zones is not
implemented yet.
With this change DnsTransaction objects will generate additional
DnsTransaction objects when looking for DNSKEY or DS RRs to validate an
RRSIG on a response. DnsTransaction objects are thus created for three
reasons now:
1) Because a user asked for something to be resolved, i.e. requested by
a DnsQuery/DnsQueryCandidate object.
2) As result of LLMNR RR probing, requested by a DnsZoneItem.
3) Because another DnsTransaction requires the requested RRs for
validation of its own response.
DnsTransactions are shared between all these users, and are GC
automatically as soon as all of these users don't need a specific
transaction anymore.
To unify the handling of these three reasons for existance for a
DnsTransaction, a new common naming is introduced: each DnsTransaction
now tracks its "owners" via a Set* object named "notify_xyz", containing
all owners to notify on completion.
A new DnsTransaction state is introduced called "VALIDATING" that is
entered after a response has been receieved which needs to be validated,
as long as we are still waiting for the DNSKEY/DS RRs from other
DnsTransactions.
This patch will request the DNSKEY/DS RRs bottom-up, and then validate
them top-down.
Caching of RRs is now only done after verification, so that the cache is
not poisoned with known invalid data.
The "DnsAnswer" object gained a substantial number of new calls, since
we need to add/remove RRs to it dynamically now.
When increasing the DnsAnswer array, don't operate piecemeal, grow the
array exponentially.
This way, the default logic for DnsAnswer allocations matches the
behaviour for GREEDY_REALLOC and suchlike, and we can reduce the number
of necessary allocations.
resolved: when parsing DNS packets, handle OPT RR specially
As soon as we encounter the OPT RR while parsing, store it in a special
field in the DnsPacket structure. That way, we won't be confused if we
iterate through RRs, and can check that there's really only one of these
RRs around.
resolved: refuse modifying DnsAnswer objects that have more than one reference
DnsAnswer objects should be considered immutable after having passed to
more than one user, i.e. with a reference counter > 1. Enforce that in
code, so that we can track down misuses easier.