summaryrefslogtreecommitdiff
path: root/package/network/services/dnsmasq/patches/0018-Fix-sometimes-missing-DNSSEC-RRs-when-DNSSEC-validat.patch
diff options
context:
space:
mode:
Diffstat (limited to 'package/network/services/dnsmasq/patches/0018-Fix-sometimes-missing-DNSSEC-RRs-when-DNSSEC-validat.patch')
-rw-r--r--package/network/services/dnsmasq/patches/0018-Fix-sometimes-missing-DNSSEC-RRs-when-DNSSEC-validat.patch87
1 files changed, 87 insertions, 0 deletions
diff --git a/package/network/services/dnsmasq/patches/0018-Fix-sometimes-missing-DNSSEC-RRs-when-DNSSEC-validat.patch b/package/network/services/dnsmasq/patches/0018-Fix-sometimes-missing-DNSSEC-RRs-when-DNSSEC-validat.patch
new file mode 100644
index 0000000..1d75418
--- /dev/null
+++ b/package/network/services/dnsmasq/patches/0018-Fix-sometimes-missing-DNSSEC-RRs-when-DNSSEC-validat.patch
@@ -0,0 +1,87 @@
+From a997ca0da044719a0ce8a232d14da8b30022592b Mon Sep 17 00:00:00 2001
+From: Simon Kelley <simon@thekelleys.org.uk>
+Date: Fri, 29 Jun 2018 14:39:41 +0100
+Subject: [PATCH 18/18] Fix sometimes missing DNSSEC RRs when DNSSEC validation
+ not enabled.
+
+Dnsmasq does pass on the do-bit, and return DNSSEC RRs, irrespective
+of of having DNSSEC validation compiled in or enabled.
+
+The thing to understand here is that the cache does not store all the
+DNSSEC RRs, and dnsmasq doesn't have the (very complex) logic required
+to determine the set of DNSSEC RRs required in an answer. Therefore if
+the client wants the DNSSEC RRs, the query can not be answered from
+the cache. When DNSSEC validation is enabled, any query with the
+do-bit set is never answered from the cache, unless the domain is
+known not to be signed: the query is always forwarded. This ensures
+that the DNSEC RRs are included.
+
+The same thing should be true when DNSSEC validation is not enabled,
+but there's a bug in the logic.
+
+line 1666 of src/rfc1035.c looks like this
+
+ if ((crecp->flags & (F_HOSTS | F_DHCP | F_CONFIG)) || !do_bit || !(crecp->flags & F_DNSSECOK))
+
+{ ...answer from cache ... }
+
+So local stuff (hosts, DHCP, ) get answered. If the do_bit is not set
+then the query is answered, and if the domain is known not to be
+signed, the query is answered.
+
+Unfortunately, if DNSSEC validation is not turned on then the
+F_DNSSECOK bit is not valid, and it's always zero, so the question
+always gets answered from the cache, even when the do-bit is set.
+
+This code should look like that at line 1468, dealing with PTR queries
+
+ if ((crecp->flags & (F_HOSTS | F_DHCP | F_CONFIG)) ||
+ !do_bit ||
+ (option_bool(OPT_DNSSEC_VALID) && !(crecp->flags & F_DNSSECOK)))
+
+where the F_DNSSECOK bit is only used when validation is enabled.
+
+Signed-off-by: Kevin Darbyshire-Bryant <ldir@darbyshire-bryant.me.uk>
+---
+ CHANGELOG | 7 ++++++-
+ src/rfc1035.c | 6 ++++--
+ 2 files changed, 10 insertions(+), 3 deletions(-)
+
+--- a/CHANGELOG
++++ b/CHANGELOG
+@@ -33,7 +33,12 @@ version 2.80
+ even if auth-sec-servers is not. Thanks to Raphaël Halimi for
+ the suggestion.
+
+-
++ Fix bug which sometimes caused dnsmasq to wrongly return answers
++ without DNSSEC RRs to queries with the do-bit set, but only when
++ DNSSEC validation was not enabled.
++ Thanks to Petr Menšík for spotting this.
++
++
+ version 2.79
+ Fix parsing of CNAME arguments, which are confused by extra spaces.
+ Thanks to Diego Aguirre for spotting the bug.
+--- a/src/rfc1035.c
++++ b/src/rfc1035.c
+@@ -1663,7 +1663,9 @@ size_t answer_request(struct dns_header
+ }
+
+ /* If the client asked for DNSSEC don't use cached data. */
+- if ((crecp->flags & (F_HOSTS | F_DHCP | F_CONFIG)) || !do_bit || !(crecp->flags & F_DNSSECOK))
++ if ((crecp->flags & (F_HOSTS | F_DHCP | F_CONFIG)) ||
++ !do_bit ||
++ (option_bool(OPT_DNSSEC_VALID) && !(crecp->flags & F_DNSSECOK)))
+ do
+ {
+ /* don't answer wildcard queries with data not from /etc/hosts
+@@ -1747,7 +1749,7 @@ size_t answer_request(struct dns_header
+ {
+ if ((crecp = cache_find_by_name(NULL, name, now, F_CNAME | (dryrun ? F_NO_RR : 0))) &&
+ (qtype == T_CNAME || (crecp->flags & F_CONFIG)) &&
+- ((crecp->flags & F_CONFIG) || !do_bit || !(crecp->flags & F_DNSSECOK)))
++ ((crecp->flags & F_CONFIG) || !do_bit || (option_bool(OPT_DNSSEC_VALID) && !(crecp->flags & F_DNSSECOK))))
+ {
+ if (!(crecp->flags & F_DNSSECOK))
+ sec_data = 0;