Age | Commit message (Collapse) | Author |
|
When storing negative responses, clamp the SOA minimum TTL (as suggested
by RFC2308) to the TTL of the NSEC/NSEC3 RRs we used to prove
non-existance, if it there is any.
This is necessary since otherwise an attacker might put together a faked
negative response for one of our question including a high-ttl SOA RR
for any parent zone, and we'd use trust the TTL.
|
|
|
|
This makes sure that we also honour the RRSIG expiry for negative
caching.
|
|
When we verified a signature, fix up the RR's TTL to the original TTL
mentioned in the signature, and store the signature expiry information
in the RR, too. Then, use that when adding RRs to the cache.
|
|
This collects statistical data about transactions, dnssec verifications
and the cache, and exposes it over the bus. The systemd-resolve-host
tool learns new options to query these statistics and reset them.
|
|
Let's simplify usage and memory management of DnsResourceRecord's
dns_resource_record_to_string() call: cache the formatted string as
part of the object, and return it on subsequent calls, freeing it when
the DnsResourceRecord itself is freed.
|
|
entries
We use ANY RR keys to store NXDOMAIN information, but we previously
didn't flush out old ANY RR items in the cache when adding new entries.
Fix that.
|
|
Let's abstract which RRs shall honour CNAMEs, and which ones should not.
|
|
|
|
In most of the other call, we called similar functions that remove the
data structure link-ups to other objects "unlink", hence we should here,
too.
|
|
Given that we already have dns_cache_remove_by_rr() this makes clearer
what the operation actually does.
|
|
This adds a new DnsAnswer item flag "DNS_ANSWER_SHARED_OWNER" which is
set for mDNS RRs that lack the cache-flush bit. The cache-flush bit is
removed from the DnsResourceRecord object in favour of this.
This also splits out the code that removes previous entries when adding
new positive ones into a new separate call dns_cache_remove_previous().
|
|
After all we want to allow NULL DnsAnswer objects as equivalent to empty
ones, hence we should use the right checks everywhere.
|
|
Make sure the cache never altes the authenticated bit of RRs stored in
it, and drops it for RRs when passing it out again.
|
|
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.
|
|
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.
|
|
|
|
|
|
We should never use the TTL of an unauthenticated SOA to cache an
authenticated RR.
|
|
We call it anyway as one of the first calls in dns_cache_put(), hence
there's no reason to do this multiple times.
|
|
Let's keep entries for longer and more of them. After all, due to the
DNSSEC hookup the amount of RRs we need to store is much higher now.
|
|
|
|
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.
|
|
|
|
|
|
This is in the fast path, so let's not do all this work unneccessarily.
|
|
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.
This fixes 90325e8c2e559a21ef0bc2f26b844c140faf8020.
|
|
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.
|
|
Some DNS servers will hand out negative answers without SOA records,
these can not be cached, so log about that fact.
|
|
An NXDOMAIN entry means there are no RRs of any type for a name,
so only cache by CLASS + NAME, rather than CLASS + NAME + TYPE.
|
|
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.
|
|
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.
|
|
Quoting @teg:
"Contrary to what the comment said, we always verify redirect chains in
full, and cache all the CNAME records. There is therefore no need to
do extra negative caching along a CNAME chain."
This simply steals @teg's commit since we'll touch the SOA matching case
in a later patch, and rather want this bit gone, so that we don't have
to "fix" it, only to remove it later on.
|
|
For mDNS, if we're unable to stuff all known answers into the given packet,
allocate a new one, push the RR into that one and link it to the current
one.
|
|
This new functions exports cached records of type PTR, SRV and TXT into
an existing DnsPacket. This is used in order to fill in known records
to mDNS queries, for known answer supression.
|
|
In mDNS, DNS_RESOURCE_KEY_CACHE_FLUSH denotes whether other records with the
same key should be flushed from the cache.
|
|
This adds a new SD_RESOLVED_AUTHENTICATED flag for responses we return
on the bus. When set, then the data has been authenticated. For now this
mostly reflects the DNSSEC AD bit, if DNSSEC=trust is set. As soon as
the client-side validation is complete it will be hooked up to this flag
too.
We also set this bit whenver we generated the data ourselves, for
example, because it originates in our local LLMNR zone, or from the
built-in trust anchor database.
The "systemd-resolve-host" tool has been updated to show the flag state
for the data it shows.
|
|
When an RR type is not set in an NSEC, then the CNAME/DNAME types might
still be, hence check them too.
Otherwise we might end up refusing resolving of CNAME'd RRs if we cached
an NSEC before.
|
|
Sometimes when looking up entries in hashmaps indexed by a
DnsResourceKey it is helpful not having to allocate a full
DnsResourceKey dynamically just to use it as search key. Instead,
optionally allow allocation of a DnsResourceKey on the stack. Resource
keys allocated like that of course are subject to other lifetime cycles
than the usual Resource keys, hence initialize the reference counter to
to (unsigned) -1.
While we are at it, remove the prototype for
dns_resource_key_new_dname() which was never implemented.
|
|
If we have a precisely matching NSEC RR for a name, we can use its type
bit field to synthesize NODATA cache lookup results for all types not
mentioned in there.
This is useful for mDNS where NSEC RRs are used to indicate missing RRs
for a specific type, but is beneficial in other cases too.
To test this, consider these two lines:
systemd-resolve-host -t NSEC nasa.gov
systemd-resolve-host -t SRV nasa.gov
The second line will not result in traffic as the first line already
cached the NSEC field.
|
|
Most servers apparently always implicitly convert DNAME to CNAME, but
some servers don't, hence implement this properly, as this is required
by edns0.
|
|
|
|
When a NXDATA or a NODATA response is received for an alias it may
include CNAME records from the redirect chain. We should cache the
response for each of these names to avoid needless roundtrips in
the future.
It is not sufficient to do the negative caching only for the
canonical name, as the included redirection chain is not guaranteed
to be complete. In fact, only the final CNAME record from the chain
is guaranteed to be included.
We take care not to cache entries that redirects outside the current
zone, as the SOA will then not be valid.
|
|
CNAME records are special in the way they are treated by DNS servers,
and our cache should mimic that behavior: In case a domain name has an
alias, its CNAME record is returned in place of any other.
Our cache was not doing this despite caching the CNAME records, this
entailed needless lookups to re-resolve the CNAME.
|
|
Only one key is allowed per transaction now, so let's simplify things and only allow putting
one question key into the cache at a time.
|
|
|
|
Patch via coccinelle.
|
|
|
|
Currently, dns_cache_put() does a number of things:
1) It unconditionally removes all keys contained in the passed
question before adding keys from the newly arrived answers.
2) It puts positive entries into the cache for all RRs contained
in the answer.
3) It creates negative entries in the cache for all keys in the
question that are not answered.
Allow passing q = NULL in the parameters and skip 1) and 3), so
we can use that function for mDNS responses. In this case, the
question is irrelevant, we are interested in all answers we got.
|
|
Let's simplify things and only maintain a single RR key per transaction
object, instead of a full DnsQuestion. Unicast DNS and LLMNR don't
support multiple questions per packet anway, and Multicast DNS suggests
coalescing questions beyond a single dns query, across the whole system.
|