1 /*
2 * ldns-keyfetcher retrieves the DNSKEYS for a certain domain
3 * It traces the authoritative nameservers down from the root
4 * And uses TCP, to minimize spoofing danger.
5 *
6 * (c) NLnet Labs, 2006 - 2008
7 * See the file LICENSE for the license
8 */
9
10 #include "config.h"
11 #include <ldns/ldns.h>
12 #include <errno.h>
13
14 int verbosity = 0;
15 /* 0=use both ip4 and ip6 (default). 1=ip4only. 2=ip6only. */
16 uint8_t address_family = 0;
17 bool store_in_file = false;
18
19 static void
usage(FILE * fp,char * prog)20 usage(FILE *fp, char *prog) {
21 fprintf(fp, "%s domain\n", prog);
22 fprintf(fp, " retrieve the dnskeys for a domain\n");
23 fprintf(fp, "Options:\n");
24 fprintf(fp, "-4\t\tUse IPv4 only\n");
25 fprintf(fp, "-6\t\tUse IPv6 only\n");
26 fprintf(fp, "-h\t\tShow this help\n");
27 fprintf(fp, "-i\t\tInsecurer mode; don't do checks, just query for the keys\n");
28 fprintf(fp, "-r <file>\tUse file to read root hints from\n");
29 fprintf(fp, "-s\t\tDon't print the keys but store them in files\n\t\tcalled K<file>.+<alg>.+<keytag>.key\n");
30 fprintf(fp, "-v <int>\tVerbosity level (0-5, not verbose-very verbose)\n");
31 }
32
33 static ldns_rr_list *
retrieve_dnskeys(ldns_resolver * local_res,ldns_rdf * name,ldns_rr_type t,ldns_rr_class c,ldns_rr_list * dns_root)34 retrieve_dnskeys(ldns_resolver *local_res, ldns_rdf *name, ldns_rr_type t,
35 ldns_rr_class c, ldns_rr_list *dns_root)
36 {
37 ldns_resolver *res;
38 ldns_pkt *p;
39 ldns_rr_list *new_nss_a;
40 ldns_rr_list *new_nss_aaaa;
41 ldns_rr_list *new_nss;
42 ldns_rr_list *ns_addr;
43 ldns_rr_list *ns_addr2;
44 uint16_t loop_count;
45 ldns_rdf *pop;
46 ldns_status status;
47 size_t i;
48
49 size_t nss_i;
50 ldns_rr_list *answer_list = NULL;
51 ldns_rr_list *authority_list = NULL;
52
53 size_t last_nameserver_count;
54 ldns_rdf **last_nameservers;
55
56 loop_count = 0;
57 new_nss_a = NULL;
58 new_nss_aaaa = NULL;
59 new_nss = NULL;
60 ns_addr = NULL;
61 ns_addr2 = NULL;
62 p = ldns_pkt_new();
63 res = ldns_resolver_new();
64
65 if (!p || !res) {
66 fprintf(stderr, "Memory allocation failed");
67 return NULL;
68 }
69
70 if (verbosity >= 2) {
71 printf("Finding dnskey data for zone: ");
72 ldns_rdf_print(stdout, name);
73 printf("\n\n");
74 }
75
76 /* transfer some properties of local_res to res,
77 * because they were given on the command line */
78 ldns_resolver_set_ip6(res,
79 ldns_resolver_ip6(local_res));
80 ldns_resolver_set_port(res,
81 ldns_resolver_port(local_res));
82 ldns_resolver_set_debug(res,
83 ldns_resolver_debug(local_res));
84 ldns_resolver_set_dnssec(res,
85 ldns_resolver_dnssec(local_res));
86 ldns_resolver_set_fail(res,
87 ldns_resolver_fail(local_res));
88 ldns_resolver_set_usevc(res,
89 ldns_resolver_usevc(local_res));
90 ldns_resolver_set_random(res,
91 ldns_resolver_random(local_res));
92 ldns_resolver_set_recursive(res, false);
93
94 /* setup the root nameserver in the new resolver */
95 status = ldns_resolver_push_nameserver_rr_list(res, dns_root);
96 if (status != LDNS_STATUS_OK) {
97 fprintf(stderr, "Error setting root nameservers in resolver: %s\n", ldns_get_errorstr_by_id(status));
98 return NULL;
99 }
100
101 ldns_pkt_free(p);
102 status = ldns_resolver_send(&p, res, name, t, c, 0);
103 if (status != LDNS_STATUS_OK) {
104 fprintf(stderr, "Error querying root servers: %s\n", ldns_get_errorstr_by_id(status));
105 return NULL;
106 }
107
108 if (ldns_pkt_get_rcode(p) != LDNS_RCODE_NOERROR) {
109 printf("Error in packet:\n");
110 ldns_pkt_print(stdout, p);
111 return NULL;
112 }
113
114 if (verbosity >= 4) {
115 ldns_pkt_print(stdout, p);
116 printf("\n\n");
117 }
118
119 /* from now on, use TCP */
120 ldns_resolver_set_usevc(res, true);
121
122 while(status == LDNS_STATUS_OK &&
123 ldns_pkt_reply_type(p) == LDNS_PACKET_REFERRAL) {
124
125 if (verbosity >= 3) {
126 printf("This is a delegation!\n\n");
127 }
128 if (address_family == 0 || address_family == 1) {
129 new_nss_a = ldns_pkt_rr_list_by_type(p,
130 LDNS_RR_TYPE_A, LDNS_SECTION_ADDITIONAL);
131 } else {
132 new_nss_a = ldns_rr_list_new();
133 }
134 if (address_family == 0 || address_family == 2) {
135 new_nss_aaaa = ldns_pkt_rr_list_by_type(p,
136 LDNS_RR_TYPE_AAAA, LDNS_SECTION_ADDITIONAL);
137 } else {
138 new_nss_aaaa = ldns_rr_list_new();
139 }
140 new_nss = ldns_pkt_rr_list_by_type(p,
141 LDNS_RR_TYPE_NS, LDNS_SECTION_AUTHORITY);
142
143 /* remove the old nameserver from the resolver */
144 while((pop = ldns_resolver_pop_nameserver(res))) { ldns_rdf_deep_free(pop); }
145
146 /* also check for new_nss emptiness */
147
148 if (!new_nss_aaaa && !new_nss_a) {
149 /*
150 * no nameserver found!!!
151 * try to resolve the names we do got
152 */
153 if (verbosity >= 3) {
154 printf("Did not get address record for nameserver, doing separate query.\n");
155 }
156 ns_addr = ldns_rr_list_new();
157 for(i = 0; (size_t) i < ldns_rr_list_rr_count(new_nss); i++) {
158 /* get the name of the nameserver */
159 pop = ldns_rr_rdf(ldns_rr_list_rr(new_nss, i), 0);
160 if (!pop) {
161 break;
162 }
163
164 /* retrieve it's addresses */
165 ns_addr2 = ldns_get_rr_list_addr_by_name(local_res, pop, c, 0);
166 if (!ldns_rr_list_cat(ns_addr, ns_addr2)) {
167 fprintf(stderr, "Internal error adding nameserver address.\n");
168 exit(EXIT_FAILURE);
169 }
170 ldns_rr_list_free(ns_addr2);
171 }
172
173 if (ns_addr) {
174 if (ldns_resolver_push_nameserver_rr_list(res, ns_addr) !=
175 LDNS_STATUS_OK) {
176 fprintf(stderr, "Error adding new nameservers");
177 ldns_pkt_free(p);
178 return NULL;
179 }
180 ldns_rr_list_deep_free(ns_addr);
181 } else {
182 ldns_rr_list_print(stdout, ns_addr);
183 fprintf(stderr, "Could not find the nameserver ip addr; abort");
184 ldns_pkt_free(p);
185 return NULL;
186 }
187 }
188
189 /* normally, the first working ns is used, but we need all now, so do it one by one
190 * if the answer is null, take it from the next resolver
191 * if the answer is not, compare it to that of the next resolver
192 * error if different, continue if the same
193 * if answer list null and no resolvers left die.
194 */
195
196 ldns_rr_list_deep_free(answer_list);
197 ldns_rr_list_deep_free(authority_list);
198 answer_list = NULL;
199 authority_list = NULL;
200 for (nss_i = 0; nss_i < ldns_rr_list_rr_count(new_nss_aaaa); nss_i++) {
201 while((pop = ldns_resolver_pop_nameserver(res))) { ldns_rdf_deep_free(pop); }
202
203 status = ldns_resolver_push_nameserver(res, ldns_rr_rdf(ldns_rr_list_rr(new_nss_aaaa, nss_i), 0));
204 if (status != LDNS_STATUS_OK) {
205 fprintf(stderr, "Error adding nameserver to resolver: %s\n", ldns_get_errorstr_by_id(status));
206 }
207
208 if (verbosity >= 1) {
209 fprintf(stdout, "Querying nameserver: ");
210 ldns_rdf_print(stdout, ldns_rr_owner(ldns_rr_list_rr(new_nss_aaaa, nss_i)));
211 fprintf(stdout, " (");
212 ldns_rdf_print(stdout, ldns_rr_rdf(ldns_rr_list_rr(new_nss_aaaa, nss_i), 0));
213 fprintf(stdout, ")\n");
214 }
215 status = ldns_resolver_push_nameserver(res, ldns_rr_rdf(ldns_rr_list_rr(new_nss_aaaa, nss_i), 0));
216 if (status != LDNS_STATUS_OK) {
217 fprintf(stderr, "Error adding nameserver to resolver: %s\n", ldns_get_errorstr_by_id(status));
218 }
219
220 ldns_pkt_free(p);
221 status = ldns_resolver_send(&p, res, name, t, c, 0);
222 if (status == LDNS_STATUS_OK && p) {
223 if (ldns_pkt_get_rcode(p) != LDNS_RCODE_NOERROR) {
224 printf("Error in packet:\n");
225 ldns_pkt_print(stdout, p);
226 return NULL;
227 }
228
229 if (verbosity >= 4) {
230 ldns_pkt_print(stdout, p);
231 printf("\n\n");
232 }
233
234 if (answer_list) {
235 if (verbosity >= 2) {
236 printf("Comparing answer list of answer to previous\n\n");
237 }
238 ldns_rr_list_sort(ldns_pkt_answer(p));
239 ldns_rr_list_sort(answer_list);
240 if (ldns_rr_list_compare(answer_list, ldns_pkt_answer(p)) != 0) {
241 fprintf(stderr, "ERROR: different answer answer from nameserver\n");
242 fprintf(stderr, "\nI had (from previous servers):\n");
243 ldns_rr_list_print(stderr, answer_list);
244 fprintf(stderr, "\nI received (from nameserver at ");
245 ldns_rdf_print(stderr, ldns_resolver_nameservers(res)[0]);
246 fprintf(stderr, "):\n");
247 ldns_rr_list_print(stderr, ldns_pkt_answer(p));
248 exit(EXIT_FAILURE);
249 }
250 } else {
251 answer_list = ldns_rr_list_clone(ldns_pkt_answer(p));
252 ldns_rr_list_sort(answer_list);
253 if (verbosity >= 2) {
254 printf("First answer list for this set, nothing to compare with\n\n");
255 }
256 }
257 if (authority_list) {
258 if (verbosity >= 2) {
259 printf("Comparing authority list of answer to previous\n\n");
260 }
261 ldns_rr_list_sort(ldns_pkt_authority(p));
262 ldns_rr_list_sort(authority_list);
263 if (ldns_rr_list_compare(authority_list, ldns_pkt_authority(p)) != 0) {
264 fprintf(stderr, "ERROR: different authority answer from nameserver\n");
265 fprintf(stderr, "\nI had (from previous servers):\n");
266 ldns_rr_list_print(stderr, authority_list);
267 fprintf(stderr, "\nI received (from nameserver at ");
268 ldns_rdf_print(stderr, ldns_resolver_nameservers(res)[0]);
269 fprintf(stderr, "):\n");
270 ldns_rr_list_print(stderr, ldns_pkt_authority(p));
271 exit(EXIT_FAILURE);
272 }
273 } else {
274 authority_list = ldns_rr_list_clone(ldns_pkt_authority(p));
275 ldns_rr_list_sort(authority_list);
276 if (verbosity >= 2) {
277 printf("First authority list for this set, nothing to compare with\n\n");
278 }
279 if (verbosity >= 3) {
280 printf("NS RRset:\n");
281 ldns_rr_list_print(stdout, authority_list);
282 printf("\n");
283 }
284 }
285 }
286 }
287
288 ldns_rr_list_deep_free(answer_list);
289 ldns_rr_list_deep_free(authority_list);
290 answer_list = NULL;
291 authority_list = NULL;
292 for (nss_i = 0; nss_i < ldns_rr_list_rr_count(new_nss_a); nss_i++) {
293
294 while((pop = ldns_resolver_pop_nameserver(res))) {ldns_rdf_deep_free(pop); }
295
296 if (verbosity >= 1) {
297 fprintf(stdout, "Querying nameserver: ");
298 ldns_rdf_print(stdout, ldns_rr_owner(ldns_rr_list_rr(new_nss_a, nss_i)));
299 fprintf(stdout, " (");
300 ldns_rdf_print(stdout, ldns_rr_rdf(ldns_rr_list_rr(new_nss_a, nss_i), 0));
301 fprintf(stdout, ")\n");
302 }
303 status = ldns_resolver_push_nameserver(res, ldns_rr_rdf(ldns_rr_list_rr(new_nss_a, nss_i), 0));
304 if (status != LDNS_STATUS_OK) {
305 fprintf(stderr, "Error adding nameserver to resolver: %s\n", ldns_get_errorstr_by_id(status));
306 }
307
308 ldns_pkt_free(p);
309 status = ldns_resolver_send(&p, res, name, t, c, 0);
310
311 if (status == LDNS_STATUS_OK) {
312 if (ldns_pkt_get_rcode(p) != LDNS_RCODE_NOERROR) {
313 printf("Error in packet:\n");
314 ldns_pkt_print(stdout, p);
315 return NULL;
316 }
317
318 if (verbosity >= 4) {
319 ldns_pkt_print(stdout, p);
320 printf("\n\n");
321 }
322
323 if (answer_list) {
324 if (verbosity >= 2) {
325 printf("Comparing answer list of answer to previous\n\n");
326 }
327 ldns_rr_list_sort(ldns_pkt_answer(p));
328 ldns_rr_list_sort(answer_list);
329 if (ldns_rr_list_compare(answer_list, ldns_pkt_answer(p)) != 0) {
330 fprintf(stderr, "ERROR: different answer answer from nameserver\n");
331 fprintf(stderr, "\nI had (from previous servers):\n");
332 ldns_rr_list_print(stderr, answer_list);
333 fprintf(stderr, "\nI received (from nameserver at ");
334 ldns_rdf_print(stderr, ldns_resolver_nameservers(res)[0]);
335 fprintf(stderr, "):\n");
336 ldns_rr_list_print(stderr, ldns_pkt_answer(p));
337 exit(EXIT_FAILURE);
338 }
339 } else {
340 if (verbosity >= 2) {
341 printf("First answer list for this set, nothing to compare with\n\n");
342 }
343 answer_list = ldns_rr_list_clone(ldns_pkt_answer(p));
344 ldns_rr_list_sort(answer_list);
345 }
346 if (authority_list) {
347 if (verbosity >= 2) {
348 printf("Comparing authority list of answer to previous\n\n");
349 }
350 ldns_rr_list_sort(ldns_pkt_authority(p));
351 ldns_rr_list_sort(authority_list);
352 if (ldns_rr_list_compare(authority_list, ldns_pkt_authority(p)) != 0) {
353 fprintf(stderr, "ERROR: different authority answer from nameserver\n");
354 fprintf(stderr, "\nI had (from previous servers):\n");
355 ldns_rr_list_print(stderr, authority_list);
356 fprintf(stderr, "\nI received (from nameserver at ");
357 ldns_rdf_print(stderr, ldns_resolver_nameservers(res)[0]);
358 fprintf(stderr, "):\n");
359 ldns_rr_list_print(stderr, ldns_pkt_authority(p));
360 exit(EXIT_FAILURE);
361 }
362 } else {
363 if (verbosity >= 2) {
364 printf("First authority list for this set, nothing to compare with\n\n");
365 }
366 authority_list = ldns_rr_list_clone(ldns_pkt_authority(p));
367 ldns_rr_list_sort(authority_list);
368 if (verbosity >= 3) {
369 printf("NS RRset:\n");
370 ldns_rr_list_print(stdout, authority_list);
371 printf("\n");
372 }
373 }
374 }
375 }
376 ldns_rr_list_deep_free(authority_list);
377 authority_list = NULL;
378
379 if (loop_count++ > 20) {
380 /* unlikely that we are doing something useful */
381 fprintf(stderr, "Looks like we are looping");
382 ldns_pkt_free(p);
383 return NULL;
384 }
385
386 ldns_pkt_free(p);
387
388 if (verbosity >= 3) {
389 fprintf(stdout, "This level ok. Continuing to next.\n\n");
390 }
391
392 status = ldns_resolver_send(&p, res, name, t, c, 0);
393
394 if (status != LDNS_STATUS_OK) {
395 fprintf(stderr, "Error querying root servers: %s\n", ldns_get_errorstr_by_id(status));
396 return NULL;
397 }
398
399 if (ldns_pkt_get_rcode(p) != LDNS_RCODE_NOERROR) {
400 printf("Error in packet:\n");
401 ldns_pkt_print(stdout, p);
402 return NULL;
403 }
404
405 if (verbosity >= 4) {
406 ldns_pkt_print(stdout, p);
407 printf("\n\n");
408 }
409
410
411 ldns_rr_list_deep_free(new_nss_aaaa);
412 ldns_rr_list_deep_free(new_nss_a);
413 ldns_rr_list_deep_free(new_nss);
414 new_nss_aaaa = NULL;
415 new_nss_a = NULL;
416 ns_addr = NULL;
417 }
418
419 ldns_rr_list_deep_free(answer_list);
420 answer_list = NULL;
421 /* clone the nameserver list, we are going to handle them one by one */
422 last_nameserver_count = 0;
423 last_nameservers = LDNS_XMALLOC(ldns_rdf *, ldns_resolver_nameserver_count(res));
424
425 pop = NULL;
426 while((pop = ldns_resolver_pop_nameserver(res))) {
427 last_nameservers[last_nameserver_count] = pop;
428 last_nameserver_count++;
429 }
430
431 for (nss_i = 0; nss_i < last_nameserver_count; nss_i++) {
432 /* remove previous nameserver */
433 while((pop = ldns_resolver_pop_nameserver(res))) { ldns_rdf_deep_free(pop); }
434
435 if (verbosity >= 1) {
436 printf("Querying nameserver: ");
437 ldns_rdf_print(stdout, last_nameservers[nss_i]);
438 printf("\n");
439 }
440 status = ldns_resolver_push_nameserver(res, last_nameservers[nss_i]);
441 if (status != LDNS_STATUS_OK) {
442 fprintf(stderr, "Error adding nameserver to resolver: %s\n", ldns_get_errorstr_by_id(status));
443 }
444
445 ldns_pkt_free(p);
446 status = ldns_resolver_send(&p, res, name, t, c, 0);
447
448 if (!p) {
449 fprintf(stderr, "no packet received\n");
450 LDNS_FREE(last_nameservers);
451 return NULL;
452 }
453
454 if (status == LDNS_STATUS_RES_NO_NS) {
455 fprintf(stderr, "Error: nameserver at ");
456 ldns_rdf_print(stderr, last_nameservers[nss_i]);
457 fprintf(stderr, " not responding. Unable to check RRset here, aborting.\n");
458 LDNS_FREE(last_nameservers);
459 return NULL;
460 }
461
462 if (ldns_pkt_get_rcode(p) != LDNS_RCODE_NOERROR) {
463 printf("Error in packet:\n");
464 ldns_pkt_print(stdout, p);
465 LDNS_FREE(last_nameservers);
466 return NULL;
467 }
468
469 if (answer_list) {
470 if (verbosity >= 2) {
471 printf("1Comparing answer rr list of answer to previous\n");
472 }
473 ldns_rr_list_sort(ldns_pkt_answer(p));
474 ldns_rr_list_sort(answer_list);
475 if (ldns_rr_list_compare(answer_list, ldns_pkt_answer(p)) != 0) {
476 printf("ERROR: different answer section in response from nameserver\n");
477 fprintf(stderr, "\nI had:\n");
478 ldns_rr_list_print(stderr, answer_list);
479 fprintf(stderr, "\nI received (from nameserver at ");
480 ldns_rdf_print(stderr, ldns_resolver_nameservers(res)[0]);
481 fprintf(stderr, "):\n");
482 ldns_rr_list_print(stderr, ldns_pkt_answer(p));
483 exit(EXIT_FAILURE);
484 }
485 } else {
486 if (verbosity >= 2) {
487 printf("First answer rr list for this set, nothing to compare with\n");
488 }
489 answer_list = ldns_rr_list_clone(ldns_pkt_answer(p));
490 if (verbosity >= 3) {
491 printf("DNSKEY RRset:\n");
492 ldns_rr_list_print(stdout, answer_list);
493 }
494 }
495
496 }
497
498 for (nss_i = 0; nss_i < last_nameserver_count; nss_i++) {
499 ldns_rdf_deep_free(last_nameservers[nss_i]);
500 }
501 LDNS_FREE(last_nameservers);
502 ldns_resolver_deep_free(res);
503 ldns_pkt_free(p);
504 return answer_list;
505 }
506
507
508 /*
509 * The file with the given path should contain a list of NS RRs
510 * for the root zone and A records for those NS RRs.
511 * Read them, check them, and append the a records to the rr list given.
512 */
513 static ldns_rr_list *
read_root_hints(const char * filename)514 read_root_hints(const char *filename)
515 {
516 FILE *fp = NULL;
517 int line_nr = 0;
518 ldns_zone *z;
519 ldns_status status;
520 ldns_rr_list *addresses = NULL;
521 ldns_rr *rr;
522 size_t i;
523
524 fp = fopen(filename, "r");
525 if (!fp) {
526 fprintf(stderr, "Unable to open %s for reading: %s\n", filename, strerror(errno));
527 return NULL;
528 }
529
530 status = ldns_zone_new_frm_fp_l(&z, fp, NULL, 0, 0, &line_nr);
531 fclose(fp);
532 if (status != LDNS_STATUS_OK) {
533 fprintf(stderr, "Error reading root hints file: %s\n", ldns_get_errorstr_by_id(status));
534 return NULL;
535 } else {
536 addresses = ldns_rr_list_new();
537 for (i = 0; i < ldns_rr_list_rr_count(ldns_zone_rrs(z)); i++) {
538 rr = ldns_rr_list_rr(ldns_zone_rrs(z), i);
539 if ((address_family == 0 || address_family == 1) &&
540 ldns_rr_get_type(rr) == LDNS_RR_TYPE_A ) {
541 ldns_rr_list_push_rr(addresses, ldns_rr_clone(rr));
542 }
543 if ((address_family == 0 || address_family == 2) &&
544 ldns_rr_get_type(rr) == LDNS_RR_TYPE_AAAA) {
545 ldns_rr_list_push_rr(addresses, ldns_rr_clone(rr));
546 }
547 }
548 ldns_zone_deep_free(z);
549 return addresses;
550 }
551 }
552
553
554 int
main(int argc,char * argv[])555 main(int argc, char *argv[])
556 {
557 ldns_resolver *res;
558 ldns_rdf *ns;
559 ldns_rdf *domain;
560 ldns_rr_list *l = NULL;
561
562 ldns_rr_list *dns_root = NULL;
563 const char *root_file = "/etc/named.root";
564
565 ldns_status status;
566
567 int i;
568
569 char *domain_str;
570 char *outputfile_str;
571 ldns_buffer *outputfile_buffer;
572 FILE *outputfile;
573 ldns_rr *k;
574
575 bool insecure = false;
576 ldns_pkt *pkt;
577
578 domain = NULL;
579 res = NULL;
580
581 if (argc < 2) {
582 usage(stdout, argv[0]);
583 exit(EXIT_FAILURE);
584 } else {
585 for (i = 1; i < argc; i++) {
586 if (strncmp("-4", argv[i], 3) == 0) {
587 if (address_family != 0) {
588 fprintf(stderr, "Options -4 and -6 cannot be specified at the same time\n");
589 exit(EXIT_FAILURE);
590 }
591 address_family = 1;
592 } else if (strncmp("-6", argv[i], 3) == 0) {
593 if (address_family != 0) {
594 fprintf(stderr, "Options -4 and -6 cannot be specified at the same time\n");
595 exit(EXIT_FAILURE);
596 }
597 address_family = 2;
598 } else if (strncmp("-h", argv[i], 3) == 0) {
599 usage(stdout, argv[0]);
600 exit(EXIT_SUCCESS);
601 } else if (strncmp("-i", argv[i], 2) == 0) {
602 insecure = true;
603 } else if (strncmp("-r", argv[i], 2) == 0) {
604 if (strlen(argv[i]) > 2) {
605 root_file = argv[i]+2;
606 } else if (i+1 >= argc) {
607 usage(stdout, argv[0]);
608 exit(EXIT_FAILURE);
609 } else {
610 root_file = argv[i+1];
611 i++;
612 }
613 } else if (strncmp("-s", argv[i], 3) == 0) {
614 store_in_file = true;
615 } else if (strncmp("-v", argv[i], 2) == 0) {
616 if (strlen(argv[i]) > 2) {
617 verbosity = atoi(argv[i]+2);
618 } else if (i+1 > argc) {
619 usage(stdout, argv[0]);
620 exit(EXIT_FAILURE);
621 } else {
622 verbosity = atoi(argv[i+1]);
623 i++;
624 }
625 } else {
626 /* create a rdf from the command line arg */
627 if (domain) {
628 fprintf(stdout, "You can only specify one domain at a time\n");
629 exit(EXIT_FAILURE);
630 }
631
632 domain = ldns_dname_new_frm_str(argv[i]);
633 }
634
635 }
636 if (!domain) {
637 usage(stdout, argv[0]);
638 exit(EXIT_FAILURE);
639 }
640 }
641
642 dns_root = read_root_hints(root_file);
643 if (!dns_root) {
644 fprintf(stderr, "cannot read the root hints file\n");
645 exit(EXIT_FAILURE);
646 }
647
648 /* create a new resolver from /etc/resolv.conf */
649 status = ldns_resolver_new_frm_file(&res, NULL);
650
651 if (status != LDNS_STATUS_OK) {
652 fprintf(stderr, "Warning: Unable to create stub resolver from /etc/resolv.conf:\n");
653 fprintf(stderr, "%s\n", ldns_get_errorstr_by_id(status));
654 fprintf(stderr, "defaulting to nameserver at 127.0.0.1 for separate nameserver name lookups\n");
655 do {
656 res = ldns_resolver_new();
657 if (res) {
658 ns = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_A,
659 "127.0.0.1");
660 if (ns) {
661 status = ldns_resolver_push_nameserver(
662 res, ns);
663 if (status == LDNS_STATUS_OK) {
664 break;
665 }
666 ldns_rdf_deep_free(ns);
667 }
668 ldns_resolver_free(res);
669 }
670 fprintf(stderr, "Unable to create stub resolver: %s\n",
671 ldns_get_errorstr_by_id(status));
672 exit(EXIT_FAILURE);
673
674 } while (false);
675 ldns_rdf_deep_free(ns);
676 }
677
678 ldns_resolver_set_ip6(res, address_family);
679
680 if (insecure) {
681 pkt = ldns_resolver_query(res, domain, LDNS_RR_TYPE_DNSKEY, LDNS_RR_CLASS_IN, LDNS_RD);
682 if (pkt) {
683 l = ldns_pkt_rr_list_by_type(pkt, LDNS_RR_TYPE_DNSKEY, LDNS_SECTION_ANY_NOQUESTION);
684 }
685 } else {
686 l = retrieve_dnskeys(res, domain, LDNS_RR_TYPE_DNSKEY, LDNS_RR_CLASS_IN, dns_root);
687 }
688
689 /* separator for result data and verbosity data */
690 if (verbosity > 0) {
691 fprintf(stdout, "; ---------------------------\n");
692 fprintf(stdout, "; Got the following keys:\n");
693 }
694 if (l) {
695 if (store_in_file) {
696 /* create filename:
697 * K<domain>.+<alg>.+<id>.key
698 */
699 for (i = 0; (size_t) i < ldns_rr_list_rr_count(l); i++) {
700 k = ldns_rr_list_rr(l, (size_t) i);
701
702 outputfile_buffer = ldns_buffer_new(300);
703 domain_str = ldns_rdf2str(ldns_rr_owner(k));
704 ldns_buffer_printf(outputfile_buffer, "K%s+%03u+%05u.key", domain_str, ldns_rdf2native_int8(ldns_rr_rdf(k, 2)),
705 (unsigned int) ldns_calc_keytag(k));
706 outputfile_str = ldns_buffer_export(outputfile_buffer);
707
708 if (verbosity >= 1) {
709 fprintf(stdout, "Writing key to file %s\n", outputfile_str);
710 }
711
712 outputfile = fopen(outputfile_str, "w");
713 if (!outputfile) {
714 fprintf(stderr, "Error writing key to file %s: %s\n", outputfile_str, strerror(errno));
715 } else {
716 ldns_rr_print(outputfile, k);
717 fclose(outputfile);
718 }
719
720 LDNS_FREE(domain_str);
721 LDNS_FREE(outputfile_str);
722 LDNS_FREE(outputfile_buffer);
723 }
724 } else {
725 ldns_rr_list_print(stdout, l);
726 }
727 } else {
728 fprintf(stderr, "no answer packet received, stub resolver config:\n");
729 ldns_resolver_print(stderr, res);
730 }
731
732 ldns_rdf_deep_free(domain);
733 ldns_resolver_deep_free(res);
734 ldns_rr_list_deep_free(l);
735 ldns_rr_list_deep_free(dns_root);
736 return EXIT_SUCCESS;
737 }
738