/* special case were there was a wildcard expansion match, the exact match must be disproven */ ldns_status ldns_verify_denial_wildcard(ldns_pkt *pkt, ldns_rdf *name, ldns_rr_type type, ldns_rr_list **nsec_rrs, ldns_rr_list **nsec_rr_sigs) { ldns_rdf *nsec3_ce = NULL; ldns_rr *nsec3_ex = NULL; ldns_rdf *wildcard_name = NULL; ldns_rdf *nsec3_wc_ce = NULL; ldns_rr *nsec3_wc_ex = NULL; ldns_rdf *chopped_dname = NULL; ldns_rr_list *nsecs; ldns_status result = LDNS_STATUS_ERR; nsecs = ldns_pkt_rr_list_by_type(pkt, LDNS_RR_TYPE_NSEC3, LDNS_SECTION_ANY_NOQUESTION); if (nsecs) { wildcard_name = ldns_dname_new_frm_str("*"); chopped_dname = ldns_dname_left_chop(name); result = ldns_dname_cat(wildcard_name, chopped_dname); ldns_rdf_deep_free(chopped_dname); nsec3_ex = ldns_nsec3_exact_match(name, type, nsecs); nsec3_ce = ldns_nsec3_closest_encloser(name, type, nsecs); nsec3_wc_ce = ldns_nsec3_closest_encloser(wildcard_name, type, nsecs); nsec3_wc_ex = ldns_nsec3_exact_match(wildcard_name, type, nsecs); if (nsec3_ex) { if (verbosity >= 3) { printf(";; Error, exact match for for name found, but should not exist (draft -07 section 8.8)\n"); } result = LDNS_STATUS_NSEC3_ERR; } else if (!nsec3_ce) { if (verbosity >= 3) { printf(";; Error, closest encloser for exact match missing in wildcard response (draft -07 section 8.8)\n"); } result = LDNS_STATUS_NSEC3_ERR; /* } else if (!nsec3_wc_ex) { printf(";; Error, no wildcard nsec3 match: "); ldns_rdf_print(stdout, wildcard_name); printf(" (draft -07 section 8.8)\n"); result = LDNS_STATUS_NSEC3_ERR; */ /* } else if (!nsec */ } else { if (verbosity >= 3) { printf(";; wilcard expansion proven\n"); } result = LDNS_STATUS_OK; } } else { if (verbosity >= 3) { printf(";; Error: no NSEC or NSEC3 records in answer\n"); } result = LDNS_STATUS_CRYPTO_NO_RRSIG; } if (nsecs && nsec_rrs && nsec_rr_sigs) { (void) get_dnssec_rr(pkt, ldns_rr_owner(ldns_rr_list_rr(nsecs, 0)), LDNS_RR_TYPE_NSEC3, nsec_rrs, nsec_rr_sigs); } return result; }
void covertests(ldns_rr_list *list, ldns_rdf *qname) { size_t i; ldns_rdf *smaller = qname; ldns_rdf *wcard = ldns_dname_new_frm_str("*"); for(i=0; i<ldns_dname_label_count(qname)+1; ++i) { check_cover(list, smaller); ldns_rdf* wcardchild = ldns_dname_cat_clone(wcard, smaller); check_cover(list, wcardchild); smaller = ldns_dname_left_chop(smaller); } /* check covers by weird names */ if(0) { check_cover(list, ldns_dname_new_frm_str("x.bar.example.")); check_cover(list, ldns_dname_new_frm_str("bar.example.")); } }
ldns_status ldns_dnssec_zone_mark_glue(ldns_dnssec_zone *zone) { ldns_rbnode_t *cur_node; ldns_dnssec_name *cur_name; ldns_rdf *cur_owner, *cur_parent; cur_node = ldns_rbtree_first(zone->names); while (cur_node != LDNS_RBTREE_NULL) { cur_name = (ldns_dnssec_name *) cur_node->data; cur_node = ldns_rbtree_next(cur_node); if (ldns_dnssec_name_has_only_a(cur_name)) { /* assume glue XXX check for zone cur */ cur_owner = ldns_rdf_clone(ldns_rr_owner( cur_name->rrsets->rrs->rr)); while (ldns_dname_label_count(cur_owner) > ldns_dname_label_count(zone->soa->name)) { if (ldns_dnssec_zone_find_rrset(zone, cur_owner, LDNS_RR_TYPE_NS)) { /* fprintf(stderr, "[XX] Marking as glue: "); ldns_rdf_print(stderr, cur_name->name); fprintf(stderr, "\n"); */ cur_name->is_glue = true; } cur_parent = ldns_dname_left_chop(cur_owner); ldns_rdf_deep_free(cur_owner); cur_owner = cur_parent; } ldns_rdf_deep_free(cur_owner); } } return LDNS_STATUS_OK; }
void check_cover(ldns_rr_list *list, ldns_rdf *qname) { ldns_status status; size_t i; if(check_done(qname)) return; for(i=0; i<ldns_rr_list_rr_count(list); ++i) { ldns_rr* nsec3 = ldns_rr_list_rr(list, i); if(ldns_rr_get_type(nsec3) != LDNS_RR_TYPE_NSEC3) { /* skip non nsec3 */ continue; } ldns_rdf* hashed = ldns_nsec3_hash_name_frm_nsec3( nsec3, qname); status = ldns_dname_cat(hashed, ldns_dname_left_chop( ldns_rr_owner(nsec3))); if(status != LDNS_STATUS_OK) abort_ldns_error("ldns_dname_cat", status); if(ldns_dname_compare(hashed, ldns_rr_owner(nsec3)) == 0) { ldns_rdf_print(stdout, ldns_rr_owner(nsec3)); printf(" proves "); ldns_rdf_print(stdout, qname); printf(" exists.\n"); } else if(ldns_nsec_covers_name(nsec3, hashed)) { ldns_rdf_print(stdout, ldns_rr_owner(nsec3)); printf(" proves "); ldns_rdf_print(stdout, qname); printf(" does not exist.\n"); } ldns_rdf_free(hashed); } }
/* this is NOT the hash, but the original name! */ ldns_rdf * ldns_nsec3_closest_encloser(ldns_rdf *qname, ldns_rr_type qtype, ldns_rr_list *nsec3s) { /* remember parameters, they must match */ uint8_t algorithm; uint32_t iterations; uint8_t salt_length; uint8_t *salt; ldns_rdf *sname, *hashed_sname, *tmp; ldns_rr *ce; bool flag; bool exact_match_found; bool in_range_found; ldns_status status; ldns_rdf *zone_name; size_t nsec_i; ldns_rr *nsec; ldns_rdf *result = NULL; if (!qname || !nsec3s || ldns_rr_list_rr_count(nsec3s) < 1) { return NULL; } if (verbosity >= 4) { printf(";; finding closest encloser for type %d ", qtype); ldns_rdf_print(stdout, qname); printf("\n"); } nsec = ldns_rr_list_rr(nsec3s, 0); algorithm = ldns_nsec3_algorithm(nsec); salt_length = ldns_nsec3_salt_length(nsec); salt = ldns_nsec3_salt_data(nsec); iterations = ldns_nsec3_iterations(nsec); sname = ldns_rdf_clone(qname); ce = NULL; flag = false; zone_name = ldns_dname_left_chop(ldns_rr_owner(nsec)); /* algorithm from nsec3-07 8.3 */ while (ldns_dname_label_count(sname) > 0) { exact_match_found = false; in_range_found = false; if (verbosity >= 3) { printf(";; "); ldns_rdf_print(stdout, sname); printf(" hashes to: "); } hashed_sname = ldns_nsec3_hash_name(sname, algorithm, iterations, salt_length, salt); status = ldns_dname_cat(hashed_sname, zone_name); if (verbosity >= 3) { ldns_rdf_print(stdout, hashed_sname); printf("\n"); } for (nsec_i = 0; nsec_i < ldns_rr_list_rr_count(nsec3s); nsec_i++) { nsec = ldns_rr_list_rr(nsec3s, nsec_i); /* check values of iterations etc! */ /* exact match? */ if (ldns_dname_compare(ldns_rr_owner(nsec), hashed_sname) == 0) { if (verbosity >= 4) { printf(";; exact match found\n"); } exact_match_found = true; } else if (ldns_nsec_covers_name(nsec, hashed_sname)) { if (verbosity >= 4) { printf(";; in range of an nsec\n"); } in_range_found = true; } } if (!exact_match_found && in_range_found) { flag = true; } else if (exact_match_found && flag) { result = ldns_rdf_clone(sname); } else if (exact_match_found && !flag) { // error! if (verbosity >= 4) { printf(";; the closest encloser is the same name (ie. this is an exact match, ie there is no closest encloser)\n"); } ldns_rdf_deep_free(hashed_sname); goto done; } else { flag = false; } ldns_rdf_deep_free(hashed_sname); tmp = sname; sname = ldns_dname_left_chop(sname); ldns_rdf_deep_free(tmp); } done: LDNS_FREE(salt); ldns_rdf_deep_free(zone_name); ldns_rdf_deep_free(sname); if (!result) { if (verbosity >= 4) { printf(";; no closest encloser found\n"); } } /* todo checks from end of 6.2. here or in caller? */ return result; }
/*return hash name match*/ ldns_rr * ldns_nsec3_exact_match(ldns_rdf *qname, ldns_rr_type qtype, ldns_rr_list *nsec3s) { uint8_t algorithm; uint32_t iterations; uint8_t salt_length; uint8_t *salt; ldns_rdf *sname, *hashed_sname; size_t nsec_i; ldns_rr *nsec; ldns_rr *result = NULL; ldns_status status; const ldns_rr_descriptor *descriptor; ldns_rdf *zone_name; if (verbosity >= 4) { printf(";; finding exact match for "); descriptor = ldns_rr_descript(qtype); if (descriptor && descriptor->_name) { printf("%s ", descriptor->_name); } else { printf("TYPE%d ", qtype); } ldns_rdf_print(stdout, qname); printf("\n"); } if (!qname || !nsec3s || ldns_rr_list_rr_count(nsec3s) < 1) { if (verbosity >= 4) { printf("no qname, nsec3s or list empty\n"); } return NULL; } nsec = ldns_rr_list_rr(nsec3s, 0); algorithm = ldns_nsec3_algorithm(nsec); salt_length = ldns_nsec3_salt_length(nsec); salt = ldns_nsec3_salt_data(nsec); iterations = ldns_nsec3_iterations(nsec); sname = ldns_rdf_clone(qname); if (verbosity >= 4) { printf(";; owner name hashes to: "); } hashed_sname = ldns_nsec3_hash_name(sname, algorithm, iterations, salt_length, salt); zone_name = ldns_dname_left_chop(ldns_rr_owner(nsec)); status = ldns_dname_cat(hashed_sname, zone_name); if (verbosity >= 4) { ldns_rdf_print(stdout, hashed_sname); printf("\n"); } for (nsec_i = 0; nsec_i < ldns_rr_list_rr_count(nsec3s); nsec_i++) { nsec = ldns_rr_list_rr(nsec3s, nsec_i); /* check values of iterations etc! */ /* exact match? */ if (ldns_dname_compare(ldns_rr_owner(nsec), hashed_sname) == 0) { result = nsec; goto done; } } done: ldns_rdf_deep_free(zone_name); ldns_rdf_deep_free(sname); ldns_rdf_deep_free(hashed_sname); LDNS_FREE(salt); if (verbosity >= 4) { if (result) { printf(";; Found.\n"); } else { printf(";; Not foud.\n"); } } return result; }