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