1 /* $NetBSD: dighost.c,v 1.15 2015/07/08 17:28:54 christos Exp $ */ 2 3 /* 4 * Copyright (C) 2004-2015 Internet Systems Consortium, Inc. ("ISC") 5 * Copyright (C) 2000-2003 Internet Software Consortium. 6 * 7 * Permission to use, copy, modify, and/or distribute this software for any 8 * purpose with or without fee is hereby granted, provided that the above 9 * copyright notice and this permission notice appear in all copies. 10 * 11 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH 12 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 13 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, 14 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 15 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 16 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 17 * PERFORMANCE OF THIS SOFTWARE. 18 */ 19 20 /* Id: dighost.c,v 1.345 2011/12/07 17:23:28 each Exp */ 21 22 /*! \file 23 * \note 24 * Notice to programmers: Do not use this code as an example of how to 25 * use the ISC library to perform DNS lookups. Dig and Host both operate 26 * on the request level, since they allow fine-tuning of output and are 27 * intended as debugging tools. As a result, they perform many of the 28 * functions which could be better handled using the dns_resolver 29 * functions in most applications. 30 */ 31 32 #include <config.h> 33 #include <stdlib.h> 34 #include <unistd.h> 35 #include <string.h> 36 #include <limits.h> 37 38 #ifdef HAVE_LOCALE_H 39 #include <locale.h> 40 #endif 41 42 #ifdef WITH_IDN 43 #include <idn/result.h> 44 #include <idn/log.h> 45 #include <idn/resconf.h> 46 #include <idn/api.h> 47 #endif 48 49 #include <dns/byaddr.h> 50 #ifdef DIG_SIGCHASE 51 #include <dns/callbacks.h> 52 #include <dns/dnssec.h> 53 #include <dns/ds.h> 54 #include <dns/master.h> 55 #include <dns/nsec.h> 56 #include <isc/random.h> 57 #include <ctype.h> 58 #endif 59 #include <dns/fixedname.h> 60 #include <dns/log.h> 61 #include <dns/message.h> 62 #include <dns/name.h> 63 #include <dns/rcode.h> 64 #include <dns/rdata.h> 65 #include <dns/rdataclass.h> 66 #include <dns/rdatalist.h> 67 #include <dns/rdataset.h> 68 #include <dns/rdatastruct.h> 69 #include <dns/rdatatype.h> 70 #include <dns/result.h> 71 #include <dns/tsig.h> 72 73 #include <dst/dst.h> 74 #include <dst/result.h> 75 76 #include <isc/app.h> 77 #include <isc/base64.h> 78 #include <isc/entropy.h> 79 #include <isc/file.h> 80 #include <isc/hex.h> 81 #include <isc/lang.h> 82 #include <isc/log.h> 83 #include <isc/netaddr.h> 84 #include <isc/netdb.h> 85 #include <isc/parseint.h> 86 #include <isc/print.h> 87 #include <isc/random.h> 88 #include <isc/result.h> 89 #include <isc/serial.h> 90 #include <isc/sockaddr.h> 91 #include <isc/string.h> 92 #include <isc/task.h> 93 #include <isc/timer.h> 94 #include <isc/types.h> 95 #include <isc/util.h> 96 97 #include <isccfg/namedconf.h> 98 99 #include <lwres/lwres.h> 100 #include <lwres/net.h> 101 102 #include <bind9/getaddresses.h> 103 104 #include <dig/dig.h> 105 106 #ifdef PKCS11CRYPTO 107 #include <pk11/result.h> 108 #endif 109 110 #if ! defined(NS_INADDRSZ) 111 #define NS_INADDRSZ 4 112 #endif 113 114 #if ! defined(NS_IN6ADDRSZ) 115 #define NS_IN6ADDRSZ 16 116 #endif 117 118 static lwres_context_t *lwctx = NULL; 119 static lwres_conf_t *lwconf; 120 121 dig_lookuplist_t lookup_list; 122 dig_serverlist_t server_list; 123 dig_searchlistlist_t search_list; 124 125 isc_boolean_t 126 check_ra = ISC_FALSE, 127 have_ipv4 = ISC_FALSE, 128 have_ipv6 = ISC_FALSE, 129 specified_source = ISC_FALSE, 130 free_now = ISC_FALSE, 131 cancel_now = ISC_FALSE, 132 usesearch = ISC_FALSE, 133 showsearch = ISC_FALSE, 134 qr = ISC_FALSE, 135 is_dst_up = ISC_FALSE, 136 keep_open = ISC_FALSE; 137 in_port_t port = 53; 138 unsigned int timeout = 0; 139 unsigned int extrabytes; 140 isc_mem_t *mctx = NULL; 141 isc_log_t *lctx = NULL; 142 isc_taskmgr_t *taskmgr = NULL; 143 isc_task_t *global_task = NULL; 144 isc_timermgr_t *timermgr = NULL; 145 isc_socketmgr_t *socketmgr = NULL; 146 isc_sockaddr_t bind_address; 147 isc_sockaddr_t bind_any; 148 int sendcount = 0; 149 int recvcount = 0; 150 int sockcount = 0; 151 int ndots = -1; 152 int tries = 3; 153 int lookup_counter = 0; 154 155 #ifdef WITH_IDN 156 static void initialize_idn(void); 157 static isc_result_t output_filter(isc_buffer_t *buffer, 158 unsigned int used_org, 159 isc_boolean_t absolute); 160 static idn_result_t append_textname(char *name, const char *origin, 161 size_t namesize); 162 static void idn_check_result(idn_result_t r, const char *msg); 163 164 #define MAXDLEN 256 165 int idnoptions = 0; 166 #endif 167 168 isc_socket_t *keep = NULL; 169 isc_sockaddr_t keepaddr; 170 171 /*% 172 * Exit Codes: 173 * 174 *\li 0 Everything went well, including things like NXDOMAIN 175 *\li 1 Usage error 176 *\li 7 Got too many RR's or Names 177 *\li 8 Couldn't open batch file 178 *\li 9 No reply from server 179 *\li 10 Internal error 180 */ 181 int exitcode = 0; 182 int fatalexit = 0; 183 char keynametext[MXNAME]; 184 char keyfile[MXNAME] = ""; 185 char keysecret[MXNAME] = ""; 186 unsigned char cookie_secret[33]; 187 unsigned char cookie[8]; 188 dns_name_t *hmacname = NULL; 189 unsigned int digestbits = 0; 190 isc_buffer_t *namebuf = NULL; 191 dns_tsigkey_t *key = NULL; 192 isc_boolean_t validated = ISC_TRUE; 193 isc_entropy_t *entp = NULL; 194 isc_mempool_t *commctx = NULL; 195 isc_boolean_t debugging = ISC_FALSE; 196 isc_boolean_t debugtiming = ISC_FALSE; 197 isc_boolean_t memdebugging = ISC_FALSE; 198 const char *progname = NULL; 199 isc_mutex_t lookup_lock; 200 dig_lookup_t *current_lookup = NULL; 201 202 #ifdef DIG_SIGCHASE 203 204 isc_result_t get_trusted_key(isc_mem_t *mctx); 205 dns_rdataset_t * sigchase_scanname(dns_rdatatype_t type, 206 dns_rdatatype_t covers, 207 isc_boolean_t *lookedup, 208 dns_name_t *rdata_name); 209 dns_rdataset_t * chase_scanname_section(dns_message_t *msg, 210 dns_name_t *name, 211 dns_rdatatype_t type, 212 dns_rdatatype_t covers, 213 int section); 214 isc_result_t advanced_rrsearch(dns_rdataset_t **rdataset, 215 dns_name_t *name, 216 dns_rdatatype_t type, 217 dns_rdatatype_t covers, 218 isc_boolean_t *lookedup); 219 isc_result_t sigchase_verify_sig_key(dns_name_t *name, 220 dns_rdataset_t *rdataset, 221 dst_key_t* dnsseckey, 222 dns_rdataset_t *sigrdataset, 223 isc_mem_t *mctx); 224 isc_result_t sigchase_verify_sig(dns_name_t *name, 225 dns_rdataset_t *rdataset, 226 dns_rdataset_t *keyrdataset, 227 dns_rdataset_t *sigrdataset, 228 isc_mem_t *mctx); 229 isc_result_t sigchase_verify_ds(dns_name_t *name, 230 dns_rdataset_t *keyrdataset, 231 dns_rdataset_t *dsrdataset, 232 isc_mem_t *mctx); 233 void sigchase(dns_message_t *msg); 234 void print_rdata(dns_rdata_t *rdata, isc_mem_t *mctx); 235 void print_rdataset(dns_name_t *name, 236 dns_rdataset_t *rdataset, isc_mem_t *mctx); 237 void dup_name(dns_name_t *source, dns_name_t* target, 238 isc_mem_t *mctx); 239 void free_name(dns_name_t *name, isc_mem_t *mctx); 240 void dump_database(void); 241 void dump_database_section(dns_message_t *msg, int section); 242 dns_rdataset_t * search_type(dns_name_t *name, dns_rdatatype_t type, 243 dns_rdatatype_t covers); 244 isc_result_t contains_trusted_key(dns_name_t *name, 245 dns_rdataset_t *rdataset, 246 dns_rdataset_t *sigrdataset, 247 isc_mem_t *mctx); 248 void print_type(dns_rdatatype_t type); 249 isc_result_t prove_nx_domain(dns_message_t * msg, 250 dns_name_t * name, 251 dns_name_t * rdata_name, 252 dns_rdataset_t ** rdataset, 253 dns_rdataset_t ** sigrdataset); 254 isc_result_t prove_nx_type(dns_message_t * msg, dns_name_t *name, 255 dns_rdataset_t *nsec, 256 dns_rdataclass_t class, 257 dns_rdatatype_t type, 258 dns_name_t * rdata_name, 259 dns_rdataset_t ** rdataset, 260 dns_rdataset_t ** sigrdataset); 261 isc_result_t prove_nx(dns_message_t * msg, dns_name_t * name, 262 dns_rdataclass_t class, 263 dns_rdatatype_t type, 264 dns_name_t * rdata_name, 265 dns_rdataset_t ** rdataset, 266 dns_rdataset_t ** sigrdataset); 267 static void nameFromString(const char *str, dns_name_t *p_ret); 268 int inf_name(dns_name_t * name1, dns_name_t * name2); 269 isc_result_t removetmpkey(isc_mem_t *mctx, const char *file); 270 void clean_trustedkey(void); 271 isc_result_t insert_trustedkey(void *arg, dns_name_t *name, 272 dns_rdataset_t *rdataset); 273 #if DIG_SIGCHASE_BU 274 isc_result_t getneededrr(dns_message_t *msg); 275 void sigchase_bottom_up(dns_message_t *msg); 276 void sigchase_bu(dns_message_t *msg); 277 #endif 278 #if DIG_SIGCHASE_TD 279 isc_result_t initialization(dns_name_t *name); 280 isc_result_t prepare_lookup(dns_name_t *name); 281 isc_result_t grandfather_pb_test(dns_name_t * zone_name, 282 dns_rdataset_t *sigrdataset); 283 isc_result_t child_of_zone(dns_name_t *name, 284 dns_name_t *zone_name, 285 dns_name_t *child_name); 286 void sigchase_td(dns_message_t *msg); 287 #endif 288 char trustedkey[MXNAME] = ""; 289 290 dns_rdataset_t *chase_rdataset = NULL; 291 dns_rdataset_t *chase_sigrdataset = NULL; 292 dns_rdataset_t *chase_dsrdataset = NULL; 293 dns_rdataset_t *chase_sigdsrdataset = NULL; 294 dns_rdataset_t *chase_keyrdataset = NULL; 295 dns_rdataset_t *chase_sigkeyrdataset = NULL; 296 dns_rdataset_t *chase_nsrdataset = NULL; 297 298 dns_name_t chase_name; /* the query name */ 299 #if DIG_SIGCHASE_TD 300 /* 301 * the current name is the parent name when we follow delegation 302 */ 303 dns_name_t chase_current_name; 304 /* 305 * the child name is used for delegation (NS DS responses in AUTHORITY section) 306 */ 307 dns_name_t chase_authority_name; 308 #endif 309 #if DIG_SIGCHASE_BU 310 dns_name_t chase_signame; 311 #endif 312 313 314 isc_boolean_t chase_siglookedup = ISC_FALSE; 315 isc_boolean_t chase_keylookedup = ISC_FALSE; 316 isc_boolean_t chase_sigkeylookedup = ISC_FALSE; 317 isc_boolean_t chase_dslookedup = ISC_FALSE; 318 isc_boolean_t chase_sigdslookedup = ISC_FALSE; 319 #if DIG_SIGCHASE_TD 320 isc_boolean_t chase_nslookedup = ISC_FALSE; 321 isc_boolean_t chase_lookedup = ISC_FALSE; 322 323 324 isc_boolean_t delegation_follow = ISC_FALSE; 325 isc_boolean_t grandfather_pb = ISC_FALSE; 326 isc_boolean_t have_response = ISC_FALSE; 327 isc_boolean_t have_delegation_ns = ISC_FALSE; 328 dns_message_t * error_message = NULL; 329 #endif 330 331 isc_boolean_t dsvalidating = ISC_FALSE; 332 isc_boolean_t chase_name_dup = ISC_FALSE; 333 334 ISC_LIST(dig_message_t) chase_message_list; 335 ISC_LIST(dig_message_t) chase_message_list2; 336 337 338 #define MAX_TRUSTED_KEY 5 339 typedef struct struct_trusted_key_list { 340 dst_key_t * key[MAX_TRUSTED_KEY]; 341 int nb_tk; 342 } struct_tk_list; 343 344 struct_tk_list tk_list = { {NULL, NULL, NULL, NULL, NULL}, 0}; 345 346 #endif 347 348 #define DIG_MAX_ADDRESSES 20 349 350 /*% 351 * Apply and clear locks at the event level in global task. 352 * Can I get rid of these using shutdown events? XXX 353 */ 354 #define LOCK_LOOKUP {\ 355 debug("lock_lookup %s:%d", __FILE__, __LINE__);\ 356 check_result(isc_mutex_lock((&lookup_lock)), "isc_mutex_lock");\ 357 debug("success");\ 358 } 359 #define UNLOCK_LOOKUP {\ 360 debug("unlock_lookup %s:%d", __FILE__, __LINE__);\ 361 check_result(isc_mutex_unlock((&lookup_lock)),\ 362 "isc_mutex_unlock");\ 363 } 364 365 static void 366 cancel_lookup(dig_lookup_t *lookup); 367 368 static void 369 recv_done(isc_task_t *task, isc_event_t *event); 370 371 static void 372 send_udp(dig_query_t *query); 373 374 static void 375 connect_timeout(isc_task_t *task, isc_event_t *event); 376 377 static void 378 launch_next_query(dig_query_t *query, isc_boolean_t include_question); 379 380 static void 381 check_next_lookup(dig_lookup_t *lookup); 382 383 static isc_boolean_t 384 next_origin(dig_lookup_t *oldlookup); 385 386 static void * 387 mem_alloc(void *arg, size_t size) { 388 return (isc_mem_get(arg, size)); 389 } 390 391 static void 392 mem_free(void *arg, void *mem, size_t size) { 393 isc_mem_put(arg, mem, size); 394 } 395 396 char * 397 next_token(char **stringp, const char *delim) { 398 char *res; 399 400 do { 401 res = strsep(stringp, delim); 402 if (res == NULL) 403 break; 404 } while (*res == '\0'); 405 return (res); 406 } 407 408 static int 409 count_dots(char *string) { 410 char *s; 411 int i = 0; 412 413 s = string; 414 while (*s != '\0') { 415 if (*s == '.') 416 i++; 417 s++; 418 } 419 return (i); 420 } 421 422 static void 423 hex_dump(isc_buffer_t *b) { 424 unsigned int len, i; 425 isc_region_t r; 426 427 isc_buffer_usedregion(b, &r); 428 429 printf("%d bytes\n", r.length); 430 for (len = 0; len < r.length; len++) { 431 printf("%02x ", r.base[len]); 432 if (len % 16 == 15) { 433 fputs(" ", stdout); 434 for (i = len - 15; i <= len; i++) { 435 if (r.base[i] >= '!' && r.base[i] <= '}') 436 putchar(r.base[i]); 437 else 438 putchar('.'); 439 } 440 printf("\n"); 441 } 442 } 443 if (len % 16 != 0) { 444 for (i = len; (i % 16) != 0; i++) 445 fputs(" ", stdout); 446 fputs(" ", stdout); 447 for (i = ((len>>4)<<4); i < len; i++) { 448 if (r.base[i] >= '!' && r.base[i] <= '}') 449 putchar(r.base[i]); 450 else 451 putchar('.'); 452 } 453 printf("\n"); 454 } 455 } 456 457 /*% 458 * Append 'len' bytes of 'text' at '*p', failing with 459 * ISC_R_NOSPACE if that would advance p past 'end'. 460 */ 461 static isc_result_t 462 append(const char *text, int len, char **p, char *end) { 463 if (len > end - *p) 464 return (ISC_R_NOSPACE); 465 memmove(*p, text, len); 466 *p += len; 467 return (ISC_R_SUCCESS); 468 } 469 470 static isc_result_t 471 reverse_octets(const char *in, char **p, char *end) { 472 char *dot = strchr(in, '.'); 473 int len; 474 if (dot != NULL) { 475 isc_result_t result; 476 result = reverse_octets(dot + 1, p, end); 477 if (result != ISC_R_SUCCESS) 478 return (result); 479 result = append(".", 1, p, end); 480 if (result != ISC_R_SUCCESS) 481 return (result); 482 len = (int)(dot - in); 483 } else { 484 len = strlen(in); 485 } 486 return (append(in, len, p, end)); 487 } 488 489 isc_result_t 490 get_reverse(char *reverse, size_t len, char *value, isc_boolean_t ip6_int, 491 isc_boolean_t strict) 492 { 493 int r; 494 isc_result_t result; 495 isc_netaddr_t addr; 496 497 addr.family = AF_INET6; 498 r = inet_pton(AF_INET6, value, &addr.type.in6); 499 if (r > 0) { 500 /* This is a valid IPv6 address. */ 501 dns_fixedname_t fname; 502 dns_name_t *name; 503 unsigned int options = 0; 504 505 if (ip6_int) 506 options |= DNS_BYADDROPT_IPV6INT; 507 dns_fixedname_init(&fname); 508 name = dns_fixedname_name(&fname); 509 result = dns_byaddr_createptrname2(&addr, options, name); 510 if (result != ISC_R_SUCCESS) 511 return (result); 512 dns_name_format(name, reverse, (unsigned int)len); 513 return (ISC_R_SUCCESS); 514 } else { 515 /* 516 * Not a valid IPv6 address. Assume IPv4. 517 * If 'strict' is not set, construct the 518 * in-addr.arpa name by blindly reversing 519 * octets whether or not they look like integers, 520 * so that this can be used for RFC2317 names 521 * and such. 522 */ 523 char *p = reverse; 524 char *end = reverse + len; 525 if (strict && inet_pton(AF_INET, value, &addr.type.in) != 1) 526 return (DNS_R_BADDOTTEDQUAD); 527 result = reverse_octets(value, &p, end); 528 if (result != ISC_R_SUCCESS) 529 return (result); 530 /* Append .in-addr.arpa. and a terminating NUL. */ 531 result = append(".in-addr.arpa.", 15, &p, end); 532 if (result != ISC_R_SUCCESS) 533 return (result); 534 return (ISC_R_SUCCESS); 535 } 536 } 537 538 void 539 fatal(const char *format, ...) { 540 va_list args; 541 542 fflush(stdout); 543 fprintf(stderr, "%s: ", progname); 544 va_start(args, format); 545 vfprintf(stderr, format, args); 546 va_end(args); 547 fprintf(stderr, "\n"); 548 if (exitcode < 10) 549 exitcode = 10; 550 if (fatalexit != 0) 551 exitcode = fatalexit; 552 exit(exitcode); 553 } 554 555 void 556 debug(const char *format, ...) { 557 va_list args; 558 isc_time_t t; 559 560 if (debugging) { 561 fflush(stdout); 562 if (debugtiming) { 563 TIME_NOW(&t); 564 fprintf(stderr, "%d.%06d: ", isc_time_seconds(&t), 565 isc_time_nanoseconds(&t) / 1000); 566 } 567 va_start(args, format); 568 vfprintf(stderr, format, args); 569 va_end(args); 570 fprintf(stderr, "\n"); 571 } 572 } 573 574 void 575 check_result(isc_result_t result, const char *msg) { 576 if (result != ISC_R_SUCCESS) { 577 fatal("%s: %s", msg, isc_result_totext(result)); 578 } 579 } 580 581 /*% 582 * Create a server structure, which is part of the lookup structure. 583 * This is little more than a linked list of servers to query in hopes 584 * of finding the answer the user is looking for 585 */ 586 dig_server_t * 587 make_server(const char *servname, const char *userarg) { 588 dig_server_t *srv; 589 590 REQUIRE(servname != NULL); 591 592 debug("make_server(%s)", servname); 593 srv = isc_mem_allocate(mctx, sizeof(struct dig_server)); 594 if (srv == NULL) 595 fatal("memory allocation failure in %s:%d", 596 __FILE__, __LINE__); 597 strlcpy(srv->servername, servname, MXNAME); 598 strlcpy(srv->userarg, userarg, MXNAME); 599 ISC_LINK_INIT(srv, link); 600 return (srv); 601 } 602 603 static int 604 addr2af(int lwresaddrtype) 605 { 606 int af = 0; 607 608 switch (lwresaddrtype) { 609 case LWRES_ADDRTYPE_V4: 610 af = AF_INET; 611 break; 612 613 case LWRES_ADDRTYPE_V6: 614 af = AF_INET6; 615 break; 616 } 617 618 return (af); 619 } 620 621 /*% 622 * Create a copy of the server list from the lwres configuration structure. 623 * The dest list must have already had ISC_LIST_INIT applied. 624 */ 625 static void 626 copy_server_list(lwres_conf_t *confdata, dig_serverlist_t *dest) { 627 dig_server_t *newsrv; 628 char tmp[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255") + 629 sizeof("%4000000000")]; 630 int af; 631 int i; 632 633 debug("copy_server_list()"); 634 for (i = 0; i < confdata->nsnext; i++) { 635 af = addr2af(confdata->nameservers[i].family); 636 637 if (af == AF_INET && !have_ipv4) 638 continue; 639 if (af == AF_INET6 && !have_ipv6) 640 continue; 641 642 lwres_net_ntop(af, confdata->nameservers[i].address, 643 tmp, sizeof(tmp)); 644 if (af == AF_INET6 && confdata->nameservers[i].zone != 0) { 645 char buf[sizeof("%4000000000")]; 646 snprintf(buf, sizeof(buf), "%%%u", 647 confdata->nameservers[i].zone); 648 strlcat(tmp, buf, sizeof(tmp)); 649 } 650 newsrv = make_server(tmp, tmp); 651 ISC_LINK_INIT(newsrv, link); 652 ISC_LIST_ENQUEUE(*dest, newsrv, link); 653 } 654 } 655 656 void 657 flush_server_list(void) { 658 dig_server_t *s, *ps; 659 660 debug("flush_server_list()"); 661 s = ISC_LIST_HEAD(server_list); 662 while (s != NULL) { 663 ps = s; 664 s = ISC_LIST_NEXT(s, link); 665 ISC_LIST_DEQUEUE(server_list, ps, link); 666 isc_mem_free(mctx, ps); 667 } 668 } 669 670 void 671 set_nameserver(char *opt) { 672 isc_result_t result; 673 isc_sockaddr_t sockaddrs[DIG_MAX_ADDRESSES]; 674 isc_netaddr_t netaddr; 675 int count, i; 676 dig_server_t *srv; 677 char tmp[ISC_NETADDR_FORMATSIZE]; 678 679 if (opt == NULL) 680 return; 681 682 result = bind9_getaddresses(opt, 0, sockaddrs, 683 DIG_MAX_ADDRESSES, &count); 684 if (result != ISC_R_SUCCESS) 685 fatal("couldn't get address for '%s': %s", 686 opt, isc_result_totext(result)); 687 688 flush_server_list(); 689 690 for (i = 0; i < count; i++) { 691 isc_netaddr_fromsockaddr(&netaddr, &sockaddrs[i]); 692 isc_netaddr_format(&netaddr, tmp, sizeof(tmp)); 693 srv = make_server(tmp, opt); 694 if (srv == NULL) 695 fatal("memory allocation failure"); 696 ISC_LIST_APPEND(server_list, srv, link); 697 } 698 } 699 700 static isc_result_t 701 add_nameserver(lwres_conf_t *confdata, const char *addr, int af) { 702 703 int i = confdata->nsnext; 704 705 if (confdata->nsnext >= LWRES_CONFMAXNAMESERVERS) 706 return (ISC_R_FAILURE); 707 708 switch (af) { 709 case AF_INET: 710 confdata->nameservers[i].family = LWRES_ADDRTYPE_V4; 711 confdata->nameservers[i].length = NS_INADDRSZ; 712 break; 713 case AF_INET6: 714 confdata->nameservers[i].family = LWRES_ADDRTYPE_V6; 715 confdata->nameservers[i].length = NS_IN6ADDRSZ; 716 break; 717 default: 718 return (ISC_R_FAILURE); 719 } 720 721 if (lwres_net_pton(af, addr, &confdata->nameservers[i].address) == 1) { 722 confdata->nsnext++; 723 return (ISC_R_SUCCESS); 724 } 725 return (ISC_R_FAILURE); 726 } 727 728 /*% 729 * Produce a cloned server list. The dest list must have already had 730 * ISC_LIST_INIT applied. 731 */ 732 void 733 clone_server_list(dig_serverlist_t src, dig_serverlist_t *dest) { 734 dig_server_t *srv, *newsrv; 735 736 debug("clone_server_list()"); 737 srv = ISC_LIST_HEAD(src); 738 while (srv != NULL) { 739 newsrv = make_server(srv->servername, srv->userarg); 740 ISC_LINK_INIT(newsrv, link); 741 ISC_LIST_ENQUEUE(*dest, newsrv, link); 742 srv = ISC_LIST_NEXT(srv, link); 743 } 744 } 745 746 /*% 747 * Create an empty lookup structure, which holds all the information needed 748 * to get an answer to a user's question. This structure contains two 749 * linked lists: the server list (servers to query) and the query list 750 * (outstanding queries which have been made to the listed servers). 751 */ 752 dig_lookup_t * 753 make_empty_lookup(void) { 754 dig_lookup_t *looknew; 755 756 debug("make_empty_lookup()"); 757 758 INSIST(!free_now); 759 760 looknew = isc_mem_allocate(mctx, sizeof(struct dig_lookup)); 761 if (looknew == NULL) 762 fatal("memory allocation failure in %s:%d", 763 __FILE__, __LINE__); 764 looknew->pending = ISC_TRUE; 765 looknew->textname[0] = 0; 766 looknew->cmdline[0] = 0; 767 looknew->rdtype = dns_rdatatype_a; 768 looknew->qrdtype = dns_rdatatype_a; 769 looknew->rdclass = dns_rdataclass_in; 770 looknew->rdtypeset = ISC_FALSE; 771 looknew->rdclassset = ISC_FALSE; 772 looknew->sendspace = NULL; 773 looknew->sendmsg = NULL; 774 looknew->name = NULL; 775 looknew->oname = NULL; 776 looknew->timer = NULL; 777 looknew->xfr_q = NULL; 778 looknew->current_query = NULL; 779 looknew->doing_xfr = ISC_FALSE; 780 looknew->ixfr_serial = 0; 781 looknew->trace = ISC_FALSE; 782 looknew->trace_root = ISC_FALSE; 783 looknew->identify = ISC_FALSE; 784 looknew->identify_previous_line = ISC_FALSE; 785 looknew->ignore = ISC_FALSE; 786 looknew->servfail_stops = ISC_TRUE; 787 looknew->besteffort = ISC_TRUE; 788 looknew->dnssec = ISC_FALSE; 789 looknew->expire = ISC_FALSE; 790 looknew->nsid = ISC_FALSE; 791 #ifdef ISC_PLATFORM_USESIT 792 looknew->sit = ISC_FALSE; 793 #endif 794 #ifdef DIG_SIGCHASE 795 looknew->sigchase = ISC_FALSE; 796 #if DIG_SIGCHASE_TD 797 looknew->do_topdown = ISC_FALSE; 798 looknew->trace_root_sigchase = ISC_FALSE; 799 looknew->rdtype_sigchaseset = ISC_FALSE; 800 looknew->rdtype_sigchase = dns_rdatatype_any; 801 looknew->qrdtype_sigchase = dns_rdatatype_any; 802 looknew->rdclass_sigchase = dns_rdataclass_in; 803 looknew->rdclass_sigchaseset = ISC_FALSE; 804 #endif 805 #endif 806 looknew->udpsize = 0; 807 looknew->edns = -1; 808 looknew->recurse = ISC_TRUE; 809 looknew->aaonly = ISC_FALSE; 810 looknew->adflag = ISC_FALSE; 811 looknew->cdflag = ISC_FALSE; 812 looknew->ns_search_only = ISC_FALSE; 813 looknew->origin = NULL; 814 looknew->tsigctx = NULL; 815 looknew->querysig = NULL; 816 looknew->retries = tries; 817 looknew->nsfound = 0; 818 looknew->tcp_mode = ISC_FALSE; 819 looknew->tcp_mode_set = ISC_FALSE; 820 looknew->ip6_int = ISC_FALSE; 821 looknew->comments = ISC_TRUE; 822 looknew->stats = ISC_TRUE; 823 looknew->section_question = ISC_TRUE; 824 looknew->section_answer = ISC_TRUE; 825 looknew->section_authority = ISC_TRUE; 826 looknew->section_additional = ISC_TRUE; 827 looknew->new_search = ISC_FALSE; 828 looknew->done_as_is = ISC_FALSE; 829 looknew->need_search = ISC_FALSE; 830 looknew->ecs_addr = NULL; 831 #ifdef ISC_PLATFORM_USESIT 832 looknew->sitvalue = NULL; 833 #endif 834 dns_fixedname_init(&looknew->fdomain); 835 ISC_LINK_INIT(looknew, link); 836 ISC_LIST_INIT(looknew->q); 837 ISC_LIST_INIT(looknew->connecting); 838 ISC_LIST_INIT(looknew->my_server_list); 839 return (looknew); 840 } 841 842 /*% 843 * Clone a lookup, perhaps copying the server list. This does not clone 844 * the query list, since it will be regenerated by the setup_lookup() 845 * function, nor does it queue up the new lookup for processing. 846 * Caution: If you don't clone the servers, you MUST clone the server 847 * list separately from somewhere else, or construct it by hand. 848 */ 849 dig_lookup_t * 850 clone_lookup(dig_lookup_t *lookold, isc_boolean_t servers) { 851 dig_lookup_t *looknew; 852 853 debug("clone_lookup()"); 854 855 INSIST(!free_now); 856 857 looknew = make_empty_lookup(); 858 INSIST(looknew != NULL); 859 strlcpy(looknew->textname, lookold->textname, MXNAME); 860 #if DIG_SIGCHASE_TD 861 strlcpy(looknew->textnamesigchase, lookold->textnamesigchase, MXNAME); 862 #endif 863 strlcpy(looknew->cmdline, lookold->cmdline, MXNAME); 864 looknew->textname[MXNAME-1] = 0; 865 looknew->rdtype = lookold->rdtype; 866 looknew->qrdtype = lookold->qrdtype; 867 looknew->rdclass = lookold->rdclass; 868 looknew->rdtypeset = lookold->rdtypeset; 869 looknew->rdclassset = lookold->rdclassset; 870 looknew->doing_xfr = lookold->doing_xfr; 871 looknew->ixfr_serial = lookold->ixfr_serial; 872 looknew->trace = lookold->trace; 873 looknew->trace_root = lookold->trace_root; 874 looknew->identify = lookold->identify; 875 looknew->identify_previous_line = lookold->identify_previous_line; 876 looknew->ignore = lookold->ignore; 877 looknew->servfail_stops = lookold->servfail_stops; 878 looknew->besteffort = lookold->besteffort; 879 looknew->dnssec = lookold->dnssec; 880 looknew->expire = lookold->expire; 881 looknew->nsid = lookold->nsid; 882 #ifdef ISC_PLATFORM_USESIT 883 looknew->sit = lookold->sit; 884 looknew->sitvalue = lookold->sitvalue; 885 #endif 886 #ifdef DIG_SIGCHASE 887 looknew->sigchase = lookold->sigchase; 888 #if DIG_SIGCHASE_TD 889 looknew->do_topdown = lookold->do_topdown; 890 looknew->trace_root_sigchase = lookold->trace_root_sigchase; 891 looknew->rdtype_sigchaseset = lookold->rdtype_sigchaseset; 892 looknew->rdtype_sigchase = lookold->rdtype_sigchase; 893 looknew->qrdtype_sigchase = lookold->qrdtype_sigchase; 894 looknew->rdclass_sigchase = lookold->rdclass_sigchase; 895 looknew->rdclass_sigchaseset = lookold->rdclass_sigchaseset; 896 #endif 897 #endif 898 looknew->udpsize = lookold->udpsize; 899 looknew->edns = lookold->edns; 900 looknew->recurse = lookold->recurse; 901 looknew->aaonly = lookold->aaonly; 902 looknew->adflag = lookold->adflag; 903 looknew->cdflag = lookold->cdflag; 904 looknew->ns_search_only = lookold->ns_search_only; 905 looknew->tcp_mode = lookold->tcp_mode; 906 looknew->tcp_mode_set = lookold->tcp_mode_set; 907 looknew->comments = lookold->comments; 908 looknew->stats = lookold->stats; 909 looknew->section_question = lookold->section_question; 910 looknew->section_answer = lookold->section_answer; 911 looknew->section_authority = lookold->section_authority; 912 looknew->section_additional = lookold->section_additional; 913 looknew->retries = lookold->retries; 914 looknew->tsigctx = NULL; 915 looknew->need_search = lookold->need_search; 916 looknew->done_as_is = lookold->done_as_is; 917 918 if (lookold->ecs_addr != NULL) { 919 size_t len = sizeof(isc_sockaddr_t); 920 looknew->ecs_addr = isc_mem_allocate(mctx, len); 921 memmove(looknew->ecs_addr, lookold->ecs_addr, len); 922 } 923 924 dns_name_copy(dns_fixedname_name(&lookold->fdomain), 925 dns_fixedname_name(&looknew->fdomain), NULL); 926 927 if (servers) 928 clone_server_list(lookold->my_server_list, 929 &looknew->my_server_list); 930 return (looknew); 931 } 932 933 /*% 934 * Requeue a lookup for further processing, perhaps copying the server 935 * list. The new lookup structure is returned to the caller, and is 936 * queued for processing. If servers are not cloned in the requeue, they 937 * must be added before allowing the current event to complete, since the 938 * completion of the event may result in the next entry on the lookup 939 * queue getting run. 940 */ 941 dig_lookup_t * 942 requeue_lookup(dig_lookup_t *lookold, isc_boolean_t servers) { 943 dig_lookup_t *looknew; 944 945 debug("requeue_lookup()"); 946 947 lookup_counter++; 948 if (lookup_counter > LOOKUP_LIMIT) 949 fatal("too many lookups"); 950 951 looknew = clone_lookup(lookold, servers); 952 INSIST(looknew != NULL); 953 954 debug("before insertion, init@%p -> %p, new@%p -> %p", 955 lookold, lookold->link.next, looknew, looknew->link.next); 956 ISC_LIST_PREPEND(lookup_list, looknew, link); 957 debug("after insertion, init -> %p, new = %p, new -> %p", 958 lookold, looknew, looknew->link.next); 959 return (looknew); 960 } 961 962 963 static void 964 setup_text_key(void) { 965 isc_result_t result; 966 dns_name_t keyname; 967 isc_buffer_t secretbuf; 968 int secretsize; 969 unsigned char *secretstore; 970 971 debug("setup_text_key()"); 972 result = isc_buffer_allocate(mctx, &namebuf, MXNAME); 973 check_result(result, "isc_buffer_allocate"); 974 dns_name_init(&keyname, NULL); 975 check_result(result, "dns_name_init"); 976 isc_buffer_putstr(namebuf, keynametext); 977 secretsize = strlen(keysecret) * 3 / 4; 978 secretstore = isc_mem_allocate(mctx, secretsize); 979 if (secretstore == NULL) 980 fatal("memory allocation failure in %s:%d", 981 __FILE__, __LINE__); 982 isc_buffer_init(&secretbuf, secretstore, secretsize); 983 result = isc_base64_decodestring(keysecret, &secretbuf); 984 if (result != ISC_R_SUCCESS) 985 goto failure; 986 987 secretsize = isc_buffer_usedlength(&secretbuf); 988 989 if (hmacname == NULL) { 990 result = DST_R_UNSUPPORTEDALG; 991 goto failure; 992 } 993 994 result = dns_name_fromtext(&keyname, namebuf, dns_rootname, 0, namebuf); 995 if (result != ISC_R_SUCCESS) 996 goto failure; 997 998 result = dns_tsigkey_create(&keyname, hmacname, secretstore, 999 secretsize, ISC_FALSE, NULL, 0, 0, mctx, 1000 NULL, &key); 1001 failure: 1002 if (result != ISC_R_SUCCESS) 1003 printf(";; Couldn't create key %s: %s\n", 1004 keynametext, isc_result_totext(result)); 1005 else 1006 dst_key_setbits(key->key, digestbits); 1007 1008 isc_mem_free(mctx, secretstore); 1009 dns_name_invalidate(&keyname); 1010 isc_buffer_free(&namebuf); 1011 } 1012 1013 isc_result_t 1014 parse_uint(isc_uint32_t *uip, const char *value, isc_uint32_t max, 1015 const char *desc) { 1016 isc_uint32_t n; 1017 isc_result_t result = isc_parse_uint32(&n, value, 10); 1018 if (result == ISC_R_SUCCESS && n > max) 1019 result = ISC_R_RANGE; 1020 if (result != ISC_R_SUCCESS) { 1021 printf("invalid %s '%s': %s\n", desc, 1022 value, isc_result_totext(result)); 1023 return (result); 1024 } 1025 *uip = n; 1026 return (ISC_R_SUCCESS); 1027 } 1028 1029 static isc_uint32_t 1030 parse_bits(char *arg, const char *desc, isc_uint32_t max) { 1031 isc_result_t result; 1032 isc_uint32_t tmp; 1033 1034 result = parse_uint(&tmp, arg, max, desc); 1035 if (result != ISC_R_SUCCESS) 1036 fatal("couldn't parse digest bits"); 1037 tmp = (tmp + 7) & ~0x7U; 1038 return (tmp); 1039 } 1040 1041 isc_result_t 1042 parse_netprefix(isc_sockaddr_t **sap, const char *value) { 1043 isc_result_t result = ISC_R_SUCCESS; 1044 isc_sockaddr_t *sa = NULL; 1045 struct in_addr in4; 1046 struct in6_addr in6; 1047 isc_uint32_t netmask = 0; 1048 char *slash = NULL; 1049 isc_boolean_t parsed = ISC_FALSE; 1050 1051 if ((slash = strchr(value, '/'))) { 1052 *slash = '\0'; 1053 result = isc_parse_uint32(&netmask, slash + 1, 10); 1054 if (result != ISC_R_SUCCESS) { 1055 *slash = '/'; 1056 fatal("invalid prefix length '%s': %s\n", 1057 value, isc_result_totext(result)); 1058 } 1059 } 1060 1061 sa = isc_mem_allocate(mctx, sizeof(*sa)); 1062 if (inet_pton(AF_INET6, value, &in6) == 1) { 1063 isc_sockaddr_fromin6(sa, &in6, 0); 1064 parsed = ISC_TRUE; 1065 if (netmask == 0 || netmask > 128) 1066 netmask = 128; 1067 } else if (inet_pton(AF_INET, value, &in4) == 1) { 1068 parsed = ISC_TRUE; 1069 isc_sockaddr_fromin(sa, &in4, 0); 1070 if (netmask == 0 || netmask > 32) 1071 netmask = 32; 1072 } else if (netmask != 0) { 1073 char buf[64]; 1074 int i; 1075 1076 strlcpy(buf, value, sizeof(buf)); 1077 for (i = 0; i < 3; i++) { 1078 strlcat(buf, ".0", sizeof(buf)); 1079 if (inet_pton(AF_INET, buf, &in4) == 1) { 1080 parsed = ISC_TRUE; 1081 isc_sockaddr_fromin(sa, &in4, 0); 1082 break; 1083 } 1084 } 1085 1086 } 1087 1088 if (slash != NULL) 1089 *slash = '/'; 1090 1091 if (!parsed) 1092 fatal("invalid address '%s'", value); 1093 1094 sa->length = netmask; 1095 *sap = sa; 1096 1097 return (ISC_R_SUCCESS); 1098 } 1099 1100 1101 /* 1102 * Parse HMAC algorithm specification 1103 */ 1104 void 1105 parse_hmac(const char *hmac) { 1106 char buf[20]; 1107 int len; 1108 1109 REQUIRE(hmac != NULL); 1110 1111 len = strlen(hmac); 1112 if (len >= (int) sizeof(buf)) 1113 fatal("unknown key type '%.*s'", len, hmac); 1114 strlcpy(buf, hmac, sizeof(buf)); 1115 1116 digestbits = 0; 1117 1118 if (strcasecmp(buf, "hmac-md5") == 0) { 1119 hmacname = DNS_TSIG_HMACMD5_NAME; 1120 } else if (strncasecmp(buf, "hmac-md5-", 9) == 0) { 1121 hmacname = DNS_TSIG_HMACMD5_NAME; 1122 digestbits = parse_bits(&buf[9], "digest-bits [0..128]", 128); 1123 } else if (strcasecmp(buf, "hmac-sha1") == 0) { 1124 hmacname = DNS_TSIG_HMACSHA1_NAME; 1125 digestbits = 0; 1126 } else if (strncasecmp(buf, "hmac-sha1-", 10) == 0) { 1127 hmacname = DNS_TSIG_HMACSHA1_NAME; 1128 digestbits = parse_bits(&buf[10], "digest-bits [0..160]", 160); 1129 } else if (strcasecmp(buf, "hmac-sha224") == 0) { 1130 hmacname = DNS_TSIG_HMACSHA224_NAME; 1131 } else if (strncasecmp(buf, "hmac-sha224-", 12) == 0) { 1132 hmacname = DNS_TSIG_HMACSHA224_NAME; 1133 digestbits = parse_bits(&buf[12], "digest-bits [0..224]", 224); 1134 } else if (strcasecmp(buf, "hmac-sha256") == 0) { 1135 hmacname = DNS_TSIG_HMACSHA256_NAME; 1136 } else if (strncasecmp(buf, "hmac-sha256-", 12) == 0) { 1137 hmacname = DNS_TSIG_HMACSHA256_NAME; 1138 digestbits = parse_bits(&buf[12], "digest-bits [0..256]", 256); 1139 } else if (strcasecmp(buf, "hmac-sha384") == 0) { 1140 hmacname = DNS_TSIG_HMACSHA384_NAME; 1141 } else if (strncasecmp(buf, "hmac-sha384-", 12) == 0) { 1142 hmacname = DNS_TSIG_HMACSHA384_NAME; 1143 digestbits = parse_bits(&buf[12], "digest-bits [0..384]", 384); 1144 } else if (strcasecmp(buf, "hmac-sha512") == 0) { 1145 hmacname = DNS_TSIG_HMACSHA512_NAME; 1146 } else if (strncasecmp(buf, "hmac-sha512-", 12) == 0) { 1147 hmacname = DNS_TSIG_HMACSHA512_NAME; 1148 digestbits = parse_bits(&buf[12], "digest-bits [0..512]", 512); 1149 } else { 1150 fprintf(stderr, ";; Warning, ignoring " 1151 "invalid TSIG algorithm %s\n", buf); 1152 } 1153 } 1154 1155 /* 1156 * Get a key from a named.conf format keyfile 1157 */ 1158 static isc_result_t 1159 read_confkey(void) { 1160 cfg_parser_t *pctx = NULL; 1161 cfg_obj_t *file = NULL; 1162 const cfg_obj_t *keyobj = NULL; 1163 const cfg_obj_t *secretobj = NULL; 1164 const cfg_obj_t *algorithmobj = NULL; 1165 const char *keyname; 1166 const char *secretstr; 1167 const char *algorithm; 1168 isc_result_t result; 1169 1170 if (! isc_file_exists(keyfile)) 1171 return (ISC_R_FILENOTFOUND); 1172 1173 result = cfg_parser_create(mctx, NULL, &pctx); 1174 if (result != ISC_R_SUCCESS) 1175 goto cleanup; 1176 1177 result = cfg_parse_file(pctx, keyfile, &cfg_type_sessionkey, 1178 &file); 1179 if (result != ISC_R_SUCCESS) 1180 goto cleanup; 1181 1182 result = cfg_map_get(file, "key", &keyobj); 1183 if (result != ISC_R_SUCCESS) 1184 goto cleanup; 1185 1186 (void) cfg_map_get(keyobj, "secret", &secretobj); 1187 (void) cfg_map_get(keyobj, "algorithm", &algorithmobj); 1188 if (secretobj == NULL || algorithmobj == NULL) 1189 fatal("key must have algorithm and secret"); 1190 1191 keyname = cfg_obj_asstring(cfg_map_getname(keyobj)); 1192 secretstr = cfg_obj_asstring(secretobj); 1193 algorithm = cfg_obj_asstring(algorithmobj); 1194 1195 strlcpy(keynametext, keyname, sizeof(keynametext)); 1196 strlcpy(keysecret, secretstr, sizeof(keysecret)); 1197 parse_hmac(algorithm); 1198 setup_text_key(); 1199 1200 cleanup: 1201 if (pctx != NULL) { 1202 if (file != NULL) 1203 cfg_obj_destroy(pctx, &file); 1204 cfg_parser_destroy(&pctx); 1205 } 1206 1207 return (result); 1208 } 1209 1210 static void 1211 setup_file_key(void) { 1212 isc_result_t result; 1213 dst_key_t *dstkey = NULL; 1214 1215 debug("setup_file_key()"); 1216 1217 /* Try reading the key from a K* pair */ 1218 result = dst_key_fromnamedfile(keyfile, NULL, 1219 DST_TYPE_PRIVATE | DST_TYPE_KEY, mctx, 1220 &dstkey); 1221 1222 /* If that didn't work, try reading it as a session.key keyfile */ 1223 if (result != ISC_R_SUCCESS) { 1224 result = read_confkey(); 1225 if (result == ISC_R_SUCCESS) 1226 return; 1227 } 1228 1229 if (result != ISC_R_SUCCESS) { 1230 fprintf(stderr, "Couldn't read key from %s: %s\n", 1231 keyfile, isc_result_totext(result)); 1232 goto failure; 1233 } 1234 1235 switch (dst_key_alg(dstkey)) { 1236 case DST_ALG_HMACMD5: 1237 hmacname = DNS_TSIG_HMACMD5_NAME; 1238 break; 1239 case DST_ALG_HMACSHA1: 1240 hmacname = DNS_TSIG_HMACSHA1_NAME; 1241 break; 1242 case DST_ALG_HMACSHA224: 1243 hmacname = DNS_TSIG_HMACSHA224_NAME; 1244 break; 1245 case DST_ALG_HMACSHA256: 1246 hmacname = DNS_TSIG_HMACSHA256_NAME; 1247 break; 1248 case DST_ALG_HMACSHA384: 1249 hmacname = DNS_TSIG_HMACSHA384_NAME; 1250 break; 1251 case DST_ALG_HMACSHA512: 1252 hmacname = DNS_TSIG_HMACSHA512_NAME; 1253 break; 1254 default: 1255 printf(";; Couldn't create key %s: bad algorithm\n", 1256 keynametext); 1257 goto failure; 1258 } 1259 result = dns_tsigkey_createfromkey(dst_key_name(dstkey), hmacname, 1260 dstkey, ISC_FALSE, NULL, 0, 0, 1261 mctx, NULL, &key); 1262 if (result != ISC_R_SUCCESS) { 1263 printf(";; Couldn't create key %s: %s\n", 1264 keynametext, isc_result_totext(result)); 1265 goto failure; 1266 } 1267 failure: 1268 if (dstkey != NULL) 1269 dst_key_free(&dstkey); 1270 } 1271 1272 static dig_searchlist_t * 1273 make_searchlist_entry(char *domain) { 1274 dig_searchlist_t *search; 1275 search = isc_mem_allocate(mctx, sizeof(*search)); 1276 if (search == NULL) 1277 fatal("memory allocation failure in %s:%d", 1278 __FILE__, __LINE__); 1279 strlcpy(search->origin, domain, MXNAME); 1280 search->origin[MXNAME-1] = 0; 1281 ISC_LINK_INIT(search, link); 1282 return (search); 1283 } 1284 1285 static void 1286 clear_searchlist(void) { 1287 dig_searchlist_t *search; 1288 while ((search = ISC_LIST_HEAD(search_list)) != NULL) { 1289 ISC_LIST_UNLINK(search_list, search, link); 1290 isc_mem_free(mctx, search); 1291 } 1292 } 1293 1294 static void 1295 create_search_list(lwres_conf_t *confdata) { 1296 int i; 1297 dig_searchlist_t *search; 1298 1299 debug("create_search_list()"); 1300 clear_searchlist(); 1301 1302 for (i = 0; i < confdata->searchnxt; i++) { 1303 search = make_searchlist_entry(confdata->search[i]); 1304 ISC_LIST_APPEND(search_list, search, link); 1305 } 1306 } 1307 1308 /*% 1309 * Setup the system as a whole, reading key information and resolv.conf 1310 * settings. 1311 */ 1312 void 1313 setup_system(void) { 1314 dig_searchlist_t *domain = NULL; 1315 lwres_result_t lwresult; 1316 unsigned int lwresflags; 1317 isc_result_t result; 1318 1319 debug("setup_system()"); 1320 1321 lwresflags = LWRES_CONTEXT_SERVERMODE; 1322 if (have_ipv4) 1323 lwresflags |= LWRES_CONTEXT_USEIPV4; 1324 if (have_ipv6) 1325 lwresflags |= LWRES_CONTEXT_USEIPV6; 1326 1327 lwresult = lwres_context_create(&lwctx, mctx, mem_alloc, mem_free, 1328 lwresflags); 1329 if (lwresult != LWRES_R_SUCCESS) 1330 fatal("lwres_context_create failed"); 1331 1332 lwresult = lwres_conf_parse(lwctx, RESOLV_CONF); 1333 if (lwresult != LWRES_R_SUCCESS && lwresult != LWRES_R_NOTFOUND) 1334 fatal("parse of %s failed", RESOLV_CONF); 1335 1336 lwconf = lwres_conf_get(lwctx); 1337 1338 /* Make the search list */ 1339 if (lwconf->searchnxt > 0) 1340 create_search_list(lwconf); 1341 else { /* No search list. Use the domain name if any */ 1342 if (lwconf->domainname != NULL) { 1343 domain = make_searchlist_entry(lwconf->domainname); 1344 ISC_LIST_APPEND(search_list, domain, link); 1345 domain = NULL; 1346 } 1347 } 1348 1349 if (ndots == -1) { 1350 ndots = lwconf->ndots; 1351 debug("ndots is %d.", ndots); 1352 } 1353 1354 /* If user doesn't specify server use nameservers from resolv.conf. */ 1355 if (ISC_LIST_EMPTY(server_list)) 1356 copy_server_list(lwconf, &server_list); 1357 1358 /* If we don't find a nameserver fall back to localhost */ 1359 if (ISC_LIST_EMPTY(server_list)) { 1360 if (have_ipv4) { 1361 lwresult = add_nameserver(lwconf, "127.0.0.1", AF_INET); 1362 if (lwresult != ISC_R_SUCCESS) 1363 fatal("add_nameserver failed"); 1364 } 1365 if (have_ipv6) { 1366 lwresult = add_nameserver(lwconf, "::1", AF_INET6); 1367 if (lwresult != ISC_R_SUCCESS) 1368 fatal("add_nameserver failed"); 1369 } 1370 1371 copy_server_list(lwconf, &server_list); 1372 } 1373 1374 #ifdef WITH_IDN 1375 initialize_idn(); 1376 #endif 1377 1378 if (keyfile[0] != 0) 1379 setup_file_key(); 1380 else if (keysecret[0] != 0) 1381 setup_text_key(); 1382 #ifdef DIG_SIGCHASE 1383 /* Setup the list of messages for +sigchase */ 1384 ISC_LIST_INIT(chase_message_list); 1385 ISC_LIST_INIT(chase_message_list2); 1386 dns_name_init(&chase_name, NULL); 1387 #if DIG_SIGCHASE_TD 1388 dns_name_init(&chase_current_name, NULL); 1389 dns_name_init(&chase_authority_name, NULL); 1390 #endif 1391 #if DIG_SIGCHASE_BU 1392 dns_name_init(&chase_signame, NULL); 1393 #endif 1394 1395 #endif 1396 result = isc_entropy_getdata(entp, cookie_secret, 1397 sizeof(cookie_secret), NULL, 0); 1398 if (result != ISC_R_SUCCESS) 1399 fatal("unable to generate cookie secret"); 1400 } 1401 1402 /*% 1403 * Override the search list derived from resolv.conf by 'domain'. 1404 */ 1405 void 1406 set_search_domain(char *domain) { 1407 dig_searchlist_t *search; 1408 1409 clear_searchlist(); 1410 search = make_searchlist_entry(domain); 1411 ISC_LIST_APPEND(search_list, search, link); 1412 } 1413 1414 /*% 1415 * Setup the ISC and DNS libraries for use by the system. 1416 */ 1417 void 1418 setup_libs(void) { 1419 isc_result_t result; 1420 isc_logconfig_t *logconfig = NULL; 1421 1422 debug("setup_libs()"); 1423 1424 #ifdef PKCS11CRYPTO 1425 pk11_result_register(); 1426 #endif 1427 dns_result_register(); 1428 1429 result = isc_net_probeipv4(); 1430 if (result == ISC_R_SUCCESS) 1431 have_ipv4 = ISC_TRUE; 1432 1433 result = isc_net_probeipv6(); 1434 if (result == ISC_R_SUCCESS) 1435 have_ipv6 = ISC_TRUE; 1436 if (!have_ipv6 && !have_ipv4) 1437 fatal("can't find either v4 or v6 networking"); 1438 1439 result = isc_mem_create(0, 0, &mctx); 1440 check_result(result, "isc_mem_create"); 1441 isc_mem_setname(mctx, "dig", NULL); 1442 1443 result = isc_log_create(mctx, &lctx, &logconfig); 1444 check_result(result, "isc_log_create"); 1445 1446 isc_log_setcontext(lctx); 1447 dns_log_init(lctx); 1448 dns_log_setcontext(lctx); 1449 1450 result = isc_log_usechannel(logconfig, "default_debug", NULL, NULL); 1451 check_result(result, "isc_log_usechannel"); 1452 1453 isc_log_setdebuglevel(lctx, 0); 1454 1455 result = isc_taskmgr_create(mctx, 1, 0, &taskmgr); 1456 check_result(result, "isc_taskmgr_create"); 1457 1458 result = isc_task_create(taskmgr, 0, &global_task); 1459 check_result(result, "isc_task_create"); 1460 isc_task_setname(global_task, "dig", NULL); 1461 1462 result = isc_timermgr_create(mctx, &timermgr); 1463 check_result(result, "isc_timermgr_create"); 1464 1465 result = isc_socketmgr_create(mctx, &socketmgr); 1466 check_result(result, "isc_socketmgr_create"); 1467 1468 result = isc_entropy_create(mctx, &entp); 1469 check_result(result, "isc_entropy_create"); 1470 1471 result = dst_lib_init(mctx, entp, 0); 1472 check_result(result, "dst_lib_init"); 1473 is_dst_up = ISC_TRUE; 1474 1475 result = isc_mempool_create(mctx, COMMSIZE, &commctx); 1476 check_result(result, "isc_mempool_create"); 1477 isc_mempool_setname(commctx, "COMMPOOL"); 1478 /* 1479 * 6 and 2 set as reasonable parameters for 3 or 4 nameserver 1480 * systems. 1481 */ 1482 isc_mempool_setfreemax(commctx, 6); 1483 isc_mempool_setfillcount(commctx, 2); 1484 1485 result = isc_mutex_init(&lookup_lock); 1486 check_result(result, "isc_mutex_init"); 1487 } 1488 1489 /*% 1490 * Add EDNS0 option record to a message. Currently, the only supported 1491 * options are UDP buffer size, the DO bit, and EDNS options 1492 * (e.g., NSID, SIT, client-subnet) 1493 */ 1494 static void 1495 add_opt(dns_message_t *msg, isc_uint16_t udpsize, isc_uint16_t edns, 1496 isc_boolean_t dnssec, dns_ednsopt_t *opts, size_t count) 1497 { 1498 dns_rdataset_t *rdataset = NULL; 1499 isc_result_t result; 1500 unsigned int flags = 0; 1501 1502 debug("add_opt()"); 1503 if (dnssec) 1504 flags |= DNS_MESSAGEEXTFLAG_DO; 1505 result = dns_message_buildopt(msg, &rdataset, edns, udpsize, flags, 1506 opts, count); 1507 check_result(result, "dns_message_buildopt"); 1508 result = dns_message_setopt(msg, rdataset); 1509 check_result(result, "dns_message_setopt"); 1510 } 1511 1512 /*% 1513 * Add a question section to a message, asking for the specified name, 1514 * type, and class. 1515 */ 1516 static void 1517 add_question(dns_message_t *message, dns_name_t *name, 1518 dns_rdataclass_t rdclass, dns_rdatatype_t rdtype) 1519 { 1520 dns_rdataset_t *rdataset; 1521 isc_result_t result; 1522 1523 debug("add_question()"); 1524 rdataset = NULL; 1525 result = dns_message_gettemprdataset(message, &rdataset); 1526 check_result(result, "dns_message_gettemprdataset()"); 1527 dns_rdataset_makequestion(rdataset, rdclass, rdtype); 1528 ISC_LIST_APPEND(name->list, rdataset, link); 1529 } 1530 1531 /*% 1532 * Check if we're done with all the queued lookups, which is true iff 1533 * all sockets, sends, and recvs are accounted for (counters == 0), 1534 * and the lookup list is empty. 1535 * If we are done, pass control back out to dighost_shutdown() (which is 1536 * part of dig.c, host.c, or nslookup.c) to either shutdown the system as 1537 * a whole or reseed the lookup list. 1538 */ 1539 static void 1540 check_if_done(void) { 1541 debug("check_if_done()"); 1542 debug("list %s", ISC_LIST_EMPTY(lookup_list) ? "empty" : "full"); 1543 if (ISC_LIST_EMPTY(lookup_list) && current_lookup == NULL && 1544 sendcount == 0) { 1545 INSIST(sockcount == 0); 1546 INSIST(recvcount == 0); 1547 debug("shutting down"); 1548 dighost_shutdown(); 1549 } 1550 } 1551 1552 /*% 1553 * Clear out a query when we're done with it. WARNING: This routine 1554 * WILL invalidate the query pointer. 1555 */ 1556 static void 1557 clear_query(dig_query_t *query) { 1558 dig_lookup_t *lookup; 1559 1560 REQUIRE(query != NULL); 1561 1562 debug("clear_query(%p)", query); 1563 1564 lookup = query->lookup; 1565 1566 if (lookup->current_query == query) 1567 lookup->current_query = NULL; 1568 1569 if (ISC_LINK_LINKED(query, link)) 1570 ISC_LIST_UNLINK(lookup->q, query, link); 1571 if (ISC_LINK_LINKED(query, clink)) 1572 ISC_LIST_UNLINK(lookup->connecting, query, clink); 1573 if (ISC_LINK_LINKED(&query->recvbuf, link)) 1574 ISC_LIST_DEQUEUE(query->recvlist, &query->recvbuf, 1575 link); 1576 if (ISC_LINK_LINKED(&query->lengthbuf, link)) 1577 ISC_LIST_DEQUEUE(query->lengthlist, &query->lengthbuf, 1578 link); 1579 INSIST(query->recvspace != NULL); 1580 1581 if (query->sock != NULL) { 1582 isc_socket_detach(&query->sock); 1583 sockcount--; 1584 debug("sockcount=%d", sockcount); 1585 } 1586 isc_mempool_put(commctx, query->recvspace); 1587 isc_buffer_invalidate(&query->recvbuf); 1588 isc_buffer_invalidate(&query->lengthbuf); 1589 if (query->waiting_senddone) 1590 query->pending_free = ISC_TRUE; 1591 else 1592 isc_mem_free(mctx, query); 1593 } 1594 1595 /*% 1596 * Try and clear out a lookup if we're done with it. Return ISC_TRUE if 1597 * the lookup was successfully cleared. If ISC_TRUE is returned, the 1598 * lookup pointer has been invalidated. 1599 */ 1600 static isc_boolean_t 1601 try_clear_lookup(dig_lookup_t *lookup) { 1602 dig_query_t *q; 1603 1604 REQUIRE(lookup != NULL); 1605 1606 debug("try_clear_lookup(%p)", lookup); 1607 1608 if (ISC_LIST_HEAD(lookup->q) != NULL || 1609 ISC_LIST_HEAD(lookup->connecting) != NULL) 1610 { 1611 if (debugging) { 1612 q = ISC_LIST_HEAD(lookup->q); 1613 while (q != NULL) { 1614 debug("query to %s still pending", q->servname); 1615 q = ISC_LIST_NEXT(q, link); 1616 } 1617 1618 q = ISC_LIST_HEAD(lookup->connecting); 1619 while (q != NULL) { 1620 debug("query to %s still connecting", 1621 q->servname); 1622 q = ISC_LIST_NEXT(q, clink); 1623 } 1624 } 1625 return (ISC_FALSE); 1626 } 1627 1628 /* 1629 * At this point, we know there are no queries on the lookup, 1630 * so can make it go away also. 1631 */ 1632 destroy_lookup(lookup); 1633 return (ISC_TRUE); 1634 } 1635 1636 void 1637 destroy_lookup(dig_lookup_t *lookup) { 1638 dig_server_t *s; 1639 void *ptr; 1640 1641 debug("destroy"); 1642 s = ISC_LIST_HEAD(lookup->my_server_list); 1643 while (s != NULL) { 1644 debug("freeing server %p belonging to %p", s, lookup); 1645 ptr = s; 1646 s = ISC_LIST_NEXT(s, link); 1647 ISC_LIST_DEQUEUE(lookup->my_server_list, 1648 (dig_server_t *)ptr, link); 1649 isc_mem_free(mctx, ptr); 1650 } 1651 if (lookup->sendmsg != NULL) 1652 dns_message_destroy(&lookup->sendmsg); 1653 if (lookup->querysig != NULL) { 1654 debug("freeing buffer %p", lookup->querysig); 1655 isc_buffer_free(&lookup->querysig); 1656 } 1657 if (lookup->timer != NULL) 1658 isc_timer_detach(&lookup->timer); 1659 if (lookup->sendspace != NULL) 1660 isc_mempool_put(commctx, lookup->sendspace); 1661 1662 if (lookup->tsigctx != NULL) 1663 dst_context_destroy(&lookup->tsigctx); 1664 1665 if (lookup->ecs_addr != NULL) 1666 isc_mem_free(mctx, lookup->ecs_addr); 1667 1668 isc_mem_free(mctx, lookup); 1669 } 1670 1671 /*% 1672 * If we can, start the next lookup in the queue running. 1673 * This assumes that the lookup on the head of the queue hasn't been 1674 * started yet. It also removes the lookup from the head of the queue, 1675 * setting the current_lookup pointer pointing to it. 1676 */ 1677 void 1678 start_lookup(void) { 1679 debug("start_lookup()"); 1680 if (cancel_now) 1681 return; 1682 1683 /* 1684 * If there's a current lookup running, we really shouldn't get 1685 * here. 1686 */ 1687 INSIST(current_lookup == NULL); 1688 1689 current_lookup = ISC_LIST_HEAD(lookup_list); 1690 /* 1691 * Put the current lookup somewhere so cancel_all can find it 1692 */ 1693 if (current_lookup != NULL) { 1694 ISC_LIST_DEQUEUE(lookup_list, current_lookup, link); 1695 #if DIG_SIGCHASE_TD 1696 if (current_lookup->do_topdown && 1697 !current_lookup->rdtype_sigchaseset) { 1698 dst_key_t *trustedkey = NULL; 1699 isc_buffer_t *b = NULL; 1700 isc_region_t r; 1701 isc_result_t result; 1702 dns_name_t query_name; 1703 dns_name_t *key_name; 1704 int i; 1705 1706 result = get_trusted_key(mctx); 1707 if (result != ISC_R_SUCCESS) { 1708 printf("\n;; No trusted key, " 1709 "+sigchase option is disabled\n"); 1710 current_lookup->sigchase = ISC_FALSE; 1711 goto novalidation; 1712 } 1713 dns_name_init(&query_name, NULL); 1714 nameFromString(current_lookup->textname, &query_name); 1715 1716 for (i = 0; i < tk_list.nb_tk; i++) { 1717 key_name = dst_key_name(tk_list.key[i]); 1718 1719 if (dns_name_issubdomain(&query_name, 1720 key_name) == ISC_TRUE) 1721 trustedkey = tk_list.key[i]; 1722 /* 1723 * Verify temp is really the lowest 1724 * WARNING 1725 */ 1726 } 1727 if (trustedkey == NULL) { 1728 printf("\n;; The queried zone: "); 1729 dns_name_print(&query_name, stdout); 1730 printf(" isn't a subdomain of any Trusted Keys" 1731 ": +sigchase option is disable\n"); 1732 current_lookup->sigchase = ISC_FALSE; 1733 free_name(&query_name, mctx); 1734 goto novalidation; 1735 } 1736 free_name(&query_name, mctx); 1737 1738 current_lookup->rdtype_sigchase 1739 = current_lookup->rdtype; 1740 current_lookup->rdtype_sigchaseset 1741 = current_lookup->rdtypeset; 1742 current_lookup->rdtype = dns_rdatatype_ns; 1743 1744 current_lookup->qrdtype_sigchase 1745 = current_lookup->qrdtype; 1746 current_lookup->qrdtype = dns_rdatatype_ns; 1747 1748 current_lookup->rdclass_sigchase 1749 = current_lookup->rdclass; 1750 current_lookup->rdclass_sigchaseset 1751 = current_lookup->rdclassset; 1752 current_lookup->rdclass = dns_rdataclass_in; 1753 1754 strlcpy(current_lookup->textnamesigchase, 1755 current_lookup->textname, MXNAME); 1756 1757 current_lookup->trace_root_sigchase = ISC_TRUE; 1758 1759 result = isc_buffer_allocate(mctx, &b, BUFSIZE); 1760 check_result(result, "isc_buffer_allocate"); 1761 result = dns_name_totext(dst_key_name(trustedkey), 1762 ISC_FALSE, b); 1763 check_result(result, "dns_name_totext"); 1764 isc_buffer_usedregion(b, &r); 1765 r.base[r.length] = '\0'; 1766 strlcpy(current_lookup->textname, (char*)r.base, 1767 MXNAME); 1768 isc_buffer_free(&b); 1769 1770 nameFromString(current_lookup->textnamesigchase, 1771 &chase_name); 1772 1773 dns_name_init(&chase_authority_name, NULL); 1774 } 1775 novalidation: 1776 #endif 1777 if (setup_lookup(current_lookup)) 1778 do_lookup(current_lookup); 1779 else if (next_origin(current_lookup)) 1780 check_next_lookup(current_lookup); 1781 } else { 1782 check_if_done(); 1783 } 1784 } 1785 1786 /*% 1787 * If we can, clear the current lookup and start the next one running. 1788 * This calls try_clear_lookup, so may invalidate the lookup pointer. 1789 */ 1790 static void 1791 check_next_lookup(dig_lookup_t *lookup) { 1792 1793 INSIST(!free_now); 1794 1795 debug("check_next_lookup(%p)", lookup); 1796 1797 if (ISC_LIST_HEAD(lookup->q) != NULL) { 1798 debug("still have a worker"); 1799 return; 1800 } 1801 if (try_clear_lookup(lookup)) { 1802 current_lookup = NULL; 1803 start_lookup(); 1804 } 1805 } 1806 1807 /*% 1808 * Create and queue a new lookup as a followup to the current lookup, 1809 * based on the supplied message and section. This is used in trace and 1810 * name server search modes to start a new lookup using servers from 1811 * NS records in a reply. Returns the number of followup lookups made. 1812 */ 1813 static int 1814 followup_lookup(dns_message_t *msg, dig_query_t *query, dns_section_t section) 1815 { 1816 dig_lookup_t *lookup = NULL; 1817 dig_server_t *srv = NULL; 1818 dns_rdataset_t *rdataset = NULL; 1819 dns_rdata_t rdata = DNS_RDATA_INIT; 1820 dns_name_t *name = NULL; 1821 isc_result_t result; 1822 isc_boolean_t success = ISC_FALSE; 1823 int numLookups = 0; 1824 int num; 1825 isc_result_t lresult, addresses_result; 1826 char bad_namestr[DNS_NAME_FORMATSIZE]; 1827 dns_name_t *domain; 1828 isc_boolean_t horizontal = ISC_FALSE, bad = ISC_FALSE; 1829 1830 INSIST(!free_now); 1831 1832 debug("following up %s", query->lookup->textname); 1833 1834 addresses_result = ISC_R_SUCCESS; 1835 bad_namestr[0] = '\0'; 1836 for (result = dns_message_firstname(msg, section); 1837 result == ISC_R_SUCCESS; 1838 result = dns_message_nextname(msg, section)) { 1839 name = NULL; 1840 dns_message_currentname(msg, section, &name); 1841 1842 if (section == DNS_SECTION_AUTHORITY) { 1843 rdataset = NULL; 1844 result = dns_message_findtype(name, dns_rdatatype_soa, 1845 0, &rdataset); 1846 if (result == ISC_R_SUCCESS) 1847 return (0); 1848 } 1849 rdataset = NULL; 1850 result = dns_message_findtype(name, dns_rdatatype_ns, 0, 1851 &rdataset); 1852 if (result != ISC_R_SUCCESS) 1853 continue; 1854 1855 debug("found NS set"); 1856 1857 if (query->lookup->trace && !query->lookup->trace_root) { 1858 dns_namereln_t namereln; 1859 unsigned int nlabels; 1860 int order; 1861 1862 domain = dns_fixedname_name(&query->lookup->fdomain); 1863 namereln = dns_name_fullcompare(name, domain, 1864 &order, &nlabels); 1865 if (namereln == dns_namereln_equal) { 1866 if (!horizontal) 1867 printf(";; BAD (HORIZONTAL) REFERRAL\n"); 1868 horizontal = ISC_TRUE; 1869 } else if (namereln != dns_namereln_subdomain) { 1870 if (!bad) 1871 printf(";; BAD REFERRAL\n"); 1872 bad = ISC_TRUE; 1873 continue; 1874 } 1875 } 1876 1877 for (result = dns_rdataset_first(rdataset); 1878 result == ISC_R_SUCCESS; 1879 result = dns_rdataset_next(rdataset)) { 1880 char namestr[DNS_NAME_FORMATSIZE]; 1881 dns_rdata_ns_t ns; 1882 1883 if (query->lookup->trace_root && 1884 query->lookup->nsfound >= MXSERV) 1885 break; 1886 1887 dns_rdataset_current(rdataset, &rdata); 1888 1889 query->lookup->nsfound++; 1890 result = dns_rdata_tostruct(&rdata, &ns, NULL); 1891 check_result(result, "dns_rdata_tostruct"); 1892 dns_name_format(&ns.name, namestr, sizeof(namestr)); 1893 dns_rdata_freestruct(&ns); 1894 1895 /* Initialize lookup if we've not yet */ 1896 debug("found NS %s", namestr); 1897 if (!success) { 1898 success = ISC_TRUE; 1899 lookup_counter++; 1900 lookup = requeue_lookup(query->lookup, 1901 ISC_FALSE); 1902 cancel_lookup(query->lookup); 1903 lookup->doing_xfr = ISC_FALSE; 1904 if (!lookup->trace_root && 1905 section == DNS_SECTION_ANSWER) 1906 lookup->trace = ISC_FALSE; 1907 else 1908 lookup->trace = query->lookup->trace; 1909 lookup->ns_search_only = 1910 query->lookup->ns_search_only; 1911 lookup->trace_root = ISC_FALSE; 1912 if (lookup->ns_search_only) 1913 lookup->recurse = ISC_FALSE; 1914 domain = dns_fixedname_name(&lookup->fdomain); 1915 dns_name_copy(name, domain, NULL); 1916 } 1917 debug("adding server %s", namestr); 1918 num = getaddresses(lookup, namestr, &lresult); 1919 if (lresult != ISC_R_SUCCESS) { 1920 printf("couldn't get address for '%s': %s\n", 1921 namestr, isc_result_totext(lresult)); 1922 if (addresses_result == ISC_R_SUCCESS) { 1923 addresses_result = lresult; 1924 strcpy(bad_namestr, namestr); 1925 } 1926 } 1927 numLookups += num; 1928 dns_rdata_reset(&rdata); 1929 } 1930 } 1931 if (numLookups == 0 && addresses_result != ISC_R_SUCCESS) { 1932 fatal("couldn't get address for '%s': %s", 1933 bad_namestr, isc_result_totext(result)); 1934 } 1935 1936 if (lookup == NULL && 1937 section == DNS_SECTION_ANSWER && 1938 (query->lookup->trace || query->lookup->ns_search_only)) 1939 return (followup_lookup(msg, query, DNS_SECTION_AUTHORITY)); 1940 1941 /* 1942 * Randomize the order the nameserver will be tried. 1943 */ 1944 if (numLookups > 1) { 1945 isc_uint32_t i, j; 1946 dig_serverlist_t my_server_list; 1947 dig_server_t *next; 1948 1949 ISC_LIST_INIT(my_server_list); 1950 1951 i = numLookups; 1952 for (srv = ISC_LIST_HEAD(lookup->my_server_list); 1953 srv != NULL; 1954 srv = ISC_LIST_HEAD(lookup->my_server_list)) { 1955 INSIST(i > 0); 1956 isc_random_get(&j); 1957 j %= i; 1958 next = ISC_LIST_NEXT(srv, link); 1959 while (j-- > 0 && next != NULL) { 1960 srv = next; 1961 next = ISC_LIST_NEXT(srv, link); 1962 } 1963 ISC_LIST_DEQUEUE(lookup->my_server_list, srv, link); 1964 ISC_LIST_APPEND(my_server_list, srv, link); 1965 i--; 1966 } 1967 ISC_LIST_APPENDLIST(lookup->my_server_list, 1968 my_server_list, link); 1969 } 1970 1971 return (numLookups); 1972 } 1973 1974 /*% 1975 * Create and queue a new lookup using the next origin from the search 1976 * list, read in setup_system(). 1977 * 1978 * Return ISC_TRUE iff there was another searchlist entry. 1979 */ 1980 static isc_boolean_t 1981 next_origin(dig_lookup_t *oldlookup) { 1982 dig_lookup_t *newlookup; 1983 dig_searchlist_t *search; 1984 dns_fixedname_t fixed; 1985 dns_name_t *name; 1986 isc_result_t result; 1987 1988 INSIST(!free_now); 1989 1990 debug("next_origin()"); 1991 debug("following up %s", oldlookup->textname); 1992 1993 if (!usesearch) 1994 /* 1995 * We're not using a search list, so don't even think 1996 * about finding the next entry. 1997 */ 1998 return (ISC_FALSE); 1999 2000 /* 2001 * Check for a absolute name or ndots being met. 2002 */ 2003 dns_fixedname_init(&fixed); 2004 name = dns_fixedname_name(&fixed); 2005 result = dns_name_fromstring2(name, oldlookup->textname, NULL, 2006 0, NULL); 2007 if (result == ISC_R_SUCCESS && 2008 (dns_name_isabsolute(name) || 2009 (int)dns_name_countlabels(name) > ndots)) 2010 return (ISC_FALSE); 2011 2012 if (oldlookup->origin == NULL && !oldlookup->need_search) 2013 /* 2014 * Then we just did rootorg; there's nothing left. 2015 */ 2016 return (ISC_FALSE); 2017 if (oldlookup->origin == NULL && oldlookup->need_search) { 2018 newlookup = requeue_lookup(oldlookup, ISC_TRUE); 2019 newlookup->origin = ISC_LIST_HEAD(search_list); 2020 newlookup->need_search = ISC_FALSE; 2021 } else { 2022 search = ISC_LIST_NEXT(oldlookup->origin, link); 2023 if (search == NULL && oldlookup->done_as_is) 2024 return (ISC_FALSE); 2025 newlookup = requeue_lookup(oldlookup, ISC_TRUE); 2026 newlookup->origin = search; 2027 } 2028 cancel_lookup(oldlookup); 2029 return (ISC_TRUE); 2030 } 2031 2032 /*% 2033 * Insert an SOA record into the sendmessage in a lookup. Used for 2034 * creating IXFR queries. 2035 */ 2036 static void 2037 insert_soa(dig_lookup_t *lookup) { 2038 isc_result_t result; 2039 dns_rdata_soa_t soa; 2040 dns_rdata_t *rdata = NULL; 2041 dns_rdatalist_t *rdatalist = NULL; 2042 dns_rdataset_t *rdataset = NULL; 2043 dns_name_t *soaname = NULL; 2044 2045 debug("insert_soa()"); 2046 soa.mctx = mctx; 2047 soa.serial = lookup->ixfr_serial; 2048 soa.refresh = 0; 2049 soa.retry = 0; 2050 soa.expire = 0; 2051 soa.minimum = 0; 2052 soa.common.rdclass = lookup->rdclass; 2053 soa.common.rdtype = dns_rdatatype_soa; 2054 2055 dns_name_init(&soa.origin, NULL); 2056 dns_name_init(&soa.contact, NULL); 2057 2058 dns_name_clone(dns_rootname, &soa.origin); 2059 dns_name_clone(dns_rootname, &soa.contact); 2060 2061 isc_buffer_init(&lookup->rdatabuf, lookup->rdatastore, 2062 sizeof(lookup->rdatastore)); 2063 2064 result = dns_message_gettemprdata(lookup->sendmsg, &rdata); 2065 check_result(result, "dns_message_gettemprdata"); 2066 2067 result = dns_rdata_fromstruct(rdata, lookup->rdclass, 2068 dns_rdatatype_soa, &soa, 2069 &lookup->rdatabuf); 2070 check_result(result, "isc_rdata_fromstruct"); 2071 2072 result = dns_message_gettemprdatalist(lookup->sendmsg, &rdatalist); 2073 check_result(result, "dns_message_gettemprdatalist"); 2074 2075 result = dns_message_gettemprdataset(lookup->sendmsg, &rdataset); 2076 check_result(result, "dns_message_gettemprdataset"); 2077 2078 dns_rdatalist_init(rdatalist); 2079 rdatalist->type = dns_rdatatype_soa; 2080 rdatalist->rdclass = lookup->rdclass; 2081 rdatalist->covers = 0; 2082 rdatalist->ttl = 0; 2083 ISC_LIST_INIT(rdatalist->rdata); 2084 ISC_LIST_APPEND(rdatalist->rdata, rdata, link); 2085 2086 dns_rdatalist_tordataset(rdatalist, rdataset); 2087 2088 result = dns_message_gettempname(lookup->sendmsg, &soaname); 2089 check_result(result, "dns_message_gettempname"); 2090 dns_name_init(soaname, NULL); 2091 dns_name_clone(lookup->name, soaname); 2092 ISC_LIST_INIT(soaname->list); 2093 ISC_LIST_APPEND(soaname->list, rdataset, link); 2094 dns_message_addname(lookup->sendmsg, soaname, DNS_SECTION_AUTHORITY); 2095 } 2096 2097 #ifdef ISC_PLATFORM_USESIT 2098 static void 2099 compute_cookie(unsigned char *clientcookie, size_t len) { 2100 /* XXXMPA need to fix, should be per server. */ 2101 INSIST(len >= 8U); 2102 memmove(clientcookie, cookie_secret, 8); 2103 } 2104 #endif 2105 2106 /*% 2107 * Setup the supplied lookup structure, making it ready to start sending 2108 * queries to servers. Create and initialize the message to be sent as 2109 * well as the query structures and buffer space for the replies. If the 2110 * server list is empty, clone it from the system default list. 2111 */ 2112 isc_boolean_t 2113 setup_lookup(dig_lookup_t *lookup) { 2114 isc_result_t result; 2115 isc_uint32_t id; 2116 int len; 2117 dig_server_t *serv; 2118 dig_query_t *query; 2119 isc_buffer_t b; 2120 dns_compress_t cctx; 2121 char store[MXNAME]; 2122 char ecsbuf[20]; 2123 #ifdef ISC_PLATFORM_USESIT 2124 char sitbuf[256]; 2125 #endif 2126 #ifdef WITH_IDN 2127 idn_result_t mr; 2128 char utf8_textname[MXNAME], utf8_origin[MXNAME], idn_textname[MXNAME]; 2129 #endif 2130 2131 #ifdef WITH_IDN 2132 result = dns_name_settotextfilter(output_filter); 2133 check_result(result, "dns_name_settotextfilter"); 2134 #endif 2135 2136 REQUIRE(lookup != NULL); 2137 INSIST(!free_now); 2138 2139 debug("setup_lookup(%p)", lookup); 2140 2141 result = dns_message_create(mctx, DNS_MESSAGE_INTENTRENDER, 2142 &lookup->sendmsg); 2143 check_result(result, "dns_message_create"); 2144 2145 if (lookup->new_search) { 2146 debug("resetting lookup counter."); 2147 lookup_counter = 0; 2148 } 2149 2150 if (ISC_LIST_EMPTY(lookup->my_server_list)) { 2151 debug("cloning server list"); 2152 clone_server_list(server_list, &lookup->my_server_list); 2153 } 2154 result = dns_message_gettempname(lookup->sendmsg, &lookup->name); 2155 check_result(result, "dns_message_gettempname"); 2156 dns_name_init(lookup->name, NULL); 2157 2158 isc_buffer_init(&lookup->namebuf, lookup->namespace, 2159 sizeof(lookup->namespace)); 2160 isc_buffer_init(&lookup->onamebuf, lookup->onamespace, 2161 sizeof(lookup->onamespace)); 2162 2163 #ifdef WITH_IDN 2164 /* 2165 * We cannot convert `textname' and `origin' separately. 2166 * `textname' doesn't contain TLD, but local mapping needs 2167 * TLD. 2168 */ 2169 mr = idn_encodename(IDN_LOCALCONV | IDN_DELIMMAP, lookup->textname, 2170 utf8_textname, sizeof(utf8_textname)); 2171 idn_check_result(mr, "convert textname to UTF-8"); 2172 #endif 2173 2174 /* 2175 * If the name has too many dots, force the origin to be NULL 2176 * (which produces an absolute lookup). Otherwise, take the origin 2177 * we have if there's one in the struct already. If it's NULL, 2178 * take the first entry in the searchlist iff either usesearch 2179 * is TRUE or we got a domain line in the resolv.conf file. 2180 */ 2181 if (lookup->new_search) { 2182 #ifdef WITH_IDN 2183 if ((count_dots(utf8_textname) >= ndots) || !usesearch) { 2184 lookup->origin = NULL; /* Force abs lookup */ 2185 lookup->done_as_is = ISC_TRUE; 2186 lookup->need_search = usesearch; 2187 } else if (lookup->origin == NULL && usesearch) { 2188 lookup->origin = ISC_LIST_HEAD(search_list); 2189 lookup->need_search = ISC_FALSE; 2190 } 2191 #else 2192 if ((count_dots(lookup->textname) >= ndots) || !usesearch) { 2193 lookup->origin = NULL; /* Force abs lookup */ 2194 lookup->done_as_is = ISC_TRUE; 2195 lookup->need_search = usesearch; 2196 } else if (lookup->origin == NULL && usesearch) { 2197 lookup->origin = ISC_LIST_HEAD(search_list); 2198 lookup->need_search = ISC_FALSE; 2199 } 2200 #endif 2201 } 2202 2203 #ifdef WITH_IDN 2204 if (lookup->origin != NULL) { 2205 mr = idn_encodename(IDN_LOCALCONV | IDN_DELIMMAP, 2206 lookup->origin->origin, utf8_origin, 2207 sizeof(utf8_origin)); 2208 idn_check_result(mr, "convert origin to UTF-8"); 2209 mr = append_textname(utf8_textname, utf8_origin, 2210 sizeof(utf8_textname)); 2211 idn_check_result(mr, "append origin to textname"); 2212 } 2213 mr = idn_encodename(idnoptions | IDN_LOCALMAP | IDN_NAMEPREP | 2214 IDN_IDNCONV | IDN_LENCHECK, utf8_textname, 2215 idn_textname, sizeof(idn_textname)); 2216 idn_check_result(mr, "convert UTF-8 textname to IDN encoding"); 2217 #else 2218 if (lookup->origin != NULL) { 2219 debug("trying origin %s", lookup->origin->origin); 2220 result = dns_message_gettempname(lookup->sendmsg, 2221 &lookup->oname); 2222 check_result(result, "dns_message_gettempname"); 2223 dns_name_init(lookup->oname, NULL); 2224 /* XXX Helper funct to conv char* to name? */ 2225 len = strlen(lookup->origin->origin); 2226 isc_buffer_init(&b, lookup->origin->origin, len); 2227 isc_buffer_add(&b, len); 2228 result = dns_name_fromtext(lookup->oname, &b, dns_rootname, 2229 0, &lookup->onamebuf); 2230 if (result != ISC_R_SUCCESS) { 2231 dns_message_puttempname(lookup->sendmsg, 2232 &lookup->name); 2233 dns_message_puttempname(lookup->sendmsg, 2234 &lookup->oname); 2235 fatal("'%s' is not in legal name syntax (%s)", 2236 lookup->origin->origin, 2237 isc_result_totext(result)); 2238 } 2239 if (lookup->trace && lookup->trace_root) { 2240 dns_name_clone(dns_rootname, lookup->name); 2241 } else { 2242 dns_fixedname_t fixed; 2243 dns_name_t *name; 2244 2245 dns_fixedname_init(&fixed); 2246 name = dns_fixedname_name(&fixed); 2247 len = strlen(lookup->textname); 2248 isc_buffer_init(&b, lookup->textname, len); 2249 isc_buffer_add(&b, len); 2250 result = dns_name_fromtext(name, &b, NULL, 0, NULL); 2251 if (result == ISC_R_SUCCESS && 2252 !dns_name_isabsolute(name)) 2253 result = dns_name_concatenate(name, 2254 lookup->oname, 2255 lookup->name, 2256 &lookup->namebuf); 2257 else if (result == ISC_R_SUCCESS) 2258 result = dns_name_copy(name, lookup->name, 2259 &lookup->namebuf); 2260 if (result != ISC_R_SUCCESS) { 2261 dns_message_puttempname(lookup->sendmsg, 2262 &lookup->name); 2263 dns_message_puttempname(lookup->sendmsg, 2264 &lookup->oname); 2265 if (result == DNS_R_NAMETOOLONG) 2266 return (ISC_FALSE); 2267 fatal("'%s' is not in legal name syntax (%s)", 2268 lookup->textname, 2269 isc_result_totext(result)); 2270 } 2271 } 2272 dns_message_puttempname(lookup->sendmsg, &lookup->oname); 2273 } else 2274 #endif 2275 { 2276 debug("using root origin"); 2277 if (lookup->trace && lookup->trace_root) 2278 dns_name_clone(dns_rootname, lookup->name); 2279 else { 2280 #ifdef WITH_IDN 2281 len = strlen(idn_textname); 2282 isc_buffer_init(&b, idn_textname, len); 2283 isc_buffer_add(&b, len); 2284 result = dns_name_fromtext(lookup->name, &b, 2285 dns_rootname, 0, 2286 &lookup->namebuf); 2287 #else 2288 len = strlen(lookup->textname); 2289 isc_buffer_init(&b, lookup->textname, len); 2290 isc_buffer_add(&b, len); 2291 result = dns_name_fromtext(lookup->name, &b, 2292 dns_rootname, 0, 2293 &lookup->namebuf); 2294 #endif 2295 } 2296 if (result != ISC_R_SUCCESS) { 2297 dns_message_puttempname(lookup->sendmsg, 2298 &lookup->name); 2299 fatal("'%s' is not a legal name " 2300 "(%s)", lookup->textname, 2301 isc_result_totext(result)); 2302 } 2303 } 2304 dns_name_format(lookup->name, store, sizeof(store)); 2305 trying(store, lookup); 2306 INSIST(dns_name_isabsolute(lookup->name)); 2307 2308 isc_random_get(&id); 2309 lookup->sendmsg->id = (unsigned short)id & 0xFFFF; 2310 lookup->sendmsg->opcode = dns_opcode_query; 2311 lookup->msgcounter = 0; 2312 /* 2313 * If this is a trace request, completely disallow recursion, since 2314 * it's meaningless for traces. 2315 */ 2316 if (lookup->trace || (lookup->ns_search_only && !lookup->trace_root)) 2317 lookup->recurse = ISC_FALSE; 2318 2319 if (lookup->recurse && 2320 lookup->rdtype != dns_rdatatype_axfr && 2321 lookup->rdtype != dns_rdatatype_ixfr) { 2322 debug("recursive query"); 2323 lookup->sendmsg->flags |= DNS_MESSAGEFLAG_RD; 2324 } 2325 2326 /* XXX aaflag */ 2327 if (lookup->aaonly) { 2328 debug("AA query"); 2329 lookup->sendmsg->flags |= DNS_MESSAGEFLAG_AA; 2330 } 2331 2332 if (lookup->adflag) { 2333 debug("AD query"); 2334 lookup->sendmsg->flags |= DNS_MESSAGEFLAG_AD; 2335 } 2336 2337 if (lookup->cdflag) { 2338 debug("CD query"); 2339 lookup->sendmsg->flags |= DNS_MESSAGEFLAG_CD; 2340 } 2341 2342 dns_message_addname(lookup->sendmsg, lookup->name, 2343 DNS_SECTION_QUESTION); 2344 2345 if (lookup->trace && lookup->trace_root) { 2346 lookup->qrdtype = lookup->rdtype; 2347 lookup->rdtype = dns_rdatatype_ns; 2348 } 2349 2350 if ((lookup->rdtype == dns_rdatatype_axfr) || 2351 (lookup->rdtype == dns_rdatatype_ixfr)) { 2352 /* 2353 * Force TCP mode if we're doing an axfr. 2354 */ 2355 if (lookup->rdtype == dns_rdatatype_axfr) { 2356 lookup->doing_xfr = ISC_TRUE; 2357 lookup->tcp_mode = ISC_TRUE; 2358 } else if (lookup->tcp_mode) { 2359 lookup->doing_xfr = ISC_TRUE; 2360 } 2361 } 2362 2363 add_question(lookup->sendmsg, lookup->name, lookup->rdclass, 2364 lookup->rdtype); 2365 2366 /* add_soa */ 2367 if (lookup->rdtype == dns_rdatatype_ixfr) 2368 insert_soa(lookup); 2369 2370 /* XXX Insist this? */ 2371 lookup->tsigctx = NULL; 2372 lookup->querysig = NULL; 2373 if (key != NULL) { 2374 debug("initializing keys"); 2375 result = dns_message_settsigkey(lookup->sendmsg, key); 2376 check_result(result, "dns_message_settsigkey"); 2377 } 2378 2379 lookup->sendspace = isc_mempool_get(commctx); 2380 if (lookup->sendspace == NULL) 2381 fatal("memory allocation failure"); 2382 2383 result = dns_compress_init(&cctx, -1, mctx); 2384 check_result(result, "dns_compress_init"); 2385 2386 debug("starting to render the message"); 2387 isc_buffer_init(&lookup->renderbuf, lookup->sendspace, COMMSIZE); 2388 result = dns_message_renderbegin(lookup->sendmsg, &cctx, 2389 &lookup->renderbuf); 2390 check_result(result, "dns_message_renderbegin"); 2391 if (lookup->udpsize > 0 || lookup->dnssec || 2392 lookup->edns > -1 || lookup->ecs_addr != NULL) 2393 { 2394 dns_ednsopt_t opts[DNS_EDNSOPTIONS]; 2395 int i = 0; 2396 2397 if (lookup->udpsize == 0) 2398 lookup->udpsize = 4096; 2399 if (lookup->edns < 0) 2400 lookup->edns = 0; 2401 2402 if (lookup->nsid) { 2403 INSIST(i < DNS_EDNSOPTIONS); 2404 opts[i].code = DNS_OPT_NSID; 2405 opts[i].length = 0; 2406 opts[i].value = NULL; 2407 i++; 2408 } 2409 2410 if (lookup->ecs_addr != NULL) { 2411 isc_uint32_t prefixlen; 2412 struct sockaddr *sa; 2413 struct sockaddr_in *sin; 2414 struct sockaddr_in6 *sin6; 2415 size_t addrl; 2416 2417 sa = &lookup->ecs_addr->type.sa; 2418 prefixlen = lookup->ecs_addr->length; 2419 2420 /* Round up prefix len to a multiple of 8 */ 2421 addrl = (prefixlen + 7) / 8; 2422 2423 INSIST(i < DNS_EDNSOPTIONS); 2424 opts[i].code = DNS_OPT_CLIENT_SUBNET; 2425 opts[i].length = (isc_uint16_t) addrl + 4; 2426 check_result(result, "isc_buffer_allocate"); 2427 isc_buffer_init(&b, ecsbuf, sizeof(ecsbuf)); 2428 if (sa->sa_family == AF_INET) { 2429 sin = (struct sockaddr_in *) sa; 2430 isc_buffer_putuint16(&b, 1); 2431 isc_buffer_putuint8(&b, prefixlen); 2432 isc_buffer_putuint8(&b, 0); 2433 isc_buffer_putmem(&b, 2434 (isc_uint8_t *) &sin->sin_addr, 2435 (unsigned int) addrl); 2436 } else { 2437 sin6 = (struct sockaddr_in6 *) sa; 2438 isc_buffer_putuint16(&b, 2); 2439 isc_buffer_putuint8(&b, prefixlen); 2440 isc_buffer_putuint8(&b, 0); 2441 isc_buffer_putmem(&b, 2442 (isc_uint8_t *) &sin6->sin6_addr, 2443 (unsigned int) addrl); 2444 } 2445 2446 opts[i].value = (isc_uint8_t *) ecsbuf; 2447 i++; 2448 } 2449 2450 #ifdef ISC_PLATFORM_USESIT 2451 if (lookup->sit) { 2452 INSIST(i < DNS_EDNSOPTIONS); 2453 opts[i].code = DNS_OPT_SIT; 2454 if (lookup->sitvalue != NULL) { 2455 isc_buffer_init(&b, sitbuf, sizeof(sitbuf)); 2456 result = isc_hex_decodestring(lookup->sitvalue, 2457 &b); 2458 check_result(result, "isc_hex_decodestring"); 2459 opts[i].value = isc_buffer_base(&b); 2460 opts[i].length = isc_buffer_usedlength(&b); 2461 } else { 2462 compute_cookie(cookie, sizeof(cookie)); 2463 opts[i].length = 8; 2464 opts[i].value = cookie; 2465 } 2466 i++; 2467 } 2468 #endif 2469 2470 if (lookup->expire) { 2471 INSIST(i < DNS_EDNSOPTIONS); 2472 opts[i].code = DNS_OPT_EXPIRE; 2473 opts[i].length = 0; 2474 opts[i].value = NULL; 2475 i++; 2476 } 2477 2478 add_opt(lookup->sendmsg, lookup->udpsize, 2479 lookup->edns, lookup->dnssec, opts, i); 2480 } 2481 2482 result = dns_message_rendersection(lookup->sendmsg, 2483 DNS_SECTION_QUESTION, 0); 2484 check_result(result, "dns_message_rendersection"); 2485 result = dns_message_rendersection(lookup->sendmsg, 2486 DNS_SECTION_AUTHORITY, 0); 2487 check_result(result, "dns_message_rendersection"); 2488 result = dns_message_renderend(lookup->sendmsg); 2489 check_result(result, "dns_message_renderend"); 2490 debug("done rendering"); 2491 2492 dns_compress_invalidate(&cctx); 2493 2494 /* 2495 * Force TCP mode if the request is larger than 512 bytes. 2496 */ 2497 if (isc_buffer_usedlength(&lookup->renderbuf) > 512) 2498 lookup->tcp_mode = ISC_TRUE; 2499 2500 lookup->pending = ISC_FALSE; 2501 2502 for (serv = ISC_LIST_HEAD(lookup->my_server_list); 2503 serv != NULL; 2504 serv = ISC_LIST_NEXT(serv, link)) { 2505 query = isc_mem_allocate(mctx, sizeof(dig_query_t)); 2506 if (query == NULL) 2507 fatal("memory allocation failure in %s:%d", 2508 __FILE__, __LINE__); 2509 debug("create query %p linked to lookup %p", 2510 query, lookup); 2511 query->lookup = lookup; 2512 query->waiting_connect = ISC_FALSE; 2513 query->waiting_senddone = ISC_FALSE; 2514 query->pending_free = ISC_FALSE; 2515 query->recv_made = ISC_FALSE; 2516 query->first_pass = ISC_TRUE; 2517 query->first_soa_rcvd = ISC_FALSE; 2518 query->second_rr_rcvd = ISC_FALSE; 2519 query->first_repeat_rcvd = ISC_FALSE; 2520 query->warn_id = ISC_TRUE; 2521 query->first_rr_serial = 0; 2522 query->second_rr_serial = 0; 2523 query->servname = serv->servername; 2524 query->userarg = serv->userarg; 2525 query->rr_count = 0; 2526 query->msg_count = 0; 2527 query->byte_count = 0; 2528 query->ixfr_axfr = ISC_FALSE; 2529 ISC_LIST_INIT(query->recvlist); 2530 ISC_LIST_INIT(query->lengthlist); 2531 query->sock = NULL; 2532 query->recvspace = isc_mempool_get(commctx); 2533 if (query->recvspace == NULL) 2534 fatal("memory allocation failure"); 2535 2536 isc_buffer_init(&query->recvbuf, query->recvspace, COMMSIZE); 2537 isc_buffer_init(&query->lengthbuf, query->lengthspace, 2); 2538 isc_buffer_init(&query->slbuf, query->slspace, 2); 2539 query->sendbuf = lookup->renderbuf; 2540 2541 ISC_LINK_INIT(query, clink); 2542 ISC_LINK_INIT(query, link); 2543 ISC_LIST_ENQUEUE(lookup->q, query, link); 2544 } 2545 2546 /* XXX qrflag, print_query, etc... */ 2547 if (!ISC_LIST_EMPTY(lookup->q) && qr) { 2548 extrabytes = 0; 2549 printmessage(ISC_LIST_HEAD(lookup->q), lookup->sendmsg, 2550 ISC_TRUE); 2551 } 2552 return (ISC_TRUE); 2553 } 2554 2555 /*% 2556 * Event handler for send completion. Track send counter, and clear out 2557 * the query if the send was canceled. 2558 */ 2559 static void 2560 send_done(isc_task_t *_task, isc_event_t *event) { 2561 isc_socketevent_t *sevent = (isc_socketevent_t *)event; 2562 isc_buffer_t *b = NULL; 2563 dig_query_t *query, *next; 2564 dig_lookup_t *l; 2565 2566 REQUIRE(event->ev_type == ISC_SOCKEVENT_SENDDONE); 2567 2568 UNUSED(_task); 2569 2570 LOCK_LOOKUP; 2571 2572 debug("send_done()"); 2573 sendcount--; 2574 debug("sendcount=%d", sendcount); 2575 INSIST(sendcount >= 0); 2576 2577 for (b = ISC_LIST_HEAD(sevent->bufferlist); 2578 b != NULL; 2579 b = ISC_LIST_HEAD(sevent->bufferlist)) { 2580 ISC_LIST_DEQUEUE(sevent->bufferlist, b, link); 2581 isc_mem_free(mctx, b); 2582 } 2583 2584 query = event->ev_arg; 2585 query->waiting_senddone = ISC_FALSE; 2586 l = query->lookup; 2587 2588 if (l->ns_search_only && !l->trace_root && !l->tcp_mode) { 2589 debug("sending next, since searching"); 2590 next = ISC_LIST_NEXT(query, link); 2591 if (next != NULL) 2592 send_udp(next); 2593 } 2594 2595 isc_event_free(&event); 2596 2597 if (query->pending_free) 2598 isc_mem_free(mctx, query); 2599 2600 check_if_done(); 2601 UNLOCK_LOOKUP; 2602 } 2603 2604 /*% 2605 * Cancel a lookup, sending isc_socket_cancel() requests to all outstanding 2606 * IO sockets. The cancel handlers should take care of cleaning up the 2607 * query and lookup structures 2608 */ 2609 static void 2610 cancel_lookup(dig_lookup_t *lookup) { 2611 dig_query_t *query, *next; 2612 2613 debug("cancel_lookup()"); 2614 query = ISC_LIST_HEAD(lookup->q); 2615 while (query != NULL) { 2616 next = ISC_LIST_NEXT(query, link); 2617 if (query->sock != NULL) { 2618 isc_socket_cancel(query->sock, global_task, 2619 ISC_SOCKCANCEL_ALL); 2620 check_if_done(); 2621 } else { 2622 clear_query(query); 2623 } 2624 query = next; 2625 } 2626 if (lookup->timer != NULL) 2627 isc_timer_detach(&lookup->timer); 2628 lookup->pending = ISC_FALSE; 2629 lookup->retries = 0; 2630 } 2631 2632 static void 2633 bringup_timer(dig_query_t *query, unsigned int default_timeout) { 2634 dig_lookup_t *l; 2635 unsigned int local_timeout; 2636 isc_result_t result; 2637 2638 debug("bringup_timer()"); 2639 /* 2640 * If the timer already exists, that means we're calling this 2641 * a second time (for a retry). Don't need to recreate it, 2642 * just reset it. 2643 */ 2644 l = query->lookup; 2645 if (ISC_LIST_NEXT(query, link) != NULL) 2646 local_timeout = SERVER_TIMEOUT; 2647 else { 2648 if (timeout == 0) 2649 local_timeout = default_timeout; 2650 else 2651 local_timeout = timeout; 2652 } 2653 debug("have local timeout of %d", local_timeout); 2654 isc_interval_set(&l->interval, local_timeout, 0); 2655 if (l->timer != NULL) 2656 isc_timer_detach(&l->timer); 2657 result = isc_timer_create(timermgr, isc_timertype_once, NULL, 2658 &l->interval, global_task, connect_timeout, 2659 l, &l->timer); 2660 check_result(result, "isc_timer_create"); 2661 } 2662 2663 static void 2664 force_timeout(dig_lookup_t *l, dig_query_t *query) { 2665 isc_event_t *event; 2666 2667 debug("force_timeout ()"); 2668 event = isc_event_allocate(mctx, query, ISC_TIMEREVENT_IDLE, 2669 connect_timeout, l, 2670 sizeof(isc_event_t)); 2671 if (event == NULL) { 2672 fatal("isc_event_allocate: %s", 2673 isc_result_totext(ISC_R_NOMEMORY)); 2674 } 2675 isc_task_send(global_task, &event); 2676 2677 /* 2678 * The timer may have expired if, for example, get_address() takes 2679 * long time and the timer was running on a different thread. 2680 * We need to cancel the possible timeout event not to confuse 2681 * ourselves due to the duplicate events. 2682 */ 2683 if (l->timer != NULL) 2684 isc_timer_detach(&l->timer); 2685 } 2686 2687 2688 static void 2689 connect_done(isc_task_t *task, isc_event_t *event); 2690 2691 /*% 2692 * Unlike send_udp, this can't be called multiple times with the same 2693 * query. When we retry TCP, we requeue the whole lookup, which should 2694 * start anew. 2695 */ 2696 static void 2697 send_tcp_connect(dig_query_t *query) { 2698 isc_result_t result; 2699 dig_query_t *next; 2700 dig_lookup_t *l; 2701 2702 debug("send_tcp_connect(%p)", query); 2703 2704 l = query->lookup; 2705 query->waiting_connect = ISC_TRUE; 2706 query->lookup->current_query = query; 2707 result = get_address(query->servname, port, &query->sockaddr); 2708 if (result != ISC_R_SUCCESS) { 2709 /* 2710 * This servname doesn't have an address. Try the next server 2711 * by triggering an immediate 'timeout' (we lie, but the effect 2712 * is the same). 2713 */ 2714 force_timeout(l, query); 2715 return; 2716 } 2717 2718 if (specified_source && 2719 (isc_sockaddr_pf(&query->sockaddr) != 2720 isc_sockaddr_pf(&bind_address))) { 2721 printf(";; Skipping server %s, incompatible " 2722 "address family\n", query->servname); 2723 query->waiting_connect = ISC_FALSE; 2724 next = ISC_LIST_NEXT(query, link); 2725 l = query->lookup; 2726 clear_query(query); 2727 if (next == NULL) { 2728 printf(";; No acceptable nameservers\n"); 2729 check_next_lookup(l); 2730 return; 2731 } 2732 send_tcp_connect(next); 2733 return; 2734 } 2735 2736 INSIST(query->sock == NULL); 2737 2738 if (keep != NULL && isc_sockaddr_equal(&keepaddr, &query->sockaddr)) { 2739 sockcount++; 2740 isc_socket_attach(keep, &query->sock); 2741 query->waiting_connect = ISC_FALSE; 2742 launch_next_query(query, ISC_TRUE); 2743 goto search; 2744 } 2745 2746 result = isc_socket_create(socketmgr, 2747 isc_sockaddr_pf(&query->sockaddr), 2748 isc_sockettype_tcp, &query->sock); 2749 check_result(result, "isc_socket_create"); 2750 sockcount++; 2751 debug("sockcount=%d", sockcount); 2752 if (specified_source) 2753 result = isc_socket_bind(query->sock, &bind_address, 2754 ISC_SOCKET_REUSEADDRESS); 2755 else { 2756 if ((isc_sockaddr_pf(&query->sockaddr) == AF_INET) && 2757 have_ipv4) 2758 isc_sockaddr_any(&bind_any); 2759 else 2760 isc_sockaddr_any6(&bind_any); 2761 result = isc_socket_bind(query->sock, &bind_any, 0); 2762 } 2763 check_result(result, "isc_socket_bind"); 2764 bringup_timer(query, TCP_TIMEOUT); 2765 result = isc_socket_connect(query->sock, &query->sockaddr, 2766 global_task, connect_done, query); 2767 check_result(result, "isc_socket_connect"); 2768 search: 2769 /* 2770 * If we're at the endgame of a nameserver search, we need to 2771 * immediately bring up all the queries. Do it here. 2772 */ 2773 if (l->ns_search_only && !l->trace_root) { 2774 debug("sending next, since searching"); 2775 next = ISC_LIST_NEXT(query, link); 2776 if (ISC_LINK_LINKED(query, link)) 2777 ISC_LIST_DEQUEUE(l->q, query, link); 2778 ISC_LIST_ENQUEUE(l->connecting, query, clink); 2779 if (next != NULL) 2780 send_tcp_connect(next); 2781 } 2782 } 2783 2784 static isc_buffer_t * 2785 clone_buffer(isc_buffer_t *source) { 2786 isc_buffer_t *buffer; 2787 buffer = isc_mem_allocate(mctx, sizeof(*buffer)); 2788 if (buffer == NULL) 2789 fatal("memory allocation failure in %s:%d", 2790 __FILE__, __LINE__); 2791 *buffer = *source; 2792 return (buffer); 2793 } 2794 2795 /*% 2796 * Send a UDP packet to the remote nameserver, possible starting the 2797 * recv action as well. Also make sure that the timer is running and 2798 * is properly reset. 2799 */ 2800 static void 2801 send_udp(dig_query_t *query) { 2802 dig_lookup_t *l = NULL; 2803 isc_result_t result; 2804 isc_buffer_t *sendbuf; 2805 2806 debug("send_udp(%p)", query); 2807 2808 l = query->lookup; 2809 bringup_timer(query, UDP_TIMEOUT); 2810 l->current_query = query; 2811 debug("working on lookup %p, query %p", query->lookup, query); 2812 if (!query->recv_made) { 2813 /* XXX Check the sense of this, need assertion? */ 2814 query->waiting_connect = ISC_FALSE; 2815 result = get_address(query->servname, port, &query->sockaddr); 2816 if (result != ISC_R_SUCCESS) { 2817 /* This servname doesn't have an address. */ 2818 force_timeout(l, query); 2819 return; 2820 } 2821 2822 result = isc_socket_create(socketmgr, 2823 isc_sockaddr_pf(&query->sockaddr), 2824 isc_sockettype_udp, &query->sock); 2825 check_result(result, "isc_socket_create"); 2826 sockcount++; 2827 debug("sockcount=%d", sockcount); 2828 if (specified_source) { 2829 result = isc_socket_bind(query->sock, &bind_address, 2830 ISC_SOCKET_REUSEADDRESS); 2831 } else { 2832 isc_sockaddr_anyofpf(&bind_any, 2833 isc_sockaddr_pf(&query->sockaddr)); 2834 result = isc_socket_bind(query->sock, &bind_any, 0); 2835 } 2836 check_result(result, "isc_socket_bind"); 2837 2838 query->recv_made = ISC_TRUE; 2839 ISC_LINK_INIT(&query->recvbuf, link); 2840 ISC_LIST_ENQUEUE(query->recvlist, &query->recvbuf, 2841 link); 2842 debug("recving with lookup=%p, query=%p, sock=%p", 2843 query->lookup, query, query->sock); 2844 result = isc_socket_recvv(query->sock, &query->recvlist, 1, 2845 global_task, recv_done, query); 2846 check_result(result, "isc_socket_recvv"); 2847 recvcount++; 2848 debug("recvcount=%d", recvcount); 2849 } 2850 ISC_LIST_INIT(query->sendlist); 2851 sendbuf = clone_buffer(&query->sendbuf); 2852 ISC_LIST_ENQUEUE(query->sendlist, sendbuf, link); 2853 debug("sending a request"); 2854 TIME_NOW(&query->time_sent); 2855 INSIST(query->sock != NULL); 2856 query->waiting_senddone = ISC_TRUE; 2857 result = isc_socket_sendtov2(query->sock, &query->sendlist, 2858 global_task, send_done, query, 2859 &query->sockaddr, NULL, 2860 ISC_SOCKFLAG_NORETRY); 2861 check_result(result, "isc_socket_sendtov"); 2862 sendcount++; 2863 } 2864 2865 /*% 2866 * IO timeout handler, used for both connect and recv timeouts. If 2867 * retries are still allowed, either resend the UDP packet or queue a 2868 * new TCP lookup. Otherwise, cancel the lookup. 2869 */ 2870 static void 2871 connect_timeout(isc_task_t *task, isc_event_t *event) { 2872 dig_lookup_t *l = NULL; 2873 dig_query_t *query = NULL, *next, *cq; 2874 2875 UNUSED(task); 2876 REQUIRE(event->ev_type == ISC_TIMEREVENT_IDLE); 2877 2878 debug("connect_timeout()"); 2879 2880 LOCK_LOOKUP; 2881 l = event->ev_arg; 2882 query = l->current_query; 2883 isc_event_free(&event); 2884 2885 INSIST(!free_now); 2886 2887 if ((query != NULL) && (query->lookup->current_query != NULL) && 2888 (ISC_LIST_NEXT(query->lookup->current_query, link) != NULL)) { 2889 debug("trying next server..."); 2890 cq = query->lookup->current_query; 2891 if (!l->tcp_mode) 2892 send_udp(ISC_LIST_NEXT(cq, link)); 2893 else { 2894 if (query->sock != NULL) 2895 isc_socket_cancel(query->sock, NULL, 2896 ISC_SOCKCANCEL_ALL); 2897 next = ISC_LIST_NEXT(cq, link); 2898 if (next != NULL) 2899 send_tcp_connect(next); 2900 } 2901 UNLOCK_LOOKUP; 2902 return; 2903 } 2904 2905 if (l->retries > 1) { 2906 if (!l->tcp_mode) { 2907 l->retries--; 2908 debug("resending UDP request to first server"); 2909 send_udp(ISC_LIST_HEAD(l->q)); 2910 } else { 2911 debug("making new TCP request, %d tries left", 2912 l->retries); 2913 l->retries--; 2914 requeue_lookup(l, ISC_TRUE); 2915 cancel_lookup(l); 2916 check_next_lookup(l); 2917 } 2918 } else { 2919 fputs(l->cmdline, stdout); 2920 printf(";; connection timed out; no servers could be " 2921 "reached\n"); 2922 cancel_lookup(l); 2923 check_next_lookup(l); 2924 if (exitcode < 9) 2925 exitcode = 9; 2926 } 2927 UNLOCK_LOOKUP; 2928 } 2929 2930 /*% 2931 * Event handler for the TCP recv which gets the length header of TCP 2932 * packets. Start the next recv of length bytes. 2933 */ 2934 static void 2935 tcp_length_done(isc_task_t *task, isc_event_t *event) { 2936 isc_socketevent_t *sevent; 2937 isc_buffer_t *b = NULL; 2938 isc_result_t result; 2939 dig_query_t *query = NULL; 2940 dig_lookup_t *l; 2941 isc_uint16_t length; 2942 2943 REQUIRE(event->ev_type == ISC_SOCKEVENT_RECVDONE); 2944 INSIST(!free_now); 2945 2946 UNUSED(task); 2947 2948 debug("tcp_length_done()"); 2949 2950 LOCK_LOOKUP; 2951 sevent = (isc_socketevent_t *)event; 2952 query = event->ev_arg; 2953 2954 recvcount--; 2955 INSIST(recvcount >= 0); 2956 2957 b = ISC_LIST_HEAD(sevent->bufferlist); 2958 INSIST(b == &query->lengthbuf); 2959 ISC_LIST_DEQUEUE(sevent->bufferlist, b, link); 2960 2961 if (sevent->result == ISC_R_CANCELED) { 2962 isc_event_free(&event); 2963 l = query->lookup; 2964 clear_query(query); 2965 check_next_lookup(l); 2966 UNLOCK_LOOKUP; 2967 return; 2968 } 2969 if (sevent->result != ISC_R_SUCCESS) { 2970 char sockstr[ISC_SOCKADDR_FORMATSIZE]; 2971 isc_sockaddr_format(&query->sockaddr, sockstr, 2972 sizeof(sockstr)); 2973 printf(";; communications error to %s: %s\n", 2974 sockstr, isc_result_totext(sevent->result)); 2975 l = query->lookup; 2976 isc_socket_detach(&query->sock); 2977 sockcount--; 2978 debug("sockcount=%d", sockcount); 2979 INSIST(sockcount >= 0); 2980 isc_event_free(&event); 2981 clear_query(query); 2982 check_next_lookup(l); 2983 UNLOCK_LOOKUP; 2984 return; 2985 } 2986 length = isc_buffer_getuint16(b); 2987 if (length == 0) { 2988 isc_event_free(&event); 2989 launch_next_query(query, ISC_FALSE); 2990 UNLOCK_LOOKUP; 2991 return; 2992 } 2993 2994 /* 2995 * Even though the buffer was already init'ed, we need 2996 * to redo it now, to force the length we want. 2997 */ 2998 isc_buffer_invalidate(&query->recvbuf); 2999 isc_buffer_init(&query->recvbuf, query->recvspace, length); 3000 ENSURE(ISC_LIST_EMPTY(query->recvlist)); 3001 ISC_LINK_INIT(&query->recvbuf, link); 3002 ISC_LIST_ENQUEUE(query->recvlist, &query->recvbuf, link); 3003 debug("recving with lookup=%p, query=%p", query->lookup, query); 3004 result = isc_socket_recvv(query->sock, &query->recvlist, length, task, 3005 recv_done, query); 3006 check_result(result, "isc_socket_recvv"); 3007 recvcount++; 3008 debug("resubmitted recv request with length %d, recvcount=%d", 3009 length, recvcount); 3010 isc_event_free(&event); 3011 UNLOCK_LOOKUP; 3012 } 3013 3014 /*% 3015 * For transfers that involve multiple recvs (XFR's in particular), 3016 * launch the next recv. 3017 */ 3018 static void 3019 launch_next_query(dig_query_t *query, isc_boolean_t include_question) { 3020 isc_result_t result; 3021 dig_lookup_t *l; 3022 isc_buffer_t *buffer; 3023 3024 INSIST(!free_now); 3025 3026 debug("launch_next_query()"); 3027 3028 if (!query->lookup->pending) { 3029 debug("ignoring launch_next_query because !pending"); 3030 isc_socket_detach(&query->sock); 3031 sockcount--; 3032 debug("sockcount=%d", sockcount); 3033 INSIST(sockcount >= 0); 3034 query->waiting_connect = ISC_FALSE; 3035 l = query->lookup; 3036 clear_query(query); 3037 check_next_lookup(l); 3038 return; 3039 } 3040 3041 isc_buffer_clear(&query->slbuf); 3042 isc_buffer_clear(&query->lengthbuf); 3043 isc_buffer_putuint16(&query->slbuf, (isc_uint16_t) query->sendbuf.used); 3044 ISC_LIST_INIT(query->sendlist); 3045 ISC_LINK_INIT(&query->slbuf, link); 3046 if (!query->first_soa_rcvd) { 3047 buffer = clone_buffer(&query->slbuf); 3048 ISC_LIST_ENQUEUE(query->sendlist, buffer, link); 3049 if (include_question) { 3050 buffer = clone_buffer(&query->sendbuf); 3051 ISC_LIST_ENQUEUE(query->sendlist, buffer, link); 3052 } 3053 } 3054 3055 ISC_LINK_INIT(&query->lengthbuf, link); 3056 ISC_LIST_ENQUEUE(query->lengthlist, &query->lengthbuf, link); 3057 3058 result = isc_socket_recvv(query->sock, &query->lengthlist, 0, 3059 global_task, tcp_length_done, query); 3060 check_result(result, "isc_socket_recvv"); 3061 recvcount++; 3062 debug("recvcount=%d", recvcount); 3063 if (!query->first_soa_rcvd) { 3064 debug("sending a request in launch_next_query"); 3065 TIME_NOW(&query->time_sent); 3066 query->waiting_senddone = ISC_TRUE; 3067 result = isc_socket_sendv(query->sock, &query->sendlist, 3068 global_task, send_done, query); 3069 check_result(result, "isc_socket_sendv"); 3070 sendcount++; 3071 debug("sendcount=%d", sendcount); 3072 } 3073 query->waiting_connect = ISC_FALSE; 3074 #if 0 3075 check_next_lookup(query->lookup); 3076 #endif 3077 return; 3078 } 3079 3080 /*% 3081 * Event handler for TCP connect complete. Make sure the connection was 3082 * successful, then pass into launch_next_query to actually send the 3083 * question. 3084 */ 3085 static void 3086 connect_done(isc_task_t *task, isc_event_t *event) { 3087 isc_socketevent_t *sevent = NULL; 3088 dig_query_t *query = NULL, *next; 3089 dig_lookup_t *l; 3090 3091 UNUSED(task); 3092 3093 REQUIRE(event->ev_type == ISC_SOCKEVENT_CONNECT); 3094 INSIST(!free_now); 3095 3096 debug("connect_done()"); 3097 3098 LOCK_LOOKUP; 3099 sevent = (isc_socketevent_t *)event; 3100 query = sevent->ev_arg; 3101 3102 INSIST(query->waiting_connect); 3103 3104 query->waiting_connect = ISC_FALSE; 3105 3106 if (sevent->result == ISC_R_CANCELED) { 3107 debug("in cancel handler"); 3108 isc_socket_detach(&query->sock); 3109 INSIST(sockcount > 0); 3110 sockcount--; 3111 debug("sockcount=%d", sockcount); 3112 query->waiting_connect = ISC_FALSE; 3113 isc_event_free(&event); 3114 l = query->lookup; 3115 clear_query(query); 3116 check_next_lookup(l); 3117 UNLOCK_LOOKUP; 3118 return; 3119 } 3120 if (sevent->result != ISC_R_SUCCESS) { 3121 char sockstr[ISC_SOCKADDR_FORMATSIZE]; 3122 3123 debug("unsuccessful connection: %s", 3124 isc_result_totext(sevent->result)); 3125 isc_sockaddr_format(&query->sockaddr, sockstr, sizeof(sockstr)); 3126 if (sevent->result != ISC_R_CANCELED) 3127 printf(";; Connection to %s(%s) for %s failed: " 3128 "%s.\n", sockstr, 3129 query->servname, query->lookup->textname, 3130 isc_result_totext(sevent->result)); 3131 isc_socket_detach(&query->sock); 3132 sockcount--; 3133 INSIST(sockcount >= 0); 3134 /* XXX Clean up exitcodes */ 3135 if (exitcode < 9) 3136 exitcode = 9; 3137 debug("sockcount=%d", sockcount); 3138 query->waiting_connect = ISC_FALSE; 3139 isc_event_free(&event); 3140 l = query->lookup; 3141 if ((l->current_query != NULL) && 3142 (ISC_LINK_LINKED(l->current_query, link))) 3143 next = ISC_LIST_NEXT(l->current_query, link); 3144 else 3145 next = NULL; 3146 clear_query(query); 3147 if (next != NULL) { 3148 bringup_timer(next, TCP_TIMEOUT); 3149 send_tcp_connect(next); 3150 } else 3151 check_next_lookup(l); 3152 UNLOCK_LOOKUP; 3153 return; 3154 } 3155 if (keep_open) { 3156 if (keep != NULL) 3157 isc_socket_detach(&keep); 3158 isc_socket_attach(query->sock, &keep); 3159 keepaddr = query->sockaddr; 3160 } 3161 launch_next_query(query, ISC_TRUE); 3162 isc_event_free(&event); 3163 UNLOCK_LOOKUP; 3164 } 3165 3166 /*% 3167 * Check if the ongoing XFR needs more data before it's complete, using 3168 * the semantics of IXFR and AXFR protocols. Much of the complexity of 3169 * this routine comes from determining when an IXFR is complete. 3170 * ISC_FALSE means more data is on the way, and the recv has been issued. 3171 */ 3172 static isc_boolean_t 3173 check_for_more_data(dig_query_t *query, dns_message_t *msg, 3174 isc_socketevent_t *sevent) 3175 { 3176 dns_rdataset_t *rdataset = NULL; 3177 dns_rdata_t rdata = DNS_RDATA_INIT; 3178 dns_rdata_soa_t soa; 3179 isc_uint32_t ixfr_serial = query->lookup->ixfr_serial, serial; 3180 isc_result_t result; 3181 isc_boolean_t ixfr = query->lookup->rdtype == dns_rdatatype_ixfr; 3182 isc_boolean_t axfr = query->lookup->rdtype == dns_rdatatype_axfr; 3183 3184 if (ixfr) 3185 axfr = query->ixfr_axfr; 3186 3187 debug("check_for_more_data()"); 3188 3189 /* 3190 * By the time we're in this routine, we know we're doing 3191 * either an AXFR or IXFR. If there's no second_rr_type, 3192 * then we don't yet know which kind of answer we got back 3193 * from the server. Here, we're going to walk through the 3194 * rr's in the message, acting as necessary whenever we hit 3195 * an SOA rr. 3196 */ 3197 3198 query->msg_count++; 3199 query->byte_count += sevent->n; 3200 result = dns_message_firstname(msg, DNS_SECTION_ANSWER); 3201 if (result != ISC_R_SUCCESS) { 3202 puts("; Transfer failed."); 3203 return (ISC_TRUE); 3204 } 3205 do { 3206 dns_name_t *name; 3207 name = NULL; 3208 dns_message_currentname(msg, DNS_SECTION_ANSWER, 3209 &name); 3210 for (rdataset = ISC_LIST_HEAD(name->list); 3211 rdataset != NULL; 3212 rdataset = ISC_LIST_NEXT(rdataset, link)) { 3213 result = dns_rdataset_first(rdataset); 3214 if (result != ISC_R_SUCCESS) 3215 continue; 3216 do { 3217 query->rr_count++; 3218 dns_rdata_reset(&rdata); 3219 dns_rdataset_current(rdataset, &rdata); 3220 /* 3221 * If this is the first rr, make sure 3222 * it's an SOA 3223 */ 3224 if ((!query->first_soa_rcvd) && 3225 (rdata.type != dns_rdatatype_soa)) { 3226 puts("; Transfer failed. " 3227 "Didn't start with SOA answer."); 3228 return (ISC_TRUE); 3229 } 3230 if ((!query->second_rr_rcvd) && 3231 (rdata.type != dns_rdatatype_soa)) { 3232 query->second_rr_rcvd = ISC_TRUE; 3233 query->second_rr_serial = 0; 3234 debug("got the second rr as nonsoa"); 3235 axfr = query->ixfr_axfr = ISC_TRUE; 3236 goto next_rdata; 3237 } 3238 3239 /* 3240 * If the record is anything except an SOA 3241 * now, just continue on... 3242 */ 3243 if (rdata.type != dns_rdatatype_soa) 3244 goto next_rdata; 3245 3246 /* Now we have an SOA. Work with it. */ 3247 debug("got an SOA"); 3248 result = dns_rdata_tostruct(&rdata, &soa, NULL); 3249 check_result(result, "dns_rdata_tostruct"); 3250 serial = soa.serial; 3251 dns_rdata_freestruct(&soa); 3252 if (!query->first_soa_rcvd) { 3253 query->first_soa_rcvd = ISC_TRUE; 3254 query->first_rr_serial = serial; 3255 debug("this is the first serial %u", 3256 serial); 3257 if (ixfr && isc_serial_ge(ixfr_serial, 3258 serial)) { 3259 debug("got up to date " 3260 "response"); 3261 goto doexit; 3262 } 3263 goto next_rdata; 3264 } 3265 if (axfr) { 3266 debug("doing axfr, got second SOA"); 3267 goto doexit; 3268 } 3269 if (!query->second_rr_rcvd) { 3270 if (query->first_rr_serial == serial) { 3271 debug("doing ixfr, got " 3272 "empty zone"); 3273 goto doexit; 3274 } 3275 debug("this is the second serial %u", 3276 serial); 3277 query->second_rr_rcvd = ISC_TRUE; 3278 query->second_rr_serial = serial; 3279 goto next_rdata; 3280 } 3281 /* 3282 * If we get to this point, we're doing an 3283 * IXFR and have to start really looking 3284 * at serial numbers. 3285 */ 3286 if (query->first_rr_serial == serial) { 3287 debug("got a match for ixfr"); 3288 if (!query->first_repeat_rcvd) { 3289 query->first_repeat_rcvd = 3290 ISC_TRUE; 3291 goto next_rdata; 3292 } 3293 debug("done with ixfr"); 3294 goto doexit; 3295 } 3296 debug("meaningless soa %u", serial); 3297 next_rdata: 3298 result = dns_rdataset_next(rdataset); 3299 } while (result == ISC_R_SUCCESS); 3300 } 3301 result = dns_message_nextname(msg, DNS_SECTION_ANSWER); 3302 } while (result == ISC_R_SUCCESS); 3303 launch_next_query(query, ISC_FALSE); 3304 return (ISC_FALSE); 3305 doexit: 3306 received(sevent->n, &sevent->address, query); 3307 return (ISC_TRUE); 3308 } 3309 3310 #ifdef ISC_PLATFORM_USESIT 3311 static void 3312 process_sit(dig_lookup_t *l, dns_message_t *msg, 3313 isc_buffer_t *optbuf, size_t optlen) 3314 { 3315 char bb[256]; 3316 isc_buffer_t hexbuf; 3317 size_t len; 3318 const unsigned char *sit; 3319 isc_result_t result; 3320 3321 if (l->sitvalue != NULL) { 3322 isc_buffer_init(&hexbuf, bb, sizeof(bb)); 3323 result = isc_hex_decodestring(l->sitvalue, &hexbuf); 3324 check_result(result, "isc_hex_decodestring"); 3325 sit = isc_buffer_base(&hexbuf); 3326 len = isc_buffer_usedlength(&hexbuf); 3327 } else { 3328 sit = cookie; 3329 len = sizeof(cookie); 3330 } 3331 3332 INSIST(msg->sitok == 0 && msg->sitbad == 0); 3333 if (optlen >= len && optlen >= 8U) { 3334 if (memcmp(isc_buffer_current(optbuf), sit, 8) == 0) { 3335 msg->sitok = 1; 3336 } else { 3337 printf(";; Warning: SIT client cookie mismatch\n"); 3338 msg->sitbad = 1; 3339 } 3340 } else { 3341 printf(";; Warning: SIT bad token (too short)\n"); 3342 msg->sitbad = 1; 3343 } 3344 isc_buffer_forward(optbuf, (unsigned int)optlen); 3345 } 3346 3347 static void 3348 process_opt(dig_lookup_t *l, dns_message_t *msg) { 3349 dns_rdata_t rdata; 3350 isc_result_t result; 3351 isc_buffer_t optbuf; 3352 isc_uint16_t optcode, optlen; 3353 dns_rdataset_t *opt = msg->opt; 3354 3355 result = dns_rdataset_first(opt); 3356 if (result == ISC_R_SUCCESS) { 3357 dns_rdata_init(&rdata); 3358 dns_rdataset_current(opt, &rdata); 3359 isc_buffer_init(&optbuf, rdata.data, rdata.length); 3360 isc_buffer_add(&optbuf, rdata.length); 3361 while (isc_buffer_remaininglength(&optbuf) >= 4) { 3362 optcode = isc_buffer_getuint16(&optbuf); 3363 optlen = isc_buffer_getuint16(&optbuf); 3364 switch (optcode) { 3365 case DNS_OPT_SIT: 3366 process_sit(l, msg, &optbuf, optlen); 3367 break; 3368 default: 3369 isc_buffer_forward(&optbuf, optlen); 3370 break; 3371 } 3372 } 3373 } 3374 } 3375 #endif 3376 3377 3378 /*% 3379 * Event handler for recv complete. Perform whatever actions are necessary, 3380 * based on the specifics of the user's request. 3381 */ 3382 static void 3383 recv_done(isc_task_t *task, isc_event_t *event) { 3384 isc_socketevent_t *sevent = NULL; 3385 dig_query_t *query = NULL; 3386 isc_buffer_t *b = NULL; 3387 dns_message_t *msg = NULL; 3388 #ifdef DIG_SIGCHASE 3389 dig_message_t *chase_msg = NULL; 3390 dig_message_t *chase_msg2 = NULL; 3391 #endif 3392 isc_result_t result; 3393 dig_lookup_t *n, *l; 3394 isc_boolean_t docancel = ISC_FALSE; 3395 isc_boolean_t match = ISC_TRUE; 3396 unsigned int parseflags; 3397 dns_messageid_t id; 3398 unsigned int msgflags; 3399 #ifdef DIG_SIGCHASE 3400 isc_result_t do_sigchase = ISC_FALSE; 3401 3402 dns_message_t *msg_temp = NULL; 3403 isc_region_t r; 3404 isc_buffer_t *buf = NULL; 3405 #endif 3406 3407 UNUSED(task); 3408 INSIST(!free_now); 3409 3410 debug("recv_done()"); 3411 3412 LOCK_LOOKUP; 3413 recvcount--; 3414 debug("recvcount=%d", recvcount); 3415 INSIST(recvcount >= 0); 3416 3417 query = event->ev_arg; 3418 TIME_NOW(&query->time_recv); 3419 debug("lookup=%p, query=%p", query->lookup, query); 3420 3421 l = query->lookup; 3422 3423 REQUIRE(event->ev_type == ISC_SOCKEVENT_RECVDONE); 3424 sevent = (isc_socketevent_t *)event; 3425 3426 b = ISC_LIST_HEAD(sevent->bufferlist); 3427 INSIST(b == &query->recvbuf); 3428 ISC_LIST_DEQUEUE(sevent->bufferlist, &query->recvbuf, link); 3429 3430 if ((l->tcp_mode) && (l->timer != NULL)) 3431 isc_timer_touch(l->timer); 3432 if ((!l->pending && !l->ns_search_only) || cancel_now) { 3433 debug("no longer pending. Got %s", 3434 isc_result_totext(sevent->result)); 3435 query->waiting_connect = ISC_FALSE; 3436 3437 isc_event_free(&event); 3438 clear_query(query); 3439 check_next_lookup(l); 3440 UNLOCK_LOOKUP; 3441 return; 3442 } 3443 3444 if (sevent->result != ISC_R_SUCCESS) { 3445 if (sevent->result == ISC_R_CANCELED) { 3446 debug("in recv cancel handler"); 3447 query->waiting_connect = ISC_FALSE; 3448 } else { 3449 printf(";; communications error: %s\n", 3450 isc_result_totext(sevent->result)); 3451 isc_socket_detach(&query->sock); 3452 sockcount--; 3453 debug("sockcount=%d", sockcount); 3454 INSIST(sockcount >= 0); 3455 } 3456 isc_event_free(&event); 3457 clear_query(query); 3458 check_next_lookup(l); 3459 UNLOCK_LOOKUP; 3460 return; 3461 } 3462 3463 if (!l->tcp_mode && 3464 !isc_sockaddr_compare(&sevent->address, &query->sockaddr, 3465 ISC_SOCKADDR_CMPADDR| 3466 ISC_SOCKADDR_CMPPORT| 3467 ISC_SOCKADDR_CMPSCOPE| 3468 ISC_SOCKADDR_CMPSCOPEZERO)) { 3469 char buf1[ISC_SOCKADDR_FORMATSIZE]; 3470 char buf2[ISC_SOCKADDR_FORMATSIZE]; 3471 isc_sockaddr_t any; 3472 3473 if (isc_sockaddr_pf(&query->sockaddr) == AF_INET) 3474 isc_sockaddr_any(&any); 3475 else 3476 isc_sockaddr_any6(&any); 3477 3478 /* 3479 * We don't expect a match when the packet is 3480 * sent to 0.0.0.0, :: or to a multicast addresses. 3481 * XXXMPA broadcast needs to be handled here as well. 3482 */ 3483 if ((!isc_sockaddr_eqaddr(&query->sockaddr, &any) && 3484 !isc_sockaddr_ismulticast(&query->sockaddr)) || 3485 isc_sockaddr_getport(&query->sockaddr) != 3486 isc_sockaddr_getport(&sevent->address)) { 3487 isc_sockaddr_format(&sevent->address, buf1, 3488 sizeof(buf1)); 3489 isc_sockaddr_format(&query->sockaddr, buf2, 3490 sizeof(buf2)); 3491 printf(";; reply from unexpected source: %s," 3492 " expected %s\n", buf1, buf2); 3493 match = ISC_FALSE; 3494 } 3495 } 3496 3497 result = dns_message_peekheader(b, &id, &msgflags); 3498 if (result != ISC_R_SUCCESS || l->sendmsg->id != id) { 3499 match = ISC_FALSE; 3500 if (l->tcp_mode) { 3501 isc_boolean_t fail = ISC_TRUE; 3502 if (result == ISC_R_SUCCESS) { 3503 if (!query->first_soa_rcvd || 3504 query->warn_id) 3505 printf(";; %s: ID mismatch: " 3506 "expected ID %u, got %u\n", 3507 query->first_soa_rcvd ? 3508 "WARNING" : "ERROR", 3509 l->sendmsg->id, id); 3510 if (query->first_soa_rcvd) 3511 fail = ISC_FALSE; 3512 query->warn_id = ISC_FALSE; 3513 } else 3514 printf(";; ERROR: short " 3515 "(< header size) message\n"); 3516 if (fail) { 3517 isc_event_free(&event); 3518 clear_query(query); 3519 check_next_lookup(l); 3520 UNLOCK_LOOKUP; 3521 return; 3522 } 3523 match = ISC_TRUE; 3524 } else if (result == ISC_R_SUCCESS) 3525 printf(";; Warning: ID mismatch: " 3526 "expected ID %u, got %u\n", l->sendmsg->id, id); 3527 else 3528 printf(";; Warning: short " 3529 "(< header size) message received\n"); 3530 } 3531 3532 if (result == ISC_R_SUCCESS && (msgflags & DNS_MESSAGEFLAG_QR) == 0) 3533 printf(";; Warning: query response not set\n"); 3534 3535 if (!match) 3536 goto udp_mismatch; 3537 3538 result = dns_message_create(mctx, DNS_MESSAGE_INTENTPARSE, &msg); 3539 check_result(result, "dns_message_create"); 3540 3541 if (key != NULL) { 3542 if (l->querysig == NULL) { 3543 debug("getting initial querysig"); 3544 result = dns_message_getquerytsig(l->sendmsg, mctx, 3545 &l->querysig); 3546 check_result(result, "dns_message_getquerytsig"); 3547 } 3548 result = dns_message_setquerytsig(msg, l->querysig); 3549 check_result(result, "dns_message_setquerytsig"); 3550 result = dns_message_settsigkey(msg, key); 3551 check_result(result, "dns_message_settsigkey"); 3552 msg->tsigctx = l->tsigctx; 3553 l->tsigctx = NULL; 3554 if (l->msgcounter != 0) 3555 msg->tcp_continuation = 1; 3556 l->msgcounter++; 3557 } 3558 3559 debug("before parse starts"); 3560 parseflags = DNS_MESSAGEPARSE_PRESERVEORDER; 3561 #ifdef DIG_SIGCHASE 3562 if (!l->sigchase) { 3563 do_sigchase = ISC_FALSE; 3564 } else { 3565 parseflags = 0; 3566 do_sigchase = ISC_TRUE; 3567 } 3568 #endif 3569 if (l->besteffort) { 3570 parseflags |= DNS_MESSAGEPARSE_BESTEFFORT; 3571 parseflags |= DNS_MESSAGEPARSE_IGNORETRUNCATION; 3572 } 3573 result = dns_message_parse(msg, b, parseflags); 3574 if (result == DNS_R_RECOVERABLE) { 3575 printf(";; Warning: Message parser reports malformed " 3576 "message packet.\n"); 3577 result = ISC_R_SUCCESS; 3578 } 3579 if (result != ISC_R_SUCCESS) { 3580 printf(";; Got bad packet: %s\n", isc_result_totext(result)); 3581 hex_dump(b); 3582 query->waiting_connect = ISC_FALSE; 3583 dns_message_destroy(&msg); 3584 isc_event_free(&event); 3585 clear_query(query); 3586 cancel_lookup(l); 3587 check_next_lookup(l); 3588 UNLOCK_LOOKUP; 3589 return; 3590 } 3591 if (msg->counts[DNS_SECTION_QUESTION] != 0) { 3592 match = ISC_TRUE; 3593 for (result = dns_message_firstname(msg, DNS_SECTION_QUESTION); 3594 result == ISC_R_SUCCESS && match; 3595 result = dns_message_nextname(msg, DNS_SECTION_QUESTION)) { 3596 dns_name_t *name = NULL; 3597 dns_rdataset_t *rdataset; 3598 3599 dns_message_currentname(msg, DNS_SECTION_QUESTION, 3600 &name); 3601 for (rdataset = ISC_LIST_HEAD(name->list); 3602 rdataset != NULL; 3603 rdataset = ISC_LIST_NEXT(rdataset, link)) { 3604 if (l->rdtype != rdataset->type || 3605 l->rdclass != rdataset->rdclass || 3606 !dns_name_equal(l->name, name)) { 3607 char namestr[DNS_NAME_FORMATSIZE]; 3608 char typebuf[DNS_RDATATYPE_FORMATSIZE]; 3609 char classbuf[DNS_RDATACLASS_FORMATSIZE]; 3610 dns_name_format(name, namestr, 3611 sizeof(namestr)); 3612 dns_rdatatype_format(rdataset->type, 3613 typebuf, 3614 sizeof(typebuf)); 3615 dns_rdataclass_format(rdataset->rdclass, 3616 classbuf, 3617 sizeof(classbuf)); 3618 printf(";; Question section mismatch: " 3619 "got %s/%s/%s\n", 3620 namestr, typebuf, classbuf); 3621 match = ISC_FALSE; 3622 } 3623 } 3624 } 3625 if (!match) { 3626 dns_message_destroy(&msg); 3627 if (l->tcp_mode) { 3628 isc_event_free(&event); 3629 clear_query(query); 3630 check_next_lookup(l); 3631 UNLOCK_LOOKUP; 3632 return; 3633 } else 3634 goto udp_mismatch; 3635 } 3636 } 3637 if ((msg->flags & DNS_MESSAGEFLAG_TC) != 0 && 3638 !l->ignore && !l->tcp_mode) { 3639 if (l->comments) 3640 printf(";; Truncated, retrying in TCP mode.\n"); 3641 n = requeue_lookup(l, ISC_TRUE); 3642 n->tcp_mode = ISC_TRUE; 3643 n->origin = query->lookup->origin; 3644 dns_message_destroy(&msg); 3645 isc_event_free(&event); 3646 clear_query(query); 3647 cancel_lookup(l); 3648 check_next_lookup(l); 3649 UNLOCK_LOOKUP; 3650 return; 3651 } 3652 if ((msg->rcode == dns_rcode_servfail && !l->servfail_stops) || 3653 (check_ra && (msg->flags & DNS_MESSAGEFLAG_RA) == 0 && l->recurse)) 3654 { 3655 dig_query_t *next = ISC_LIST_NEXT(query, link); 3656 if (l->current_query == query) 3657 l->current_query = NULL; 3658 if (next != NULL) { 3659 debug("sending query %p\n", next); 3660 if (l->tcp_mode) 3661 send_tcp_connect(next); 3662 else 3663 send_udp(next); 3664 } 3665 /* 3666 * If our query is at the head of the list and there 3667 * is no next, we're the only one left, so fall 3668 * through to print the message. 3669 */ 3670 if ((ISC_LIST_HEAD(l->q) != query) || 3671 (ISC_LIST_NEXT(query, link) != NULL)) { 3672 if (l->comments) 3673 printf(";; Got %s from %s, " 3674 "trying next server\n", 3675 msg->rcode == dns_rcode_servfail ? 3676 "SERVFAIL reply" : 3677 "recursion not available", 3678 query->servname); 3679 clear_query(query); 3680 check_next_lookup(l); 3681 dns_message_destroy(&msg); 3682 isc_event_free(&event); 3683 UNLOCK_LOOKUP; 3684 return; 3685 } 3686 } 3687 3688 if (key != NULL) { 3689 result = dns_tsig_verify(&query->recvbuf, msg, NULL, NULL); 3690 if (result != ISC_R_SUCCESS) { 3691 printf(";; Couldn't verify signature: %s\n", 3692 isc_result_totext(result)); 3693 validated = ISC_FALSE; 3694 } 3695 l->tsigctx = msg->tsigctx; 3696 msg->tsigctx = NULL; 3697 if (l->querysig != NULL) { 3698 debug("freeing querysig buffer %p", l->querysig); 3699 isc_buffer_free(&l->querysig); 3700 } 3701 result = dns_message_getquerytsig(msg, mctx, &l->querysig); 3702 check_result(result,"dns_message_getquerytsig"); 3703 } 3704 3705 extrabytes = isc_buffer_remaininglength(b); 3706 3707 debug("after parse"); 3708 if (l->doing_xfr && l->xfr_q == NULL) { 3709 l->xfr_q = query; 3710 /* 3711 * Once we are in the XFR message, increase 3712 * the timeout to much longer, so brief network 3713 * outages won't cause the XFR to abort 3714 */ 3715 if (timeout != INT_MAX && l->timer != NULL) { 3716 unsigned int local_timeout; 3717 3718 if (timeout == 0) { 3719 if (l->tcp_mode) 3720 local_timeout = TCP_TIMEOUT * 4; 3721 else 3722 local_timeout = UDP_TIMEOUT * 4; 3723 } else { 3724 if (timeout < (INT_MAX / 4)) 3725 local_timeout = timeout * 4; 3726 else 3727 local_timeout = INT_MAX; 3728 } 3729 debug("have local timeout of %d", local_timeout); 3730 isc_interval_set(&l->interval, local_timeout, 0); 3731 result = isc_timer_reset(l->timer, 3732 isc_timertype_once, 3733 NULL, 3734 &l->interval, 3735 ISC_FALSE); 3736 check_result(result, "isc_timer_reset"); 3737 } 3738 } 3739 3740 #ifdef ISC_PLATFORM_USESIT 3741 if (l->sitvalue != NULL) { 3742 if (msg->opt == NULL) 3743 printf(";; expected opt record in response\n"); 3744 else 3745 process_opt(l, msg); 3746 } else if (l->sit && msg->opt != NULL) 3747 process_opt(l, msg); 3748 #endif 3749 3750 if (!l->doing_xfr || l->xfr_q == query) { 3751 if (msg->rcode == dns_rcode_nxdomain && 3752 (l->origin != NULL || l->need_search)) { 3753 if (!next_origin(query->lookup) || showsearch) { 3754 printmessage(query, msg, ISC_TRUE); 3755 received(b->used, &sevent->address, query); 3756 } 3757 } else if (!l->trace && !l->ns_search_only) { 3758 #ifdef DIG_SIGCHASE 3759 if (!do_sigchase) 3760 #endif 3761 printmessage(query, msg, ISC_TRUE); 3762 } else if (l->trace) { 3763 int nl = 0; 3764 int count = msg->counts[DNS_SECTION_ANSWER]; 3765 3766 debug("in TRACE code"); 3767 if (!l->ns_search_only) 3768 printmessage(query, msg, ISC_TRUE); 3769 3770 l->rdtype = l->qrdtype; 3771 if (l->trace_root || (l->ns_search_only && count > 0)) { 3772 if (!l->trace_root) 3773 l->rdtype = dns_rdatatype_soa; 3774 nl = followup_lookup(msg, query, 3775 DNS_SECTION_ANSWER); 3776 l->trace_root = ISC_FALSE; 3777 } else if (count == 0) 3778 nl = followup_lookup(msg, query, 3779 DNS_SECTION_AUTHORITY); 3780 if (nl == 0) 3781 docancel = ISC_TRUE; 3782 } else { 3783 debug("in NSSEARCH code"); 3784 3785 if (l->trace_root) { 3786 /* 3787 * This is the initial NS query. 3788 */ 3789 int nl; 3790 3791 l->rdtype = dns_rdatatype_soa; 3792 nl = followup_lookup(msg, query, 3793 DNS_SECTION_ANSWER); 3794 if (nl == 0) 3795 docancel = ISC_TRUE; 3796 l->trace_root = ISC_FALSE; 3797 usesearch = ISC_FALSE; 3798 } else 3799 #ifdef DIG_SIGCHASE 3800 if (!do_sigchase) 3801 #endif 3802 printmessage(query, msg, ISC_TRUE); 3803 } 3804 #ifdef DIG_SIGCHASE 3805 if (do_sigchase) { 3806 chase_msg = isc_mem_allocate(mctx, 3807 sizeof(dig_message_t)); 3808 if (chase_msg == NULL) { 3809 fatal("Memory allocation failure in %s:%d", 3810 __FILE__, __LINE__); 3811 } 3812 ISC_LIST_INITANDAPPEND(chase_message_list, chase_msg, 3813 link); 3814 if (dns_message_create(mctx, DNS_MESSAGE_INTENTPARSE, 3815 &msg_temp) != ISC_R_SUCCESS) { 3816 fatal("dns_message_create in %s:%d", 3817 __FILE__, __LINE__); 3818 } 3819 3820 isc_buffer_usedregion(b, &r); 3821 result = isc_buffer_allocate(mctx, &buf, r.length); 3822 3823 check_result(result, "isc_buffer_allocate"); 3824 result = isc_buffer_copyregion(buf, &r); 3825 check_result(result, "isc_buffer_copyregion"); 3826 3827 result = dns_message_parse(msg_temp, buf, 0); 3828 3829 isc_buffer_free(&buf); 3830 chase_msg->msg = msg_temp; 3831 3832 chase_msg2 = isc_mem_allocate(mctx, 3833 sizeof(dig_message_t)); 3834 if (chase_msg2 == NULL) { 3835 fatal("Memory allocation failure in %s:%d", 3836 __FILE__, __LINE__); 3837 } 3838 ISC_LIST_INITANDAPPEND(chase_message_list2, chase_msg2, 3839 link); 3840 chase_msg2->msg = msg; 3841 } 3842 #endif 3843 } 3844 3845 #ifdef DIG_SIGCHASE 3846 if (l->sigchase && ISC_LIST_EMPTY(lookup_list)) { 3847 sigchase(msg_temp); 3848 } 3849 #endif 3850 3851 if (l->pending) 3852 debug("still pending."); 3853 if (l->doing_xfr) { 3854 if (query != l->xfr_q) { 3855 dns_message_destroy(&msg); 3856 isc_event_free(&event); 3857 query->waiting_connect = ISC_FALSE; 3858 UNLOCK_LOOKUP; 3859 return; 3860 } 3861 if (!docancel) 3862 docancel = check_for_more_data(query, msg, sevent); 3863 if (docancel) { 3864 dns_message_destroy(&msg); 3865 clear_query(query); 3866 cancel_lookup(l); 3867 check_next_lookup(l); 3868 } 3869 } else { 3870 3871 if (msg->rcode == dns_rcode_noerror || l->origin == NULL) { 3872 3873 #ifdef DIG_SIGCHASE 3874 if (!l->sigchase) 3875 #endif 3876 received(b->used, &sevent->address, query); 3877 } 3878 3879 if (!query->lookup->ns_search_only) 3880 query->lookup->pending = ISC_FALSE; 3881 if (!query->lookup->ns_search_only || 3882 query->lookup->trace_root || docancel) { 3883 #ifdef DIG_SIGCHASE 3884 if (!do_sigchase) 3885 #endif 3886 dns_message_destroy(&msg); 3887 3888 cancel_lookup(l); 3889 } 3890 clear_query(query); 3891 check_next_lookup(l); 3892 } 3893 if (msg != NULL) { 3894 #ifdef DIG_SIGCHASE 3895 if (do_sigchase) 3896 msg = NULL; 3897 else 3898 #endif 3899 dns_message_destroy(&msg); 3900 } 3901 isc_event_free(&event); 3902 UNLOCK_LOOKUP; 3903 return; 3904 3905 udp_mismatch: 3906 isc_buffer_invalidate(&query->recvbuf); 3907 isc_buffer_init(&query->recvbuf, query->recvspace, COMMSIZE); 3908 ISC_LIST_ENQUEUE(query->recvlist, &query->recvbuf, link); 3909 result = isc_socket_recvv(query->sock, &query->recvlist, 1, 3910 global_task, recv_done, query); 3911 check_result(result, "isc_socket_recvv"); 3912 recvcount++; 3913 isc_event_free(&event); 3914 UNLOCK_LOOKUP; 3915 return; 3916 } 3917 3918 /*% 3919 * Turn a name into an address, using system-supplied routines. This is 3920 * used in looking up server names, etc... and needs to use system-supplied 3921 * routines, since they may be using a non-DNS system for these lookups. 3922 */ 3923 isc_result_t 3924 get_address(char *host, in_port_t myport, isc_sockaddr_t *sockaddr) { 3925 int count; 3926 isc_result_t result; 3927 3928 isc_app_block(); 3929 result = bind9_getaddresses(host, myport, sockaddr, 1, &count); 3930 isc_app_unblock(); 3931 if (result != ISC_R_SUCCESS) 3932 return (result); 3933 3934 INSIST(count == 1); 3935 3936 return (ISC_R_SUCCESS); 3937 } 3938 3939 int 3940 getaddresses(dig_lookup_t *lookup, const char *host, isc_result_t *resultp) { 3941 isc_result_t result; 3942 isc_sockaddr_t sockaddrs[DIG_MAX_ADDRESSES]; 3943 isc_netaddr_t netaddr; 3944 int count, i; 3945 dig_server_t *srv; 3946 char tmp[ISC_NETADDR_FORMATSIZE]; 3947 3948 result = bind9_getaddresses(host, 0, sockaddrs, 3949 DIG_MAX_ADDRESSES, &count); 3950 if (resultp != NULL) 3951 *resultp = result; 3952 if (result != ISC_R_SUCCESS) { 3953 if (resultp == NULL) 3954 fatal("couldn't get address for '%s': %s", 3955 host, isc_result_totext(result)); 3956 return 0; 3957 } 3958 3959 for (i = 0; i < count; i++) { 3960 isc_netaddr_fromsockaddr(&netaddr, &sockaddrs[i]); 3961 isc_netaddr_format(&netaddr, tmp, sizeof(tmp)); 3962 srv = make_server(tmp, host); 3963 ISC_LIST_APPEND(lookup->my_server_list, srv, link); 3964 } 3965 3966 return count; 3967 } 3968 3969 /*% 3970 * Initiate either a TCP or UDP lookup 3971 */ 3972 void 3973 do_lookup(dig_lookup_t *lookup) { 3974 dig_query_t *query; 3975 3976 REQUIRE(lookup != NULL); 3977 3978 debug("do_lookup()"); 3979 lookup->pending = ISC_TRUE; 3980 query = ISC_LIST_HEAD(lookup->q); 3981 if (query != NULL) { 3982 if (lookup->tcp_mode) 3983 send_tcp_connect(query); 3984 else 3985 send_udp(query); 3986 } 3987 } 3988 3989 /*% 3990 * Start everything in action upon task startup. 3991 */ 3992 void 3993 onrun_callback(isc_task_t *task, isc_event_t *event) { 3994 UNUSED(task); 3995 3996 isc_event_free(&event); 3997 LOCK_LOOKUP; 3998 start_lookup(); 3999 UNLOCK_LOOKUP; 4000 } 4001 4002 /*% 4003 * Make everything on the lookup queue go away. Mainly used by the 4004 * SIGINT handler. 4005 */ 4006 void 4007 cancel_all(void) { 4008 dig_lookup_t *l, *n; 4009 dig_query_t *q, *nq; 4010 4011 debug("cancel_all()"); 4012 4013 LOCK_LOOKUP; 4014 if (free_now) { 4015 UNLOCK_LOOKUP; 4016 return; 4017 } 4018 cancel_now = ISC_TRUE; 4019 if (current_lookup != NULL) { 4020 if (current_lookup->timer != NULL) 4021 isc_timer_detach(¤t_lookup->timer); 4022 for (q = ISC_LIST_HEAD(current_lookup->q); 4023 q != NULL; 4024 q = nq) 4025 { 4026 nq = ISC_LIST_NEXT(q, link); 4027 debug("canceling pending query %p, belonging to %p", 4028 q, current_lookup); 4029 if (q->sock != NULL) 4030 isc_socket_cancel(q->sock, NULL, 4031 ISC_SOCKCANCEL_ALL); 4032 else 4033 clear_query(q); 4034 } 4035 for (q = ISC_LIST_HEAD(current_lookup->connecting); 4036 q != NULL; 4037 q = nq) 4038 { 4039 nq = ISC_LIST_NEXT(q, clink); 4040 debug("canceling connecting query %p, belonging to %p", 4041 q, current_lookup); 4042 if (q->sock != NULL) 4043 isc_socket_cancel(q->sock, NULL, 4044 ISC_SOCKCANCEL_ALL); 4045 else 4046 clear_query(q); 4047 } 4048 } 4049 l = ISC_LIST_HEAD(lookup_list); 4050 while (l != NULL) { 4051 n = ISC_LIST_NEXT(l, link); 4052 ISC_LIST_DEQUEUE(lookup_list, l, link); 4053 try_clear_lookup(l); 4054 l = n; 4055 } 4056 UNLOCK_LOOKUP; 4057 } 4058 4059 /*% 4060 * Destroy all of the libs we are using, and get everything ready for a 4061 * clean shutdown. 4062 */ 4063 void 4064 destroy_libs(void) { 4065 #ifdef DIG_SIGCHASE 4066 void * ptr; 4067 dig_message_t *chase_msg; 4068 #endif 4069 #ifdef WITH_IDN 4070 isc_result_t result; 4071 #endif 4072 4073 if (keep != NULL) 4074 isc_socket_detach(&keep); 4075 debug("destroy_libs()"); 4076 if (global_task != NULL) { 4077 debug("freeing task"); 4078 isc_task_detach(&global_task); 4079 } 4080 /* 4081 * The taskmgr_destroy() call blocks until all events are cleared 4082 * from the task. 4083 */ 4084 if (taskmgr != NULL) { 4085 debug("freeing taskmgr"); 4086 isc_taskmgr_destroy(&taskmgr); 4087 } 4088 LOCK_LOOKUP; 4089 REQUIRE(sockcount == 0); 4090 REQUIRE(recvcount == 0); 4091 REQUIRE(sendcount == 0); 4092 4093 INSIST(ISC_LIST_HEAD(lookup_list) == NULL); 4094 INSIST(current_lookup == NULL); 4095 INSIST(!free_now); 4096 4097 free_now = ISC_TRUE; 4098 4099 lwres_conf_clear(lwctx); 4100 lwres_context_destroy(&lwctx); 4101 4102 flush_server_list(); 4103 4104 clear_searchlist(); 4105 4106 #ifdef WITH_IDN 4107 result = dns_name_settotextfilter(NULL); 4108 check_result(result, "dns_name_settotextfilter"); 4109 #endif 4110 dns_name_destroy(); 4111 4112 if (commctx != NULL) { 4113 debug("freeing commctx"); 4114 isc_mempool_destroy(&commctx); 4115 } 4116 if (socketmgr != NULL) { 4117 debug("freeing socketmgr"); 4118 isc_socketmgr_destroy(&socketmgr); 4119 } 4120 if (timermgr != NULL) { 4121 debug("freeing timermgr"); 4122 isc_timermgr_destroy(&timermgr); 4123 } 4124 if (key != NULL) { 4125 debug("freeing key %p", key); 4126 dns_tsigkey_detach(&key); 4127 } 4128 if (namebuf != NULL) 4129 isc_buffer_free(&namebuf); 4130 4131 if (is_dst_up) { 4132 debug("destroy DST lib"); 4133 dst_lib_destroy(); 4134 is_dst_up = ISC_FALSE; 4135 } 4136 if (entp != NULL) { 4137 debug("detach from entropy"); 4138 isc_entropy_detach(&entp); 4139 } 4140 4141 UNLOCK_LOOKUP; 4142 DESTROYLOCK(&lookup_lock); 4143 #ifdef DIG_SIGCHASE 4144 4145 debug("Destroy the messages kept for sigchase"); 4146 /* Destroy the messages kept for sigchase */ 4147 chase_msg = ISC_LIST_HEAD(chase_message_list); 4148 4149 while (chase_msg != NULL) { 4150 INSIST(chase_msg->msg != NULL); 4151 dns_message_destroy(&(chase_msg->msg)); 4152 ptr = chase_msg; 4153 chase_msg = ISC_LIST_NEXT(chase_msg, link); 4154 isc_mem_free(mctx, ptr); 4155 } 4156 4157 chase_msg = ISC_LIST_HEAD(chase_message_list2); 4158 4159 while (chase_msg != NULL) { 4160 INSIST(chase_msg->msg != NULL); 4161 dns_message_destroy(&(chase_msg->msg)); 4162 ptr = chase_msg; 4163 chase_msg = ISC_LIST_NEXT(chase_msg, link); 4164 isc_mem_free(mctx, ptr); 4165 } 4166 if (dns_name_dynamic(&chase_name)) 4167 free_name(&chase_name, mctx); 4168 #if DIG_SIGCHASE_TD 4169 if (dns_name_dynamic(&chase_current_name)) 4170 free_name(&chase_current_name, mctx); 4171 if (dns_name_dynamic(&chase_authority_name)) 4172 free_name(&chase_authority_name, mctx); 4173 #endif 4174 #if DIG_SIGCHASE_BU 4175 if (dns_name_dynamic(&chase_signame)) 4176 free_name(&chase_signame, mctx); 4177 #endif 4178 4179 #endif 4180 debug("Removing log context"); 4181 isc_log_destroy(&lctx); 4182 4183 debug("Destroy memory"); 4184 if (memdebugging != 0) 4185 isc_mem_stats(mctx, stderr); 4186 if (mctx != NULL) 4187 isc_mem_destroy(&mctx); 4188 } 4189 4190 #ifdef WITH_IDN 4191 static void 4192 initialize_idn(void) { 4193 idn_result_t r; 4194 isc_result_t result; 4195 4196 #ifdef HAVE_SETLOCALE 4197 /* Set locale */ 4198 (void)setlocale(LC_ALL, ""); 4199 #endif 4200 /* Create configuration context. */ 4201 r = idn_nameinit(1); 4202 if (r != idn_success) 4203 fatal("idn api initialization failed: %s", 4204 idn_result_tostring(r)); 4205 4206 /* Set domain name -> text post-conversion filter. */ 4207 result = dns_name_settotextfilter(output_filter); 4208 check_result(result, "dns_name_settotextfilter"); 4209 } 4210 4211 static isc_result_t 4212 output_filter(isc_buffer_t *buffer, unsigned int used_org, 4213 isc_boolean_t absolute) 4214 { 4215 char tmp1[MAXDLEN], tmp2[MAXDLEN]; 4216 size_t fromlen, tolen; 4217 isc_boolean_t end_with_dot; 4218 4219 /* 4220 * Copy contents of 'buffer' to 'tmp1', supply trailing dot 4221 * if 'absolute' is true, and terminate with NUL. 4222 */ 4223 fromlen = isc_buffer_usedlength(buffer) - used_org; 4224 if (fromlen >= MAXDLEN) 4225 return (ISC_R_SUCCESS); 4226 memmove(tmp1, (char *)isc_buffer_base(buffer) + used_org, fromlen); 4227 end_with_dot = (tmp1[fromlen - 1] == '.') ? ISC_TRUE : ISC_FALSE; 4228 if (absolute && !end_with_dot) { 4229 fromlen++; 4230 if (fromlen >= MAXDLEN) 4231 return (ISC_R_SUCCESS); 4232 tmp1[fromlen - 1] = '.'; 4233 } 4234 tmp1[fromlen] = '\0'; 4235 4236 /* 4237 * Convert contents of 'tmp1' to local encoding. 4238 */ 4239 if (idn_decodename(IDN_DECODE_APP, tmp1, tmp2, MAXDLEN) != idn_success) 4240 return (ISC_R_SUCCESS); 4241 strcpy(tmp1, tmp2); 4242 4243 /* 4244 * Copy the converted contents in 'tmp1' back to 'buffer'. 4245 * If we have appended trailing dot, remove it. 4246 */ 4247 tolen = strlen(tmp1); 4248 if (absolute && !end_with_dot && tmp1[tolen - 1] == '.') 4249 tolen--; 4250 4251 if (isc_buffer_length(buffer) < used_org + tolen) 4252 return (ISC_R_NOSPACE); 4253 4254 isc_buffer_subtract(buffer, isc_buffer_usedlength(buffer) - used_org); 4255 memmove(isc_buffer_used(buffer), tmp1, tolen); 4256 isc_buffer_add(buffer, (unsigned int)tolen); 4257 4258 return (ISC_R_SUCCESS); 4259 } 4260 4261 static idn_result_t 4262 append_textname(char *name, const char *origin, size_t namesize) { 4263 size_t namelen = strlen(name); 4264 size_t originlen = strlen(origin); 4265 4266 /* Already absolute? */ 4267 if (namelen > 0 && name[namelen - 1] == '.') 4268 return idn_success; 4269 4270 /* Append dot and origin */ 4271 4272 if (namelen + 1 + originlen >= namesize) 4273 return idn_buffer_overflow; 4274 4275 if (*origin != '.') 4276 name[namelen++] = '.'; 4277 (void)strcpy(name + namelen, origin); 4278 return idn_success; 4279 } 4280 4281 static void 4282 idn_check_result(idn_result_t r, const char *msg) { 4283 if (r != idn_success) { 4284 exitcode = 1; 4285 fatal("%s: %s", msg, idn_result_tostring(r)); 4286 } 4287 } 4288 #endif /* WITH_IDN */ 4289 4290 #ifdef DIG_SIGCHASE 4291 void 4292 print_type(dns_rdatatype_t type) 4293 { 4294 isc_buffer_t * b = NULL; 4295 isc_result_t result; 4296 isc_region_t r; 4297 4298 result = isc_buffer_allocate(mctx, &b, 4000); 4299 check_result(result, "isc_buffer_allocate"); 4300 4301 result = dns_rdatatype_totext(type, b); 4302 check_result(result, "print_type"); 4303 4304 isc_buffer_usedregion(b, &r); 4305 r.base[r.length] = '\0'; 4306 4307 printf("%s", r.base); 4308 4309 isc_buffer_free(&b); 4310 } 4311 4312 void 4313 dump_database_section(dns_message_t *msg, int section) 4314 { 4315 dns_name_t *msg_name=NULL; 4316 4317 dns_rdataset_t *rdataset; 4318 4319 do { 4320 dns_message_currentname(msg, section, &msg_name); 4321 4322 for (rdataset = ISC_LIST_HEAD(msg_name->list); rdataset != NULL; 4323 rdataset = ISC_LIST_NEXT(rdataset, link)) { 4324 dns_name_print(msg_name, stdout); 4325 printf("\n"); 4326 print_rdataset(msg_name, rdataset, mctx); 4327 printf("end\n"); 4328 } 4329 msg_name = NULL; 4330 } while (dns_message_nextname(msg, section) == ISC_R_SUCCESS); 4331 } 4332 4333 void 4334 dump_database(void) { 4335 dig_message_t * msg; 4336 4337 for (msg = ISC_LIST_HEAD(chase_message_list); msg != NULL; 4338 msg = ISC_LIST_NEXT(msg, link)) { 4339 if (dns_message_firstname(msg->msg, DNS_SECTION_ANSWER) 4340 == ISC_R_SUCCESS) 4341 dump_database_section(msg->msg, DNS_SECTION_ANSWER); 4342 4343 if (dns_message_firstname(msg->msg, DNS_SECTION_AUTHORITY) 4344 == ISC_R_SUCCESS) 4345 dump_database_section(msg->msg, DNS_SECTION_AUTHORITY); 4346 4347 if (dns_message_firstname(msg->msg, DNS_SECTION_ADDITIONAL) 4348 == ISC_R_SUCCESS) 4349 dump_database_section(msg->msg, DNS_SECTION_ADDITIONAL); 4350 } 4351 } 4352 4353 4354 dns_rdataset_t * 4355 search_type(dns_name_t *name, dns_rdatatype_t type, dns_rdatatype_t covers) { 4356 dns_rdataset_t *rdataset; 4357 dns_rdata_sig_t siginfo; 4358 dns_rdata_t sigrdata = DNS_RDATA_INIT; 4359 isc_result_t result; 4360 4361 for (rdataset = ISC_LIST_HEAD(name->list); rdataset != NULL; 4362 rdataset = ISC_LIST_NEXT(rdataset, link)) { 4363 if (type == dns_rdatatype_any) { 4364 if (rdataset->type != dns_rdatatype_rrsig) 4365 return (rdataset); 4366 } else if ((type == dns_rdatatype_rrsig) && 4367 (rdataset->type == dns_rdatatype_rrsig)) { 4368 result = dns_rdataset_first(rdataset); 4369 check_result(result, "empty rdataset"); 4370 dns_rdataset_current(rdataset, &sigrdata); 4371 result = dns_rdata_tostruct(&sigrdata, &siginfo, NULL); 4372 check_result(result, "sigrdata tostruct siginfo"); 4373 4374 if ((siginfo.covered == covers) || 4375 (covers == dns_rdatatype_any)) { 4376 dns_rdata_reset(&sigrdata); 4377 dns_rdata_freestruct(&siginfo); 4378 return (rdataset); 4379 } 4380 dns_rdata_reset(&sigrdata); 4381 dns_rdata_freestruct(&siginfo); 4382 } else if (rdataset->type == type) 4383 return (rdataset); 4384 } 4385 return (NULL); 4386 } 4387 4388 dns_rdataset_t * 4389 chase_scanname_section(dns_message_t *msg, dns_name_t *name, 4390 dns_rdatatype_t type, dns_rdatatype_t covers, 4391 int section) 4392 { 4393 dns_rdataset_t *rdataset; 4394 dns_name_t *msg_name = NULL; 4395 4396 if (msg->counts[section] == 0) 4397 return (NULL); 4398 4399 do { 4400 dns_message_currentname(msg, section, &msg_name); 4401 if (dns_name_compare(msg_name, name) == 0) { 4402 rdataset = search_type(msg_name, type, covers); 4403 if (rdataset != NULL) 4404 return (rdataset); 4405 } 4406 msg_name = NULL; 4407 } while (dns_message_nextname(msg, section) == ISC_R_SUCCESS); 4408 4409 return (NULL); 4410 } 4411 4412 4413 dns_rdataset_t * 4414 chase_scanname(dns_name_t *name, dns_rdatatype_t type, dns_rdatatype_t covers) 4415 { 4416 dns_rdataset_t *rdataset = NULL; 4417 dig_message_t * msg; 4418 4419 for (msg = ISC_LIST_HEAD(chase_message_list2); msg != NULL; 4420 msg = ISC_LIST_NEXT(msg, link)) { 4421 if (dns_message_firstname(msg->msg, DNS_SECTION_ANSWER) 4422 == ISC_R_SUCCESS) 4423 rdataset = chase_scanname_section(msg->msg, name, 4424 type, covers, 4425 DNS_SECTION_ANSWER); 4426 if (rdataset != NULL) 4427 return (rdataset); 4428 if (dns_message_firstname(msg->msg, DNS_SECTION_AUTHORITY) 4429 == ISC_R_SUCCESS) 4430 rdataset = 4431 chase_scanname_section(msg->msg, name, 4432 type, covers, 4433 DNS_SECTION_AUTHORITY); 4434 if (rdataset != NULL) 4435 return (rdataset); 4436 if (dns_message_firstname(msg->msg, DNS_SECTION_ADDITIONAL) 4437 == ISC_R_SUCCESS) 4438 rdataset = 4439 chase_scanname_section(msg->msg, name, type, 4440 covers, 4441 DNS_SECTION_ADDITIONAL); 4442 if (rdataset != NULL) 4443 return (rdataset); 4444 } 4445 4446 return (NULL); 4447 } 4448 4449 dns_rdataset_t * 4450 sigchase_scanname(dns_rdatatype_t type, dns_rdatatype_t covers, 4451 isc_boolean_t * lookedup, dns_name_t *rdata_name) 4452 { 4453 dig_lookup_t *lookup; 4454 isc_buffer_t *b = NULL; 4455 isc_region_t r; 4456 isc_result_t result; 4457 dns_rdataset_t * temp; 4458 dns_rdatatype_t querytype; 4459 4460 temp = chase_scanname(rdata_name, type, covers); 4461 if (temp != NULL) 4462 return (temp); 4463 4464 if (*lookedup == ISC_TRUE) 4465 return (NULL); 4466 4467 lookup = clone_lookup(current_lookup, ISC_TRUE); 4468 lookup->trace_root = ISC_FALSE; 4469 lookup->new_search = ISC_TRUE; 4470 4471 result = isc_buffer_allocate(mctx, &b, BUFSIZE); 4472 check_result(result, "isc_buffer_allocate"); 4473 result = dns_name_totext(rdata_name, ISC_FALSE, b); 4474 check_result(result, "dns_name_totext"); 4475 isc_buffer_usedregion(b, &r); 4476 r.base[r.length] = '\0'; 4477 strlcpy(lookup->textname, (char*)r.base, sizeof(lookup->textname)); 4478 isc_buffer_free(&b); 4479 4480 if (type == dns_rdatatype_rrsig) 4481 querytype = covers; 4482 else 4483 querytype = type; 4484 4485 if (querytype == 0 || querytype == 255) { 4486 printf("Error in the queried type: %d\n", querytype); 4487 return (NULL); 4488 } 4489 4490 lookup->rdtype = querytype; 4491 lookup->rdtypeset = ISC_TRUE; 4492 lookup->qrdtype = querytype; 4493 *lookedup = ISC_TRUE; 4494 4495 ISC_LIST_APPEND(lookup_list, lookup, link); 4496 printf("\n\nLaunch a query to find a RRset of type "); 4497 print_type(type); 4498 printf(" for zone: %s\n", lookup->textname); 4499 return (NULL); 4500 } 4501 4502 isc_result_t 4503 insert_trustedkey(void *arg, dns_name_t *name, dns_rdataset_t *rdataset) 4504 { 4505 isc_result_t result; 4506 dst_key_t *key; 4507 4508 UNUSED(arg); 4509 4510 if (rdataset == NULL || rdataset->type != dns_rdatatype_dnskey) 4511 return (ISC_R_SUCCESS); 4512 4513 for (result = dns_rdataset_first(rdataset); 4514 result == ISC_R_SUCCESS; 4515 result = dns_rdataset_next(rdataset)) { 4516 dns_rdata_t rdata = DNS_RDATA_INIT; 4517 isc_buffer_t b; 4518 4519 dns_rdataset_current(rdataset, &rdata); 4520 isc_buffer_init(&b, rdata.data, rdata.length); 4521 isc_buffer_add(&b, rdata.length); 4522 if (tk_list.nb_tk >= MAX_TRUSTED_KEY) 4523 return (ISC_R_SUCCESS); 4524 key = NULL; 4525 result = dst_key_fromdns(name, rdata.rdclass, &b, mctx, &key); 4526 if (result != ISC_R_SUCCESS) 4527 continue; 4528 tk_list.key[tk_list.nb_tk++] = key; 4529 } 4530 return (ISC_R_SUCCESS); 4531 } 4532 4533 void 4534 clean_trustedkey() 4535 { 4536 int i = 0; 4537 4538 for (i= 0; i < MAX_TRUSTED_KEY; i++) { 4539 if (tk_list.key[i] != NULL) { 4540 dst_key_free(&tk_list.key[i]); 4541 tk_list.key[i] = NULL; 4542 } else 4543 break; 4544 } 4545 tk_list.nb_tk = 0; 4546 return; 4547 } 4548 4549 char alphnum[] = 4550 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; 4551 4552 isc_result_t 4553 removetmpkey(isc_mem_t *mctx, const char *file) 4554 { 4555 char *tempnamekey = NULL; 4556 int tempnamekeylen; 4557 isc_result_t result; 4558 4559 tempnamekeylen = strlen(file)+10; 4560 4561 tempnamekey = isc_mem_allocate(mctx, tempnamekeylen); 4562 if (tempnamekey == NULL) 4563 return (ISC_R_NOMEMORY); 4564 4565 memset(tempnamekey, 0, tempnamekeylen); 4566 4567 strcat(tempnamekey, file); 4568 strcat(tempnamekey,".key"); 4569 isc_file_remove(tempnamekey); 4570 4571 result = isc_file_remove(tempnamekey); 4572 isc_mem_free(mctx, tempnamekey); 4573 return (result); 4574 } 4575 4576 isc_result_t 4577 get_trusted_key(isc_mem_t *mctx) 4578 { 4579 isc_result_t result; 4580 const char *filename = NULL; 4581 dns_rdatacallbacks_t callbacks; 4582 4583 result = isc_file_exists(trustedkey); 4584 if (result != ISC_TRUE) { 4585 result = isc_file_exists("/etc/trusted-key.key"); 4586 if (result != ISC_TRUE) { 4587 result = isc_file_exists("./trusted-key.key"); 4588 if (result != ISC_TRUE) 4589 return (ISC_R_FAILURE); 4590 else 4591 filename = "./trusted-key.key"; 4592 } else 4593 filename = "/etc/trusted-key.key"; 4594 } else 4595 filename = trustedkey; 4596 4597 if (filename == NULL) { 4598 printf("No trusted key\n"); 4599 return (ISC_R_FAILURE); 4600 } 4601 4602 dns_rdatacallbacks_init_stdio(&callbacks); 4603 callbacks.add = insert_trustedkey; 4604 return (dns_master_loadfile(filename, dns_rootname, dns_rootname, 4605 current_lookup->rdclass, DNS_MASTER_NOTTL, 4606 &callbacks, mctx)); 4607 } 4608 4609 4610 static void 4611 nameFromString(const char *str, dns_name_t *p_ret) { 4612 size_t len = strlen(str); 4613 isc_result_t result; 4614 isc_buffer_t buffer; 4615 dns_fixedname_t fixedname; 4616 4617 REQUIRE(p_ret != NULL); 4618 REQUIRE(str != NULL); 4619 4620 isc_buffer_constinit(&buffer, str, len); 4621 isc_buffer_add(&buffer, len); 4622 4623 dns_fixedname_init(&fixedname); 4624 result = dns_name_fromtext(dns_fixedname_name(&fixedname), &buffer, 4625 dns_rootname, DNS_NAME_DOWNCASE, NULL); 4626 check_result(result, "nameFromString"); 4627 4628 if (dns_name_dynamic(p_ret)) 4629 free_name(p_ret, mctx); 4630 4631 result = dns_name_dup(dns_fixedname_name(&fixedname), mctx, p_ret); 4632 check_result(result, "nameFromString"); 4633 } 4634 4635 4636 #if DIG_SIGCHASE_TD 4637 isc_result_t 4638 prepare_lookup(dns_name_t *name) 4639 { 4640 isc_result_t result; 4641 dig_lookup_t *lookup = NULL; 4642 dig_server_t *s; 4643 void *ptr; 4644 4645 lookup = clone_lookup(current_lookup, ISC_TRUE); 4646 lookup->trace_root = ISC_FALSE; 4647 lookup->new_search = ISC_TRUE; 4648 lookup->trace_root_sigchase = ISC_FALSE; 4649 4650 strlcpy(lookup->textname, lookup->textnamesigchase, MXNAME); 4651 4652 lookup->rdtype = lookup->rdtype_sigchase; 4653 lookup->rdtypeset = ISC_TRUE; 4654 lookup->qrdtype = lookup->qrdtype_sigchase; 4655 4656 s = ISC_LIST_HEAD(lookup->my_server_list); 4657 while (s != NULL) { 4658 debug("freeing server %p belonging to %p", 4659 s, lookup); 4660 ptr = s; 4661 s = ISC_LIST_NEXT(s, link); 4662 ISC_LIST_DEQUEUE(lookup->my_server_list, 4663 (dig_server_t *)ptr, link); 4664 isc_mem_free(mctx, ptr); 4665 } 4666 4667 4668 for (result = dns_rdataset_first(chase_nsrdataset); 4669 result == ISC_R_SUCCESS; 4670 result = dns_rdataset_next(chase_nsrdataset)) { 4671 char namestr[DNS_NAME_FORMATSIZE]; 4672 dns_rdata_ns_t ns; 4673 dns_rdata_t rdata = DNS_RDATA_INIT; 4674 dig_server_t * srv = NULL; 4675 #define __FOLLOW_GLUE__ 4676 #ifdef __FOLLOW_GLUE__ 4677 isc_buffer_t *b = NULL; 4678 isc_result_t result; 4679 isc_region_t r; 4680 dns_rdataset_t *rdataset = NULL; 4681 isc_boolean_t true = ISC_TRUE; 4682 #endif 4683 4684 memset(namestr, 0, DNS_NAME_FORMATSIZE); 4685 4686 dns_rdataset_current(chase_nsrdataset, &rdata); 4687 4688 result = dns_rdata_tostruct(&rdata, &ns, NULL); 4689 check_result(result, "dns_rdata_tostruct"); 4690 4691 #ifdef __FOLLOW_GLUE__ 4692 4693 result = advanced_rrsearch(&rdataset, &ns.name, 4694 dns_rdatatype_aaaa, 4695 dns_rdatatype_any, &true); 4696 if (result == ISC_R_SUCCESS) { 4697 for (result = dns_rdataset_first(rdataset); 4698 result == ISC_R_SUCCESS; 4699 result = dns_rdataset_next(rdataset)) { 4700 dns_rdata_t aaaa = DNS_RDATA_INIT; 4701 dns_rdataset_current(rdataset, &aaaa); 4702 4703 result = isc_buffer_allocate(mctx, &b, 80); 4704 check_result(result, "isc_buffer_allocate"); 4705 4706 dns_rdata_totext(&aaaa, &ns.name, b); 4707 isc_buffer_usedregion(b, &r); 4708 r.base[r.length] = '\0'; 4709 strlcpy(namestr, (char*)r.base, 4710 DNS_NAME_FORMATSIZE); 4711 isc_buffer_free(&b); 4712 dns_rdata_reset(&aaaa); 4713 4714 4715 srv = make_server(namestr, namestr); 4716 4717 ISC_LIST_APPEND(lookup->my_server_list, 4718 srv, link); 4719 } 4720 } 4721 4722 rdataset = NULL; 4723 result = advanced_rrsearch(&rdataset, &ns.name, dns_rdatatype_a, 4724 dns_rdatatype_any, &true); 4725 if (result == ISC_R_SUCCESS) { 4726 for (result = dns_rdataset_first(rdataset); 4727 result == ISC_R_SUCCESS; 4728 result = dns_rdataset_next(rdataset)) { 4729 dns_rdata_t a = DNS_RDATA_INIT; 4730 dns_rdataset_current(rdataset, &a); 4731 4732 result = isc_buffer_allocate(mctx, &b, 80); 4733 check_result(result, "isc_buffer_allocate"); 4734 4735 dns_rdata_totext(&a, &ns.name, b); 4736 isc_buffer_usedregion(b, &r); 4737 r.base[r.length] = '\0'; 4738 strlcpy(namestr, (char*)r.base, 4739 DNS_NAME_FORMATSIZE); 4740 isc_buffer_free(&b); 4741 dns_rdata_reset(&a); 4742 printf("ns name: %s\n", namestr); 4743 4744 4745 srv = make_server(namestr, namestr); 4746 4747 ISC_LIST_APPEND(lookup->my_server_list, 4748 srv, link); 4749 } 4750 } 4751 #else 4752 4753 dns_name_format(&ns.name, namestr, sizeof(namestr)); 4754 printf("ns name: "); 4755 dns_name_print(&ns.name, stdout); 4756 printf("\n"); 4757 srv = make_server(namestr, namestr); 4758 4759 ISC_LIST_APPEND(lookup->my_server_list, srv, link); 4760 4761 #endif 4762 dns_rdata_freestruct(&ns); 4763 dns_rdata_reset(&rdata); 4764 4765 } 4766 4767 ISC_LIST_APPEND(lookup_list, lookup, link); 4768 printf("\nLaunch a query to find a RRset of type "); 4769 print_type(lookup->rdtype); 4770 printf(" for zone: %s", lookup->textname); 4771 printf(" with nameservers:"); 4772 printf("\n"); 4773 print_rdataset(name, chase_nsrdataset, mctx); 4774 return (ISC_R_SUCCESS); 4775 } 4776 4777 4778 isc_result_t 4779 child_of_zone(dns_name_t * name, dns_name_t * zone_name, 4780 dns_name_t * child_name) 4781 { 4782 dns_namereln_t name_reln; 4783 int orderp; 4784 unsigned int nlabelsp; 4785 4786 name_reln = dns_name_fullcompare(name, zone_name, &orderp, &nlabelsp); 4787 if (name_reln != dns_namereln_subdomain || 4788 dns_name_countlabels(name) <= dns_name_countlabels(zone_name) + 1) { 4789 printf("\n;; ERROR : "); 4790 dns_name_print(name, stdout); 4791 printf(" is not a subdomain of: "); 4792 dns_name_print(zone_name, stdout); 4793 printf(" FAILED\n\n"); 4794 return (ISC_R_FAILURE); 4795 } 4796 4797 dns_name_getlabelsequence(name, 4798 dns_name_countlabels(name) - 4799 dns_name_countlabels(zone_name) -1, 4800 dns_name_countlabels(zone_name) +1, 4801 child_name); 4802 return (ISC_R_SUCCESS); 4803 } 4804 4805 isc_result_t 4806 grandfather_pb_test(dns_name_t *zone_name, dns_rdataset_t *sigrdataset) { 4807 dns_rdata_sig_t siginfo; 4808 dns_rdataset_t mysigrdataset; 4809 isc_result_t result; 4810 4811 dns_rdataset_init(&mysigrdataset); 4812 dns_rdataset_clone(sigrdataset, &mysigrdataset); 4813 4814 result = dns_rdataset_first(&mysigrdataset); 4815 check_result(result, "empty RRSIG dataset"); 4816 4817 do { 4818 dns_rdata_t sigrdata = DNS_RDATA_INIT; 4819 4820 dns_rdataset_current(&mysigrdataset, &sigrdata); 4821 4822 result = dns_rdata_tostruct(&sigrdata, &siginfo, NULL); 4823 check_result(result, "sigrdata tostruct siginfo"); 4824 4825 if (dns_name_compare(&siginfo.signer, zone_name) == 0) { 4826 result = ISC_R_SUCCESS; 4827 goto cleanup; 4828 } 4829 } while (dns_rdataset_next(&mysigrdataset) == ISC_R_SUCCESS); 4830 4831 result = ISC_R_FAILURE; 4832 cleanup: 4833 dns_rdataset_disassociate(&mysigrdataset); 4834 4835 return (result); 4836 } 4837 4838 4839 isc_result_t 4840 initialization(dns_name_t *name) 4841 { 4842 isc_result_t result; 4843 isc_boolean_t true = ISC_TRUE; 4844 4845 chase_nsrdataset = NULL; 4846 result = advanced_rrsearch(&chase_nsrdataset, name, dns_rdatatype_ns, 4847 dns_rdatatype_any, &true); 4848 if (result != ISC_R_SUCCESS) { 4849 printf("\n;; NS RRset is missing to continue validation:" 4850 " FAILED\n\n"); 4851 return (ISC_R_FAILURE); 4852 } 4853 INSIST(chase_nsrdataset != NULL); 4854 prepare_lookup(name); 4855 4856 dup_name(name, &chase_current_name, mctx); 4857 4858 return (ISC_R_SUCCESS); 4859 } 4860 #endif 4861 4862 void 4863 print_rdataset(dns_name_t *name, dns_rdataset_t *rdataset, isc_mem_t *mctx) 4864 { 4865 isc_buffer_t *b = NULL; 4866 isc_result_t result; 4867 isc_region_t r; 4868 4869 result = isc_buffer_allocate(mctx, &b, 9000); 4870 check_result(result, "isc_buffer_allocate"); 4871 4872 printrdataset(name, rdataset, b); 4873 4874 isc_buffer_usedregion(b, &r); 4875 r.base[r.length] = '\0'; 4876 4877 4878 printf("%s\n", r.base); 4879 4880 isc_buffer_free(&b); 4881 } 4882 4883 4884 void 4885 dup_name(dns_name_t *source, dns_name_t *target, isc_mem_t *mctx) { 4886 isc_result_t result; 4887 4888 if (dns_name_dynamic(target)) 4889 free_name(target, mctx); 4890 result = dns_name_dup(source, mctx, target); 4891 check_result(result, "dns_name_dup"); 4892 } 4893 4894 void 4895 free_name(dns_name_t *name, isc_mem_t *mctx) { 4896 dns_name_free(name, mctx); 4897 dns_name_init(name, NULL); 4898 } 4899 4900 /* 4901 * 4902 * take a DNSKEY RRset and the RRSIG RRset corresponding in parameter 4903 * return ISC_R_SUCCESS if the DNSKEY RRset contains a trusted_key 4904 * and the RRset is valid 4905 * return ISC_R_NOTFOUND if not contains trusted key 4906 or if the RRset isn't valid 4907 * return ISC_R_FAILURE if problem 4908 * 4909 */ 4910 isc_result_t 4911 contains_trusted_key(dns_name_t *name, dns_rdataset_t *rdataset, 4912 dns_rdataset_t *sigrdataset, 4913 isc_mem_t *mctx) 4914 { 4915 dns_rdataset_t myrdataset; 4916 dst_key_t *dnsseckey = NULL; 4917 int i; 4918 isc_result_t result; 4919 4920 if (name == NULL || rdataset == NULL) 4921 return (ISC_R_FAILURE); 4922 4923 dns_rdataset_init(&myrdataset); 4924 dns_rdataset_clone(rdataset, &myrdataset); 4925 4926 result = dns_rdataset_first(&myrdataset); 4927 check_result(result, "empty rdataset"); 4928 4929 do { 4930 dns_rdata_t rdata = DNS_RDATA_INIT; 4931 4932 dns_rdataset_current(&myrdataset, &rdata); 4933 INSIST(rdata.type == dns_rdatatype_dnskey); 4934 4935 result = dns_dnssec_keyfromrdata(name, &rdata, 4936 mctx, &dnsseckey); 4937 check_result(result, "dns_dnssec_keyfromrdata"); 4938 4939 for (i = 0; i < tk_list.nb_tk; i++) { 4940 if (dst_key_compare(tk_list.key[i], dnsseckey) 4941 == ISC_TRUE) { 4942 dns_rdata_reset(&rdata); 4943 4944 printf(";; Ok, find a Trusted Key in the " 4945 "DNSKEY RRset: %d\n", 4946 dst_key_id(dnsseckey)); 4947 result = sigchase_verify_sig_key(name, rdataset, 4948 dnsseckey, 4949 sigrdataset, 4950 mctx); 4951 if (result == ISC_R_SUCCESS) 4952 goto cleanup; 4953 } 4954 } 4955 dst_key_free(&dnsseckey); 4956 } while (dns_rdataset_next(&myrdataset) == ISC_R_SUCCESS); 4957 4958 cleanup: 4959 if (dnsseckey != NULL) 4960 dst_key_free(&dnsseckey); 4961 dns_rdataset_disassociate(&myrdataset); 4962 4963 return (ISC_R_NOTFOUND); 4964 } 4965 4966 isc_result_t 4967 sigchase_verify_sig(dns_name_t *name, dns_rdataset_t *rdataset, 4968 dns_rdataset_t *keyrdataset, 4969 dns_rdataset_t *sigrdataset, 4970 isc_mem_t *mctx) 4971 { 4972 dns_rdataset_t mykeyrdataset; 4973 dst_key_t *dnsseckey = NULL; 4974 isc_result_t result; 4975 4976 dns_rdataset_init(&mykeyrdataset); 4977 dns_rdataset_clone(keyrdataset, &mykeyrdataset); 4978 4979 result = dns_rdataset_first(&mykeyrdataset); 4980 check_result(result, "empty DNSKEY dataset"); 4981 4982 do { 4983 dns_rdata_t keyrdata = DNS_RDATA_INIT; 4984 4985 dns_rdataset_current(&mykeyrdataset, &keyrdata); 4986 INSIST(keyrdata.type == dns_rdatatype_dnskey); 4987 4988 result = dns_dnssec_keyfromrdata(name, &keyrdata, 4989 mctx, &dnsseckey); 4990 check_result(result, "dns_dnssec_keyfromrdata"); 4991 4992 result = sigchase_verify_sig_key(name, rdataset, dnsseckey, 4993 sigrdataset, mctx); 4994 if (result == ISC_R_SUCCESS) 4995 goto cleanup; 4996 dst_key_free(&dnsseckey); 4997 } while (dns_rdataset_next(&mykeyrdataset) == ISC_R_SUCCESS); 4998 4999 result = ISC_R_NOTFOUND; 5000 5001 cleanup: 5002 if (dnsseckey != NULL) 5003 dst_key_free(&dnsseckey); 5004 dns_rdataset_disassociate(&mykeyrdataset); 5005 5006 return (result); 5007 } 5008 5009 isc_result_t 5010 sigchase_verify_sig_key(dns_name_t *name, dns_rdataset_t *rdataset, 5011 dst_key_t *dnsseckey, dns_rdataset_t *sigrdataset, 5012 isc_mem_t *mctx) 5013 { 5014 dns_rdata_sig_t siginfo; 5015 dns_rdataset_t myrdataset; 5016 dns_rdataset_t mysigrdataset; 5017 isc_result_t result; 5018 5019 dns_rdataset_init(&myrdataset); 5020 dns_rdataset_clone(rdataset, &myrdataset); 5021 dns_rdataset_init(&mysigrdataset); 5022 dns_rdataset_clone(sigrdataset, &mysigrdataset); 5023 5024 result = dns_rdataset_first(&mysigrdataset); 5025 check_result(result, "empty RRSIG dataset"); 5026 5027 do { 5028 dns_rdata_t sigrdata = DNS_RDATA_INIT; 5029 5030 dns_rdataset_current(&mysigrdataset, &sigrdata); 5031 5032 result = dns_rdata_tostruct(&sigrdata, &siginfo, NULL); 5033 check_result(result, "sigrdata tostruct siginfo"); 5034 5035 /* 5036 * Test if the id of the DNSKEY is 5037 * the id of the DNSKEY signer's 5038 */ 5039 if (siginfo.keyid == dst_key_id(dnsseckey)) { 5040 5041 result = dns_rdataset_first(&myrdataset); 5042 check_result(result, "empty DS dataset"); 5043 5044 result = dns_dnssec_verify(name, &myrdataset, dnsseckey, 5045 ISC_FALSE, mctx, &sigrdata); 5046 5047 printf(";; VERIFYING "); 5048 print_type(rdataset->type); 5049 printf(" RRset for "); 5050 dns_name_print(name, stdout); 5051 printf(" with DNSKEY:%d: %s\n", dst_key_id(dnsseckey), 5052 isc_result_totext(result)); 5053 5054 if (result == ISC_R_SUCCESS) 5055 goto cleanup; 5056 } 5057 } while (dns_rdataset_next(&mysigrdataset) == ISC_R_SUCCESS); 5058 5059 result = ISC_R_NOTFOUND; 5060 5061 cleanup: 5062 dns_rdataset_disassociate(&myrdataset); 5063 dns_rdataset_disassociate(&mysigrdataset); 5064 5065 return (result); 5066 } 5067 5068 5069 isc_result_t 5070 sigchase_verify_ds(dns_name_t *name, dns_rdataset_t *keyrdataset, 5071 dns_rdataset_t *dsrdataset, isc_mem_t *mctx) 5072 { 5073 dns_rdata_ds_t dsinfo; 5074 dns_rdataset_t mydsrdataset; 5075 dns_rdataset_t mykeyrdataset; 5076 dst_key_t *dnsseckey = NULL; 5077 isc_result_t result; 5078 unsigned char dsbuf[DNS_DS_BUFFERSIZE]; 5079 5080 dns_rdataset_init(&mydsrdataset); 5081 dns_rdataset_clone(dsrdataset, &mydsrdataset); 5082 dns_rdataset_init(&mykeyrdataset); 5083 dns_rdataset_clone(keyrdataset, &mykeyrdataset); 5084 5085 result = dns_rdataset_first(&mydsrdataset); 5086 check_result(result, "empty DSset dataset"); 5087 do { 5088 dns_rdata_t dsrdata = DNS_RDATA_INIT; 5089 5090 dns_rdataset_current(&mydsrdataset, &dsrdata); 5091 5092 result = dns_rdata_tostruct(&dsrdata, &dsinfo, NULL); 5093 check_result(result, "dns_rdata_tostruct for DS"); 5094 5095 result = dns_rdataset_first(&mykeyrdataset); 5096 check_result(result, "empty KEY dataset"); 5097 5098 do { 5099 dns_rdata_t keyrdata = DNS_RDATA_INIT; 5100 5101 dns_rdataset_current(&mykeyrdataset, &keyrdata); 5102 INSIST(keyrdata.type == dns_rdatatype_dnskey); 5103 5104 result = dns_dnssec_keyfromrdata(name, &keyrdata, 5105 mctx, &dnsseckey); 5106 check_result(result, "dns_dnssec_keyfromrdata"); 5107 5108 /* 5109 * Test if the id of the DNSKEY is the 5110 * id of DNSKEY referenced by the DS 5111 */ 5112 if (dsinfo.key_tag == dst_key_id(dnsseckey)) { 5113 dns_rdata_t newdsrdata = DNS_RDATA_INIT; 5114 5115 result = dns_ds_buildrdata(name, &keyrdata, 5116 dsinfo.digest_type, 5117 dsbuf, &newdsrdata); 5118 dns_rdata_freestruct(&dsinfo); 5119 5120 if (result != ISC_R_SUCCESS) { 5121 printf("Oops: impossible to build" 5122 " new DS rdata\n"); 5123 goto cleanup; 5124 } 5125 5126 5127 if (dns_rdata_compare(&dsrdata, 5128 &newdsrdata) == 0) { 5129 printf(";; OK a DS valids a DNSKEY" 5130 " in the RRset\n"); 5131 printf(";; Now verify that this" 5132 " DNSKEY validates the " 5133 "DNSKEY RRset\n"); 5134 5135 result = sigchase_verify_sig_key(name, 5136 keyrdataset, 5137 dnsseckey, 5138 chase_sigkeyrdataset, 5139 mctx); 5140 if (result == ISC_R_SUCCESS) 5141 goto cleanup; 5142 } else { 5143 printf(";; This DS is NOT the DS for" 5144 " the chasing KEY: FAILED\n"); 5145 } 5146 } 5147 dst_key_free(&dnsseckey); 5148 } while (dns_rdataset_next(&mykeyrdataset) == ISC_R_SUCCESS); 5149 } while (dns_rdataset_next(&mydsrdataset) == ISC_R_SUCCESS); 5150 5151 result = ISC_R_NOTFOUND; 5152 5153 cleanup: 5154 if (dnsseckey != NULL) 5155 dst_key_free(&dnsseckey); 5156 dns_rdataset_disassociate(&mydsrdataset); 5157 dns_rdataset_disassociate(&mykeyrdataset); 5158 5159 return (result); 5160 } 5161 5162 /* 5163 * 5164 * take a pointer on a rdataset in parameter and try to resolv it. 5165 * the searched rrset is a rrset on 'name' with type 'type' 5166 * (and if the type is a rrsig the signature cover 'covers'). 5167 * the lookedup is to known if you have already done the query on the net. 5168 * ISC_R_SUCCESS: if we found the rrset 5169 * ISC_R_NOTFOUND: we do not found the rrset in cache 5170 * and we do a query on the net 5171 * ISC_R_FAILURE: rrset not found 5172 */ 5173 isc_result_t 5174 advanced_rrsearch(dns_rdataset_t **rdataset, dns_name_t *name, 5175 dns_rdatatype_t type, dns_rdatatype_t covers, 5176 isc_boolean_t *lookedup) 5177 { 5178 isc_boolean_t tmplookedup; 5179 5180 INSIST(rdataset != NULL); 5181 5182 if (*rdataset != NULL) 5183 return (ISC_R_SUCCESS); 5184 5185 tmplookedup = *lookedup; 5186 if ((*rdataset = sigchase_scanname(type, covers, 5187 lookedup, name)) == NULL) { 5188 if (tmplookedup) 5189 return (ISC_R_FAILURE); 5190 return (ISC_R_NOTFOUND); 5191 } 5192 *lookedup = ISC_FALSE; 5193 return (ISC_R_SUCCESS); 5194 } 5195 5196 5197 5198 #if DIG_SIGCHASE_TD 5199 void 5200 sigchase_td(dns_message_t *msg) 5201 { 5202 isc_result_t result; 5203 dns_name_t *name = NULL; 5204 isc_boolean_t have_answer = ISC_FALSE; 5205 isc_boolean_t true = ISC_TRUE; 5206 5207 if (msg->rcode != dns_rcode_noerror && 5208 msg->rcode != dns_rcode_nxdomain) { 5209 char buf[20]; 5210 isc_buffer_t b; 5211 5212 isc_buffer_init(&b, buf, sizeof(buf)); 5213 result = dns_rcode_totext(msg->rcode, &b); 5214 check_result(result, "dns_rcode_totext failed"); 5215 printf("error response code %.*s\n", 5216 (int)isc_buffer_usedlength(&b), buf); 5217 error_message = msg; 5218 return; 5219 } 5220 5221 if ((result = dns_message_firstname(msg, DNS_SECTION_ANSWER)) 5222 == ISC_R_SUCCESS) { 5223 dns_message_currentname(msg, DNS_SECTION_ANSWER, &name); 5224 if (current_lookup->trace_root_sigchase) { 5225 initialization(name); 5226 return; 5227 } 5228 have_answer = true; 5229 } else { 5230 if (!current_lookup->trace_root_sigchase) { 5231 result = dns_message_firstname(msg, 5232 DNS_SECTION_AUTHORITY); 5233 if (result != ISC_R_SUCCESS) { 5234 printf("no answer or authority section\n"); 5235 error_message = msg; 5236 return; 5237 } 5238 dns_message_currentname(msg, DNS_SECTION_AUTHORITY, 5239 &name); 5240 chase_nsrdataset 5241 = chase_scanname_section(msg, name, 5242 dns_rdatatype_ns, 5243 dns_rdatatype_any, 5244 DNS_SECTION_AUTHORITY); 5245 dup_name(name, &chase_authority_name, mctx); 5246 if (chase_nsrdataset != NULL) { 5247 have_delegation_ns = ISC_TRUE; 5248 printf("no response but there is a delegation" 5249 " in authority section: "); 5250 dns_name_print(name, stdout); 5251 printf("\n"); 5252 } else { 5253 printf("no response and no delegation in " 5254 "authority section but a reference" 5255 " to: "); 5256 dns_name_print(name, stdout); 5257 printf("\n"); 5258 error_message = msg; 5259 } 5260 } else { 5261 printf(";; NO ANSWERS: %s\n", 5262 isc_result_totext(result)); 5263 free_name(&chase_name, mctx); 5264 clean_trustedkey(); 5265 return; 5266 } 5267 } 5268 5269 5270 if (have_answer) { 5271 chase_rdataset 5272 = chase_scanname_section(msg, &chase_name, 5273 current_lookup 5274 ->rdtype_sigchase, 5275 dns_rdatatype_any, 5276 DNS_SECTION_ANSWER); 5277 if (chase_rdataset != NULL) 5278 have_response = ISC_TRUE; 5279 } 5280 5281 result = advanced_rrsearch(&chase_keyrdataset, 5282 &chase_current_name, 5283 dns_rdatatype_dnskey, 5284 dns_rdatatype_any, 5285 &chase_keylookedup); 5286 if (result == ISC_R_FAILURE) { 5287 printf("\n;; DNSKEY is missing to continue validation:" 5288 " FAILED\n\n"); 5289 goto cleanandgo; 5290 } 5291 if (result == ISC_R_NOTFOUND) 5292 return; 5293 INSIST(chase_keyrdataset != NULL); 5294 printf("\n;; DNSKEYset:\n"); 5295 print_rdataset(&chase_current_name , chase_keyrdataset, mctx); 5296 5297 5298 result = advanced_rrsearch(&chase_sigkeyrdataset, 5299 &chase_current_name, 5300 dns_rdatatype_rrsig, 5301 dns_rdatatype_dnskey, 5302 &chase_sigkeylookedup); 5303 if (result == ISC_R_FAILURE) { 5304 printf("\n;; RRSIG of DNSKEY is missing to continue validation:" 5305 " FAILED\n\n"); 5306 goto cleanandgo; 5307 } 5308 if (result == ISC_R_NOTFOUND) 5309 return; 5310 INSIST(chase_sigkeyrdataset != NULL); 5311 printf("\n;; RRSIG of the DNSKEYset:\n"); 5312 print_rdataset(&chase_current_name , chase_sigkeyrdataset, mctx); 5313 5314 5315 if (!chase_dslookedup && !chase_nslookedup) { 5316 if (!delegation_follow) { 5317 result = contains_trusted_key(&chase_current_name, 5318 chase_keyrdataset, 5319 chase_sigkeyrdataset, 5320 mctx); 5321 } else { 5322 INSIST(chase_dsrdataset != NULL); 5323 INSIST(chase_sigdsrdataset != NULL); 5324 result = sigchase_verify_ds(&chase_current_name, 5325 chase_keyrdataset, 5326 chase_dsrdataset, 5327 mctx); 5328 } 5329 5330 if (result != ISC_R_SUCCESS) { 5331 printf("\n;; chain of trust can't be validated:" 5332 " FAILED\n\n"); 5333 goto cleanandgo; 5334 } else { 5335 chase_dsrdataset = NULL; 5336 chase_sigdsrdataset = NULL; 5337 } 5338 } 5339 5340 if (have_response || (!have_delegation_ns && !have_response)) { 5341 /* test if it's a grand father case */ 5342 5343 if (have_response) { 5344 result = advanced_rrsearch(&chase_sigrdataset, 5345 &chase_name, 5346 dns_rdatatype_rrsig, 5347 current_lookup 5348 ->rdtype_sigchase, 5349 &true); 5350 if (result == ISC_R_FAILURE) { 5351 printf("\n;; RRset is missing to continue" 5352 " validation SHOULD NOT APPEND:" 5353 " FAILED\n\n"); 5354 goto cleanandgo; 5355 } 5356 5357 } else { 5358 result = advanced_rrsearch(&chase_sigrdataset, 5359 &chase_authority_name, 5360 dns_rdatatype_rrsig, 5361 dns_rdatatype_any, 5362 &true); 5363 if (result == ISC_R_FAILURE) { 5364 printf("\n;; RRSIG is missing to continue" 5365 " validation SHOULD NOT APPEND:" 5366 " FAILED\n\n"); 5367 goto cleanandgo; 5368 } 5369 } 5370 result = grandfather_pb_test(&chase_current_name, 5371 chase_sigrdataset); 5372 if (result != ISC_R_SUCCESS) { 5373 dns_name_t tmp_name; 5374 5375 printf("\n;; We are in a Grand Father Problem:" 5376 " See 2.2.1 in RFC 3658\n"); 5377 chase_rdataset = NULL; 5378 chase_sigrdataset = NULL; 5379 have_response = ISC_FALSE; 5380 have_delegation_ns = ISC_FALSE; 5381 5382 dns_name_init(&tmp_name, NULL); 5383 result = child_of_zone(&chase_name, &chase_current_name, 5384 &tmp_name); 5385 if (dns_name_dynamic(&chase_authority_name)) 5386 free_name(&chase_authority_name, mctx); 5387 dup_name(&tmp_name, &chase_authority_name, mctx); 5388 printf(";; and we try to continue chain of trust" 5389 " validation of the zone: "); 5390 dns_name_print(&chase_authority_name, stdout); 5391 printf("\n"); 5392 have_delegation_ns = ISC_TRUE; 5393 } else { 5394 if (have_response) 5395 goto finalstep; 5396 else 5397 chase_sigrdataset = NULL; 5398 } 5399 } 5400 5401 if (have_delegation_ns) { 5402 chase_nsrdataset = NULL; 5403 result = advanced_rrsearch(&chase_nsrdataset, 5404 &chase_authority_name, 5405 dns_rdatatype_ns, 5406 dns_rdatatype_any, 5407 &chase_nslookedup); 5408 if (result == ISC_R_FAILURE) { 5409 printf("\n;;NSset is missing to continue validation:" 5410 " FAILED\n\n"); 5411 goto cleanandgo; 5412 } 5413 if (result == ISC_R_NOTFOUND) { 5414 return; 5415 } 5416 INSIST(chase_nsrdataset != NULL); 5417 5418 result = advanced_rrsearch(&chase_dsrdataset, 5419 &chase_authority_name, 5420 dns_rdatatype_ds, 5421 dns_rdatatype_any, 5422 &chase_dslookedup); 5423 if (result == ISC_R_FAILURE) { 5424 printf("\n;; DSset is missing to continue validation:" 5425 " FAILED\n\n"); 5426 goto cleanandgo; 5427 } 5428 if (result == ISC_R_NOTFOUND) 5429 return; 5430 INSIST(chase_dsrdataset != NULL); 5431 printf("\n;; DSset:\n"); 5432 print_rdataset(&chase_authority_name , chase_dsrdataset, mctx); 5433 5434 result = advanced_rrsearch(&chase_sigdsrdataset, 5435 &chase_authority_name, 5436 dns_rdatatype_rrsig, 5437 dns_rdatatype_ds, 5438 &true); 5439 if (result != ISC_R_SUCCESS) { 5440 printf("\n;; DSset is missing to continue validation:" 5441 " FAILED\n\n"); 5442 goto cleanandgo; 5443 } 5444 printf("\n;; RRSIGset of DSset\n"); 5445 print_rdataset(&chase_authority_name, 5446 chase_sigdsrdataset, mctx); 5447 INSIST(chase_sigdsrdataset != NULL); 5448 5449 result = sigchase_verify_sig(&chase_authority_name, 5450 chase_dsrdataset, 5451 chase_keyrdataset, 5452 chase_sigdsrdataset, mctx); 5453 if (result != ISC_R_SUCCESS) { 5454 printf("\n;; Impossible to verify the DSset:" 5455 " FAILED\n\n"); 5456 goto cleanandgo; 5457 } 5458 chase_keyrdataset = NULL; 5459 chase_sigkeyrdataset = NULL; 5460 5461 5462 prepare_lookup(&chase_authority_name); 5463 5464 have_response = ISC_FALSE; 5465 have_delegation_ns = ISC_FALSE; 5466 delegation_follow = ISC_TRUE; 5467 error_message = NULL; 5468 dup_name(&chase_authority_name, &chase_current_name, mctx); 5469 free_name(&chase_authority_name, mctx); 5470 return; 5471 } 5472 5473 5474 if (error_message != NULL) { 5475 dns_rdataset_t *rdataset; 5476 dns_rdataset_t *sigrdataset; 5477 dns_name_t rdata_name; 5478 isc_result_t ret = ISC_R_FAILURE; 5479 5480 dns_name_init(&rdata_name, NULL); 5481 result = prove_nx(error_message, &chase_name, 5482 current_lookup->rdclass_sigchase, 5483 current_lookup->rdtype_sigchase, &rdata_name, 5484 &rdataset, &sigrdataset); 5485 if (rdataset == NULL || sigrdataset == NULL || 5486 dns_name_countlabels(&rdata_name) == 0) { 5487 printf("\n;; Impossible to verify the non-existence," 5488 " the NSEC RRset can't be validated:" 5489 " FAILED\n\n"); 5490 goto cleanandgo; 5491 } 5492 ret = sigchase_verify_sig(&rdata_name, rdataset, 5493 chase_keyrdataset, 5494 sigrdataset, mctx); 5495 if (ret != ISC_R_SUCCESS) { 5496 free_name(&rdata_name, mctx); 5497 printf("\n;; Impossible to verify the NSEC RR to prove" 5498 " the non-existence : FAILED\n\n"); 5499 goto cleanandgo; 5500 } 5501 free_name(&rdata_name, mctx); 5502 if (result != ISC_R_SUCCESS) { 5503 printf("\n;; Impossible to verify the non-existence:" 5504 " FAILED\n\n"); 5505 goto cleanandgo; 5506 } else { 5507 printf("\n;; OK the query doesn't have response but" 5508 " we have validate this fact : SUCCESS\n\n"); 5509 goto cleanandgo; 5510 } 5511 } 5512 5513 cleanandgo: 5514 printf(";; cleanandgo \n"); 5515 if (dns_name_dynamic(&chase_current_name)) 5516 free_name(&chase_current_name, mctx); 5517 if (dns_name_dynamic(&chase_authority_name)) 5518 free_name(&chase_authority_name, mctx); 5519 clean_trustedkey(); 5520 return; 5521 5522 finalstep : 5523 result = advanced_rrsearch(&chase_rdataset, &chase_name, 5524 current_lookup->rdtype_sigchase, 5525 dns_rdatatype_any , 5526 &true); 5527 if (result == ISC_R_FAILURE) { 5528 printf("\n;; RRsig of RRset is missing to continue validation" 5529 " SHOULD NOT APPEND: FAILED\n\n"); 5530 goto cleanandgo; 5531 } 5532 result = sigchase_verify_sig(&chase_name, chase_rdataset, 5533 chase_keyrdataset, 5534 chase_sigrdataset, mctx); 5535 if (result != ISC_R_SUCCESS) { 5536 printf("\n;; Impossible to verify the RRset : FAILED\n\n"); 5537 /* 5538 printf("RRset:\n"); 5539 print_rdataset(&chase_name , chase_rdataset, mctx); 5540 printf("DNSKEYset:\n"); 5541 print_rdataset(&chase_name , chase_keyrdataset, mctx); 5542 printf("RRSIG of RRset:\n"); 5543 print_rdataset(&chase_name , chase_sigrdataset, mctx); 5544 printf("\n"); 5545 */ 5546 goto cleanandgo; 5547 } else { 5548 printf("\n;; The Answer:\n"); 5549 print_rdataset(&chase_name , chase_rdataset, mctx); 5550 5551 printf("\n;; FINISH : we have validate the DNSSEC chain" 5552 " of trust: SUCCESS\n\n"); 5553 goto cleanandgo; 5554 } 5555 } 5556 5557 #endif 5558 5559 5560 #if DIG_SIGCHASE_BU 5561 5562 isc_result_t 5563 getneededrr(dns_message_t *msg) 5564 { 5565 isc_result_t result; 5566 dns_name_t *name = NULL; 5567 dns_rdata_t sigrdata = DNS_RDATA_INIT; 5568 dns_rdata_sig_t siginfo; 5569 isc_boolean_t true = ISC_TRUE; 5570 5571 if ((result = dns_message_firstname(msg, DNS_SECTION_ANSWER)) 5572 != ISC_R_SUCCESS) { 5573 printf(";; NO ANSWERS: %s\n", isc_result_totext(result)); 5574 5575 if (chase_name.ndata == NULL) 5576 return (ISC_R_ADDRNOTAVAIL); 5577 } else { 5578 dns_message_currentname(msg, DNS_SECTION_ANSWER, &name); 5579 } 5580 5581 /* What do we chase? */ 5582 if (chase_rdataset == NULL) { 5583 result = advanced_rrsearch(&chase_rdataset, name, 5584 dns_rdatatype_any, 5585 dns_rdatatype_any, &true); 5586 if (result != ISC_R_SUCCESS) { 5587 printf("\n;; No Answers: Validation FAILED\n\n"); 5588 return (ISC_R_NOTFOUND); 5589 } 5590 dup_name(name, &chase_name, mctx); 5591 printf(";; RRset to chase:\n"); 5592 print_rdataset(&chase_name, chase_rdataset, mctx); 5593 } 5594 INSIST(chase_rdataset != NULL); 5595 5596 5597 if (chase_sigrdataset == NULL) { 5598 result = advanced_rrsearch(&chase_sigrdataset, name, 5599 dns_rdatatype_rrsig, 5600 chase_rdataset->type, 5601 &chase_siglookedup); 5602 if (result == ISC_R_FAILURE) { 5603 printf("\n;; RRSIG is missing for continue validation:" 5604 " FAILED\n\n"); 5605 if (dns_name_dynamic(&chase_name)) 5606 free_name(&chase_name, mctx); 5607 return (ISC_R_NOTFOUND); 5608 } 5609 if (result == ISC_R_NOTFOUND) { 5610 return (ISC_R_NOTFOUND); 5611 } 5612 printf("\n;; RRSIG of the RRset to chase:\n"); 5613 print_rdataset(&chase_name, chase_sigrdataset, mctx); 5614 } 5615 INSIST(chase_sigrdataset != NULL); 5616 5617 5618 /* first find the DNSKEY name */ 5619 result = dns_rdataset_first(chase_sigrdataset); 5620 check_result(result, "empty RRSIG dataset"); 5621 dns_rdataset_current(chase_sigrdataset, &sigrdata); 5622 result = dns_rdata_tostruct(&sigrdata, &siginfo, NULL); 5623 check_result(result, "sigrdata tostruct siginfo"); 5624 dup_name(&siginfo.signer, &chase_signame, mctx); 5625 dns_rdata_freestruct(&siginfo); 5626 dns_rdata_reset(&sigrdata); 5627 5628 /* Do we have a key? */ 5629 if (chase_keyrdataset == NULL) { 5630 result = advanced_rrsearch(&chase_keyrdataset, 5631 &chase_signame, 5632 dns_rdatatype_dnskey, 5633 dns_rdatatype_any, 5634 &chase_keylookedup); 5635 if (result == ISC_R_FAILURE) { 5636 printf("\n;; DNSKEY is missing to continue validation:" 5637 " FAILED\n\n"); 5638 free_name(&chase_signame, mctx); 5639 if (dns_name_dynamic(&chase_name)) 5640 free_name(&chase_name, mctx); 5641 return (ISC_R_NOTFOUND); 5642 } 5643 if (result == ISC_R_NOTFOUND) { 5644 free_name(&chase_signame, mctx); 5645 return (ISC_R_NOTFOUND); 5646 } 5647 printf("\n;; DNSKEYset that signs the RRset to chase:\n"); 5648 print_rdataset(&chase_signame, chase_keyrdataset, mctx); 5649 } 5650 INSIST(chase_keyrdataset != NULL); 5651 5652 if (chase_sigkeyrdataset == NULL) { 5653 result = advanced_rrsearch(&chase_sigkeyrdataset, 5654 &chase_signame, 5655 dns_rdatatype_rrsig, 5656 dns_rdatatype_dnskey, 5657 &chase_sigkeylookedup); 5658 if (result == ISC_R_FAILURE) { 5659 printf("\n;; RRSIG for DNSKEY is missing to continue" 5660 " validation : FAILED\n\n"); 5661 free_name(&chase_signame, mctx); 5662 if (dns_name_dynamic(&chase_name)) 5663 free_name(&chase_name, mctx); 5664 return (ISC_R_NOTFOUND); 5665 } 5666 if (result == ISC_R_NOTFOUND) { 5667 free_name(&chase_signame, mctx); 5668 return (ISC_R_NOTFOUND); 5669 } 5670 printf("\n;; RRSIG of the DNSKEYset that signs the " 5671 "RRset to chase:\n"); 5672 print_rdataset(&chase_signame, chase_sigkeyrdataset, mctx); 5673 } 5674 INSIST(chase_sigkeyrdataset != NULL); 5675 5676 5677 if (chase_dsrdataset == NULL) { 5678 result = advanced_rrsearch(&chase_dsrdataset, &chase_signame, 5679 dns_rdatatype_ds, dns_rdatatype_any, 5680 &chase_dslookedup); 5681 if (result == ISC_R_FAILURE) { 5682 printf("\n;; WARNING There is no DS for the zone: "); 5683 dns_name_print(&chase_signame, stdout); 5684 printf("\n"); 5685 } 5686 if (result == ISC_R_NOTFOUND) { 5687 free_name(&chase_signame, mctx); 5688 return (ISC_R_NOTFOUND); 5689 } 5690 if (chase_dsrdataset != NULL) { 5691 printf("\n;; DSset of the DNSKEYset\n"); 5692 print_rdataset(&chase_signame, chase_dsrdataset, mctx); 5693 } 5694 } 5695 5696 if (chase_dsrdataset != NULL) { 5697 /* 5698 * if there is no RRSIG of DS, 5699 * we don't want to search on the network 5700 */ 5701 result = advanced_rrsearch(&chase_sigdsrdataset, 5702 &chase_signame, 5703 dns_rdatatype_rrsig, 5704 dns_rdatatype_ds, &true); 5705 if (result == ISC_R_FAILURE) { 5706 printf(";; WARNING : NO RRSIG DS : RRSIG DS" 5707 " should come with DS\n"); 5708 /* 5709 * We continue even the DS couldn't be validated, 5710 * because the DNSKEY could be a Trusted Key. 5711 */ 5712 chase_dsrdataset = NULL; 5713 } else { 5714 printf("\n;; RRSIG of the DSset of the DNSKEYset\n"); 5715 print_rdataset(&chase_signame, chase_sigdsrdataset, 5716 mctx); 5717 } 5718 } 5719 return (1); 5720 } 5721 5722 5723 5724 void 5725 sigchase_bu(dns_message_t *msg) 5726 { 5727 isc_result_t result; 5728 int ret; 5729 5730 if (tk_list.nb_tk == 0) { 5731 result = get_trusted_key(mctx); 5732 if (result != ISC_R_SUCCESS) { 5733 printf("No trusted keys present\n"); 5734 return; 5735 } 5736 } 5737 5738 5739 ret = getneededrr(msg); 5740 if (ret == ISC_R_NOTFOUND) 5741 return; 5742 5743 if (ret == ISC_R_ADDRNOTAVAIL) { 5744 /* We have no response */ 5745 dns_rdataset_t *rdataset; 5746 dns_rdataset_t *sigrdataset; 5747 dns_name_t rdata_name; 5748 dns_name_t query_name; 5749 5750 5751 dns_name_init(&query_name, NULL); 5752 dns_name_init(&rdata_name, NULL); 5753 nameFromString(current_lookup->textname, &query_name); 5754 5755 result = prove_nx(msg, &query_name, current_lookup->rdclass, 5756 current_lookup->rdtype, &rdata_name, 5757 &rdataset, &sigrdataset); 5758 free_name(&query_name, mctx); 5759 if (rdataset == NULL || sigrdataset == NULL || 5760 dns_name_countlabels(&rdata_name) == 0) { 5761 printf("\n;; Impossible to verify the Non-existence," 5762 " the NSEC RRset can't be validated: " 5763 "FAILED\n\n"); 5764 clean_trustedkey(); 5765 return; 5766 } 5767 5768 if (result != ISC_R_SUCCESS) { 5769 printf("\n No Answers and impossible to prove the" 5770 " unsecurity : Validation FAILED\n\n"); 5771 clean_trustedkey(); 5772 return; 5773 } 5774 printf(";; An NSEC prove the non-existence of a answers," 5775 " Now we want validate this NSEC\n"); 5776 5777 dup_name(&rdata_name, &chase_name, mctx); 5778 free_name(&rdata_name, mctx); 5779 chase_rdataset = rdataset; 5780 chase_sigrdataset = sigrdataset; 5781 chase_keyrdataset = NULL; 5782 chase_sigkeyrdataset = NULL; 5783 chase_dsrdataset = NULL; 5784 chase_sigdsrdataset = NULL; 5785 chase_siglookedup = ISC_FALSE; 5786 chase_keylookedup = ISC_FALSE; 5787 chase_dslookedup = ISC_FALSE; 5788 chase_sigdslookedup = ISC_FALSE; 5789 sigchase(msg); 5790 clean_trustedkey(); 5791 return; 5792 } 5793 5794 5795 printf("\n\n\n;; WE HAVE MATERIAL, WE NOW DO VALIDATION\n"); 5796 5797 result = sigchase_verify_sig(&chase_name, chase_rdataset, 5798 chase_keyrdataset, 5799 chase_sigrdataset, mctx); 5800 if (result != ISC_R_SUCCESS) { 5801 free_name(&chase_name, mctx); 5802 free_name(&chase_signame, mctx); 5803 printf(";; No DNSKEY is valid to check the RRSIG" 5804 " of the RRset: FAILED\n"); 5805 clean_trustedkey(); 5806 return; 5807 } 5808 printf(";; OK We found DNSKEY (or more) to validate the RRset\n"); 5809 5810 result = contains_trusted_key(&chase_signame, chase_keyrdataset, 5811 chase_sigkeyrdataset, mctx); 5812 if (result == ISC_R_SUCCESS) { 5813 free_name(&chase_name, mctx); 5814 free_name(&chase_signame, mctx); 5815 printf("\n;; Ok this DNSKEY is a Trusted Key," 5816 " DNSSEC validation is ok: SUCCESS\n\n"); 5817 clean_trustedkey(); 5818 return; 5819 } 5820 5821 printf(";; Now, we are going to validate this DNSKEY by the DS\n"); 5822 5823 if (chase_dsrdataset == NULL) { 5824 free_name(&chase_name, mctx); 5825 free_name(&chase_signame, mctx); 5826 printf(";; the DNSKEY isn't trusted-key and there isn't" 5827 " DS to validate the DNSKEY: FAILED\n"); 5828 clean_trustedkey(); 5829 return; 5830 } 5831 5832 result = sigchase_verify_ds(&chase_signame, chase_keyrdataset, 5833 chase_dsrdataset, mctx); 5834 if (result != ISC_R_SUCCESS) { 5835 free_name(&chase_signame, mctx); 5836 free_name(&chase_name, mctx); 5837 printf(";; ERROR no DS validates a DNSKEY in the" 5838 " DNSKEY RRset: FAILED\n"); 5839 clean_trustedkey(); 5840 return; 5841 } else 5842 printf(";; OK this DNSKEY (validated by the DS) validates" 5843 " the RRset of the DNSKEYs, thus the DNSKEY validates" 5844 " the RRset\n"); 5845 INSIST(chase_sigdsrdataset != NULL); 5846 5847 dup_name(&chase_signame, &chase_name, mctx); 5848 free_name(&chase_signame, mctx); 5849 chase_rdataset = chase_dsrdataset; 5850 chase_sigrdataset = chase_sigdsrdataset; 5851 chase_keyrdataset = NULL; 5852 chase_sigkeyrdataset = NULL; 5853 chase_dsrdataset = NULL; 5854 chase_sigdsrdataset = NULL; 5855 chase_siglookedup = chase_keylookedup = ISC_FALSE; 5856 chase_dslookedup = chase_sigdslookedup = ISC_FALSE; 5857 5858 printf(";; Now, we want to validate the DS : recursive call\n"); 5859 sigchase(msg); 5860 return; 5861 } 5862 #endif 5863 5864 void 5865 sigchase(dns_message_t *msg) { 5866 #if DIG_SIGCHASE_TD 5867 if (current_lookup->do_topdown) { 5868 sigchase_td(msg); 5869 return; 5870 } 5871 #endif 5872 #if DIG_SIGCHASE_BU 5873 sigchase_bu(msg); 5874 return; 5875 #endif 5876 } 5877 5878 5879 /* 5880 * return 1 if name1 < name2 5881 * 0 if name1 == name2 5882 * -1 if name1 > name2 5883 * and -2 if problem 5884 */ 5885 int 5886 inf_name(dns_name_t *name1, dns_name_t *name2) 5887 { 5888 dns_label_t label1; 5889 dns_label_t label2; 5890 unsigned int nblabel1; 5891 unsigned int nblabel2; 5892 int min_lum_label; 5893 int i; 5894 int ret = -2; 5895 5896 nblabel1 = dns_name_countlabels(name1); 5897 nblabel2 = dns_name_countlabels(name2); 5898 5899 if (nblabel1 >= nblabel2) 5900 min_lum_label = nblabel2; 5901 else 5902 min_lum_label = nblabel1; 5903 5904 5905 for (i=1 ; i < min_lum_label; i++) { 5906 dns_name_getlabel(name1, nblabel1 -1 - i, &label1); 5907 dns_name_getlabel(name2, nblabel2 -1 - i, &label2); 5908 if ((ret = isc_region_compare(&label1, &label2)) != 0) { 5909 if (ret < 0) 5910 return (-1); 5911 else if (ret > 0) 5912 return (1); 5913 } 5914 } 5915 if (nblabel1 == nblabel2) 5916 return (0); 5917 5918 if (nblabel1 < nblabel2) 5919 return (-1); 5920 else 5921 return (1); 5922 } 5923 5924 /** 5925 * 5926 * 5927 * 5928 */ 5929 isc_result_t 5930 prove_nx_domain(dns_message_t *msg, 5931 dns_name_t *name, 5932 dns_name_t *rdata_name, 5933 dns_rdataset_t **rdataset, 5934 dns_rdataset_t **sigrdataset) 5935 { 5936 isc_result_t ret = ISC_R_FAILURE; 5937 isc_result_t result = ISC_R_NOTFOUND; 5938 dns_rdataset_t *nsecset = NULL; 5939 dns_rdataset_t *signsecset = NULL ; 5940 dns_rdata_t nsec = DNS_RDATA_INIT; 5941 dns_name_t *nsecname; 5942 dns_rdata_nsec_t nsecstruct; 5943 5944 if ((result = dns_message_firstname(msg, DNS_SECTION_AUTHORITY)) 5945 != ISC_R_SUCCESS) { 5946 printf(";; nothing in authority section : impossible to" 5947 " validate the non-existence : FAILED\n"); 5948 return (ISC_R_FAILURE); 5949 } 5950 5951 do { 5952 nsecname = NULL; 5953 dns_message_currentname(msg, DNS_SECTION_AUTHORITY, &nsecname); 5954 nsecset = search_type(nsecname, dns_rdatatype_nsec, 5955 dns_rdatatype_any); 5956 if (nsecset == NULL) 5957 continue; 5958 5959 printf("There is a NSEC for this zone in the" 5960 " AUTHORITY section:\n"); 5961 print_rdataset(nsecname, nsecset, mctx); 5962 5963 for (result = dns_rdataset_first(nsecset); 5964 result == ISC_R_SUCCESS; 5965 result = dns_rdataset_next(nsecset)) { 5966 dns_rdataset_current(nsecset, &nsec); 5967 5968 signsecset 5969 = chase_scanname_section(msg, nsecname, 5970 dns_rdatatype_rrsig, 5971 dns_rdatatype_nsec, 5972 DNS_SECTION_AUTHORITY); 5973 if (signsecset == NULL) { 5974 printf(";; no RRSIG NSEC in authority section:" 5975 " impossible to validate the " 5976 "non-existence: FAILED\n"); 5977 return (ISC_R_FAILURE); 5978 } 5979 5980 ret = dns_rdata_tostruct(&nsec, &nsecstruct, NULL); 5981 check_result(ret,"dns_rdata_tostruct"); 5982 5983 if ((inf_name(nsecname, &nsecstruct.next) == 1 && 5984 inf_name(name, &nsecstruct.next) == 1) || 5985 (inf_name(name, nsecname) == 1 && 5986 inf_name(&nsecstruct.next, name) == 1)) { 5987 dns_rdata_freestruct(&nsecstruct); 5988 *rdataset = nsecset; 5989 *sigrdataset = signsecset; 5990 dup_name(nsecname, rdata_name, mctx); 5991 5992 return (ISC_R_SUCCESS); 5993 } 5994 5995 dns_rdata_freestruct(&nsecstruct); 5996 dns_rdata_reset(&nsec); 5997 } 5998 } while (dns_message_nextname(msg, DNS_SECTION_AUTHORITY) 5999 == ISC_R_SUCCESS); 6000 6001 *rdataset = NULL; 6002 *sigrdataset = NULL; 6003 rdata_name = NULL; 6004 return (ISC_R_FAILURE); 6005 } 6006 6007 /** 6008 * 6009 * 6010 * 6011 * 6012 * 6013 */ 6014 isc_result_t 6015 prove_nx_type(dns_message_t *msg, dns_name_t *name, dns_rdataset_t *nsecset, 6016 dns_rdataclass_t class, dns_rdatatype_t type, 6017 dns_name_t *rdata_name, dns_rdataset_t **rdataset, 6018 dns_rdataset_t **sigrdataset) 6019 { 6020 isc_result_t ret; 6021 dns_rdataset_t *signsecset; 6022 dns_rdata_t nsec = DNS_RDATA_INIT; 6023 6024 UNUSED(class); 6025 6026 ret = dns_rdataset_first(nsecset); 6027 check_result(ret,"dns_rdataset_first"); 6028 6029 dns_rdataset_current(nsecset, &nsec); 6030 6031 ret = dns_nsec_typepresent(&nsec, type); 6032 if (ret == ISC_R_SUCCESS) 6033 printf("OK the NSEC said that the type doesn't exist \n"); 6034 6035 signsecset = chase_scanname_section(msg, name, 6036 dns_rdatatype_rrsig, 6037 dns_rdatatype_nsec, 6038 DNS_SECTION_AUTHORITY); 6039 if (signsecset == NULL) { 6040 printf("There isn't RRSIG NSEC for the zone \n"); 6041 return (ISC_R_FAILURE); 6042 } 6043 dup_name(name, rdata_name, mctx); 6044 *rdataset = nsecset; 6045 *sigrdataset = signsecset; 6046 6047 return (ret); 6048 } 6049 6050 /** 6051 * 6052 * 6053 * 6054 * 6055 */ 6056 isc_result_t 6057 prove_nx(dns_message_t *msg, dns_name_t *name, dns_rdataclass_t class, 6058 dns_rdatatype_t type, dns_name_t *rdata_name, 6059 dns_rdataset_t **rdataset, dns_rdataset_t **sigrdataset) 6060 { 6061 isc_result_t ret; 6062 dns_rdataset_t *nsecset = NULL; 6063 6064 printf("We want to prove the non-existence of a type of rdata %d" 6065 " or of the zone: \n", type); 6066 6067 if ((ret = dns_message_firstname(msg, DNS_SECTION_AUTHORITY)) 6068 != ISC_R_SUCCESS) { 6069 printf(";; nothing in authority section : impossible to" 6070 " validate the non-existence : FAILED\n"); 6071 return (ISC_R_FAILURE); 6072 } 6073 6074 nsecset = chase_scanname_section(msg, name, dns_rdatatype_nsec, 6075 dns_rdatatype_any, 6076 DNS_SECTION_AUTHORITY); 6077 if (nsecset != NULL) { 6078 printf("We have a NSEC for this zone :OK\n"); 6079 ret = prove_nx_type(msg, name, nsecset, class, 6080 type, rdata_name, rdataset, 6081 sigrdataset); 6082 if (ret != ISC_R_SUCCESS) { 6083 printf("prove_nx: ERROR type exist\n"); 6084 return (ret); 6085 } else { 6086 printf("prove_nx: OK type does not exist\n"); 6087 return (ISC_R_SUCCESS); 6088 } 6089 } else { 6090 printf("there is no NSEC for this zone: validating " 6091 "that the zone doesn't exist\n"); 6092 ret = prove_nx_domain(msg, name, rdata_name, 6093 rdataset, sigrdataset); 6094 return (ret); 6095 } 6096 /* Never get here */ 6097 } 6098 #endif 6099