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 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_rr * ldns_create_empty_rrsig(ldns_rr_list *rrset, ldns_key *current_key) { uint32_t orig_ttl; time_t now; ldns_rr *current_sig; uint8_t label_count; label_count = ldns_dname_label_count(ldns_rr_owner(ldns_rr_list_rr(rrset, 0))); current_sig = ldns_rr_new_frm_type(LDNS_RR_TYPE_RRSIG); /* set the type on the new signature */ orig_ttl = ldns_rr_ttl(ldns_rr_list_rr(rrset, 0)); ldns_rr_set_ttl(current_sig, orig_ttl); ldns_rr_set_owner(current_sig, ldns_rdf_clone( ldns_rr_owner( ldns_rr_list_rr(rrset, 0)))); /* fill in what we know of the signature */ /* set the orig_ttl */ (void)ldns_rr_rrsig_set_origttl( current_sig, ldns_native2rdf_int32(LDNS_RDF_TYPE_INT32, orig_ttl)); /* the signers name */ (void)ldns_rr_rrsig_set_signame( current_sig, ldns_rdf_clone(ldns_key_pubkey_owner(current_key))); /* label count - get it from the first rr in the rr_list */ (void)ldns_rr_rrsig_set_labels( current_sig, ldns_native2rdf_int8(LDNS_RDF_TYPE_INT8, label_count)); /* inception, expiration */ now = time(NULL); if (ldns_key_inception(current_key) != 0) { (void)ldns_rr_rrsig_set_inception( current_sig, ldns_native2rdf_int32( LDNS_RDF_TYPE_TIME, ldns_key_inception(current_key))); } else { (void)ldns_rr_rrsig_set_inception( current_sig, ldns_native2rdf_int32(LDNS_RDF_TYPE_TIME, now)); } if (ldns_key_expiration(current_key) != 0) { (void)ldns_rr_rrsig_set_expiration( current_sig, ldns_native2rdf_int32( LDNS_RDF_TYPE_TIME, ldns_key_expiration(current_key))); } else { (void)ldns_rr_rrsig_set_expiration( current_sig, ldns_native2rdf_int32( LDNS_RDF_TYPE_TIME, now + LDNS_DEFAULT_EXP_TIME)); } (void)ldns_rr_rrsig_set_keytag( current_sig, ldns_native2rdf_int16(LDNS_RDF_TYPE_INT16, ldns_key_keytag(current_key))); (void)ldns_rr_rrsig_set_algorithm( current_sig, ldns_native2rdf_int8( LDNS_RDF_TYPE_ALG, ldns_key_algorithm(current_key))); (void)ldns_rr_rrsig_set_typecovered( current_sig, ldns_native2rdf_int16( LDNS_RDF_TYPE_TYPE, ldns_rr_get_type(ldns_rr_list_rr(rrset, 0)))); return current_sig; }
ldns_status ldns_dnssec_zone_add_empty_nonterminals(ldns_dnssec_zone *zone) { ldns_dnssec_name *new_name; ldns_rdf *cur_name; ldns_rdf *next_name; ldns_rbnode_t *cur_node, *next_node, *new_node; /* for the detection */ uint16_t i, cur_label_count, next_label_count; uint16_t soa_label_count = 0; ldns_rdf *l1, *l2; int lpos; if (!zone) { return LDNS_STATUS_ERR; } if (zone->soa && zone->soa->name) { soa_label_count = ldns_dname_label_count(zone->soa->name); } cur_node = ldns_rbtree_first(zone->names); while (cur_node != LDNS_RBTREE_NULL) { next_node = ldns_rbtree_next(cur_node); /* skip glue */ while (next_node != LDNS_RBTREE_NULL && next_node->data && ((ldns_dnssec_name *)next_node->data)->is_glue ) { next_node = ldns_rbtree_next(next_node); } if (next_node == LDNS_RBTREE_NULL) { next_node = ldns_rbtree_first(zone->names); } if (! cur_node->data || ! next_node->data) { return LDNS_STATUS_ERR; } cur_name = ((ldns_dnssec_name *)cur_node->data)->name; next_name = ((ldns_dnssec_name *)next_node->data)->name; cur_label_count = ldns_dname_label_count(cur_name); next_label_count = ldns_dname_label_count(next_name); /* Since the names are in canonical order, we can * recognize empty non-terminals by their labels; * every label after the first one on the next owner * name is a non-terminal if it either does not exist * in the current name or is different from the same * label in the current name (counting from the end) */ for (i = 1; i < next_label_count - soa_label_count; i++) { lpos = (int)cur_label_count - (int)next_label_count + (int)i; if (lpos >= 0) { l1 = ldns_dname_clone_from(cur_name, (uint8_t)lpos); } else { l1 = NULL; } l2 = ldns_dname_clone_from(next_name, i); if (!l1 || ldns_dname_compare(l1, l2) != 0) { /* We have an empty nonterminal, add it to the * tree */ new_name = ldns_dnssec_name_new(); if (!new_name) { return LDNS_STATUS_MEM_ERR; } new_name->name = ldns_dname_clone_from(next_name, i); if (!new_name->name) { ldns_dnssec_name_free(new_name); return LDNS_STATUS_MEM_ERR; } new_name->name_alloced = true; new_node = LDNS_MALLOC(ldns_rbnode_t); if (!new_node) { ldns_dnssec_name_free(new_name); return LDNS_STATUS_MEM_ERR; } new_node->key = new_name->name; new_node->data = new_name; (void)ldns_rbtree_insert(zone->names, new_node); ldns_dnssec_name_make_hashed_name( zone, new_name, NULL); } ldns_rdf_deep_free(l1); ldns_rdf_deep_free(l2); } /* we might have inserted a new node after * the current one so we can't just use next() */ if (next_node != ldns_rbtree_first(zone->names)) { cur_node = next_node; } else { cur_node = LDNS_RBTREE_NULL; } } return LDNS_STATUS_OK; }
/* 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; }
int main(int argc, char **argv) { /* Local Vars */ int i; int soa_valid = 0; int ns_valid = 0; ldns_rdf *rd_domain; ldns_rdf *rd_trace; ldns_rdf *rd_cdomain; ldns_pkt *pkt; ldns_resolver *res; ldns_rr *rr; ldns_rr_list *rrl; ldns_rr_list *rrl_domain_soa; ldns_rr_list *rrl_domain_soa_rrsig; ldns_rr_list *rrl_domain_ns; ldns_rr_list *rrl_domain_ns_rrsig; ldns_rr_list *rrl_valid_keys; ldns_status status; /* Set signal handling and alarm */ if (signal(SIGALRM, timeout_alarm_handler) == SIG_ERR) critical("Setup SIGALRM trap failed!"); /* Process check arguments */ if (process_arguments(argc, argv) != OK) unknown("Parsing arguments failed!"); /* Start plugin timeout */ alarm(mp_timeout); rd_domain = ldns_dname_new_frm_str(domainname); if (!rd_domain) unknown("Illegal domain name"); rd_trace = ldns_dname_new_frm_str(domaintrace); if (!rd_trace) unknown("Illegal trace domain name"); /* Check domain is subdomain from trace start */ if (!ldns_dname_is_subdomain(rd_domain, rd_trace)) { ldns_rr_list_deep_free(trusted_keys); ldns_rdf_deep_free(rd_domain); ldns_rdf_deep_free(rd_trace); unknown("'%s' is not a subdomain of '%s'.", domainname, domaintrace); } /* Add trusted keys for trace domain to rrl_valid_keys. */ rrl_valid_keys = ldns_rr_list_new(); for(i = 0; i < ldns_rr_list_rr_count(trusted_keys); i++) { rr = ldns_rr_list_rr(trusted_keys, i); if (ldns_dname_compare(ldns_rr_owner(rr),rd_trace) == 0) ldns_rr_list_push_rr(rrl_valid_keys, ldns_rr_clone(rr)); } ldns_rr_list_deep_free(trusted_keys); if (ldns_rr_list_rr_count(rrl_valid_keys) == 0) { ldns_rdf_deep_free(rd_domain); ldns_rdf_deep_free(rd_trace); ldns_rr_list_deep_free(rrl_valid_keys); critical("No trusted key for trace start '%s'", domaintrace?domaintrace:"."); } if (mp_verbose >= 2) { printf("--[ Trusted keys used ]-------------------------------------\n"); ldns_rr_list_sort(rrl_valid_keys); ldns_rr_list_print(stdout, rrl_valid_keys); printf("------------------------------------------------------------\n"); } /* create a new resolver with dns_server or server from /etc/resolv.conf */ res = createResolver(hostname); if (!res) { ldns_rdf_deep_free(rd_domain); ldns_rdf_deep_free(rd_trace); ldns_rr_list_deep_free(rrl_valid_keys); unknown("Creating resolver failed."); } resolverEnableDnssec(res); ldns_resolver_set_dnssec_anchors(res, rrl_valid_keys); /* check domain exists */ pkt = mp_ldns_resolver_query(res, rd_domain, LDNS_RR_TYPE_SOA, LDNS_RR_CLASS_IN, LDNS_RD); if (pkt == NULL || ldns_pkt_get_rcode(pkt) != LDNS_RCODE_NOERROR) { ldns_rdf_deep_free(rd_domain); ldns_rdf_deep_free(rd_trace); ldns_resolver_deep_free(res); if (pkt && ldns_pkt_get_rcode(pkt) == LDNS_RCODE_NXDOMAIN) { ldns_pkt_free(pkt); critical("Domain '%s' don't exist.", domainname); } ldns_pkt_free(pkt); critical("Unable to get SOA for %s.", domainname); } rrl_domain_soa = ldns_pkt_rr_list_by_name_and_type(pkt, rd_domain, LDNS_RR_TYPE_SOA, LDNS_SECTION_ANSWER); if (rrl_domain_soa == NULL || ldns_rr_list_rr_count(rrl_domain_soa) == 0) { ldns_rdf_deep_free(rd_domain); ldns_rdf_deep_free(rd_trace); ldns_resolver_deep_free(res); ldns_pkt_free(pkt); critical("Domain '%s' not found.", domainname); } rrl_domain_soa_rrsig = ldns_dnssec_pkt_get_rrsigs_for_name_and_type(pkt, rd_domain, LDNS_RR_TYPE_SOA); if (rrl_domain_soa_rrsig == NULL || ldns_rr_list_rr_count(rrl_domain_soa_rrsig) == 0) { free(domaintrace); ldns_rdf_deep_free(rd_domain); ldns_rdf_deep_free(rd_trace); ldns_resolver_deep_free(res); ldns_pkt_free(pkt); ldns_rr_list_deep_free(rrl_domain_soa); critical("Domain '%s' not signed.", domainname); } ldns_pkt_free(pkt); pkt = ldns_resolver_query(res, rd_domain, LDNS_RR_TYPE_NS, LDNS_RR_CLASS_IN, LDNS_RD); rrl_domain_ns = ldns_pkt_rr_list_by_name_and_type(pkt, rd_domain, LDNS_RR_TYPE_NS, LDNS_SECTION_ANSWER); rrl_domain_ns_rrsig = ldns_dnssec_pkt_get_rrsigs_for_name_and_type(pkt, rd_domain, LDNS_RR_TYPE_NS); ldns_pkt_free(pkt); if (mp_verbose >= 2) { printf("--[ Checked Domain ]----------------------------------------\n"); ldns_rr_list_print(stdout, rrl_domain_soa); printf("------------------------------------------------------------\n"); ldns_rr_list_print(stdout, rrl_domain_soa_rrsig); printf("------------------------------------------------------------\n"); ldns_rr_list_print(stdout, rrl_domain_ns); printf("------------------------------------------------------------\n"); ldns_rr_list_print(stdout, rrl_domain_ns_rrsig); printf("------------------------------------------------------------\n"); } /* create a new resolver with dns_server or server from /etc/resolv.conf */ ldns_resolver_free(res); res = createResolver(resolver); if (!res) { ldns_rdf_deep_free(rd_domain); ldns_rdf_deep_free(rd_trace); ldns_rr_list_deep_free(rrl_valid_keys); unknown("Creating resolver failed."); } resolverEnableDnssec(res); ldns_resolver_set_dnssec_anchors(res, rrl_valid_keys); /* Fetch valid keys from top down */ i = ldns_dname_label_count(rd_domain) - ldns_dname_label_count(rd_trace); for (; i>=0; i--) { rd_cdomain = ldns_dname_clone_from(rd_domain, i); if (mp_verbose) { char *str = ldns_rdf2str(rd_cdomain); printf("Trace: %s\n", str); free(str); } rrl = ldns_fetch_valid_domain_keys(res, rd_cdomain, rrl_valid_keys, &status); if (mp_verbose >= 2) { printf("--[ Valid Keys ]----------------------------------------\n"); ldns_rr_list_sort(rrl); ldns_rr_list_print(stdout, rrl); printf("------------------------------------------------------------\n"); } ldns_rr_list_cat(rrl_valid_keys, rrl); ldns_rr_list_free(rrl); ldns_rdf_deep_free(rd_cdomain); } ldns_rdf_deep_free(rd_trace); ldns_rdf_deep_free(rd_domain); /* Validate SOA */ for(i = 0; i < ldns_rr_list_rr_count(rrl_domain_soa_rrsig); i++) { rr = ldns_rr_list_rr(rrl_domain_soa_rrsig, i); status = ldns_verify_rrsig_keylist(rrl_domain_soa, rr, rrl_valid_keys, NULL); if (status == LDNS_STATUS_OK) soa_valid++; else if (mp_verbose > 0) fprintf(stderr, "ldns_verify_rrsig_keylist SOA failed: %s\n", ldns_get_errorstr_by_id(status)); } ldns_rr_list_deep_free(rrl_domain_soa); ldns_rr_list_deep_free(rrl_domain_soa_rrsig); if (soa_valid == 0) { critical("No valid Signatur for SOA of '%s'", domainname); free(domainname); free(domaintrace); ldns_resolver_deep_free(res); ldns_rr_list_deep_free(rrl_domain_ns); ldns_rr_list_deep_free(rrl_domain_ns_rrsig); return checkState; } /* Validate NS */ for(i = 0; i < ldns_rr_list_rr_count(rrl_domain_ns_rrsig); i++) { rr = ldns_rr_list_rr(rrl_domain_ns_rrsig, i); status = ldns_verify_rrsig_keylist(rrl_domain_ns, rr, rrl_valid_keys, NULL); if (status == LDNS_STATUS_OK) ns_valid++; else if (mp_verbose > 0) fprintf(stderr, "ldns_verify_rrsig_keylist NS failed: %s\n", ldns_get_errorstr_by_id(status)); } ldns_rr_list_deep_free(rrl_domain_ns); ldns_rr_list_deep_free(rrl_domain_ns_rrsig); ldns_resolver_deep_free(res); if (ns_valid == 0) { critical("No valid Signatur for NS of '%s'", domainname); free(domainname); free(domaintrace); return checkState; } ok("Trust for '%s' successfull traces from '%s'", domainname, domaintrace); free(domainname); free(domaintrace); return checkState; }