summaryrefslogtreecommitdiff
path: root/src/resolve/resolved-dns-transaction.c
AgeCommit message (Collapse)Author
2016-01-25resolved: log each time we increase the DNSSEC verdict countersLennart Poettering
Also, don't consider RRs that aren't primary to the lookups we do as relevant to the lookups.
2016-01-25resolved: if we detect a message with incomplete DNSSEC data, consider this ↵Lennart Poettering
an invalid packet event
2016-01-25resolved: also collect statistics about negative DNSSEC proofsLennart Poettering
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-25resolve: generate a nice clean error when clients try to resolve a name when ↵Lennart Poettering
the network is down
2016-01-18resolved: don't try to print error strings, where errno isn't setLennart Poettering
2016-01-18resolved: when restarting a transaction pick a new IDLennart Poettering
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-18resolved: enforce maximum limit on DNS transactionsLennart Poettering
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-18resolved: fix how we detect whether auxiliary DNSSEC transactions are readyLennart Poettering
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-17resolved: when we find a DNAME RR, don't insist in a signed CNAME RRLennart Poettering
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-17resolved: when the server feature level changes between query and response ↵Lennart Poettering
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-17resolved: check OPT RR before accepting a reply for verification of server ↵Lennart Poettering
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-17resolved: when restarting a DNS transaction, remove all auxiliary DNSSEC ↵Lennart Poettering
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-17resolved: downgrade server feature level more aggressively when we have ↵Lennart Poettering
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-17resolved: rename dnssec_verify_dnskey() → dnssec_verify_dnskey_by_ds()Lennart Poettering
This should clarify that this is not regular signature-based validation, but validation through DS RR fingerprints.
2016-01-17resolved: when validating an RRset, store information about the synthesizing ↵Lennart Poettering
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-13resolved: implement the full NSEC and NSEC3 postive wildcard proofsLennart Poettering
2016-01-11resolved: refuse doing queries for known-obsolete RR typesLennart Poettering
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-11resolved: rename DnsTransaction's current_features field to ↵Lennart Poettering
current_feature_level This is a follow-up for f4461e5641d53f27d6e76e0607bdaa9c0c58c1f6.
2016-01-11resolved: accept rightfully unsigned NSEC responsesLennart Poettering
2016-01-11resolved: rework how and when we detect whether our chosen DNS server knows ↵Lennart Poettering
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-11resolved: rework server feature level logicLennart Poettering
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-11resolved: log why we use TCP when UDP isn't supported by a serverLennart Poettering
2016-01-11resolved: log about truncated replies before trying again, not afterLennart Poettering
2016-01-11resolved: don't attempt to send queries for DNSSEC RR types to servers not ↵Lennart Poettering
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-11resolved: log about reasons for switching to TCPLennart Poettering
2016-01-11resolved: properly handle UDP ICMP errors as lost packetsLennart Poettering
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-11resolved: when we get a TCP connection failure, try againLennart Poettering
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-11resolved: introduce dns_transaction_retry() and use it everywhereLennart Poettering
The code to retry transactions has been used over and over again, simplify it by replacing it by a new function.
2016-01-11resolved: set a description on all our event sourcesLennart Poettering
2016-01-11resolved: properly look for NSEC/NSEC3 RRs when getting a positive wildcard ↵Lennart Poettering
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-11resolved: when validating, first strip revoked trust anchor keys from ↵Lennart Poettering
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-11resolved: rework trust anchor revoke checkingLennart Poettering
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-11resolved: look for revoked trust anchors before validating a messageLennart Poettering
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-11resolved: remove one level of indentation in dns_transaction_validate_dnssec()Lennart Poettering
Invert an "if" check, so that we can use "continue" rather than another code block indentation.
2016-01-06resolved: introduce support for per-interface negative trust anchorsLennart Poettering
2016-01-06resolved: count unsupported dnssec algorithm as indeterminate RRsetLennart Poettering
After all, when we don't support the algorithm we cannot determine validity.
2016-01-05resolved: try to detect fritz.box-style private DNS zones, and downgrade to ↵Lennart Poettering
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-05resolved: fix DNSSEC transaction dependency recursion checkLennart Poettering
We followed the wrong connection. This only worked sometimes at all, because we also return the wrong error code.
2016-01-05resolved: rename "downgrade-ok" mode to "allow-downgrade"Lennart Poettering
After discussing this with Tom, we figured out "allow-downgrade" sounds nicer.
2016-01-05resolved: when caching negative responses, honour NSEC/NSEC3 TTLsLennart Poettering
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-04resolved: explicitly handle case when the trust anchor is emptyLennart Poettering
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-04resolved: explicitly avoid cyclic transaction dependenciesLennart Poettering
We already try hard not to create cyclic transaction dependencies, where a transaction requires another one for DNSSEC validation purposes, which in turn (possibly indirectly) pulls in the original transaction again, thus resulting in a cyclic dependency and ultimately a deadlock since each transaction waits for another one forever. So far we wanted to avoid such cyclic dependencies by only going "up the tree" when requesting auxiliary RRs and only going from one RR type to another, but never back. However this turned out to be insufficient. Consider a domain that publishes one or more DNSKEY but which has no DS for it. A request for the domain's DNSKEY triggers a request for the domain's DS, which will then fail, but return an NSEC, signed by the DNSKEY. To validate that we'd request the DNSKEY again. Thus a DNSKEY request results in a DS request which results in the original DNSKEY request again. If the original lookup had been a DS lookup we'd end up in the same cyclic dependency, hence we cannot statically break one of them, since both requests are of course fully valid. Hence, do full cyclic dependency checking: each time we are about to add a dependency to a transaction, check if the transaction is already a dependency of the dependency (recursively down the tree).
2016-01-04resolved: block transaction GC'ing while ↵Lennart Poettering
dns_transaction_request_dnssec_keys() is running If any of the transactions started by dns_transaction_request_dnssec_keys() finishes promptly without requiring asynchronous operation this is reported back to the issuing transaction from the same stackframe. This might ultimately result in this transaction to be freed while we are still in its _request_dnssec_keys() stack frame. To avoid memory corruption block the transaction GC while in the call, and manually issue a GC after it returned.
2016-01-04resolved: partially implement RFC5011 Trust Anchor supportLennart Poettering
With this patch resolved will properly handle revoked keys, but not augment the locally configured trust anchor database with newly learned keys. Specifically, resolved now refuses validating RRsets with revoked keys, and it will remove revoked keys from the configured trust anchors (only until reboot). This patch does not add logic for adding new keys to the set of trust anchors. This is a deliberate decision as this only can work with persistent disk storage, and would result in a different update logic for stateful and stateless systems. Since we have to support stateless systems anyway, and don't want to encourage two independent upgrade paths we focus on upgrading the trust anchor database via the usual OS upgrade logic. Whenever a trust anchor entry is found revoked and removed from the trust anchor a recognizable log message is written, encouraging the user to update the trust anchor or update his operating system.
2016-01-04resolved: actually make use of message ID when logging about failed DNSSEC ↵Lennart Poettering
validation
2016-01-03Merge pull request #2255 from teg/resolved-fixes-2Lennart Poettering
Fixes to NSEC3 proof v2
2016-01-03resolved: add negative trust anchro support, and add trust anchor ↵Lennart Poettering
configuration files This adds negative trust anchor support and allows reading trust anchor data from disk, from files /etc/systemd/dnssec-trust-anchors.d/*.positive and /etc/systemd/dnssec-trust-anchros.d/*.negative, as well as the matching counterparts in /usr/lib and /run. The positive trust anchor files are more or less compatible to normal DNS zone files containing DNSKEY and DS RRs. The negative trust anchor files contain only new-line separated hostnames for which to require no signing. By default no trust anchor files are installed, in which case the compiled-in root domain DS RR is used, as before. As soon as at least one positive root anchor for the root is defined via trust anchor files this buil-in DS RR is not added though.
2016-01-03resolved: don't conclude NODATA if CNAME existsTom Gundersen
Instead introduce the new return-code DNSSEC_NSEC_CNAME to indicate this condition. See RFC 6840, Section 4.3.
2016-01-02resolved: explain why we don't check IP addresses/ports of incoming DNS UDP ↵Lennart Poettering
traffic
2015-12-28resolved: clean up dns_transaction_stop()Lennart Poettering
This renames dns_transaction_stop() to dns_transaction_stop_timeout() and makes it only about stopping the transaction timeout. This is safe, as in most occasions we call dns_transaction_stop() at the same time as dns_transaction_close_connection() anyway, which does the rest of what dns_transaction_stop() used to do. And in the one where we don't call it, it's implicitly called by the UDP emission or TCP connection code. This also closes the connections as we enter the validation phase of a transaction, so that no further messages may be received then.