/** * This routine adds a new RR to a trust anchor. The trust anchor may not * exist yet, and is created if not. The RR can be DS or DNSKEY. * This routine will also remove duplicates; storing them only once. * @param anchors: anchor storage. * @param name: name of trust anchor (wireformat) * @param type: type or RR * @param dclass: class of RR * @param rdata: rdata wireformat, starting with rdlength. * If NULL, nothing is stored, but an entry is created. * @param rdata_len: length of rdata including rdlength. * @return: NULL on error, else the trust anchor. */ static struct trust_anchor* anchor_store_new_key(struct val_anchors* anchors, uint8_t* name, uint16_t type, uint16_t dclass, uint8_t* rdata, size_t rdata_len) { struct ta_key* k; struct trust_anchor* ta; int namelabs; size_t namelen; namelabs = dname_count_size_labels(name, &namelen); if(type != LDNS_RR_TYPE_DS && type != LDNS_RR_TYPE_DNSKEY) { log_err("Bad type for trust anchor"); return 0; } /* lookup or create trustanchor */ ta = anchor_find(anchors, name, namelabs, namelen, dclass); if(!ta) { ta = anchor_new_ta(anchors, name, namelabs, namelen, dclass); if(!ta) return NULL; lock_basic_lock(&ta->lock); } if(!rdata) { lock_basic_unlock(&ta->lock); return ta; } /* look for duplicates */ if(anchor_find_key(ta, rdata, rdata_len, type)) { lock_basic_unlock(&ta->lock); return ta; } k = anchor_new_ta_key(anchors, rdata, rdata_len, type); if(!k) { lock_basic_unlock(&ta->lock); return NULL; } /* add new key */ if(type == LDNS_RR_TYPE_DS) ta->numDS++; else ta->numDNSKEY++; k->next = ta->keylist; ta->keylist = k; lock_basic_unlock(&ta->lock); return ta; }
int anchor_has_keytag(struct val_anchors* anchors, uint8_t* name, int namelabs, size_t namelen, uint16_t dclass, uint16_t keytag) { uint16_t* taglist; uint16_t* tl; size_t numtag, i; struct trust_anchor* anchor = anchor_find(anchors, name, namelabs, namelen, dclass); if(!anchor) return 0; if(!anchor->numDS && !anchor->numDNSKEY) { lock_basic_unlock(&anchor->lock); return 0; } taglist = calloc(anchor->numDS + anchor->numDNSKEY, sizeof(*taglist)); if(!taglist) { lock_basic_unlock(&anchor->lock); return 0; } numtag = anchor_list_keytags(anchor, taglist, anchor->numDS+anchor->numDNSKEY); lock_basic_unlock(&anchor->lock); if(!numtag) { free(taglist); return 0; } tl = taglist; for(i=0; i<numtag; i++) { if(*tl == keytag) { free(taglist); return 1; } tl++; } free(taglist); return 0; }
int iter_indicates_dnssec(struct module_env* env, struct delegpt* dp, struct dns_msg* msg, uint16_t dclass) { struct trust_anchor* a; /* information not available, !env->anchors can be common */ if(!env || !env->anchors || !dp || !dp->name) return 0; /* a trust anchor exists with this name, RRSIGs expected */ if((a=anchor_find(env->anchors, dp->name, dp->namelabs, dp->namelen, dclass))) { lock_basic_unlock(&a->lock); return 1; } /* see if DS rrset was given, in AUTH section */ if(msg && msg->rep && reply_find_rrset_section_ns(msg->rep, dp->name, dp->namelen, LDNS_RR_TYPE_DS, dclass)) return 1; /* look in key cache */ if(env->key_cache) { struct key_entry_key* kk = key_cache_obtain(env->key_cache, dp->name, dp->namelen, dclass, env->scratch, *env->now); if(kk) { if(query_dname_compare(kk->name, dp->name) == 0) { if(key_entry_isgood(kk) || key_entry_isbad(kk)) { regional_free_all(env->scratch); return 1; } else if(key_entry_isnull(kk)) { regional_free_all(env->scratch); return 0; } } regional_free_all(env->scratch); } } return 0; }