ldns_status ldns_dnssec_rrs_add_rr(ldns_dnssec_rrs *rrs, ldns_rr *rr) { int cmp; ldns_dnssec_rrs *new_rrs; if (!rrs || !rr) { return LDNS_STATUS_ERR; } /* this could be done more efficiently; name and type should already be equal */ cmp = ldns_rr_compare(rrs->rr, rr); /* should we error on equal? */ if (cmp <= 0) { if (rrs->next) { return ldns_dnssec_rrs_add_rr(rrs->next, rr); } else { new_rrs = ldns_dnssec_rrs_new(); new_rrs->rr = rr; rrs->next = new_rrs; } } else if (cmp > 0) { /* put the current old rr in the new next, put the new rr in the current container */ new_rrs = ldns_dnssec_rrs_new(); new_rrs->rr = rrs->rr; new_rrs->next = rrs->next; rrs->rr = rr; rrs->next = new_rrs; } return LDNS_STATUS_OK; }
ldns_status ldns_dnssec_name_add_rr(ldns_dnssec_name *name, ldns_rr *rr) { ldns_status result = LDNS_STATUS_OK; ldns_rr_type rr_type; ldns_rr_type typecovered = 0; /* special handling for NSEC3 and NSECX covering RRSIGS */ if (!name || !rr) { return LDNS_STATUS_ERR; } rr_type = ldns_rr_get_type(rr); if (rr_type == LDNS_RR_TYPE_RRSIG) { typecovered = ldns_rdf2rr_type(ldns_rr_rrsig_typecovered(rr)); } if (rr_type == LDNS_RR_TYPE_NSEC || rr_type == LDNS_RR_TYPE_NSEC3) { /* XX check if is already set (and error?) */ name->nsec = rr; } else if (typecovered == LDNS_RR_TYPE_NSEC || typecovered == LDNS_RR_TYPE_NSEC3) { if (name->nsec_signatures) { result = ldns_dnssec_rrs_add_rr(name->nsec_signatures, rr); } else { name->nsec_signatures = ldns_dnssec_rrs_new(); name->nsec_signatures->rr = rr; } } else { /* it's a 'normal' RR, add it to the right rrset */ if (name->rrsets) { result = ldns_dnssec_rrsets_add_rr(name->rrsets, rr); } else { name->rrsets = ldns_dnssec_rrsets_new(); result = ldns_dnssec_rrsets_add_rr(name->rrsets, rr); } } return result; }
ldns_status ldns_dnssec_zone_create_rrsigs(ldns_dnssec_zone *zone, ldns_rr_list *new_rrs, ldns_key_list *key_list, int (*func)(ldns_rr *, void*), void *arg) { ldns_status result = LDNS_STATUS_OK; ldns_rbnode_t *cur_node; ldns_rr_list *rr_list; ldns_dnssec_name *cur_name; ldns_dnssec_rrsets *cur_rrset; ldns_dnssec_rrs *cur_rr; ldns_rr_list *siglist; size_t i; ldns_rr_list *pubkey_list = ldns_rr_list_new(); zone = zone; new_rrs = new_rrs; key_list = key_list; for (i = 0; i<ldns_key_list_key_count(key_list); i++) { ldns_rr_list_push_rr(pubkey_list, ldns_key2rr(ldns_key_list_key(key_list, i))); } /* TODO: callback to see is list should be signed */ /* TODO: remove 'old' signatures from signature list */ cur_node = ldns_rbtree_first(zone->names); while (cur_node != LDNS_RBTREE_NULL) { cur_name = (ldns_dnssec_name *) cur_node->data; if (!cur_name->is_glue) { cur_rrset = cur_name->rrsets; while (cur_rrset) { /* reset keys to use */ ldns_key_list_set_use(key_list, true); /* walk through old sigs, remove the old, and mark which keys (not) to use) */ cur_rrset->signatures = ldns_dnssec_remove_signatures(cur_rrset->signatures, key_list, func, arg); /* TODO: just set count to zero? */ rr_list = ldns_rr_list_new(); cur_rr = cur_rrset->rrs; while (cur_rr) { ldns_rr_list_push_rr(rr_list, cur_rr->rr); cur_rr = cur_rr->next; } /* only sign non-delegation RRsets */ /* (glue should have been marked earlier) */ if ((ldns_rr_list_type(rr_list) != LDNS_RR_TYPE_NS || ldns_dname_compare(ldns_rr_list_owner(rr_list), zone->soa->name) == 0) && /* OK, there is also the possibility that the record * is glue, but at the same owner name as other records that * are not NS nor A/AAAA. Bleh, our current data structure * doesn't really support that... */ !((ldns_rr_list_type(rr_list) == LDNS_RR_TYPE_A || ldns_rr_list_type(rr_list) == LDNS_RR_TYPE_AAAA) && !ldns_dname_compare(ldns_rr_list_owner(rr_list), zone->soa->name) == 0 && ldns_dnssec_zone_find_rrset(zone, ldns_rr_list_owner(rr_list), LDNS_RR_TYPE_NS) )) { siglist = ldns_sign_public(rr_list, key_list); for (i = 0; i < ldns_rr_list_rr_count(siglist); i++) { if (cur_rrset->signatures) { ldns_dnssec_rrs_add_rr(cur_rrset->signatures, ldns_rr_list_rr(siglist, i)); } else { cur_rrset->signatures = ldns_dnssec_rrs_new(); cur_rrset->signatures->rr = ldns_rr_list_rr(siglist, i); ldns_rr_list_push_rr(new_rrs, ldns_rr_list_rr(siglist, i)); } } ldns_rr_list_free(siglist); } ldns_rr_list_free(rr_list); cur_rrset = cur_rrset->next; } /* sign the nsec */ cur_name->nsec_signatures = ldns_dnssec_remove_signatures(cur_name->nsec_signatures, key_list, func, arg); rr_list = ldns_rr_list_new(); ldns_rr_list_push_rr(rr_list, cur_name->nsec); siglist = ldns_sign_public(rr_list, key_list); for (i = 0; i < ldns_rr_list_rr_count(siglist); i++) { if (cur_name->nsec_signatures) { ldns_dnssec_rrs_add_rr(cur_name->nsec_signatures, ldns_rr_list_rr(siglist, i)); } else { cur_name->nsec_signatures = ldns_dnssec_rrs_new(); cur_name->nsec_signatures->rr = ldns_rr_list_rr(siglist, i); ldns_rr_list_push_rr(new_rrs, ldns_rr_list_rr(siglist, i)); } } ldns_rr_list_free(siglist); ldns_rr_list_free(rr_list); } cur_node = ldns_rbtree_next(cur_node); } ldns_rr_list_deep_free(pubkey_list); return result; }
ldns_status ldns_dnssec_rrsets_add_rr(ldns_dnssec_rrsets *rrsets, ldns_rr *rr) { ldns_dnssec_rrsets *new_rrsets; ldns_rr_type rr_type; bool rrsig = false; ldns_status result = LDNS_STATUS_OK; if (!rrsets || !rr) { return LDNS_STATUS_ERR; } rr_type = ldns_rr_get_type(rr); if (rr_type == LDNS_RR_TYPE_RRSIG) { rrsig = true; rr_type = ldns_rdf2rr_type(ldns_rr_rrsig_typecovered(rr)); } if (!rrsets->rrs && rrsets->type == 0 && !rrsets->signatures) { if (!rrsig) { rrsets->rrs = ldns_dnssec_rrs_new(); rrsets->rrs->rr = rr; rrsets->type = rr_type; } else { rrsets->signatures = ldns_dnssec_rrs_new(); rrsets->signatures->rr = rr; rrsets->type = rr_type; } return LDNS_STATUS_OK; } if (rr_type > ldns_dnssec_rrsets_type(rrsets)) { if (rrsets->next) { result = ldns_dnssec_rrsets_add_rr(rrsets->next, rr); } else { new_rrsets = ldns_dnssec_rrsets_new_frm_rr(rr); rrsets->next = new_rrsets; } } else if (rr_type < ldns_dnssec_rrsets_type(rrsets)) { /* move the current one into the new next, replace field of current with data from new rr */ new_rrsets = ldns_dnssec_rrsets_new(); new_rrsets->rrs = rrsets->rrs; new_rrsets->type = rrsets->type; new_rrsets->signatures = rrsets->signatures; new_rrsets->next = rrsets->next; if (!rrsig) { rrsets->rrs = ldns_dnssec_rrs_new(); rrsets->rrs->rr = rr; rrsets->signatures = NULL; } else { rrsets->rrs = NULL; rrsets->signatures = ldns_dnssec_rrs_new(); rrsets->signatures->rr = rr; } rrsets->type = rr_type; rrsets->next = new_rrsets; } else { /* equal, add to current rrsets */ if (rrsig) { if (rrsets->signatures) { result = ldns_dnssec_rrs_add_rr(rrsets->signatures, rr); } else { rrsets->signatures = ldns_dnssec_rrs_new(); rrsets->signatures->rr = rr; } } else { if (rrsets->rrs) { result = ldns_dnssec_rrs_add_rr(rrsets->rrs, rr); } else { rrsets->rrs = ldns_dnssec_rrs_new(); rrsets->rrs->rr = rr; } } } return result; }
ldns_status ldns_dnssec_name_add_rr(ldns_dnssec_name *name, ldns_rr *rr) { ldns_status result = LDNS_STATUS_OK; ldns_rdf *name_name; bool hashed_name = false; ldns_rr_type rr_type; ldns_rr_type typecovered = 0; /* special handling for NSEC3 and NSECX covering RRSIGS */ if (!name || !rr) { return LDNS_STATUS_ERR; } rr_type = ldns_rr_get_type(rr); if (rr_type == LDNS_RR_TYPE_RRSIG) { typecovered = ldns_rdf2rr_type(ldns_rr_rrsig_typecovered(rr)); } #ifdef HAVE_SSL if (rr_type == LDNS_RR_TYPE_NSEC3 || typecovered == LDNS_RR_TYPE_NSEC3) { name_name = ldns_nsec3_hash_name_frm_nsec3(rr, ldns_dnssec_name_name(name)); hashed_name = true; } else { name_name = ldns_dnssec_name_name(name); } #else name_name = ldns_dnssec_name_name(name); #endif /* HAVE_SSL */ if (rr_type == LDNS_RR_TYPE_NSEC || rr_type == LDNS_RR_TYPE_NSEC3) { /* XX check if is already set (and error?) */ name->nsec = rr; } else if (typecovered == LDNS_RR_TYPE_NSEC || typecovered == LDNS_RR_TYPE_NSEC3) { if (name->nsec_signatures) { result = ldns_dnssec_rrs_add_rr(name->nsec_signatures, rr); } else { name->nsec_signatures = ldns_dnssec_rrs_new(); name->nsec_signatures->rr = rr; } } else { /* it's a 'normal' RR, add it to the right rrset */ if (name->rrsets) { result = ldns_dnssec_rrsets_add_rr(name->rrsets, rr); } else { name->rrsets = ldns_dnssec_rrsets_new(); result = ldns_dnssec_rrsets_add_rr(name->rrsets, rr); } } if (hashed_name) { ldns_rdf_deep_free(name_name); } return result; }
ldns_status ldns_dnssec_zone_create_rrsigs_flg( ldns_dnssec_zone *zone , ldns_rr_list *new_rrs , ldns_key_list *key_list , int (*func)(ldns_rr *, void*) , void *arg , int flags ) { ldns_status result = LDNS_STATUS_OK; ldns_rbnode_t *cur_node; ldns_rr_list *rr_list; ldns_dnssec_name *cur_name; ldns_dnssec_rrsets *cur_rrset; ldns_dnssec_rrs *cur_rr; ldns_rr_list *siglist; size_t i; int on_delegation_point = 0; /* handle partially occluded names */ ldns_rr_list *pubkey_list = ldns_rr_list_new(); for (i = 0; i<ldns_key_list_key_count(key_list); i++) { ldns_rr_list_push_rr( pubkey_list , ldns_key2rr(ldns_key_list_key( key_list, i)) ); } /* TODO: callback to see is list should be signed */ /* TODO: remove 'old' signatures from signature list */ cur_node = ldns_rbtree_first(zone->names); while (cur_node != LDNS_RBTREE_NULL) { cur_name = (ldns_dnssec_name *) cur_node->data; if (!cur_name->is_glue) { on_delegation_point = ldns_dnssec_rrsets_contains_type( cur_name->rrsets, LDNS_RR_TYPE_NS) && !ldns_dnssec_rrsets_contains_type( cur_name->rrsets, LDNS_RR_TYPE_SOA); cur_rrset = cur_name->rrsets; while (cur_rrset) { /* reset keys to use */ ldns_key_list_set_use(key_list, true); /* walk through old sigs, remove the old, and mark which keys (not) to use) */ cur_rrset->signatures = ldns_dnssec_remove_signatures(cur_rrset->signatures, key_list, func, arg); if(!(flags&LDNS_SIGN_DNSKEY_WITH_ZSK) && cur_rrset->type == LDNS_RR_TYPE_DNSKEY) ldns_key_list_filter_for_dnskey(key_list); if(cur_rrset->type != LDNS_RR_TYPE_DNSKEY) ldns_key_list_filter_for_non_dnskey(key_list); /* TODO: just set count to zero? */ rr_list = ldns_rr_list_new(); cur_rr = cur_rrset->rrs; while (cur_rr) { ldns_rr_list_push_rr(rr_list, cur_rr->rr); cur_rr = cur_rr->next; } /* only sign non-delegation RRsets */ /* (glue should have been marked earlier, * except on the delegation points itself) */ if (!on_delegation_point || ldns_rr_list_type(rr_list) == LDNS_RR_TYPE_DS || ldns_rr_list_type(rr_list) == LDNS_RR_TYPE_NSEC || ldns_rr_list_type(rr_list) == LDNS_RR_TYPE_NSEC3) { siglist = ldns_sign_public(rr_list, key_list); for (i = 0; i < ldns_rr_list_rr_count(siglist); i++) { if (cur_rrset->signatures) { result = ldns_dnssec_rrs_add_rr(cur_rrset->signatures, ldns_rr_list_rr(siglist, i)); } else { cur_rrset->signatures = ldns_dnssec_rrs_new(); cur_rrset->signatures->rr = ldns_rr_list_rr(siglist, i); } if (new_rrs) { ldns_rr_list_push_rr(new_rrs, ldns_rr_list_rr(siglist, i)); } } ldns_rr_list_free(siglist); } ldns_rr_list_free(rr_list); cur_rrset = cur_rrset->next; } /* sign the nsec */ ldns_key_list_set_use(key_list, true); cur_name->nsec_signatures = ldns_dnssec_remove_signatures(cur_name->nsec_signatures, key_list, func, arg); ldns_key_list_filter_for_non_dnskey(key_list); rr_list = ldns_rr_list_new(); ldns_rr_list_push_rr(rr_list, cur_name->nsec); siglist = ldns_sign_public(rr_list, key_list); for (i = 0; i < ldns_rr_list_rr_count(siglist); i++) { if (cur_name->nsec_signatures) { result = ldns_dnssec_rrs_add_rr(cur_name->nsec_signatures, ldns_rr_list_rr(siglist, i)); } else { cur_name->nsec_signatures = ldns_dnssec_rrs_new(); cur_name->nsec_signatures->rr = ldns_rr_list_rr(siglist, i); } if (new_rrs) { ldns_rr_list_push_rr(new_rrs, ldns_rr_list_rr(siglist, i)); } } ldns_rr_list_free(siglist); ldns_rr_list_free(rr_list); } cur_node = ldns_rbtree_next(cur_node); } ldns_rr_list_deep_free(pubkey_list); return result; }