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 d6ef5df18edfd8af46abbd09107cef9d42810cb4 (commit)
via b56472d49b2e50d6c8f84023b80c3ee43114bfe1 (commit)
via 1117fb59647efa47d5a7ab68962bf11f7c501dca (commit)
from db9d194a6cc4efa8251415895e823e4db254c7a4 (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 d6ef5df18edfd8af46abbd09107cef9d42810cb4
Author: Michael Tremer <michael.tremer(a)ipfire.org>
Date: Fri Jan 2 12:20:50 2015 +0100
firewall: Fix off-by-one error in configuration parser
The configuration parser determines how many comma-separated
values there are in a line. If new values are added we need
to check first if those are set in every line to avoid any
undefined behaviour. A wrong comparison parameter was used
which caused that the limit feature was never enabled in
the rule generation.
commit b56472d49b2e50d6c8f84023b80c3ee43114bfe1
Author: Michael Tremer <michael.tremer(a)ipfire.org>
Date: Fri Jan 2 11:49:07 2015 +0100
dnsmasq: Import some patches from upstream
These may fix the stability issues described in #10607
commit 1117fb59647efa47d5a7ab68962bf11f7c501dca
Author: Michael Tremer <michael.tremer(a)ipfire.org>
Date: Fri Jan 2 11:11:22 2015 +0100
Build fixes
-----------------------------------------------------------------------
Summary of changes:
config/firewall/rules.pl | 12 +-
.../{oldcore/84 => core/87}/filelists/dnsmasq | 0
lfs/dnsmasq | 6 +
lfs/libcap | 2 +-
lfs/libpcap | 3 +-
.../dnsmasq-2.73-bad-packet-protection.patch | 25 ++
...-code-when-attempting-to-verify-large-RRs.patch | 85 +++++
...x-problems-validating-NSEC3-and-wildcards.patch | 365 +++++++++++++++++++++
.../dnsmasq-2.73-initialise-return-value.patch | 32 ++
...g-to-A-AAAA-records-shadowed-in-etc-hosts.patch | 99 ++++++
...ve-floor-on-edns0-packet-size-with-DNSSEC.patch | 28 ++
11 files changed, 649 insertions(+), 8 deletions(-)
copy config/rootfiles/{oldcore/84 => core/87}/filelists/dnsmasq (100%)
create mode 100644 src/patches/dnsmasq/dnsmasq-2.73-bad-packet-protection.patch
create mode 100644 src/patches/dnsmasq/dnsmasq-2.73-fix-crash-in-DNSSEC-code-when-attempting-to-verify-large-RRs.patch
create mode 100644 src/patches/dnsmasq/dnsmasq-2.73-fix-problems-validating-NSEC3-and-wildcards.patch
create mode 100644 src/patches/dnsmasq/dnsmasq-2.73-initialise-return-value.patch
create mode 100644 src/patches/dnsmasq/dnsmasq-2.73-make-caching-work-for-CNAMEs-pointing-to-A-AAAA-records-shadowed-in-etc-hosts.patch
create mode 100644 src/patches/dnsmasq/dnsmasq-2.73-remove-floor-on-edns0-packet-size-with-DNSSEC.patch
Difference in files:
diff --git a/config/firewall/rules.pl b/config/firewall/rules.pl
index 75a9357..a475e2d 100755
--- a/config/firewall/rules.pl
+++ b/config/firewall/rules.pl
@@ -280,7 +280,7 @@ sub buildrules {
# Concurrent connection limit
my @ratelimit_options = ();
- if (($elements gt 34) && ($$hash{$key}[32] eq 'ON')) {
+ if (($elements ge 34) && ($$hash{$key}[32] eq 'ON')) {
my $conn_limit = $$hash{$key}[33];
if ($conn_limit ge 1) {
@@ -296,13 +296,13 @@ sub buildrules {
}
# Ratelimit
- if (($elements gt 37) && ($$hash{$key}[34] eq 'ON')) {
+ if (($elements ge 37) && ($$hash{$key}[34] eq 'ON')) {
my $rate_limit = "$$hash{$key}[35]/$$hash{$key}[36]";
- if ($rate_limit) {
- push(@ratelimit_options, ("-m", "limit"));
- push(@ratelimit_options, ("--limit", $rate_limit));
- }
+ if ($rate_limit) {
+ push(@ratelimit_options, ("-m", "limit"));
+ push(@ratelimit_options, ("--limit", $rate_limit));
+ }
}
# Check which protocols are used in this rule and so that we can
diff --git a/config/rootfiles/core/87/filelists/dnsmasq b/config/rootfiles/core/87/filelists/dnsmasq
new file mode 120000
index 0000000..d469c74
--- /dev/null
+++ b/config/rootfiles/core/87/filelists/dnsmasq
@@ -0,0 +1 @@
+../../../common/dnsmasq
\ No newline at end of file
diff --git a/lfs/dnsmasq b/lfs/dnsmasq
index 60dabf4..8493657 100644
--- a/lfs/dnsmasq
+++ b/lfs/dnsmasq
@@ -72,6 +72,12 @@ $(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) && sed -i src/config.h \
-e 's|/\* #define HAVE_IDN \*/|#define HAVE_IDN|g' \
diff --git a/lfs/libcap b/lfs/libcap
index ca38c75..66ab555 100644
--- a/lfs/libcap
+++ b/lfs/libcap
@@ -73,7 +73,7 @@ $(TARGET) : $(patsubst %,$(DIR_DL)/%,$(objects))
cd $(DIR_APP) && make
cd $(DIR_APP) && make install
# link for old binaries
- ln -s libcap.so.2 /lib/libcap.so.1
+ ln -svf libcap.so.2 /lib/libcap.so.1
chmod +x /lib/libcap.so.*
@rm -rf $(DIR_APP)
@$(POSTBUILD)
diff --git a/lfs/libpcap b/lfs/libpcap
index 07e65cd..fa2aae8 100644
--- a/lfs/libpcap
+++ b/lfs/libpcap
@@ -74,7 +74,8 @@ $(TARGET) : $(patsubst %,$(DIR_DL)/%,$(objects))
@rm -rf $(DIR_APP) && cd $(DIR_SRC) && tar zxf $(DIR_DL)/$(DL_FILE)
cd $(DIR_APP) && ./configure \
--prefix=/usr \
- --enable-bluetooth=no
+ --enable-bluetooth=no \
+ --disable-dbus
cd $(DIR_APP) && make $(MAKETUNING)
cd $(DIR_APP) && make install
diff --git a/src/patches/dnsmasq/dnsmasq-2.73-bad-packet-protection.patch b/src/patches/dnsmasq/dnsmasq-2.73-bad-packet-protection.patch
new file mode 100644
index 0000000..bdbe168
--- /dev/null
+++ b/src/patches/dnsmasq/dnsmasq-2.73-bad-packet-protection.patch
@@ -0,0 +1,25 @@
+From 0b1008d367d44e77352134a4c5178f896f0db3e7 Mon Sep 17 00:00:00 2001
+From: Simon Kelley <simon(a)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
+
diff --git a/src/patches/dnsmasq/dnsmasq-2.73-fix-crash-in-DNSSEC-code-when-attempting-to-verify-large-RRs.patch b/src/patches/dnsmasq/dnsmasq-2.73-fix-crash-in-DNSSEC-code-when-attempting-to-verify-large-RRs.patch
new file mode 100644
index 0000000..82c68ed
--- /dev/null
+++ b/src/patches/dnsmasq/dnsmasq-2.73-fix-crash-in-DNSSEC-code-when-attempting-to-verify-large-RRs.patch
@@ -0,0 +1,85 @@
+From 094b5c3d904bae9aeb3206d9f3b8348926b84975 Mon Sep 17 00:00:00 2001
+From: Simon Kelley <simon(a)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
+
diff --git a/src/patches/dnsmasq/dnsmasq-2.73-fix-problems-validating-NSEC3-and-wildcards.patch b/src/patches/dnsmasq/dnsmasq-2.73-fix-problems-validating-NSEC3-and-wildcards.patch
new file mode 100644
index 0000000..25bbbb7
--- /dev/null
+++ b/src/patches/dnsmasq/dnsmasq-2.73-fix-problems-validating-NSEC3-and-wildcards.patch
@@ -0,0 +1,365 @@
+From fbc5205702c7f6f431d9f1043c553d7fb62ddfdb Mon Sep 17 00:00:00 2001
+From: Simon Kelley <simon(a)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
+
diff --git a/src/patches/dnsmasq/dnsmasq-2.73-initialise-return-value.patch b/src/patches/dnsmasq/dnsmasq-2.73-initialise-return-value.patch
new file mode 100644
index 0000000..e961734
--- /dev/null
+++ b/src/patches/dnsmasq/dnsmasq-2.73-initialise-return-value.patch
@@ -0,0 +1,32 @@
+From 83d2ed09fc0216b567d7fb2197e4ff3eae150b0d Mon Sep 17 00:00:00 2001
+From: Simon Kelley <simon(a)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
+
diff --git a/src/patches/dnsmasq/dnsmasq-2.73-make-caching-work-for-CNAMEs-pointing-to-A-AAAA-records-shadowed-in-etc-hosts.patch b/src/patches/dnsmasq/dnsmasq-2.73-make-caching-work-for-CNAMEs-pointing-to-A-AAAA-records-shadowed-in-etc-hosts.patch
new file mode 100644
index 0000000..e2b6f37
--- /dev/null
+++ b/src/patches/dnsmasq/dnsmasq-2.73-make-caching-work-for-CNAMEs-pointing-to-A-AAAA-records-shadowed-in-etc-hosts.patch
@@ -0,0 +1,99 @@
+From cbc652423403e3cef00e00240f6beef713142246 Mon Sep 17 00:00:00 2001
+From: Simon Kelley <simon(a)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
+
diff --git a/src/patches/dnsmasq/dnsmasq-2.73-remove-floor-on-edns0-packet-size-with-DNSSEC.patch b/src/patches/dnsmasq/dnsmasq-2.73-remove-floor-on-edns0-packet-size-with-DNSSEC.patch
new file mode 100644
index 0000000..64a8507
--- /dev/null
+++ b/src/patches/dnsmasq/dnsmasq-2.73-remove-floor-on-edns0-packet-size-with-DNSSEC.patch
@@ -0,0 +1,28 @@
+From 800c5cc1e7438818fd80f08c2d472df249a6942d Mon Sep 17 00:00:00 2001
+From: Simon Kelley <simon(a)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
+
hooks/post-receive
--
IPFire 2.x development tree