When checking that an answer is the answer to the question that
we asked, compare the name in a case-sensitive manner.
Clients can set the letters in a query to a random pattern of
uppercase and lowercase to add more randomness as protection against
cache-poisoning attacks, and we don't want to nullify that.
This actually restores the status quo before
commit ed6d29a784
since matching questions and answers using a checksum
can't help but be case sensitive.
This patch is a preparation for introducing DNS-0x20
in the dnsmasq query path.
If the client asks for DNSSEC RRs via the do bit, and
we have an answer cached, we can only return the cached
answer if the RR was not validated. This is because
we don't the extra info (RRSIGS, NSECs) for a complete
validated answer. In that case we have to forward again.
This bug was that the "is the cache entry validated" test was
in an outer loop rather than an inner one. A cache hit on
a different RRtype that wasn't validated would satify the
condition to use the cache, even if the cache entry for
the required RRtype didn't. The only time when there can be a mix
of validated and non validated cache entries for the same domain
is when most are not validated, but one is a negative cache for
a DS record.
This bug took a long time to find.
When dnsmasq is configured to act as an authoritative server and has
an authoritative zone configured, and recieves a query for
that zone _as_forwarder_ it answers the query directly rather
than forwarding it. This doesn't affect the answer, but it
saves dnsmasq forwarding the query to the recusor upstream,
whch then bounces it back to dnsmasq in auth mode. The
exception should be when the query is for the root of zone, for a DS
RR. The answer to that has to come from the parent, via the
recursor, and will typically be a proof-of-nonexistence since
dnsmasq doesn't support signed zones. This patch suppresses
local answers and forces forwarding to the upstream recursor
for such queries. It stops breakage when a DNSSEC validating
client makes queries to dnsmasq acting as forwarder for a zone
for which it is authoritative.
If we get a duplicate answer for a query via UDP which we have
either already received and started DNSSEC validation, or was
truncated and we've passed to TCP, then just ignore it.
The code was already in place, but had evolved wonky and
only worked for error replies which would otherwise prompt
a retransmit.
If a child process dies unexpectedly, log the error and
try and tidy up so the main process continues to run and
doesn't block awaiting the dead child.
Print a specific INFO message instead of a generic WARNING message,
so users know what to do.
Starting dnsmasq without upstream servers indicates a problem by default,
but is perfectly normal with D-Bus enabled. For example, NetworkManager
starts dnsmasq with no upstream servers, then immediately populates it
over D-Bus.
Handling events on file descriptors can result in new file
descriptors being created or old ones being deleted. As such
the results of the last call to poll() become invalid in subtle
ways.
After handling each file descriptor in check_dns_listeners()
return, to go around the poll() loop again and get valid data
for the new situation.
Thanks to Dominik Derigs for his indefatigable sleuthing of this one.
I have no memory for why this was ever there. It breaks DNSSEC
validation of large RRsets.
I can't see any DoS potential that is exposed by removing it.
Print a specific INFO message instead of a generic WARNING message,
so users aren't inconvenienced and maintainers know what to do.
Debian currently runs this service as part of NetworkManager,
in a systemd service without CAP_CHOWN. Other distributions may
have the same problem, or might add the issue in future.
This fix should communicate the issue clearly to them.
I misread the man page for socket(7) and TCP timeouts.
A timeout generates a -1 return and EAGAIN errno, NOT a short read.
Short reads are legit, and aborting when they are seen creates
hard-to-reproduce errors.
If dnsmasq is configured to add an EDNS client subnet to a query,
it is careful to suppress use of the cache, since a cached answer may
not be valid for a query with a different client subnet.
Extend this behaviour to queries which arrive a dnsmasq
already carrying an EDNS client subnet.
This change is rather more involved than may seem necessary at first sight,
since the existing code relies on all queries being decorated by dnsmasq
and therefore not cached, so there is no chance that an incoming query
might hit the cache and cache lookup don't need to be suppressed, just
cache insertion. When downstream queries may be a mix of client-subnet
bearing and plain vanilla, it can't be assumed that the answers are never
in the cache, and queries with subnets must not do lookups.
I am attaching an incremental git-am ready patch to go on top your Git HEAD,
to fix all sorts of issues and make this conforming C99 with default
options set,
and fix another load of warnings you receive when setting the compiler
to pick the nits,
-pedantic-errors -std=c99 (or c11, c18, c2x).
It changes many void * to uint8_t * to make the "increment by bytes"
explicit.
You can't do:
void *foo;
// ...
foo += 2.
The make target 'install-common' expects results from the target 'all'.
A 'make -j install' may fail because both targets are brought
up-to-todate in parallel. As a result the final binary will not exist at
the time 'install-common' runs, because 'all' is not yet done.
Adjust the dependencies to update 'all' before processing 'install-common'.
Signed-off-by: Olaf Hering <olaf@aepfle.de>
Not doing so can result in a use after free since the name for DHCP
derived DNS records is represented as a pointer into the DHCP lease
table. Update will only happen when necessary since lease_update_dns
tests internally on dns_dirty and the force argument is zero.
Signed-off-by: Erik Karlsson <erik.karlsson@iopsys.eu>
We can't answer and shouldn't forward non-QUERY DNS requests.
This patch fixes handling such requests from TCP connections; before
the connection would be closed without reply.
It also changes the RCODE in the answer from REFUSED to NOTIMP and
provides clearer logging.