diff --git a/package/network/services/dnsmasq/Makefile b/package/network/services/dnsmasq/Makefile index 7ba7d56b52..46b68a24a6 100644 --- a/package/network/services/dnsmasq/Makefile +++ b/package/network/services/dnsmasq/Makefile @@ -8,12 +8,12 @@ include $(TOPDIR)/rules.mk PKG_NAME:=dnsmasq -PKG_VERSION:=2.78 -PKG_RELEASE:=10 +PKG_VERSION:=2.79rc1 +PKG_RELEASE:=1 PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz -PKG_SOURCE_URL:=http://thekelleys.org.uk/dnsmasq/ -PKG_HASH:=89949f438c74b0c7543f06689c319484bd126cc4b1f8c745c742ab397681252b +PKG_SOURCE_URL:=http://thekelleys.org.uk/dnsmasq/release-candidates/ +PKG_HASH:=57d17a3a6cf34af5dcbc5107c45b05671bda9d250718fe073ca12c5f61099985 PKG_LICENSE:=GPL-2.0 PKG_LICENSE_FILES:=COPYING diff --git a/package/network/services/dnsmasq/patches/210-dnssec-improve-timestamp-heuristic.patch b/package/network/services/dnsmasq/patches/210-dnssec-improve-timestamp-heuristic.patch index 2f854d490b..be1195abbd 100644 --- a/package/network/services/dnsmasq/patches/210-dnssec-improve-timestamp-heuristic.patch +++ b/package/network/services/dnsmasq/patches/210-dnssec-improve-timestamp-heuristic.patch @@ -10,7 +10,7 @@ Signed-off-by: Steven Barth --- a/src/dnssec.c +++ b/src/dnssec.c -@@ -462,17 +462,24 @@ static time_t timestamp_time; +@@ -143,17 +143,24 @@ static time_t timestamp_time; int setup_timestamp(void) { struct stat statbuf; @@ -36,7 +36,7 @@ Signed-off-by: Steven Barth { /* time already OK, update timestamp, and do key checking from the start. */ if (utimes(daemon->timestamp_file, NULL) == -1) -@@ -493,7 +500,7 @@ int setup_timestamp(void) +@@ -174,7 +181,7 @@ int setup_timestamp(void) close(fd); diff --git a/package/network/services/dnsmasq/patches/240-ubus.patch b/package/network/services/dnsmasq/patches/240-ubus.patch index d21ca0dbaa..415c7a5e4c 100644 --- a/package/network/services/dnsmasq/patches/240-ubus.patch +++ b/package/network/services/dnsmasq/patches/240-ubus.patch @@ -74,7 +74,7 @@ int main (int argc, char **argv) { int bind_fallback = 0; -@@ -911,6 +971,7 @@ int main (int argc, char **argv) +@@ -928,6 +988,7 @@ int main (int argc, char **argv) set_dbus_listeners(); #endif @@ -82,7 +82,7 @@ #ifdef HAVE_DHCP if (daemon->dhcp || daemon->relay4) { -@@ -1041,6 +1102,8 @@ int main (int argc, char **argv) +@@ -1058,6 +1119,8 @@ int main (int argc, char **argv) check_dbus_listeners(); #endif @@ -104,7 +104,7 @@ mostly_clean : --- a/src/dnsmasq.h +++ b/src/dnsmasq.h -@@ -1397,6 +1397,8 @@ void emit_dbus_signal(int action, struct +@@ -1415,6 +1415,8 @@ void emit_dbus_signal(int action, struct # endif #endif diff --git a/package/network/services/dnsmasq/patches/250-Fix-infinite-retries-in-strict-order-mode.patch b/package/network/services/dnsmasq/patches/250-Fix-infinite-retries-in-strict-order-mode.patch deleted file mode 100644 index faff680e03..0000000000 --- a/package/network/services/dnsmasq/patches/250-Fix-infinite-retries-in-strict-order-mode.patch +++ /dev/null @@ -1,45 +0,0 @@ -From ef3d137a646fa8309e1ff5184e3e145eef40cc4d Mon Sep 17 00:00:00 2001 -From: Simon Kelley -Date: Tue, 5 Dec 2017 22:37:29 +0000 -Subject: [PATCH] Fix infinite retries in strict-order mode. - - If all configured dns servers return refused in - response to a query; dnsmasq will end up in an infinite loop - retransmitting the dns query resulting into high CPU load. - Problem is caused by the dns refuse retransmission logic which does - not check for the end of a dns server list iteration in strict mode. - Having one configured dns server returning a refused reply easily - triggers this problem in strict order mode. This was introduced in - 9396752c115b3ab733fa476b30da73237e12e7ba - - Thanks to Hans Dedecker for spotting this - and the initial patch. ---- - src/forward.c | 14 ++++++++++++-- - 1 file changed, 12 insertions(+), 2 deletions(-) - ---- a/src/forward.c -+++ b/src/forward.c -@@ -797,10 +797,20 @@ void reply_query(int fd, int family, tim - unsigned char *pheader; - size_t plen; - int is_sign; -- -+ -+ /* In strict order mode, there must be a server later in the chain -+ left to send to, otherwise without the forwardall mechanism, -+ code further on will cycle around the list forwever if they -+ all return REFUSED. Note that server is always non-NULL before -+ this executes. */ -+ if (option_bool(OPT_ORDER)) -+ for (server = forward->sentto->next; server; server = server->next) -+ if (!(server->flags & (SERV_LITERAL_ADDRESS | SERV_HAS_DOMAIN | SERV_FOR_NODOTS | SERV_NO_ADDR | SERV_LOOP))) -+ break; -+ - /* recreate query from reply */ - pheader = find_pseudoheader(header, (size_t)n, &plen, NULL, &is_sign, NULL); -- if (!is_sign) -+ if (!is_sign && server) - { - header->ancount = htons(0); - header->nscount = htons(0); diff --git a/package/network/services/dnsmasq/patches/260-dnssec-SIGINT.patch b/package/network/services/dnsmasq/patches/260-dnssec-SIGINT.patch deleted file mode 100644 index e280142f75..0000000000 --- a/package/network/services/dnsmasq/patches/260-dnssec-SIGINT.patch +++ /dev/null @@ -1,120 +0,0 @@ -From 3c973ad92d317df736d5a8fde67baba6b102d91e Mon Sep 17 00:00:00 2001 -From: Simon Kelley -Date: Sun, 14 Jan 2018 21:05:37 +0000 -Subject: [PATCH] Use SIGINT (instead of overloading SIGHUP) to turn on DNSSEC - time validation. - ---- - src/dnsmasq.c | 36 +++++++++++++++++++++++++----------- - src/dnsmasq.h | 1 + - src/helper.c | 3 ++- - 5 files changed, 38 insertions(+), 14 deletions(-) - ---- a/src/dnsmasq.c -+++ b/src/dnsmasq.c -@@ -137,7 +137,8 @@ int main (int argc, char **argv) - sigaction(SIGTERM, &sigact, NULL); - sigaction(SIGALRM, &sigact, NULL); - sigaction(SIGCHLD, &sigact, NULL); -- -+ sigaction(SIGINT, &sigact, NULL); -+ - /* ignore SIGPIPE */ - sigact.sa_handler = SIG_IGN; - sigaction(SIGPIPE, &sigact, NULL); -@@ -815,7 +816,7 @@ int main (int argc, char **argv) - - daemon->dnssec_no_time_check = option_bool(OPT_DNSSEC_TIME); - if (option_bool(OPT_DNSSEC_TIME) && !daemon->back_to_the_future) -- my_syslog(LOG_INFO, _("DNSSEC signature timestamps not checked until first cache reload")); -+ my_syslog(LOG_INFO, _("DNSSEC signature timestamps not checked until receipt of SIGINT")); - - if (rc == 1) - my_syslog(LOG_INFO, _("DNSSEC signature timestamps not checked until system time valid")); -@@ -1142,7 +1143,7 @@ static void sig_handler(int sig) - { - /* ignore anything other than TERM during startup - and in helper proc. (helper ignore TERM too) */ -- if (sig == SIGTERM) -+ if (sig == SIGTERM || sig == SIGINT) - exit(EC_MISC); - } - else if (pid != getpid()) -@@ -1168,6 +1169,15 @@ static void sig_handler(int sig) - event = EVENT_DUMP; - else if (sig == SIGUSR2) - event = EVENT_REOPEN; -+ else if (sig == SIGINT) -+ { -+ /* Handle SIGINT normally in debug mode, so -+ ctrl-c continues to operate. */ -+ if (option_bool(OPT_DEBUG)) -+ exit(EC_MISC); -+ else -+ event = EVENT_TIME; -+ } - else - return; - -@@ -1295,14 +1305,7 @@ static void async_event(int pipe, time_t - { - case EVENT_RELOAD: - daemon->soa_sn++; /* Bump zone serial, as it may have changed. */ -- --#ifdef HAVE_DNSSEC -- if (daemon->dnssec_no_time_check && option_bool(OPT_DNSSEC_VALID) && option_bool(OPT_DNSSEC_TIME)) -- { -- my_syslog(LOG_INFO, _("now checking DNSSEC signature timestamps")); -- daemon->dnssec_no_time_check = 0; -- } --#endif -+ - /* fall through */ - - case EVENT_INIT: -@@ -1411,6 +1414,17 @@ static void async_event(int pipe, time_t - poll_resolv(0, 1, now); - break; - -+ case EVENT_TIME: -+#ifdef HAVE_DNSSEC -+ if (daemon->dnssec_no_time_check && option_bool(OPT_DNSSEC_VALID) && option_bool(OPT_DNSSEC_TIME)) -+ { -+ my_syslog(LOG_INFO, _("now checking DNSSEC signature timestamps")); -+ daemon->dnssec_no_time_check = 0; -+ clear_cache_and_reload(now); -+ } -+#endif -+ break; -+ - case EVENT_TERM: - /* Knock all our children on the head. */ - for (i = 0; i < MAX_PROCS; i++) ---- a/src/dnsmasq.h -+++ b/src/dnsmasq.h -@@ -175,6 +175,7 @@ struct event_desc { - #define EVENT_NEWROUTE 23 - #define EVENT_TIME_ERR 24 - #define EVENT_SCRIPT_LOG 25 -+#define EVENT_TIME 26 - - /* Exit codes. */ - #define EC_GOOD 0 ---- a/src/helper.c -+++ b/src/helper.c -@@ -97,13 +97,14 @@ int create_helper(int event_fd, int err_ - return pipefd[1]; - } - -- /* ignore SIGTERM, so that we can clean up when the main process gets hit -+ /* ignore SIGTERM and SIGINT, so that we can clean up when the main process gets hit - and SIGALRM so that we can use sleep() */ - sigact.sa_handler = SIG_IGN; - sigact.sa_flags = 0; - sigemptyset(&sigact.sa_mask); - sigaction(SIGTERM, &sigact, NULL); - sigaction(SIGALRM, &sigact, NULL); -+ sigaction(SIGINT, &sigact, NULL); - - if (!option_bool(OPT_DEBUG) && uid != 0) - { diff --git a/package/network/services/dnsmasq/patches/270-dnssec-wildcards.patch b/package/network/services/dnsmasq/patches/270-dnssec-wildcards.patch deleted file mode 100644 index d13ac2cbad..0000000000 --- a/package/network/services/dnsmasq/patches/270-dnssec-wildcards.patch +++ /dev/null @@ -1,202 +0,0 @@ -From 4fe6744a220eddd3f1749b40cac3dfc510787de6 Mon Sep 17 00:00:00 2001 -From: Simon Kelley -Date: Fri, 19 Jan 2018 12:26:08 +0000 -Subject: [PATCH] DNSSEC fix for wildcard NSEC records. CVE-2017-15107 - applies. - -It's OK for NSEC records to be expanded from wildcards, -but in that case, the proof of non-existence is only valid -starting at the wildcard name, *. NOT the name expanded -from the wildcard. Without this check it's possible for an -attacker to craft an NSEC which wrongly proves non-existence -in a domain which includes a wildcard for NSEC. ---- - src/dnssec.c | 117 +++++++++++++++++++++++++++++++++++++++++++++++++++------- - 2 files changed, 114 insertions(+), 15 deletions(-) - ---- a/src/dnssec.c -+++ b/src/dnssec.c -@@ -424,15 +424,17 @@ static void from_wire(char *name) - static int count_labels(char *name) - { - int i; -- -+ char *p; -+ - if (*name == 0) - return 0; - -- for (i = 0; *name; name++) -- if (*name == '.') -+ for (p = name, i = 0; *p; p++) -+ if (*p == '.') - i++; - -- return i+1; -+ /* Don't count empty first label. */ -+ return *name == '.' ? i : i+1; - } - - /* Implement RFC1982 wrapped compare for 32-bit numbers */ -@@ -1412,8 +1414,8 @@ static int hostname_cmp(const char *a, c - } - } - --static int prove_non_existence_nsec(struct dns_header *header, size_t plen, unsigned char **nsecs, int nsec_count, -- char *workspace1, char *workspace2, char *name, int type, int *nons) -+static int prove_non_existence_nsec(struct dns_header *header, size_t plen, unsigned char **nsecs, unsigned char **labels, int nsec_count, -+ char *workspace1_in, char *workspace2, char *name, int type, int *nons) - { - int i, rc, rdlen; - unsigned char *p, *psave; -@@ -1426,6 +1428,9 @@ static int prove_non_existence_nsec(stru - /* Find NSEC record that proves name doesn't exist */ - for (i = 0; i < nsec_count; i++) - { -+ char *workspace1 = workspace1_in; -+ int sig_labels, name_labels; -+ - p = nsecs[i]; - if (!extract_name(header, plen, &p, workspace1, 1, 10)) - return 0; -@@ -1434,7 +1439,27 @@ static int prove_non_existence_nsec(stru - psave = p; - if (!extract_name(header, plen, &p, workspace2, 1, 10)) - return 0; -- -+ -+ /* If NSEC comes from wildcard expansion, use original wildcard -+ as name for computation. */ -+ sig_labels = *labels[i]; -+ name_labels = count_labels(workspace1); -+ -+ if (sig_labels < name_labels) -+ { -+ int k; -+ for (k = name_labels - sig_labels; k != 0; k--) -+ { -+ while (*workspace1 != '.' && *workspace1 != 0) -+ workspace1++; -+ if (k != 1 && *workspace1 == '.') -+ workspace1++; -+ } -+ -+ workspace1--; -+ *workspace1 = '*'; -+ } -+ - rc = hostname_cmp(workspace1, name); - - if (rc == 0) -@@ -1832,24 +1857,26 @@ static int prove_non_existence_nsec3(str - - static int prove_non_existence(struct dns_header *header, size_t plen, char *keyname, char *name, int qtype, int qclass, char *wildname, int *nons) - { -- static unsigned char **nsecset = NULL; -- static int nsecset_sz = 0; -+ static unsigned char **nsecset = NULL, **rrsig_labels = NULL; -+ static int nsecset_sz = 0, rrsig_labels_sz = 0; - - int type_found = 0; -- unsigned char *p = skip_questions(header, plen); -+ unsigned char *auth_start, *p = skip_questions(header, plen); - int type, class, rdlen, i, nsecs_found; - - /* Move to NS section */ - if (!p || !(p = skip_section(p, ntohs(header->ancount), header, plen))) - return 0; -+ -+ auth_start = p; - - for (nsecs_found = 0, i = ntohs(header->nscount); i != 0; i--) - { - unsigned char *pstart = p; - -- if (!(p = skip_name(p, header, plen, 10))) -+ if (!extract_name(header, plen, &p, daemon->workspacename, 1, 10)) - return 0; -- -+ - GETSHORT(type, p); - GETSHORT(class, p); - p += 4; /* TTL */ -@@ -1866,7 +1893,69 @@ static int prove_non_existence(struct dn - if (!expand_workspace(&nsecset, &nsecset_sz, nsecs_found)) - return 0; - -- nsecset[nsecs_found++] = pstart; -+ if (type == T_NSEC) -+ { -+ /* If we're looking for NSECs, find the corresponding SIGs, to -+ extract the labels value, which we need in case the NSECs -+ are the result of wildcard expansion. -+ Note that the NSEC may not have been validated yet -+ so if there are multiple SIGs, make sure the label value -+ is the same in all, to avoid be duped by a rogue one. -+ If there are no SIGs, that's an error */ -+ unsigned char *p1 = auth_start; -+ int res, j, rdlen1, type1, class1; -+ -+ if (!expand_workspace(&rrsig_labels, &rrsig_labels_sz, nsecs_found)) -+ return 0; -+ -+ rrsig_labels[nsecs_found] = NULL; -+ -+ for (j = ntohs(header->nscount); j != 0; j--) -+ { -+ if (!(res = extract_name(header, plen, &p1, daemon->workspacename, 0, 10))) -+ return 0; -+ -+ GETSHORT(type1, p1); -+ GETSHORT(class1, p1); -+ p1 += 4; /* TTL */ -+ GETSHORT(rdlen1, p1); -+ -+ if (!CHECK_LEN(header, p1, plen, rdlen1)) -+ return 0; -+ -+ if (res == 1 && class1 == qclass && type1 == T_RRSIG) -+ { -+ int type_covered; -+ unsigned char *psav = p1; -+ -+ if (rdlen1 < 18) -+ return 0; /* bad packet */ -+ -+ GETSHORT(type_covered, p1); -+ -+ if (type_covered == T_NSEC) -+ { -+ p1++; /* algo */ -+ -+ /* labels field must be the same in every SIG we find. */ -+ if (!rrsig_labels[nsecs_found]) -+ rrsig_labels[nsecs_found] = p1; -+ else if (*rrsig_labels[nsecs_found] != *p1) /* algo */ -+ return 0; -+ } -+ p1 = psav; -+ } -+ -+ if (!ADD_RDLEN(header, p1, plen, rdlen1)) -+ return 0; -+ } -+ -+ /* Must have found at least one sig. */ -+ if (!rrsig_labels[nsecs_found]) -+ return 0; -+ } -+ -+ nsecset[nsecs_found++] = pstart; - } - - if (!ADD_RDLEN(header, p, plen, rdlen)) -@@ -1874,7 +1963,7 @@ static int prove_non_existence(struct dn - } - - if (type_found == T_NSEC) -- return prove_non_existence_nsec(header, plen, nsecset, nsecs_found, daemon->workspacename, keyname, name, qtype, nons); -+ return prove_non_existence_nsec(header, plen, nsecset, rrsig_labels, nsecs_found, daemon->workspacename, keyname, name, qtype, nons); - else if (type_found == T_NSEC3) - return prove_non_existence_nsec3(header, plen, nsecset, nsecs_found, daemon->workspacename, keyname, name, qtype, wildname, nons); - else