Age | Commit message (Collapse) | Author |
|
RSASHA1_NSEC3_SHA1 is an alias for RSASHA1, used to do NSEC3 feature
negotiation. While verifying RRsets there's no difference, hence support
it here.
|
|
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.
|
|
After all, they are for flags and parameters of RRs and already relevant
when dealing with RRs outside of the serialization concept.
|
|
|
|
This adds most basic operation for doing DNSSEC validation on the
client side. However, it does not actually add the verification logic to
the resolver. Specifically, this patch only includes:
- Verifying DNSKEY RRs against a DS RRs
- Verifying RRSets against a combination of RRSIG and DNSKEY RRs
- Matching up RRSIG RRs and DNSKEY RRs
- Matching up RR keys and RRSIG RRs
- Calculating the DNSSEC key tag from a DNSKEY RR
All currently used DNSSEC combinations of SHA and RSA are implemented. Support
for MD5 hashing and DSA or EC cyphers are not. MD5 and DSA are probably
obsolete, and shouldn't be added. EC should probably be added
eventually, if it actually is deployed on the Internet.
|
|
dns_resource_record_to_wire_format()
Now that we have dns_resource_record_to_wire_format() we can generate
the RR serialization we return to bus clients in ResolveRecord() with
it. We pass the RR data along in the original form, not the DNSSEC
canonical form, since that would mean we'd lose RR name casing, which is
however important to keep for DNS-SD services and similar.
|
|
This adds dns_resource_record_to_wire_format() that generates the raw
wire-format of a single DnsResourceRecord object, and caches it in the
object, optionally in DNSSEC canonical form. This call is used later to
generate the RR serialization of RRs to verify.
This adds four new fields to DnsResourceRecord objects:
- wire_format points to the buffer with the wire-format version of the
RR
- wire_format_size stores the size of that buffer
- wire_format_rdata_offset specifies the index into the buffer where the
RDATA of the RR begins (i.e. the size of the key part of the RR).
- wire_format_canonical is a boolean that stores whether the cached wire
format is in DNSSEC canonical form or not.
Note that this patch adds a mode where a DnsPacket is allocated on the
stack (instead of on the heap), so that it is cheaper to reuse the
DnsPacket object for generating this wire format. After all we reuse the
DnsPacket object for this, since it comes with all the dynamic memory
management, and serialization calls we need anyway.
|
|
|
|
When verifying signatures we need to be able to verify the original
data we got for an RR set, and that means we cannot simply drop flags
bits or consider RRs invalid too eagerly. Hence, instead of parsing the
DNSKEY flags store them as-is. Similar, accept the protocol field as it
is, and don't consider it a parsing error if it is not 3.
Of course, this means that the DNSKEY handling code later on needs to
check explicit for protocol != 3.
|
|
|
|
Change the iterator counter so that a different varable is used for each
invocation of the macro, so that it may be nested.
|
|
It essentially does the same as dns_packet_append_raw_string(), hence
make it a wrapper around it.
|
|
|
|
Make gcc cleanup helper calls public in most of our sd-xyz APIs
|
|
|
|
GLIB has recently started to officially support the gcc cleanup
attribute in its public API, hence let's do the same for our APIs.
With this patch we'll define an xyz_unrefp() call for each public
xyz_unref() call, to make it easy to use inside a
__attribute__((cleanup())) expression. Then, all code is ported over to
make use of this.
The new calls are also documented in the man pages, with examples how to
use them (well, I only added docs where the _unref() call itself already
had docs, and the examples, only cover sd_bus_unrefp() and
sd_event_unrefp()).
This also renames sd_lldp_free() to sd_lldp_unref(), since that's how we
tend to call our destructors these days.
Note that this defines no public macro that wraps gcc's attribute and
makes it easier to use. While I think it's our duty in the library to
make our stuff easy to use, I figure it's not our duty to make gcc's own
features easy to use on its own. Most likely, client code which wants to
make use of this should define its own:
#define _cleanup_(function) __attribute__((cleanup(function)))
Or similar, to make the gcc feature easier to use.
Making this logic public has the benefit that we can remove three header
files whose only purpose was to define these functions internally.
See #2008.
|
|
This is often needed for proper DNSSEC support, and even to handle AAAA records
without falling back to TCP.
If the path between the client and server is fully compliant, this should always
work, however, that is not the case, and overlarge packets will get mysteriously
lost in some cases.
For that reason, we use a similar fallback mechanism as we do for palin EDNS0,
EDNS0+DO, etc.:
The large UDP size feature is different from the other supported feature, as we
cannot simply verify that it works based on receiving a reply (as the server
will usually send us much smaller packets than what we claim to support, so
simply receiving a reply does not mean much).
For that reason, we keep track of the largest UDP packet we ever received, as this
is the smallest known good size (defaulting to the standard 512 bytes). If
announcing the default large size of 4096 fails (in the same way as the other
features), we fall back to the known good size. The same logic of retrying after a
grace-period applies.
|
|
This indicates that we can handle DNSSEC records (per RFC3225), even if
all we do is silently drop them. This feature requires EDNS0 support.
As we do not yet support larger UDP packets, this feature increases the
risk of getting truncated packets.
Similarly to how we fall back to plain UDP if EDNS0 fails, we will fall
back to plain EDNS0 if EDNS0+DO fails (with the same logic of remembering
success and retrying after a grace period after failure).
|
|
This is a minimal implementation of RFC6891. Only default values
are used, so in reality this will be a noop.
EDNS0 support is dependent on the current server's feature level,
so appending the OPT pseudo RR is done when the packet is emitted,
rather than when it is assembled. To handle different feature
levels on retransmission, we strip off the OPT RR again after
sending the packet.
Similarly, to how we fall back to TCP if UDP fails, we fall back
to plain UDP if EDNS0 fails (but if EDNS0 ever succeeded we never
fall back again, and after a timeout we will retry EDNS0).
|
|
Needed for EDNS0.
|
|
Previously, we would only degrade on packet loss, but when adding EDNS0 support,
we also have to handle the case where the server replies with an explicit error.
|
|
This is inspired by the logic in BIND [0], follow-up patches
will implement the reset of that scheme.
If we get a server error back, or if after several attempts we don't
get a reply at all, we switch from UDP to TCP for the given
server for the current and all subsequent requests. However, if
we ever successfully received a reply over UDP, we never fall
back to TCP, and once a grace-period has passed, we try to upgrade
again to using UDP. The grace-period starts off at five minutes
after the current feature level was verified and then grows
exponentially to six hours. This is to mitigate problems due
to temporary lack of network connectivity, but at the same time
avoid flooding the network with retries when the feature attempted
feature level genuinely does not work.
Note that UDP is likely much more commonly supported than TCP,
but depending on the path between the client and the server, we
may have more luck with TCP in case something is wrong. We really
do prefer UDP though, as that is much more lightweight, that is
why TCP is only the last resort.
[0]: <https://kb.isc.org/article/AA-01219/0/Refinements-to-EDNS-fallback-behavior-can-cause-different-outcomes-in-Recursive-Servers.html>
|
|
After all, this is likely a local DNS forwarder that caches anyway,
hence there's no point in caching twice.
Fixes #2038.
|
|
After all /etc/resolv.conf is usually done when the network
configuration changes, which is a good reason to flush the global cache.
See: #2038
|
|
If /etc/resolv.conf is missing, this should not result in the server
list to be cleared, after all the native data from resolved.conf
shouldn't be flushed out then. Hence flush out the data only if
/etc/resolv.conf exists, but we cannot read it for some reason.
|
|
|
|
It probably doesn't make sense to mix local and global configuration.
Applying global search lists to local DNS servers appears unnecessary
and creates problems because we'll traverse the search domains
non-simultaneously on multiple scopes.
Also see:
https://github.com/systemd/systemd/pull/2031
|
|
key per scope
When the zone probing code looks for a transaction to reuse it will
refuse to look at transactions that have been answered from cache or the
zone itself, but insist on the network. This has the effect that there
might be multiple transactions around for the same key on the same
scope. Previously we'd track all transactions in a hashmap, indexed by
the key, which implied that there would be only one transaction per key,
per scope. With this change the hashmap will only store the most recent
transaction per key, and a linked list will be used to track all
transactions per scope, allowing multiple per-key per-scope.
Note that the linked list fields for this actually already existed in
the DnsTransaction structure, but were previously unused.
|
|
Let's track where the data came from: from the network, the cache or the
local zone. This is not only useful for debugging purposes, but is also
useful when the zone probing wants to ensure it's not reusing
transactions that were answered from the cache or the zone itself.
|
|
DnsTransaction objects
Previously we'd only store the DnsPacket in the DnsTransaction, and the
DnsQuery would then take the DnsPacket's DnsAnswer and return it. With
this change we already pull the DnsAnswer out inside the transaction.
We still store the DnsPacket in the transaction, if we have it, since we
still need to determine from which peer a response originates, to
implement caching properly. However, the DnsQuery logic doesn't care
anymore for the packet, it now only looks at answers and rcodes from the
successfuly candidate.
This also has the benefit of unifying how we propagate incoming packets,
data from the local zone or the local cache.
|
|
Let's use a more useful way to write the flags. Also, leave some space
in the middle for the mDNS flags. After all, these flags are exposed on
the bus, and we should really make sure to expose flags that are going
to be stable, hence allow some room here...
(Not that the room really mattered, except to be nice to one's OCD)
|
|
resolved. Fully implement search domains for single-label names
|
|
It may be unexpected to find a CNAME record when doing a reverse lookup, as we
expect to find a PTR record directly. However, it is explicitly supported
according to <https://tools.ietf.org/html/rfc2181#section-10.2>, and there
seems to be no benefit to not supporting it.
|
|
The assumption that no NSEC bitmap could be empty due to the presence of the bit representing
the record itself turns out to be flawed. See (the admittedly experimental) RFC4956 for a
counter example.
|
|
The new dns_label_escape() call now operates on a buffer passed in,
similar to dns_label_unescape(). This should make decoding a bit faster,
and nicer.
|
|
For similar reasons as dns_name_is_root() got changed in the previous
commit.
|
|
Let's change the return value to bool. If we encounter an error while
parsing, return "false" instead of the actual parsing error, after all
the specified hostname does not qualify for what the function is
supposed to test.
Dealing with the additional error codes was always cumbersome, and
easily misused, like for example in the DHCP code.
Let's also rename the functions from dns_name_root() to
dns_name_is_root(), to indicate that this function checks something and
returns a bool. Similar for dns_name_is_signal_label().
|
|
This adds support for searching single-label hostnames in a set of
configured search domains.
A new object DnsQueryCandidate is added that links queries to scopes.
It keeps track of the search domain last used for a query on a specific
link. Whenever a host name was unsuccessfuly resolved on a scope all its
transactions are flushed out and replaced by a new set, with the next
search domain appended.
This also adds a new flag SD_RESOLVED_NO_SEARCH to disable search domain
behaviour. The "systemd-resolve-host" tool is updated to make this
configurable via --search=.
Fixes #1697
|
|
For now, let's just expose the LLMNR hostname currently in use; a
combined list of all dns servers with their interface indexes; a
combined list of all search domains with their interface indexes.
|
|
Let's split this out from the resolv.conf parser, so that this becomes
generically useful.
|
|
|
|
This copies concepts we introduced for the DnsSearchDomain stuff, and
reworks the operations on lists of dns servers to be reusable and
generic for use both with the Link and the Manager object.
|
|
With this change, we add a new object to resolved, "DnsSearchDomain="
which wraps a search domain. This is then used to introduce a global
search domain list, in addition to the existing per-link search domain
list which is reword to make use of this new object too.
This is preparation for implement proper unicast DNS search domain
support.
|
|
Previously, we'd keep adding new dns servers we discover to the end of
our linked list of servers. When we encountered a pre-existing server,
we'd just leave it where it was. In essence that meant that old servers
ended up at the front, and new servers at the end, but not in an order
that would reflect the configuration.
With this change we ensure that every pre-existing server we want to add
again we move to the back of the linked list, so that the order is
stable and in sync with the requested configuration.
|
|
|
|
Closes #342.
|
|
Previously, there was a chance of memory corruption, because when
switching to the next DNS server we didn't care whether they linked list
of DNS servers was still valid.
Clean up lifecycle of the dns server logic:
- When a DnsServer object is still in the linked list of DnsServers for
a link or the manager, indicate so with a "linked" boolean field, and
never follow the linked list if that boolean is not set.
- When picking a DnsServer to use for a link ot manager, always
explicitly take a reference.
This also rearranges some logic, to make the tracking of dns servers by
link and globally more alike.
|
|
resolved-dns-server.c
|
|
|
|
No functional changes.
|