Commit Graph

173 Commits

Author SHA1 Message Date
Michael Biebl c629ff587b Typo fixes 2016-02-12 00:26:37 +01:00
Daniel Mack b26fa1a2fb tree-wide: remove Emacs lines from all files
This should be handled fine now by .dir-locals.el, so need to carry that
stuff in every file.
2016-02-10 13:41:57 +01:00
Lennart Poettering 011696f762 resolved: rework what ResolveHostname() with family == AF_UNSPEC means
Previously, if a hostanem is resolved with AF_UNSPEC specified, this would be used as indication to resolve both an
AF_INET and an AF_INET6 address. With this change this logic is altered: an AF_INET address is only resolved if there's
actually a routable IPv4 address on the specific interface, and similar an AF_INET6 address is only resolved if there's
a routable IPv6 address. With this in place, it's ensured that the returned data is actually connectable by
applications. This logic mimics glibc's resolver behaviour.

Note that if the client asks explicitly for AF_INET or AF_INET6 it will get what it asked for.

This also simplifies the logic how it is determined whether a specific lookup shall take place on a scope.
Specifically, the checks with dns_scope_good_key() are now moved out of the transaction code and into the query code,
so that we don't even create a transaction object on a specific scope if we cannot execute the resolution on it anyway.
2016-02-01 22:18:15 +01:00
Torstein Husebø e94968ba72 resolve: fix typos 2016-02-01 21:08:00 +01:00
Lennart Poettering eac7cda211 resolved: fix the rcode to SUCCESS if we find at least one matching RR in a DNS response
If we encounter NXDOMAIN, but find at least one matching RR in a response, then patch it to become SUCCESS. This should
clean up handling of CNAME/DNAMEs, and makes sure broken servers and those conforming to RFC 6604 are treated the same
way. The new behaviour opposes the logic suggested in RFC 6604, but given that some servers don't implement it
correctly, and given that in some ways the CNAME/DNAME chains will be incomplete anyway, and given that DNSSEC
generally only allows us to prove the first element of a CNAME/DNAME chain, this should simplify things for us.
2016-01-26 14:42:04 +01:00
Lennart Poettering 4cb94977ed resolved: don't consider NSEC/NSEC3 RRs as "pimary" for transactions
So far, abritrary NSEC and NSEC3 RRs were implicitly consider "primary" for any transaction, meaning we'd abort the
transaction immediately if we couldn't validate it. With this patch this logic is removed, and the NSEC/NSEC3 RRs will
not be considered primary anymore. This has the effect that they will be dropped from the message if they don't
validate, but processing continues. This is safe to do, as they are required anyway to validate positive wildcard and
negative responses, and if they are missing then, then message will be considered unsigned, which hence means the
outcome is effectively the same.

This is benefical in case the server sends us NSEC/NSEC3 RRs that are not directly related to the lookup we did, but
simply auxiliary information. Previously, if we couldn't authenticate those RRs we'd fail the entire lookup while with
this change we'll simply drop the auxiliary information and proceed without it.
2016-01-25 17:19:20 +01:00
Lennart Poettering 7cc6ed7ba6 resolved: replace DNS_TRANSACTION_RESOURCES by DNS_TRANSACTION_ERRNO
Whenever we encounter an OS error we did not expect, we so far put the transaction into DNS_TRANSACTION_RESOURCES
state. Rename this state to DNS_TRANSACTION_ERRNO, and save + propagate the actual system error to the caller. This
should make error messages triggered by system errors much more readable by the user.
2016-01-25 17:19:19 +01:00
Lennart Poettering 1e02e182f1 resolved: log recognizably about DNSSEC downgrades
If we downgrade from DNSSEC to non-DNSSEC mode, let's log about this in a recognizable way (i.e. with a message ID),
after all, this is of major importance.
2016-01-25 17:19:19 +01:00
Lennart Poettering 0791110fbe resolved: properly handle LLMNR/TCP connection errors
The LLMNR spec suggests to do do reverse address lookups by doing direct LLMNR/TCP connections to the indicated
address, instead of doing any LLMNR multicast queries. When we do this and the peer doesn't actually implement LLMNR
this will result in a TCP connection error, which we need to handle. In contrast to most LLMNR lookups this will give
us a quick response on whether we can find a suitable name. Report this as new transaction state, since this should
mostly be treated like an NXDOMAIN rcode, except that it's not one.
2016-01-25 17:19:19 +01:00
Lennart Poettering 59c5b5974d resolved: log each time we increase the DNSSEC verdict counters
Also, don't consider RRs that aren't primary to the lookups we do as relevant to the lookups.
2016-01-25 17:19:19 +01:00
Lennart Poettering fcfaff1235 resolved: if we detect a message with incomplete DNSSEC data, consider this an invalid packet event 2016-01-25 17:19:19 +01:00
Lennart Poettering 7aa8ce9855 resolved: also collect statistics about negative DNSSEC proofs
We already maintain statistics about positive DNSSEC proofs, and count them up by 1 for each validated RRset. Now,
update the same counters each time we validated a negative query, so that the statistics are the combined result of all
validation checks, both positive and negative.
2016-01-25 17:19:19 +01:00
Lennart Poettering edbcc1fdd9 resolve: generate a nice clean error when clients try to resolve a name when the network is down 2016-01-25 15:59:40 +01:00
Lennart Poettering e09f605eec resolved: don't try to print error strings, where errno isn't set 2016-01-18 23:31:29 +01:00
Lennart Poettering 4dd15077f3 resolved: when restarting a transaction pick a new ID
When we restart a transaction because of an incompatible server, pick a new transaction ID.

This should increase compatibility with DNS servers that don't like if they get different requests with the same
transaction ID.
2016-01-18 23:31:29 +01:00
Lennart Poettering b214dc0f68 resolved: enforce maximum limit on DNS transactions
given that DNSSEC lookups may result in quite a number of auxiliary transactions, let's better be safe than sorry and
also enforce a limit on the number of total transactions, not just on the number of queries.
2016-01-18 23:31:29 +01:00
Lennart Poettering 942eb2e71b resolved: fix how we detect whether auxiliary DNSSEC transactions are ready
Previously, when getting notified about a completed auxiliary DNSSEC transaction we'd immediately act on it, and
possibly abort the main transaction. This is problematic, as DNS transactions that already completed at the time we
started using them will never get the notification event, and hence never be acted on in the same way.

Hence, introduce a new call dns_transaction_dnssec_ready() that checks the state of auxiliary DNSSEC transactions, and
returns 1 when we are ready for the actual DNSSEC validation step. Then, make sure this is invoked when the auxiliary
transactions are first acquired (and thus possibly reused) as well when the notifications explained above take place.

This fixes problems particularly when doing combined A and AAAA lookups  where the auxiliary DNSSEC transactions get
reused between them, and where we got confused if we reused an auxiliary DNSSEC transaction from one when it already
got completed from the other.
2016-01-18 23:31:16 +01:00
Lennart Poettering 43e6779ac2 resolved: when we find a DNAME RR, don't insist in a signed CNAME RR
If we have a signed DNAME RR response, there's no need to insist on a signature for a CNAME RR response, after all it
is unlikely to be signed, given the implicit synthethis of CNAME through DNAME RRs.
2016-01-17 21:50:10 +01:00
Lennart Poettering c02cf2f41f resolved: when the server feature level changes between query and response restart transaction
In some cases we learn something about a server's feature level through its responses. If we notice that after doing
basic checking of a response, and after collecting all auxiliary DNSSEC info the feature level of the server is lower
than where we started, restart the whole transaction.

This is useful to deal with servers that response rubbish when talked to with too high feature levels.
2016-01-17 20:47:46 +01:00
Lennart Poettering ed9717fcbf resolved: check OPT RR before accepting a reply for verification of server feature level
Let's make sure we first check if the OPT was lost in the reply, before we accept a reply as successful and use it for
verifying the current feature level.
2016-01-17 20:47:46 +01:00
Lennart Poettering c5b4f86178 resolved: when restarting a DNS transaction, remove all auxiliary DNSSEC transactions
When we restart a DNS transaction, remove all connections to any auxiliary DNSSEC transactions, after all we might
acquire completely different data this time, requiring different auxiliary DNSSEC transactions.
2016-01-17 20:47:46 +01:00
Lennart Poettering de54e62b4b resolved: downgrade server feature level more aggressively when we have reason to
This adds logic to downgrade the feature level more aggressively when we have reason to. Specifically:

- When we get a response packet that lacks an OPT RR for a query that had it. If so, downgrade immediately to UDP mode,
  i.e. don't generate EDNS0 packets anymore.

- When we get a response which we are sure should be signed, but lacks RRSIG RRs, we downgrade to EDNS0 mode, i.e.
  below DO mode, since DO is apparently not really supported.

This should increase compatibility with servers that generate non-sensical responses if they messages with OPT RRs and
suchlike, for example the situation described here:

https://open.nlnetlabs.nl/pipermail/dnssec-trigger/2014-November/000376.html

This also changes the downgrade code to explain in a debug log message why a specific downgrade happened.
2016-01-17 20:47:46 +01:00
Lennart Poettering 96bb76734d resolved: rename dnssec_verify_dnskey() → dnssec_verify_dnskey_by_ds()
This should clarify that this is not regular signature-based validation, but validation through DS RR fingerprints.
2016-01-17 20:47:45 +01:00
Lennart Poettering 97c67192ea resolved: when validating an RRset, store information about the synthesizing source and zone in each RR
Having this information available is useful when we need to check whether various RRs are suitable for proofs. This
information is stored in the RRs as number of labels to skip from the beginning of the owner name to reach the
synthesizing source/signer. Simple accessor calls are then added to retrieve the signer/source from the RR using this
information.

This also moves validation of a a number of RRSIG parameters into a new call dnssec_rrsig_prepare() that as side-effect
initializes the two numeric values.
2016-01-17 20:47:45 +01:00
Lennart Poettering e926785a1f resolved: implement the full NSEC and NSEC3 postive wildcard proofs 2016-01-13 20:21:57 +01:00
Lennart Poettering d0129ddb9f resolved: refuse doing queries for known-obsolete RR types
Given how fragile DNS servers are with some DNS types, and given that we really should avoid confusing them with
known-weird lookups, refuse doing lookups for known-obsolete RR types.
2016-01-11 20:05:29 +01:00
Lennart Poettering 274b874830 resolved: rename DnsTransaction's current_features field to current_feature_level
This is a follow-up for f4461e5641.
2016-01-11 19:40:00 +01:00
Lennart Poettering 372dd764a6 resolved: accept rightfully unsigned NSEC responses 2016-01-11 19:40:00 +01:00
Lennart Poettering 92ec902aad resolved: rework how and when we detect whether our chosen DNS server knows DNSSEC
Move detection into a set of new functions, that check whether one specific server can do DNSSEC, whether a server and
a specific transaction can do DNSSEC, or whether a transaction and all its auxiliary transactions could do so.

Also, do these checks both before we acquire additional RRs for the validation (so that we can skip them if the server
doesn't do DNSSEC anyway), and after we acquired them all (to see if any of the lookups changed our opinion about the
servers).

THis also tightens the checks a bit: a server that lacks TCP support is considered incompatible with DNSSEC too.
2016-01-11 19:40:00 +01:00
Lennart Poettering 6bb2c08597 resolved: rework server feature level logic
This changes the DnsServer logic to count failed UDP and TCP failures separately. This is useful so that we don't end
up downgrading the feature level from one UDP level to a lower UDP level just because a TCP connection we did because
of a TC response failed.

This also adds accounting of truncated packets. If we detect incoming truncated packets, and count too many failed TCP
connections (which is the normal fall back if we get a trucnated UDP packet) we downgrade the feature level, given that
the responses at the current levels don't get through, and we somehow need to make sure they become smaller, which they
will do if we don't request DNSSEC or EDNS support.

This makes resolved work much better with crappy DNS servers that do not implement TCP and only limited UDP packet
sizes, but otherwise support DNSSEC RRs. They end up choking on the generally larger DNSSEC RRs and there's no way to
retrieve the full data.
2016-01-11 19:40:00 +01:00
Lennart Poettering 034e803191 resolved: log why we use TCP when UDP isn't supported by a server 2016-01-11 19:40:00 +01:00
Lennart Poettering f757cd8510 resolved: log about truncated replies before trying again, not after 2016-01-11 19:40:00 +01:00
Lennart Poettering 91adc4db33 resolved: don't attempt to send queries for DNSSEC RR types to servers not supporting them
If we already degraded the feature level below DO don't bother with sending requests for DS, DNSKEY, RRSIG, NSEC, NSEC3
or NSEC3PARAM RRs. After all, we cannot do DNSSEC validation then anyway, and we better not press a legacy server like
this with such modern concepts.

This also has the benefit that when we try to validate a response we received using DNSSEC, and we detect a limited
server support level while doing so, all further auxiliary DNSSEC queries will fail right-away.
2016-01-11 19:40:00 +01:00
Lennart Poettering 29ab055292 resolved: log about reasons for switching to TCP 2016-01-11 19:40:00 +01:00
Lennart Poettering 7e1851e3c6 resolved: properly handle UDP ICMP errors as lost packets
UDP ICMP errors are reported to us via recvmsg() when we read a reply. Handle this properly, and consider this a lost
packet, and retry the connection.

This also adds some additional logging for invalid incoming packets.
2016-01-11 19:40:00 +01:00
Lennart Poettering a1a3f73a57 resolved: when we get a TCP connection failure, try again
Previously, when we couldn't connect to a DNS server via TCP we'd abort the whole transaction using a
"connection-failure" state. This change removes that, and counts failed connections as "lost packet" events, so that
we switch back to the UDP protocol again.
2016-01-11 19:39:59 +01:00
Lennart Poettering 8d10d62055 resolved: introduce dns_transaction_retry() and use it everywhere
The code to retry transactions has been used over and over again, simplify it by replacing it by a new function.
2016-01-11 19:39:59 +01:00
Lennart Poettering aa4a9deb7d resolved: set a description on all our event sources 2016-01-11 19:39:59 +01:00
Lennart Poettering 0c7bff0acc resolved: properly look for NSEC/NSEC3 RRs when getting a positive wildcard response
This implements RFC 5155, Section 8.8 and RFC 4035, Section 5.3.4:

When we receive a response with an RRset generated from a wildcard we
need to look for one NSEC/NSEC3 RR that proves that there's no explicit RR
around before we accept the wildcard RRset as response.

This patch does a couple of things: the validation calls will now
identify wildcard signatures for us, and let us know the RRSIG used (so
that the RRSIG's signer field let's us know what the wildcard was that
generate the entry). Moreover, when iterating trough the RRsets of a
response we now employ three phases instead of just two.

a) in the first phase we only look for DNSKEYs RRs
b) in the second phase we only look for NSEC RRs
c) in the third phase we look for all kinds of RRs

Phase a) is necessary, since DNSKEYs "unlock" more signatures for us,
hence we shouldn't assume a key is missing until all DNSKEY RRs have
been processed.

Phase b) is necessary since NSECs need to be validated before we can
validate wildcard RRs due to the logic explained above.

Phase c) validates everything else. This phase also handles RRsets that
cannot be fully validated and removes them or lets the transaction fail.
2016-01-11 19:39:59 +01:00
Lennart Poettering c9c7206541 resolved: when validating, first strip revoked trust anchor keys from validated keys list
When validating a transaction we initially collect DNSKEY, DS, SOA RRs
in the "validated_keys" list, that we need for the proofs. This includes
DNSKEY and DS data from our trust anchor database. Quite possibly we
learn that some of these DNSKEY/DS RRs have been revoked between the
time we request and collect those additional RRs and we begin the
validation step. In this case we need to make sure that the respective
DS/DNSKEY RRs are removed again from our list. This patch adds that, and
strips known revoked trust anchor RRs from the validated list before we
begin the actual validation proof, and each time we add more DNSKEY
material to it while we are doing the proof.
2016-01-11 19:39:59 +01:00
Lennart Poettering d424da2ae0 resolved: rework trust anchor revoke checking
Instead of first iterating through all DNSKEYs in the DnsAnswer in
dns_transaction_check_revoked_trust_anchors(), and
then doing that a second time in dns_trust_anchor_check_revoked(), do so
only once in the former, and pass the dnskey we found directly to the
latter.
2016-01-11 19:39:59 +01:00
Lennart Poettering 0f87f3e8e7 resolved: look for revoked trust anchors before validating a message
There's not reason to wait for checking for revoked trust anchors until
after validation, after all revoked DNSKEYs only need to be self-signed,
but not have a full trust chain.

This way, we can be sure that all trust anchor lookups we do during
validation already honour that some keys might have been revoked.
2016-01-11 19:39:59 +01:00
Lennart Poettering f3cf586d56 resolved: remove one level of indentation in dns_transaction_validate_dnssec()
Invert an "if" check, so that we can use "continue" rather than another
code block indentation.
2016-01-11 19:39:58 +01:00
Lennart Poettering 8a516214c4 resolved: introduce support for per-interface negative trust anchors 2016-01-06 18:36:32 +01:00
Lennart Poettering e497292aba resolved: count unsupported dnssec algorithm as indeterminate RRset
After all, when we don't support the algorithm we cannot determine
validity.
2016-01-06 00:57:24 +01:00
Lennart Poettering d33b6cf343 resolved: try to detect fritz.box-style private DNS zones, and downgrade to non-DNSSEC mode for them
This adds logic to detect cases like the Fritz!Box routers which serve
a private DNS domain "fritz.box" under the TLD "box" that does not
exist in the root servers. If this is detected DNSSEC validation is
turned off for this private domain, thus improving compatibility with
such private DNS zones.

This should be fairly secure as we first rely on the proof that .box
does not exist before this logic is applied. Nevertheless the logic is
only enabled for DNSSEC=allow-downgrade mode.

This logic does not work for routers that set up a full DNS zone directly
under a non-existing TLD, as in that case we cannot prove
that the domain is truly non-existing according to the root servers.
2016-01-05 22:13:56 +01:00
Lennart Poettering 3eb6aa009d resolved: fix DNSSEC transaction dependency recursion check
We followed the wrong connection. This only worked sometimes at all, because we
also return the wrong error code.
2016-01-05 20:27:18 +01:00
Lennart Poettering 1ed8c0fbb4 resolved: rename "downgrade-ok" mode to "allow-downgrade"
After discussing this with Tom, we figured out "allow-downgrade" sounds
nicer.
2016-01-05 20:00:53 +01:00
Lennart Poettering d3760be01b resolved: when caching negative responses, honour NSEC/NSEC3 TTLs
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.
2016-01-05 01:35:28 +01:00
Lennart Poettering b2b796b8ab resolved: explicitly handle case when the trust anchor is empty
Since we honour RFC5011 revoked keys it might happen we end up with an
empty trust anchor, or one where there's no entry for the root left.
With this patch the logic is changed what to do in this case.

Before this patch we'd end up requesting the root DS, which returns with
NODATA but a signed NSEC we cannot verify, since the trust anchor is
empty after all. Thus we'd return a DNSSEC result of "missing-key", as
we lack a verified version of the key.

With this patch in place, look-ups for the root DS are explicitly
recognized, and not passed on to the DNS servers. Instead, if
downgrade-ok mode is on an unsigned NODATA response is synthesized, so
that the validator code continues under the assumption the root zone was
unsigned. If downgrade-ok mode is off a new transaction failure is
generated, that makes this case recognizable.
2016-01-04 22:42:10 +01:00