diff options
Diffstat (limited to 'meta-openembedded/meta-networking/recipes-support/dnsmasq/files/CVE-2017-15107.patch')
-rw-r--r-- | meta-openembedded/meta-networking/recipes-support/dnsmasq/files/CVE-2017-15107.patch | 263 |
1 files changed, 0 insertions, 263 deletions
diff --git a/meta-openembedded/meta-networking/recipes-support/dnsmasq/files/CVE-2017-15107.patch b/meta-openembedded/meta-networking/recipes-support/dnsmasq/files/CVE-2017-15107.patch deleted file mode 100644 index 701101bcb..000000000 --- a/meta-openembedded/meta-networking/recipes-support/dnsmasq/files/CVE-2017-15107.patch +++ /dev/null @@ -1,263 +0,0 @@ -From 5a56e1b78a753d3295564daddc9ce389cc69fd68 Mon Sep 17 00:00:00 2001 -From: Simon Kelley <simon@thekelleys.org.uk> -Date: Fri, 19 Jan 2018 12:26:08 +0000 -Subject: [PATCH] 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. - -Upstream-Status: Backport [http://thekelleys.org.uk/gitweb/?p=dnsmasq.git;a=commit;h=4fe6744a220eddd3f1749b40cac3dfc510787de6] -CVE: CVE-2017-15107 -Signed-off-by: Sinan Kaya <okaya@kernel.org> ---- - CHANGELOG | 44 +++++++++++++++++++ - src/dnssec.c | 117 +++++++++++++++++++++++++++++++++++++++++++++------ - 2 files changed, 147 insertions(+), 14 deletions(-) - -diff --git a/CHANGELOG b/CHANGELOG -index 075fe1a6..5226dce8 100644 ---- a/CHANGELOG -+++ b/CHANGELOG -@@ -1,3 +1,47 @@ -+version 2.79 -+ Fix parsing of CNAME arguments, which are confused by extra spaces. -+ Thanks to Diego Aguirre for spotting the bug. -+ -+ Where available, use IP_UNICAST_IF or IPV6_UNICAST_IF to bind -+ upstream servers to an interface, rather than SO_BINDTODEVICE. -+ Thanks to Beniamino Galvani for the patch. -+ -+ Always return a SERVFAIL answer to DNS queries without the -+ recursion desired bit set, UNLESS acting as an authoritative -+ DNS server. This avoids a potential route to cache snooping. -+ -+ Add support for Ed25519 signatures in DNSSEC validation. -+ -+ No longer support RSA/MD5 signatures in DNSSEC validation, -+ since these are not secure. This behaviour is mandated in -+ RFC-6944. -+ -+ Fix incorrect error exit code from dhcp_release6 utility. -+ Thanks Gaudenz Steinlin for the bug report. -+ -+ Use SIGINT (instead of overloading SIGHUP) to turn on DNSSEC -+ time validation when --dnssec-no-timecheck is in use. -+ Note that this is an incompatible change from earlier releases. -+ -+ Allow more than one --bridge-interface option to refer to an -+ interface, so that we can use -+ --bridge-interface=int1,alias1 -+ --bridge-interface=int1,alias2 -+ as an alternative to -+ --bridge-interface=int1,alias1,alias2 -+ Thanks to Neil Jerram for work on this. -+ -+ Fix for DNSSEC with wildcard-derived NSEC records. -+ 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. -+ Thanks to Ralph Dolmans for finding this, and co-ordinating -+ the vulnerability tracking and fix release. -+ CVE-2017-15107 applies. -+ -+ - version 2.78 - Fix logic of appending ".<layer>" to PXE basename. Thanks to Chris - Novakovic for the patch. -diff --git a/src/dnssec.c b/src/dnssec.c -index a74d01ab..1417be56 100644 ---- a/src/dnssec.c -+++ b/src/dnssec.c -@@ -424,15 +424,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 */ -@@ -1405,8 +1407,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; -@@ -1419,6 +1421,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; -@@ -1427,7 +1432,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) -@@ -1825,24 +1850,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 */ -@@ -1859,7 +1886,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)) -@@ -1867,7 +1956,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 --- -2.19.0 - |