diff --git a/CVE-2019-18934.patch b/CVE-2019-18934.patch deleted file mode 100644 index 7a9f9e6e51640a82cca4b0b500ebc63be91bf66f..0000000000000000000000000000000000000000 --- a/CVE-2019-18934.patch +++ /dev/null @@ -1,227 +0,0 @@ -From 34e52a4313d59b9d57e928c44300fd81e1a48910 Mon Sep 17 00:00:00 2001 -From: "W.C.A. Wijngaards" -Date: Tue, 19 Nov 2019 07:49:59 +0100 -Subject: [PATCH] Fix CVE-2019-18934, shell execution in ipsecmod. - ---- - ipsecmod/ipsecmod.c | 147 ++++++++++++++++++++++++++++++++++++-------- - 1 file changed, 120 insertions(+), 27 deletions(-) - -diff --git a/ipsecmod/ipsecmod.c b/ipsecmod/ipsecmod.c -index c8400c633..9e916d604 100644 ---- a/ipsecmod/ipsecmod.c -+++ b/ipsecmod/ipsecmod.c -@@ -161,6 +161,71 @@ generate_request(struct module_qstate* qstate, int id, uint8_t* name, - return 1; - } - -+/** -+ * Check if the string passed is a valid domain name with safe characters to -+ * pass to a shell. -+ * This will only allow: -+ * - digits -+ * - alphas -+ * - hyphen (not at the start) -+ * - dot (not at the start, or the only character) -+ * - underscore -+ * @param s: pointer to the string. -+ * @param slen: string's length. -+ * @return true if s only contains safe characters; false otherwise. -+ */ -+static int -+domainname_has_safe_characters(char* s, size_t slen) { -+ size_t i; -+ for(i = 0; i < slen; i++) { -+ if(s[i] == '\0') return 1; -+ if((s[i] == '-' && i != 0) -+ || (s[i] == '.' && (i != 0 || s[1] == '\0')) -+ || (s[i] == '_') || (s[i] >= '0' && s[i] <= '9') -+ || (s[i] >= 'A' && s[i] <= 'Z') -+ || (s[i] >= 'a' && s[i] <= 'z')) { -+ continue; -+ } -+ return 0; -+ } -+ return 1; -+} -+ -+/** -+ * Check if the stringified IPSECKEY RDATA contains safe characters to pass to -+ * a shell. -+ * This is only relevant for checking the gateway when the gateway type is 3 -+ * (domainname). -+ * @param s: pointer to the string. -+ * @param slen: string's length. -+ * @return true if s contains only safe characters; false otherwise. -+ */ -+static int -+ipseckey_has_safe_characters(char* s, size_t slen) { -+ int precedence, gateway_type, algorithm; -+ char* gateway; -+ gateway = (char*)calloc(slen, sizeof(char)); -+ if(!gateway) { -+ log_err("ipsecmod: out of memory when calling the hook"); -+ return 0; -+ } -+ if(sscanf(s, "%d %d %d %s ", -+ &precedence, &gateway_type, &algorithm, gateway) != 4) { -+ free(gateway); -+ return 0; -+ } -+ if(gateway_type != 3) { -+ free(gateway); -+ return 1; -+ } -+ if(domainname_has_safe_characters(gateway, slen)) { -+ free(gateway); -+ return 1; -+ } -+ free(gateway); -+ return 0; -+} -+ - /** - * Prepare the data and call the hook. - * -@@ -175,7 +240,7 @@ call_hook(struct module_qstate* qstate, struct ipsecmod_qstate* iq, - { - size_t slen, tempdata_len, tempstring_len, i; - char str[65535], *s, *tempstring; -- int w; -+ int w = 0, w_temp, qtype; - struct ub_packed_rrset_key* rrset_key; - struct packed_rrset_data* rrset_data; - uint8_t *tempdata; -@@ -192,9 +257,9 @@ call_hook(struct module_qstate* qstate, struct ipsecmod_qstate* iq, - memset(s, 0, slen); - - /* Copy the hook into the buffer. */ -- sldns_str_print(&s, &slen, "%s", qstate->env->cfg->ipsecmod_hook); -+ w += sldns_str_print(&s, &slen, "%s", qstate->env->cfg->ipsecmod_hook); - /* Put space into the buffer. */ -- sldns_str_print(&s, &slen, " "); -+ w += sldns_str_print(&s, &slen, " "); - /* Copy the qname into the buffer. */ - tempstring = sldns_wire2str_dname(qstate->qinfo.qname, - qstate->qinfo.qname_len); -@@ -202,68 +267,96 @@ call_hook(struct module_qstate* qstate, struct ipsecmod_qstate* iq, - log_err("ipsecmod: out of memory when calling the hook"); - return 0; - } -- sldns_str_print(&s, &slen, "\"%s\"", tempstring); -+ if(!domainname_has_safe_characters(tempstring, strlen(tempstring))) { -+ log_err("ipsecmod: qname has unsafe characters"); -+ free(tempstring); -+ return 0; -+ } -+ w += sldns_str_print(&s, &slen, "\"%s\"", tempstring); - free(tempstring); - /* Put space into the buffer. */ -- sldns_str_print(&s, &slen, " "); -+ w += sldns_str_print(&s, &slen, " "); - /* Copy the IPSECKEY TTL into the buffer. */ - rrset_data = (struct packed_rrset_data*)iq->ipseckey_rrset->entry.data; -- sldns_str_print(&s, &slen, "\"%ld\"", (long)rrset_data->ttl); -+ w += sldns_str_print(&s, &slen, "\"%ld\"", (long)rrset_data->ttl); - /* Put space into the buffer. */ -- sldns_str_print(&s, &slen, " "); -- /* Copy the A/AAAA record(s) into the buffer. Start and end this section -- * with a double quote. */ -+ w += sldns_str_print(&s, &slen, " "); - rrset_key = reply_find_answer_rrset(&qstate->return_msg->qinfo, - qstate->return_msg->rep); -+ /* Double check that the records are indeed A/AAAA. -+ * This should never happen as this function is only executed for A/AAAA -+ * queries but make sure we don't pass anything other than A/AAAA to the -+ * shell. */ -+ qtype = ntohs(rrset_key->rk.type); -+ if(qtype != LDNS_RR_TYPE_AAAA && qtype != LDNS_RR_TYPE_A) { -+ log_err("ipsecmod: Answer is not of A or AAAA type"); -+ return 0; -+ } - rrset_data = (struct packed_rrset_data*)rrset_key->entry.data; -- sldns_str_print(&s, &slen, "\""); -+ /* Copy the A/AAAA record(s) into the buffer. Start and end this section -+ * with a double quote. */ -+ w += sldns_str_print(&s, &slen, "\""); - for(i=0; icount; i++) { - if(i > 0) { - /* Put space into the buffer. */ -- sldns_str_print(&s, &slen, " "); -+ w += sldns_str_print(&s, &slen, " "); - } - /* Ignore the first two bytes, they are the rr_data len. */ -- w = sldns_wire2str_rdata_buf(rrset_data->rr_data[i] + 2, -+ w_temp = sldns_wire2str_rdata_buf(rrset_data->rr_data[i] + 2, - rrset_data->rr_len[i] - 2, s, slen, qstate->qinfo.qtype); -- if(w < 0) { -+ if(w_temp < 0) { - /* Error in printout. */ -- return -1; -- } else if((size_t)w >= slen) { -+ log_err("ipsecmod: Error in printing IP address"); -+ return 0; -+ } else if((size_t)w_temp >= slen) { - s = NULL; /* We do not want str to point outside of buffer. */ - slen = 0; -- return -1; -+ log_err("ipsecmod: shell command too long"); -+ return 0; - } else { -- s += w; -- slen -= w; -+ s += w_temp; -+ slen -= w_temp; -+ w += w_temp; - } - } -- sldns_str_print(&s, &slen, "\""); -+ w += sldns_str_print(&s, &slen, "\""); - /* Put space into the buffer. */ -- sldns_str_print(&s, &slen, " "); -+ w += sldns_str_print(&s, &slen, " "); - /* Copy the IPSECKEY record(s) into the buffer. Start and end this section - * with a double quote. */ -- sldns_str_print(&s, &slen, "\""); -+ w += sldns_str_print(&s, &slen, "\""); - rrset_data = (struct packed_rrset_data*)iq->ipseckey_rrset->entry.data; - for(i=0; icount; i++) { - if(i > 0) { - /* Put space into the buffer. */ -- sldns_str_print(&s, &slen, " "); -+ w += sldns_str_print(&s, &slen, " "); - } - /* Ignore the first two bytes, they are the rr_data len. */ - tempdata = rrset_data->rr_data[i] + 2; - tempdata_len = rrset_data->rr_len[i] - 2; - /* Save the buffer pointers. */ - tempstring = s; tempstring_len = slen; -- w = sldns_wire2str_ipseckey_scan(&tempdata, &tempdata_len, &s, &slen, -- NULL, 0); -+ w_temp = sldns_wire2str_ipseckey_scan(&tempdata, &tempdata_len, &s, -+ &slen, NULL, 0); - /* There was an error when parsing the IPSECKEY; reset the buffer - * pointers to their previous values. */ -- if(w == -1){ -+ if(w_temp == -1) { - s = tempstring; slen = tempstring_len; -+ } else if(w_temp > 0) { -+ if(!ipseckey_has_safe_characters( -+ tempstring, tempstring_len - slen)) { -+ log_err("ipsecmod: ipseckey has unsafe characters"); -+ return 0; -+ } -+ w += w_temp; - } - } -- sldns_str_print(&s, &slen, "\""); -- verbose(VERB_ALGO, "ipsecmod: hook command: '%s'", str); -+ w += sldns_str_print(&s, &slen, "\""); -+ if(w >= (int)sizeof(str)) { -+ log_err("ipsecmod: shell command too long"); -+ return 0; -+ } -+ verbose(VERB_ALGO, "ipsecmod: shell command: '%s'", str); - /* ipsecmod-hook should return 0 on success. */ - if(system(str) != 0) - return 0; diff --git a/backport-CVE-2020-12662_CVE-2020-12663.patch b/backport-CVE-2020-12662_CVE-2020-12663.patch deleted file mode 100644 index 69339fc2261b426a91870570104abdb768e9040c..0000000000000000000000000000000000000000 --- a/backport-CVE-2020-12662_CVE-2020-12663.patch +++ /dev/null @@ -1,964 +0,0 @@ -From 72129533b9dcd8456c59a867ad78221642eb774c Mon Sep 17 00:00:00 2001 -From: "W.C.A. Wijngaards" -Date: Tue, 19 May 2020 10:27:27 +0200 -Subject: [PATCH] - CVE-2020-12662 Unbound can be tricked into amplifying an - incoming query into a large number of queries directed to a target. - - CVE-2020-12663 Malformed answers from upstream name servers can be used to - make Unbound unresponsive. - -Conflicts: - doc/Changelog - unbound-1.7.3/iterator/iterator.c ---- - unbound-1.7.3/iterator/iter_delegpt.c | 51 +++++++----- - unbound-1.7.3/iterator/iter_delegpt.h | 28 +++++-- - unbound-1.7.3/iterator/iter_scrub.c | 24 ++++-- - unbound-1.7.3/iterator/iter_utils.c | 4 +- - unbound-1.7.3/iterator/iterator.c | 149 ++++++++++++++++++++++++++++------ - unbound-1.7.3/iterator/iterator.h | 12 ++- - unbound-1.7.3/services/cache/dns.c | 10 ++- - unbound-1.7.3/util/data/dname.c | 30 +++++++ - unbound-1.7.3/util/data/msgparse.c | 6 +- - 9 files changed, 248 insertions(+), 66 deletions(-) - -diff --git a/unbound-1.7.3/iterator/iter_delegpt.c b/unbound-1.7.3/iterator/iter_delegpt.c -index f88b3e1..9a672b0 100644 ---- a/unbound-1.7.3/iterator/iter_delegpt.c -+++ b/unbound-1.7.3/iterator/iter_delegpt.c -@@ -84,7 +84,7 @@ struct delegpt* delegpt_copy(struct delegpt* dp, struct regional* region) - } - for(a = dp->target_list; a; a = a->next_target) { - if(!delegpt_add_addr(copy, region, &a->addr, a->addrlen, -- a->bogus, a->lame, a->tls_auth_name)) -+ a->bogus, a->lame, a->tls_auth_name, NULL)) - return NULL; - } - return copy; -@@ -161,7 +161,7 @@ delegpt_find_addr(struct delegpt* dp, struct sockaddr_storage* addr, - int - delegpt_add_target(struct delegpt* dp, struct regional* region, - uint8_t* name, size_t namelen, struct sockaddr_storage* addr, -- socklen_t addrlen, uint8_t bogus, uint8_t lame) -+ socklen_t addrlen, uint8_t bogus, uint8_t lame, int* additions) - { - struct delegpt_ns* ns = delegpt_find_ns(dp, name, namelen); - log_assert(!dp->dp_type_mlc); -@@ -176,13 +176,14 @@ delegpt_add_target(struct delegpt* dp, struct regional* region, - if(ns->got4 && ns->got6) - ns->resolved = 1; - } -- return delegpt_add_addr(dp, region, addr, addrlen, bogus, lame, NULL); -+ return delegpt_add_addr(dp, region, addr, addrlen, bogus, lame, NULL, -+ additions); - } - - int - delegpt_add_addr(struct delegpt* dp, struct regional* region, - struct sockaddr_storage* addr, socklen_t addrlen, uint8_t bogus, -- uint8_t lame, char* tls_auth_name) -+ uint8_t lame, char* tls_auth_name, int* additions) - { - struct delegpt_addr* a; - log_assert(!dp->dp_type_mlc); -@@ -194,6 +195,8 @@ delegpt_add_addr(struct delegpt* dp, struct regional* region, - a->lame = 0; - return 1; - } -+ if(additions) -+ *additions = 1; - - a = (struct delegpt_addr*)regional_alloc(region, - sizeof(struct delegpt_addr)); -@@ -382,10 +385,10 @@ delegpt_from_message(struct dns_msg* msg, struct regional* region) - continue; - - if(ntohs(s->rk.type) == LDNS_RR_TYPE_A) { -- if(!delegpt_add_rrset_A(dp, region, s, 0)) -+ if(!delegpt_add_rrset_A(dp, region, s, 0, NULL)) - return NULL; - } else if(ntohs(s->rk.type) == LDNS_RR_TYPE_AAAA) { -- if(!delegpt_add_rrset_AAAA(dp, region, s, 0)) -+ if(!delegpt_add_rrset_AAAA(dp, region, s, 0, NULL)) - return NULL; - } - } -@@ -416,7 +419,7 @@ delegpt_rrset_add_ns(struct delegpt* dp, struct regional* region, - - int - delegpt_add_rrset_A(struct delegpt* dp, struct regional* region, -- struct ub_packed_rrset_key* ak, uint8_t lame) -+ struct ub_packed_rrset_key* ak, uint8_t lame, int* additions) - { - struct packed_rrset_data* d=(struct packed_rrset_data*)ak->entry.data; - size_t i; -@@ -432,7 +435,7 @@ delegpt_add_rrset_A(struct delegpt* dp, struct regional* region, - memmove(&sa.sin_addr, d->rr_data[i]+2, INET_SIZE); - if(!delegpt_add_target(dp, region, ak->rk.dname, - ak->rk.dname_len, (struct sockaddr_storage*)&sa, -- len, (d->security==sec_status_bogus), lame)) -+ len, (d->security==sec_status_bogus), lame, additions)) - return 0; - } - return 1; -@@ -440,7 +443,7 @@ delegpt_add_rrset_A(struct delegpt* dp, struct regional* region, - - int - delegpt_add_rrset_AAAA(struct delegpt* dp, struct regional* region, -- struct ub_packed_rrset_key* ak, uint8_t lame) -+ struct ub_packed_rrset_key* ak, uint8_t lame, int* additions) - { - struct packed_rrset_data* d=(struct packed_rrset_data*)ak->entry.data; - size_t i; -@@ -456,7 +459,7 @@ delegpt_add_rrset_AAAA(struct delegpt* dp, struct regional* region, - memmove(&sa.sin6_addr, d->rr_data[i]+2, INET6_SIZE); - if(!delegpt_add_target(dp, region, ak->rk.dname, - ak->rk.dname_len, (struct sockaddr_storage*)&sa, -- len, (d->security==sec_status_bogus), lame)) -+ len, (d->security==sec_status_bogus), lame, additions)) - return 0; - } - return 1; -@@ -464,20 +467,33 @@ delegpt_add_rrset_AAAA(struct delegpt* dp, struct regional* region, - - int - delegpt_add_rrset(struct delegpt* dp, struct regional* region, -- struct ub_packed_rrset_key* rrset, uint8_t lame) -+ struct ub_packed_rrset_key* rrset, uint8_t lame, int* additions) - { - if(!rrset) - return 1; - if(ntohs(rrset->rk.type) == LDNS_RR_TYPE_NS) - return delegpt_rrset_add_ns(dp, region, rrset, lame); - else if(ntohs(rrset->rk.type) == LDNS_RR_TYPE_A) -- return delegpt_add_rrset_A(dp, region, rrset, lame); -+ return delegpt_add_rrset_A(dp, region, rrset, lame, additions); - else if(ntohs(rrset->rk.type) == LDNS_RR_TYPE_AAAA) -- return delegpt_add_rrset_AAAA(dp, region, rrset, lame); -+ return delegpt_add_rrset_AAAA(dp, region, rrset, lame, -+ additions); - log_warn("Unknown rrset type added to delegpt"); - return 1; - } - -+void delegpt_mark_neg(struct delegpt_ns* ns, uint16_t qtype) -+{ -+ if(ns) { -+ if(qtype == LDNS_RR_TYPE_A) -+ ns->got4 = 2; -+ else if(qtype == LDNS_RR_TYPE_AAAA) -+ ns->got6 = 2; -+ if(ns->got4 && ns->got6) -+ ns->resolved = 1; -+ } -+} -+ - void delegpt_add_neg_msg(struct delegpt* dp, struct msgreply_entry* msg) - { - struct reply_info* rep = (struct reply_info*)msg->entry.data; -@@ -487,14 +503,7 @@ void delegpt_add_neg_msg(struct delegpt* dp, struct msgreply_entry* msg) - if(FLAGS_GET_RCODE(rep->flags) != 0 || rep->an_numrrsets == 0) { - struct delegpt_ns* ns = delegpt_find_ns(dp, msg->key.qname, - msg->key.qname_len); -- if(ns) { -- if(msg->key.qtype == LDNS_RR_TYPE_A) -- ns->got4 = 1; -- else if(msg->key.qtype == LDNS_RR_TYPE_AAAA) -- ns->got6 = 1; -- if(ns->got4 && ns->got6) -- ns->resolved = 1; -- } -+ delegpt_mark_neg(ns, msg->key.qtype); - } - } - -diff --git a/unbound-1.7.3/iterator/iter_delegpt.h b/unbound-1.7.3/iterator/iter_delegpt.h -index 354bd61..e76a017 100644 ---- a/unbound-1.7.3/iterator/iter_delegpt.h -+++ b/unbound-1.7.3/iterator/iter_delegpt.h -@@ -104,9 +104,10 @@ struct delegpt_ns { - * and marked true if got4 and got6 are both true. - */ - int resolved; -- /** if the ipv4 address is in the delegpt */ -+ /** if the ipv4 address is in the delegpt, 0=not, 1=yes 2=negative, -+ * negative means it was done, but no content. */ - uint8_t got4; -- /** if the ipv6 address is in the delegpt */ -+ /** if the ipv6 address is in the delegpt, 0=not, 1=yes 2=negative */ - uint8_t got6; - /** - * If the name is parent-side only and thus dispreferred. -@@ -213,11 +214,12 @@ int delegpt_rrset_add_ns(struct delegpt* dp, struct regional* regional, - * @param addrlen: the length of addr. - * @param bogus: security status for the address, pass true if bogus. - * @param lame: address is lame. -+ * @param additions: will be set to 1 if a new address is added - * @return false on error. - */ - int delegpt_add_target(struct delegpt* dp, struct regional* regional, - uint8_t* name, size_t namelen, struct sockaddr_storage* addr, -- socklen_t addrlen, uint8_t bogus, uint8_t lame); -+ socklen_t addrlen, uint8_t bogus, uint8_t lame, int* additions); - - /** - * Add A RRset to delegpt. -@@ -225,10 +227,11 @@ int delegpt_add_target(struct delegpt* dp, struct regional* regional, - * @param regional: where to allocate the info. - * @param rrset: RRset A to add. - * @param lame: rrset is lame, disprefer it. -+ * @param additions: will be set to 1 if a new address is added - * @return 0 on alloc error. - */ - int delegpt_add_rrset_A(struct delegpt* dp, struct regional* regional, -- struct ub_packed_rrset_key* rrset, uint8_t lame); -+ struct ub_packed_rrset_key* rrset, uint8_t lame, int* additions); - - /** - * Add AAAA RRset to delegpt. -@@ -236,10 +239,11 @@ int delegpt_add_rrset_A(struct delegpt* dp, struct regional* regional, - * @param regional: where to allocate the info. - * @param rrset: RRset AAAA to add. - * @param lame: rrset is lame, disprefer it. -+ * @param additions: will be set to 1 if a new address is added - * @return 0 on alloc error. - */ - int delegpt_add_rrset_AAAA(struct delegpt* dp, struct regional* regional, -- struct ub_packed_rrset_key* rrset, uint8_t lame); -+ struct ub_packed_rrset_key* rrset, uint8_t lame, int* additions); - - /** - * Add any RRset to delegpt. -@@ -248,10 +252,11 @@ int delegpt_add_rrset_AAAA(struct delegpt* dp, struct regional* regional, - * @param regional: where to allocate the info. - * @param rrset: RRset to add, NS, A, AAAA. - * @param lame: rrset is lame, disprefer it. -+ * @param additions: will be set to 1 if a new address is added - * @return 0 on alloc error. - */ - int delegpt_add_rrset(struct delegpt* dp, struct regional* regional, -- struct ub_packed_rrset_key* rrset, uint8_t lame); -+ struct ub_packed_rrset_key* rrset, uint8_t lame, int* additions); - - /** - * Add address to the delegation point. No servername is associated or checked. -@@ -262,11 +267,12 @@ int delegpt_add_rrset(struct delegpt* dp, struct regional* regional, - * @param bogus: if address is bogus. - * @param lame: if address is lame. - * @param tls_auth_name: TLS authentication name (or NULL). -+ * @param additions: will be set to 1 if a new address is added - * @return false on error. - */ - int delegpt_add_addr(struct delegpt* dp, struct regional* regional, - struct sockaddr_storage* addr, socklen_t addrlen, -- uint8_t bogus, uint8_t lame, char* tls_auth_name); -+ uint8_t bogus, uint8_t lame, char* tls_auth_name, int* additions); - - /** - * Find NS record in name list of delegation point. -@@ -340,6 +346,14 @@ struct delegpt* delegpt_from_message(struct dns_msg* msg, - struct regional* regional); - - /** -+ * Mark negative return in delegation point for specific nameserver. -+ * sets the got4 or got6 to negative, updates the ns->resolved. -+ * @param ns: the nameserver in the delegpt. -+ * @param qtype: A or AAAA (host order). -+ */ -+void delegpt_mark_neg(struct delegpt_ns* ns, uint16_t qtype); -+ -+/** - * Add negative message to delegation point. - * @param dp: delegation point. - * @param msg: the message added, marks off A or AAAA from an NS entry. -diff --git a/unbound-1.7.3/iterator/iter_scrub.c b/unbound-1.7.3/iterator/iter_scrub.c -index 12580dc..ccea9fc 100644 ---- a/unbound-1.7.3/iterator/iter_scrub.c -+++ b/unbound-1.7.3/iterator/iter_scrub.c -@@ -185,8 +185,9 @@ mark_additional_rrset(sldns_buffer* pkt, struct msg_parse* msg, - /** Get target name of a CNAME */ - static int - parse_get_cname_target(struct rrset_parse* rrset, uint8_t** sname, -- size_t* snamelen) -+ size_t* snamelen, sldns_buffer* pkt) - { -+ size_t oldpos, dlen; - if(rrset->rr_count != 1) { - struct rr_parse* sig; - verbose(VERB_ALGO, "Found CNAME rrset with " -@@ -204,6 +205,19 @@ parse_get_cname_target(struct rrset_parse* rrset, uint8_t** sname, - *sname = rrset->rr_first->ttl_data + sizeof(uint32_t) - + sizeof(uint16_t); /* skip ttl, rdatalen */ - *snamelen = rrset->rr_first->size - sizeof(uint16_t); -+ -+ if(rrset->rr_first->outside_packet) { -+ if(!dname_valid(*sname, *snamelen)) -+ return 0; -+ return 1; -+ } -+ oldpos = sldns_buffer_position(pkt); -+ sldns_buffer_set_position(pkt, (size_t)(*sname - sldns_buffer_begin(pkt))); -+ dlen = pkt_dname_len(pkt); -+ sldns_buffer_set_position(pkt, oldpos); -+ if(dlen == 0) -+ return 0; /* parse fail on the rdata name */ -+ *snamelen = dlen; - return 1; - } - -@@ -215,7 +229,7 @@ synth_cname(uint8_t* qname, size_t qnamelen, struct rrset_parse* dname_rrset, - /* we already know that sname is a strict subdomain of DNAME owner */ - uint8_t* dtarg = NULL; - size_t dtarglen; -- if(!parse_get_cname_target(dname_rrset, &dtarg, &dtarglen)) -+ if(!parse_get_cname_target(dname_rrset, &dtarg, &dtarglen, pkt)) - return 0; - log_assert(qnamelen > dname_rrset->dname_len); - /* DNAME from com. to net. with qname example.com. -> example.net. */ -@@ -372,7 +386,7 @@ scrub_normalize(sldns_buffer* pkt, struct msg_parse* msg, - /* check next cname */ - uint8_t* t = NULL; - size_t tlen = 0; -- if(!parse_get_cname_target(nx, &t, &tlen)) -+ if(!parse_get_cname_target(nx, &t, &tlen, pkt)) - return 0; - if(dname_pkt_compare(pkt, alias, t) == 0) { - /* it's OK and better capitalized */ -@@ -423,7 +437,7 @@ scrub_normalize(sldns_buffer* pkt, struct msg_parse* msg, - size_t tlen = 0; - if(synth_cname(sname, snamelen, nx, alias, - &aliaslen, pkt) && -- parse_get_cname_target(rrset, &t, &tlen) && -+ parse_get_cname_target(rrset, &t, &tlen, pkt) && - dname_pkt_compare(pkt, alias, t) == 0) { - /* the synthesized CNAME equals the - * current CNAME. This CNAME is the -@@ -442,7 +456,7 @@ scrub_normalize(sldns_buffer* pkt, struct msg_parse* msg, - } - - /* move to next name in CNAME chain */ -- if(!parse_get_cname_target(rrset, &sname, &snamelen)) -+ if(!parse_get_cname_target(rrset, &sname, &snamelen, pkt)) - return 0; - prev = rrset; - rrset = rrset->rrset_all_next; -diff --git a/unbound-1.7.3/iterator/iter_utils.c b/unbound-1.7.3/iterator/iter_utils.c -index 0a8f770..a107bee 100644 ---- a/unbound-1.7.3/iterator/iter_utils.c -+++ b/unbound-1.7.3/iterator/iter_utils.c -@@ -1008,7 +1008,7 @@ int iter_lookup_parent_glue_from_cache(struct module_env* env, - log_rrset_key(VERB_ALGO, "found parent-side", akey); - ns->done_pside4 = 1; - /* a negative-cache-element has no addresses it adds */ -- if(!delegpt_add_rrset_A(dp, region, akey, 1)) -+ if(!delegpt_add_rrset_A(dp, region, akey, 1, NULL)) - log_err("malloc failure in lookup_parent_glue"); - lock_rw_unlock(&akey->entry.lock); - } -@@ -1020,7 +1020,7 @@ int iter_lookup_parent_glue_from_cache(struct module_env* env, - log_rrset_key(VERB_ALGO, "found parent-side", akey); - ns->done_pside6 = 1; - /* a negative-cache-element has no addresses it adds */ -- if(!delegpt_add_rrset_AAAA(dp, region, akey, 1)) -+ if(!delegpt_add_rrset_AAAA(dp, region, akey, 1, NULL)) - log_err("malloc failure in lookup_parent_glue"); - lock_rw_unlock(&akey->entry.lock); - } -diff --git a/unbound-1.7.3/iterator/iterator.c b/unbound-1.7.3/iterator/iterator.c -index 58a9bff..b9c353b 100644 ---- a/unbound-1.7.3/iterator/iterator.c -+++ b/unbound-1.7.3/iterator/iterator.c -@@ -69,6 +69,9 @@ - #include "sldns/parseutil.h" - #include "sldns/sbuffer.h" - -+ -+static void target_count_increase_nx(struct iter_qstate* iq, int num); -+ - int - iter_init(struct module_env* env, int id) - { -@@ -147,6 +151,7 @@ iter_new(struct module_qstate* qstate, int id) - iq->sent_count = 0; - iq->ratelimit_ok = 0; - iq->target_count = NULL; -+ iq->dp_target_count = 0; - iq->wait_priming_stub = 0; - iq->refetch_glue = 0; - iq->dnssec_expected = 0; -@@ -218,6 +223,7 @@ final_state(struct iter_qstate* iq) - static void - error_supers(struct module_qstate* qstate, int id, struct module_qstate* super) - { -+ struct iter_env* ie = (struct iter_env*)qstate->env->modinfo[id]; - struct iter_qstate* super_iq = (struct iter_qstate*)super->minfo[id]; - - if(qstate->qinfo.qtype == LDNS_RR_TYPE_A || -@@ -242,7 +248,11 @@ error_supers(struct module_qstate* qstate, int id, struct module_qstate* super) - super->region, super_iq->dp)) - log_err("out of memory adding missing"); - } -+ delegpt_mark_neg(dpns, qstate->qinfo.qtype); - dpns->resolved = 1; /* mark as failed */ -+ if((dpns->got4 == 2 || !ie->supports_ipv4) && -+ (dpns->got6 == 2 || !ie->supports_ipv6)) -+ target_count_increase_nx(super_iq, 1); - } - if(qstate->qinfo.qtype == LDNS_RR_TYPE_NS) { - /* prime failed to get delegation */ -@@ -577,7 +587,7 @@ static void - target_count_create(struct iter_qstate* iq) - { - if(!iq->target_count) { -- iq->target_count = (int*)calloc(2, sizeof(int)); -+ iq->target_count = (int*)calloc(3, sizeof(int)); - /* if calloc fails we simply do not track this number */ - if(iq->target_count) - iq->target_count[0] = 1; -@@ -590,6 +600,15 @@ target_count_increase(struct iter_qstate* iq, int num) - target_count_create(iq); - if(iq->target_count) - iq->target_count[1] += num; -+ iq->dp_target_count++; -+} -+ -+static void -+target_count_increase_nx(struct iter_qstate* iq, int num) -+{ -+ target_count_create(iq); -+ if(iq->target_count) -+ iq->target_count[2] += num; - } - - /** -@@ -612,13 +631,15 @@ target_count_increase(struct iter_qstate* iq, int num) - * @param subq_ret: if newly allocated, the subquerystate, or NULL if it does - * not need initialisation. - * @param v: if true, validation is done on the subquery. -+ * @param detached: true if this qstate should not attach to the subquery - * @return false on error (malloc). - */ - static int - generate_sub_request(uint8_t* qname, size_t qnamelen, uint16_t qtype, - uint16_t qclass, struct module_qstate* qstate, int id, - struct iter_qstate* iq, enum iter_state initial_state, -- enum iter_state finalstate, struct module_qstate** subq_ret, int v) -+ enum iter_state finalstate, struct module_qstate** subq_ret, int v, -+ int detached) - { - struct module_qstate* subq = NULL; - struct iter_qstate* subiq = NULL; -@@ -645,11 +666,23 @@ generate_sub_request(uint8_t* qname, size_t qnamelen, uint16_t qtype, - valrec = 1; - } - -- /* attach subquery, lookup existing or make a new one */ -- fptr_ok(fptr_whitelist_modenv_attach_sub(qstate->env->attach_sub)); -- if(!(*qstate->env->attach_sub)(qstate, &qinf, qflags, prime, valrec, -- &subq)) { -- return 0; -+ if(detached) { -+ struct mesh_state* sub = NULL; -+ fptr_ok(fptr_whitelist_modenv_add_sub( -+ qstate->env->add_sub)); -+ if(!(*qstate->env->add_sub)(qstate, &qinf, -+ qflags, prime, valrec, &subq, &sub)){ -+ return 0; -+ } -+ } -+ else { -+ /* attach subquery, lookup existing or make a new one */ -+ fptr_ok(fptr_whitelist_modenv_attach_sub( -+ qstate->env->attach_sub)); -+ if(!(*qstate->env->attach_sub)(qstate, &qinf, qflags, prime, -+ valrec, &subq)) { -+ return 0; -+ } - } - *subq_ret = subq; - if(subq) { -@@ -672,6 +705,7 @@ generate_sub_request(uint8_t* qname, size_t qnamelen, uint16_t qtype, - subiq->target_count = iq->target_count; - if(iq->target_count) - iq->target_count[0] ++; /* extra reference */ -+ subiq->dp_target_count = 0; - subiq->num_current_queries = 0; - subiq->depth = iq->depth+1; - outbound_list_init(&subiq->outlist); -@@ -715,7 +749,7 @@ prime_root(struct module_qstate* qstate, struct iter_qstate* iq, int id, - * the normal INIT state logic (which would cause an infloop). */ - if(!generate_sub_request((uint8_t*)"\000", 1, LDNS_RR_TYPE_NS, - qclass, qstate, id, iq, QUERYTARGETS_STATE, PRIME_RESP_STATE, -- &subq, 0)) { -+ &subq, 0, 0)) { - verbose(VERB_ALGO, "could not prime root"); - return 0; - } -@@ -805,7 +839,7 @@ prime_stub(struct module_qstate* qstate, struct iter_qstate* iq, int id, - * redundant INIT state processing. */ - if(!generate_sub_request(stub_dp->name, stub_dp->namelen, - LDNS_RR_TYPE_NS, qclass, qstate, id, iq, -- QUERYTARGETS_STATE, PRIME_RESP_STATE, &subq, 0)) { -+ QUERYTARGETS_STATE, PRIME_RESP_STATE, &subq, 0, 0)) { - verbose(VERB_ALGO, "could not prime stub"); - (void)error_response(qstate, id, LDNS_RCODE_SERVFAIL); - return 1; /* return 1 to make module stop, with error */ -@@ -976,7 +1010,7 @@ generate_a_aaaa_check(struct module_qstate* qstate, struct iter_qstate* iq, - if(!generate_sub_request(s->rk.dname, s->rk.dname_len, - ntohs(s->rk.type), ntohs(s->rk.rrset_class), - qstate, id, iq, -- INIT_REQUEST_STATE, FINISHED_STATE, &subq, 1)) { -+ INIT_REQUEST_STATE, FINISHED_STATE, &subq, 1, 0)) { - verbose(VERB_ALGO, "could not generate addr check"); - return; - } -@@ -1020,7 +1054,7 @@ generate_ns_check(struct module_qstate* qstate, struct iter_qstate* iq, int id) - iq->dp->name, LDNS_RR_TYPE_NS, iq->qchase.qclass); - if(!generate_sub_request(iq->dp->name, iq->dp->namelen, - LDNS_RR_TYPE_NS, iq->qchase.qclass, qstate, id, iq, -- INIT_REQUEST_STATE, FINISHED_STATE, &subq, 1)) { -+ INIT_REQUEST_STATE, FINISHED_STATE, &subq, 1, 0)) { - verbose(VERB_ALGO, "could not generate ns check"); - return; - } -@@ -1077,7 +1111,7 @@ generate_dnskey_prefetch(struct module_qstate* qstate, - iq->dp->name, LDNS_RR_TYPE_DNSKEY, iq->qchase.qclass); - if(!generate_sub_request(iq->dp->name, iq->dp->namelen, - LDNS_RR_TYPE_DNSKEY, iq->qchase.qclass, qstate, id, iq, -- INIT_REQUEST_STATE, FINISHED_STATE, &subq, 0)) { -+ INIT_REQUEST_STATE, FINISHED_STATE, &subq, 0, 0)) { - /* we'll be slower, but it'll work */ - verbose(VERB_ALGO, "could not generate dnskey prefetch"); - return; -@@ -1251,6 +1285,7 @@ processInitRequest(struct module_qstate* qstate, struct iter_qstate* iq, - iq->refetch_glue = 0; - iq->query_restart_count++; - iq->sent_count = 0; -+ iq->dp_target_count = 0; - sock_list_insert(&qstate->reply_origin, NULL, 0, qstate->region); - if(qstate->env->cfg->qname_minimisation) - iq->minimisation_state = INIT_MINIMISE_STATE; -@@ -1613,7 +1648,7 @@ generate_parentside_target_query(struct module_qstate* qstate, - { - struct module_qstate* subq; - if(!generate_sub_request(name, namelen, qtype, qclass, qstate, -- id, iq, INIT_REQUEST_STATE, FINISHED_STATE, &subq, 0)) -+ id, iq, INIT_REQUEST_STATE, FINISHED_STATE, &subq, 0, 0)) - return 0; - if(subq) { - struct iter_qstate* subiq = -@@ -1664,7 +1699,7 @@ generate_target_query(struct module_qstate* qstate, struct iter_qstate* iq, - { - struct module_qstate* subq; - if(!generate_sub_request(name, namelen, qtype, qclass, qstate, -- id, iq, INIT_REQUEST_STATE, FINISHED_STATE, &subq, 0)) -+ id, iq, INIT_REQUEST_STATE, FINISHED_STATE, &subq, 0, 0)) - return 0; - log_nametypeclass(VERB_QUERY, "new target", name, qtype, qclass); - return 1; -@@ -1703,6 +1738,14 @@ query_for_targets(struct module_qstate* qstate, struct iter_qstate* iq, - "number of glue fetches %d", s, iq->target_count[1]); - return 0; - } -+ if(iq->dp_target_count > MAX_DP_TARGET_COUNT) { -+ char s[LDNS_MAX_DOMAINLEN+1]; -+ dname_str(qstate->qinfo.qname, s); -+ verbose(VERB_QUERY, "request %s has exceeded the maximum " -+ "number of glue fetches %d to a single delegation point", -+ s, iq->dp_target_count); -+ return 0; -+ } - - iter_mark_cycle_targets(qstate, iq->dp); - missing = (int)delegpt_count_missing_targets(iq->dp); -@@ -1815,7 +1858,7 @@ processLastResort(struct module_qstate* qstate, struct iter_qstate* iq, - for(a = p->target_list; a; a=a->next_target) { - (void)delegpt_add_addr(iq->dp, qstate->region, - &a->addr, a->addrlen, a->bogus, -- a->lame, a->tls_auth_name); -+ a->lame, a->tls_auth_name, NULL); - } - } - iq->dp->has_parent_side_NS = 1; -@@ -1832,6 +1875,7 @@ processLastResort(struct module_qstate* qstate, struct iter_qstate* iq, - iq->refetch_glue = 1; - iq->query_restart_count++; - iq->sent_count = 0; -+ iq->dp_target_count = 0; - if(qstate->env->cfg->qname_minimisation) - iq->minimisation_state = INIT_MINIMISE_STATE; - return next_state(iq, INIT_REQUEST_STATE); -@@ -1986,7 +2030,7 @@ processDSNSFind(struct module_qstate* qstate, struct iter_qstate* iq, int id) - iq->dsns_point, LDNS_RR_TYPE_NS, iq->qchase.qclass); - if(!generate_sub_request(iq->dsns_point, iq->dsns_point_len, - LDNS_RR_TYPE_NS, iq->qchase.qclass, qstate, id, iq, -- INIT_REQUEST_STATE, FINISHED_STATE, &subq, 0)) { -+ INIT_REQUEST_STATE, FINISHED_STATE, &subq, 0, 0)) { - return error_response_cache(qstate, id, LDNS_RCODE_SERVFAIL); - } - -@@ -2039,6 +2083,13 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq, - "number of sends with %d", iq->sent_count); - return error_response(qstate, id, LDNS_RCODE_SERVFAIL); - } -+ if(iq->target_count && iq->target_count[2] > MAX_TARGET_NX) { -+ verbose(VERB_QUERY, "request has exceeded the maximum " -+ " number of nxdomain nameserver lookups with %d", -+ iq->target_count[2]); -+ errinf(qstate, "exceeded the maximum nameserver nxdomains"); -+ return error_response(qstate, id, LDNS_RCODE_SERVFAIL); -+ } - - /* Make sure we have a delegation point, otherwise priming failed - * or another failure occurred */ -@@ -2139,12 +2190,41 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq, - iq->qinfo_out.qtype, iq->qinfo_out.qclass, - qstate->query_flags, qstate->region, - qstate->env->scratch, 0); -- if(msg && msg->rep->an_numrrsets == 0 -- && FLAGS_GET_RCODE(msg->rep->flags) == -+ if(msg && FLAGS_GET_RCODE(msg->rep->flags) == - LDNS_RCODE_NOERROR) - /* no need to send query if it is already -- * cached as NOERROR/NODATA */ -+ * cached as NOERROR */ - return 1; -+ if(msg && FLAGS_GET_RCODE(msg->rep->flags) == -+ LDNS_RCODE_NXDOMAIN && -+ qstate->env->need_to_validate && -+ qstate->env->cfg->harden_below_nxdomain) { -+ if(msg->rep->security == sec_status_secure) { -+ iq->response = msg; -+ return final_state(iq); -+ } -+ if(msg->rep->security == sec_status_unchecked) { -+ struct module_qstate* subq = NULL; -+ if(!generate_sub_request( -+ iq->qinfo_out.qname, -+ iq->qinfo_out.qname_len, -+ iq->qinfo_out.qtype, -+ iq->qinfo_out.qclass, -+ qstate, id, iq, -+ INIT_REQUEST_STATE, -+ FINISHED_STATE, &subq, 1, 1)) -+ verbose(VERB_ALGO, -+ "could not validate NXDOMAIN " -+ "response"); -+ } -+ } -+ if(msg && FLAGS_GET_RCODE(msg->rep->flags) == -+ LDNS_RCODE_NXDOMAIN) { -+ /* return and add a label in the next -+ * minimisation iteration. -+ */ -+ return 1; -+ } - } - } - if(iq->minimisation_state == SKIP_MINIMISE_STATE) { -@@ -2219,6 +2299,8 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq, - * generated query will immediately be discarded due to depth and - * that servfail is cached, which is not good as opportunism goes. */ - if(iq->depth < ie->max_dependency_depth -+ && iq->num_target_queries == 0 -+ && (!iq->target_count || iq->target_count[2]==0) - && iq->sent_count < TARGET_FETCH_STOP) { - tf_policy = ie->target_fetch_policy[iq->depth]; - } -@@ -2256,6 +2338,7 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq, - iq->num_current_queries++; /* RespState decrements it*/ - iq->referral_count++; /* make sure we don't loop */ - iq->sent_count = 0; -+ iq->dp_target_count = 0; - iq->state = QUERY_RESP_STATE; - return 1; - } -@@ -2341,6 +2424,7 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq, - iq->num_current_queries++; /* RespState decrements it*/ - iq->referral_count++; /* make sure we don't loop */ - iq->sent_count = 0; -+ iq->dp_target_count = 0; - iq->state = QUERY_RESP_STATE; - return 1; - } -@@ -2607,7 +2691,8 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq, - /* Make subrequest to validate intermediate - * NXDOMAIN if harden-below-nxdomain is - * enabled. */ -- if(qstate->env->cfg->harden_below_nxdomain) { -+ if(qstate->env->cfg->harden_below_nxdomain && -+ qstate->env->need_to_validate) { - struct module_qstate* subq = NULL; - log_query_info(VERB_QUERY, - "schedule NXDOMAIN validation:", -@@ -2619,7 +2704,7 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq, - iq->response->qinfo.qclass, - qstate, id, iq, - INIT_REQUEST_STATE, -- FINISHED_STATE, &subq, 1)) -+ FINISHED_STATE, &subq, 1, 1)) - verbose(VERB_ALGO, - "could not validate NXDOMAIN " - "response"); -@@ -2702,6 +2787,7 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq, - /* Count this as a referral. */ - iq->referral_count++; - iq->sent_count = 0; -+ iq->dp_target_count = 0; - /* see if the next dp is a trust anchor, or a DS was sent - * along, indicating dnssec is expected for next zone */ - iq->dnssec_expected = iter_indicates_dnssec(qstate->env, -@@ -2776,6 +2862,7 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq, - iq->dsns_point = NULL; - iq->auth_zone_response = 0; - iq->sent_count = 0; -+ iq->dp_target_count = 0; - if(iq->minimisation_state != MINIMISE_STATE) - /* Only count as query restart when it is not an extra - * query as result of qname minimisation. */ -@@ -2964,7 +3051,7 @@ processPrimeResponse(struct module_qstate* qstate, int id) - if(!generate_sub_request(qstate->qinfo.qname, - qstate->qinfo.qname_len, qstate->qinfo.qtype, - qstate->qinfo.qclass, qstate, id, iq, -- INIT_REQUEST_STATE, FINISHED_STATE, &subq, 1)) { -+ INIT_REQUEST_STATE, FINISHED_STATE, &subq, 1, 0)) { - verbose(VERB_ALGO, "could not generate prime check"); - } - generate_a_aaaa_check(qstate, iq, id); -@@ -2992,6 +3079,7 @@ static void - processTargetResponse(struct module_qstate* qstate, int id, - struct module_qstate* forq) - { -+ struct iter_env* ie = (struct iter_env*)qstate->env->modinfo[id]; - struct iter_qstate* iq = (struct iter_qstate*)qstate->minfo[id]; - struct iter_qstate* foriq = (struct iter_qstate*)forq->minfo[id]; - struct ub_packed_rrset_key* rrset; -@@ -3029,7 +3117,7 @@ processTargetResponse(struct module_qstate* qstate, int id, - log_rrset_key(VERB_ALGO, "add parentside glue to dp", - iq->pside_glue); - if(!delegpt_add_rrset(foriq->dp, forq->region, -- iq->pside_glue, 1)) -+ iq->pside_glue, 1, NULL)) - log_err("out of memory adding pside glue"); - } - -@@ -3040,6 +3128,7 @@ processTargetResponse(struct module_qstate* qstate, int id, - * response type was ANSWER. */ - rrset = reply_find_answer_rrset(&iq->qchase, qstate->return_msg->rep); - if(rrset) { -+ int additions = 0; - /* if CNAMEs have been followed - add new NS to delegpt. */ - /* BTW. RFC 1918 says NS should not have got CNAMEs. Robust. */ - if(!delegpt_find_ns(foriq->dp, rrset->rk.dname, -@@ -3051,13 +3140,23 @@ processTargetResponse(struct module_qstate* qstate, int id, - } - /* if dpns->lame then set the address(es) lame too */ - if(!delegpt_add_rrset(foriq->dp, forq->region, rrset, -- dpns->lame)) -+ dpns->lame, &additions)) - log_err("out of memory adding targets"); -+ if(!additions) { -+ /* no new addresses, increase the nxns counter, like -+ * this could be a list of wildcards with no new -+ * addresses */ -+ target_count_increase_nx(foriq, 1); -+ } - verbose(VERB_ALGO, "added target response"); - delegpt_log(VERB_ALGO, foriq->dp); - } else { - verbose(VERB_ALGO, "iterator TargetResponse failed"); -+ delegpt_mark_neg(dpns, qstate->qinfo.qtype); - dpns->resolved = 1; /* fail the target */ -+ if((dpns->got4 == 2 || !ie->supports_ipv4) && -+ (dpns->got6 == 2 || !ie->supports_ipv6)) -+ target_count_increase_nx(foriq, 1); - } - } - -@@ -3228,7 +3327,7 @@ processCollectClass(struct module_qstate* qstate, int id) - qstate->qinfo.qname_len, qstate->qinfo.qtype, - c, qstate, id, iq, INIT_REQUEST_STATE, - FINISHED_STATE, &subq, -- (int)!(qstate->query_flags&BIT_CD))) { -+ (int)!(qstate->query_flags&BIT_CD), 0)) { - return error_response(qstate, id, - LDNS_RCODE_SERVFAIL); - } -diff --git a/unbound-1.7.3/iterator/iterator.h b/unbound-1.7.3/iterator/iterator.h -index 67ffeb1..84f5a76 100644 ---- a/unbound-1.7.3/iterator/iterator.h -+++ b/unbound-1.7.3/iterator/iterator.h -@@ -55,6 +55,11 @@ struct rbtree_type; - - /** max number of targets spawned for a query and its subqueries */ - #define MAX_TARGET_COUNT 64 -+/** max number of target lookups per qstate, per delegation point */ -+#define MAX_DP_TARGET_COUNT 16 -+/** max number of nxdomains allowed for target lookups for a query and -+ * its subqueries */ -+#define MAX_TARGET_NX 5 - /** max number of query restarts. Determines max number of CNAME chain. */ - #define MAX_RESTART_COUNT 8 - /** max number of referrals. Makes sure resolver does not run away */ -@@ -305,9 +310,14 @@ struct iter_qstate { - int sent_count; - - /** number of target queries spawned in [1], for this query and its -- * subqueries, the malloced-array is shared, [0] refcount. */ -+ * subqueries, the malloced-array is shared, [0] refcount. -+ * in [2] the number of nxdomains is counted. */ - int* target_count; - -+ /** number of target lookups per delegation point. Reset to 0 after -+ * receiving referral answer. Not shared with subqueries. */ -+ int dp_target_count; -+ - /** if true, already tested for ratelimiting and passed the test */ - int ratelimit_ok; - -diff --git a/unbound-1.7.3/services/cache/dns.c b/unbound-1.7.3/services/cache/dns.c -index 35adc35..9098b60 100644 ---- a/unbound-1.7.3/services/cache/dns.c -+++ b/unbound-1.7.3/services/cache/dns.c -@@ -271,7 +271,7 @@ find_add_addrs(struct module_env* env, uint16_t qclass, - akey = rrset_cache_lookup(env->rrset_cache, ns->name, - ns->namelen, LDNS_RR_TYPE_A, qclass, 0, now, 0); - if(akey) { -- if(!delegpt_add_rrset_A(dp, region, akey, 0)) { -+ if(!delegpt_add_rrset_A(dp, region, akey, 0, NULL)) { - lock_rw_unlock(&akey->entry.lock); - return 0; - } -@@ -291,7 +291,7 @@ find_add_addrs(struct module_env* env, uint16_t qclass, - akey = rrset_cache_lookup(env->rrset_cache, ns->name, - ns->namelen, LDNS_RR_TYPE_AAAA, qclass, 0, now, 0); - if(akey) { -- if(!delegpt_add_rrset_AAAA(dp, region, akey, 0)) { -+ if(!delegpt_add_rrset_AAAA(dp, region, akey, 0, NULL)) { - lock_rw_unlock(&akey->entry.lock); - return 0; - } -@@ -325,7 +325,8 @@ cache_fill_missing(struct module_env* env, uint16_t qclass, - akey = rrset_cache_lookup(env->rrset_cache, ns->name, - ns->namelen, LDNS_RR_TYPE_A, qclass, 0, now, 0); - if(akey) { -- if(!delegpt_add_rrset_A(dp, region, akey, ns->lame)) { -+ if(!delegpt_add_rrset_A(dp, region, akey, ns->lame, -+ NULL)) { - lock_rw_unlock(&akey->entry.lock); - return 0; - } -@@ -345,7 +346,8 @@ cache_fill_missing(struct module_env* env, uint16_t qclass, - akey = rrset_cache_lookup(env->rrset_cache, ns->name, - ns->namelen, LDNS_RR_TYPE_AAAA, qclass, 0, now, 0); - if(akey) { -- if(!delegpt_add_rrset_AAAA(dp, region, akey, ns->lame)) { -+ if(!delegpt_add_rrset_AAAA(dp, region, akey, ns->lame, -+ NULL)) { - lock_rw_unlock(&akey->entry.lock); - return 0; - } -diff --git a/unbound-1.7.3/util/data/dname.c b/unbound-1.7.3/util/data/dname.c -index c7360f7..3109971 100644 ---- a/unbound-1.7.3/util/data/dname.c -+++ b/unbound-1.7.3/util/data/dname.c -@@ -231,17 +231,28 @@ int - dname_pkt_compare(sldns_buffer* pkt, uint8_t* d1, uint8_t* d2) - { - uint8_t len1, len2; -+ int count1 = 0, count2 = 0; - log_assert(pkt && d1 && d2); - len1 = *d1++; - len2 = *d2++; - while( len1 != 0 || len2 != 0 ) { - /* resolve ptrs */ - if(LABEL_IS_PTR(len1)) { -+ if((size_t)PTR_OFFSET(len1, *d1) -+ >= sldns_buffer_limit(pkt)) -+ return -1; -+ if(count1++ > MAX_COMPRESS_PTRS) -+ return -1; - d1 = sldns_buffer_at(pkt, PTR_OFFSET(len1, *d1)); - len1 = *d1++; - continue; - } - if(LABEL_IS_PTR(len2)) { -+ if((size_t)PTR_OFFSET(len2, *d2) -+ >= sldns_buffer_limit(pkt)) -+ return 1; -+ if(count2++ > MAX_COMPRESS_PTRS) -+ return 1; - d2 = sldns_buffer_at(pkt, PTR_OFFSET(len2, *d2)); - len2 = *d2++; - continue; -@@ -300,12 +311,18 @@ dname_pkt_hash(sldns_buffer* pkt, uint8_t* dname, hashvalue_type h) - uint8_t labuf[LDNS_MAX_LABELLEN+1]; - uint8_t lablen; - int i; -+ int count = 0; - - /* preserve case of query, make hash label by label */ - lablen = *dname++; - while(lablen) { - if(LABEL_IS_PTR(lablen)) { - /* follow pointer */ -+ if((size_t)PTR_OFFSET(lablen, *dname) -+ >= sldns_buffer_limit(pkt)) -+ return h; -+ if(count++ > MAX_COMPRESS_PTRS) -+ return h; - dname = sldns_buffer_at(pkt, PTR_OFFSET(lablen, *dname)); - lablen = *dname++; - continue; -@@ -333,6 +350,9 @@ void dname_pkt_copy(sldns_buffer* pkt, uint8_t* to, uint8_t* dname) - while(lablen) { - if(LABEL_IS_PTR(lablen)) { - /* follow pointer */ -+ if((size_t)PTR_OFFSET(lablen, *dname) -+ >= sldns_buffer_limit(pkt)) -+ return; - dname = sldns_buffer_at(pkt, PTR_OFFSET(lablen, *dname)); - lablen = *dname++; - continue; -@@ -357,6 +377,7 @@ void dname_pkt_copy(sldns_buffer* pkt, uint8_t* to, uint8_t* dname) - void dname_print(FILE* out, struct sldns_buffer* pkt, uint8_t* dname) - { - uint8_t lablen; -+ int count = 0; - if(!out) out = stdout; - if(!dname) return; - -@@ -370,6 +391,15 @@ void dname_print(FILE* out, struct sldns_buffer* pkt, uint8_t* dname) - fputs("??compressionptr??", out); - return; - } -+ if((size_t)PTR_OFFSET(lablen, *dname) -+ >= sldns_buffer_limit(pkt)) { -+ fputs("??compressionptr??", out); -+ return; -+ } -+ if(count++ > MAX_COMPRESS_PTRS) { -+ fputs("??compressionptr??", out); -+ return; -+ } - dname = sldns_buffer_at(pkt, PTR_OFFSET(lablen, *dname)); - lablen = *dname++; - continue; -diff --git a/unbound-1.7.3/util/data/msgparse.c b/unbound-1.7.3/util/data/msgparse.c -index 13cad8a..9bd376f 100644 ---- a/unbound-1.7.3/util/data/msgparse.c -+++ b/unbound-1.7.3/util/data/msgparse.c -@@ -55,7 +55,11 @@ smart_compare(sldns_buffer* pkt, uint8_t* dnow, - { - if(LABEL_IS_PTR(*dnow)) { - /* ptr points to a previous dname */ -- uint8_t* p = sldns_buffer_at(pkt, PTR_OFFSET(dnow[0], dnow[1])); -+ uint8_t* p; -+ if((size_t)PTR_OFFSET(dnow[0], dnow[1]) -+ >= sldns_buffer_limit(pkt)) -+ return -1; -+ p = sldns_buffer_at(pkt, PTR_OFFSET(dnow[0], dnow[1])); - if( p == dprfirst || p == dprlast ) - return 0; - /* prev dname is also a ptr, both ptrs are the same. */ --- -1.8.3.1 diff --git a/unbound-1.7.3.tar.gz b/unbound-1.11.0.tar.gz similarity index 45% rename from unbound-1.7.3.tar.gz rename to unbound-1.11.0.tar.gz index ca3d60abd00e8006b005ddce41a50eff34aaa717..29799d023c0515700f107d004fdf5d4e7b50de66 100644 Binary files a/unbound-1.7.3.tar.gz and b/unbound-1.11.0.tar.gz differ diff --git a/unbound-1.7.2-python3-devel.patch b/unbound-1.7.2-python3-devel.patch deleted file mode 100644 index db6fce07005f043ee2c6533fb2780ade98f4f586..0000000000000000000000000000000000000000 --- a/unbound-1.7.2-python3-devel.patch +++ /dev/null @@ -1,320 +0,0 @@ -From b5aab36d41f374eddb0f66f28f251588f53a1e1e Mon Sep 17 00:00:00 2001 -From: Wouter Wijngaards -Date: Wed, 27 Jun 2018 05:46:36 +0000 -Subject: [PATCH 1/2] - #4109: Fix that package config depends on python - unconditionally. - -git-svn-id: file:///svn/unbound/trunk@4757 be551aaa-1e26-0410-a405-d3ace91eadb9 ---- - configure | 257 +++++++++++++++++++++++++++++++---------------------------- - configure.ac | 5 +- - 2 files changed, 137 insertions(+), 125 deletions(-) - -diff --git a/configure b/configure -index 3f1c372a..2a1687ae 100755 ---- a/configure -+++ b/configure -@@ -670,9 +670,6 @@ SYSTEMD_DAEMON_LIBS - SYSTEMD_DAEMON_CFLAGS - SYSTEMD_LIBS - SYSTEMD_CFLAGS --PKG_CONFIG_LIBDIR --PKG_CONFIG_PATH --PKG_CONFIG - staticexe - PC_LIBEVENT_DEPENDENCY - UNBOUND_EVENT_UNINSTALL -@@ -697,6 +694,9 @@ swig - SWIG_LIB - SWIG - PC_PY_DEPENDENCY -+PKG_CONFIG_LIBDIR -+PKG_CONFIG_PATH -+PKG_CONFIG - PY_MAJOR_VERSION - PYTHON_SITE_PKG - PYTHON_LDFLAGS -@@ -16930,7 +16930,136 @@ $as_echo "#define HAVE_PYTHON 1" >>confdefs.h - CPPFLAGS="$PYTHON_CPPFLAGS" - fi - ub_have_python=yes -- PC_PY_DEPENDENCY="python" -+ -+ -+ -+ -+ -+ -+ -+if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then -+ if test -n "$ac_tool_prefix"; then -+ # Extract the first word of "${ac_tool_prefix}pkg-config", so it can be a program name with args. -+set dummy ${ac_tool_prefix}pkg-config; ac_word=$2 -+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -+$as_echo_n "checking for $ac_word... " >&6; } -+if ${ac_cv_path_PKG_CONFIG+:} false; then : -+ $as_echo_n "(cached) " >&6 -+else -+ case $PKG_CONFIG in -+ [\\/]* | ?:[\\/]*) -+ ac_cv_path_PKG_CONFIG="$PKG_CONFIG" # Let the user override the test with a path. -+ ;; -+ *) -+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -+for as_dir in $PATH -+do -+ IFS=$as_save_IFS -+ test -z "$as_dir" && as_dir=. -+ for ac_exec_ext in '' $ac_executable_extensions; do -+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then -+ ac_cv_path_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext" -+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 -+ break 2 -+ fi -+done -+ done -+IFS=$as_save_IFS -+ -+ ;; -+esac -+fi -+PKG_CONFIG=$ac_cv_path_PKG_CONFIG -+if test -n "$PKG_CONFIG"; then -+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PKG_CONFIG" >&5 -+$as_echo "$PKG_CONFIG" >&6; } -+else -+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -+$as_echo "no" >&6; } -+fi -+ -+ -+fi -+if test -z "$ac_cv_path_PKG_CONFIG"; then -+ ac_pt_PKG_CONFIG=$PKG_CONFIG -+ # Extract the first word of "pkg-config", so it can be a program name with args. -+set dummy pkg-config; ac_word=$2 -+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -+$as_echo_n "checking for $ac_word... " >&6; } -+if ${ac_cv_path_ac_pt_PKG_CONFIG+:} false; then : -+ $as_echo_n "(cached) " >&6 -+else -+ case $ac_pt_PKG_CONFIG in -+ [\\/]* | ?:[\\/]*) -+ ac_cv_path_ac_pt_PKG_CONFIG="$ac_pt_PKG_CONFIG" # Let the user override the test with a path. -+ ;; -+ *) -+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -+for as_dir in $PATH -+do -+ IFS=$as_save_IFS -+ test -z "$as_dir" && as_dir=. -+ for ac_exec_ext in '' $ac_executable_extensions; do -+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then -+ ac_cv_path_ac_pt_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext" -+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 -+ break 2 -+ fi -+done -+ done -+IFS=$as_save_IFS -+ -+ ;; -+esac -+fi -+ac_pt_PKG_CONFIG=$ac_cv_path_ac_pt_PKG_CONFIG -+if test -n "$ac_pt_PKG_CONFIG"; then -+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_pt_PKG_CONFIG" >&5 -+$as_echo "$ac_pt_PKG_CONFIG" >&6; } -+else -+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -+$as_echo "no" >&6; } -+fi -+ -+ if test "x$ac_pt_PKG_CONFIG" = x; then -+ PKG_CONFIG="" -+ else -+ case $cross_compiling:$ac_tool_warned in -+yes:) -+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 -+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} -+ac_tool_warned=yes ;; -+esac -+ PKG_CONFIG=$ac_pt_PKG_CONFIG -+ fi -+else -+ PKG_CONFIG="$ac_cv_path_PKG_CONFIG" -+fi -+ -+fi -+if test -n "$PKG_CONFIG"; then -+ _pkg_min_version=0.9.0 -+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking pkg-config is at least version $_pkg_min_version" >&5 -+$as_echo_n "checking pkg-config is at least version $_pkg_min_version... " >&6; } -+ if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then -+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -+$as_echo "yes" >&6; } -+ else -+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -+$as_echo "no" >&6; } -+ PKG_CONFIG="" -+ fi -+fi -+ if test -n "$PKG_CONFIG" && \ -+ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"\"python\${PY_MAJOR_VERSION}\"\""; } >&5 -+ ($PKG_CONFIG --exists --print-errors ""python${PY_MAJOR_VERSION}"") 2>&5 -+ ac_status=$? -+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 -+ test $ac_status = 0; }; then -+ PC_PY_DEPENDENCY="python${PY_MAJOR_VERSION}" -+else -+ PC_PY_DEPENDENCY="python" -+fi - - - # Check for SWIG -@@ -18960,126 +19089,6 @@ else - fi - - have_systemd=no -- -- -- -- -- -- -- --if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then -- if test -n "$ac_tool_prefix"; then -- # Extract the first word of "${ac_tool_prefix}pkg-config", so it can be a program name with args. --set dummy ${ac_tool_prefix}pkg-config; ac_word=$2 --{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 --$as_echo_n "checking for $ac_word... " >&6; } --if ${ac_cv_path_PKG_CONFIG+:} false; then : -- $as_echo_n "(cached) " >&6 --else -- case $PKG_CONFIG in -- [\\/]* | ?:[\\/]*) -- ac_cv_path_PKG_CONFIG="$PKG_CONFIG" # Let the user override the test with a path. -- ;; -- *) -- as_save_IFS=$IFS; IFS=$PATH_SEPARATOR --for as_dir in $PATH --do -- IFS=$as_save_IFS -- test -z "$as_dir" && as_dir=. -- for ac_exec_ext in '' $ac_executable_extensions; do -- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then -- ac_cv_path_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext" -- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 -- break 2 -- fi --done -- done --IFS=$as_save_IFS -- -- ;; --esac --fi --PKG_CONFIG=$ac_cv_path_PKG_CONFIG --if test -n "$PKG_CONFIG"; then -- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PKG_CONFIG" >&5 --$as_echo "$PKG_CONFIG" >&6; } --else -- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 --$as_echo "no" >&6; } --fi -- -- --fi --if test -z "$ac_cv_path_PKG_CONFIG"; then -- ac_pt_PKG_CONFIG=$PKG_CONFIG -- # Extract the first word of "pkg-config", so it can be a program name with args. --set dummy pkg-config; ac_word=$2 --{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 --$as_echo_n "checking for $ac_word... " >&6; } --if ${ac_cv_path_ac_pt_PKG_CONFIG+:} false; then : -- $as_echo_n "(cached) " >&6 --else -- case $ac_pt_PKG_CONFIG in -- [\\/]* | ?:[\\/]*) -- ac_cv_path_ac_pt_PKG_CONFIG="$ac_pt_PKG_CONFIG" # Let the user override the test with a path. -- ;; -- *) -- as_save_IFS=$IFS; IFS=$PATH_SEPARATOR --for as_dir in $PATH --do -- IFS=$as_save_IFS -- test -z "$as_dir" && as_dir=. -- for ac_exec_ext in '' $ac_executable_extensions; do -- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then -- ac_cv_path_ac_pt_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext" -- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 -- break 2 -- fi --done -- done --IFS=$as_save_IFS -- -- ;; --esac --fi --ac_pt_PKG_CONFIG=$ac_cv_path_ac_pt_PKG_CONFIG --if test -n "$ac_pt_PKG_CONFIG"; then -- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_pt_PKG_CONFIG" >&5 --$as_echo "$ac_pt_PKG_CONFIG" >&6; } --else -- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 --$as_echo "no" >&6; } --fi -- -- if test "x$ac_pt_PKG_CONFIG" = x; then -- PKG_CONFIG="" -- else -- case $cross_compiling:$ac_tool_warned in --yes:) --{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 --$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} --ac_tool_warned=yes ;; --esac -- PKG_CONFIG=$ac_pt_PKG_CONFIG -- fi --else -- PKG_CONFIG="$ac_cv_path_PKG_CONFIG" --fi -- --fi --if test -n "$PKG_CONFIG"; then -- _pkg_min_version=0.9.0 -- { $as_echo "$as_me:${as_lineno-$LINENO}: checking pkg-config is at least version $_pkg_min_version" >&5 --$as_echo_n "checking pkg-config is at least version $_pkg_min_version... " >&6; } -- if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then -- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 --$as_echo "yes" >&6; } -- else -- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 --$as_echo "no" >&6; } -- PKG_CONFIG="" -- fi --fi - if test "x$enable_systemd" != xno; then : - - -diff --git a/configure.ac b/configure.ac -index 1828253c..b2c95d1a 100644 ---- a/configure.ac -+++ b/configure.ac -@@ -586,7 +586,10 @@ if test x_$ub_test_python != x_no; then - CPPFLAGS="$PYTHON_CPPFLAGS" - fi - ub_have_python=yes -- PC_PY_DEPENDENCY="python" -+ PKG_PROG_PKG_CONFIG -+ PKG_CHECK_EXISTS(["python${PY_MAJOR_VERSION}"], -+ [PC_PY_DEPENDENCY="python${PY_MAJOR_VERSION}"], -+ [PC_PY_DEPENDENCY="python"]) - AC_SUBST(PC_PY_DEPENDENCY) - - # Check for SWIG --- -2.14.4 - diff --git a/unbound-1.7.2-python3-pkgconfig.patch b/unbound-1.7.2-python3-pkgconfig.patch deleted file mode 100644 index 86ba0b8bd0af90ac352f6f98ba717bfa82d889a2..0000000000000000000000000000000000000000 --- a/unbound-1.7.2-python3-pkgconfig.patch +++ /dev/null @@ -1,31 +0,0 @@ -From bca54a8b252d4a75e940424dc761c6a4e487eb84 Mon Sep 17 00:00:00 2001 -From: Wouter Wijngaards -Date: Wed, 27 Jun 2018 06:07:31 +0000 -Subject: [PATCH 2/2] =?UTF-8?q?-=20Patch,=20do=20not=20export=20python=20f?= - =?UTF-8?q?rom=20pkg-config,=20from=20Petr=20Men=C5=A1=C3=ADk.?= -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -git-svn-id: file:///svn/unbound/trunk@4758 be551aaa-1e26-0410-a405-d3ace91eadb9 ---- - contrib/libunbound.pc.in | 3 ++- - 1 file changed, 2 insertions(+), 1 deletion(-) - -diff --git a/contrib/libunbound.pc.in b/contrib/libunbound.pc.in -index 0cb9f875..810c5713 100644 ---- a/contrib/libunbound.pc.in -+++ b/contrib/libunbound.pc.in -@@ -7,7 +7,8 @@ Name: unbound - Description: Library with validating, recursive, and caching DNS resolver - URL: http://www.unbound.net - Version: @PACKAGE_VERSION@ --Requires: @PC_LIBEVENT_DEPENDENCY@ @PC_PY_DEPENDENCY@ -+Requires: libcrypto libssl @PC_LIBEVENT_DEPENDENCY@ -+Requires.private: @PC_PY_DEPENDENCY@ - Libs: -L${libdir} -lunbound -lssl -lcrypto - Libs.private: @SSLLIB@ @LIBS@ - Cflags: -I${includedir} --- -2.14.4 - diff --git a/unbound-1.7.3-anchor-fallback.patch b/unbound-1.7.3-anchor-fallback.patch deleted file mode 100644 index 2470ce11f2cdde3c061f88faded02b338ab807e7..0000000000000000000000000000000000000000 --- a/unbound-1.7.3-anchor-fallback.patch +++ /dev/null @@ -1,182 +0,0 @@ -From 81e9f82a8ddd811d7ebafe2fd0ee5af836d0b405 Mon Sep 17 00:00:00 2001 -From: Wouter Wijngaards -Date: Wed, 4 Jul 2018 10:02:16 +0000 -Subject: [PATCH] - Fix #4112: Fix that unbound-anchor -f /etc/resolv.conf will - not pass if DNSSEC is not enabled. New option -R allows fallback from - resolv.conf to direct queries. - -git-svn-id: file:///svn/unbound/trunk@4770 be551aaa-1e26-0410-a405-d3ace91eadb9 ---- - doc/unbound-anchor.8.in | 5 ++++ - smallapp/unbound-anchor.c | 66 ++++++++++++++++++++++++++++++++++------------- - 2 files changed, 53 insertions(+), 18 deletions(-) - -diff --git a/doc/unbound-anchor.8.in b/doc/unbound-anchor.8.in -index 02a3e781..e114eb25 100644 ---- a/doc/unbound-anchor.8.in -+++ b/doc/unbound-anchor.8.in -@@ -109,6 +109,11 @@ It does so, because the tool when used for bootstrapping the recursive - resolver, cannot use that recursive resolver itself because it is bootstrapping - that server. - .TP -+.B \-R -+Allow fallback from \-f resolv.conf file to direct root servers query. -+It allows you to prefer local resolvers, but fallback automatically -+to direct root query if they do not respond or do not support DNSSEC. -+.TP - .B \-v - More verbose. Once prints informational messages, multiple times may enable - large debug amounts (such as full certificates or byte\-dumps of downloaded -diff --git a/smallapp/unbound-anchor.c b/smallapp/unbound-anchor.c -index b3009108..f3985090 100644 ---- a/smallapp/unbound-anchor.c -+++ b/smallapp/unbound-anchor.c -@@ -192,9 +192,10 @@ usage(void) - printf("-n name signer's subject emailAddress, default %s\n", P7SIGNER); - printf("-4 work using IPv4 only\n"); - printf("-6 work using IPv6 only\n"); -- printf("-f resolv.conf use given resolv.conf to resolve -u name\n"); -- printf("-r root.hints use given root.hints to resolve -u name\n" -+ printf("-f resolv.conf use given resolv.conf\n"); -+ printf("-r root.hints use given root.hints\n" - " builtin root hints are used by default\n"); -+ printf("-R fallback from -f to root query on error\n"); - printf("-v more verbose\n"); - printf("-C conf debug, read config\n"); - printf("-P port use port for https connect, default 443\n"); -@@ -1920,8 +1921,7 @@ static int - do_certupdate(const char* root_anchor_file, const char* root_cert_file, - const char* urlname, const char* xmlname, const char* p7sname, - const char* p7signer, const char* res_conf, const char* root_hints, -- const char* debugconf, int ip4only, int ip6only, int port, -- struct ub_result* dnskey) -+ const char* debugconf, int ip4only, int ip6only, int port) - { - STACK_OF(X509)* cert; - BIO *xml, *p7s; -@@ -1961,7 +1961,6 @@ do_certupdate(const char* root_anchor_file, const char* root_cert_file, - #ifndef S_SPLINT_S - sk_X509_pop_free(cert, X509_free); - #endif -- ub_resolve_free(dnskey); - ip_list_free(ip_list); - return 1; - } -@@ -2199,16 +2198,33 @@ probe_date_allows_certupdate(const char* root_anchor_file) - return 0; - } - -+static struct ub_result * -+fetch_root_key(const char* root_anchor_file, const char* res_conf, -+ const char* root_hints, const char* debugconf, -+ int ip4only, int ip6only) -+{ -+ struct ub_ctx* ctx; -+ struct ub_result* dnskey; -+ -+ ctx = create_unbound_context(res_conf, root_hints, debugconf, -+ ip4only, ip6only); -+ add_5011_probe_root(ctx, root_anchor_file); -+ dnskey = prime_root_key(ctx); -+ ub_ctx_delete(ctx); -+ return dnskey; -+} -+ - /** perform the unbound-anchor work */ - static int - do_root_update_work(const char* root_anchor_file, const char* root_cert_file, - const char* urlname, const char* xmlname, const char* p7sname, - const char* p7signer, const char* res_conf, const char* root_hints, -- const char* debugconf, int ip4only, int ip6only, int force, int port) -+ const char* debugconf, int ip4only, int ip6only, int force, -+ int res_conf_fallback, int port) - { -- struct ub_ctx* ctx; - struct ub_result* dnskey; - int used_builtin = 0; -+ int rcode; - - /* see if builtin rootanchor needs to be provided, or if - * rootanchor is 'revoked-trust-point' */ -@@ -2217,12 +2233,22 @@ do_root_update_work(const char* root_anchor_file, const char* root_cert_file, - - /* make unbound context with 5011-probe for root anchor, - * and probe . DNSKEY */ -- ctx = create_unbound_context(res_conf, root_hints, debugconf, -- ip4only, ip6only); -- add_5011_probe_root(ctx, root_anchor_file); -- dnskey = prime_root_key(ctx); -- ub_ctx_delete(ctx); -- -+ dnskey = fetch_root_key(root_anchor_file, res_conf, -+ root_hints, debugconf, ip4only, ip6only); -+ rcode = dnskey->rcode; -+ -+ if (res_conf_fallback && res_conf && !dnskey->secure) { -+ if (verb) printf("%s failed, retrying direct\n", res_conf); -+ ub_resolve_free(dnskey); -+ /* try direct query without res_conf */ -+ dnskey = fetch_root_key(root_anchor_file, NULL, -+ root_hints, debugconf, ip4only, ip6only); -+ if (rcode != 0 && dnskey->rcode == 0) { -+ res_conf = NULL; -+ rcode = 0; -+ } -+ } -+ - /* if secure: exit */ - if(dnskey->secure && !force) { - if(verb) printf("success: the anchor is ok\n"); -@@ -2230,18 +2256,18 @@ do_root_update_work(const char* root_anchor_file, const char* root_cert_file, - return used_builtin; - } - if(force && verb) printf("debug cert update forced\n"); -+ ub_resolve_free(dnskey); - - /* if not (and NOERROR): check date and do certupdate */ -- if((dnskey->rcode == 0 && -+ if((rcode == 0 && - probe_date_allows_certupdate(root_anchor_file)) || force) { - if(do_certupdate(root_anchor_file, root_cert_file, urlname, - xmlname, p7sname, p7signer, res_conf, root_hints, -- debugconf, ip4only, ip6only, port, dnskey)) -+ debugconf, ip4only, ip6only, port)) - return 1; - return used_builtin; - } - if(verb) printf("fail: the anchor is NOT ok and could not be fixed\n"); -- ub_resolve_free(dnskey); - return used_builtin; - } - -@@ -2264,8 +2290,9 @@ int main(int argc, char* argv[]) - const char* root_hints = NULL; - const char* debugconf = NULL; - int dolist=0, ip4only=0, ip6only=0, force=0, port = HTTPS_PORT; -+ int res_conf_fallback = 0; - /* parse the options */ -- while( (c=getopt(argc, argv, "46C:FP:a:c:f:hln:r:s:u:vx:")) != -1) { -+ while( (c=getopt(argc, argv, "46C:FRP:a:c:f:hln:r:s:u:vx:")) != -1) { - switch(c) { - case 'l': - dolist = 1; -@@ -2300,6 +2327,9 @@ int main(int argc, char* argv[]) - case 'r': - root_hints = optarg; - break; -+ case 'R': -+ res_conf_fallback = 1; -+ break; - case 'C': - debugconf = optarg; - break; -@@ -2346,5 +2376,5 @@ int main(int argc, char* argv[]) - - return do_root_update_work(root_anchor_file, root_cert_file, urlname, - xmlname, p7sname, p7signer, res_conf, root_hints, debugconf, -- ip4only, ip6only, force, port); -+ ip4only, ip6only, force, res_conf_fallback, port); - } --- -2.14.4 - diff --git a/unbound-1.7.3-host-any.patch b/unbound-1.7.3-host-any.patch deleted file mode 100644 index 9db4b947654558e412bf959c0e05099824494edf..0000000000000000000000000000000000000000 --- a/unbound-1.7.3-host-any.patch +++ /dev/null @@ -1,12 +0,0 @@ -diff --git a/smallapp/unbound-host.c b/smallapp/unbound-host.c -index 53bf3277..f02511fe 100644 ---- a/smallapp/unbound-host.c -+++ b/smallapp/unbound-host.c -@@ -340,6 +340,7 @@ pretty_output(char* q, int t, int c, struct ub_result* result, int docname) - exit(1); - } - printf("%s\n", s); -+ free(s); - } else printf(" has no %s record", tstr); - printf(" %s\n", secstatus); - } diff --git a/unbound.conf b/unbound.conf index 2de6b64132185be9495ebd86786af5127e494008..748a661d06f76e47a20b9b2f57561cec1e7383bc 100644 --- a/unbound.conf +++ b/unbound.conf @@ -105,6 +105,7 @@ server: # are present, they are processed in order. # Our SElinux policy does not allow non-ephemeral ports to be used outgoing-port-avoid: 0-32767 + outgoing-port-avoid: 61000-65535 # number of outgoing simultaneous tcp buffers to hold per thread. # outgoing-num-tcp: 10 diff --git a/unbound.spec b/unbound.spec index 6036c18175f60e6cd571a4583df306d5239a3957..73557ce93960e9aef038995c77f93994524d4ef5 100644 --- a/unbound.spec +++ b/unbound.spec @@ -1,8 +1,8 @@ %{!?delete_la: %global delete_la find $RPM_BUILD_ROOT -type f -name "*.la" -delete} Name: unbound -Version: 1.7.3 -Release: 15 +Version: 1.11.0 +Release: 1 Summary: Unbound is a validating, recursive, caching DNS resolver License: BSD Url: https://nlnetlabs.nl/projects/unbound/about/ @@ -21,16 +21,11 @@ Source11: unbound.sysconfig Source12: unbound-anchor.timer Source13: unbound-anchor.service -Patch0001: unbound-1.7.2-python3-devel.patch -Patch0002: unbound-1.7.2-python3-pkgconfig.patch -Patch0003: unbound-1.7.3-anchor-fallback.patch -Patch0004: unbound-1.7.3-host-any.patch -Patch0005: CVE-2019-18934.patch - -Patch6001: backport-CVE-2020-12662_CVE-2020-12663.patch +#Patch0001: unbound-1.10.0-auth-callback.patch BuildRequires: make flex swig pkgconfig systemd python-unversioned-command BuildRequires: libevent-devel expat-devel openssl-devel python3-devel +BuildRequires: unbound-libs %{?systemd_requires} Requires: %{name}-libs = %{version}-%{release} @@ -77,12 +72,8 @@ Package help includes includes man pages for unbound. %setup -qcn %{name}-%{version} pushd %{name}-%{version} -%patch0001 -p1 -b .python3 -%patch0002 -p1 -b .python3 -%patch0003 -p1 -b .anchor-fallback -%patch0004 -p1 -b .host-any -%patch0005 -p1 -%patch6001 -p2 + +#%patch0001 -p1 cp -pr doc pythonmod libunbound ../ popd @@ -126,7 +117,7 @@ install -p -m 0644 %{SOURCE11} $RPM_BUILD_ROOT%{_sysconfdir}/sysconfig/unbound install -p -m 0644 %{SOURCE12} $RPM_BUILD_ROOT%{_unitdir}/unbound-anchor.timer install -p -m 0644 %{SOURCE13} $RPM_BUILD_ROOT%{_unitdir}/unbound-anchor.service - +cp -a %{_libdir}/libunbound.so.2* %{buildroot}%{_libdir} %delete_la @@ -238,11 +229,11 @@ popd %{_mandir}/man* %changelog -* Fri Jul 24 2020 zhangnaru - 1.7.3-15 -- Type:cves -- ID:CVE-2020-12662 CVE-2020-12663 +* Sat Aug 29 2020 xiaqirong - 1.11.0-1 +- Type:requirement +- ID:NA - SUG:NA -- DESC:fix CVE-2020-12662 CVE-2020-12663 +- DESC:update unbound version to 1.11.0 * Wed Feb 19 2020 hexiujun - 1.7.3-14 - Type:enhancement diff --git a/unbound.yaml b/unbound.yaml new file mode 100644 index 0000000000000000000000000000000000000000..7672e0ee79375fe87c216a64d5e790988bf15c59 --- /dev/null +++ b/unbound.yaml @@ -0,0 +1,4 @@ +version_control: github +src_repo: NLnetLabs/unbound +tag_prefix: release- +seperator: .