diff -Nru unbound-1.6.7/debian/changelog unbound-1.6.7/debian/changelog --- unbound-1.6.7/debian/changelog 2018-02-28 08:23:03.000000000 +0000 +++ unbound-1.6.7/debian/changelog 2018-05-28 02:38:19.000000000 +0000 @@ -1,3 +1,12 @@ +unbound (1.6.7-1ubuntu2.1) bionic-security; urgency=medium + + * SECURITY UPDATE: vulnerability in the processing of wildcard + synthesized NSEC records (LP: #1773720) + - debian/patches/CVE-2017-15105.patch + - CVE-2017-15105 + + -- Simon Deziel Mon, 28 May 2018 02:38:19 +0000 + unbound (1.6.7-1ubuntu2) bionic; urgency=medium * debian/apparmor-profile: add capabilities to chown/chmod Unix diff -Nru unbound-1.6.7/debian/patches/CVE-2017-15105.patch unbound-1.6.7/debian/patches/CVE-2017-15105.patch --- unbound-1.6.7/debian/patches/CVE-2017-15105.patch 1970-01-01 00:00:00.000000000 +0000 +++ unbound-1.6.7/debian/patches/CVE-2017-15105.patch 2018-05-28 02:37:03.000000000 +0000 @@ -0,0 +1,865 @@ +Description: vulnerability in the processing of wildcard synthesized NSEC records +Origin: https://unbound.net/downloads/patch_cve_2017_15105.diff +Forwarded: not-needed + +Index: testcode/unitverify.c +=================================================================== +--- testcode/unitverify.c (revision 4377) ++++ testcode/unitverify.c (working copy) +@@ -186,7 +186,9 @@ + ntohs(rrset->rk.rrset_class)); + } + setup_sigalg(dnskey, sigalg); /* check all algorithms in the dnskey */ +- sec = dnskeyset_verify_rrset(env, ve, rrset, dnskey, sigalg, &reason); ++ /* ok to give null as qstate here, won't be used for answer section. */ ++ sec = dnskeyset_verify_rrset(env, ve, rrset, dnskey, sigalg, &reason, ++ LDNS_SECTION_ANSWER, NULL); + if(vsig) { + printf("verify outcome is: %s %s\n", sec_status_to_string(sec), + reason?reason:""); +Index: validator/autotrust.c +=================================================================== +--- validator/autotrust.c (revision 4377) ++++ validator/autotrust.c (working copy) +@@ -1227,17 +1227,20 @@ + * @param ve: validator environment (with options) for verification. + * @param tp: trust point to verify with + * @param rrset: DNSKEY rrset to verify. ++ * @param qstate: qstate with region. + * @return false on failure, true if verification successful. + */ + static int + verify_dnskey(struct module_env* env, struct val_env* ve, +- struct trust_anchor* tp, struct ub_packed_rrset_key* rrset) ++ struct trust_anchor* tp, struct ub_packed_rrset_key* rrset, ++ struct module_qstate* qstate) + { + char* reason = NULL; + uint8_t sigalg[ALGO_NEEDS_MAX+1]; + int downprot = env->cfg->harden_algo_downgrade; + enum sec_status sec = val_verify_DNSKEY_with_TA(env, ve, rrset, +- tp->ds_rrset, tp->dnskey_rrset, downprot?sigalg:NULL, &reason); ++ tp->ds_rrset, tp->dnskey_rrset, downprot?sigalg:NULL, &reason, ++ qstate); + /* sigalg is ignored, it returns algorithms signalled to exist, but + * in 5011 there are no other rrsets to check. if downprot is + * enabled, then it checks that the DNSKEY is signed with all +@@ -1276,7 +1279,8 @@ + /** Is rr self-signed revoked key */ + static int + rr_is_selfsigned_revoked(struct module_env* env, struct val_env* ve, +- struct ub_packed_rrset_key* dnskey_rrset, size_t i) ++ struct ub_packed_rrset_key* dnskey_rrset, size_t i, ++ struct module_qstate* qstate) + { + enum sec_status sec; + char* reason = NULL; +@@ -1285,7 +1289,7 @@ + /* no algorithm downgrade protection necessary, if it is selfsigned + * revoked it can be removed. */ + sec = dnskey_verify_rrset(env, ve, dnskey_rrset, dnskey_rrset, i, +- &reason); ++ &reason, LDNS_SECTION_ANSWER, qstate); + return (sec == sec_status_secure); + } + +@@ -1501,7 +1505,7 @@ + static void + check_contains_revoked(struct module_env* env, struct val_env* ve, + struct trust_anchor* tp, struct ub_packed_rrset_key* dnskey_rrset, +- int* changed) ++ int* changed, struct module_qstate* qstate) + { + struct packed_rrset_data* dd = (struct packed_rrset_data*) + dnskey_rrset->entry.data; +@@ -1521,7 +1525,7 @@ + } + if(!ta) + continue; /* key not found */ +- if(rr_is_selfsigned_revoked(env, ve, dnskey_rrset, i)) { ++ if(rr_is_selfsigned_revoked(env, ve, dnskey_rrset, i, qstate)) { + /* checked if there is an rrsig signed by this key. */ + /* same keytag, but stored can be revoked already, so + * compare keytags, with +0 or +128(REVOKE flag) */ +@@ -2118,7 +2122,8 @@ + } + + int autr_process_prime(struct module_env* env, struct val_env* ve, +- struct trust_anchor* tp, struct ub_packed_rrset_key* dnskey_rrset) ++ struct trust_anchor* tp, struct ub_packed_rrset_key* dnskey_rrset, ++ struct module_qstate* qstate) + { + int changed = 0; + log_assert(tp && tp->autr); +@@ -2159,7 +2164,7 @@ + return 1; /* trust point exists */ + } + /* check for revoked keys to remove immediately */ +- check_contains_revoked(env, ve, tp, dnskey_rrset, &changed); ++ check_contains_revoked(env, ve, tp, dnskey_rrset, &changed, qstate); + if(changed) { + verbose(VERB_ALGO, "autotrust: revokedkeys, reassemble"); + if(!autr_assemble(tp)) { +@@ -2175,7 +2180,7 @@ + } + } + /* verify the dnskey rrset and see if it is valid. */ +- if(!verify_dnskey(env, ve, tp, dnskey_rrset)) { ++ if(!verify_dnskey(env, ve, tp, dnskey_rrset, qstate)) { + verbose(VERB_ALGO, "autotrust: dnskey did not verify."); + /* only increase failure count if this is not the first prime, + * this means there was a previous successful probe */ +Index: validator/autotrust.h +=================================================================== +--- validator/autotrust.h (revision 4377) ++++ validator/autotrust.h (working copy) +@@ -47,6 +47,7 @@ + struct trust_anchor; + struct ub_packed_rrset_key; + struct module_env; ++struct module_qstate; + struct val_env; + struct sldns_buffer; + +@@ -188,12 +189,14 @@ + * @param tp: trust anchor to process. + * @param dnskey_rrset: DNSKEY rrset probed (can be NULL if bad prime result). + * allocated in a region. Has not been validated yet. ++ * @param qstate: qstate with region. + * @return false if trust anchor was revoked completely. + * Otherwise logs errors to log, does not change return value. + * On errors, likely the trust point has been unchanged. + */ + int autr_process_prime(struct module_env* env, struct val_env* ve, +- struct trust_anchor* tp, struct ub_packed_rrset_key* dnskey_rrset); ++ struct trust_anchor* tp, struct ub_packed_rrset_key* dnskey_rrset, ++ struct module_qstate* qstate); + + /** + * Debug printout of rfc5011 tracked anchors +Index: validator/val_nsec.c +=================================================================== +--- validator/val_nsec.c (revision 4377) ++++ validator/val_nsec.c (working copy) +@@ -176,7 +176,7 @@ + static int + nsec_verify_rrset(struct module_env* env, struct val_env* ve, + struct ub_packed_rrset_key* nsec, struct key_entry_key* kkey, +- char** reason) ++ char** reason, struct module_qstate* qstate) + { + struct packed_rrset_data* d = (struct packed_rrset_data*) + nsec->entry.data; +@@ -185,7 +185,8 @@ + rrset_check_sec_status(env->rrset_cache, nsec, *env->now); + if(d->security == sec_status_secure) + return 1; +- d->security = val_verify_rrset_entry(env, ve, nsec, kkey, reason); ++ d->security = val_verify_rrset_entry(env, ve, nsec, kkey, reason, ++ LDNS_SECTION_AUTHORITY, qstate); + if(d->security == sec_status_secure) { + rrset_update_sec_status(env->rrset_cache, nsec, *env->now); + return 1; +@@ -196,7 +197,8 @@ + enum sec_status + val_nsec_prove_nodata_dsreply(struct module_env* env, struct val_env* ve, + struct query_info* qinfo, struct reply_info* rep, +- struct key_entry_key* kkey, time_t* proof_ttl, char** reason) ++ struct key_entry_key* kkey, time_t* proof_ttl, char** reason, ++ struct module_qstate* qstate) + { + struct ub_packed_rrset_key* nsec = reply_find_rrset_section_ns( + rep, qinfo->qname, qinfo->qname_len, LDNS_RR_TYPE_NSEC, +@@ -213,7 +215,7 @@ + * 1) this is a delegation point and there is no DS + * 2) this is not a delegation point */ + if(nsec) { +- if(!nsec_verify_rrset(env, ve, nsec, kkey, reason)) { ++ if(!nsec_verify_rrset(env, ve, nsec, kkey, reason, qstate)) { + verbose(VERB_ALGO, "NSEC RRset for the " + "referral did not verify."); + return sec_status_bogus; +@@ -242,7 +244,8 @@ + i++) { + if(rep->rrsets[i]->rk.type != htons(LDNS_RR_TYPE_NSEC)) + continue; +- if(!nsec_verify_rrset(env, ve, rep->rrsets[i], kkey, reason)) { ++ if(!nsec_verify_rrset(env, ve, rep->rrsets[i], kkey, reason, ++ qstate)) { + verbose(VERB_ALGO, "NSEC for empty non-terminal " + "did not verify."); + return sec_status_bogus; +Index: validator/val_nsec.h +=================================================================== +--- validator/val_nsec.h (revision 4377) ++++ validator/val_nsec.h (working copy) +@@ -46,6 +46,7 @@ + #include "util/data/packed_rrset.h" + struct val_env; + struct module_env; ++struct module_qstate; + struct ub_packed_rrset_key; + struct reply_info; + struct query_info; +@@ -64,6 +65,7 @@ + * @param kkey: key entry to use for verification of signatures. + * @param proof_ttl: if secure, the TTL of how long this proof lasts. + * @param reason: string explaining why bogus. ++ * @param qstate: qstate with region. + * @return security status. + * SECURE: proved absence of DS. + * INSECURE: proved that this was not a delegation point. +@@ -73,7 +75,7 @@ + enum sec_status val_nsec_prove_nodata_dsreply(struct module_env* env, + struct val_env* ve, struct query_info* qinfo, + struct reply_info* rep, struct key_entry_key* kkey, +- time_t* proof_ttl, char** reason); ++ time_t* proof_ttl, char** reason, struct module_qstate* qstate); + + /** + * nsec typemap check, takes an NSEC-type bitmap as argument, checks for type. +Index: validator/val_nsec3.c +=================================================================== +--- validator/val_nsec3.c (revision 4377) ++++ validator/val_nsec3.c (working copy) +@@ -1285,7 +1285,7 @@ + static int + list_is_secure(struct module_env* env, struct val_env* ve, + struct ub_packed_rrset_key** list, size_t num, +- struct key_entry_key* kkey, char** reason) ++ struct key_entry_key* kkey, char** reason, struct module_qstate* qstate) + { + struct packed_rrset_data* d; + size_t i; +@@ -1299,7 +1299,7 @@ + if(d->security == sec_status_secure) + continue; + d->security = val_verify_rrset_entry(env, ve, list[i], kkey, +- reason); ++ reason, LDNS_SECTION_AUTHORITY, qstate); + if(d->security != sec_status_secure) { + verbose(VERB_ALGO, "NSEC3 did not verify"); + return 0; +@@ -1312,7 +1312,8 @@ + enum sec_status + nsec3_prove_nods(struct module_env* env, struct val_env* ve, + struct ub_packed_rrset_key** list, size_t num, +- struct query_info* qinfo, struct key_entry_key* kkey, char** reason) ++ struct query_info* qinfo, struct key_entry_key* kkey, char** reason, ++ struct module_qstate* qstate) + { + rbtree_type ct; + struct nsec3_filter flt; +@@ -1325,7 +1326,7 @@ + *reason = "no valid NSEC3s"; + return sec_status_bogus; /* no valid NSEC3s, bogus */ + } +- if(!list_is_secure(env, ve, list, num, kkey, reason)) ++ if(!list_is_secure(env, ve, list, num, kkey, reason, qstate)) + return sec_status_bogus; /* not all NSEC3 records secure */ + rbtree_init(&ct, &nsec3_hash_cmp); /* init names-to-hash cache */ + filter_init(&flt, list, num, qinfo); /* init RR iterator */ +Index: validator/val_nsec3.h +=================================================================== +--- validator/val_nsec3.h (revision 4377) ++++ validator/val_nsec3.h (working copy) +@@ -71,6 +71,7 @@ + struct val_env; + struct regional; + struct module_env; ++struct module_qstate; + struct ub_packed_rrset_key; + struct reply_info; + struct query_info; +@@ -185,6 +186,7 @@ + * @param qinfo: query that is verified for. + * @param kkey: key entry that signed the NSEC3s. + * @param reason: string for bogus result. ++ * @param qstate: qstate with region. + * @return: + * sec_status SECURE of the proposition is proven by the NSEC3 RRs, + * BOGUS if not, INSECURE if all of the NSEC3s could be validly ignored. +@@ -194,7 +196,8 @@ + enum sec_status + nsec3_prove_nods(struct module_env* env, struct val_env* ve, + struct ub_packed_rrset_key** list, size_t num, +- struct query_info* qinfo, struct key_entry_key* kkey, char** reason); ++ struct query_info* qinfo, struct key_entry_key* kkey, char** reason, ++ struct module_qstate* qstate); + + /** + * Prove NXDOMAIN or NODATA. +Index: validator/val_sigcrypt.c +=================================================================== +--- validator/val_sigcrypt.c (revision 4377) ++++ validator/val_sigcrypt.c (working copy) +@@ -485,7 +485,8 @@ + enum sec_status + dnskeyset_verify_rrset(struct module_env* env, struct val_env* ve, + struct ub_packed_rrset_key* rrset, struct ub_packed_rrset_key* dnskey, +- uint8_t* sigalg, char** reason) ++ uint8_t* sigalg, char** reason, sldns_pkt_section section, ++ struct module_qstate* qstate) + { + enum sec_status sec; + size_t i, num; +@@ -512,7 +513,7 @@ + } + for(i=0; inow, rrset, +- dnskey, i, &sortree, reason); ++ dnskey, i, &sortree, reason, section, qstate); + /* see which algorithm has been fixed up */ + if(sec == sec_status_secure) { + if(!sigalg) +@@ -553,7 +554,8 @@ + enum sec_status + dnskey_verify_rrset(struct module_env* env, struct val_env* ve, + struct ub_packed_rrset_key* rrset, struct ub_packed_rrset_key* dnskey, +- size_t dnskey_idx, char** reason) ++ size_t dnskey_idx, char** reason, sldns_pkt_section section, ++ struct module_qstate* qstate) + { + enum sec_status sec; + size_t i, num, numchecked = 0; +@@ -577,7 +579,8 @@ + buf_canon = 0; + sec = dnskey_verify_rrset_sig(env->scratch, + env->scratch_buffer, ve, *env->now, rrset, +- dnskey, dnskey_idx, i, &sortree, &buf_canon, reason); ++ dnskey, dnskey_idx, i, &sortree, &buf_canon, reason, ++ section, qstate); + if(sec == sec_status_secure) + return sec; + numchecked ++; +@@ -591,7 +594,8 @@ + dnskeyset_verify_rrset_sig(struct module_env* env, struct val_env* ve, + time_t now, struct ub_packed_rrset_key* rrset, + struct ub_packed_rrset_key* dnskey, size_t sig_idx, +- struct rbtree_type** sortree, char** reason) ++ struct rbtree_type** sortree, char** reason, sldns_pkt_section section, ++ struct module_qstate* qstate) + { + /* find matching keys and check them */ + enum sec_status sec = sec_status_bogus; +@@ -616,7 +620,7 @@ + /* see if key verifies */ + sec = dnskey_verify_rrset_sig(env->scratch, + env->scratch_buffer, ve, now, rrset, dnskey, i, +- sig_idx, sortree, &buf_canon, reason); ++ sig_idx, sortree, &buf_canon, reason, section, qstate); + if(sec == sec_status_secure) + return sec; + } +@@ -1121,12 +1125,15 @@ + * signer name length. + * @param sortree: if NULL is passed a new sorted rrset tree is built. + * Otherwise it is reused. ++ * @param section: section of packet where this rrset comes from. ++ * @param qstate: qstate with region. + * @return false on alloc error. + */ + static int + rrset_canonical(struct regional* region, sldns_buffer* buf, + struct ub_packed_rrset_key* k, uint8_t* sig, size_t siglen, +- struct rbtree_type** sortree) ++ struct rbtree_type** sortree, sldns_pkt_section section, ++ struct module_qstate* qstate) + { + struct packed_rrset_data* d = (struct packed_rrset_data*)k->entry.data; + uint8_t* can_owner = NULL; +@@ -1175,6 +1182,20 @@ + canonicalize_rdata(buf, k, d->rr_len[walk->rr_idx]); + } + sldns_buffer_flip(buf); ++ ++ /* Replace RR owner with canonical owner for NSEC records in authority ++ * section, to prevent that a wildcard synthesized NSEC can be used in ++ * the non-existence proves. */ ++ if(ntohs(k->rk.type) == LDNS_RR_TYPE_NSEC && ++ section == LDNS_SECTION_AUTHORITY) { ++ k->rk.dname = regional_alloc_init(qstate->region, can_owner, ++ can_owner_len); ++ if(!k->rk.dname) ++ return 0; ++ k->rk.dname_len = can_owner_len; ++ } ++ ++ + return 1; + } + +@@ -1318,7 +1339,8 @@ + struct val_env* ve, time_t now, + struct ub_packed_rrset_key* rrset, struct ub_packed_rrset_key* dnskey, + size_t dnskey_idx, size_t sig_idx, +- struct rbtree_type** sortree, int* buf_canon, char** reason) ++ struct rbtree_type** sortree, int* buf_canon, char** reason, ++ sldns_pkt_section section, struct module_qstate* qstate) + { + enum sec_status sec; + uint8_t* sig; /* RRSIG rdata */ +@@ -1417,7 +1439,7 @@ + /* create rrset canonical format in buffer, ready for + * signature */ + if(!rrset_canonical(region, buf, rrset, sig+2, +- 18 + signer_len, sortree)) { ++ 18 + signer_len, sortree, section, qstate)) { + log_err("verify: failed due to alloc error"); + return sec_status_unchecked; + } +Index: validator/val_sigcrypt.h +=================================================================== +--- validator/val_sigcrypt.h (revision 4377) ++++ validator/val_sigcrypt.h (working copy) +@@ -44,8 +44,10 @@ + #ifndef VALIDATOR_VAL_SIGCRYPT_H + #define VALIDATOR_VAL_SIGCRYPT_H + #include "util/data/packed_rrset.h" ++#include "sldns/pkthdr.h" + struct val_env; + struct module_env; ++struct module_qstate; + struct ub_packed_rrset_key; + struct rbtree_type; + struct regional; +@@ -237,6 +239,8 @@ + * @param sigalg: if nonNULL provide downgrade protection otherwise one + * algorithm is enough. + * @param reason: if bogus, a string returned, fixed or alloced in scratch. ++ * @param section: section of packet where this rrset comes from. ++ * @param qstate: qstate with region. + * @return SECURE if one key in the set verifies one rrsig. + * UNCHECKED on allocation errors, unsupported algorithms, malformed data, + * and BOGUS on verification failures (no keys match any signatures). +@@ -243,7 +247,8 @@ + */ + enum sec_status dnskeyset_verify_rrset(struct module_env* env, + struct val_env* ve, struct ub_packed_rrset_key* rrset, +- struct ub_packed_rrset_key* dnskey, uint8_t* sigalg, char** reason); ++ struct ub_packed_rrset_key* dnskey, uint8_t* sigalg, char** reason, ++ sldns_pkt_section section, struct module_qstate* qstate); + + /** + * verify rrset against one specific dnskey (from rrset) +@@ -253,12 +258,15 @@ + * @param dnskey: DNSKEY rrset, keyset. + * @param dnskey_idx: which key from the rrset to try. + * @param reason: if bogus, a string returned, fixed or alloced in scratch. ++ * @param section: section of packet where this rrset comes from. ++ * @param qstate: qstate with region. + * @return secure if *this* key signs any of the signatures on rrset. + * unchecked on error or and bogus on bad signature. + */ + enum sec_status dnskey_verify_rrset(struct module_env* env, + struct val_env* ve, struct ub_packed_rrset_key* rrset, +- struct ub_packed_rrset_key* dnskey, size_t dnskey_idx, char** reason); ++ struct ub_packed_rrset_key* dnskey, size_t dnskey_idx, char** reason, ++ sldns_pkt_section section, struct module_qstate* qstate); + + /** + * verify rrset, with dnskey rrset, for a specific rrsig in rrset +@@ -271,6 +279,8 @@ + * @param sortree: reused sorted order. Stored in region. Pass NULL at start, + * and for a new rrset. + * @param reason: if bogus, a string returned, fixed or alloced in scratch. ++ * @param section: section of packet where this rrset comes from. ++ * @param qstate: qstate with region. + * @return secure if any key signs *this* signature. bogus if no key signs it, + * or unchecked on error. + */ +@@ -277,7 +287,8 @@ + enum sec_status dnskeyset_verify_rrset_sig(struct module_env* env, + struct val_env* ve, time_t now, struct ub_packed_rrset_key* rrset, + struct ub_packed_rrset_key* dnskey, size_t sig_idx, +- struct rbtree_type** sortree, char** reason); ++ struct rbtree_type** sortree, char** reason, sldns_pkt_section section, ++ struct module_qstate* qstate); + + /** + * verify rrset, with specific dnskey(from set), for a specific rrsig +@@ -295,6 +306,8 @@ + * pass false at start. pass old value only for same rrset and same + * signature (but perhaps different key) for reuse. + * @param reason: if bogus, a string returned, fixed or alloced in scratch. ++ * @param section: section of packet where this rrset comes from. ++ * @param qstate: qstate with region. + * @return secure if this key signs this signature. unchecked on error or + * bogus if it did not validate. + */ +@@ -302,7 +315,8 @@ + struct sldns_buffer* buf, struct val_env* ve, time_t now, + struct ub_packed_rrset_key* rrset, struct ub_packed_rrset_key* dnskey, + size_t dnskey_idx, size_t sig_idx, +- struct rbtree_type** sortree, int* buf_canon, char** reason); ++ struct rbtree_type** sortree, int* buf_canon, char** reason, ++ sldns_pkt_section section, struct module_qstate* qstate); + + /** + * canonical compare for two tree entries +Index: validator/val_utils.c +=================================================================== +--- validator/val_utils.c (revision 4377) ++++ validator/val_utils.c (working copy) +@@ -335,7 +335,8 @@ + enum sec_status + val_verify_rrset(struct module_env* env, struct val_env* ve, + struct ub_packed_rrset_key* rrset, struct ub_packed_rrset_key* keys, +- uint8_t* sigalg, char** reason) ++ uint8_t* sigalg, char** reason, sldns_pkt_section section, ++ struct module_qstate* qstate) + { + enum sec_status sec; + struct packed_rrset_data* d = (struct packed_rrset_data*)rrset-> +@@ -357,7 +358,8 @@ + } + log_nametypeclass(VERB_ALGO, "verify rrset", rrset->rk.dname, + ntohs(rrset->rk.type), ntohs(rrset->rk.rrset_class)); +- sec = dnskeyset_verify_rrset(env, ve, rrset, keys, sigalg, reason); ++ sec = dnskeyset_verify_rrset(env, ve, rrset, keys, sigalg, reason, ++ section, qstate); + verbose(VERB_ALGO, "verify result: %s", sec_status_to_string(sec)); + regional_free_all(env->scratch); + +@@ -390,7 +392,7 @@ + enum sec_status + val_verify_rrset_entry(struct module_env* env, struct val_env* ve, + struct ub_packed_rrset_key* rrset, struct key_entry_key* kkey, +- char** reason) ++ char** reason, sldns_pkt_section section, struct module_qstate* qstate) + { + /* temporary dnskey rrset-key */ + struct ub_packed_rrset_key dnskey; +@@ -403,7 +405,8 @@ + dnskey.rk.dname_len = kkey->namelen; + dnskey.entry.key = &dnskey; + dnskey.entry.data = kd->rrset_data; +- sec = val_verify_rrset(env, ve, rrset, &dnskey, kd->algo, reason); ++ sec = val_verify_rrset(env, ve, rrset, &dnskey, kd->algo, reason, ++ section, qstate); + return sec; + } + +@@ -411,7 +414,8 @@ + static enum sec_status + verify_dnskeys_with_ds_rr(struct module_env* env, struct val_env* ve, + struct ub_packed_rrset_key* dnskey_rrset, +- struct ub_packed_rrset_key* ds_rrset, size_t ds_idx, char** reason) ++ struct ub_packed_rrset_key* ds_rrset, size_t ds_idx, char** reason, ++ struct module_qstate* qstate) + { + enum sec_status sec = sec_status_bogus; + size_t i, num, numchecked = 0, numhashok = 0; +@@ -442,7 +446,7 @@ + /* Otherwise, we have a match! Make sure that the DNSKEY + * verifies *with this key* */ + sec = dnskey_verify_rrset(env, ve, dnskey_rrset, +- dnskey_rrset, i, reason); ++ dnskey_rrset, i, reason, LDNS_SECTION_ANSWER, qstate); + if(sec == sec_status_secure) { + return sec; + } +@@ -478,7 +482,8 @@ + enum sec_status + val_verify_DNSKEY_with_DS(struct module_env* env, struct val_env* ve, + struct ub_packed_rrset_key* dnskey_rrset, +- struct ub_packed_rrset_key* ds_rrset, uint8_t* sigalg, char** reason) ++ struct ub_packed_rrset_key* ds_rrset, uint8_t* sigalg, char** reason, ++ struct module_qstate* qstate) + { + /* as long as this is false, we can consider this DS rrset to be + * equivalent to no DS rrset. */ +@@ -520,7 +525,7 @@ + has_useful_ds = 1; + + sec = verify_dnskeys_with_ds_rr(env, ve, dnskey_rrset, +- ds_rrset, i, reason); ++ ds_rrset, i, reason, qstate); + if(sec == sec_status_secure) { + if(!sigalg || algo_needs_set_secure(&needs, + (uint8_t)ds_get_key_algo(ds_rrset, i))) { +@@ -553,11 +558,12 @@ + struct key_entry_key* + val_verify_new_DNSKEYs(struct regional* region, struct module_env* env, + struct val_env* ve, struct ub_packed_rrset_key* dnskey_rrset, +- struct ub_packed_rrset_key* ds_rrset, int downprot, char** reason) ++ struct ub_packed_rrset_key* ds_rrset, int downprot, char** reason, ++ struct module_qstate* qstate) + { + uint8_t sigalg[ALGO_NEEDS_MAX+1]; + enum sec_status sec = val_verify_DNSKEY_with_DS(env, ve, +- dnskey_rrset, ds_rrset, downprot?sigalg:NULL, reason); ++ dnskey_rrset, ds_rrset, downprot?sigalg:NULL, reason, qstate); + + if(sec == sec_status_secure) { + return key_entry_create_rrset(region, +@@ -579,7 +585,8 @@ + val_verify_DNSKEY_with_TA(struct module_env* env, struct val_env* ve, + struct ub_packed_rrset_key* dnskey_rrset, + struct ub_packed_rrset_key* ta_ds, +- struct ub_packed_rrset_key* ta_dnskey, uint8_t* sigalg, char** reason) ++ struct ub_packed_rrset_key* ta_dnskey, uint8_t* sigalg, char** reason, ++ struct module_qstate* qstate) + { + /* as long as this is false, we can consider this anchor to be + * equivalent to no anchor. */ +@@ -630,7 +637,7 @@ + has_useful_ta = 1; + + sec = verify_dnskeys_with_ds_rr(env, ve, dnskey_rrset, +- ta_ds, i, reason); ++ ta_ds, i, reason, qstate); + if(sec == sec_status_secure) { + if(!sigalg || algo_needs_set_secure(&needs, + (uint8_t)ds_get_key_algo(ta_ds, i))) { +@@ -656,7 +663,7 @@ + has_useful_ta = 1; + + sec = dnskey_verify_rrset(env, ve, dnskey_rrset, +- ta_dnskey, i, reason); ++ ta_dnskey, i, reason, LDNS_SECTION_ANSWER, qstate); + if(sec == sec_status_secure) { + if(!sigalg || algo_needs_set_secure(&needs, + (uint8_t)dnskey_get_algo(ta_dnskey, i))) { +@@ -690,12 +697,12 @@ + struct val_env* ve, struct ub_packed_rrset_key* dnskey_rrset, + struct ub_packed_rrset_key* ta_ds_rrset, + struct ub_packed_rrset_key* ta_dnskey_rrset, int downprot, +- char** reason) ++ char** reason, struct module_qstate* qstate) + { + uint8_t sigalg[ALGO_NEEDS_MAX+1]; + enum sec_status sec = val_verify_DNSKEY_with_TA(env, ve, + dnskey_rrset, ta_ds_rrset, ta_dnskey_rrset, +- downprot?sigalg:NULL, reason); ++ downprot?sigalg:NULL, reason, qstate); + + if(sec == sec_status_secure) { + return key_entry_create_rrset(region, +Index: validator/val_utils.h +=================================================================== +--- validator/val_utils.h (revision 4377) ++++ validator/val_utils.h (working copy) +@@ -42,10 +42,12 @@ + #ifndef VALIDATOR_VAL_UTILS_H + #define VALIDATOR_VAL_UTILS_H + #include "util/data/packed_rrset.h" ++#include "sldns/pkthdr.h" + struct query_info; + struct reply_info; + struct val_env; + struct module_env; ++struct module_qstate; + struct ub_packed_rrset_key; + struct key_entry_key; + struct regional; +@@ -120,11 +122,14 @@ + * @param sigalg: if nonNULL provide downgrade protection otherwise one + * algorithm is enough. Algo list is constructed in here. + * @param reason: reason of failure. Fixed string or alloced in scratch. ++ * @param section: section of packet where this rrset comes from. ++ * @param qstate: qstate with region. + * @return security status of verification. + */ + enum sec_status val_verify_rrset(struct module_env* env, struct val_env* ve, + struct ub_packed_rrset_key* rrset, struct ub_packed_rrset_key* keys, +- uint8_t* sigalg, char** reason); ++ uint8_t* sigalg, char** reason, sldns_pkt_section section, ++ struct module_qstate* qstate); + + /** + * Verify RRset with keys from a keyset. +@@ -133,11 +138,14 @@ + * @param rrset: what to verify + * @param kkey: key_entry to verify with. + * @param reason: reason of failure. Fixed string or alloced in scratch. ++ * @param section: section of packet where this rrset comes from. ++ * @param qstate: qstate with region. + * @return security status of verification. + */ + enum sec_status val_verify_rrset_entry(struct module_env* env, + struct val_env* ve, struct ub_packed_rrset_key* rrset, +- struct key_entry_key* kkey, char** reason); ++ struct key_entry_key* kkey, char** reason, sldns_pkt_section section, ++ struct module_qstate* qstate); + + /** + * Verify DNSKEYs with DS rrset. Like val_verify_new_DNSKEYs but +@@ -150,6 +158,7 @@ + * algorithm is enough. The list of signalled algorithms is returned, + * must have enough space for ALGO_NEEDS_MAX+1. + * @param reason: reason of failure. Fixed string or alloced in scratch. ++ * @param qstate: qstate with region. + * @return: sec_status_secure if a DS matches. + * sec_status_insecure if end of trust (i.e., unknown algorithms). + * sec_status_bogus if it fails. +@@ -156,7 +165,8 @@ + */ + enum sec_status val_verify_DNSKEY_with_DS(struct module_env* env, + struct val_env* ve, struct ub_packed_rrset_key* dnskey_rrset, +- struct ub_packed_rrset_key* ds_rrset, uint8_t* sigalg, char** reason); ++ struct ub_packed_rrset_key* ds_rrset, uint8_t* sigalg, char** reason, ++ struct module_qstate* qstate); + + /** + * Verify DNSKEYs with DS and DNSKEY rrset. Like val_verify_DNSKEY_with_DS +@@ -170,6 +180,7 @@ + * algorithm is enough. The list of signalled algorithms is returned, + * must have enough space for ALGO_NEEDS_MAX+1. + * @param reason: reason of failure. Fixed string or alloced in scratch. ++ * @param qstate: qstate with region. + * @return: sec_status_secure if a DS matches. + * sec_status_insecure if end of trust (i.e., unknown algorithms). + * sec_status_bogus if it fails. +@@ -177,7 +188,8 @@ + enum sec_status val_verify_DNSKEY_with_TA(struct module_env* env, + struct val_env* ve, struct ub_packed_rrset_key* dnskey_rrset, + struct ub_packed_rrset_key* ta_ds, +- struct ub_packed_rrset_key* ta_dnskey, uint8_t* sigalg, char** reason); ++ struct ub_packed_rrset_key* ta_dnskey, uint8_t* sigalg, char** reason, ++ struct module_qstate* qstate); + + /** + * Verify new DNSKEYs with DS rrset. The DS contains hash values that should +@@ -192,6 +204,7 @@ + * @param downprot: if true provide downgrade protection otherwise one + * algorithm is enough. + * @param reason: reason of failure. Fixed string or alloced in scratch. ++ * @param qstate: qstate with region. + * @return a KeyEntry. This will either contain the now trusted + * dnskey_rrset, a "null" key entry indicating that this DS + * rrset/DNSKEY pair indicate an secure end to the island of trust +@@ -205,7 +218,8 @@ + struct key_entry_key* val_verify_new_DNSKEYs(struct regional* region, + struct module_env* env, struct val_env* ve, + struct ub_packed_rrset_key* dnskey_rrset, +- struct ub_packed_rrset_key* ds_rrset, int downprot, char** reason); ++ struct ub_packed_rrset_key* ds_rrset, int downprot, char** reason, ++ struct module_qstate* qstate); + + + /** +@@ -220,6 +234,7 @@ + * @param downprot: if true provide downgrade protection otherwise one + * algorithm is enough. + * @param reason: reason of failure. Fixed string or alloced in scratch. ++ * @param qstate: qstate with region. + * @return a KeyEntry. This will either contain the now trusted + * dnskey_rrset, a "null" key entry indicating that this DS + * rrset/DNSKEY pair indicate an secure end to the island of trust +@@ -235,7 +250,7 @@ + struct ub_packed_rrset_key* dnskey_rrset, + struct ub_packed_rrset_key* ta_ds_rrset, + struct ub_packed_rrset_key* ta_dnskey_rrset, +- int downprot, char** reason); ++ int downprot, char** reason, struct module_qstate* qstate); + + /** + * Determine if DS rrset is usable for validator or not. +@@ -252,7 +267,7 @@ + * the result of a wildcard expansion. If so, return the name of the + * generating wildcard. + * +- * @param rrset The rrset to chedck. ++ * @param rrset The rrset to check. + * @param wc: the wildcard name, if the rrset was synthesized from a wildcard. + * unchanged if not. The wildcard name, without "*." in front, is + * returned. This is a pointer into the rrset owner name. +Index: validator/validator.c +=================================================================== +--- validator/validator.c (revision 4377) ++++ validator/validator.c (working copy) +@@ -572,7 +572,8 @@ + } + + /* Verify the answer rrset */ +- sec = val_verify_rrset_entry(env, ve, s, key_entry, &reason); ++ sec = val_verify_rrset_entry(env, ve, s, key_entry, &reason, ++ LDNS_SECTION_ANSWER, qstate); + /* If the (answer) rrset failed to validate, then this + * message is BAD. */ + if(sec != sec_status_secure) { +@@ -601,7 +602,8 @@ + for(i=chase_reply->an_numrrsets; ian_numrrsets+ + chase_reply->ns_numrrsets; i++) { + s = chase_reply->rrsets[i]; +- sec = val_verify_rrset_entry(env, ve, s, key_entry, &reason); ++ sec = val_verify_rrset_entry(env, ve, s, key_entry, &reason, ++ LDNS_SECTION_AUTHORITY, qstate); + /* If anything in the authority section fails to be secure, + * we have a bad message. */ + if(sec != sec_status_secure) { +@@ -629,7 +631,7 @@ + val_find_rrset_signer(s, &sname, &slen); + if(sname && query_dname_compare(sname, key_entry->name)==0) + (void)val_verify_rrset_entry(env, ve, s, key_entry, +- &reason); ++ &reason, LDNS_SECTION_ADDITIONAL, qstate); + /* the additional section can fail to be secure, + * it is optional, check signature in case we need + * to clean the additional section later. */ +@@ -2484,7 +2486,7 @@ + /* attempt to verify with trust anchor DS and DNSKEY */ + kkey = val_verify_new_DNSKEYs_with_ta(qstate->region, qstate->env, ve, + dnskey_rrset, ta->ds_rrset, ta->dnskey_rrset, downprot, +- &reason); ++ &reason, qstate); + if(!kkey) { + log_err("out of memory: verifying prime TA"); + return NULL; +@@ -2574,7 +2576,7 @@ + /* Verify only returns BOGUS or SECURE. If the rrset is + * bogus, then we are done. */ + sec = val_verify_rrset_entry(qstate->env, ve, ds, +- vq->key_entry, &reason); ++ vq->key_entry, &reason, LDNS_SECTION_ANSWER, qstate); + if(sec != sec_status_secure) { + verbose(VERB_DETAIL, "DS rrset in DS response did " + "not verify"); +@@ -2621,7 +2623,7 @@ + /* Try to prove absence of the DS with NSEC */ + sec = val_nsec_prove_nodata_dsreply( + qstate->env, ve, qinfo, msg->rep, vq->key_entry, +- &proof_ttl, &reason); ++ &proof_ttl, &reason, qstate); + switch(sec) { + case sec_status_secure: + verbose(VERB_DETAIL, "NSEC RRset for the " +@@ -2649,7 +2651,8 @@ + + sec = nsec3_prove_nods(qstate->env, ve, + msg->rep->rrsets + msg->rep->an_numrrsets, +- msg->rep->ns_numrrsets, qinfo, vq->key_entry, &reason); ++ msg->rep->ns_numrrsets, qinfo, vq->key_entry, &reason, ++ qstate); + switch(sec) { + case sec_status_insecure: + /* case insecure also continues to unsigned +@@ -2710,7 +2713,7 @@ + goto return_bogus; + } + sec = val_verify_rrset_entry(qstate->env, ve, cname, +- vq->key_entry, &reason); ++ vq->key_entry, &reason, LDNS_SECTION_ANSWER, qstate); + if(sec == sec_status_secure) { + verbose(VERB_ALGO, "CNAME validated, " + "proof that DS does not exist"); +@@ -2876,7 +2879,7 @@ + } + downprot = qstate->env->cfg->harden_algo_downgrade; + vq->key_entry = val_verify_new_DNSKEYs(qstate->region, qstate->env, +- ve, dnskey, vq->ds_rrset, downprot, &reason); ++ ve, dnskey, vq->ds_rrset, downprot, &reason, qstate); + + if(!vq->key_entry) { + log_err("out of memory in verify new DNSKEYs"); +@@ -2952,7 +2955,8 @@ + } + + if(ta->autr) { +- if(!autr_process_prime(qstate->env, ve, ta, dnskey_rrset)) { ++ if(!autr_process_prime(qstate->env, ve, ta, dnskey_rrset, ++ qstate)) { + /* trust anchor revoked, restart with less anchors */ + vq->state = VAL_INIT_STATE; + vq->trust_anchor_name = NULL; diff -Nru unbound-1.6.7/debian/patches/series unbound-1.6.7/debian/patches/series --- unbound-1.6.7/debian/patches/series 2018-02-15 07:45:35.000000000 +0000 +++ unbound-1.6.7/debian/patches/series 2018-05-28 02:37:08.000000000 +0000 @@ -1 +1,2 @@ debian-changes +CVE-2017-15105.patch