/** see if the reply has signed NSEC records and return the signer */ static uint8_t* reply_nsec_signer(struct reply_info* rep, size_t* signer_len, uint16_t* dclass) { size_t i; struct packed_rrset_data* d; uint8_t* s; for(i=rep->an_numrrsets; i< rep->an_numrrsets+rep->ns_numrrsets; i++){ if(ntohs(rep->rrsets[i]->rk.type) == LDNS_RR_TYPE_NSEC || ntohs(rep->rrsets[i]->rk.type) == LDNS_RR_TYPE_NSEC3) { d = (struct packed_rrset_data*)rep->rrsets[i]-> entry.data; /* return first signer name of first NSEC */ if(d->rrsig_count != 0) { val_find_rrset_signer(rep->rrsets[i], &s, signer_len); if(s && *signer_len) { *dclass = ntohs(rep->rrsets[i]-> rk.rrset_class); return s; } } } } return 0; }
int iter_ds_toolow(struct dns_msg* msg, struct delegpt* dp) { /* if for query example.com, there is example.com SOA or a subdomain * of example.com, then we are too low and need to fetch NS. */ size_t i; /* if we have a DNAME or CNAME we are probably wrong */ /* if we have a qtype DS in the answer section, its fine */ for(i=0; i < msg->rep->an_numrrsets; i++) { struct ub_packed_rrset_key* s = msg->rep->rrsets[i]; if(ntohs(s->rk.type) == LDNS_RR_TYPE_DNAME || ntohs(s->rk.type) == LDNS_RR_TYPE_CNAME) { /* not the right answer, maybe too low, check the * RRSIG signer name (if there is any) for a hint * that it is from the dp zone anyway */ uint8_t* sname; size_t slen; val_find_rrset_signer(s, &sname, &slen); if(sname && query_dname_compare(dp->name, sname)==0) return 0; /* it is fine, from the right dp */ return 1; } if(ntohs(s->rk.type) == LDNS_RR_TYPE_DS) return 0; /* fine, we have a DS record */ } for(i=msg->rep->an_numrrsets; i < msg->rep->an_numrrsets + msg->rep->ns_numrrsets; i++) { struct ub_packed_rrset_key* s = msg->rep->rrsets[i]; if(ntohs(s->rk.type) == LDNS_RR_TYPE_SOA) { if(dname_subdomain_c(s->rk.dname, msg->qinfo.qname)) return 1; /* point is too low */ if(query_dname_compare(s->rk.dname, dp->name)==0) return 0; /* right dp */ } if(ntohs(s->rk.type) == LDNS_RR_TYPE_NSEC || ntohs(s->rk.type) == LDNS_RR_TYPE_NSEC3) { uint8_t* sname; size_t slen; val_find_rrset_signer(s, &sname, &slen); if(sname && query_dname_compare(dp->name, sname)==0) return 0; /* it is fine, from the right dp */ return 1; } } /* we do not know */ return 1; }
void val_find_signer(enum val_classification subtype, struct query_info* qinf, struct reply_info* rep, size_t skip, uint8_t** signer_name, size_t* signer_len) { size_t i; if(subtype == VAL_CLASS_POSITIVE || subtype == VAL_CLASS_ANY) { /* check for the answer rrset */ for(i=skip; i<rep->an_numrrsets; i++) { if(query_dname_compare(qinf->qname, rep->rrsets[i]->rk.dname) == 0) { val_find_rrset_signer(rep->rrsets[i], signer_name, signer_len); return; } } *signer_name = NULL; *signer_len = 0; } else if(subtype == VAL_CLASS_CNAME) { /* check for the first signed cname/dname rrset */ for(i=skip; i<rep->an_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_DNAME) break; /* only check CNAME after a DNAME */ } *signer_name = NULL; *signer_len = 0; } else if(subtype == VAL_CLASS_NAMEERROR || subtype == VAL_CLASS_NODATA) { /*Check to see if the AUTH section NSEC record(s) have rrsigs*/ for(i=rep->an_numrrsets; i< rep->an_numrrsets+rep->ns_numrrsets; i++) { if(ntohs(rep->rrsets[i]->rk.type) == LDNS_RR_TYPE_NSEC || ntohs(rep->rrsets[i]->rk.type) == LDNS_RR_TYPE_NSEC3) { val_find_rrset_signer(rep->rrsets[i], signer_name, signer_len); return; } } } else if(subtype == VAL_CLASS_CNAMENOANSWER) { /* find closest superdomain signer name in authority section * NSEC and NSEC3s */ int matchcount = 0; *signer_name = NULL; *signer_len = 0; for(i=rep->an_numrrsets; i<rep->an_numrrsets+rep-> ns_numrrsets; i++) { if(ntohs(rep->rrsets[i]->rk.type) == LDNS_RR_TYPE_NSEC || ntohs(rep->rrsets[i]->rk.type) == LDNS_RR_TYPE_NSEC3) { val_find_best_signer(rep->rrsets[i], qinf, signer_name, signer_len, &matchcount); } } } else if(subtype == VAL_CLASS_REFERRAL) { /* find keys for the item at skip */ if(skip < rep->rrset_count) { val_find_rrset_signer(rep->rrsets[skip], signer_name, signer_len); return; } *signer_name = NULL; *signer_len = 0; } else { verbose(VERB_QUERY, "find_signer: could not find signer name" " for unknown type response"); *signer_name = NULL; *signer_len = 0; } }