]> CyberLeo.Net >> Repos - FreeBSD/releng/10.2.git/blob - contrib/ldns/drill/chasetrace.c
- Copy stable/10@285827 to releng/10.2 in preparation for 10.2-RC1
[FreeBSD/releng/10.2.git] / contrib / ldns / drill / chasetrace.c
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