xref: /freebsd/contrib/ldns/drill/chasetrace.c (revision 0b3105a37d7adcadcb720112fed4dc4e8040be99)
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  */
23 ldns_pkt *
24 do_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
232 ldns_status
233 do_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