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