Date: Thursday, October 18, 2018 @ 19:14:06 Author: eworm Revision: 336847
archrelease: copy trunk to testing-x86_64 Added: dnsmasq/repos/testing-x86_64/ dnsmasq/repos/testing-x86_64/0001-DNSSEC-fix-for-wildcard-NSEC-records.patch (from rev 336846, dnsmasq/trunk/0001-DNSSEC-fix-for-wildcard-NSEC-records.patch) dnsmasq/repos/testing-x86_64/PKGBUILD (from rev 336846, dnsmasq/trunk/PKGBUILD) dnsmasq/repos/testing-x86_64/dnsmasq-sysusers.conf (from rev 336846, dnsmasq/trunk/dnsmasq-sysusers.conf) dnsmasq/repos/testing-x86_64/dnsmasq.service (from rev 336846, dnsmasq/trunk/dnsmasq.service) -------------------------------------------------+ 0001-DNSSEC-fix-for-wildcard-NSEC-records.patch | 203 ++++++++++++++++++++++ PKGBUILD | 59 ++++++ dnsmasq-sysusers.conf | 1 dnsmasq.service | 14 + 4 files changed, 277 insertions(+) Copied: dnsmasq/repos/testing-x86_64/0001-DNSSEC-fix-for-wildcard-NSEC-records.patch (from rev 336846, dnsmasq/trunk/0001-DNSSEC-fix-for-wildcard-NSEC-records.patch) =================================================================== --- testing-x86_64/0001-DNSSEC-fix-for-wildcard-NSEC-records.patch (rev 0) +++ testing-x86_64/0001-DNSSEC-fix-for-wildcard-NSEC-records.patch 2018-10-18 19:14:06 UTC (rev 336847) @@ -0,0 +1,203 @@ +From 4fe6744a220eddd3f1749b40cac3dfc510787de6 Mon Sep 17 00:00:00 2001 +From: Simon Kelley <si...@thekelleys.org.uk> +Date: Fri, 19 Jan 2018 12:26:08 +0000 +Subject: DNSSEC fix for wildcard NSEC records. CVE-2017-15107 applies. + +It's OK for NSEC records to be expanded from wildcards, +but in that case, the proof of non-existence is only valid +starting at the wildcard name, *.<domain> NOT the name expanded +from the wildcard. Without this check it's possible for an +attacker to craft an NSEC which wrongly proves non-existence +in a domain which includes a wildcard for NSEC. +--- + src/dnssec.c | 117 ++++++++++++++++++++++++++++++++++++++++++++++++++++------- + 2 files changed, 114 insertions(+), 15 deletions(-) + +diff --git a/src/dnssec.c b/src/dnssec.c +index eb6c11c..a54a0b4 100644 +--- a/src/dnssec.c ++++ b/src/dnssec.c +@@ -103,15 +103,17 @@ static void from_wire(char *name) + static int count_labels(char *name) + { + int i; +- ++ char *p; ++ + if (*name == 0) + return 0; + +- for (i = 0; *name; name++) +- if (*name == '.') ++ for (p = name, i = 0; *p; p++) ++ if (*p == '.') + i++; + +- return i+1; ++ /* Don't count empty first label. */ ++ return *name == '.' ? i : i+1; + } + + /* Implement RFC1982 wrapped compare for 32-bit numbers */ +@@ -1094,8 +1096,8 @@ static int hostname_cmp(const char *a, const char *b) + } + } + +-static int prove_non_existence_nsec(struct dns_header *header, size_t plen, unsigned char **nsecs, int nsec_count, +- char *workspace1, char *workspace2, char *name, int type, int *nons) ++static int prove_non_existence_nsec(struct dns_header *header, size_t plen, unsigned char **nsecs, unsigned char **labels, int nsec_count, ++ char *workspace1_in, char *workspace2, char *name, int type, int *nons) + { + int i, rc, rdlen; + unsigned char *p, *psave; +@@ -1108,6 +1110,9 @@ static int prove_non_existence_nsec(struct dns_header *header, size_t plen, unsi + /* Find NSEC record that proves name doesn't exist */ + for (i = 0; i < nsec_count; i++) + { ++ char *workspace1 = workspace1_in; ++ int sig_labels, name_labels; ++ + p = nsecs[i]; + if (!extract_name(header, plen, &p, workspace1, 1, 10)) + return 0; +@@ -1116,7 +1121,27 @@ static int prove_non_existence_nsec(struct dns_header *header, size_t plen, unsi + psave = p; + if (!extract_name(header, plen, &p, workspace2, 1, 10)) + return 0; +- ++ ++ /* If NSEC comes from wildcard expansion, use original wildcard ++ as name for computation. */ ++ sig_labels = *labels[i]; ++ name_labels = count_labels(workspace1); ++ ++ if (sig_labels < name_labels) ++ { ++ int k; ++ for (k = name_labels - sig_labels; k != 0; k--) ++ { ++ while (*workspace1 != '.' && *workspace1 != 0) ++ workspace1++; ++ if (k != 1 && *workspace1 == '.') ++ workspace1++; ++ } ++ ++ workspace1--; ++ *workspace1 = '*'; ++ } ++ + rc = hostname_cmp(workspace1, name); + + if (rc == 0) +@@ -1514,24 +1539,26 @@ static int prove_non_existence_nsec3(struct dns_header *header, size_t plen, uns + + static int prove_non_existence(struct dns_header *header, size_t plen, char *keyname, char *name, int qtype, int qclass, char *wildname, int *nons) + { +- static unsigned char **nsecset = NULL; +- static int nsecset_sz = 0; ++ static unsigned char **nsecset = NULL, **rrsig_labels = NULL; ++ static int nsecset_sz = 0, rrsig_labels_sz = 0; + + int type_found = 0; +- unsigned char *p = skip_questions(header, plen); ++ unsigned char *auth_start, *p = skip_questions(header, plen); + int type, class, rdlen, i, nsecs_found; + + /* Move to NS section */ + if (!p || !(p = skip_section(p, ntohs(header->ancount), header, plen))) + return 0; ++ ++ auth_start = p; + + for (nsecs_found = 0, i = ntohs(header->nscount); i != 0; i--) + { + unsigned char *pstart = p; + +- if (!(p = skip_name(p, header, plen, 10))) ++ if (!extract_name(header, plen, &p, daemon->workspacename, 1, 10)) + return 0; +- ++ + GETSHORT(type, p); + GETSHORT(class, p); + p += 4; /* TTL */ +@@ -1548,7 +1575,69 @@ static int prove_non_existence(struct dns_header *header, size_t plen, char *key + if (!expand_workspace(&nsecset, &nsecset_sz, nsecs_found)) + return 0; + +- nsecset[nsecs_found++] = pstart; ++ if (type == T_NSEC) ++ { ++ /* If we're looking for NSECs, find the corresponding SIGs, to ++ extract the labels value, which we need in case the NSECs ++ are the result of wildcard expansion. ++ Note that the NSEC may not have been validated yet ++ so if there are multiple SIGs, make sure the label value ++ is the same in all, to avoid be duped by a rogue one. ++ If there are no SIGs, that's an error */ ++ unsigned char *p1 = auth_start; ++ int res, j, rdlen1, type1, class1; ++ ++ if (!expand_workspace(&rrsig_labels, &rrsig_labels_sz, nsecs_found)) ++ return 0; ++ ++ rrsig_labels[nsecs_found] = NULL; ++ ++ for (j = ntohs(header->nscount); j != 0; j--) ++ { ++ if (!(res = extract_name(header, plen, &p1, daemon->workspacename, 0, 10))) ++ return 0; ++ ++ GETSHORT(type1, p1); ++ GETSHORT(class1, p1); ++ p1 += 4; /* TTL */ ++ GETSHORT(rdlen1, p1); ++ ++ if (!CHECK_LEN(header, p1, plen, rdlen1)) ++ return 0; ++ ++ if (res == 1 && class1 == qclass && type1 == T_RRSIG) ++ { ++ int type_covered; ++ unsigned char *psav = p1; ++ ++ if (rdlen < 18) ++ return 0; /* bad packet */ ++ ++ GETSHORT(type_covered, p1); ++ ++ if (type_covered == T_NSEC) ++ { ++ p1++; /* algo */ ++ ++ /* labels field must be the same in every SIG we find. */ ++ if (!rrsig_labels[nsecs_found]) ++ rrsig_labels[nsecs_found] = p1; ++ else if (*rrsig_labels[nsecs_found] != *p1) /* algo */ ++ return 0; ++ } ++ p1 = psav; ++ } ++ ++ if (!ADD_RDLEN(header, p1, plen, rdlen1)) ++ return 0; ++ } ++ ++ /* Must have found at least one sig. */ ++ if (!rrsig_labels[nsecs_found]) ++ return 0; ++ } ++ ++ nsecset[nsecs_found++] = pstart; + } + + if (!ADD_RDLEN(header, p, plen, rdlen)) +@@ -1556,7 +1645,7 @@ 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); ++ return prove_non_existence_nsec(header, plen, nsecset, rrsig_labels, nsecs_found, daemon->workspacename, keyname, name, qtype, nons); + else if (type_found == T_NSEC3) + return prove_non_existence_nsec3(header, plen, nsecset, nsecs_found, daemon->workspacename, keyname, name, qtype, wildname, nons); + else Copied: dnsmasq/repos/testing-x86_64/PKGBUILD (from rev 336846, dnsmasq/trunk/PKGBUILD) =================================================================== --- testing-x86_64/PKGBUILD (rev 0) +++ testing-x86_64/PKGBUILD 2018-10-18 19:14:06 UTC (rev 336847) @@ -0,0 +1,59 @@ +# Maintainer: Christian Hesse <m...@eworm.de> +# Maintainer: Dave Reisner <dreis...@archlinux.org> +# Contributor: Paul Mattal <p...@archlinux.org> +# Contributor: Tom Newsom <jeeps...@gmx.co.uk> + +pkgname=dnsmasq +pkgver=2.80 +pkgrel=1 +pkgdesc="Lightweight, easy to configure DNS forwarder and DHCP server" +url="http://www.thekelleys.org.uk/dnsmasq/doc.html" +arch=('x86_64') +license=('GPL') +depends=('glibc' 'gmp' 'libidn2' 'libdbus' 'libnetfilter_conntrack' 'nettle') +backup=('etc/dnsmasq.conf') +validpgpkeys=('D6EACBD6EE46B834248D111215CDDA6AE19135A2') # Simon Kelley <si...@thekelleys.org.uk> +source=("http://www.thekelleys.org.uk/$pkgname/$pkgname-$pkgver.tar.xz"{,.asc} + 'dnsmasq-sysusers.conf' + 'dnsmasq.service') +sha256sums=('cdaba2785e92665cf090646cba6f94812760b9d7d8c8d0cfb07ac819377a63bb' + 'SKIP' + '7f6ff6a709038ae580758f4b6a754451d7f7ce22957b88a36b97f7b643d3c2ab' + '983a3c7a68ce114cf7b44f0d9c59b74c266647a9e5ac34c1d1d5161610bc57fe') + +_build_copts="-DHAVE_DNSSEC -DHAVE_DBUS -DHAVE_LIBIDN2 -DHAVE_CONNTRACK" + +build() { + cd "$pkgname-$pkgver" + + make \ + CFLAGS="$CPPFLAGS $CFLAGS" \ + LDFLAGS="$LDFLAGS" \ + COPTS="$_build_copts" \ + PREFIX=/usr \ + BINDIR=/usr/bin \ + all-i18n +} + +package() { + cd "$pkgname-$pkgver" + + # need to pass COPTS here to avoid rebuilding the binary. + make \ + COPTS="$_build_copts" \ + PREFIX=/usr \ + BINDIR=/usr/bin \ + DESTDIR="$pkgdir" \ + install install-i18n + + install -Dm644 "dbus/dnsmasq.conf" "$pkgdir"/usr/share/dbus-1/system.d/dnsmasq.conf + install -Dm644 "dnsmasq.conf.example" "$pkgdir"/etc/dnsmasq.conf + install -Dm644 "$srcdir/dnsmasq.service" "$pkgdir"/usr/lib/systemd/system/dnsmasq.service + install -Dm644 "$srcdir/dnsmasq-sysusers.conf" "$pkgdir"/usr/lib/sysusers.d/dnsmasq.conf + + # DNSSEC setup + sed -i 's,%%PREFIX%%,/usr,' "$pkgdir"/etc/dnsmasq.conf + install -Dm644 "trust-anchors.conf" "$pkgdir"/usr/share/dnsmasq/trust-anchors.conf +} + +# vim: ts=2 sw=2 et ft=sh Copied: dnsmasq/repos/testing-x86_64/dnsmasq-sysusers.conf (from rev 336846, dnsmasq/trunk/dnsmasq-sysusers.conf) =================================================================== --- testing-x86_64/dnsmasq-sysusers.conf (rev 0) +++ testing-x86_64/dnsmasq-sysusers.conf 2018-10-18 19:14:06 UTC (rev 336847) @@ -0,0 +1 @@ +u dnsmasq - "dnsmasq daemon" / Copied: dnsmasq/repos/testing-x86_64/dnsmasq.service (from rev 336846, dnsmasq/trunk/dnsmasq.service) =================================================================== --- testing-x86_64/dnsmasq.service (rev 0) +++ testing-x86_64/dnsmasq.service 2018-10-18 19:14:06 UTC (rev 336847) @@ -0,0 +1,14 @@ +[Unit] +Description=A lightweight DHCP and caching DNS server +After=network.target +Documentation=man:dnsmasq(8) + +[Service] +Type=dbus +BusName=uk.org.thekelleys.dnsmasq +ExecStartPre=/usr/bin/dnsmasq --test +ExecStart=/usr/bin/dnsmasq -k --enable-dbus --user=dnsmasq --pid-file +ExecReload=/bin/kill -HUP $MAINPID + +[Install] +WantedBy=multi-user.target