From: W.C.A. Wijngaards Date: Thu, 6 Jun 2024 13:28:21 +0000 (+0200) Subject: - Fix validation for repeated use of a DNAME record. X-Git-Tag: release-1.21.0rc1~59 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=4c2da2b979f502bb95d744709383422f3ab925ba;p=thirdparty%2Funbound.git - Fix validation for repeated use of a DNAME record. --- diff --git a/doc/Changelog b/doc/Changelog index 4d7a8fdee..3fb5447dc 100644 --- a/doc/Changelog +++ b/doc/Changelog @@ -1,6 +1,7 @@ 6 June 2024: Wouter - Fix memory leak in setup of dsa sig. - Fix typos for 'the the' in text. + - Fix validation for repeated use of a DNAME record. 4 June 2024: Yorgos - Merge #1080: AddressSanitizer detection in tdir tests and memory leak diff --git a/validator/val_utils.c b/validator/val_utils.c index a7db41dad..add6d9bba 100644 --- a/validator/val_utils.c +++ b/validator/val_utils.c @@ -240,6 +240,26 @@ val_find_best_signer(struct ub_packed_rrset_key* rrset, } } +/** Detect if the, unsigned, CNAME is under a previous DNAME RR in the + * message, and thus it was generated from that previous DNAME. + */ +static int +cname_under_previous_dname(struct reply_info* rep, size_t cname_idx, + size_t* ret) +{ + size_t i; + for(i=0; irrsets[i]->rk.type) == LDNS_RR_TYPE_DNAME && + dname_strict_subdomain_c(rep->rrsets[cname_idx]-> + rk.dname, rep->rrsets[i]->rk.dname)) { + *ret = i; + return 1; + } + } + *ret = 0; + return 0; +} + void val_find_signer(enum val_classification subtype, struct query_info* qinf, struct reply_info* rep, size_t skip, uint8_t** signer_name, @@ -275,12 +295,19 @@ val_find_signer(enum val_classification subtype, struct query_info* qinf, *signer_name = NULL; *signer_len = 0; } else if(subtype == VAL_CLASS_CNAME) { + size_t j; /* check for the first signed cname/dname rrset */ for(i=skip; ian_numrrsets; i++) { val_find_rrset_signer(rep->rrsets[i], signer_name, signer_len); if(*signer_name) return; + if(ntohs(rep->rrsets[i]->rk.type) == LDNS_RR_TYPE_CNAME + && cname_under_previous_dname(rep, i, &j)) { + val_find_rrset_signer(rep->rrsets[j], + signer_name, signer_len); + return; + } if(ntohs(rep->rrsets[i]->rk.type) != LDNS_RR_TYPE_DNAME) break; /* only check CNAME after a DNAME */ } @@ -979,7 +1006,7 @@ void val_fill_reply(struct reply_info* chase, struct reply_info* orig, size_t skip, uint8_t* name, size_t len, uint8_t* signer) { - size_t i; + size_t i, j; int seen_dname = 0; chase->rrset_count = 0; chase->an_numrrsets = 0; @@ -1002,8 +1029,15 @@ val_fill_reply(struct reply_info* chase, struct reply_info* orig, LDNS_RR_TYPE_DNAME) { seen_dname = 1; } + } else if(ntohs(orig->rrsets[i]->rk.type) == LDNS_RR_TYPE_CNAME + && ((struct packed_rrset_data*)orig->rrsets[i]-> + entry.data)->rrsig_count == 0 && + cname_under_previous_dname(orig, i, &j) && + rrset_has_signer(orig->rrsets[j], name, len)) { + chase->rrsets[chase->an_numrrsets++] = orig->rrsets[j]; + chase->rrsets[chase->an_numrrsets++] = orig->rrsets[i]; } - } + } /* AUTHORITY section */ for(i = (skip > orig->an_numrrsets)?skip:orig->an_numrrsets; ian_numrrsets+orig->ns_numrrsets; diff --git a/validator/validator.c b/validator/validator.c index 3cf291658..ec656db12 100644 --- a/validator/validator.c +++ b/validator/validator.c @@ -275,7 +275,7 @@ val_new_getmsg(struct module_qstate* qstate, struct val_qstate* vq) return NULL; /* protect against integer overflow */ vq->chase_reply->rrsets = regional_alloc_init(qstate->region, vq->orig_msg->rep->rrsets, sizeof(struct ub_packed_rrset_key*) - * vq->orig_msg->rep->rrset_count); + * (vq->orig_msg->rep->rrset_count + vq->orig_msg->rep->an_numrrsets /* for extra DNAME records for unsigned CNAME repetitions*/) ); if(!vq->chase_reply->rrsets) return NULL; vq->rrset_skip = 0;