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; }
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; }