static ldns_dnssec_rrsets * ldns_dnssec_rrsets_new_frm_rr(ldns_rr *rr) { ldns_dnssec_rrsets *new_rrsets; ldns_rr_type rr_type; bool rrsig; new_rrsets = ldns_dnssec_rrsets_new(); 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)); } else { rrsig = false; } if (!rrsig) { new_rrsets->rrs = ldns_dnssec_rrs_new(); new_rrsets->rrs->rr = rr; } else { new_rrsets->signatures = ldns_dnssec_rrs_new(); new_rrsets->signatures->rr = rr; } new_rrsets->type = rr_type; return new_rrsets; }
/* * generic function to get some RRset from a nameserver * and possible some signatures too (that would be the day...) */ ldns_pkt_type get_dnssec_rr(ldns_pkt *p, ldns_rdf *name, ldns_rr_type t, ldns_rr_list **rrlist, ldns_rr_list **sig) { ldns_pkt_type pt = LDNS_PACKET_UNKNOWN; ldns_rr_list *rr = NULL; ldns_rr_list *sigs = NULL; size_t i; if (!p) { if (rrlist) { *rrlist = NULL; } return LDNS_PACKET_UNKNOWN; } pt = ldns_pkt_reply_type(p); if (name) { rr = ldns_pkt_rr_list_by_name_and_type(p, name, t, LDNS_SECTION_ANSWER); if (!rr) { rr = ldns_pkt_rr_list_by_name_and_type(p, name, t, LDNS_SECTION_AUTHORITY); } sigs = ldns_pkt_rr_list_by_name_and_type(p, name, LDNS_RR_TYPE_RRSIG, LDNS_SECTION_ANSWER); if (!sigs) { sigs = ldns_pkt_rr_list_by_name_and_type(p, name, LDNS_RR_TYPE_RRSIG, LDNS_SECTION_AUTHORITY); } } else { /* A DS-referral - get the DS records if they are there */ rr = ldns_pkt_rr_list_by_type(p, t, LDNS_SECTION_AUTHORITY); sigs = ldns_pkt_rr_list_by_type(p, LDNS_RR_TYPE_RRSIG, LDNS_SECTION_AUTHORITY); } if (sig) { *sig = ldns_rr_list_new(); for (i = 0; i < ldns_rr_list_rr_count(sigs); i++) { /* only add the sigs that cover this type */ if (ldns_rdf2rr_type(ldns_rr_rrsig_typecovered(ldns_rr_list_rr(sigs, i))) == t) { ldns_rr_list_push_rr(*sig, ldns_rr_clone(ldns_rr_list_rr(sigs, i))); } } } ldns_rr_list_deep_free(sigs); if (rrlist) { *rrlist = rr; } if (pt == LDNS_PACKET_NXDOMAIN || pt == LDNS_PACKET_NODATA) { return pt; } else { return LDNS_PACKET_ANSWER; } }
ldns_status ldns_dnssec_zone_add_rr(ldns_dnssec_zone *zone, ldns_rr *rr) { ldns_status result = LDNS_STATUS_OK; ldns_dnssec_name *cur_name; ldns_rbnode_t *cur_node; ldns_rr_type type_covered = 0; if (!zone || !rr) { return LDNS_STATUS_ERR; } if (!zone->names) { zone->names = ldns_rbtree_create(ldns_dname_compare_v); if(!zone->names) return LDNS_STATUS_MEM_ERR; } /* we need the original of the hashed name if this is an NSEC3, or an RRSIG that covers an NSEC3 */ if (ldns_rr_get_type(rr) == LDNS_RR_TYPE_RRSIG) { type_covered = ldns_rdf2rr_type(ldns_rr_rrsig_typecovered(rr)); } if (ldns_rr_get_type(rr) == LDNS_RR_TYPE_NSEC3 || type_covered == LDNS_RR_TYPE_NSEC3) { cur_node = ldns_dnssec_zone_find_nsec3_original(zone, rr); if (!cur_node) { return LDNS_STATUS_DNSSEC_NSEC3_ORIGINAL_NOT_FOUND; } } else { cur_node = ldns_rbtree_search(zone->names, ldns_rr_owner(rr)); } if (!cur_node) { /* add */ cur_name = ldns_dnssec_name_new_frm_rr(rr); if(!cur_name) return LDNS_STATUS_MEM_ERR; cur_node = LDNS_MALLOC(ldns_rbnode_t); if(!cur_node) { ldns_dnssec_name_free(cur_name); return LDNS_STATUS_MEM_ERR; } cur_node->key = ldns_rr_owner(rr); cur_node->data = cur_name; (void)ldns_rbtree_insert(zone->names, cur_node); ldns_dnssec_name_make_hashed_name(zone, cur_name, NULL); } else { cur_name = (ldns_dnssec_name *) cur_node->data; result = ldns_dnssec_name_add_rr(cur_name, rr); } if (ldns_rr_get_type(rr) == LDNS_RR_TYPE_SOA) { zone->soa = cur_name; } return result; }
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; }
/** * Read namedb from backup file. * */ ods_status backup_read_namedb(FILE* in, void* zone) { zone_type* z = (zone_type*) zone; denial_type* denial = NULL; rrset_type* rrset = NULL; ods_status result = ODS_STATUS_OK; ldns_rr_type type_covered; ldns_rr* rr = NULL; ldns_rdf* prev = NULL; ldns_rdf* orig = NULL; ldns_rdf* dname = NULL; ldns_status status = LDNS_STATUS_OK; char line[SE_ADFILE_MAXLINE]; char* str = NULL; char* locator = NULL; uint32_t flags = 0; unsigned int l = 0; ods_log_assert(in); ods_log_assert(z); /* $ORIGIN <zone name> */ dname = adapi_get_origin(z); if (!dname) { ods_log_error("[%s] error getting default value for $ORIGIN", backup_str); return ODS_STATUS_ERR; } orig = ldns_rdf_clone(dname); if (!orig) { ods_log_error("[%s] error setting default value for $ORIGIN", backup_str); return ODS_STATUS_ERR; } /* read RRs */ ods_log_debug("[%s] read RRs %s", backup_str, z->name); while ((rr = backup_read_rr(in, z, line, &orig, &prev, &status, &l)) != NULL) { /* check status */ if (status != LDNS_STATUS_OK) { ods_log_error("[%s] error reading RR #%i (%s): %s", backup_str, l, ldns_get_errorstr_by_id(status), line); result = ODS_STATUS_ERR; goto backup_namedb_done; } /* add to the database */ result = adapi_add_rr(z, rr, 1); if (result == ODS_STATUS_UNCHANGED) { ods_log_debug("[%s] skipping RR #%i (duplicate): %s", backup_str, l, line); ldns_rr_free(rr); rr = NULL; result = ODS_STATUS_OK; continue; } else if (result != ODS_STATUS_OK) { ods_log_error("[%s] error adding RR #%i: %s", backup_str, l, line); ldns_rr_free(rr); rr = NULL; goto backup_namedb_done; } } if (result == ODS_STATUS_OK && status != LDNS_STATUS_OK) { ods_log_error("[%s] error reading RR #%i (%s): %s", backup_str, l, ldns_get_errorstr_by_id(status), line); result = ODS_STATUS_ERR; goto backup_namedb_done; } namedb_diff(z->db, 0, 0); /* read NSEC(3)s */ ods_log_debug("[%s] read NSEC(3)s %s", backup_str, z->name); l = 0; while ((rr = backup_read_rr(in, z, line, &orig, &prev, &status, &l)) != NULL) { /* check status */ if (status != LDNS_STATUS_OK) { ods_log_error("[%s] error reading NSEC(3) #%i (%s): %s", backup_str, l, ldns_get_errorstr_by_id(status), line); result = ODS_STATUS_ERR; goto backup_namedb_done; } if (ldns_rr_get_type(rr) != LDNS_RR_TYPE_NSEC && ldns_rr_get_type(rr) != LDNS_RR_TYPE_NSEC3) { ods_log_error("[%s] error NSEC(3) #%i is not NSEC(3): %s", backup_str, l, line); ldns_rr_free(rr); rr = NULL; result = ODS_STATUS_ERR; goto backup_namedb_done; } /* add to the denial chain */ denial = namedb_lookup_denial(z->db, ldns_rr_owner(rr)); if (!denial) { ods_log_error("[%s] error adding NSEC(3) #%i: %s", backup_str, l, line); ldns_rr_free(rr); rr = NULL; result = ODS_STATUS_ERR; goto backup_namedb_done; } denial_add_rr(denial, rr); } if (result == ODS_STATUS_OK && status != LDNS_STATUS_OK) { ods_log_error("[%s] error reading NSEC(3) #%i (%s): %s", backup_str, l, ldns_get_errorstr_by_id(status), line); result = ODS_STATUS_ERR; goto backup_namedb_done; } /* read RRSIGs */ ods_log_debug("[%s] read RRSIGs %s", backup_str, z->name); l = 0; while ((rr = backup_read_rr(in, z, line, &orig, &prev, &status, &l)) != NULL) { /* check status */ if (status != LDNS_STATUS_OK) { ods_log_error("[%s] error reading RRSIG #%i (%s): %s", backup_str, l, ldns_get_errorstr_by_id(status), line); result = ODS_STATUS_ERR; goto backup_namedb_done; } if (ldns_rr_get_type(rr) != LDNS_RR_TYPE_RRSIG) { ods_log_error("[%s] error RRSIG #%i is not RRSIG: %s", backup_str, l, line); ldns_rr_free(rr); rr = NULL; result = ODS_STATUS_ERR; goto backup_namedb_done; } /* read locator and flags */ str = strstr(line, "flags"); if (str) { flags = (uint32_t) atoi(str+6); } str = strstr(line, "locator"); if (str) { locator = replace_space_with_nul(str+8); } /* add signatures */ type_covered = ldns_rdf2rr_type(ldns_rr_rrsig_typecovered(rr)); if (type_covered == LDNS_RR_TYPE_NSEC || type_covered == LDNS_RR_TYPE_NSEC3) { denial = namedb_lookup_denial(z->db, ldns_rr_owner(rr)); if (!denial) { ods_log_error("[%s] error restoring RRSIG #%i (%s): %s", backup_str, l, ldns_get_errorstr_by_id(status), line); ldns_rr_free(rr); rr = NULL; result = ODS_STATUS_ERR; goto backup_namedb_done; } rrset = denial->rrset; } else { rrset = zone_lookup_rrset(z, ldns_rr_owner(rr), type_covered); } if (!rrset || !rrset_add_rrsig(rrset, rr, locator, flags)) { ods_log_error("[%s] error restoring RRSIG #%i (%s): %s", backup_str, l, ldns_get_errorstr_by_id(status), line); ldns_rr_free(rr); rr = NULL; result = ODS_STATUS_ERR; goto backup_namedb_done; } else { rrset->needs_signing = 0; } } if (result == ODS_STATUS_OK && status != LDNS_STATUS_OK) { ods_log_error("[%s] error reading RRSIG #%i (%s): %s", backup_str, l, ldns_get_errorstr_by_id(status), line); result = ODS_STATUS_ERR; } backup_namedb_done: if (orig) { ldns_rdf_deep_free(orig); orig = NULL; } if (prev) { ldns_rdf_deep_free(prev); prev = NULL; } return result; }
static bool rr_is_rrsig_covering(ldns_rr* rr, ldns_rr_type t) { return ldns_rr_get_type(rr) == LDNS_RR_TYPE_RRSIG && ldns_rdf2rr_type(ldns_rr_rrsig_typecovered(rr)) == t; }
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; }