This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "IPFire 2.x development tree".
The branch, next has been updated via 9977da131b2d2e560057b79db714a987977026b4 (commit) via 21ac63688a76cefccf4796fe608fae436c38d5c8 (commit) via c3b4c861f5531712b6579cae839ea621f5336950 (commit) via 2135528774a66fa30143c024993054aed0f60c5a (commit) from 4df3276bb43bfb77e570b8c329da3885f644dabb (commit)
Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below.
- Log ----------------------------------------------------------------- commit 9977da131b2d2e560057b79db714a987977026b4 Author: Matthias Fischer matthias.fischer@ipfire.org Date: Sun Dec 27 00:20:13 2015 +0100
bind: Update to 9.10.3-P2
Changelog:
[security] Update allowed OpenSSL versions as named is potentially vulnerable to CVE-2015-3193.
[maint] H.ROOT-SERVERS.NET is 198.97.190.53 and 2001:500:1::53. [RT #40556]
[security] Insufficient testing when parsing a message allowed records with an incorrect class to be be accepted, triggering a REQUIRE failure when those records were subsequently cached. (CVE-2015-8000) [RT #40987]
[security] Address fetch context reference count handling error on socket error. (CVE-2015-8461) [RT#40945]
Signed-off-by: Matthias Fischer matthias.fischer@ipfire.org Signed-off-by: Michael Tremer michael.tremer@ipfire.org
commit 21ac63688a76cefccf4796fe608fae436c38d5c8 Author: Michael Tremer michael.tremer@ipfire.org Date: Mon Dec 28 15:37:02 2015 +0100
core97: Ship dnsmasq
Signed-off-by: Michael Tremer michael.tremer@ipfire.org
commit c3b4c861f5531712b6579cae839ea621f5336950 Author: Matthias Fischer matthias.fischer@ipfire.org Date: Thu Dec 24 10:17:16 2015 +0100
dnsmasq 2.75: latest patches from upstream
Same procedure as... :-)
Best to all for xmas and 2016!
Matthias
Signed-off-by: Matthias Fischer matthias.fischer@ipfire.org Signed-off-by: Michael Tremer michael.tremer@ipfire.org
commit 2135528774a66fa30143c024993054aed0f60c5a Author: Michael Tremer michael.tremer@ipfire.org Date: Mon Dec 28 15:30:13 2015 +0100
core97: Ship pgrep with the updater
Signed-off-by: Michael Tremer michael.tremer@ipfire.org
-----------------------------------------------------------------------
Summary of changes: .../{oldcore/96 => core/97}/filelists/dnsmasq | 0 config/rootfiles/core/97/filelists/files | 1 + config/rootfiles/core/97/update.sh | 2 + lfs/bind | 4 +- lfs/dnsmasq | 5 + ...EDNS0_handling_and_computation_use_of_udp.patch | 643 +++++++++++++++++++++ ...aks_in_handling_unknown_DNSSEC_algorithms.patch | 262 +++++++++ ...obscure_off-by-one_in_DNSSEC_hostname_cmp.patch | 27 + .../028-Minor_tweak_to_previous_commit.patch | 39 ++ .../dnsmasq/029-NSEC3_check_RFC5155_para_8_2.patch | 39 ++ 10 files changed, 1020 insertions(+), 2 deletions(-) copy config/rootfiles/{oldcore/96 => core/97}/filelists/dnsmasq (100%) create mode 100644 src/patches/dnsmasq/025-Major_tidy_up_of_EDNS0_handling_and_computation_use_of_udp.patch create mode 100644 src/patches/dnsmasq/026-More_tweaks_in_handling_unknown_DNSSEC_algorithms.patch create mode 100644 src/patches/dnsmasq/027-Nasty_rare_and_obscure_off-by-one_in_DNSSEC_hostname_cmp.patch create mode 100644 src/patches/dnsmasq/028-Minor_tweak_to_previous_commit.patch create mode 100644 src/patches/dnsmasq/029-NSEC3_check_RFC5155_para_8_2.patch
Difference in files: diff --git a/config/rootfiles/core/97/filelists/dnsmasq b/config/rootfiles/core/97/filelists/dnsmasq new file mode 120000 index 0000000..d469c74 --- /dev/null +++ b/config/rootfiles/core/97/filelists/dnsmasq @@ -0,0 +1 @@ +../../../common/dnsmasq \ No newline at end of file diff --git a/config/rootfiles/core/97/filelists/files b/config/rootfiles/core/97/filelists/files index 409e5fe..643ab97 100644 --- a/config/rootfiles/core/97/filelists/files +++ b/config/rootfiles/core/97/filelists/files @@ -1,2 +1,3 @@ etc/system-release etc/issue +usr/bin/pgrep diff --git a/config/rootfiles/core/97/update.sh b/config/rootfiles/core/97/update.sh index 4727d36..e6d4f21 100644 --- a/config/rootfiles/core/97/update.sh +++ b/config/rootfiles/core/97/update.sh @@ -32,6 +32,7 @@ do done
# Stop services +/etc/init.d/dnsmasq stop
# Extract files extract_files @@ -40,6 +41,7 @@ extract_files # /usr/local/bin/update-lang-cache
# Start services +/etc/init.d/dnsmasq start
# This update need a reboot... #touch /var/run/need_reboot diff --git a/lfs/bind b/lfs/bind index 6480798..b0d5185 100644 --- a/lfs/bind +++ b/lfs/bind @@ -25,7 +25,7 @@
include Config
-VER = 9.10.3 +VER = 9.10.3-P2
THISAPP = bind-$(VER) DL_FILE = $(THISAPP).tar.gz @@ -43,7 +43,7 @@ objects = $(DL_FILE)
$(DL_FILE) = $(DL_FROM)/$(DL_FILE)
-$(DL_FILE)_MD5 = d8cbf04a62a139a841d4bf878087a555 +$(DL_FILE)_MD5 = 672dd3c2796b12ac8440f55bcaecfa82
install : $(TARGET)
diff --git a/lfs/dnsmasq b/lfs/dnsmasq index c8fd7db..8058663 100644 --- a/lfs/dnsmasq +++ b/lfs/dnsmasq @@ -97,6 +97,11 @@ $(TARGET) : $(patsubst %,$(DIR_DL)/%,$(objects)) cd $(DIR_APP) && patch -Np1 -i $(DIR_SRC)/src/patches/dnsmasq/022-Tidy_up_DNSSEC_non-existence_code_Check_zone_status_is_NSEC_proof_bad.patch cd $(DIR_APP) && patch -Np1 -i $(DIR_SRC)/src/patches/dnsmasq/023-Fix_brace_botch_in_dnssec_validate_ds.patch cd $(DIR_APP) && patch -Np1 -i $(DIR_SRC)/src/patches/dnsmasq/024-Do_a_better_job_of_determining_which_DNSSEC_sig_algos_are_supported.patch + cd $(DIR_APP) && patch -Np1 -i $(DIR_SRC)/src/patches/dnsmasq/025-Major_tidy_up_of_EDNS0_handling_and_computation_use_of_udp.patch + cd $(DIR_APP) && patch -Np1 -i $(DIR_SRC)/src/patches/dnsmasq/026-More_tweaks_in_handling_unknown_DNSSEC_algorithms.patch + cd $(DIR_APP) && patch -Np1 -i $(DIR_SRC)/src/patches/dnsmasq/027-Nasty_rare_and_obscure_off-by-one_in_DNSSEC_hostname_cmp.patch + cd $(DIR_APP) && patch -Np1 -i $(DIR_SRC)/src/patches/dnsmasq/028-Minor_tweak_to_previous_commit.patch + cd $(DIR_APP) && patch -Np1 -i $(DIR_SRC)/src/patches/dnsmasq/029-NSEC3_check_RFC5155_para_8_2.patch cd $(DIR_APP) && patch -Np1 -i $(DIR_SRC)/src/patches/dnsmasq-Add-support-to-read-ISC-DHCP-lease-file.patch
cd $(DIR_APP) && sed -i src/config.h \ diff --git a/src/patches/dnsmasq/025-Major_tidy_up_of_EDNS0_handling_and_computation_use_of_udp.patch b/src/patches/dnsmasq/025-Major_tidy_up_of_EDNS0_handling_and_computation_use_of_udp.patch new file mode 100644 index 0000000..c016e73 --- /dev/null +++ b/src/patches/dnsmasq/025-Major_tidy_up_of_EDNS0_handling_and_computation_use_of_udp.patch @@ -0,0 +1,643 @@ +From fa14bec83b2db010fd076910fddab56957b9375d Mon Sep 17 00:00:00 2001 +From: Simon Kelley simon@thekelleys.org.uk +Date: Sun, 20 Dec 2015 17:12:16 +0000 +Subject: [PATCH] Major tidy up of EDNS0 handling and computation/use of udp + packet size. + +--- + src/auth.c | 8 ++- + src/dnsmasq.h | 7 ++- + src/dnssec.c | 1 - + src/forward.c | 184 ++++++++++++++++++++++++++++++++++++++++---------------- + src/netlink.c | 3 +- + src/rfc1035.c | 81 +++++++------------------ + src/rrfilter.c | 2 +- + 7 files changed, 168 insertions(+), 118 deletions(-) + +diff --git a/src/auth.c b/src/auth.c +index 2b0b7d6..85bd5e7 100644 +--- a/src/auth.c ++++ b/src/auth.c +@@ -81,7 +81,8 @@ int in_zone(struct auth_zone *zone, char *name, char **cut) + } + + +-size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t now, union mysockaddr *peer_addr, int local_query) ++size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t now, union mysockaddr *peer_addr, ++ int local_query, int do_bit, int have_pseudoheader) + { + char *name = daemon->namebuff; + unsigned char *p, *ansp; +@@ -820,6 +821,11 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n + header->ancount = htons(anscount); + header->nscount = htons(authcount); + header->arcount = htons(0); ++ ++ /* Advertise our packet size limit in our reply */ ++ if (have_pseudoheader) ++ return add_pseudoheader(header, ansp - (unsigned char *)header, (unsigned char *)limit, daemon->edns_pktsz, 0, NULL, 0, do_bit); ++ + return ansp - (unsigned char *)header; + } + +diff --git a/src/dnsmasq.h b/src/dnsmasq.h +index 39a930c..abb34c5 100644 +--- a/src/dnsmasq.h ++++ b/src/dnsmasq.h +@@ -1113,7 +1113,7 @@ int extract_addresses(struct dns_header *header, size_t qlen, char *namebuff, + int no_cache, int secure, int *doctored); + size_t answer_request(struct dns_header *header, char *limit, size_t qlen, + struct in_addr local_addr, struct in_addr local_netmask, +- time_t now, int *ad_reqd, int *do_bit); ++ time_t now, int ad_reqd, int do_bit, int have_pseudoheader); + int check_for_bogus_wildcard(struct dns_header *header, size_t qlen, char *name, + struct bogus_addr *addr, time_t now); + int check_for_ignored_address(struct dns_header *header, size_t qlen, struct bogus_addr *baddr); +@@ -1123,6 +1123,8 @@ int check_for_local_domain(char *name, time_t now); + unsigned int questions_crc(struct dns_header *header, size_t plen, char *buff); + size_t resize_packet(struct dns_header *header, size_t plen, + unsigned char *pheader, size_t hlen); ++size_t add_pseudoheader(struct dns_header *header, size_t plen, unsigned char *limit, ++ unsigned short udp_sz, int optno, unsigned char *opt, size_t optlen, int set_do); + size_t add_mac(struct dns_header *header, size_t plen, char *limit, union mysockaddr *l3); + size_t add_source_addr(struct dns_header *header, size_t plen, char *limit, union mysockaddr *source); + #ifdef HAVE_DNSSEC +@@ -1141,7 +1143,8 @@ int private_net(struct in_addr addr, int ban_localhost); + /* auth.c */ + #ifdef HAVE_AUTH + size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, +- time_t now, union mysockaddr *peer_addr, int local_query); ++ time_t now, union mysockaddr *peer_addr, int local_query, ++ int do_bit, int have_pseudoheader); + int in_zone(struct auth_zone *zone, char *name, char **cut); + #endif + +diff --git a/src/dnssec.c b/src/dnssec.c +index 82394ee..299ca64 100644 +--- a/src/dnssec.c ++++ b/src/dnssec.c +@@ -67,7 +67,6 @@ static char *algo_digest_name(int algo) + case 12: return "gosthash94"; + case 13: return "sha256"; + case 14: return "sha384"; +- + default: return NULL; + } + } +diff --git a/src/forward.c b/src/forward.c +index 3e801c8..041353c 100644 +--- a/src/forward.c ++++ b/src/forward.c +@@ -244,7 +244,6 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr, + void *hash = &crc; + #endif + unsigned int gotname = extract_request(header, plen, daemon->namebuff, NULL); +- unsigned char *pheader; + + (void)do_bit; + +@@ -264,7 +263,8 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr, + there's no point retrying the query, retry the key query instead...... */ + if (forward->blocking_query) + { +- int fd; ++ int fd, is_sign; ++ unsigned char *pheader; + + forward->flags &= ~FREC_TEST_PKTSZ; + +@@ -276,8 +276,8 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr, + blockdata_retrieve(forward->stash, forward->stash_len, (void *)header); + plen = forward->stash_len; + +- if (find_pseudoheader(header, plen, NULL, &pheader, NULL)) +- PUTSHORT((forward->flags & FREC_TEST_PKTSZ) ? SAFE_PKTSZ : forward->sentto->edns_pktsz, pheader); ++ if (find_pseudoheader(header, plen, NULL, &pheader, &is_sign) && !is_sign) ++ PUTSHORT(SAFE_PKTSZ, pheader); + + if (forward->sentto->addr.sa.sa_family == AF_INET) + log_query(F_NOEXTRA | F_DNSSEC | F_IPV4, "retry", (struct all_addr *)&forward->sentto->addr.in.sin_addr, "dnssec"); +@@ -394,32 +394,40 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr, + forward->log_id = daemon->log_id; + + if (option_bool(OPT_ADD_MAC)) +- plen = add_mac(header, plen, ((char *) header) + daemon->packet_buff_sz, &forward->source); +- ++ { ++ size_t new = add_mac(header, plen, ((char *) header) + daemon->packet_buff_sz, &forward->source); ++ if (new != plen) ++ { ++ plen = new; ++ forward->flags |= FREC_ADDED_PHEADER; ++ } ++ } ++ + if (option_bool(OPT_CLIENT_SUBNET)) + { + size_t new = add_source_addr(header, plen, ((char *) header) + daemon->packet_buff_sz, &forward->source); + if (new != plen) + { + plen = new; +- forward->flags |= FREC_HAS_SUBNET; ++ forward->flags |= FREC_HAS_SUBNET | FREC_ADDED_PHEADER; + } + } + + #ifdef HAVE_DNSSEC + if (option_bool(OPT_DNSSEC_VALID)) + { +- size_t new_plen = add_do_bit(header, plen, ((char *) header) + daemon->packet_buff_sz); ++ size_t new = add_do_bit(header, plen, ((char *) header) + daemon->packet_buff_sz); + ++ if (new != plen) ++ forward->flags |= FREC_ADDED_PHEADER; ++ ++ plen = new; ++ + /* For debugging, set Checking Disabled, otherwise, have the upstream check too, + this allows it to select auth servers when one is returning bad data. */ + if (option_bool(OPT_DNSSEC_DEBUG)) + header->hb4 |= HB4_CD; + +- if (new_plen != plen) +- forward->flags |= FREC_ADDED_PHEADER; +- +- plen = new_plen; + } + #endif + +@@ -469,10 +477,23 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr, + } + #endif + } +- +- if (find_pseudoheader(header, plen, NULL, &pheader, NULL)) +- PUTSHORT((forward->flags & FREC_TEST_PKTSZ) ? SAFE_PKTSZ : start->edns_pktsz, pheader); + ++#ifdef HAVE_DNSSEC ++ if (option_bool(OPT_DNSSEC_VALID) && !do_bit) ++ { ++ /* Difficult one here. If our client didn't send EDNS0, we will have set the UDP ++ packet size to 512. But that won't provide space for the RRSIGS in many cases. ++ The RRSIGS will be stripped out before the answer goes back, so the packet should ++ shrink again. So, if we added a do-bit, bump the udp packet size to the value ++ known to be OK for this server. Maybe check returned size after stripping and set ++ the truncated bit? */ ++ unsigned char *pheader; ++ int is_sign; ++ if (find_pseudoheader(header, plen, NULL, &pheader, &is_sign)) ++ PUTSHORT(start->edns_pktsz, pheader); ++ } ++#endif ++ + if (retry_send(sendto(fd, (char *)header, plen, 0, + &start->addr.sa, + sa_len(&start->addr)))) +@@ -563,30 +584,34 @@ static size_t process_reply(struct dns_header *header, time_t now, struct server + } + #endif + +- /* If upstream is advertising a larger UDP packet size +- than we allow, trim it so that we don't get overlarge +- requests for the client. We can't do this for signed packets. */ +- + if ((pheader = find_pseudoheader(header, n, &plen, &sizep, &is_sign))) + { +- unsigned short udpsz; +- unsigned char *psave = sizep; +- +- GETSHORT(udpsz, sizep); +- +- if (!is_sign && udpsz > daemon->edns_pktsz) +- PUTSHORT(daemon->edns_pktsz, psave); +- + if (check_subnet && !check_source(header, plen, pheader, query_source)) + { + my_syslog(LOG_WARNING, _("discarding DNS reply: subnet option mismatch")); + return 0; + } + +- if (added_pheader) ++ if (!is_sign) + { +- pheader = 0; +- header->arcount = htons(0); ++ if (added_pheader) ++ { ++ /* client didn't send EDNS0, we added one, strip it off before returning answer. */ ++ n = rrfilter(header, n, 0); ++ pheader = NULL; ++ } ++ else ++ { ++ /* If upstream is advertising a larger UDP packet size ++ than we allow, trim it so that we don't get overlarge ++ requests for the client. We can't do this for signed packets. */ ++ unsigned short udpsz; ++ unsigned char *psave = sizep; ++ ++ GETSHORT(udpsz, sizep); ++ if (udpsz > daemon->edns_pktsz) ++ PUTSHORT(daemon->edns_pktsz, psave); ++ } + } + } + +@@ -655,14 +680,16 @@ static size_t process_reply(struct dns_header *header, time_t now, struct server + } + + if (option_bool(OPT_DNSSEC_VALID)) +- header->hb4 &= ~HB4_AD; +- +- if (!(header->hb4 & HB4_CD) && ad_reqd && cache_secure) +- header->hb4 |= HB4_AD; +- +- /* If the requestor didn't set the DO bit, don't return DNSSEC info. */ +- if (!do_bit) +- n = rrfilter(header, n, 1); ++ { ++ header->hb4 &= ~HB4_AD; ++ ++ if (!(header->hb4 & HB4_CD) && ad_reqd && cache_secure) ++ header->hb4 |= HB4_AD; ++ ++ /* If the requestor didn't set the DO bit, don't return DNSSEC info. */ ++ if (!do_bit) ++ n = rrfilter(header, n, 1); ++ } + #endif + + /* do this after extract_addresses. Ensure NODATA reply and remove +@@ -761,8 +788,14 @@ void reply_query(int fd, int family, time_t now) + if ((nn = resize_packet(header, (size_t)n, pheader, plen))) + { + header->hb3 &= ~(HB3_QR | HB3_AA | HB3_TC); +- header->hb4 &= ~(HB4_RA | HB4_RCODE); +- forward_query(-1, NULL, NULL, 0, header, nn, now, forward, 0, 0); ++ header->hb4 &= ~(HB4_RA | HB4_RCODE | HB4_CD | HB4_AD); ++ if (forward->flags |= FREC_CHECKING_DISABLED) ++ header->hb4 |= HB4_CD; ++ if (forward->flags |= FREC_AD_QUESTION) ++ header->hb4 |= HB4_AD; ++ if (forward->flags & FREC_DO_QUESTION) ++ add_do_bit(header, nn, (char *)pheader + plen); ++ forward_query(-1, NULL, NULL, 0, header, nn, now, forward, forward->flags & FREC_AD_QUESTION, forward->flags & FREC_DO_QUESTION); + return; + } + } +@@ -1007,12 +1040,13 @@ void receive_query(struct listener *listen, time_t now) + { + struct dns_header *header = (struct dns_header *)daemon->packet; + union mysockaddr source_addr; +- unsigned short type; ++ unsigned char *pheader; ++ unsigned short type, udp_size = PACKETSZ; /* default if no EDNS0 */ + struct all_addr dst_addr; + struct in_addr netmask, dst_addr_4; + size_t m; + ssize_t n; +- int if_index = 0, auth_dns = 0; ++ int if_index = 0, auth_dns = 0, do_bit = 0, have_pseudoheader = 0; + #ifdef HAVE_AUTH + int local_auth = 0; + #endif +@@ -1279,10 +1313,30 @@ void receive_query(struct listener *listen, time_t now) + #endif + } + ++ if (find_pseudoheader(header, (size_t)n, NULL, &pheader, NULL)) ++ { ++ unsigned short flags; ++ ++ have_pseudoheader = 1; ++ GETSHORT(udp_size, pheader); ++ pheader += 2; /* ext_rcode */ ++ GETSHORT(flags, pheader); ++ ++ if (flags & 0x8000) ++ do_bit = 1;/* do bit */ ++ ++ /* If the client provides an EDNS0 UDP size, use that to limit our reply. ++ (bounded by the maximum configured). If no EDNS0, then it ++ defaults to 512 */ ++ if (udp_size > daemon->edns_pktsz) ++ udp_size = daemon->edns_pktsz; ++ } ++ + #ifdef HAVE_AUTH + if (auth_dns) + { +- m = answer_auth(header, ((char *) header) + daemon->packet_buff_sz, (size_t)n, now, &source_addr, local_auth); ++ m = answer_auth(header, ((char *) header) + udp_size, (size_t)n, now, &source_addr, ++ local_auth, do_bit, have_pseudoheader); + if (m >= 1) + { + send_from(listen->fd, option_bool(OPT_NOWILD) || option_bool(OPT_CLEVERBIND), +@@ -1293,9 +1347,13 @@ void receive_query(struct listener *listen, time_t now) + else + #endif + { +- int ad_reqd, do_bit; +- m = answer_request(header, ((char *) header) + daemon->packet_buff_sz, (size_t)n, +- dst_addr_4, netmask, now, &ad_reqd, &do_bit); ++ int ad_reqd = do_bit; ++ /* RFC 6840 5.7 */ ++ if (header->hb4 & HB4_AD) ++ ad_reqd = 1; ++ ++ m = answer_request(header, ((char *) header) + udp_size, (size_t)n, ++ dst_addr_4, netmask, now, ad_reqd, do_bit, have_pseudoheader); + + if (m >= 1) + { +@@ -1397,7 +1455,7 @@ unsigned char *tcp_request(int confd, time_t now, + #ifdef HAVE_AUTH + int local_auth = 0; + #endif +- int checking_disabled, ad_question, do_bit, added_pheader = 0; ++ int checking_disabled, do_bit, added_pheader = 0, have_pseudoheader = 0; + int check_subnet, no_cache_dnssec = 0, cache_secure = 0, bogusanswer = 0; + size_t m; + unsigned short qtype; +@@ -1414,6 +1472,7 @@ unsigned char *tcp_request(int confd, time_t now, + union mysockaddr peer_addr; + socklen_t peer_len = sizeof(union mysockaddr); + int query_count = 0; ++ unsigned char *pheader; + + if (getpeername(confd, (struct sockaddr *)&peer_addr, &peer_len) == -1) + return packet; +@@ -1508,15 +1567,35 @@ unsigned char *tcp_request(int confd, time_t now, + else + dst_addr_4.s_addr = 0; + ++ do_bit = 0; ++ ++ if (find_pseudoheader(header, (size_t)size, NULL, &pheader, NULL)) ++ { ++ unsigned short flags; ++ ++ have_pseudoheader = 1; ++ pheader += 4; /* udp_size, ext_rcode */ ++ GETSHORT(flags, pheader); ++ ++ if (flags & 0x8000) ++ do_bit = 1;/* do bit */ ++ } ++ + #ifdef HAVE_AUTH + if (auth_dns) +- m = answer_auth(header, ((char *) header) + 65536, (size_t)size, now, &peer_addr, local_auth); ++ m = answer_auth(header, ((char *) header) + 65536, (size_t)size, now, &peer_addr, ++ local_auth, do_bit, have_pseudoheader); + else + #endif + { +- /* m > 0 if answered from cache */ +- m = answer_request(header, ((char *) header) + 65536, (size_t)size, +- dst_addr_4, netmask, now, &ad_question, &do_bit); ++ int ad_reqd = do_bit; ++ /* RFC 6840 5.7 */ ++ if (header->hb4 & HB4_AD) ++ ad_reqd = 1; ++ ++ /* m > 0 if answered from cache */ ++ m = answer_request(header, ((char *) header) + 65536, (size_t)size, ++ dst_addr_4, netmask, now, ad_reqd, do_bit, have_pseudoheader); + + /* Do this by steam now we're not in the select() loop */ + check_log_writer(1); +@@ -1615,6 +1694,7 @@ unsigned char *tcp_request(int confd, time_t now, + } + + #ifdef HAVE_DNSSEC ++ added_pheader = 0; + if (option_bool(OPT_DNSSEC_VALID)) + { + size_t new_size = add_do_bit(header, size, ((char *) header) + 65536); +@@ -1719,7 +1799,7 @@ unsigned char *tcp_request(int confd, time_t now, + + m = process_reply(header, now, last_server, (unsigned int)m, + option_bool(OPT_NO_REBIND) && !norebind, no_cache_dnssec, cache_secure, bogusanswer, +- ad_question, do_bit, added_pheader, check_subnet, &peer_addr); ++ ad_reqd, do_bit, added_pheader, check_subnet, &peer_addr); + + break; + } +diff --git a/src/netlink.c b/src/netlink.c +index 753784d..3376d68 100644 +--- a/src/netlink.c ++++ b/src/netlink.c +@@ -288,7 +288,8 @@ int iface_enumerate(int family, void *parm, int (*callback)()) + rta = RTA_NEXT(rta, len1); + } + +- if (inaddr && mac && callback_ok) ++ if (!(neigh->ndm_state & (NUD_NOARP | NUD_INCOMPLETE | NUD_FAILED)) && ++ inaddr && mac && callback_ok) + if (!((*callback)(neigh->ndm_family, inaddr, mac, maclen, parm))) + callback_ok = 0; + } +diff --git a/src/rfc1035.c b/src/rfc1035.c +index 188d05f..18858a8 100644 +--- a/src/rfc1035.c ++++ b/src/rfc1035.c +@@ -489,8 +489,8 @@ struct macparm { + union mysockaddr *l3; + }; + +-static size_t add_pseudoheader(struct dns_header *header, size_t plen, unsigned char *limit, +- int optno, unsigned char *opt, size_t optlen, int set_do) ++size_t add_pseudoheader(struct dns_header *header, size_t plen, unsigned char *limit, ++ unsigned short udp_sz, int optno, unsigned char *opt, size_t optlen, int set_do) + { + unsigned char *lenp, *datap, *p; + int rdlen, is_sign; +@@ -508,7 +508,7 @@ static size_t add_pseudoheader(struct dns_header *header, size_t plen, unsigned + return plen; + *p++ = 0; /* empty name */ + PUTSHORT(T_OPT, p); +- PUTSHORT(SAFE_PKTSZ, p); /* max packet length, this will be overwritten */ ++ PUTSHORT(udp_sz, p); /* max packet length, 512 if not given in EDNS0 header */ + PUTSHORT(0, p); /* extended RCODE and version */ + PUTSHORT(set_do ? 0x8000 : 0, p); /* DO flag */ + lenp = p; +@@ -594,7 +594,7 @@ static int filter_mac(int family, char *addrp, char *mac, size_t maclen, void *p + if (!match) + return 1; /* continue */ + +- parm->plen = add_pseudoheader(parm->header, parm->plen, parm->limit, EDNS0_OPTION_MAC, (unsigned char *)mac, maclen, 0); ++ parm->plen = add_pseudoheader(parm->header, parm->plen, parm->limit, PACKETSZ, EDNS0_OPTION_MAC, (unsigned char *)mac, maclen, 0); + + return 0; /* done */ + } +@@ -603,12 +603,6 @@ size_t add_mac(struct dns_header *header, size_t plen, char *limit, union mysock + { + struct macparm parm; + +-/* Must have an existing pseudoheader as the only ar-record, +- or have no ar-records. Must also not be signed */ +- +- if (ntohs(header->arcount) > 1) +- return plen; +- + parm.header = header; + parm.limit = (unsigned char *)limit; + parm.plen = plen; +@@ -699,13 +693,13 @@ size_t add_source_addr(struct dns_header *header, size_t plen, char *limit, unio + struct subnet_opt opt; + + len = calc_subnet_opt(&opt, source); +- return add_pseudoheader(header, plen, (unsigned char *)limit, EDNS0_OPTION_CLIENT_SUBNET, (unsigned char *)&opt, len, 0); ++ return add_pseudoheader(header, plen, (unsigned char *)limit, PACKETSZ, EDNS0_OPTION_CLIENT_SUBNET, (unsigned char *)&opt, len, 0); + } + + #ifdef HAVE_DNSSEC + size_t add_do_bit(struct dns_header *header, size_t plen, char *limit) + { +- return add_pseudoheader(header, plen, (unsigned char *)limit, 0, NULL, 0, 1); ++ return add_pseudoheader(header, plen, (unsigned char *)limit, PACKETSZ, 0, NULL, 0, 1); + } + #endif + +@@ -1525,16 +1519,16 @@ static unsigned long crec_ttl(struct crec *crecp, time_t now) + /* return zero if we can't answer from cache, or packet size if we can */ + size_t answer_request(struct dns_header *header, char *limit, size_t qlen, + struct in_addr local_addr, struct in_addr local_netmask, +- time_t now, int *ad_reqd, int *do_bit) ++ time_t now, int ad_reqd, int do_bit, int have_pseudoheader) + { + char *name = daemon->namebuff; +- unsigned char *p, *ansp, *pheader; ++ unsigned char *p, *ansp; + unsigned int qtype, qclass; + struct all_addr addr; + int nameoffset; + unsigned short flag; + int q, ans, anscount = 0, addncount = 0; +- int dryrun = 0, sec_reqd = 0, have_pseudoheader = 0; ++ int dryrun = 0; + struct crec *crecp; + int nxdomain = 0, auth = 1, trunc = 0, sec_data = 1; + struct mx_srv_record *rec; +@@ -1550,35 +1544,11 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen, + if (header->hb4 & HB4_CD) + sec_data = 0; + +- /* RFC 6840 5.7 */ +- *ad_reqd = header->hb4 & HB4_AD; +- *do_bit = 0; +- + /* If there is an additional data section then it will be overwritten by + partial replies, so we have to do a dry run to see if we can answer + the query. */ +- + if (ntohs(header->arcount) != 0) +- { +- dryrun = 1; +- +- /* If there's an additional section, there might be an EDNS(0) pseudoheader */ +- if (find_pseudoheader(header, qlen, NULL, &pheader, NULL)) +- { +- unsigned short flags; +- +- have_pseudoheader = 1; +- +- pheader += 4; /* udp size, ext_rcode */ +- GETSHORT(flags, pheader); +- +- if ((sec_reqd = flags & 0x8000)) +- { +- *do_bit = 1;/* do bit */ +- *ad_reqd = 1; +- } +- } +- } ++ dryrun = 1; + + for (rec = daemon->mxnames; rec; rec = rec->next) + rec->offset = 0; +@@ -1603,11 +1573,6 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen, + GETSHORT(qtype, p); + GETSHORT(qclass, p); + +- /* Don't filter RRSIGS from answers to ANY queries, even if do-bit +- not set. */ +- if (qtype == T_ANY) +- *do_bit = 1; +- + ans = 0; /* have we answered this question */ + + if (qtype == T_TXT || qtype == T_ANY) +@@ -1739,7 +1704,7 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen, + the zone is unsigned, which implies that we're doing + validation. */ + if ((crecp->flags & (F_HOSTS | F_DHCP | F_CONFIG)) || +- !sec_reqd || ++ !do_bit || + (option_bool(OPT_DNSSEC_VALID) && !(crecp->flags & F_DNSSECOK))) + { + do +@@ -1927,7 +1892,7 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen, + } + + /* If the client asked for DNSSEC don't use cached data. */ +- if ((crecp->flags & (F_HOSTS | F_DHCP | F_CONFIG)) || !sec_reqd || !(crecp->flags & F_DNSSECOK)) ++ if ((crecp->flags & (F_HOSTS | F_DHCP | F_CONFIG)) || !do_bit || !(crecp->flags & F_DNSSECOK)) + do + { + /* don't answer wildcard queries with data not from /etc/hosts +@@ -1961,17 +1926,12 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen, + + if (crecp->flags & F_NEG) + { +- /* We don't cache NSEC records, so if a DNSSEC-validated negative answer +- is cached and the client wants DNSSEC, forward rather than answering from the cache */ +- if (!sec_reqd || !(crecp->flags & F_DNSSECOK)) +- { +- ans = 1; +- auth = 0; +- if (crecp->flags & F_NXDOMAIN) +- nxdomain = 1; +- if (!dryrun) +- log_query(crecp->flags, name, NULL, NULL); +- } ++ ans = 1; ++ auth = 0; ++ if (crecp->flags & F_NXDOMAIN) ++ nxdomain = 1; ++ if (!dryrun) ++ log_query(crecp->flags, name, NULL, NULL); + } + else + { +@@ -2209,10 +2169,11 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen, + + len = ansp - (unsigned char *)header; + ++ /* Advertise our packet size limit in our reply */ + if (have_pseudoheader) +- len = add_pseudoheader(header, len, (unsigned char *)limit, 0, NULL, 0, sec_reqd); ++ len = add_pseudoheader(header, len, (unsigned char *)limit, daemon->edns_pktsz, 0, NULL, 0, do_bit); + +- if (*ad_reqd && sec_data) ++ if (ad_reqd && sec_data) + header->hb4 |= HB4_AD; + else + header->hb4 &= ~HB4_AD; +diff --git a/src/rrfilter.c b/src/rrfilter.c +index ae12261..b26b39f 100644 +--- a/src/rrfilter.c ++++ b/src/rrfilter.c +@@ -243,7 +243,7 @@ size_t rrfilter(struct dns_header *header, size_t plen, int mode) + for (p = rrs[0], i = 1; i < rr_found; i += 2) + { + unsigned char *start = rrs[i]; +- unsigned char *end = (i != rr_found - 1) ? rrs[i+1] : ((unsigned char *)(header+1)) + plen; ++ unsigned char *end = (i != rr_found - 1) ? rrs[i+1] : ((unsigned char *)header) + plen; + + memmove(p, start, end-start); + p += end-start; +-- +1.7.10.4 + diff --git a/src/patches/dnsmasq/026-More_tweaks_in_handling_unknown_DNSSEC_algorithms.patch b/src/patches/dnsmasq/026-More_tweaks_in_handling_unknown_DNSSEC_algorithms.patch new file mode 100644 index 0000000..910921b --- /dev/null +++ b/src/patches/dnsmasq/026-More_tweaks_in_handling_unknown_DNSSEC_algorithms.patch @@ -0,0 +1,262 @@ +From d67ecac59d58f249707d26e38d49c29b552af4d8 Mon Sep 17 00:00:00 2001 +From: Simon Kelley simon@thekelleys.org.uk +Date: Sun, 20 Dec 2015 20:44:23 +0000 +Subject: [PATCH] More tweaks in handling unknown DNSSEC algorithms. + +--- + src/dnssec.c | 128 +++++++++++++++++++++++++++++----------------------------- + 1 file changed, 63 insertions(+), 65 deletions(-) + +diff --git a/src/dnssec.c b/src/dnssec.c +index 299ca64..e09f304 100644 +--- a/src/dnssec.c ++++ b/src/dnssec.c +@@ -70,7 +70,17 @@ static char *algo_digest_name(int algo) + default: return NULL; + } + } +- ++ ++/* http://www.iana.org/assignments/dnssec-nsec3-parameters/dnssec-nsec3-paramet... */ ++static char *nsec3_digest_name(int digest) ++{ ++ switch (digest) ++ { ++ case 1: return "sha1"; ++ default: return NULL; ++ } ++} ++ + /* Find pointer to correct hash function in nettle library */ + static const struct nettle_hash *hash_find(char *name) + { +@@ -667,7 +677,6 @@ static int explore_rrset(struct dns_header *header, size_t plen, int class, int + static int rrset_sz = 0, sig_sz = 0; + unsigned char *p; + int rrsetidx, sigidx, j, rdlen, res; +- int name_labels = count_labels(name); /* For 4035 5.3.2 check */ + int gotkey = 0; + + if (!(p = skip_questions(header, plen))) +@@ -678,7 +687,7 @@ static int explore_rrset(struct dns_header *header, size_t plen, int class, int + j != 0; j--) + { + unsigned char *pstart, *pdata; +- int stype, sclass, algo, type_covered, labels, sig_expiration, sig_inception; ++ int stype, sclass, type_covered; + + pstart = p; + +@@ -712,12 +721,7 @@ static int explore_rrset(struct dns_header *header, size_t plen, int class, int + return 0; /* bad packet */ + + GETSHORT(type_covered, p); +- algo = *p++; +- labels = *p++; +- p += 4; /* orig_ttl */ +- GETLONG(sig_expiration, p); +- GETLONG(sig_inception, p); +- p += 2; /* key_tag */ ++ p += 16; /* algo, labels, orig_ttl, sig_expiration, sig_inception, key_tag */ + + if (gotkey) + { +@@ -749,11 +753,8 @@ static int explore_rrset(struct dns_header *header, size_t plen, int class, int + } + } + +- /* Don't count signatures for algos we don't support */ +- if (check_date_range(sig_inception, sig_expiration) && +- labels <= name_labels && +- type_covered == type && +- verify_func(algo)) ++ ++ if (type_covered == type) + { + if (!expand_workspace(&sigs, &sig_sz, sigidx)) + return 0; +@@ -795,7 +796,7 @@ static int validate_rrset(time_t now, struct dns_header *header, size_t plen, in + char *name, char *keyname, char **wildcard_out, struct blockdata *key, int keylen, int algo_in, int keytag_in) + { + unsigned char *p; +- int rdlen, j, name_labels; ++ int rdlen, j, name_labels, sig_expiration, sig_inception; + struct crec *crecp = NULL; + int algo, labels, orig_ttl, key_tag; + u16 *rr_desc = rrfilter_desc(type); +@@ -828,13 +829,16 @@ static int validate_rrset(time_t now, struct dns_header *header, size_t plen, in + algo = *p++; + labels = *p++; + GETLONG(orig_ttl, p); +- p += 8; /* sig_expiration, sig_inception already checked */ ++ GETLONG(sig_expiration, p); ++ GETLONG(sig_inception, p); + GETSHORT(key_tag, p); + + if (!extract_name(header, plen, &p, keyname, 1, 0)) + return STAT_BOGUS; + +- if (!(hash = hash_find(algo_digest_name(algo))) || ++ if (!check_date_range(sig_inception, sig_expiration) || ++ labels > name_labels || ++ !(hash = hash_find(algo_digest_name(algo))) || + !hash_init(hash, &ctx, &digest)) + continue; + +@@ -1112,7 +1116,10 @@ int dnssec_validate_by_ds(time_t now, struct dns_header *header, size_t plen, ch + else + { + a.addr.keytag = keytag; +- log_query(F_NOEXTRA | F_KEYTAG | F_UPSTREAM, name, &a, "DNSKEY keytag %u"); ++ if (verify_func(algo)) ++ log_query(F_NOEXTRA | F_KEYTAG | F_UPSTREAM, name, &a, "DNSKEY keytag %u"); ++ else ++ log_query(F_NOEXTRA | F_KEYTAG | F_UPSTREAM, name, &a, "DNSKEY keytag %u (not supported)"); + + recp1->addr.key.keylen = rdlen - 4; + recp1->addr.key.keydata = key; +@@ -1235,7 +1242,11 @@ int dnssec_validate_ds(time_t now, struct dns_header *header, size_t plen, char + else + { + a.addr.keytag = keytag; +- log_query(F_NOEXTRA | F_KEYTAG | F_UPSTREAM, name, &a, "DS keytag %u"); ++ if (hash_find(ds_digest_name(digest)) && verify_func(algo)) ++ log_query(F_NOEXTRA | F_KEYTAG | F_UPSTREAM, name, &a, "DS keytag %u"); ++ else ++ log_query(F_NOEXTRA | F_KEYTAG | F_UPSTREAM, name, &a, "DS keytag %u (not supported)"); ++ + crecp->addr.ds.digest = digest; + crecp->addr.ds.keydata = key; + crecp->addr.ds.algo = algo; +@@ -1660,7 +1671,7 @@ static int prove_non_existence_nsec3(struct dns_header *header, size_t plen, uns + *nons = 1; + + /* Look though the NSEC3 records to find the first one with +- an algorithm we support (currently only algo == 1). ++ an algorithm we support. + + Take the algo, iterations, and salt of that record + as the ones we're going to use, and prune any +@@ -1674,7 +1685,7 @@ static int prove_non_existence_nsec3(struct dns_header *header, size_t plen, uns + p += 10; /* type, class, TTL, rdlen */ + algo = *p++; + +- if (algo == 1) ++ if ((hash = hash_find(nsec3_digest_name(algo)))) + break; /* known algo */ + } + +@@ -1724,10 +1735,6 @@ static int prove_non_existence_nsec3(struct dns_header *header, size_t plen, uns + nsecs[i] = nsec3p; + } + +- /* Algo is checked as 1 above */ +- if (!(hash = hash_find("sha1"))) +- return 0; +- + if ((digest_len = hash_name(name, &digest, hash, salt, salt_len, iterations)) == 0) + return 0; + +@@ -1843,8 +1850,10 @@ static int prove_non_existence(struct dns_header *header, size_t plen, char *key + + if (type_found == T_NSEC) + return prove_non_existence_nsec(header, plen, nsecset, nsecs_found, daemon->workspacename, keyname, name, qtype, nons); +- else ++ else if (type_found == T_NSEC3) + return prove_non_existence_nsec3(header, plen, nsecset, nsecs_found, daemon->workspacename, keyname, name, qtype, wildname, nons); ++ else ++ return 0; + } + + /* Check signing status of name. +@@ -1857,7 +1866,7 @@ static int prove_non_existence(struct dns_header *header, size_t plen, char *key + */ + static int zone_status(char *name, int class, char *keyname, time_t now) + { +- int secure_ds, name_start = strlen(name); ++ int name_start = strlen(name); + struct crec *crecp; + char *p; + +@@ -1867,51 +1876,40 @@ static int zone_status(char *name, int class, char *keyname, time_t now) + + if (!(crecp = cache_find_by_name(NULL, keyname, now, F_DS))) + return STAT_NEED_DS; ++ ++ /* F_DNSSECOK misused in DS cache records to non-existance of NS record. ++ F_NEG && !F_DNSSECOK implies that we've proved there's no DS record here, ++ but that's because there's no NS record either, ie this isn't the start ++ of a zone. We only prove that the DNS tree below a node is unsigned when ++ we prove that we're at a zone cut AND there's no DS record. */ ++ if (crecp->flags & F_NEG) ++ { ++ if (crecp->flags & F_DNSSECOK) ++ return STAT_INSECURE; /* proved no DS here */ ++ } + else + { +- secure_ds = 0; +- ++ int gotone = 0; ++ ++ /* If all the DS records have digest and/or sig algos we don't support, ++ then the zone is insecure. Note that if an algo ++ appears in the DS, then RRSIGs for that algo MUST ++ exist for each RRset: 4035 para 2.2 So if we find ++ a DS here with digest and sig we can do, we're entitled ++ to assume we can validate the zone and if we can't later, ++ because an RRSIG is missing we return BOGUS. ++ */ + do + { +- if (crecp->uid == (unsigned int)class) +- { +- /* F_DNSSECOK misused in DS cache records to non-existance of NS record. +- F_NEG && !F_DNSSECOK implies that we've proved there's no DS record here, +- but that's because there's no NS record either, ie this isn't the start +- of a zone. We only prove that the DNS tree below a node is unsigned when +- we prove that we're at a zone cut AND there's no DS record. +- */ +- if (crecp->flags & F_NEG) +- { +- if (crecp->flags & F_DNSSECOK) +- return STAT_INSECURE; /* proved no DS here */ +- } +- else if (!hash_find(ds_digest_name(crecp->addr.ds.digest)) || !verify_func(crecp->addr.ds.algo)) +- return STAT_INSECURE; /* algo we can't use - insecure */ +- else +- secure_ds = 1; +- } ++ if (crecp->uid == (unsigned int)class && ++ hash_find(ds_digest_name(crecp->addr.ds.digest)) && ++ verify_func(crecp->addr.ds.algo)) ++ gotone = 1; + } + while ((crecp = cache_find_by_name(crecp, keyname, now, F_DS))); +- } +- +- if (secure_ds) +- { +- /* We've found only DS records that attest to the DNSKEY RRset in the zone, so we believe +- that RRset is good. Furthermore the DNSKEY whose hash is proved by the DS record is +- one we can use. However the DNSKEY RRset may contain more than one key and +- one of the other keys may use an algorithm we don't support. If that's +- the case the zone is insecure for us. */ +- +- if (!(crecp = cache_find_by_name(NULL, keyname, now, F_DNSKEY))) +- return STAT_NEED_KEY; + +- do +- { +- if (crecp->uid == (unsigned int)class && !verify_func(crecp->addr.key.algo)) +- return STAT_INSECURE; +- } +- while ((crecp = cache_find_by_name(crecp, keyname, now, F_DNSKEY))); ++ if (!gotone) ++ return STAT_INSECURE; + } + + if (name_start == 0) +-- +1.7.10.4 + diff --git a/src/patches/dnsmasq/027-Nasty_rare_and_obscure_off-by-one_in_DNSSEC_hostname_cmp.patch b/src/patches/dnsmasq/027-Nasty_rare_and_obscure_off-by-one_in_DNSSEC_hostname_cmp.patch new file mode 100644 index 0000000..031339e --- /dev/null +++ b/src/patches/dnsmasq/027-Nasty_rare_and_obscure_off-by-one_in_DNSSEC_hostname_cmp.patch @@ -0,0 +1,27 @@ +From 3e86d316c4bb406ed813aa5256615c8a95cac6d8 Mon Sep 17 00:00:00 2001 +From: Simon Kelley simon@thekelleys.org.uk +Date: Sun, 20 Dec 2015 20:50:05 +0000 +Subject: [PATCH] Nasty, rare and obscure off-by-one in DNSSEC hostname_cmp(). + +--- + src/dnssec.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/src/dnssec.c b/src/dnssec.c +index e09f304..29848e1 100644 +--- a/src/dnssec.c ++++ b/src/dnssec.c +@@ -1394,8 +1394,8 @@ static int hostname_cmp(const char *a, const char *b) + if (sb == b) + return 1; + +- ea = sa--; +- eb = sb--; ++ ea = --sa; ++ eb = --sb; + } + } + +-- +1.7.10.4 + diff --git a/src/patches/dnsmasq/028-Minor_tweak_to_previous_commit.patch b/src/patches/dnsmasq/028-Minor_tweak_to_previous_commit.patch new file mode 100644 index 0000000..f3758fc --- /dev/null +++ b/src/patches/dnsmasq/028-Minor_tweak_to_previous_commit.patch @@ -0,0 +1,39 @@ +From a86fdf437ecc29398f9715ceb5240442a17ac014 Mon Sep 17 00:00:00 2001 +From: Simon Kelley simon@thekelleys.org.uk +Date: Sun, 20 Dec 2015 21:19:20 +0000 +Subject: [PATCH] Minor tweak to previous commit. + +--- + src/dnssec.c | 6 ++---- + 1 file changed, 2 insertions(+), 4 deletions(-) + +diff --git a/src/dnssec.c b/src/dnssec.c +index 29848e1..9fa64b6 100644 +--- a/src/dnssec.c ++++ b/src/dnssec.c +@@ -1889,8 +1889,6 @@ static int zone_status(char *name, int class, char *keyname, time_t now) + } + else + { +- int gotone = 0; +- + /* If all the DS records have digest and/or sig algos we don't support, + then the zone is insecure. Note that if an algo + appears in the DS, then RRSIGs for that algo MUST +@@ -1904,11 +1902,11 @@ static int zone_status(char *name, int class, char *keyname, time_t now) + if (crecp->uid == (unsigned int)class && + hash_find(ds_digest_name(crecp->addr.ds.digest)) && + verify_func(crecp->addr.ds.algo)) +- gotone = 1; ++ break; + } + while ((crecp = cache_find_by_name(crecp, keyname, now, F_DS))); + +- if (!gotone) ++ if (!crecp) + return STAT_INSECURE; + } + +-- +1.7.10.4 + diff --git a/src/patches/dnsmasq/029-NSEC3_check_RFC5155_para_8_2.patch b/src/patches/dnsmasq/029-NSEC3_check_RFC5155_para_8_2.patch new file mode 100644 index 0000000..33219d2 --- /dev/null +++ b/src/patches/dnsmasq/029-NSEC3_check_RFC5155_para_8_2.patch @@ -0,0 +1,39 @@ +From ce5732e84fc46d7f99c152f736cfb4ef5ec98a01 Mon Sep 17 00:00:00 2001 +From: Simon Kelley simon@thekelleys.org.uk +Date: Sun, 20 Dec 2015 21:39:19 +0000 +Subject: [PATCH] NSEC3 check: RFC5155 para 8.2 + +--- + src/dnssec.c | 8 ++++++-- + 1 file changed, 6 insertions(+), 2 deletions(-) + +diff --git a/src/dnssec.c b/src/dnssec.c +index 9fa64b6..486e422 100644 +--- a/src/dnssec.c ++++ b/src/dnssec.c +@@ -1704,7 +1704,7 @@ static int prove_non_existence_nsec3(struct dns_header *header, size_t plen, uns + for (i = 0; i < nsec_count; i++) + { + unsigned char *nsec3p = nsecs[i]; +- int this_iter; ++ int this_iter, flags; + + nsecs[i] = NULL; /* Speculative, will be restored if OK. */ + +@@ -1716,8 +1716,12 @@ static int prove_non_existence_nsec3(struct dns_header *header, size_t plen, uns + if (*p++ != algo) + continue; + +- p++; /* flags */ ++ flags = *p++; /* flags */ + ++ /* 5155 8.2 */ ++ if (flags != 0 && flags != 1) ++ continue; ++ + GETSHORT(this_iter, p); + if (this_iter != iterations) + continue; +-- +1.7.10.4 +
hooks/post-receive -- IPFire 2.x development tree