Change default for dnssec-check-unsigned.
diff --git a/CHANGELOG b/CHANGELOG
index 955405b..a9136ea 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -2,6 +2,20 @@
Add support for RFC 4039 DHCP rapid commit. Thanks to Ashram Method
for the initial patch and motivation.
+ Alter the default for dnssec-check-unsigned. Versions of
+ dnsmasq prior to 2.80 defaulted to not checking unsigned
+ replies, and used --dnssec-check-unsigned to switch
+ this on. Such configurations will continue to work as before,
+ but those which used the default of no checking will need to be
+ altered to explicitly select no checking. The new default is
+ because switching off checking for unsigned replies is
+ inherently dangerous. Not only does it open the possiblity of forged
+ replies, but it allows everything to appear to be working even
+ when the upstream namesevers do not support DNSSEC, and in this
+ case no DNSSEC validation at all is occuring.
+
+
+
version 2.79
Fix parsing of CNAME arguments, which are confused by extra spaces.
diff --git a/man/dnsmasq.8 b/man/dnsmasq.8
index e2dc65c..c710fb2 100644
--- a/man/dnsmasq.8
+++ b/man/dnsmasq.8
@@ -712,10 +712,7 @@
enabled. The nameservers upstream of dnsmasq must be DNSSEC-capable,
ie capable of returning DNSSEC records with data. If they are not,
then dnsmasq will not be able to determine the trusted status of
-answers. In the default mode, this means that all replies will be
-marked as untrusted. If
-.B --dnssec-check-unsigned
-is set and the upstream servers don't support DNSSEC, then DNS service will be entirely broken.
+answers and this means that DNS service will be entirely broken.
.TP
.B --trust-anchor=[<class>],<domain>,<key-tag>,<algorithm>,<digest-type>,<digest>
Provide DS records to act a trust anchors for DNSSEC
@@ -724,17 +721,19 @@
but trust anchors for limited domains are also possible. The current
root-zone trust anchors may be downloaded from https://data.iana.org/root-anchors/root-anchors.xml
.TP
-.B --dnssec-check-unsigned
-As a default, dnsmasq does not check that unsigned DNS replies are
-legitimate: they are assumed to be valid and passed on (without the
+.B --dnssec-check-unsigned[=no]
+As a default, dnsmasq checks that unsigned DNS replies are
+legitimate: this entails possible extra queries even for the majority of DNS
+zones which are not, at the moment, signed. If
+.B --dnssec-check-unsigned=no
+appears in the configuration, then such replies they are assumed to be valid and passed on (without the
"authentic data" bit set, of course). This does not protect against an
attacker forging unsigned replies for signed DNS zones, but it is
-fast. If this flag is set, dnsmasq will check the zones of unsigned
-replies, to ensure that unsigned replies are allowed in those
-zones. The cost of this is more upstream queries and slower
-performance. See also the warning about upstream servers in the
-section on
-.B --dnssec
+fast.
+
+Versions of dnsmasq prior to 2.80 defaulted to not checking unsigned replies, and used
+.B --dnssec-check-unsigned
+to switch this on. Such configurations will continue to work as before, but those which used the default of no checking will need to be altered to explicitly select no checking. The new default is because switching off checking for unsigned replies is inherently dangerous. Not only does it open the possiblity of forged replies, but it allows everything to appear to be working even when the upstream namesevers do not support DNSSEC, and in this case no DNSSEC validation at all is occuring.
.TP
.B --dnssec-no-timecheck
DNSSEC signatures are only valid for specified time windows, and should be rejected outside those windows. This generates an
diff --git a/src/dnsmasq.c b/src/dnsmasq.c
index ce44809..38d1dd3 100644
--- a/src/dnsmasq.c
+++ b/src/dnsmasq.c
@@ -768,7 +768,10 @@
_exit(0);
}
- my_syslog(LOG_INFO, _("DNSSEC validation enabled"));
+ if (option_bool(OPT_DNSSEC_IGN_NS))
+ my_syslog(LOG_INFO, _("DNSSEC validation enabled but all unsigned answers are trusted"));
+ else
+ my_syslog(LOG_INFO, _("DNSSEC validation enabled"));
daemon->dnssec_no_time_check = option_bool(OPT_DNSSEC_TIME);
if (option_bool(OPT_DNSSEC_TIME) && !daemon->back_to_the_future)
diff --git a/src/dnsmasq.h b/src/dnsmasq.h
index ff7172f..9443405 100644
--- a/src/dnsmasq.h
+++ b/src/dnsmasq.h
@@ -241,7 +241,7 @@
#define OPT_DNSSEC_VALID 45
#define OPT_DNSSEC_TIME 46
#define OPT_DNSSEC_DEBUG 47
-#define OPT_DNSSEC_NO_SIGN 48
+#define OPT_DNSSEC_IGN_NS 48
#define OPT_LOCAL_SERVICE 49
#define OPT_LOOP_DETECT 50
#define OPT_EXTRALOG 51
diff --git a/src/forward.c b/src/forward.c
index cdd11d3..d32d0d8 100644
--- a/src/forward.c
+++ b/src/forward.c
@@ -919,7 +919,7 @@
status = dnssec_validate_ds(now, header, n, daemon->namebuff, daemon->keyname, forward->class);
else
status = dnssec_validate_reply(now, header, n, daemon->namebuff, daemon->keyname, &forward->class,
- option_bool(OPT_DNSSEC_NO_SIGN) && (server->flags & SERV_DO_DNSSEC),
+ !option_bool(OPT_DNSSEC_IGN_NS) && (server->flags & SERV_DO_DNSSEC),
NULL, NULL);
}
@@ -1504,7 +1504,7 @@
new_status = dnssec_validate_ds(now, header, n, name, keyname, class);
else
new_status = dnssec_validate_reply(now, header, n, name, keyname, &class,
- option_bool(OPT_DNSSEC_NO_SIGN) && (server->flags & SERV_DO_DNSSEC),
+ !option_bool(OPT_DNSSEC_IGN_NS) && (server->flags & SERV_DO_DNSSEC),
NULL, NULL);
if (new_status != STAT_NEED_DS && new_status != STAT_NEED_KEY)
diff --git a/src/option.c b/src/option.c
index 2667f5b..65df93a 100644
--- a/src/option.c
+++ b/src/option.c
@@ -311,7 +311,7 @@
{ "dnssec", 0, 0, LOPT_SEC_VALID },
{ "trust-anchor", 1, 0, LOPT_TRUST_ANCHOR },
{ "dnssec-debug", 0, 0, LOPT_DNSSEC_DEBUG },
- { "dnssec-check-unsigned", 0, 0, LOPT_DNSSEC_CHECK },
+ { "dnssec-check-unsigned", 2, 0, LOPT_DNSSEC_CHECK },
{ "dnssec-no-timecheck", 0, 0, LOPT_DNSSEC_TIME },
{ "dnssec-timestamp", 1, 0, LOPT_DNSSEC_STAMP },
#ifdef OPTION6_PREFIX_CLASS
@@ -484,7 +484,7 @@
{ LOPT_SEC_VALID, OPT_DNSSEC_VALID, NULL, gettext_noop("Activate DNSSEC validation"), NULL },
{ LOPT_TRUST_ANCHOR, ARG_DUP, "<domain>,[<class>],...", gettext_noop("Specify trust anchor key digest."), NULL },
{ LOPT_DNSSEC_DEBUG, OPT_DNSSEC_DEBUG, NULL, gettext_noop("Disable upstream checking for DNSSEC debugging."), NULL },
- { LOPT_DNSSEC_CHECK, OPT_DNSSEC_NO_SIGN, NULL, gettext_noop("Ensure answers without DNSSEC are in unsigned zones."), NULL },
+ { LOPT_DNSSEC_CHECK, ARG_DUP, NULL, gettext_noop("Ensure answers without DNSSEC are in unsigned zones."), NULL },
{ LOPT_DNSSEC_TIME, OPT_DNSSEC_TIME, NULL, gettext_noop("Don't check DNSSEC signature timestamps until first cache-reload"), NULL },
{ LOPT_DNSSEC_STAMP, ARG_ONE, "<path>", gettext_noop("Timestamp file to verify system clock for DNSSEC"), NULL },
#ifdef OPTION6_PREFIX_CLASS
@@ -4139,6 +4139,16 @@
daemon->timestamp_file = opt_string_alloc(arg);
break;
+ case LOPT_DNSSEC_CHECK:
+ if (arg)
+ {
+ if (strcmp(arg, "no") == 0)
+ set_option_bool(OPT_DNSSEC_IGN_NS);
+ else
+ ret_err(_("bad value for dnssec-check-unsigned"));
+ }
+ break;
+
case LOPT_TRUST_ANCHOR:
{
struct ds_config *new = opt_malloc(sizeof(struct ds_config));