1/*
2 * chasetrace.c
3 * Where all the hard work concerning chasing
4 * and tracing is done
5 * (c) 2005, 2006 NLnet Labs
6 *
7 * See the file LICENSE for the license
8 *
9 */
10
11#include "drill.h"
12#include <ldns/ldns.h>
13
14/**
15 * trace down from the root to name
16 */
17
18/* same naive method as in drill0.9
19 * We resolver _ALL_ the names, which is ofcourse not needed
20 * We _do_ use the local resolver to do that, so it still is
21 * fast, but it can be made to run much faster
22 */
23ldns_pkt *
24do_trace(ldns_resolver *local_res, ldns_rdf *name, ldns_rr_type t,
25		ldns_rr_class c)
26{
27	ldns_resolver *res;
28	ldns_pkt *p;
29	ldns_rr_list *new_nss_a;
30	ldns_rr_list *new_nss_aaaa;
31	ldns_rr_list *final_answer;
32	ldns_rr_list *new_nss;
33	ldns_rr_list *ns_addr;
34	uint16_t loop_count;
35	ldns_rdf *pop;
36	ldns_status status;
37	size_t i;
38
39	loop_count = 0;
40	new_nss_a = NULL;
41	new_nss_aaaa = NULL;
42	new_nss = NULL;
43	ns_addr = NULL;
44	final_answer = NULL;
45	p = ldns_pkt_new();
46	res = ldns_resolver_new();
47
48	if (!p) {
49		if (res) {
50			ldns_resolver_free(res);
51		}
52                error("Memory allocation failed");
53                return NULL;
54	}
55	if (!res) {
56		ldns_pkt_free(p);
57                error("Memory allocation failed");
58                return NULL;
59        }
60
61	/* transfer some properties of local_res to res,
62	 * because they were given on the commandline */
63	ldns_resolver_set_ip6(res,
64			ldns_resolver_ip6(local_res));
65	ldns_resolver_set_port(res,
66			ldns_resolver_port(local_res));
67	ldns_resolver_set_debug(res,
68			ldns_resolver_debug(local_res));
69	ldns_resolver_set_dnssec(res,
70			ldns_resolver_dnssec(local_res));
71	ldns_resolver_set_fail(res,
72			ldns_resolver_fail(local_res));
73	ldns_resolver_set_usevc(res,
74			ldns_resolver_usevc(local_res));
75	ldns_resolver_set_random(res,
76			ldns_resolver_random(local_res));
77	ldns_resolver_set_source(res,
78			ldns_resolver_source(local_res));
79	ldns_resolver_set_recursive(res, false);
80
81	/* setup the root nameserver in the new resolver */
82	status = ldns_resolver_push_nameserver_rr_list(res, global_dns_root);
83	if (status != LDNS_STATUS_OK) {
84		fprintf(stderr, "Error adding root servers to resolver: %s\n", ldns_get_errorstr_by_id(status));
85		ldns_rr_list_print(stdout, global_dns_root);
86		ldns_resolver_free(res);
87		ldns_pkt_free(p);
88		return NULL;
89	}
90
91	/* this must be a real query to local_res */
92	status = ldns_resolver_send(&p, res, ldns_dname_new_frm_str("."), LDNS_RR_TYPE_NS, c, 0);
93	/* p can still be NULL */
94
95
96	if (ldns_pkt_empty(p)) {
97		warning("No root server information received");
98	}
99
100	if (status == LDNS_STATUS_OK) {
101		if (!ldns_pkt_empty(p)) {
102			drill_pkt_print(stdout, local_res, p);
103		}
104	} else {
105		error("cannot use local resolver");
106		return NULL;
107	}
108
109	status = ldns_resolver_send(&p, res, name, t, c, 0);
110
111	while(status == LDNS_STATUS_OK &&
112	      ldns_pkt_reply_type(p) == LDNS_PACKET_REFERRAL) {
113
114		if (!p) {
115			/* some error occurred, bail out */
116			return NULL;
117		}
118
119		new_nss_a = ldns_pkt_rr_list_by_type(p,
120				LDNS_RR_TYPE_A, LDNS_SECTION_ADDITIONAL);
121		new_nss_aaaa = ldns_pkt_rr_list_by_type(p,
122				LDNS_RR_TYPE_AAAA, LDNS_SECTION_ADDITIONAL);
123		new_nss = ldns_pkt_rr_list_by_type(p,
124				LDNS_RR_TYPE_NS, LDNS_SECTION_AUTHORITY);
125
126		if (verbosity != -1) {
127			ldns_rr_list_print(stdout, new_nss);
128		}
129		/* checks itself for verbosity */
130		drill_pkt_print_footer(stdout, local_res, p);
131
132		/* remove the old nameserver from the resolver */
133		while(ldns_resolver_pop_nameserver(res)) { /* do it */ }
134
135		/* also check for new_nss emptyness */
136
137		if (!new_nss_aaaa && !new_nss_a) {
138			/*
139			 * no nameserver found!!!
140			 * try to resolve the names we do got
141			 */
142			for(i = 0; i < ldns_rr_list_rr_count(new_nss); i++) {
143				/* get the name of the nameserver */
144				pop = ldns_rr_rdf(ldns_rr_list_rr(new_nss, i), 0);
145				if (!pop) {
146					break;
147				}
148
149				ldns_rr_list_print(stdout, new_nss);
150				ldns_rdf_print(stdout, pop);
151				/* retrieve it's addresses */
152				ns_addr = ldns_rr_list_cat_clone(ns_addr,
153					ldns_get_rr_list_addr_by_name(local_res, pop, c, 0));
154			}
155
156			if (ns_addr) {
157				if (ldns_resolver_push_nameserver_rr_list(res, ns_addr) !=
158						LDNS_STATUS_OK) {
159					error("Error adding new nameservers");
160					ldns_pkt_free(p);
161					return NULL;
162				}
163				ldns_rr_list_free(ns_addr);
164			} else {
165				ldns_rr_list_print(stdout, ns_addr);
166				error("Could not find the nameserver ip addr; abort");
167				ldns_pkt_free(p);
168				return NULL;
169			}
170		}
171
172		/* add the new ones */
173		if (new_nss_aaaa) {
174			if (ldns_resolver_push_nameserver_rr_list(res, new_nss_aaaa) !=
175					LDNS_STATUS_OK) {
176				error("adding new nameservers");
177				ldns_pkt_free(p);
178				return NULL;
179			}
180		}
181		if (new_nss_a) {
182			if (ldns_resolver_push_nameserver_rr_list(res, new_nss_a) !=
183					LDNS_STATUS_OK) {
184				error("adding new nameservers");
185				ldns_pkt_free(p);
186				return NULL;
187			}
188		}
189
190		if (loop_count++ > 20) {
191			/* unlikely that we are doing something usefull */
192			error("Looks like we are looping");
193			ldns_pkt_free(p);
194			return NULL;
195		}
196
197		status = ldns_resolver_send(&p, res, name, t, c, 0);
198		new_nss_aaaa = NULL;
199		new_nss_a = NULL;
200		ns_addr = NULL;
201	}
202
203	status = ldns_resolver_send(&p, res, name, t, c, 0);
204
205	if (!p) {
206		return NULL;
207	}
208
209	new_nss = ldns_pkt_authority(p);
210	final_answer = ldns_pkt_answer(p);
211
212	if (verbosity != -1) {
213		ldns_rr_list_print(stdout, final_answer);
214		ldns_rr_list_print(stdout, new_nss);
215
216	}
217	drill_pkt_print_footer(stdout, local_res, p);
218	ldns_pkt_free(p);
219	return NULL;
220}
221
222
223/**
224 * Chase the given rr to a known and trusted key
225 *
226 * Based on drill 0.9
227 *
228 * the last argument prev_key_list, if not null, and type == DS, then the ds
229 * rr list we have must all be a ds for the keys in this list
230 */
231#ifdef HAVE_SSL
232ldns_status
233do_chase(ldns_resolver *res,
234	    ldns_rdf *name,
235	    ldns_rr_type type,
236	    ldns_rr_class c,
237	    ldns_rr_list *trusted_keys,
238	    ldns_pkt *pkt_o,
239	    uint16_t qflags,
240	    ldns_rr_list * ATTR_UNUSED(prev_key_list),
241	    int verbosity)
242{
243	ldns_rr_list *rrset = NULL;
244	ldns_status result;
245	ldns_rr *orig_rr = NULL;
246
247/*
248	ldns_rr_list *sigs;
249	ldns_rr *cur_sig;
250	uint16_t sig_i;
251	ldns_rr_list *keys;
252*/
253	ldns_pkt *pkt;
254	ldns_status tree_result;
255	ldns_dnssec_data_chain *chain;
256	ldns_dnssec_trust_tree *tree;
257
258	const ldns_rr_descriptor *descriptor;
259	descriptor = ldns_rr_descript(type);
260
261	ldns_dname2canonical(name);
262
263	pkt = ldns_pkt_clone(pkt_o);
264	if (!name) {
265		mesg("No name to chase");
266		ldns_pkt_free(pkt);
267		return LDNS_STATUS_EMPTY_LABEL;
268	}
269	if (verbosity != -1) {
270		printf(";; Chasing: ");
271			ldns_rdf_print(stdout, name);
272			if (descriptor && descriptor->_name) {
273				printf(" %s\n", descriptor->_name);
274			} else {
275				printf(" type %d\n", type);
276			}
277	}
278
279	if (!trusted_keys || ldns_rr_list_rr_count(trusted_keys) < 1) {
280		warning("No trusted keys specified");
281	}
282
283	if (pkt) {
284		rrset = ldns_pkt_rr_list_by_name_and_type(pkt,
285				name,
286				type,
287				LDNS_SECTION_ANSWER
288				);
289		if (!rrset) {
290			/* nothing in answer, try authority */
291			rrset = ldns_pkt_rr_list_by_name_and_type(pkt,
292					name,
293					type,
294					LDNS_SECTION_AUTHORITY
295					);
296		}
297		/* answer might be a cname, chase that first, then chase
298		   cname target? (TODO) */
299		if (!rrset) {
300			rrset = ldns_pkt_rr_list_by_name_and_type(pkt,
301					name,
302					LDNS_RR_TYPE_CNAME,
303					LDNS_SECTION_ANSWER
304					);
305			if (!rrset) {
306				/* nothing in answer, try authority */
307				rrset = ldns_pkt_rr_list_by_name_and_type(pkt,
308						name,
309						LDNS_RR_TYPE_CNAME,
310						LDNS_SECTION_AUTHORITY
311						);
312			}
313		}
314	} else {
315		/* no packet? */
316		if (verbosity >= 0) {
317			fprintf(stderr, "%s", ldns_get_errorstr_by_id(LDNS_STATUS_MEM_ERR));
318			fprintf(stderr, "\n");
319		}
320		return LDNS_STATUS_MEM_ERR;
321	}
322
323	if (!rrset) {
324		/* not found in original packet, try again */
325		ldns_pkt_free(pkt);
326		pkt = NULL;
327		pkt = ldns_resolver_query(res, name, type, c, qflags);
328
329		if (!pkt) {
330			if (verbosity >= 0) {
331				fprintf(stderr, "%s", ldns_get_errorstr_by_id(LDNS_STATUS_NETWORK_ERR));
332				fprintf(stderr, "\n");
333			}
334			return LDNS_STATUS_NETWORK_ERR;
335		}
336		if (verbosity >= 5) {
337			ldns_pkt_print(stdout, pkt);
338		}
339
340		rrset =	ldns_pkt_rr_list_by_name_and_type(pkt,
341				name,
342				type,
343				LDNS_SECTION_ANSWER
344				);
345	}
346
347	orig_rr = ldns_rr_new();
348
349/* if the answer had no answer section, we need to construct our own rr (for instance if
350 * the rr qe asked for doesn't exist. This rr will be destroyed when the chain is freed */
351	if (ldns_pkt_ancount(pkt) < 1) {
352		ldns_rr_set_type(orig_rr, type);
353		ldns_rr_set_owner(orig_rr, ldns_rdf_clone(name));
354
355		chain = ldns_dnssec_build_data_chain(res, qflags, rrset, pkt, ldns_rr_clone(orig_rr));
356	} else {
357		/* chase the first answer */
358		chain = ldns_dnssec_build_data_chain(res, qflags, rrset, pkt, NULL);
359	}
360
361	if (verbosity >= 4) {
362		printf("\n\nDNSSEC Data Chain:\n");
363		ldns_dnssec_data_chain_print(stdout, chain);
364	}
365
366	result = LDNS_STATUS_OK;
367
368	tree = ldns_dnssec_derive_trust_tree(chain, NULL);
369
370	if (verbosity >= 2) {
371		printf("\n\nDNSSEC Trust tree:\n");
372		ldns_dnssec_trust_tree_print(stdout, tree, 0, true);
373	}
374
375	if (ldns_rr_list_rr_count(trusted_keys) > 0) {
376		tree_result = ldns_dnssec_trust_tree_contains_keys(tree, trusted_keys);
377
378		if (tree_result == LDNS_STATUS_DNSSEC_EXISTENCE_DENIED) {
379			if (verbosity >= 1) {
380				printf("Existence denied or verifiably insecure\n");
381			}
382			result = LDNS_STATUS_OK;
383		} else if (tree_result != LDNS_STATUS_OK) {
384			if (verbosity >= 1) {
385				printf("No trusted keys found in tree: first error was: %s\n", ldns_get_errorstr_by_id(tree_result));
386			}
387			result = tree_result;
388		}
389
390	} else {
391		if (verbosity >= 0) {
392			printf("You have not provided any trusted keys.\n");
393		}
394	}
395
396	ldns_rr_free(orig_rr);
397	ldns_dnssec_trust_tree_free(tree);
398	ldns_dnssec_data_chain_deep_free(chain);
399
400	ldns_rr_list_deep_free(rrset);
401	ldns_pkt_free(pkt);
402	/*	ldns_rr_free(orig_rr);*/
403
404	return result;
405}
406#endif /* HAVE_SSL */
407
408