dnsmasq: Update to development snatpshot

This commit is contained in:
Michael Tremer
2015-02-02 00:33:04 +01:00
parent 06f451c0be
commit 32e321b248
8 changed files with 29 additions and 675 deletions

View File

@@ -24,10 +24,10 @@
include Config
VER = 2.72
VER = 1062667
THISAPP = dnsmasq-$(VER)
DL_FILE = $(THISAPP).tar.xz
DL_FILE = $(THISAPP)-20150201.tar.gz
DL_FROM = $(URL_IPFIRE)
DIR_APP = $(DIR_SRC)/$(THISAPP)
TARGET = $(DIR_INFO)/$(THISAPP)
@@ -42,7 +42,7 @@ objects = $(DL_FILE)
$(DL_FILE) = $(DL_FROM)/$(DL_FILE)
$(DL_FILE)_MD5 = 0256e0a71e27c8d8a5c89a0d18f3cfe2
$(DL_FILE)_MD5 = ee58d033a892faa69b099ed598f500c2
install : $(TARGET)
@@ -72,13 +72,7 @@ $(subst %,%_MD5,$(objects)) :
$(TARGET) : $(patsubst %,$(DIR_DL)/%,$(objects))
@$(PREBUILD)
@rm -rf $(DIR_APP) && cd $(DIR_SRC) && tar axf $(DIR_DL)/$(DL_FILE)
cd $(DIR_APP) && patch -Np1 -i $(DIR_SRC)/src/patches/dnsmasq/dnsmasq-2.73-remove-floor-on-edns0-packet-size-with-DNSSEC.patch
cd $(DIR_APP) && patch -Np1 -i $(DIR_SRC)/src/patches/dnsmasq/dnsmasq-2.73-fix-crash-in-DNSSEC-code-when-attempting-to-verify-large-RRs.patch
cd $(DIR_APP) && patch -Np1 -i $(DIR_SRC)/src/patches/dnsmasq/dnsmasq-2.73-make-caching-work-for-CNAMEs-pointing-to-A-AAAA-records-shadowed-in-etc-hosts.patch
cd $(DIR_APP) && patch -Np1 -i $(DIR_SRC)/src/patches/dnsmasq/dnsmasq-2.73-fix-problems-validating-NSEC3-and-wildcards.patch
cd $(DIR_APP) && patch -Np1 -i $(DIR_SRC)/src/patches/dnsmasq/dnsmasq-2.73-initialise-return-value.patch
cd $(DIR_APP) && patch -Np1 -i $(DIR_SRC)/src/patches/dnsmasq/dnsmasq-2.73-bad-packet-protection.patch
cd $(DIR_APP) && patch -Np1 -i $(DIR_SRC)/src/patches/dnsmasq-2.72rc2-Add-support-to-read-ISC-DHCP-lease-file.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 \
-e 's|/\* #define HAVE_IDN \*/|#define HAVE_IDN|g' \
-e 's|/\* #define HAVE_DNSSEC \*/|#define HAVE_DNSSEC|g' \
@@ -86,7 +80,7 @@ $(TARGET) : $(patsubst %,$(DIR_DL)/%,$(objects))
-e 's|#define HAVE_DHCP6|//#define HAVE_DHCP6|g' \
-e 's|#define HAVE_TFTP|//#define HAVE_TFTP|g'
cd $(DIR_APP) && make CFLAGS="$(CFLAGS)" COPTS="$(COPTS)" $(MAKETUNING)
cd $(DIR_APP) && make PREFIX=/usr install
cd $(DIR_APP) && make CFLAGS="$(CFLAGS)" COPTS="$(COPTS)" \
PREFIX=/usr all install
@rm -rf $(DIR_APP)
@$(POSTBUILD)

View File

@@ -1,18 +1,18 @@
diff --git a/Makefile b/Makefile
index 58a7975..616c6b7 100644
index 2910320b6452..0a76ce3c5154 100644
--- a/Makefile
+++ b/Makefile
@@ -69,7 +69,7 @@ objs = cache.o rfc1035.o util.o option.o forward.o network.o \
@@ -73,7 +73,7 @@ objs = cache.o rfc1035.o util.o option.o forward.o network.o \
dnsmasq.o dhcp.o lease.o rfc2131.o netlink.o dbus.o bpf.o \
helper.o tftp.o log.o conntrack.o dhcp6.o rfc3315.o \
dhcp-common.o outpacket.o radv.o slaac.o auth.o ipset.o \
- domain.o dnssec.o blockdata.o tables.o loop.o
+ domain.o dnssec.o blockdata.o tables.o loop.o isc.o
- domain.o dnssec.o blockdata.o tables.o loop.o inotify.o
+ domain.o dnssec.o blockdata.o tables.o loop.o inotify.o isc.o
hdrs = dnsmasq.h config.h dhcp-protocol.h dhcp6-protocol.h \
dns-protocol.h radv-protocol.h ip6addr.h
diff --git a/src/cache.c b/src/cache.c
index 2c3a498..77a7046 100644
index 117ae279fd4e..6ee7ee362e6c 100644
--- a/src/cache.c
+++ b/src/cache.c
@@ -17,7 +17,7 @@
@@ -34,8 +34,8 @@ index 2c3a498..77a7046 100644
#ifdef HAVE_DNSSEC
cache_blockdata_free(crecp);
#endif
@@ -1110,7 +1113,7 @@ void cache_reload(void)
total_size = read_hostsfile(ah->fname, ah->index, total_size, (struct crec **)daemon->packet, revhashsz);
@@ -1151,7 +1154,7 @@ void cache_reload(void)
}
-#ifdef HAVE_DHCP
@@ -43,7 +43,7 @@ index 2c3a498..77a7046 100644
struct in_addr a_record_from_hosts(char *name, time_t now)
{
struct crec *crecp = NULL;
@@ -1188,7 +1191,7 @@ void cache_add_dhcp_entry(char *host_name, int prot,
@@ -1229,7 +1232,7 @@ void cache_add_dhcp_entry(char *host_name, int prot,
addrlen = sizeof(struct in6_addr);
}
#endif
@@ -52,7 +52,7 @@ index 2c3a498..77a7046 100644
inet_ntop(prot, host_address, daemon->addrbuff, ADDRSTRLEN);
while ((crec = cache_find_by_name(crec, host_name, 0, flags | F_CNAME)))
@@ -1253,7 +1256,11 @@ void cache_add_dhcp_entry(char *host_name, int prot,
@@ -1294,7 +1297,11 @@ void cache_add_dhcp_entry(char *host_name, int prot,
else
crec->ttd = ttd;
crec->addr.addr = *host_address;
@@ -65,10 +65,10 @@ index 2c3a498..77a7046 100644
cache_hash(crec);
diff --git a/src/dnsmasq.c b/src/dnsmasq.c
index f4a89fc..a448ec4 100644
index e903a24c8105..eefc7f939933 100644
--- a/src/dnsmasq.c
+++ b/src/dnsmasq.c
@@ -940,6 +940,11 @@ int main (int argc, char **argv)
@@ -970,6 +970,11 @@ int main (int argc, char **argv)
poll_resolv(0, daemon->last_resolv != 0, now);
daemon->last_resolv = now;
@@ -78,30 +78,24 @@ index f4a89fc..a448ec4 100644
+ load_dhcp(now);
+#endif
}
if (FD_ISSET(piperead, &rset))
diff --git a/src/dnsmasq.h b/src/dnsmasq.h
index e74b15a..4a35168 100644
--- a/src/dnsmasq.h
+++ b/src/dnsmasq.h
@@ -1463,9 +1463,13 @@ time_t periodic_slaac(time_t now, struct dhcp_lease *leases);
void slaac_ping_reply(struct in6_addr *sender, unsigned char *packet, char *interface, struct dhcp_lease *leases);
#endif
diff --git a/src/dnsmasq.h b/src/dnsmasq.h
index 89e758b56a0a..c5edd6fdf7f5 100644
--- a/src/dnsmasq.h
+++ b/src/dnsmasq.h
@@ -1502,3 +1502,8 @@ void inotify_dnsmasq_init();
int inotify_check(time_t now);
void set_dynamic_inotify(int flag, int total_size, struct crec **rhash, int revhashsz);
#endif
+
+/* isc.c */
+#ifdef HAVE_ISC_READER
+void load_dhcp(time_t now);
+#endif
+
/* loop.c */
#ifdef HAVE_LOOP
void loop_send_probes();
int detect_loop(char *query, int type);
#endif
-
diff --git a/src/isc.c b/src/isc.c
new file mode 100644
index 0000000..5106442
index 000000000000..51064426f17f
--- /dev/null
+++ b/src/isc.c
@@ -0,0 +1,251 @@
@@ -357,10 +351,10 @@ index 0000000..5106442
+
+#endif
diff --git a/src/option.c b/src/option.c
index 45d8875..29c9ee5 100644
index cb4e76ba0aa2..f6420fcbb7ab 100644
--- a/src/option.c
+++ b/src/option.c
@@ -1669,7 +1669,7 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
@@ -1693,7 +1693,7 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
ret_err(_("bad MX target"));
break;

View File

@@ -1,25 +0,0 @@
From 0b1008d367d44e77352134a4c5178f896f0db3e7 Mon Sep 17 00:00:00 2001
From: Simon Kelley <simon@thekelleys.org.uk>
Date: Sat, 27 Dec 2014 15:33:32 +0000
Subject: [PATCH] Bad packet protection.
---
src/dnssec.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/dnssec.c b/src/dnssec.c
index ed8cf89..026794b 100644
--- a/src/dnssec.c
+++ b/src/dnssec.c
@@ -805,7 +805,7 @@ static int validate_rrset(time_t now, struct dns_header *header, size_t plen, in
{
while (*name_start != '.' && *name_start != 0)
name_start++;
- if (k != 1)
+ if (k != 1 && *name_start == '.')
name_start++;
}
--
1.7.10.4

View File

@@ -1,85 +0,0 @@
From 094b5c3d904bae9aeb3206d9f3b8348926b84975 Mon Sep 17 00:00:00 2001
From: Simon Kelley <simon@thekelleys.org.uk>
Date: Sun, 21 Dec 2014 16:11:52 +0000
Subject: [PATCH] Fix crash in DNSSEC code when attempting to verify large
RRs.
---
src/dnssec.c | 27 +++++++++++++++++++--------
1 files changed, 22 insertions(+), 8 deletions(-)
diff --git a/src/dnssec.c b/src/dnssec.c
index 69bfc29..3208ac7 100644
--- a/src/dnssec.c
+++ b/src/dnssec.c
@@ -456,16 +456,27 @@ static u16 *get_desc(int type)
/* Return bytes of canonicalised rdata, when the return value is zero, the remaining
data, pointed to by *p, should be used raw. */
-static int get_rdata(struct dns_header *header, size_t plen, unsigned char *end, char *buff,
+static int get_rdata(struct dns_header *header, size_t plen, unsigned char *end, char *buff, int bufflen,
unsigned char **p, u16 **desc)
{
int d = **desc;
- (*desc)++;
-
/* No more data needs mangling */
if (d == (u16)-1)
- return 0;
+ {
+ /* If there's more data than we have space for, just return what fits,
+ we'll get called again for more chunks */
+ if (end - *p > bufflen)
+ {
+ memcpy(buff, *p, bufflen);
+ *p += bufflen;
+ return bufflen;
+ }
+
+ return 0;
+ }
+
+ (*desc)++;
if (d == 0 && extract_name(header, plen, p, buff, 1, 0))
/* domain-name, canonicalise */
@@ -560,7 +571,7 @@ static void sort_rrset(struct dns_header *header, size_t plen, u16 *rr_desc, int
if (left1 != 0)
memmove(buff1, buff1 + len1 - left1, left1);
- if ((len1 = get_rdata(header, plen, end1, buff1 + left1, &p1, &dp1)) == 0)
+ if ((len1 = get_rdata(header, plen, end1, buff1 + left1, MAXDNAME - left1, &p1, &dp1)) == 0)
{
quit = 1;
len1 = end1 - p1;
@@ -571,7 +582,7 @@ static void sort_rrset(struct dns_header *header, size_t plen, u16 *rr_desc, int
if (left2 != 0)
memmove(buff2, buff2 + len2 - left2, left2);
- if ((len2 = get_rdata(header, plen, end2, buff2 + left2, &p2, &dp2)) == 0)
+ if ((len2 = get_rdata(header, plen, end2, buff2 + left2, MAXDNAME - left2, &p2, &dp2)) == 0)
{
quit = 1;
len2 = end2 - p2;
@@ -808,7 +819,7 @@ static int validate_rrset(time_t now, struct dns_header *header, size_t plen, in
/* canonicalise rdata and calculate length of same, use name buffer as workspace */
cp = p;
dp = rr_desc;
- for (len = 0; (seg = get_rdata(header, plen, end, name, &cp, &dp)) != 0; len += seg);
+ for (len = 0; (seg = get_rdata(header, plen, end, name, MAXDNAME, &cp, &dp)) != 0; len += seg);
len += end - cp;
len = htons(len);
hash->update(ctx, 2, (unsigned char *)&len);
@@ -816,7 +827,7 @@ static int validate_rrset(time_t now, struct dns_header *header, size_t plen, in
/* Now canonicalise again and digest. */
cp = p;
dp = rr_desc;
- while ((seg = get_rdata(header, plen, end, name, &cp, &dp)))
+ while ((seg = get_rdata(header, plen, end, name, MAXDNAME, &cp, &dp)))
hash->update(ctx, seg, (unsigned char *)name);
if (cp != end)
hash->update(ctx, end - cp, cp);
--
1.7.10.4

View File

@@ -1,365 +0,0 @@
From fbc5205702c7f6f431d9f1043c553d7fb62ddfdb Mon Sep 17 00:00:00 2001
From: Simon Kelley <simon@thekelleys.org.uk>
Date: Tue, 23 Dec 2014 15:46:08 +0000
Subject: [PATCH] Fix problems validating NSEC3 and wildcards.
---
src/dnssec.c | 253 +++++++++++++++++++++++++++++-----------------------------
1 file changed, 128 insertions(+), 125 deletions(-)
diff --git a/src/dnssec.c b/src/dnssec.c
index 3208ac7..9350d3e 100644
--- a/src/dnssec.c
+++ b/src/dnssec.c
@@ -615,6 +615,7 @@ static void sort_rrset(struct dns_header *header, size_t plen, u16 *rr_desc, int
Return code:
STAT_SECURE if it validates.
STAT_SECURE_WILDCARD if it validates and is the result of wildcard expansion.
+ (In this case *wildcard_out points to the "body" of the wildcard within name.)
STAT_NO_SIG no RRsigs found.
STAT_INSECURE RRset empty.
STAT_BOGUS signature is wrong, bad packet.
@@ -625,8 +626,8 @@ static void sort_rrset(struct dns_header *header, size_t plen, u16 *rr_desc, int
name is unchanged on exit. keyname is used as workspace and trashed.
*/
-static int validate_rrset(time_t now, struct dns_header *header, size_t plen, int class,
- int type, char *name, char *keyname, struct blockdata *key, int keylen, int algo_in, int keytag_in)
+static int validate_rrset(time_t now, struct dns_header *header, size_t plen, int class, int type,
+ char *name, char *keyname, char **wildcard_out, struct blockdata *key, int keylen, int algo_in, int keytag_in)
{
static unsigned char **rrset = NULL, **sigs = NULL;
static int rrset_sz = 0, sig_sz = 0;
@@ -798,8 +799,16 @@ static int validate_rrset(time_t now, struct dns_header *header, size_t plen, in
{
int k;
for (k = name_labels - labels; k != 0; k--)
- while (*name_start != '.' && *name_start != 0)
- name_start++;
+ {
+ while (*name_start != '.' && *name_start != 0)
+ name_start++;
+ if (k != 1)
+ name_start++;
+ }
+
+ if (wildcard_out)
+ *wildcard_out = name_start+1;
+
name_start--;
*name_start = '*';
}
@@ -974,7 +983,7 @@ int dnssec_validate_by_ds(time_t now, struct dns_header *header, size_t plen, ch
if (recp1->addr.ds.keylen == (int)hash->digest_size &&
(ds_digest = blockdata_retrieve(recp1->addr.key.keydata, recp1->addr.ds.keylen, NULL)) &&
memcmp(ds_digest, digest, recp1->addr.ds.keylen) == 0 &&
- validate_rrset(now, header, plen, class, T_DNSKEY, name, keyname, key, rdlen - 4, algo, keytag) == STAT_SECURE)
+ validate_rrset(now, header, plen, class, T_DNSKEY, name, keyname, NULL, key, rdlen - 4, algo, keytag) == STAT_SECURE)
{
valid = 1;
break;
@@ -1443,11 +1452,88 @@ static int base32_decode(char *in, unsigned char *out)
return p - out;
}
+static int check_nsec3_coverage(struct dns_header *header, size_t plen, int digest_len, unsigned char *digest, int type,
+ char *workspace1, char *workspace2, unsigned char **nsecs, int nsec_count)
+{
+ int i, hash_len, salt_len, base32_len, rdlen;
+ unsigned char *p, *psave;
+
+ for (i = 0; i < nsec_count; i++)
+ if ((p = nsecs[i]))
+ {
+ if (!extract_name(header, plen, &p, workspace1, 1, 0) ||
+ !(base32_len = base32_decode(workspace1, (unsigned char *)workspace2)))
+ return 0;
+
+ p += 8; /* class, type, TTL */
+ GETSHORT(rdlen, p);
+ psave = p;
+ p += 4; /* algo, flags, iterations */
+ salt_len = *p++; /* salt_len */
+ p += salt_len; /* salt */
+ hash_len = *p++; /* p now points to next hashed name */
+
+ if (!CHECK_LEN(header, p, plen, hash_len))
+ return 0;
+
+ if (digest_len == base32_len && hash_len == base32_len)
+ {
+ int rc = memcmp(workspace2, digest, digest_len);
+
+ if (rc == 0)
+ {
+ /* We found an NSEC3 whose hashed name exactly matches the query, so
+ we just need to check the type map. p points to the RR data for the record. */
+
+ int offset = (type & 0xff) >> 3;
+ int mask = 0x80 >> (type & 0x07);
+
+ p += hash_len; /* skip next-domain hash */
+ rdlen -= p - psave;
+
+ if (!CHECK_LEN(header, p, plen, rdlen))
+ return 0;
+
+ while (rdlen >= 2)
+ {
+ if (p[0] == type >> 8)
+ {
+ /* Does the NSEC3 say our type exists? */
+ if (offset < p[1] && (p[offset+2] & mask) != 0)
+ return STAT_BOGUS;
+
+ break; /* finshed checking */
+ }
+
+ rdlen -= p[1];
+ p += p[1];
+ }
+
+ return 1;
+ }
+ else if (rc <= 0)
+ {
+ /* Normal case, hash falls between NSEC3 name-hash and next domain name-hash,
+ wrap around case, name-hash falls between NSEC3 name-hash and end */
+ if (memcmp(p, digest, digest_len) > 0 || memcmp(workspace2, p, digest_len) > 0)
+ return 1;
+ }
+ else
+ {
+ /* wrap around case, name falls between start and next domain name */
+ if (memcmp(workspace2, p, digest_len) > 0 && memcmp(p, digest, digest_len) > 0)
+ return 1;
+ }
+ }
+ }
+ return 0;
+}
+
static int prove_non_existence_nsec3(struct dns_header *header, size_t plen, unsigned char **nsecs, int nsec_count,
- char *workspace1, char *workspace2, char *name, int type)
+ char *workspace1, char *workspace2, char *name, int type, char *wildname)
{
unsigned char *salt, *p, *digest;
- int digest_len, i, iterations, salt_len, hash_len, base32_len, algo = 0;
+ int digest_len, i, iterations, salt_len, base32_len, algo = 0;
struct nettle_hash const *hash;
char *closest_encloser, *next_closest, *wildcard;
@@ -1520,7 +1606,14 @@ static int prove_non_existence_nsec3(struct dns_header *header, size_t plen, uns
if (!(hash = hash_find("sha1")))
return STAT_BOGUS;
- /* Now, we need the "closest encloser NSEC3" */
+ if ((digest_len = hash_name(name, &digest, hash, salt, salt_len, iterations)) == 0)
+ return STAT_BOGUS;
+
+ if (check_nsec3_coverage(header, plen, digest_len, digest, type, workspace1, workspace2, nsecs, nsec_count))
+ return STAT_SECURE;
+
+ /* Can't find an NSEC3 which covers the name directly, we need the "closest encloser NSEC3"
+ or an answer inferred from a wildcard record. */
closest_encloser = name;
next_closest = NULL;
@@ -1529,6 +1622,9 @@ static int prove_non_existence_nsec3(struct dns_header *header, size_t plen, uns
if (*closest_encloser == '.')
closest_encloser++;
+ if (wildname && hostname_isequal(closest_encloser, wildname))
+ break;
+
if ((digest_len = hash_name(closest_encloser, &digest, hash, salt, salt_len, iterations)) == 0)
return STAT_BOGUS;
@@ -1551,127 +1647,33 @@ static int prove_non_existence_nsec3(struct dns_header *header, size_t plen, uns
}
while ((closest_encloser = strchr(closest_encloser, '.')));
- /* No usable NSEC3s */
- if (i == nsec_count)
+ if (!closest_encloser)
return STAT_BOGUS;
- if (!next_closest)
- {
- /* We found an NSEC3 whose hashed name exactly matches the query, so
- Now we just need to check the type map. p points to the RR data for the record. */
- int rdlen;
- unsigned char *psave;
- int offset = (type & 0xff) >> 3;
- int mask = 0x80 >> (type & 0x07);
-
- p += 8; /* class, type, TTL */
- GETSHORT(rdlen, p);
- psave = p;
- p += 5 + salt_len; /* algo, flags, iterations, salt_len, salt */
- hash_len = *p++;
- if (!CHECK_LEN(header, p, plen, hash_len))
- return STAT_BOGUS; /* bad packet */
- p += hash_len;
- rdlen -= p - psave;
-
- while (rdlen >= 2)
- {
- if (!CHECK_LEN(header, p, plen, rdlen))
- return STAT_BOGUS;
-
- if (p[0] == type >> 8)
- {
- /* Does the NSEC3 say our type exists? */
- if (offset < p[1] && (p[offset+2] & mask) != 0)
- return STAT_BOGUS;
-
- break; /* finshed checking */
- }
-
- rdlen -= p[1];
- p += p[1];
- }
-
- return STAT_SECURE;
- }
-
/* Look for NSEC3 that proves the non-existence of the next-closest encloser */
if ((digest_len = hash_name(next_closest, &digest, hash, salt, salt_len, iterations)) == 0)
return STAT_BOGUS;
- for (i = 0; i < nsec_count; i++)
- if ((p = nsecs[i]))
- {
- if (!extract_name(header, plen, &p, workspace1, 1, 0) ||
- !(base32_len = base32_decode(workspace1, (unsigned char *)workspace2)))
- return STAT_BOGUS;
-
- p += 15 + salt_len; /* class, type, TTL, rdlen, algo, flags, iterations, salt_len, salt */
- hash_len = *p++; /* p now points to next hashed name */
-
- if (!CHECK_LEN(header, p, plen, hash_len))
- return STAT_BOGUS;
-
- if (digest_len == base32_len && hash_len == base32_len)
- {
- if (memcmp(workspace2, digest, digest_len) <= 0)
- {
- /* Normal case, hash falls between NSEC3 name-hash and next domain name-hash,
- wrap around case, name-hash falls between NSEC3 name-hash and end */
- if (memcmp(p, digest, digest_len) > 0 || memcmp(workspace2, p, digest_len) > 0)
- return STAT_SECURE;
- }
- else
- {
- /* wrap around case, name falls between start and next domain name */
- if (memcmp(workspace2, p, digest_len) > 0 && memcmp(p, digest, digest_len) > 0)
- return STAT_SECURE;
- }
- }
- }
-
- /* Finally, check that there's no seat of wildcard synthesis */
- if (!(wildcard = strchr(next_closest, '.')) || wildcard == next_closest)
- return STAT_BOGUS;
-
- wildcard--;
- *wildcard = '*';
-
- if ((digest_len = hash_name(wildcard, &digest, hash, salt, salt_len, iterations)) == 0)
+ if (!check_nsec3_coverage(header, plen, digest_len, digest, type, workspace1, workspace2, nsecs, nsec_count))
return STAT_BOGUS;
- for (i = 0; i < nsec_count; i++)
- if ((p = nsecs[i]))
- {
- if (!extract_name(header, plen, &p, workspace1, 1, 0) ||
- !(base32_len = base32_decode(workspace1, (unsigned char *)workspace2)))
- return STAT_BOGUS;
-
- p += 15 + salt_len; /* class, type, TTL, rdlen, algo, flags, iterations, salt_len, salt */
- hash_len = *p++; /* p now points to next hashed name */
-
- if (!CHECK_LEN(header, p, plen, hash_len))
- return STAT_BOGUS;
-
- if (digest_len == base32_len && hash_len == base32_len)
- {
- if (memcmp(workspace2, digest, digest_len) <= 0)
- {
- /* Normal case, hash falls between NSEC3 name-hash and next domain name-hash,
- wrap around case, name-hash falls between NSEC3 name-hash and end */
- if (memcmp(p, digest, digest_len) > 0 || memcmp(workspace2, p, digest_len) > 0)
- return STAT_SECURE;
- }
- else
- {
- /* wrap around case, name falls between start and next domain name */
- if (memcmp(workspace2, p, digest_len) > 0 && memcmp(p, digest, digest_len) > 0)
- return STAT_SECURE;
- }
- }
- }
+ /* Finally, check that there's no seat of wildcard synthesis */
+ if (!wildname)
+ {
+ if (!(wildcard = strchr(next_closest, '.')) || wildcard == next_closest)
+ return STAT_BOGUS;
+
+ wildcard--;
+ *wildcard = '*';
+
+ if ((digest_len = hash_name(wildcard, &digest, hash, salt, salt_len, iterations)) == 0)
+ return STAT_BOGUS;
+
+ if (!check_nsec3_coverage(header, plen, digest_len, digest, type, workspace1, workspace2, nsecs, nsec_count))
+ return STAT_BOGUS;
+ }
- return STAT_BOGUS;
+ return STAT_SECURE;
}
/* Validate all the RRsets in the answer and authority sections of the reply (4035:3.2.3) */
@@ -1792,8 +1794,9 @@ int dnssec_validate_reply(time_t now, struct dns_header *header, size_t plen, ch
struct all_addr a;
struct blockdata *key;
struct crec *crecp;
-
- rc = validate_rrset(now, header, plen, class1, type1, name, keyname, NULL, 0, 0, 0);
+ char *wildname;
+
+ rc = validate_rrset(now, header, plen, class1, type1, name, keyname, &wildname, NULL, 0, 0, 0);
if (rc == STAT_SECURE_WILDCARD)
{
@@ -1807,7 +1810,7 @@ int dnssec_validate_reply(time_t now, struct dns_header *header, size_t plen, ch
if (nsec_type == T_NSEC)
rc = prove_non_existence_nsec(header, plen, nsecs, nsec_count, daemon->workspacename, keyname, name, type1);
else
- rc = prove_non_existence_nsec3(header, plen, nsecs, nsec_count, daemon->workspacename, keyname, name, type1);
+ rc = prove_non_existence_nsec3(header, plen, nsecs, nsec_count, daemon->workspacename, keyname, name, type1, wildname);
if (rc != STAT_SECURE)
return rc;
@@ -1933,7 +1936,7 @@ int dnssec_validate_reply(time_t now, struct dns_header *header, size_t plen, ch
if (nsec_type == T_NSEC)
return prove_non_existence_nsec(header, plen, nsecs, nsec_count, daemon->workspacename, keyname, name, qtype);
else
- return prove_non_existence_nsec3(header, plen, nsecs, nsec_count, daemon->workspacename, keyname, name, qtype);
+ return prove_non_existence_nsec3(header, plen, nsecs, nsec_count, daemon->workspacename, keyname, name, qtype, NULL);
}
/* Chase the CNAME chain in the packet until the first record which _doesn't validate.
@@ -1980,7 +1983,7 @@ int dnssec_chase_cname(time_t now, struct dns_header *header, size_t plen, char
return STAT_INSECURE;
/* validate CNAME chain, return if insecure or need more data */
- rc = validate_rrset(now, header, plen, class, type, name, keyname, NULL, 0, 0, 0);
+ rc = validate_rrset(now, header, plen, class, type, name, keyname, NULL, NULL, 0, 0, 0);
if (rc != STAT_SECURE)
{
if (rc == STAT_NO_SIG)
--
1.7.10.4

View File

@@ -1,32 +0,0 @@
From 83d2ed09fc0216b567d7fb2197e4ff3eae150b0d Mon Sep 17 00:00:00 2001
From: Simon Kelley <simon@thekelleys.org.uk>
Date: Tue, 23 Dec 2014 18:42:38 +0000
Subject: [PATCH] Initialise return value.
---
src/dnssec.c | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/src/dnssec.c b/src/dnssec.c
index 9350d3e..ed8cf89 100644
--- a/src/dnssec.c
+++ b/src/dnssec.c
@@ -637,10 +637,13 @@ static int validate_rrset(time_t now, struct dns_header *header, size_t plen, in
struct crec *crecp = NULL;
int type_covered, algo, labels, orig_ttl, sig_expiration, sig_inception, key_tag;
u16 *rr_desc = get_desc(type);
-
+
+ if (wildcard_out)
+ *wildcard_out = NULL;
+
if (!(p = skip_questions(header, plen)))
return STAT_BOGUS;
-
+
name_labels = count_labels(name); /* For 4035 5.3.2 check */
/* look for RRSIGs for this RRset and get pointers to each RR in the set. */
--
1.7.10.4

View File

@@ -1,99 +0,0 @@
From cbc652423403e3cef00e00240f6beef713142246 Mon Sep 17 00:00:00 2001
From: Simon Kelley <simon@thekelleys.org.uk>
Date: Sun, 21 Dec 2014 21:21:53 +0000
Subject: [PATCH] Make caching work for CNAMEs pointing to A/AAAA records
shadowed in /etc/hosts
If the answer to an upstream query is a CNAME which points to an
A/AAAA record which also exists in /etc/hosts and friends, then
caching is suppressed, to avoid inconsistent answers. This is
now modified to allow caching when the upstream and local A/AAAA
records have the same value.
---
src/cache.c | 34 +++++++++++++++++++++++++---------
1 file changed, 25 insertions(+), 9 deletions(-)
diff --git a/src/cache.c b/src/cache.c
index f9e1d31..ff1ca6f 100644
--- a/src/cache.c
+++ b/src/cache.c
@@ -322,7 +322,7 @@ static int is_expired(time_t now, struct crec *crecp)
return 1;
}
-static int cache_scan_free(char *name, struct all_addr *addr, time_t now, unsigned short flags)
+static struct crec *cache_scan_free(char *name, struct all_addr *addr, time_t now, unsigned short flags)
{
/* Scan and remove old entries.
If (flags & F_FORWARD) then remove any forward entries for name and any expired
@@ -331,8 +331,8 @@ static int cache_scan_free(char *name, struct all_addr *addr, time_t now, unsign
entries in the whole cache.
If (flags == 0) remove any expired entries in the whole cache.
- In the flags & F_FORWARD case, the return code is valid, and returns zero if the
- name exists in the cache as a HOSTS or DHCP entry (these are never deleted)
+ In the flags & F_FORWARD case, the return code is valid, and returns a non-NULL pointer
+ to a cache entry if the name exists in the cache as a HOSTS or DHCP entry (these are never deleted)
We take advantage of the fact that hash chains have stuff in the order <reverse>,<other>,<immortal>
so that when we hit an entry which isn't reverse and is immortal, we're done. */
@@ -361,7 +361,7 @@ static int cache_scan_free(char *name, struct all_addr *addr, time_t now, unsign
(((crecp->flags | flags) & F_CNAME) && !(crecp->flags & (F_DNSKEY | F_DS))))
{
if (crecp->flags & (F_HOSTS | F_DHCP | F_CONFIG))
- return 0;
+ return crecp;
*up = crecp->hash_next;
cache_unlink(crecp);
cache_free(crecp);
@@ -378,7 +378,7 @@ static int cache_scan_free(char *name, struct all_addr *addr, time_t now, unsign
crecp->addr.sig.type_covered == addr->addr.dnssec.type))
{
if (crecp->flags & F_CONFIG)
- return 0;
+ return crecp;
*up = crecp->hash_next;
cache_unlink(crecp);
cache_free(crecp);
@@ -423,7 +423,7 @@ static int cache_scan_free(char *name, struct all_addr *addr, time_t now, unsign
up = &crecp->hash_next;
}
- return 1;
+ return NULL;
}
/* Note: The normal calling sequence is
@@ -471,10 +471,26 @@ struct crec *cache_insert(char *name, struct all_addr *addr,
return NULL;
/* First remove any expired entries and entries for the name/address we
- are currently inserting. Fail if we attempt to delete a name from
- /etc/hosts or DHCP. */
- if (!cache_scan_free(name, addr, now, flags))
+ are currently inserting. */
+ if ((new = cache_scan_free(name, addr, now, flags)))
{
+ /* We're trying to insert a record over one from
+ /etc/hosts or DHCP, or other config. If the
+ existing record is for an A or AAAA and
+ the record we're trying to insert is the same,
+ just drop the insert, but don't error the whole process. */
+ if ((flags & (F_IPV4 | F_IPV6)) && (flags & F_FORWARD))
+ {
+ if ((flags & F_IPV4) && (new->flags & F_IPV4) &&
+ new->addr.addr.addr.addr4.s_addr == addr->addr.addr4.s_addr)
+ return new;
+#ifdef HAVE_IPV6
+ else if ((flags & F_IPV6) && (new->flags & F_IPV6) &&
+ IN6_ARE_ADDR_EQUAL(&new->addr.addr.addr.addr6, &addr->addr.addr6))
+ return new;
+#endif
+ }
+
insert_error = 1;
return NULL;
}
--
1.7.10.4

View File

@@ -1,28 +0,0 @@
From 800c5cc1e7438818fd80f08c2d472df249a6942d Mon Sep 17 00:00:00 2001
From: Simon Kelley <simon@thekelleys.org.uk>
Date: Mon, 15 Dec 2014 17:50:15 +0000
Subject: [PATCH] Remove floor on EDNS0 packet size with DNSSEC.
---
src/dnsmasq.c | 5 -----
1 files changed, 5 deletions(-)
diff --git a/src/dnsmasq.c b/src/dnsmasq.c
index bf2e25a..5c7750d 100644
--- a/src/dnsmasq.c
+++ b/src/dnsmasq.c
@@ -87,11 +87,6 @@ int main (int argc, char **argv)
if (daemon->edns_pktsz < PACKETSZ)
daemon->edns_pktsz = PACKETSZ;
-#ifdef HAVE_DNSSEC
- /* Enforce min packet big enough for DNSSEC */
- if (option_bool(OPT_DNSSEC_VALID) && daemon->edns_pktsz < EDNS_PKTSZ)
- daemon->edns_pktsz = EDNS_PKTSZ;
-#endif
daemon->packet_buff_sz = daemon->edns_pktsz > DNSMASQ_PACKETSZ ?
daemon->edns_pktsz : DNSMASQ_PACKETSZ;
--
1.7.10.4