1238104Sdes/* 2238104Sdes * securechasetrace.c 3238104Sdes * Where all the hard work concerning secure tracing is done 4238104Sdes * 5238104Sdes * (c) 2005, 2006 NLnet Labs 6238104Sdes * 7238104Sdes * See the file LICENSE for the license 8238104Sdes * 9238104Sdes */ 10238104Sdes 11238104Sdes#include "drill.h" 12238104Sdes#include <ldns/ldns.h> 13238104Sdes 14238104Sdes#define SELF "[S]" /* self sig ok */ 15238104Sdes#define TRUST "[T]" /* chain from parent */ 16238104Sdes#define BOGUS "[B]" /* bogus */ 17238104Sdes#define UNSIGNED "[U]" /* no relevant dnssec data found */ 18238104Sdes 19238104Sdes#if 0 20238104Sdes/* See if there is a key/ds in trusted that matches 21238104Sdes * a ds in *ds. 22238104Sdes */ 23238104Sdesstatic ldns_rr_list * 24238104Sdesds_key_match(ldns_rr_list *ds, ldns_rr_list *trusted) 25238104Sdes{ 26238104Sdes size_t i, j; 27238104Sdes bool match; 28238104Sdes ldns_rr *rr_i, *rr_j; 29238104Sdes ldns_rr_list *keys; 30238104Sdes 31238104Sdes if (!trusted || !ds) { 32238104Sdes return NULL; 33238104Sdes } 34238104Sdes 35238104Sdes match = false; 36238104Sdes keys = ldns_rr_list_new(); 37238104Sdes if (!keys) { 38238104Sdes return NULL; 39238104Sdes } 40238104Sdes 41238104Sdes if (!ds || !trusted) { 42238104Sdes return NULL; 43238104Sdes } 44238104Sdes 45238104Sdes for (i = 0; i < ldns_rr_list_rr_count(trusted); i++) { 46238104Sdes rr_i = ldns_rr_list_rr(trusted, i); 47238104Sdes for (j = 0; j < ldns_rr_list_rr_count(ds); j++) { 48238104Sdes 49238104Sdes rr_j = ldns_rr_list_rr(ds, j); 50238104Sdes if (ldns_rr_compare_ds(rr_i, rr_j)) { 51238104Sdes match = true; 52238104Sdes /* only allow unique RRs to match */ 53238104Sdes ldns_rr_set_push_rr(keys, rr_i); 54238104Sdes } 55238104Sdes } 56238104Sdes } 57238104Sdes if (match) { 58238104Sdes return keys; 59238104Sdes } else { 60238104Sdes return NULL; 61238104Sdes } 62238104Sdes} 63238104Sdes#endif 64238104Sdes 65238104Sdesldns_pkt * 66238104Sdesget_dnssec_pkt(ldns_resolver *r, ldns_rdf *name, ldns_rr_type t) 67238104Sdes{ 68238104Sdes ldns_pkt *p = NULL; 69238104Sdes p = ldns_resolver_query(r, name, t, LDNS_RR_CLASS_IN, 0); 70238104Sdes if (!p) { 71238104Sdes return NULL; 72238104Sdes } else { 73238104Sdes if (verbosity >= 5) { 74238104Sdes ldns_pkt_print(stdout, p); 75238104Sdes } 76238104Sdes return p; 77238104Sdes } 78238104Sdes} 79238104Sdes 80238104Sdes#ifdef HAVE_SSL 81238104Sdes/* 82238104Sdes * retrieve keys for this zone 83238104Sdes */ 84238104Sdesstatic ldns_pkt_type 85238104Sdesget_key(ldns_pkt *p, ldns_rdf *apexname, ldns_rr_list **rrlist, ldns_rr_list **opt_sig) 86238104Sdes{ 87238104Sdes return get_dnssec_rr(p, apexname, LDNS_RR_TYPE_DNSKEY, rrlist, opt_sig); 88238104Sdes} 89238104Sdes 90238104Sdes/* 91238104Sdes * check to see if we can find a DS rrset here which we can then follow 92238104Sdes */ 93238104Sdesstatic ldns_pkt_type 94238104Sdesget_ds(ldns_pkt *p, ldns_rdf *ownername, ldns_rr_list **rrlist, ldns_rr_list **opt_sig) 95238104Sdes{ 96238104Sdes return get_dnssec_rr(p, ownername, LDNS_RR_TYPE_DS, rrlist, opt_sig); 97238104Sdes} 98238104Sdes#endif /* HAVE_SSL */ 99238104Sdes 100238104Sdesvoid 101238104Sdesremove_resolver_nameservers(ldns_resolver *res) 102238104Sdes{ 103238104Sdes ldns_rdf *pop; 104238104Sdes 105238104Sdes /* remove the old nameserver from the resolver */ 106238104Sdes while((pop = ldns_resolver_pop_nameserver(res))) { 107238104Sdes ldns_rdf_deep_free(pop); 108238104Sdes } 109238104Sdes 110238104Sdes} 111238104Sdes 112238104Sdesvoid 113238104Sdesshow_current_nameservers(FILE *out, ldns_resolver *res) 114238104Sdes{ 115238104Sdes size_t i; 116238104Sdes fprintf(out, "Current nameservers for resolver object:\n"); 117238104Sdes for (i = 0; i < ldns_resolver_nameserver_count(res); i++) { 118238104Sdes ldns_rdf_print(out, ldns_resolver_nameservers(res)[i]); 119238104Sdes fprintf(out, "\n"); 120238104Sdes } 121238104Sdes} 122238104Sdes 123238104Sdes/*ldns_pkt **/ 124238104Sdes#ifdef HAVE_SSL 125238104Sdesint 126238104Sdesdo_secure_trace(ldns_resolver *local_res, ldns_rdf *name, ldns_rr_type t, 127238104Sdes ldns_rr_class c, ldns_rr_list *trusted_keys, ldns_rdf *start_name 128238104Sdes ) 129238104Sdes{ 130238104Sdes ldns_resolver *res; 131238104Sdes ldns_pkt *p, *local_p; 132238104Sdes ldns_rr_list *new_nss; 133238104Sdes ldns_rr_list *ns_addr; 134238104Sdes ldns_rdf *pop; 135238104Sdes ldns_rdf **labels = NULL; 136238104Sdes ldns_status status, st; 137238104Sdes ssize_t i; 138238104Sdes size_t j; 139238104Sdes size_t k; 140238104Sdes size_t l; 141269257Sdes uint8_t labels_count = 0; 142238104Sdes 143238104Sdes /* dnssec */ 144238104Sdes ldns_rr_list *key_list; 145238104Sdes ldns_rr_list *key_sig_list; 146238104Sdes ldns_rr_list *ds_list; 147238104Sdes ldns_rr_list *ds_sig_list; 148238104Sdes ldns_rr_list *correct_key_list; 149238104Sdes ldns_rr_list *trusted_ds_rrs; 150238104Sdes bool new_keys_trusted = false; 151238104Sdes ldns_rr_list *current_correct_keys; 152238104Sdes ldns_rr_list *dataset; 153238104Sdes 154238104Sdes ldns_rr_list *nsec_rrs = NULL; 155238104Sdes ldns_rr_list *nsec_rr_sigs = NULL; 156238104Sdes 157238104Sdes /* empty non-terminal check */ 158238104Sdes bool ent; 159269257Sdes ldns_rr *nsecrr; /* The nsec that proofs the non-terminal */ 160269257Sdes ldns_rdf *hashed_name; /* The query hashed with nsec3 params */ 161269257Sdes ldns_rdf *label0; /* The first label of an nsec3 owner name */ 162238104Sdes 163238104Sdes /* glue handling */ 164238104Sdes ldns_rr_list *new_ns_addr; 165238104Sdes ldns_rr_list *old_ns_addr; 166238104Sdes ldns_rr *ns_rr; 167238104Sdes 168238104Sdes int result = 0; 169238104Sdes 170238104Sdes /* printing niceness */ 171238104Sdes const ldns_rr_descriptor *descriptor; 172238104Sdes 173238104Sdes descriptor = ldns_rr_descript(t); 174238104Sdes 175238104Sdes new_nss = NULL; 176238104Sdes ns_addr = NULL; 177238104Sdes key_list = NULL; 178238104Sdes ds_list = NULL; 179238104Sdes 180238104Sdes p = NULL; 181238104Sdes local_p = NULL; 182238104Sdes res = ldns_resolver_new(); 183238104Sdes key_sig_list = NULL; 184238104Sdes ds_sig_list = NULL; 185238104Sdes 186238104Sdes if (!res) { 187238104Sdes error("Memory allocation failed"); 188238104Sdes result = -1; 189238104Sdes return result; 190238104Sdes } 191238104Sdes 192238104Sdes correct_key_list = ldns_rr_list_new(); 193238104Sdes if (!correct_key_list) { 194238104Sdes error("Memory allocation failed"); 195238104Sdes result = -1; 196238104Sdes return result; 197238104Sdes } 198238104Sdes 199238104Sdes trusted_ds_rrs = ldns_rr_list_new(); 200238104Sdes if (!trusted_ds_rrs) { 201238104Sdes error("Memory allocation failed"); 202238104Sdes result = -1; 203238104Sdes return result; 204238104Sdes } 205238104Sdes /* Add all preset trusted DS signatures to the list of trusted DS RRs. */ 206238104Sdes for (j = 0; j < ldns_rr_list_rr_count(trusted_keys); j++) { 207238104Sdes ldns_rr* one_rr = ldns_rr_list_rr(trusted_keys, j); 208238104Sdes if (ldns_rr_get_type(one_rr) == LDNS_RR_TYPE_DS) { 209238104Sdes ldns_rr_list_push_rr(trusted_ds_rrs, ldns_rr_clone(one_rr)); 210238104Sdes } 211238104Sdes } 212238104Sdes 213238104Sdes /* transfer some properties of local_res to res */ 214238104Sdes ldns_resolver_set_ip6(res, 215238104Sdes ldns_resolver_ip6(local_res)); 216238104Sdes ldns_resolver_set_port(res, 217238104Sdes ldns_resolver_port(local_res)); 218238104Sdes ldns_resolver_set_debug(res, 219238104Sdes ldns_resolver_debug(local_res)); 220238104Sdes ldns_resolver_set_fail(res, 221238104Sdes ldns_resolver_fail(local_res)); 222238104Sdes ldns_resolver_set_usevc(res, 223238104Sdes ldns_resolver_usevc(local_res)); 224238104Sdes ldns_resolver_set_random(res, 225238104Sdes ldns_resolver_random(local_res)); 226269257Sdes ldns_resolver_set_source(res, 227269257Sdes ldns_resolver_source(local_res)); 228238104Sdes ldns_resolver_set_recursive(local_res, true); 229238104Sdes 230238104Sdes ldns_resolver_set_recursive(res, false); 231238104Sdes ldns_resolver_set_dnssec_cd(res, false); 232238104Sdes ldns_resolver_set_dnssec(res, true); 233238104Sdes 234238104Sdes /* setup the root nameserver in the new resolver */ 235238104Sdes status = ldns_resolver_push_nameserver_rr_list(res, global_dns_root); 236238104Sdes if (status != LDNS_STATUS_OK) { 237238104Sdes printf("ERRRRR: %s\n", ldns_get_errorstr_by_id(status)); 238238104Sdes ldns_rr_list_print(stdout, global_dns_root); 239246854Sdes result = status; 240246854Sdes goto done; 241238104Sdes } 242238104Sdes labels_count = ldns_dname_label_count(name); 243238104Sdes if (start_name) { 244238104Sdes if (ldns_dname_is_subdomain(name, start_name)) { 245238104Sdes labels_count -= ldns_dname_label_count(start_name); 246238104Sdes } else { 247238104Sdes fprintf(stderr, "Error; "); 248238104Sdes ldns_rdf_print(stderr, name); 249238104Sdes fprintf(stderr, " is not a subdomain of "); 250238104Sdes ldns_rdf_print(stderr, start_name); 251238104Sdes fprintf(stderr, "\n"); 252238104Sdes goto done; 253238104Sdes } 254238104Sdes } 255238104Sdes labels = LDNS_XMALLOC(ldns_rdf*, labels_count + 2); 256238104Sdes if (!labels) { 257238104Sdes goto done; 258238104Sdes } 259238104Sdes labels[0] = ldns_dname_new_frm_str(LDNS_ROOT_LABEL_STR); 260238104Sdes labels[1] = ldns_rdf_clone(name); 261238104Sdes for(i = 2 ; i < (ssize_t)labels_count + 2; i++) { 262238104Sdes labels[i] = ldns_dname_left_chop(labels[i - 1]); 263238104Sdes } 264238104Sdes 265238104Sdes /* get the nameserver for the label 266238104Sdes * ask: dnskey and ds for the label 267238104Sdes */ 268238104Sdes for(i = (ssize_t)labels_count + 1; i > 0; i--) { 269238104Sdes status = ldns_resolver_send(&local_p, res, labels[i], LDNS_RR_TYPE_NS, c, 0); 270238104Sdes 271238104Sdes if (verbosity >= 5) { 272238104Sdes ldns_pkt_print(stdout, local_p); 273238104Sdes } 274238104Sdes 275238104Sdes new_nss = ldns_pkt_rr_list_by_type(local_p, 276238104Sdes LDNS_RR_TYPE_NS, LDNS_SECTION_ANSWER); 277238104Sdes if (!new_nss) { 278238104Sdes /* if it's a delegation, servers put them in the auth section */ 279238104Sdes new_nss = ldns_pkt_rr_list_by_type(local_p, 280238104Sdes LDNS_RR_TYPE_NS, LDNS_SECTION_AUTHORITY); 281238104Sdes } 282238104Sdes 283238104Sdes /* if this is the final step there might not be nameserver records 284238104Sdes of course if the data is in the apex, there are, so cover both 285238104Sdes cases */ 286238104Sdes if (new_nss || i > 1) { 287238104Sdes for(j = 0; j < ldns_rr_list_rr_count(new_nss); j++) { 288238104Sdes ns_rr = ldns_rr_list_rr(new_nss, j); 289238104Sdes pop = ldns_rr_rdf(ns_rr, 0); 290238104Sdes if (!pop) { 291238104Sdes printf("nopo\n"); 292238104Sdes break; 293238104Sdes } 294238104Sdes /* retrieve it's addresses */ 295238104Sdes /* trust glue? */ 296238104Sdes new_ns_addr = NULL; 297238104Sdes if (ldns_dname_is_subdomain(pop, labels[i])) { 298238104Sdes new_ns_addr = ldns_pkt_rr_list_by_name_and_type(local_p, pop, LDNS_RR_TYPE_A, LDNS_SECTION_ADDITIONAL); 299238104Sdes } 300238104Sdes if (!new_ns_addr || ldns_rr_list_rr_count(new_ns_addr) == 0) { 301238104Sdes new_ns_addr = ldns_get_rr_list_addr_by_name(res, pop, c, 0); 302238104Sdes } 303238104Sdes if (!new_ns_addr || ldns_rr_list_rr_count(new_ns_addr) == 0) { 304238104Sdes new_ns_addr = ldns_get_rr_list_addr_by_name(local_res, pop, c, 0); 305238104Sdes } 306238104Sdes 307238104Sdes if (new_ns_addr) { 308238104Sdes old_ns_addr = ns_addr; 309238104Sdes ns_addr = ldns_rr_list_cat_clone(ns_addr, new_ns_addr); 310238104Sdes ldns_rr_list_deep_free(old_ns_addr); 311238104Sdes } 312238104Sdes ldns_rr_list_deep_free(new_ns_addr); 313238104Sdes } 314238104Sdes ldns_rr_list_deep_free(new_nss); 315238104Sdes 316238104Sdes if (ns_addr) { 317238104Sdes remove_resolver_nameservers(res); 318238104Sdes 319238104Sdes if (ldns_resolver_push_nameserver_rr_list(res, ns_addr) != 320238104Sdes LDNS_STATUS_OK) { 321238104Sdes error("Error adding new nameservers"); 322238104Sdes ldns_pkt_free(local_p); 323238104Sdes goto done; 324238104Sdes } 325238104Sdes ldns_rr_list_deep_free(ns_addr); 326238104Sdes } else { 327238104Sdes status = ldns_verify_denial(local_p, labels[i], LDNS_RR_TYPE_NS, &nsec_rrs, &nsec_rr_sigs); 328238104Sdes 329238104Sdes /* verify the nsec3 themselves*/ 330238104Sdes if (verbosity >= 4) { 331238104Sdes printf("NSEC(3) Records to verify:\n"); 332238104Sdes ldns_rr_list_print(stdout, nsec_rrs); 333238104Sdes printf("With signatures:\n"); 334238104Sdes ldns_rr_list_print(stdout, nsec_rr_sigs); 335238104Sdes printf("correct keys:\n"); 336238104Sdes ldns_rr_list_print(stdout, correct_key_list); 337238104Sdes } 338238104Sdes 339238104Sdes if (status == LDNS_STATUS_OK) { 340238104Sdes if ((st = ldns_verify(nsec_rrs, nsec_rr_sigs, trusted_keys, NULL)) == LDNS_STATUS_OK) { 341238104Sdes fprintf(stdout, "%s ", TRUST); 342238104Sdes fprintf(stdout, "Existence denied: "); 343238104Sdes ldns_rdf_print(stdout, labels[i]); 344238104Sdes /* 345238104Sdes if (descriptor && descriptor->_name) { 346238104Sdes printf(" %s", descriptor->_name); 347238104Sdes } else { 348238104Sdes printf(" TYPE%u", t); 349238104Sdes } 350238104Sdes */ fprintf(stdout, " NS\n"); 351238104Sdes } else if ((st = ldns_verify(nsec_rrs, nsec_rr_sigs, correct_key_list, NULL)) == LDNS_STATUS_OK) { 352238104Sdes fprintf(stdout, "%s ", SELF); 353238104Sdes fprintf(stdout, "Existence denied: "); 354238104Sdes ldns_rdf_print(stdout, labels[i]); 355238104Sdes /* 356238104Sdes if (descriptor && descriptor->_name) { 357238104Sdes printf(" %s", descriptor->_name); 358238104Sdes } else { 359238104Sdes printf(" TYPE%u", t); 360238104Sdes } 361238104Sdes */ 362238104Sdes fprintf(stdout, " NS\n"); 363238104Sdes } else { 364238104Sdes fprintf(stdout, "%s ", BOGUS); 365238104Sdes result = 1; 366238104Sdes printf(";; Error verifying denial of existence for name "); 367238104Sdes ldns_rdf_print(stdout, labels[i]); 368238104Sdes /* 369238104Sdes printf(" type "); 370238104Sdes if (descriptor && descriptor->_name) { 371238104Sdes printf("%s", descriptor->_name); 372238104Sdes } else { 373238104Sdes printf("TYPE%u", t); 374238104Sdes } 375238104Sdes */ printf("NS: %s\n", ldns_get_errorstr_by_id(st)); 376238104Sdes } 377238104Sdes } else { 378238104Sdes fprintf(stdout, "%s ", BOGUS); 379238104Sdes result = 1; 380238104Sdes printf(";; Error verifying denial of existence for name "); 381238104Sdes ldns_rdf_print(stdout, labels[i]); 382238104Sdes printf("NS: %s\n", ldns_get_errorstr_by_id(status)); 383238104Sdes } 384238104Sdes 385238104Sdes /* there might be an empty non-terminal, in which case we need to continue */ 386238104Sdes ent = false; 387238104Sdes for (j = 0; j < ldns_rr_list_rr_count(nsec_rrs); j++) { 388269257Sdes nsecrr = ldns_rr_list_rr(nsec_rrs, j); 389269257Sdes /* For NSEC when the next name is a subdomain of the question */ 390269257Sdes if (ldns_rr_get_type(nsecrr) == LDNS_RR_TYPE_NSEC && 391269257Sdes ldns_dname_is_subdomain(ldns_rr_rdf(nsecrr, 0), labels[i])) { 392238104Sdes ent = true; 393269257Sdes 394269257Sdes /* For NSEC3, the hash matches the name and the type bitmap is empty*/ 395269257Sdes } else if (ldns_rr_get_type(nsecrr) == LDNS_RR_TYPE_NSEC3) { 396269257Sdes hashed_name = ldns_nsec3_hash_name_frm_nsec3(nsecrr, labels[i]); 397269257Sdes label0 = ldns_dname_label(ldns_rr_owner(nsecrr), 0); 398269257Sdes if (hashed_name && label0 && 399269257Sdes ldns_dname_compare(hashed_name, label0) == 0 && 400269257Sdes ldns_nsec3_bitmap(nsecrr) == NULL) { 401269257Sdes ent = true; 402269257Sdes } 403269257Sdes if (label0) { 404269257Sdes LDNS_FREE(label0); 405269257Sdes } 406269257Sdes if (hashed_name) { 407269257Sdes LDNS_FREE(hashed_name); 408269257Sdes } 409238104Sdes } 410238104Sdes } 411238104Sdes if (!ent) { 412238104Sdes ldns_rr_list_deep_free(nsec_rrs); 413238104Sdes ldns_rr_list_deep_free(nsec_rr_sigs); 414238104Sdes ldns_pkt_free(local_p); 415238104Sdes goto done; 416238104Sdes } else { 417238104Sdes printf(";; There is an empty non-terminal here, continue\n"); 418238104Sdes continue; 419238104Sdes } 420238104Sdes } 421238104Sdes 422238104Sdes if (ldns_resolver_nameserver_count(res) == 0) { 423238104Sdes error("No nameservers found for this node"); 424238104Sdes goto done; 425238104Sdes } 426238104Sdes } 427238104Sdes ldns_pkt_free(local_p); 428238104Sdes 429238104Sdes fprintf(stdout, ";; Domain: "); 430238104Sdes ldns_rdf_print(stdout, labels[i]); 431238104Sdes fprintf(stdout, "\n"); 432238104Sdes 433238104Sdes /* retrieve keys for current domain, and verify them 434238104Sdes if they match an already trusted DS, or if one of the 435238104Sdes keys used to sign these is trusted, add the keys to 436238104Sdes the trusted list */ 437238104Sdes p = get_dnssec_pkt(res, labels[i], LDNS_RR_TYPE_DNSKEY); 438238104Sdes (void) get_key(p, labels[i], &key_list, &key_sig_list); 439238104Sdes if (key_sig_list) { 440238104Sdes if (key_list) { 441238104Sdes current_correct_keys = ldns_rr_list_new(); 442238104Sdes if ((st = ldns_verify(key_list, key_sig_list, key_list, current_correct_keys)) == 443238104Sdes LDNS_STATUS_OK) { 444238104Sdes /* add all signed keys (don't just add current_correct, you'd miss 445238104Sdes * the zsk's then */ 446238104Sdes for (j = 0; j < ldns_rr_list_rr_count(key_list); j++) { 447238104Sdes ldns_rr_list_push_rr(correct_key_list, ldns_rr_clone(ldns_rr_list_rr(key_list, j))); 448238104Sdes } 449238104Sdes 450238104Sdes /* check whether these keys were signed 451238104Sdes * by a trusted keys. if so, these 452238104Sdes * keys are also trusted */ 453238104Sdes new_keys_trusted = false; 454238104Sdes for (k = 0; k < ldns_rr_list_rr_count(current_correct_keys); k++) { 455238104Sdes for (j = 0; j < ldns_rr_list_rr_count(trusted_ds_rrs); j++) { 456238104Sdes if (ldns_rr_compare_ds(ldns_rr_list_rr(current_correct_keys, k), 457238104Sdes ldns_rr_list_rr(trusted_ds_rrs, j))) { 458238104Sdes new_keys_trusted = true; 459238104Sdes } 460238104Sdes } 461238104Sdes } 462238104Sdes 463238104Sdes /* also all keys are trusted if one of the current correct keys is trusted */ 464238104Sdes for (k = 0; k < ldns_rr_list_rr_count(current_correct_keys); k++) { 465238104Sdes for (j = 0; j < ldns_rr_list_rr_count(trusted_keys); j++) { 466238104Sdes if (ldns_rr_compare(ldns_rr_list_rr(current_correct_keys, k), 467238104Sdes ldns_rr_list_rr(trusted_keys, j)) == 0) { 468238104Sdes new_keys_trusted = true; 469238104Sdes } 470238104Sdes } 471238104Sdes } 472238104Sdes 473238104Sdes 474238104Sdes if (new_keys_trusted) { 475238104Sdes ldns_rr_list_push_rr_list(trusted_keys, key_list); 476238104Sdes print_rr_list_abbr(stdout, key_list, TRUST); 477238104Sdes ldns_rr_list_free(key_list); 478238104Sdes key_list = NULL; 479238104Sdes } else { 480238104Sdes if (verbosity >= 2) { 481238104Sdes printf(";; Signature ok but no chain to a trusted key or ds record\n"); 482238104Sdes } 483238104Sdes print_rr_list_abbr(stdout, key_list, SELF); 484238104Sdes ldns_rr_list_deep_free(key_list); 485238104Sdes key_list = NULL; 486238104Sdes } 487238104Sdes } else { 488238104Sdes print_rr_list_abbr(stdout, key_list, BOGUS); 489238104Sdes result = 2; 490238104Sdes ldns_rr_list_deep_free(key_list); 491238104Sdes key_list = NULL; 492238104Sdes } 493238104Sdes ldns_rr_list_free(current_correct_keys); 494238104Sdes current_correct_keys = NULL; 495238104Sdes } else { 496238104Sdes printf(";; No DNSKEY record found for "); 497238104Sdes ldns_rdf_print(stdout, labels[i]); 498238104Sdes printf("\n"); 499238104Sdes } 500238104Sdes } 501238104Sdes 502238104Sdes ldns_pkt_free(p); 503238104Sdes ldns_rr_list_deep_free(key_sig_list); 504238104Sdes key_sig_list = NULL; 505238104Sdes 506238104Sdes /* check the DS records for the next child domain */ 507238104Sdes if (i > 1) { 508238104Sdes p = get_dnssec_pkt(res, labels[i-1], LDNS_RR_TYPE_DS); 509238104Sdes (void) get_ds(p, labels[i-1], &ds_list, &ds_sig_list); 510238104Sdes if (!ds_list) { 511238104Sdes ldns_pkt_free(p); 512238104Sdes if (ds_sig_list) { 513238104Sdes ldns_rr_list_deep_free(ds_sig_list); 514238104Sdes } 515238104Sdes p = get_dnssec_pkt(res, name, LDNS_RR_TYPE_DNSKEY); 516238104Sdes (void) get_ds(p, NULL, &ds_list, &ds_sig_list); 517238104Sdes } 518238104Sdes if (ds_sig_list) { 519238104Sdes if (ds_list) { 520238104Sdes if (verbosity >= 4) { 521238104Sdes printf("VERIFYING:\n"); 522238104Sdes printf("DS LIST:\n"); 523238104Sdes ldns_rr_list_print(stdout, ds_list); 524238104Sdes printf("SIGS:\n"); 525238104Sdes ldns_rr_list_print(stdout, ds_sig_list); 526238104Sdes printf("KEYS:\n"); 527238104Sdes ldns_rr_list_print(stdout, correct_key_list); 528238104Sdes } 529238104Sdes 530238104Sdes current_correct_keys = ldns_rr_list_new(); 531238104Sdes 532238104Sdes if ((st = ldns_verify(ds_list, ds_sig_list, correct_key_list, current_correct_keys)) == 533238104Sdes LDNS_STATUS_OK) { 534238104Sdes /* if the ds is signed by a trusted key and a key from correct keys 535238104Sdes matches that ds, add that key to the trusted keys */ 536238104Sdes new_keys_trusted = false; 537238104Sdes if (verbosity >= 2) { 538238104Sdes printf("Checking if signing key is trusted:\n"); 539238104Sdes } 540238104Sdes for (j = 0; j < ldns_rr_list_rr_count(current_correct_keys); j++) { 541238104Sdes if (verbosity >= 2) { 542238104Sdes printf("New key: "); 543238104Sdes ldns_rr_print(stdout, ldns_rr_list_rr(current_correct_keys, j)); 544238104Sdes } 545238104Sdes for (k = 0; k < ldns_rr_list_rr_count(trusted_keys); k++) { 546238104Sdes if (verbosity >= 2) { 547238104Sdes printf("\tTrusted key: "); 548238104Sdes ldns_rr_print(stdout, ldns_rr_list_rr(trusted_keys, k)); 549238104Sdes } 550238104Sdes if (ldns_rr_compare(ldns_rr_list_rr(current_correct_keys, j), 551238104Sdes ldns_rr_list_rr(trusted_keys, k)) == 0) { 552238104Sdes if (verbosity >= 2) { 553238104Sdes printf("Key is now trusted!\n"); 554238104Sdes } 555238104Sdes for (l = 0; l < ldns_rr_list_rr_count(ds_list); l++) { 556238104Sdes ldns_rr_list_push_rr(trusted_ds_rrs, ldns_rr_clone(ldns_rr_list_rr(ds_list, l))); 557238104Sdes new_keys_trusted = true; 558238104Sdes } 559238104Sdes } 560238104Sdes } 561238104Sdes } 562238104Sdes if (new_keys_trusted) { 563238104Sdes print_rr_list_abbr(stdout, ds_list, TRUST); 564238104Sdes } else { 565238104Sdes print_rr_list_abbr(stdout, ds_list, SELF); 566238104Sdes } 567238104Sdes } else { 568238104Sdes result = 3; 569238104Sdes print_rr_list_abbr(stdout, ds_list, BOGUS); 570238104Sdes } 571238104Sdes 572238104Sdes ldns_rr_list_free(current_correct_keys); 573238104Sdes current_correct_keys = NULL; 574238104Sdes } else { 575238104Sdes /* wait apparently there were no keys either, go back to the ds packet */ 576238104Sdes ldns_pkt_free(p); 577238104Sdes ldns_rr_list_deep_free(ds_sig_list); 578238104Sdes p = get_dnssec_pkt(res, labels[i-1], LDNS_RR_TYPE_DS); 579238104Sdes (void) get_ds(p, labels[i-1], &ds_list, &ds_sig_list); 580238104Sdes 581238104Sdes status = ldns_verify_denial(p, labels[i-1], LDNS_RR_TYPE_DS, &nsec_rrs, &nsec_rr_sigs); 582238104Sdes 583238104Sdes if (verbosity >= 4) { 584238104Sdes printf("NSEC(3) Records to verify:\n"); 585238104Sdes ldns_rr_list_print(stdout, nsec_rrs); 586238104Sdes printf("With signatures:\n"); 587238104Sdes ldns_rr_list_print(stdout, nsec_rr_sigs); 588238104Sdes printf("correct keys:\n"); 589238104Sdes ldns_rr_list_print(stdout, correct_key_list); 590238104Sdes } 591238104Sdes 592238104Sdes if (status == LDNS_STATUS_OK) { 593238104Sdes if ((st = ldns_verify(nsec_rrs, nsec_rr_sigs, trusted_keys, NULL)) == LDNS_STATUS_OK) { 594238104Sdes fprintf(stdout, "%s ", TRUST); 595238104Sdes fprintf(stdout, "Existence denied: "); 596238104Sdes ldns_rdf_print(stdout, labels[i-1]); 597238104Sdes printf(" DS"); 598238104Sdes fprintf(stdout, "\n"); 599238104Sdes } else if ((st = ldns_verify(nsec_rrs, nsec_rr_sigs, correct_key_list, NULL)) == LDNS_STATUS_OK) { 600238104Sdes fprintf(stdout, "%s ", SELF); 601238104Sdes fprintf(stdout, "Existence denied: "); 602238104Sdes ldns_rdf_print(stdout, labels[i-1]); 603238104Sdes printf(" DS"); 604238104Sdes fprintf(stdout, "\n"); 605238104Sdes } else { 606238104Sdes result = 4; 607238104Sdes fprintf(stdout, "%s ", BOGUS); 608238104Sdes printf("Error verifying denial of existence for "); 609238104Sdes ldns_rdf_print(stdout, labels[i-1]); 610238104Sdes printf(" DS"); 611238104Sdes printf(": %s\n", ldns_get_errorstr_by_id(st)); 612238104Sdes } 613238104Sdes 614238104Sdes 615238104Sdes } else { 616238104Sdes if (status == LDNS_STATUS_CRYPTO_NO_RRSIG) { 617238104Sdes printf(";; No DS for "); 618238104Sdes ldns_rdf_print(stdout, labels[i - 1]); 619238104Sdes } else { 620238104Sdes printf("[B] Unable to verify denial of existence for "); 621238104Sdes ldns_rdf_print(stdout, labels[i - 1]); 622238104Sdes printf(" DS: %s\n", ldns_get_errorstr_by_id(status)); 623238104Sdes } 624238104Sdes } 625238104Sdes if (verbosity >= 2) { 626238104Sdes printf(";; No ds record for delegation\n"); 627238104Sdes } 628238104Sdes } 629238104Sdes } 630238104Sdes ldns_rr_list_deep_free(ds_list); 631238104Sdes ldns_pkt_free(p); 632238104Sdes } else { 633238104Sdes /* if this is the last label, just verify the data and stop */ 634238104Sdes p = get_dnssec_pkt(res, labels[i], t); 635238104Sdes (void) get_dnssec_rr(p, labels[i], t, &dataset, &key_sig_list); 636238104Sdes if (dataset && ldns_rr_list_rr_count(dataset) > 0) { 637238104Sdes if (key_sig_list && ldns_rr_list_rr_count(key_sig_list) > 0) { 638238104Sdes 639238104Sdes /* If this is a wildcard, you must be able to deny exact match */ 640238104Sdes if ((st = ldns_verify(dataset, key_sig_list, trusted_keys, NULL)) == LDNS_STATUS_OK) { 641238104Sdes fprintf(stdout, "%s ", TRUST); 642238104Sdes ldns_rr_list_print(stdout, dataset); 643238104Sdes } else if ((st = ldns_verify(dataset, key_sig_list, correct_key_list, NULL)) == LDNS_STATUS_OK) { 644238104Sdes fprintf(stdout, "%s ", SELF); 645238104Sdes ldns_rr_list_print(stdout, dataset); 646238104Sdes } else { 647238104Sdes result = 5; 648238104Sdes fprintf(stdout, "%s ", BOGUS); 649238104Sdes ldns_rr_list_print(stdout, dataset); 650238104Sdes printf(";; Error: %s\n", ldns_get_errorstr_by_id(st)); 651238104Sdes } 652238104Sdes } else { 653238104Sdes fprintf(stdout, "%s ", UNSIGNED); 654238104Sdes ldns_rr_list_print(stdout, dataset); 655238104Sdes } 656238104Sdes ldns_rr_list_deep_free(dataset); 657238104Sdes } else { 658238104Sdes status = ldns_verify_denial(p, name, t, &nsec_rrs, &nsec_rr_sigs); 659238104Sdes if (status == LDNS_STATUS_OK) { 660238104Sdes /* verify the nsec3 themselves*/ 661238104Sdes if (verbosity >= 5) { 662238104Sdes printf("NSEC(3) Records to verify:\n"); 663238104Sdes ldns_rr_list_print(stdout, nsec_rrs); 664238104Sdes printf("With signatures:\n"); 665238104Sdes ldns_rr_list_print(stdout, nsec_rr_sigs); 666238104Sdes printf("correct keys:\n"); 667238104Sdes ldns_rr_list_print(stdout, correct_key_list); 668238104Sdes/* 669238104Sdes printf("trusted keys at %p:\n", trusted_keys); 670238104Sdes ldns_rr_list_print(stdout, trusted_keys); 671238104Sdes*/ } 672238104Sdes 673238104Sdes if ((st = ldns_verify(nsec_rrs, nsec_rr_sigs, trusted_keys, NULL)) == LDNS_STATUS_OK) { 674238104Sdes fprintf(stdout, "%s ", TRUST); 675238104Sdes fprintf(stdout, "Existence denied: "); 676238104Sdes ldns_rdf_print(stdout, name); 677238104Sdes if (descriptor && descriptor->_name) { 678238104Sdes printf(" %s", descriptor->_name); 679238104Sdes } else { 680238104Sdes printf(" TYPE%u", t); 681238104Sdes } 682238104Sdes fprintf(stdout, "\n"); 683238104Sdes } else if ((st = ldns_verify(nsec_rrs, nsec_rr_sigs, correct_key_list, NULL)) == LDNS_STATUS_OK) { 684238104Sdes fprintf(stdout, "%s ", SELF); 685238104Sdes fprintf(stdout, "Existence denied: "); 686238104Sdes ldns_rdf_print(stdout, name); 687238104Sdes if (descriptor && descriptor->_name) { 688238104Sdes printf(" %s", descriptor->_name); 689238104Sdes } else { 690238104Sdes printf(" TYPE%u", t); 691238104Sdes } 692238104Sdes fprintf(stdout, "\n"); 693238104Sdes } else { 694238104Sdes result = 6; 695238104Sdes fprintf(stdout, "%s ", BOGUS); 696238104Sdes printf("Error verifying denial of existence for "); 697238104Sdes ldns_rdf_print(stdout, name); 698238104Sdes printf(" type "); 699238104Sdes if (descriptor && descriptor->_name) { 700238104Sdes printf("%s", descriptor->_name); 701238104Sdes } else { 702238104Sdes printf("TYPE%u", t); 703238104Sdes } 704238104Sdes printf(": %s\n", ldns_get_errorstr_by_id(st)); 705238104Sdes } 706238104Sdes 707238104Sdes ldns_rr_list_deep_free(nsec_rrs); 708238104Sdes ldns_rr_list_deep_free(nsec_rr_sigs); 709238104Sdes } else { 710238104Sdes/* 711238104Sdes*/ 712238104Sdes if (status == LDNS_STATUS_CRYPTO_NO_RRSIG) { 713238104Sdes printf("%s ", UNSIGNED); 714238104Sdes printf("No data found for: "); 715238104Sdes ldns_rdf_print(stdout, name); 716238104Sdes printf(" type "); 717238104Sdes if (descriptor && descriptor->_name) { 718238104Sdes printf("%s", descriptor->_name); 719238104Sdes } else { 720238104Sdes printf("TYPE%u", t); 721238104Sdes } 722238104Sdes printf("\n"); 723238104Sdes } else { 724238104Sdes printf("[B] Unable to verify denial of existence for "); 725238104Sdes ldns_rdf_print(stdout, name); 726238104Sdes printf(" type "); 727238104Sdes if (descriptor && descriptor->_name) { 728238104Sdes printf("%s", descriptor->_name); 729238104Sdes } else { 730238104Sdes printf("TYPE%u", t); 731238104Sdes } 732238104Sdes printf("\n"); 733238104Sdes } 734238104Sdes 735238104Sdes } 736238104Sdes } 737238104Sdes ldns_pkt_free(p); 738238104Sdes } 739238104Sdes 740238104Sdes new_nss = NULL; 741238104Sdes ns_addr = NULL; 742238104Sdes ldns_rr_list_deep_free(key_list); 743238104Sdes key_list = NULL; 744238104Sdes ldns_rr_list_deep_free(key_sig_list); 745238104Sdes key_sig_list = NULL; 746238104Sdes ds_list = NULL; 747238104Sdes ldns_rr_list_deep_free(ds_sig_list); 748238104Sdes ds_sig_list = NULL; 749238104Sdes } 750238104Sdes printf(";;" SELF " self sig OK; " BOGUS " bogus; " TRUST " trusted\n"); 751238104Sdes /* verbose mode? 752238104Sdes printf("Trusted keys:\n"); 753238104Sdes ldns_rr_list_print(stdout, trusted_keys); 754238104Sdes printf("trusted dss:\n"); 755238104Sdes ldns_rr_list_print(stdout, trusted_ds_rrs); 756238104Sdes */ 757238104Sdes 758238104Sdes done: 759238104Sdes ldns_rr_list_deep_free(trusted_ds_rrs); 760238104Sdes ldns_rr_list_deep_free(correct_key_list); 761238104Sdes ldns_resolver_deep_free(res); 762238104Sdes if (labels) { 763238104Sdes for(i = 0 ; i < (ssize_t)labels_count + 2; i++) { 764238104Sdes ldns_rdf_deep_free(labels[i]); 765238104Sdes } 766238104Sdes LDNS_FREE(labels); 767238104Sdes } 768238104Sdes return result; 769238104Sdes} 770238104Sdes#endif /* HAVE_SSL */ 771