mirror of
https://github.com/vincentmli/bpfire.git
synced 2026-04-26 02:42:58 +02:00
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>
This commit is contained in:
committed by
Michael Tremer
parent
2135528774
commit
c3b4c861f5
@@ -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 \
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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-parameters.xhtml */
|
||||
+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
|
||||
|
||||
@@ -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
|
||||
|
||||
39
src/patches/dnsmasq/028-Minor_tweak_to_previous_commit.patch
Normal file
39
src/patches/dnsmasq/028-Minor_tweak_to_previous_commit.patch
Normal file
@@ -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
|
||||
|
||||
39
src/patches/dnsmasq/029-NSEC3_check_RFC5155_para_8_2.patch
Normal file
39
src/patches/dnsmasq/029-NSEC3_check_RFC5155_para_8_2.patch
Normal file
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user