1/* $NetBSD: nsupdate.c,v 1.3.4.2 2012/12/15 05:39:26 riz Exp $ */ 2 3/* 4 * Copyright (C) 2004-2012 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 */ 21 22/*! \file */ 23 24#include <config.h> 25 26#include <ctype.h> 27#include <errno.h> 28#include <limits.h> 29#include <stdlib.h> 30#include <unistd.h> 31 32#include <isc/app.h> 33#include <isc/base64.h> 34#include <isc/buffer.h> 35#include <isc/commandline.h> 36#include <isc/entropy.h> 37#include <isc/event.h> 38#include <isc/file.h> 39#include <isc/hash.h> 40#include <isc/lex.h> 41#include <isc/log.h> 42#include <isc/mem.h> 43#include <isc/parseint.h> 44#include <isc/print.h> 45#include <isc/random.h> 46#include <isc/region.h> 47#include <isc/sockaddr.h> 48#include <isc/socket.h> 49#include <isc/stdio.h> 50#include <isc/string.h> 51#include <isc/task.h> 52#include <isc/timer.h> 53#include <isc/types.h> 54#include <isc/util.h> 55 56#include <isccfg/namedconf.h> 57 58#include <dns/callbacks.h> 59#include <dns/dispatch.h> 60#include <dns/dnssec.h> 61#include <dns/events.h> 62#include <dns/fixedname.h> 63#include <dns/log.h> 64#include <dns/masterdump.h> 65#include <dns/message.h> 66#include <dns/name.h> 67#include <dns/rcode.h> 68#include <dns/rdata.h> 69#include <dns/rdataclass.h> 70#include <dns/rdatalist.h> 71#include <dns/rdataset.h> 72#include <dns/rdatastruct.h> 73#include <dns/rdatatype.h> 74#include <dns/request.h> 75#include <dns/result.h> 76#include <dns/tkey.h> 77#include <dns/tsig.h> 78 79#include <dst/dst.h> 80 81#include <lwres/lwres.h> 82#include <lwres/net.h> 83 84#ifdef GSSAPI 85#include <dst/gssapi.h> 86#include ISC_PLATFORM_KRB5HEADER 87#endif 88#include <bind9/getaddresses.h> 89 90#if defined(HAVE_READLINE) 91#include <readline/readline.h> 92#include <readline/history.h> 93#endif 94 95#ifdef HAVE_ADDRINFO 96#ifdef HAVE_GETADDRINFO 97#ifdef HAVE_GAISTRERROR 98#define USE_GETADDRINFO 99#endif 100#endif 101#endif 102 103#ifndef USE_GETADDRINFO 104#ifndef ISC_PLATFORM_NONSTDHERRNO 105extern int h_errno; 106#endif 107#endif 108 109#define MAXCMD (4 * 1024) 110#define MAXWIRE (64 * 1024) 111#define PACKETSIZE ((64 * 1024) - 1) 112#define INITTEXT (2 * 1024) 113#define MAXTEXT (128 * 1024) 114#define FIND_TIMEOUT 5 115#define TTL_MAX 2147483647U /* Maximum signed 32 bit integer. */ 116 117#define DNSDEFAULTPORT 53 118 119static isc_uint16_t dnsport = DNSDEFAULTPORT; 120 121#ifndef RESOLV_CONF 122#define RESOLV_CONF "/etc/resolv.conf" 123#endif 124 125static isc_boolean_t debugging = ISC_FALSE, ddebugging = ISC_FALSE; 126static isc_boolean_t memdebugging = ISC_FALSE; 127static isc_boolean_t have_ipv4 = ISC_FALSE; 128static isc_boolean_t have_ipv6 = ISC_FALSE; 129static isc_boolean_t is_dst_up = ISC_FALSE; 130static isc_boolean_t usevc = ISC_FALSE; 131static isc_boolean_t usegsstsig = ISC_FALSE; 132static isc_boolean_t use_win2k_gsstsig = ISC_FALSE; 133static isc_boolean_t tried_other_gsstsig = ISC_FALSE; 134static isc_boolean_t local_only = ISC_FALSE; 135static isc_taskmgr_t *taskmgr = NULL; 136static isc_task_t *global_task = NULL; 137static isc_event_t *global_event = NULL; 138static isc_log_t *lctx = NULL; 139static isc_mem_t *mctx = NULL; 140static dns_dispatchmgr_t *dispatchmgr = NULL; 141static dns_requestmgr_t *requestmgr = NULL; 142static isc_socketmgr_t *socketmgr = NULL; 143static isc_timermgr_t *timermgr = NULL; 144static dns_dispatch_t *dispatchv4 = NULL; 145static dns_dispatch_t *dispatchv6 = NULL; 146static dns_message_t *updatemsg = NULL; 147static dns_fixedname_t fuserzone; 148static dns_name_t *userzone = NULL; 149static dns_name_t *zonename = NULL; 150static dns_name_t tmpzonename; 151static dns_name_t restart_master; 152static dns_tsig_keyring_t *gssring = NULL; 153static dns_tsigkey_t *tsigkey = NULL; 154static dst_key_t *sig0key = NULL; 155static lwres_context_t *lwctx = NULL; 156static lwres_conf_t *lwconf; 157static isc_sockaddr_t *servers; 158static int ns_inuse = 0; 159static int ns_total = 0; 160static isc_sockaddr_t *userserver = NULL; 161static isc_sockaddr_t *localaddr = NULL; 162static isc_sockaddr_t *serveraddr = NULL; 163static isc_sockaddr_t tempaddr; 164static const char *keyfile = NULL; 165static char *keystr = NULL; 166static isc_entropy_t *entropy = NULL; 167static isc_boolean_t shuttingdown = ISC_FALSE; 168static FILE *input; 169static isc_boolean_t interactive = ISC_TRUE; 170static isc_boolean_t seenerror = ISC_FALSE; 171static const dns_master_style_t *style; 172static int requests = 0; 173static unsigned int logdebuglevel = 0; 174static unsigned int timeout = 300; 175static unsigned int udp_timeout = 3; 176static unsigned int udp_retries = 3; 177static dns_rdataclass_t defaultclass = dns_rdataclass_in; 178static dns_rdataclass_t zoneclass = dns_rdataclass_none; 179static dns_message_t *answer = NULL; 180static isc_uint32_t default_ttl = 0; 181static isc_boolean_t default_ttl_set = ISC_FALSE; 182 183typedef struct nsu_requestinfo { 184 dns_message_t *msg; 185 isc_sockaddr_t *addr; 186} nsu_requestinfo_t; 187 188static void 189sendrequest(isc_sockaddr_t *srcaddr, isc_sockaddr_t *destaddr, 190 dns_message_t *msg, dns_request_t **request); 191 192ISC_PLATFORM_NORETURN_PRE static void 193fatal(const char *format, ...) 194ISC_FORMAT_PRINTF(1, 2) ISC_PLATFORM_NORETURN_POST; 195 196static void 197debug(const char *format, ...) ISC_FORMAT_PRINTF(1, 2); 198 199static void 200ddebug(const char *format, ...) ISC_FORMAT_PRINTF(1, 2); 201 202#ifdef GSSAPI 203static dns_fixedname_t fkname; 204static isc_sockaddr_t *kserver = NULL; 205static char *realm = NULL; 206static char servicename[DNS_NAME_FORMATSIZE]; 207static dns_name_t *keyname; 208typedef struct nsu_gssinfo { 209 dns_message_t *msg; 210 isc_sockaddr_t *addr; 211 gss_ctx_id_t context; 212} nsu_gssinfo_t; 213 214static void 215start_gssrequest(dns_name_t *master); 216static void 217send_gssrequest(isc_sockaddr_t *srcaddr, isc_sockaddr_t *destaddr, 218 dns_message_t *msg, dns_request_t **request, 219 gss_ctx_id_t context); 220static void 221recvgss(isc_task_t *task, isc_event_t *event); 222#endif /* GSSAPI */ 223 224static void 225error(const char *format, ...) ISC_FORMAT_PRINTF(1, 2); 226 227#define STATUS_MORE (isc_uint16_t)0 228#define STATUS_SEND (isc_uint16_t)1 229#define STATUS_QUIT (isc_uint16_t)2 230#define STATUS_SYNTAX (isc_uint16_t)3 231 232typedef struct entropysource entropysource_t; 233 234struct entropysource { 235 isc_entropysource_t *source; 236 isc_mem_t *mctx; 237 ISC_LINK(entropysource_t) link; 238}; 239 240static ISC_LIST(entropysource_t) sources; 241 242static void 243setup_entropy(isc_mem_t *mctx, const char *randomfile, isc_entropy_t **ectx) 244{ 245 isc_result_t result; 246 isc_entropysource_t *source = NULL; 247 entropysource_t *elt; 248 int usekeyboard = ISC_ENTROPY_KEYBOARDMAYBE; 249 250 REQUIRE(ectx != NULL); 251 252 if (*ectx == NULL) { 253 result = isc_entropy_create(mctx, ectx); 254 if (result != ISC_R_SUCCESS) 255 fatal("could not create entropy object"); 256 ISC_LIST_INIT(sources); 257 } 258 259 if (randomfile != NULL && strcmp(randomfile, "keyboard") == 0) { 260 usekeyboard = ISC_ENTROPY_KEYBOARDYES; 261 randomfile = NULL; 262 } 263 264 result = isc_entropy_usebestsource(*ectx, &source, randomfile, 265 usekeyboard); 266 267 if (result != ISC_R_SUCCESS) 268 fatal("could not initialize entropy source: %s", 269 isc_result_totext(result)); 270 271 if (source != NULL) { 272 elt = isc_mem_get(mctx, sizeof(*elt)); 273 if (elt == NULL) 274 fatal("out of memory"); 275 elt->source = source; 276 elt->mctx = mctx; 277 ISC_LINK_INIT(elt, link); 278 ISC_LIST_APPEND(sources, elt, link); 279 } 280} 281 282static void 283cleanup_entropy(isc_entropy_t **ectx) { 284 entropysource_t *source; 285 while (!ISC_LIST_EMPTY(sources)) { 286 source = ISC_LIST_HEAD(sources); 287 ISC_LIST_UNLINK(sources, source, link); 288 isc_entropy_destroysource(&source->source); 289 isc_mem_put(source->mctx, source, sizeof(*source)); 290 } 291 isc_entropy_detach(ectx); 292} 293 294 295static dns_rdataclass_t 296getzoneclass(void) { 297 if (zoneclass == dns_rdataclass_none) 298 zoneclass = defaultclass; 299 return (zoneclass); 300} 301 302static isc_boolean_t 303setzoneclass(dns_rdataclass_t rdclass) { 304 if (zoneclass == dns_rdataclass_none || 305 rdclass == dns_rdataclass_none) 306 zoneclass = rdclass; 307 if (zoneclass != rdclass) 308 return (ISC_FALSE); 309 return (ISC_TRUE); 310} 311 312static void 313fatal(const char *format, ...) { 314 va_list args; 315 316 va_start(args, format); 317 vfprintf(stderr, format, args); 318 va_end(args); 319 fprintf(stderr, "\n"); 320 exit(1); 321} 322 323static void 324error(const char *format, ...) { 325 va_list args; 326 327 va_start(args, format); 328 vfprintf(stderr, format, args); 329 va_end(args); 330 fprintf(stderr, "\n"); 331} 332 333static void 334debug(const char *format, ...) { 335 va_list args; 336 337 if (debugging) { 338 va_start(args, format); 339 vfprintf(stderr, format, args); 340 va_end(args); 341 fprintf(stderr, "\n"); 342 } 343} 344 345static void 346ddebug(const char *format, ...) { 347 va_list args; 348 349 if (ddebugging) { 350 va_start(args, format); 351 vfprintf(stderr, format, args); 352 va_end(args); 353 fprintf(stderr, "\n"); 354 } 355} 356 357static inline void 358check_result(isc_result_t result, const char *msg) { 359 if (result != ISC_R_SUCCESS) 360 fatal("%s: %s", msg, isc_result_totext(result)); 361} 362 363static void * 364mem_alloc(void *arg, size_t size) { 365 return (isc_mem_get(arg, size)); 366} 367 368static void 369mem_free(void *arg, void *mem, size_t size) { 370 isc_mem_put(arg, mem, size); 371} 372 373static char * 374nsu_strsep(char **stringp, const char *delim) { 375 char *string = *stringp; 376 char *s; 377 const char *d; 378 char sc, dc; 379 380 if (string == NULL) 381 return (NULL); 382 383 for (; *string != '\0'; string++) { 384 sc = *string; 385 for (d = delim; (dc = *d) != '\0'; d++) { 386 if (sc == dc) 387 break; 388 } 389 if (dc == 0) 390 break; 391 } 392 393 for (s = string; *s != '\0'; s++) { 394 sc = *s; 395 for (d = delim; (dc = *d) != '\0'; d++) { 396 if (sc == dc) { 397 *s++ = '\0'; 398 *stringp = s; 399 return (string); 400 } 401 } 402 } 403 *stringp = NULL; 404 return (string); 405} 406 407static void 408reset_system(void) { 409 isc_result_t result; 410 411 ddebug("reset_system()"); 412 /* If the update message is still around, destroy it */ 413 if (updatemsg != NULL) 414 dns_message_reset(updatemsg, DNS_MESSAGE_INTENTRENDER); 415 else { 416 result = dns_message_create(mctx, DNS_MESSAGE_INTENTRENDER, 417 &updatemsg); 418 check_result(result, "dns_message_create"); 419 } 420 updatemsg->opcode = dns_opcode_update; 421 if (usegsstsig) { 422 if (tsigkey != NULL) 423 dns_tsigkey_detach(&tsigkey); 424 if (gssring != NULL) 425 dns_tsigkeyring_detach(&gssring); 426 tried_other_gsstsig = ISC_FALSE; 427 } 428} 429 430static isc_uint16_t 431parse_hmac(dns_name_t **hmac, const char *hmacstr, size_t len) { 432 isc_uint16_t digestbits = 0; 433 isc_result_t result; 434 char buf[20]; 435 436 REQUIRE(hmac != NULL && *hmac == NULL); 437 REQUIRE(hmacstr != NULL); 438 439 if (len >= sizeof(buf)) 440 fatal("unknown key type '%.*s'", (int)(len), hmacstr); 441 442 strncpy(buf, hmacstr, len); 443 buf[len] = 0; 444 445 if (strcasecmp(buf, "hmac-md5") == 0) { 446 *hmac = DNS_TSIG_HMACMD5_NAME; 447 } else if (strncasecmp(buf, "hmac-md5-", 9) == 0) { 448 *hmac = DNS_TSIG_HMACMD5_NAME; 449 result = isc_parse_uint16(&digestbits, &buf[9], 10); 450 if (result != ISC_R_SUCCESS || digestbits > 128) 451 fatal("digest-bits out of range [0..128]"); 452 digestbits = (digestbits +7) & ~0x7U; 453 } else if (strcasecmp(buf, "hmac-sha1") == 0) { 454 *hmac = DNS_TSIG_HMACSHA1_NAME; 455 } else if (strncasecmp(buf, "hmac-sha1-", 10) == 0) { 456 *hmac = DNS_TSIG_HMACSHA1_NAME; 457 result = isc_parse_uint16(&digestbits, &buf[10], 10); 458 if (result != ISC_R_SUCCESS || digestbits > 160) 459 fatal("digest-bits out of range [0..160]"); 460 digestbits = (digestbits +7) & ~0x7U; 461 } else if (strcasecmp(buf, "hmac-sha224") == 0) { 462 *hmac = DNS_TSIG_HMACSHA224_NAME; 463 } else if (strncasecmp(buf, "hmac-sha224-", 12) == 0) { 464 *hmac = DNS_TSIG_HMACSHA224_NAME; 465 result = isc_parse_uint16(&digestbits, &buf[12], 10); 466 if (result != ISC_R_SUCCESS || digestbits > 224) 467 fatal("digest-bits out of range [0..224]"); 468 digestbits = (digestbits +7) & ~0x7U; 469 } else if (strcasecmp(buf, "hmac-sha256") == 0) { 470 *hmac = DNS_TSIG_HMACSHA256_NAME; 471 } else if (strncasecmp(buf, "hmac-sha256-", 12) == 0) { 472 *hmac = DNS_TSIG_HMACSHA256_NAME; 473 result = isc_parse_uint16(&digestbits, &buf[12], 10); 474 if (result != ISC_R_SUCCESS || digestbits > 256) 475 fatal("digest-bits out of range [0..256]"); 476 digestbits = (digestbits +7) & ~0x7U; 477 } else if (strcasecmp(buf, "hmac-sha384") == 0) { 478 *hmac = DNS_TSIG_HMACSHA384_NAME; 479 } else if (strncasecmp(buf, "hmac-sha384-", 12) == 0) { 480 *hmac = DNS_TSIG_HMACSHA384_NAME; 481 result = isc_parse_uint16(&digestbits, &buf[12], 10); 482 if (result != ISC_R_SUCCESS || digestbits > 384) 483 fatal("digest-bits out of range [0..384]"); 484 digestbits = (digestbits +7) & ~0x7U; 485 } else if (strcasecmp(buf, "hmac-sha512") == 0) { 486 *hmac = DNS_TSIG_HMACSHA512_NAME; 487 } else if (strncasecmp(buf, "hmac-sha512-", 12) == 0) { 488 *hmac = DNS_TSIG_HMACSHA512_NAME; 489 result = isc_parse_uint16(&digestbits, &buf[12], 10); 490 if (result != ISC_R_SUCCESS || digestbits > 512) 491 fatal("digest-bits out of range [0..512]"); 492 digestbits = (digestbits +7) & ~0x7U; 493 } else 494 fatal("unknown key type '%s'", buf); 495 return (digestbits); 496} 497 498static int 499basenamelen(const char *file) { 500 int len = strlen(file); 501 502 if (len > 1 && file[len - 1] == '.') 503 len -= 1; 504 else if (len > 8 && strcmp(file + len - 8, ".private") == 0) 505 len -= 8; 506 else if (len > 4 && strcmp(file + len - 4, ".key") == 0) 507 len -= 4; 508 return (len); 509} 510 511static void 512setup_keystr(void) { 513 unsigned char *secret = NULL; 514 int secretlen; 515 isc_buffer_t secretbuf; 516 isc_result_t result; 517 isc_buffer_t keynamesrc; 518 char *secretstr; 519 char *s, *n; 520 dns_fixedname_t fkeyname; 521 dns_name_t *keyname; 522 char *name; 523 dns_name_t *hmacname = NULL; 524 isc_uint16_t digestbits = 0; 525 526 dns_fixedname_init(&fkeyname); 527 keyname = dns_fixedname_name(&fkeyname); 528 529 debug("Creating key..."); 530 531 s = strchr(keystr, ':'); 532 if (s == NULL || s == keystr || s[1] == 0) 533 fatal("key option must specify [hmac:]keyname:secret"); 534 secretstr = s + 1; 535 n = strchr(secretstr, ':'); 536 if (n != NULL) { 537 if (n == secretstr || n[1] == 0) 538 fatal("key option must specify [hmac:]keyname:secret"); 539 name = secretstr; 540 secretstr = n + 1; 541 digestbits = parse_hmac(&hmacname, keystr, s - keystr); 542 } else { 543 hmacname = DNS_TSIG_HMACMD5_NAME; 544 name = keystr; 545 n = s; 546 } 547 548 isc_buffer_init(&keynamesrc, name, n - name); 549 isc_buffer_add(&keynamesrc, n - name); 550 551 debug("namefromtext"); 552 result = dns_name_fromtext(keyname, &keynamesrc, dns_rootname, 0, NULL); 553 check_result(result, "dns_name_fromtext"); 554 555 secretlen = strlen(secretstr) * 3 / 4; 556 secret = isc_mem_allocate(mctx, secretlen); 557 if (secret == NULL) 558 fatal("out of memory"); 559 560 isc_buffer_init(&secretbuf, secret, secretlen); 561 result = isc_base64_decodestring(secretstr, &secretbuf); 562 if (result != ISC_R_SUCCESS) { 563 fprintf(stderr, "could not create key from %s: %s\n", 564 keystr, isc_result_totext(result)); 565 goto failure; 566 } 567 568 secretlen = isc_buffer_usedlength(&secretbuf); 569 570 debug("keycreate"); 571 result = dns_tsigkey_create(keyname, hmacname, secret, secretlen, 572 ISC_FALSE, NULL, 0, 0, mctx, NULL, 573 &tsigkey); 574 if (result != ISC_R_SUCCESS) 575 fprintf(stderr, "could not create key from %s: %s\n", 576 keystr, dns_result_totext(result)); 577 else 578 dst_key_setbits(tsigkey->key, digestbits); 579 failure: 580 if (secret != NULL) 581 isc_mem_free(mctx, secret); 582} 583 584/* 585 * Get a key from a named.conf format keyfile 586 */ 587static isc_result_t 588read_sessionkey(isc_mem_t *mctx, isc_log_t *lctx) { 589 cfg_parser_t *pctx = NULL; 590 cfg_obj_t *sessionkey = NULL; 591 const cfg_obj_t *key = NULL; 592 const cfg_obj_t *secretobj = NULL; 593 const cfg_obj_t *algorithmobj = NULL; 594 const char *keyname; 595 const char *secretstr; 596 const char *algorithm; 597 isc_result_t result; 598 int len; 599 600 if (! isc_file_exists(keyfile)) 601 return (ISC_R_FILENOTFOUND); 602 603 result = cfg_parser_create(mctx, lctx, &pctx); 604 if (result != ISC_R_SUCCESS) 605 goto cleanup; 606 607 result = cfg_parse_file(pctx, keyfile, &cfg_type_sessionkey, 608 &sessionkey); 609 if (result != ISC_R_SUCCESS) 610 goto cleanup; 611 612 result = cfg_map_get(sessionkey, "key", &key); 613 if (result != ISC_R_SUCCESS) 614 goto cleanup; 615 616 (void) cfg_map_get(key, "secret", &secretobj); 617 (void) cfg_map_get(key, "algorithm", &algorithmobj); 618 if (secretobj == NULL || algorithmobj == NULL) 619 fatal("key must have algorithm and secret"); 620 621 keyname = cfg_obj_asstring(cfg_map_getname(key)); 622 secretstr = cfg_obj_asstring(secretobj); 623 algorithm = cfg_obj_asstring(algorithmobj); 624 625 len = strlen(algorithm) + strlen(keyname) + strlen(secretstr) + 3; 626 keystr = isc_mem_allocate(mctx, len); 627 snprintf(keystr, len, "%s:%s:%s", algorithm, keyname, secretstr); 628 setup_keystr(); 629 630 cleanup: 631 if (pctx != NULL) { 632 if (sessionkey != NULL) 633 cfg_obj_destroy(pctx, &sessionkey); 634 cfg_parser_destroy(&pctx); 635 } 636 637 if (keystr != NULL) 638 isc_mem_free(mctx, keystr); 639 640 return (result); 641} 642 643static void 644setup_keyfile(isc_mem_t *mctx, isc_log_t *lctx) { 645 dst_key_t *dstkey = NULL; 646 isc_result_t result; 647 dns_name_t *hmacname = NULL; 648 649 debug("Creating key..."); 650 651 if (sig0key != NULL) 652 dst_key_free(&sig0key); 653 654 /* Try reading the key from a K* pair */ 655 result = dst_key_fromnamedfile(keyfile, NULL, 656 DST_TYPE_PRIVATE | DST_TYPE_KEY, mctx, 657 &dstkey); 658 659 /* If that didn't work, try reading it as a session.key keyfile */ 660 if (result != ISC_R_SUCCESS) { 661 result = read_sessionkey(mctx, lctx); 662 if (result == ISC_R_SUCCESS) 663 return; 664 } 665 666 if (result != ISC_R_SUCCESS) { 667 fprintf(stderr, "could not read key from %.*s.{private,key}: " 668 "%s\n", basenamelen(keyfile), keyfile, 669 isc_result_totext(result)); 670 return; 671 } 672 673 switch (dst_key_alg(dstkey)) { 674 case DST_ALG_HMACMD5: 675 hmacname = DNS_TSIG_HMACMD5_NAME; 676 break; 677 case DST_ALG_HMACSHA1: 678 hmacname = DNS_TSIG_HMACSHA1_NAME; 679 break; 680 case DST_ALG_HMACSHA224: 681 hmacname = DNS_TSIG_HMACSHA224_NAME; 682 break; 683 case DST_ALG_HMACSHA256: 684 hmacname = DNS_TSIG_HMACSHA256_NAME; 685 break; 686 case DST_ALG_HMACSHA384: 687 hmacname = DNS_TSIG_HMACSHA384_NAME; 688 break; 689 case DST_ALG_HMACSHA512: 690 hmacname = DNS_TSIG_HMACSHA512_NAME; 691 break; 692 } 693 if (hmacname != NULL) { 694 result = dns_tsigkey_createfromkey(dst_key_name(dstkey), 695 hmacname, dstkey, ISC_FALSE, 696 NULL, 0, 0, mctx, NULL, 697 &tsigkey); 698 dst_key_free(&dstkey); 699 if (result != ISC_R_SUCCESS) { 700 fprintf(stderr, "could not create key from %s: %s\n", 701 keyfile, isc_result_totext(result)); 702 return; 703 } 704 } else { 705 dst_key_attach(dstkey, &sig0key); 706 dst_key_free(&dstkey); 707 } 708} 709 710static void 711doshutdown(void) { 712 isc_task_detach(&global_task); 713 714 if (userserver != NULL) 715 isc_mem_put(mctx, userserver, sizeof(isc_sockaddr_t)); 716 717 if (localaddr != NULL) 718 isc_mem_put(mctx, localaddr, sizeof(isc_sockaddr_t)); 719 720 if (tsigkey != NULL) { 721 ddebug("Freeing TSIG key"); 722 dns_tsigkey_detach(&tsigkey); 723 } 724 725 if (sig0key != NULL) { 726 ddebug("Freeing SIG(0) key"); 727 dst_key_free(&sig0key); 728 } 729 730 if (updatemsg != NULL) 731 dns_message_destroy(&updatemsg); 732 733 if (is_dst_up) { 734 ddebug("Destroy DST lib"); 735 dst_lib_destroy(); 736 is_dst_up = ISC_FALSE; 737 } 738 739 cleanup_entropy(&entropy); 740 741 lwres_conf_clear(lwctx); 742 lwres_context_destroy(&lwctx); 743 744 isc_mem_put(mctx, servers, ns_total * sizeof(isc_sockaddr_t)); 745 746 ddebug("Destroying request manager"); 747 dns_requestmgr_detach(&requestmgr); 748 749 ddebug("Freeing the dispatchers"); 750 if (have_ipv4) 751 dns_dispatch_detach(&dispatchv4); 752 if (have_ipv6) 753 dns_dispatch_detach(&dispatchv6); 754 755 ddebug("Shutting down dispatch manager"); 756 dns_dispatchmgr_destroy(&dispatchmgr); 757 758} 759 760static void 761maybeshutdown(void) { 762 ddebug("Shutting down request manager"); 763 dns_requestmgr_shutdown(requestmgr); 764 765 if (requests != 0) 766 return; 767 768 doshutdown(); 769} 770 771static void 772shutdown_program(isc_task_t *task, isc_event_t *event) { 773 REQUIRE(task == global_task); 774 UNUSED(task); 775 776 ddebug("shutdown_program()"); 777 isc_event_free(&event); 778 779 shuttingdown = ISC_TRUE; 780 maybeshutdown(); 781} 782 783static void 784setup_system(void) { 785 isc_result_t result; 786 isc_sockaddr_t bind_any, bind_any6; 787 lwres_result_t lwresult; 788 unsigned int attrs, attrmask; 789 int i; 790 isc_logconfig_t *logconfig = NULL; 791 792 ddebug("setup_system()"); 793 794 dns_result_register(); 795 796 result = isc_net_probeipv4(); 797 if (result == ISC_R_SUCCESS) 798 have_ipv4 = ISC_TRUE; 799 800 result = isc_net_probeipv6(); 801 if (result == ISC_R_SUCCESS) 802 have_ipv6 = ISC_TRUE; 803 804 if (!have_ipv4 && !have_ipv6) 805 fatal("could not find either IPv4 or IPv6"); 806 807 result = isc_log_create(mctx, &lctx, &logconfig); 808 check_result(result, "isc_log_create"); 809 810 isc_log_setcontext(lctx); 811 dns_log_init(lctx); 812 dns_log_setcontext(lctx); 813 814 result = isc_log_usechannel(logconfig, "default_debug", NULL, NULL); 815 check_result(result, "isc_log_usechannel"); 816 817 isc_log_setdebuglevel(lctx, logdebuglevel); 818 819 lwresult = lwres_context_create(&lwctx, mctx, mem_alloc, mem_free, 1); 820 if (lwresult != LWRES_R_SUCCESS) 821 fatal("lwres_context_create failed"); 822 823 (void)lwres_conf_parse(lwctx, RESOLV_CONF); 824 lwconf = lwres_conf_get(lwctx); 825 826 ns_total = lwconf->nsnext; 827 if (ns_total <= 0) { 828 /* No name servers in resolv.conf; default to loopback. */ 829 struct in_addr localhost; 830 ns_total = 1; 831 servers = isc_mem_get(mctx, ns_total * sizeof(isc_sockaddr_t)); 832 if (servers == NULL) 833 fatal("out of memory"); 834 localhost.s_addr = htonl(INADDR_LOOPBACK); 835 isc_sockaddr_fromin(&servers[0], &localhost, dnsport); 836 } else { 837 servers = isc_mem_get(mctx, ns_total * sizeof(isc_sockaddr_t)); 838 if (servers == NULL) 839 fatal("out of memory"); 840 for (i = 0; i < ns_total; i++) { 841 if (lwconf->nameservers[i].family == LWRES_ADDRTYPE_V4) { 842 struct in_addr in4; 843 memcpy(&in4, lwconf->nameservers[i].address, 4); 844 isc_sockaddr_fromin(&servers[i], &in4, dnsport); 845 } else { 846 struct in6_addr in6; 847 memcpy(&in6, lwconf->nameservers[i].address, 16); 848 isc_sockaddr_fromin6(&servers[i], &in6, 849 dnsport); 850 } 851 } 852 } 853 854 setup_entropy(mctx, NULL, &entropy); 855 856 result = isc_hash_create(mctx, entropy, DNS_NAME_MAXWIRE); 857 check_result(result, "isc_hash_create"); 858 isc_hash_init(); 859 860 result = dns_dispatchmgr_create(mctx, entropy, &dispatchmgr); 861 check_result(result, "dns_dispatchmgr_create"); 862 863 result = isc_socketmgr_create(mctx, &socketmgr); 864 check_result(result, "dns_socketmgr_create"); 865 866 result = isc_timermgr_create(mctx, &timermgr); 867 check_result(result, "dns_timermgr_create"); 868 869 result = isc_taskmgr_create(mctx, 1, 0, &taskmgr); 870 check_result(result, "isc_taskmgr_create"); 871 872 result = isc_task_create(taskmgr, 0, &global_task); 873 check_result(result, "isc_task_create"); 874 875 result = isc_task_onshutdown(global_task, shutdown_program, NULL); 876 check_result(result, "isc_task_onshutdown"); 877 878 result = dst_lib_init(mctx, entropy, 0); 879 check_result(result, "dst_lib_init"); 880 is_dst_up = ISC_TRUE; 881 882 attrmask = DNS_DISPATCHATTR_UDP | DNS_DISPATCHATTR_TCP; 883 attrmask |= DNS_DISPATCHATTR_IPV4 | DNS_DISPATCHATTR_IPV6; 884 885 if (have_ipv6) { 886 attrs = DNS_DISPATCHATTR_UDP; 887 attrs |= DNS_DISPATCHATTR_MAKEQUERY; 888 attrs |= DNS_DISPATCHATTR_IPV6; 889 isc_sockaddr_any6(&bind_any6); 890 result = dns_dispatch_getudp(dispatchmgr, socketmgr, taskmgr, 891 &bind_any6, PACKETSIZE, 892 4, 2, 3, 5, 893 attrs, attrmask, &dispatchv6); 894 check_result(result, "dns_dispatch_getudp (v6)"); 895 } 896 897 if (have_ipv4) { 898 attrs = DNS_DISPATCHATTR_UDP; 899 attrs |= DNS_DISPATCHATTR_MAKEQUERY; 900 attrs |= DNS_DISPATCHATTR_IPV4; 901 isc_sockaddr_any(&bind_any); 902 result = dns_dispatch_getudp(dispatchmgr, socketmgr, taskmgr, 903 &bind_any, PACKETSIZE, 904 4, 2, 3, 5, 905 attrs, attrmask, &dispatchv4); 906 check_result(result, "dns_dispatch_getudp (v4)"); 907 } 908 909 result = dns_requestmgr_create(mctx, timermgr, 910 socketmgr, taskmgr, dispatchmgr, 911 dispatchv4, dispatchv6, &requestmgr); 912 check_result(result, "dns_requestmgr_create"); 913 914 if (keystr != NULL) 915 setup_keystr(); 916 else if (local_only) { 917 result = read_sessionkey(mctx, lctx); 918 if (result != ISC_R_SUCCESS) 919 fatal("can't read key from %s: %s\n", 920 keyfile, isc_result_totext(result)); 921 } else if (keyfile != NULL) 922 setup_keyfile(mctx, lctx); 923} 924 925static void 926get_address(char *host, in_port_t port, isc_sockaddr_t *sockaddr) { 927 int count; 928 isc_result_t result; 929 930 isc_app_block(); 931 result = bind9_getaddresses(host, port, sockaddr, 1, &count); 932 isc_app_unblock(); 933 if (result != ISC_R_SUCCESS) 934 fatal("couldn't get address for '%s': %s", 935 host, isc_result_totext(result)); 936 INSIST(count == 1); 937} 938 939#define PARSE_ARGS_FMT "dDML:y:ghlovk:p:rR::t:u:" 940 941static void 942pre_parse_args(int argc, char **argv) { 943 int ch; 944 945 while ((ch = isc_commandline_parse(argc, argv, PARSE_ARGS_FMT)) != -1) { 946 switch (ch) { 947 case 'M': /* was -dm */ 948 debugging = ISC_TRUE; 949 ddebugging = ISC_TRUE; 950 memdebugging = ISC_TRUE; 951 isc_mem_debugging = ISC_MEM_DEBUGTRACE | 952 ISC_MEM_DEBUGRECORD; 953 break; 954 955 case '?': 956 case 'h': 957 if (isc_commandline_option != '?') 958 fprintf(stderr, "%s: invalid argument -%c\n", 959 argv[0], isc_commandline_option); 960 fprintf(stderr, "usage: nsupdate [-dD] [-L level] [-l]" 961 "[-g | -o | -y keyname:secret | -k keyfile] " 962 "[-v] [filename]\n"); 963 exit(1); 964 965 default: 966 break; 967 } 968 } 969 isc_commandline_reset = ISC_TRUE; 970 isc_commandline_index = 1; 971} 972 973static void 974parse_args(int argc, char **argv, isc_mem_t *mctx, isc_entropy_t **ectx) { 975 int ch; 976 isc_uint32_t i; 977 isc_result_t result; 978 979 debug("parse_args"); 980 while ((ch = isc_commandline_parse(argc, argv, PARSE_ARGS_FMT)) != -1) { 981 switch (ch) { 982 case 'd': 983 debugging = ISC_TRUE; 984 break; 985 case 'D': /* was -dd */ 986 debugging = ISC_TRUE; 987 ddebugging = ISC_TRUE; 988 break; 989 case 'M': 990 break; 991 case 'l': 992 local_only = ISC_TRUE; 993 break; 994 case 'L': 995 result = isc_parse_uint32(&i, isc_commandline_argument, 996 10); 997 if (result != ISC_R_SUCCESS) { 998 fprintf(stderr, "bad library debug value " 999 "'%s'\n", isc_commandline_argument); 1000 exit(1); 1001 } 1002 logdebuglevel = i; 1003 break; 1004 case 'y': 1005 keystr = isc_commandline_argument; 1006 break; 1007 case 'v': 1008 usevc = ISC_TRUE; 1009 break; 1010 case 'k': 1011 keyfile = isc_commandline_argument; 1012 break; 1013 case 'g': 1014 usegsstsig = ISC_TRUE; 1015 use_win2k_gsstsig = ISC_FALSE; 1016 break; 1017 case 'o': 1018 usegsstsig = ISC_TRUE; 1019 use_win2k_gsstsig = ISC_TRUE; 1020 break; 1021 case 'p': 1022 result = isc_parse_uint16(&dnsport, 1023 isc_commandline_argument, 10); 1024 if (result != ISC_R_SUCCESS) { 1025 fprintf(stderr, "bad port number " 1026 "'%s'\n", isc_commandline_argument); 1027 exit(1); 1028 } 1029 break; 1030 case 't': 1031 result = isc_parse_uint32(&timeout, 1032 isc_commandline_argument, 10); 1033 if (result != ISC_R_SUCCESS) { 1034 fprintf(stderr, "bad timeout '%s'\n", isc_commandline_argument); 1035 exit(1); 1036 } 1037 if (timeout == 0) 1038 timeout = UINT_MAX; 1039 break; 1040 case 'u': 1041 result = isc_parse_uint32(&udp_timeout, 1042 isc_commandline_argument, 10); 1043 if (result != ISC_R_SUCCESS) { 1044 fprintf(stderr, "bad udp timeout '%s'\n", isc_commandline_argument); 1045 exit(1); 1046 } 1047 if (udp_timeout == 0) 1048 udp_timeout = UINT_MAX; 1049 break; 1050 case 'r': 1051 result = isc_parse_uint32(&udp_retries, 1052 isc_commandline_argument, 10); 1053 if (result != ISC_R_SUCCESS) { 1054 fprintf(stderr, "bad udp retries '%s'\n", isc_commandline_argument); 1055 exit(1); 1056 } 1057 break; 1058 1059 case 'R': 1060 setup_entropy(mctx, isc_commandline_argument, ectx); 1061 break; 1062 1063 default: 1064 fprintf(stderr, "%s: unhandled option: %c\n", 1065 argv[0], isc_commandline_option); 1066 exit(1); 1067 } 1068 } 1069 if (keyfile != NULL && keystr != NULL) { 1070 fprintf(stderr, "%s: cannot specify both -k and -y\n", 1071 argv[0]); 1072 exit(1); 1073 } 1074 1075 if (local_only) { 1076 struct in_addr localhost; 1077 1078 if (keyfile == NULL) 1079 keyfile = SESSION_KEYFILE; 1080 1081 if (userserver == NULL) { 1082 userserver = isc_mem_get(mctx, sizeof(isc_sockaddr_t)); 1083 if (userserver == NULL) 1084 fatal("out of memory"); 1085 } 1086 1087 localhost.s_addr = htonl(INADDR_LOOPBACK); 1088 isc_sockaddr_fromin(userserver, &localhost, dnsport); 1089 } 1090 1091#ifdef GSSAPI 1092 if (usegsstsig && (keyfile != NULL || keystr != NULL)) { 1093 fprintf(stderr, "%s: cannot specify -g with -k or -y\n", 1094 argv[0]); 1095 exit(1); 1096 } 1097#else 1098 if (usegsstsig) { 1099 fprintf(stderr, "%s: cannot specify -g or -o, " \ 1100 "program not linked with GSS API Library\n", 1101 argv[0]); 1102 exit(1); 1103 } 1104#endif 1105 1106 if (argv[isc_commandline_index] != NULL) { 1107 if (strcmp(argv[isc_commandline_index], "-") == 0) { 1108 input = stdin; 1109 } else { 1110 result = isc_stdio_open(argv[isc_commandline_index], 1111 "r", &input); 1112 if (result != ISC_R_SUCCESS) { 1113 fprintf(stderr, "could not open '%s': %s\n", 1114 argv[isc_commandline_index], 1115 isc_result_totext(result)); 1116 exit(1); 1117 } 1118 } 1119 interactive = ISC_FALSE; 1120 } 1121} 1122 1123static isc_uint16_t 1124parse_name(char **cmdlinep, dns_message_t *msg, dns_name_t **namep) { 1125 isc_result_t result; 1126 char *word; 1127 isc_buffer_t *namebuf = NULL; 1128 isc_buffer_t source; 1129 1130 word = nsu_strsep(cmdlinep, " \t\r\n"); 1131 if (word == NULL || *word == 0) { 1132 fprintf(stderr, "could not read owner name\n"); 1133 return (STATUS_SYNTAX); 1134 } 1135 1136 result = dns_message_gettempname(msg, namep); 1137 check_result(result, "dns_message_gettempname"); 1138 result = isc_buffer_allocate(mctx, &namebuf, DNS_NAME_MAXWIRE); 1139 check_result(result, "isc_buffer_allocate"); 1140 dns_name_init(*namep, NULL); 1141 dns_name_setbuffer(*namep, namebuf); 1142 dns_message_takebuffer(msg, &namebuf); 1143 isc_buffer_init(&source, word, strlen(word)); 1144 isc_buffer_add(&source, strlen(word)); 1145 result = dns_name_fromtext(*namep, &source, dns_rootname, 0, NULL); 1146 check_result(result, "dns_name_fromtext"); 1147 isc_buffer_invalidate(&source); 1148 return (STATUS_MORE); 1149} 1150 1151static isc_uint16_t 1152parse_rdata(char **cmdlinep, dns_rdataclass_t rdataclass, 1153 dns_rdatatype_t rdatatype, dns_message_t *msg, 1154 dns_rdata_t *rdata) 1155{ 1156 char *cmdline = *cmdlinep; 1157 isc_buffer_t source, *buf = NULL, *newbuf = NULL; 1158 isc_region_t r; 1159 isc_lex_t *lex = NULL; 1160 dns_rdatacallbacks_t callbacks; 1161 isc_result_t result; 1162 1163 if (cmdline == NULL) { 1164 rdata->flags = DNS_RDATA_UPDATE; 1165 return (STATUS_MORE); 1166 } 1167 1168 while (*cmdline != 0 && isspace((unsigned char)*cmdline)) 1169 cmdline++; 1170 1171 if (*cmdline != 0) { 1172 dns_rdatacallbacks_init(&callbacks); 1173 result = isc_lex_create(mctx, strlen(cmdline), &lex); 1174 check_result(result, "isc_lex_create"); 1175 isc_buffer_init(&source, cmdline, strlen(cmdline)); 1176 isc_buffer_add(&source, strlen(cmdline)); 1177 result = isc_lex_openbuffer(lex, &source); 1178 check_result(result, "isc_lex_openbuffer"); 1179 result = isc_buffer_allocate(mctx, &buf, MAXWIRE); 1180 check_result(result, "isc_buffer_allocate"); 1181 result = dns_rdata_fromtext(NULL, rdataclass, rdatatype, lex, 1182 dns_rootname, 0, mctx, buf, 1183 &callbacks); 1184 isc_lex_destroy(&lex); 1185 if (result == ISC_R_SUCCESS) { 1186 isc_buffer_usedregion(buf, &r); 1187 result = isc_buffer_allocate(mctx, &newbuf, r.length); 1188 check_result(result, "isc_buffer_allocate"); 1189 isc_buffer_putmem(newbuf, r.base, r.length); 1190 isc_buffer_usedregion(newbuf, &r); 1191 dns_rdata_fromregion(rdata, rdataclass, rdatatype, &r); 1192 isc_buffer_free(&buf); 1193 dns_message_takebuffer(msg, &newbuf); 1194 } else { 1195 fprintf(stderr, "invalid rdata format: %s\n", 1196 isc_result_totext(result)); 1197 isc_buffer_free(&buf); 1198 return (STATUS_SYNTAX); 1199 } 1200 } else { 1201 rdata->flags = DNS_RDATA_UPDATE; 1202 } 1203 *cmdlinep = cmdline; 1204 return (STATUS_MORE); 1205} 1206 1207static isc_uint16_t 1208make_prereq(char *cmdline, isc_boolean_t ispositive, isc_boolean_t isrrset) { 1209 isc_result_t result; 1210 char *word; 1211 dns_name_t *name = NULL; 1212 isc_textregion_t region; 1213 dns_rdataset_t *rdataset = NULL; 1214 dns_rdatalist_t *rdatalist = NULL; 1215 dns_rdataclass_t rdataclass; 1216 dns_rdatatype_t rdatatype; 1217 dns_rdata_t *rdata = NULL; 1218 isc_uint16_t retval; 1219 1220 ddebug("make_prereq()"); 1221 1222 /* 1223 * Read the owner name 1224 */ 1225 retval = parse_name(&cmdline, updatemsg, &name); 1226 if (retval != STATUS_MORE) 1227 return (retval); 1228 1229 /* 1230 * If this is an rrset prereq, read the class or type. 1231 */ 1232 if (isrrset) { 1233 word = nsu_strsep(&cmdline, " \t\r\n"); 1234 if (word == NULL || *word == 0) { 1235 fprintf(stderr, "could not read class or type\n"); 1236 goto failure; 1237 } 1238 region.base = word; 1239 region.length = strlen(word); 1240 result = dns_rdataclass_fromtext(&rdataclass, ®ion); 1241 if (result == ISC_R_SUCCESS) { 1242 if (!setzoneclass(rdataclass)) { 1243 fprintf(stderr, "class mismatch: %s\n", word); 1244 goto failure; 1245 } 1246 /* 1247 * Now read the type. 1248 */ 1249 word = nsu_strsep(&cmdline, " \t\r\n"); 1250 if (word == NULL || *word == 0) { 1251 fprintf(stderr, "could not read type\n"); 1252 goto failure; 1253 } 1254 region.base = word; 1255 region.length = strlen(word); 1256 result = dns_rdatatype_fromtext(&rdatatype, ®ion); 1257 if (result != ISC_R_SUCCESS) { 1258 fprintf(stderr, "invalid type: %s\n", word); 1259 goto failure; 1260 } 1261 } else { 1262 rdataclass = getzoneclass(); 1263 result = dns_rdatatype_fromtext(&rdatatype, ®ion); 1264 if (result != ISC_R_SUCCESS) { 1265 fprintf(stderr, "invalid type: %s\n", word); 1266 goto failure; 1267 } 1268 } 1269 } else 1270 rdatatype = dns_rdatatype_any; 1271 1272 result = dns_message_gettemprdata(updatemsg, &rdata); 1273 check_result(result, "dns_message_gettemprdata"); 1274 1275 dns_rdata_init(rdata); 1276 1277 if (isrrset && ispositive) { 1278 retval = parse_rdata(&cmdline, rdataclass, rdatatype, 1279 updatemsg, rdata); 1280 if (retval != STATUS_MORE) 1281 goto failure; 1282 } else 1283 rdata->flags = DNS_RDATA_UPDATE; 1284 1285 result = dns_message_gettemprdatalist(updatemsg, &rdatalist); 1286 check_result(result, "dns_message_gettemprdatalist"); 1287 result = dns_message_gettemprdataset(updatemsg, &rdataset); 1288 check_result(result, "dns_message_gettemprdataset"); 1289 dns_rdatalist_init(rdatalist); 1290 rdatalist->type = rdatatype; 1291 if (ispositive) { 1292 if (isrrset && rdata->data != NULL) 1293 rdatalist->rdclass = rdataclass; 1294 else 1295 rdatalist->rdclass = dns_rdataclass_any; 1296 } else 1297 rdatalist->rdclass = dns_rdataclass_none; 1298 rdatalist->covers = 0; 1299 rdatalist->ttl = 0; 1300 rdata->rdclass = rdatalist->rdclass; 1301 rdata->type = rdatatype; 1302 ISC_LIST_INIT(rdatalist->rdata); 1303 ISC_LIST_APPEND(rdatalist->rdata, rdata, link); 1304 dns_rdataset_init(rdataset); 1305 dns_rdatalist_tordataset(rdatalist, rdataset); 1306 ISC_LIST_INIT(name->list); 1307 ISC_LIST_APPEND(name->list, rdataset, link); 1308 dns_message_addname(updatemsg, name, DNS_SECTION_PREREQUISITE); 1309 return (STATUS_MORE); 1310 1311 failure: 1312 if (name != NULL) 1313 dns_message_puttempname(updatemsg, &name); 1314 return (STATUS_SYNTAX); 1315} 1316 1317static isc_uint16_t 1318evaluate_prereq(char *cmdline) { 1319 char *word; 1320 isc_boolean_t ispositive, isrrset; 1321 1322 ddebug("evaluate_prereq()"); 1323 word = nsu_strsep(&cmdline, " \t\r\n"); 1324 if (word == NULL || *word == 0) { 1325 fprintf(stderr, "could not read operation code\n"); 1326 return (STATUS_SYNTAX); 1327 } 1328 if (strcasecmp(word, "nxdomain") == 0) { 1329 ispositive = ISC_FALSE; 1330 isrrset = ISC_FALSE; 1331 } else if (strcasecmp(word, "yxdomain") == 0) { 1332 ispositive = ISC_TRUE; 1333 isrrset = ISC_FALSE; 1334 } else if (strcasecmp(word, "nxrrset") == 0) { 1335 ispositive = ISC_FALSE; 1336 isrrset = ISC_TRUE; 1337 } else if (strcasecmp(word, "yxrrset") == 0) { 1338 ispositive = ISC_TRUE; 1339 isrrset = ISC_TRUE; 1340 } else { 1341 fprintf(stderr, "incorrect operation code: %s\n", word); 1342 return (STATUS_SYNTAX); 1343 } 1344 return (make_prereq(cmdline, ispositive, isrrset)); 1345} 1346 1347static isc_uint16_t 1348evaluate_server(char *cmdline) { 1349 char *word, *server; 1350 long port; 1351 1352 if (local_only) { 1353 fprintf(stderr, "cannot reset server in localhost-only mode\n"); 1354 return (STATUS_SYNTAX); 1355 } 1356 1357 word = nsu_strsep(&cmdline, " \t\r\n"); 1358 if (word == NULL || *word == 0) { 1359 fprintf(stderr, "could not read server name\n"); 1360 return (STATUS_SYNTAX); 1361 } 1362 server = word; 1363 1364 word = nsu_strsep(&cmdline, " \t\r\n"); 1365 if (word == NULL || *word == 0) 1366 port = dnsport; 1367 else { 1368 char *endp; 1369 port = strtol(word, &endp, 10); 1370 if (*endp != 0) { 1371 fprintf(stderr, "port '%s' is not numeric\n", word); 1372 return (STATUS_SYNTAX); 1373 } else if (port < 1 || port > 65535) { 1374 fprintf(stderr, "port '%s' is out of range " 1375 "(1 to 65535)\n", word); 1376 return (STATUS_SYNTAX); 1377 } 1378 } 1379 1380 if (userserver == NULL) { 1381 userserver = isc_mem_get(mctx, sizeof(isc_sockaddr_t)); 1382 if (userserver == NULL) 1383 fatal("out of memory"); 1384 } 1385 1386 get_address(server, (in_port_t)port, userserver); 1387 1388 return (STATUS_MORE); 1389} 1390 1391static isc_uint16_t 1392evaluate_local(char *cmdline) { 1393 char *word, *local; 1394 long port; 1395 struct in_addr in4; 1396 struct in6_addr in6; 1397 1398 word = nsu_strsep(&cmdline, " \t\r\n"); 1399 if (word == NULL || *word == 0) { 1400 fprintf(stderr, "could not read server name\n"); 1401 return (STATUS_SYNTAX); 1402 } 1403 local = word; 1404 1405 word = nsu_strsep(&cmdline, " \t\r\n"); 1406 if (word == NULL || *word == 0) 1407 port = 0; 1408 else { 1409 char *endp; 1410 port = strtol(word, &endp, 10); 1411 if (*endp != 0) { 1412 fprintf(stderr, "port '%s' is not numeric\n", word); 1413 return (STATUS_SYNTAX); 1414 } else if (port < 1 || port > 65535) { 1415 fprintf(stderr, "port '%s' is out of range " 1416 "(1 to 65535)\n", word); 1417 return (STATUS_SYNTAX); 1418 } 1419 } 1420 1421 if (localaddr == NULL) { 1422 localaddr = isc_mem_get(mctx, sizeof(isc_sockaddr_t)); 1423 if (localaddr == NULL) 1424 fatal("out of memory"); 1425 } 1426 1427 if (have_ipv6 && inet_pton(AF_INET6, local, &in6) == 1) 1428 isc_sockaddr_fromin6(localaddr, &in6, (in_port_t)port); 1429 else if (have_ipv4 && inet_pton(AF_INET, local, &in4) == 1) 1430 isc_sockaddr_fromin(localaddr, &in4, (in_port_t)port); 1431 else { 1432 fprintf(stderr, "invalid address %s", local); 1433 return (STATUS_SYNTAX); 1434 } 1435 1436 return (STATUS_MORE); 1437} 1438 1439static isc_uint16_t 1440evaluate_key(char *cmdline) { 1441 char *namestr; 1442 char *secretstr; 1443 isc_buffer_t b; 1444 isc_result_t result; 1445 dns_fixedname_t fkeyname; 1446 dns_name_t *keyname; 1447 int secretlen; 1448 unsigned char *secret = NULL; 1449 isc_buffer_t secretbuf; 1450 dns_name_t *hmacname = NULL; 1451 isc_uint16_t digestbits = 0; 1452 char *n; 1453 1454 namestr = nsu_strsep(&cmdline, " \t\r\n"); 1455 if (namestr == NULL || *namestr == 0) { 1456 fprintf(stderr, "could not read key name\n"); 1457 return (STATUS_SYNTAX); 1458 } 1459 1460 dns_fixedname_init(&fkeyname); 1461 keyname = dns_fixedname_name(&fkeyname); 1462 1463 n = strchr(namestr, ':'); 1464 if (n != NULL) { 1465 digestbits = parse_hmac(&hmacname, namestr, n - namestr); 1466 namestr = n + 1; 1467 } else 1468 hmacname = DNS_TSIG_HMACMD5_NAME; 1469 1470 isc_buffer_init(&b, namestr, strlen(namestr)); 1471 isc_buffer_add(&b, strlen(namestr)); 1472 result = dns_name_fromtext(keyname, &b, dns_rootname, 0, NULL); 1473 if (result != ISC_R_SUCCESS) { 1474 fprintf(stderr, "could not parse key name\n"); 1475 return (STATUS_SYNTAX); 1476 } 1477 1478 secretstr = nsu_strsep(&cmdline, "\r\n"); 1479 if (secretstr == NULL || *secretstr == 0) { 1480 fprintf(stderr, "could not read key secret\n"); 1481 return (STATUS_SYNTAX); 1482 } 1483 secretlen = strlen(secretstr) * 3 / 4; 1484 secret = isc_mem_allocate(mctx, secretlen); 1485 if (secret == NULL) 1486 fatal("out of memory"); 1487 1488 isc_buffer_init(&secretbuf, secret, secretlen); 1489 result = isc_base64_decodestring(secretstr, &secretbuf); 1490 if (result != ISC_R_SUCCESS) { 1491 fprintf(stderr, "could not create key from %s: %s\n", 1492 secretstr, isc_result_totext(result)); 1493 isc_mem_free(mctx, secret); 1494 return (STATUS_SYNTAX); 1495 } 1496 secretlen = isc_buffer_usedlength(&secretbuf); 1497 1498 if (tsigkey != NULL) 1499 dns_tsigkey_detach(&tsigkey); 1500 result = dns_tsigkey_create(keyname, hmacname, secret, secretlen, 1501 ISC_FALSE, NULL, 0, 0, mctx, NULL, 1502 &tsigkey); 1503 isc_mem_free(mctx, secret); 1504 if (result != ISC_R_SUCCESS) { 1505 fprintf(stderr, "could not create key from %s %s: %s\n", 1506 namestr, secretstr, dns_result_totext(result)); 1507 return (STATUS_SYNTAX); 1508 } 1509 dst_key_setbits(tsigkey->key, digestbits); 1510 return (STATUS_MORE); 1511} 1512 1513static isc_uint16_t 1514evaluate_zone(char *cmdline) { 1515 char *word; 1516 isc_buffer_t b; 1517 isc_result_t result; 1518 1519 word = nsu_strsep(&cmdline, " \t\r\n"); 1520 if (word == NULL || *word == 0) { 1521 fprintf(stderr, "could not read zone name\n"); 1522 return (STATUS_SYNTAX); 1523 } 1524 1525 dns_fixedname_init(&fuserzone); 1526 userzone = dns_fixedname_name(&fuserzone); 1527 isc_buffer_init(&b, word, strlen(word)); 1528 isc_buffer_add(&b, strlen(word)); 1529 result = dns_name_fromtext(userzone, &b, dns_rootname, 0, NULL); 1530 if (result != ISC_R_SUCCESS) { 1531 userzone = NULL; /* Lest it point to an invalid name */ 1532 fprintf(stderr, "could not parse zone name\n"); 1533 return (STATUS_SYNTAX); 1534 } 1535 1536 return (STATUS_MORE); 1537} 1538 1539static isc_uint16_t 1540evaluate_realm(char *cmdline) { 1541#ifdef GSSAPI 1542 char *word; 1543 char buf[1024]; 1544 1545 word = nsu_strsep(&cmdline, " \t\r\n"); 1546 if (word == NULL || *word == 0) { 1547 if (realm != NULL) 1548 isc_mem_free(mctx, realm); 1549 realm = NULL; 1550 return (STATUS_MORE); 1551 } 1552 1553 snprintf(buf, sizeof(buf), "@%s", word); 1554 realm = isc_mem_strdup(mctx, buf); 1555 if (realm == NULL) 1556 fatal("out of memory"); 1557 return (STATUS_MORE); 1558#else 1559 UNUSED(cmdline); 1560 return (STATUS_SYNTAX); 1561#endif 1562} 1563 1564static isc_uint16_t 1565evaluate_ttl(char *cmdline) { 1566 char *word; 1567 isc_result_t result; 1568 isc_uint32_t ttl; 1569 1570 word = nsu_strsep(&cmdline, " \t\r\n"); 1571 if (word == NULL || *word == 0) { 1572 fprintf(stderr, "could not ttl\n"); 1573 return (STATUS_SYNTAX); 1574 } 1575 1576 if (!strcasecmp(word, "none")) { 1577 default_ttl = 0; 1578 default_ttl_set = ISC_FALSE; 1579 return (STATUS_MORE); 1580 } 1581 1582 result = isc_parse_uint32(&ttl, word, 10); 1583 if (result != ISC_R_SUCCESS) 1584 return (STATUS_SYNTAX); 1585 1586 if (ttl > TTL_MAX) { 1587 fprintf(stderr, "ttl '%s' is out of range (0 to %u)\n", 1588 word, TTL_MAX); 1589 return (STATUS_SYNTAX); 1590 } 1591 default_ttl = ttl; 1592 default_ttl_set = ISC_TRUE; 1593 1594 return (STATUS_MORE); 1595} 1596 1597static isc_uint16_t 1598evaluate_class(char *cmdline) { 1599 char *word; 1600 isc_textregion_t r; 1601 isc_result_t result; 1602 dns_rdataclass_t rdclass; 1603 1604 word = nsu_strsep(&cmdline, " \t\r\n"); 1605 if (word == NULL || *word == 0) { 1606 fprintf(stderr, "could not read class name\n"); 1607 return (STATUS_SYNTAX); 1608 } 1609 1610 r.base = word; 1611 r.length = strlen(word); 1612 result = dns_rdataclass_fromtext(&rdclass, &r); 1613 if (result != ISC_R_SUCCESS) { 1614 fprintf(stderr, "could not parse class name: %s\n", word); 1615 return (STATUS_SYNTAX); 1616 } 1617 switch (rdclass) { 1618 case dns_rdataclass_none: 1619 case dns_rdataclass_any: 1620 case dns_rdataclass_reserved0: 1621 fprintf(stderr, "bad default class: %s\n", word); 1622 return (STATUS_SYNTAX); 1623 default: 1624 defaultclass = rdclass; 1625 } 1626 1627 return (STATUS_MORE); 1628} 1629 1630static isc_uint16_t 1631update_addordelete(char *cmdline, isc_boolean_t isdelete) { 1632 isc_result_t result; 1633 dns_name_t *name = NULL; 1634 isc_uint32_t ttl; 1635 char *word; 1636 dns_rdataclass_t rdataclass; 1637 dns_rdatatype_t rdatatype; 1638 dns_rdata_t *rdata = NULL; 1639 dns_rdatalist_t *rdatalist = NULL; 1640 dns_rdataset_t *rdataset = NULL; 1641 isc_textregion_t region; 1642 isc_uint16_t retval; 1643 1644 ddebug("update_addordelete()"); 1645 1646 /* 1647 * Read the owner name. 1648 */ 1649 retval = parse_name(&cmdline, updatemsg, &name); 1650 if (retval != STATUS_MORE) 1651 return (retval); 1652 1653 result = dns_message_gettemprdata(updatemsg, &rdata); 1654 check_result(result, "dns_message_gettemprdata"); 1655 1656 dns_rdata_init(rdata); 1657 1658 /* 1659 * If this is an add, read the TTL and verify that it's in range. 1660 * If it's a delete, ignore a TTL if present (for compatibility). 1661 */ 1662 word = nsu_strsep(&cmdline, " \t\r\n"); 1663 if (word == NULL || *word == 0) { 1664 if (!isdelete) { 1665 fprintf(stderr, "could not read owner ttl\n"); 1666 goto failure; 1667 } 1668 else { 1669 ttl = 0; 1670 rdataclass = dns_rdataclass_any; 1671 rdatatype = dns_rdatatype_any; 1672 rdata->flags = DNS_RDATA_UPDATE; 1673 goto doneparsing; 1674 } 1675 } 1676 result = isc_parse_uint32(&ttl, word, 10); 1677 if (result != ISC_R_SUCCESS) { 1678 if (isdelete) { 1679 ttl = 0; 1680 goto parseclass; 1681 } else if (default_ttl_set) { 1682 ttl = default_ttl; 1683 goto parseclass; 1684 } else { 1685 fprintf(stderr, "ttl '%s': %s\n", word, 1686 isc_result_totext(result)); 1687 goto failure; 1688 } 1689 } 1690 1691 if (isdelete) 1692 ttl = 0; 1693 else if (ttl > TTL_MAX) { 1694 fprintf(stderr, "ttl '%s' is out of range (0 to %u)\n", 1695 word, TTL_MAX); 1696 goto failure; 1697 } 1698 1699 /* 1700 * Read the class or type. 1701 */ 1702 word = nsu_strsep(&cmdline, " \t\r\n"); 1703 parseclass: 1704 if (word == NULL || *word == 0) { 1705 if (isdelete) { 1706 rdataclass = dns_rdataclass_any; 1707 rdatatype = dns_rdatatype_any; 1708 rdata->flags = DNS_RDATA_UPDATE; 1709 goto doneparsing; 1710 } else { 1711 fprintf(stderr, "could not read class or type\n"); 1712 goto failure; 1713 } 1714 } 1715 region.base = word; 1716 region.length = strlen(word); 1717 rdataclass = dns_rdataclass_any; 1718 result = dns_rdataclass_fromtext(&rdataclass, ®ion); 1719 if (result == ISC_R_SUCCESS && rdataclass != dns_rdataclass_any) { 1720 if (!setzoneclass(rdataclass)) { 1721 fprintf(stderr, "class mismatch: %s\n", word); 1722 goto failure; 1723 } 1724 /* 1725 * Now read the type. 1726 */ 1727 word = nsu_strsep(&cmdline, " \t\r\n"); 1728 if (word == NULL || *word == 0) { 1729 if (isdelete) { 1730 rdataclass = dns_rdataclass_any; 1731 rdatatype = dns_rdatatype_any; 1732 rdata->flags = DNS_RDATA_UPDATE; 1733 goto doneparsing; 1734 } else { 1735 fprintf(stderr, "could not read type\n"); 1736 goto failure; 1737 } 1738 } 1739 region.base = word; 1740 region.length = strlen(word); 1741 result = dns_rdatatype_fromtext(&rdatatype, ®ion); 1742 if (result != ISC_R_SUCCESS) { 1743 fprintf(stderr, "'%s' is not a valid type: %s\n", 1744 word, isc_result_totext(result)); 1745 goto failure; 1746 } 1747 } else { 1748 rdataclass = getzoneclass(); 1749 result = dns_rdatatype_fromtext(&rdatatype, ®ion); 1750 if (result != ISC_R_SUCCESS) { 1751 fprintf(stderr, "'%s' is not a valid class or type: " 1752 "%s\n", word, isc_result_totext(result)); 1753 goto failure; 1754 } 1755 } 1756 1757 retval = parse_rdata(&cmdline, rdataclass, rdatatype, updatemsg, 1758 rdata); 1759 if (retval != STATUS_MORE) 1760 goto failure; 1761 1762 if (isdelete) { 1763 if ((rdata->flags & DNS_RDATA_UPDATE) != 0) 1764 rdataclass = dns_rdataclass_any; 1765 else 1766 rdataclass = dns_rdataclass_none; 1767 } else { 1768 if ((rdata->flags & DNS_RDATA_UPDATE) != 0) { 1769 fprintf(stderr, "could not read rdata\n"); 1770 goto failure; 1771 } 1772 } 1773 1774 doneparsing: 1775 1776 result = dns_message_gettemprdatalist(updatemsg, &rdatalist); 1777 check_result(result, "dns_message_gettemprdatalist"); 1778 result = dns_message_gettemprdataset(updatemsg, &rdataset); 1779 check_result(result, "dns_message_gettemprdataset"); 1780 dns_rdatalist_init(rdatalist); 1781 rdatalist->type = rdatatype; 1782 rdatalist->rdclass = rdataclass; 1783 rdatalist->covers = rdatatype; 1784 rdatalist->ttl = (dns_ttl_t)ttl; 1785 ISC_LIST_INIT(rdatalist->rdata); 1786 ISC_LIST_APPEND(rdatalist->rdata, rdata, link); 1787 dns_rdataset_init(rdataset); 1788 dns_rdatalist_tordataset(rdatalist, rdataset); 1789 ISC_LIST_INIT(name->list); 1790 ISC_LIST_APPEND(name->list, rdataset, link); 1791 dns_message_addname(updatemsg, name, DNS_SECTION_UPDATE); 1792 return (STATUS_MORE); 1793 1794 failure: 1795 if (name != NULL) 1796 dns_message_puttempname(updatemsg, &name); 1797 dns_message_puttemprdata(updatemsg, &rdata); 1798 return (STATUS_SYNTAX); 1799} 1800 1801static isc_uint16_t 1802evaluate_update(char *cmdline) { 1803 char *word; 1804 isc_boolean_t isdelete; 1805 1806 ddebug("evaluate_update()"); 1807 word = nsu_strsep(&cmdline, " \t\r\n"); 1808 if (word == NULL || *word == 0) { 1809 fprintf(stderr, "could not read operation code\n"); 1810 return (STATUS_SYNTAX); 1811 } 1812 if (strcasecmp(word, "delete") == 0) 1813 isdelete = ISC_TRUE; 1814 else if (strcasecmp(word, "del") == 0) 1815 isdelete = ISC_TRUE; 1816 else if (strcasecmp(word, "add") == 0) 1817 isdelete = ISC_FALSE; 1818 else { 1819 fprintf(stderr, "incorrect operation code: %s\n", word); 1820 return (STATUS_SYNTAX); 1821 } 1822 return (update_addordelete(cmdline, isdelete)); 1823} 1824 1825static void 1826setzone(dns_name_t *zonename) { 1827 isc_result_t result; 1828 dns_name_t *name = NULL; 1829 dns_rdataset_t *rdataset = NULL; 1830 1831 result = dns_message_firstname(updatemsg, DNS_SECTION_ZONE); 1832 if (result == ISC_R_SUCCESS) { 1833 dns_message_currentname(updatemsg, DNS_SECTION_ZONE, &name); 1834 dns_message_removename(updatemsg, name, DNS_SECTION_ZONE); 1835 for (rdataset = ISC_LIST_HEAD(name->list); 1836 rdataset != NULL; 1837 rdataset = ISC_LIST_HEAD(name->list)) { 1838 ISC_LIST_UNLINK(name->list, rdataset, link); 1839 dns_rdataset_disassociate(rdataset); 1840 dns_message_puttemprdataset(updatemsg, &rdataset); 1841 } 1842 dns_message_puttempname(updatemsg, &name); 1843 } 1844 1845 if (zonename != NULL) { 1846 result = dns_message_gettempname(updatemsg, &name); 1847 check_result(result, "dns_message_gettempname"); 1848 dns_name_init(name, NULL); 1849 dns_name_clone(zonename, name); 1850 result = dns_message_gettemprdataset(updatemsg, &rdataset); 1851 check_result(result, "dns_message_gettemprdataset"); 1852 dns_rdataset_makequestion(rdataset, getzoneclass(), 1853 dns_rdatatype_soa); 1854 ISC_LIST_INIT(name->list); 1855 ISC_LIST_APPEND(name->list, rdataset, link); 1856 dns_message_addname(updatemsg, name, DNS_SECTION_ZONE); 1857 } 1858} 1859 1860static void 1861show_message(FILE *stream, dns_message_t *msg, const char *description) { 1862 isc_result_t result; 1863 isc_buffer_t *buf = NULL; 1864 int bufsz; 1865 1866 ddebug("show_message()"); 1867 1868 setzone(userzone); 1869 1870 bufsz = INITTEXT; 1871 do { 1872 if (bufsz > MAXTEXT) { 1873 fprintf(stderr, "could not allocate large enough " 1874 "buffer to display message\n"); 1875 exit(1); 1876 } 1877 if (buf != NULL) 1878 isc_buffer_free(&buf); 1879 result = isc_buffer_allocate(mctx, &buf, bufsz); 1880 check_result(result, "isc_buffer_allocate"); 1881 result = dns_message_totext(msg, style, 0, buf); 1882 bufsz *= 2; 1883 } while (result == ISC_R_NOSPACE); 1884 if (result != ISC_R_SUCCESS) { 1885 fprintf(stderr, "could not convert message to text format.\n"); 1886 isc_buffer_free(&buf); 1887 return; 1888 } 1889 fprintf(stream, "%s\n%.*s", description, 1890 (int)isc_buffer_usedlength(buf), (char*)isc_buffer_base(buf)); 1891 isc_buffer_free(&buf); 1892} 1893 1894static isc_uint16_t 1895do_next_command(char *cmdline) { 1896 char *word; 1897 1898 ddebug("do_next_command()"); 1899 word = nsu_strsep(&cmdline, " \t\r\n"); 1900 1901 if (word == NULL || *word == 0) 1902 return (STATUS_SEND); 1903 if (word[0] == ';') 1904 return (STATUS_MORE); 1905 if (strcasecmp(word, "quit") == 0) 1906 return (STATUS_QUIT); 1907 if (strcasecmp(word, "prereq") == 0) 1908 return (evaluate_prereq(cmdline)); 1909 if (strcasecmp(word, "nxdomain") == 0) 1910 return (make_prereq(cmdline, ISC_FALSE, ISC_FALSE)); 1911 if (strcasecmp(word, "yxdomain") == 0) 1912 return (make_prereq(cmdline, ISC_TRUE, ISC_FALSE)); 1913 if (strcasecmp(word, "nxrrset") == 0) 1914 return (make_prereq(cmdline, ISC_FALSE, ISC_TRUE)); 1915 if (strcasecmp(word, "yxrrset") == 0) 1916 return (make_prereq(cmdline, ISC_TRUE, ISC_TRUE)); 1917 if (strcasecmp(word, "update") == 0) 1918 return (evaluate_update(cmdline)); 1919 if (strcasecmp(word, "delete") == 0) 1920 return (update_addordelete(cmdline, ISC_TRUE)); 1921 if (strcasecmp(word, "del") == 0) 1922 return (update_addordelete(cmdline, ISC_TRUE)); 1923 if (strcasecmp(word, "add") == 0) 1924 return (update_addordelete(cmdline, ISC_FALSE)); 1925 if (strcasecmp(word, "server") == 0) 1926 return (evaluate_server(cmdline)); 1927 if (strcasecmp(word, "local") == 0) 1928 return (evaluate_local(cmdline)); 1929 if (strcasecmp(word, "zone") == 0) 1930 return (evaluate_zone(cmdline)); 1931 if (strcasecmp(word, "class") == 0) 1932 return (evaluate_class(cmdline)); 1933 if (strcasecmp(word, "send") == 0) 1934 return (STATUS_SEND); 1935 if (strcasecmp(word, "debug") == 0) { 1936 if (debugging) 1937 ddebugging = ISC_TRUE; 1938 else 1939 debugging = ISC_TRUE; 1940 return (STATUS_MORE); 1941 } 1942 if (strcasecmp(word, "ttl") == 0) 1943 return (evaluate_ttl(cmdline)); 1944 if (strcasecmp(word, "show") == 0) { 1945 show_message(stdout, updatemsg, "Outgoing update query:"); 1946 return (STATUS_MORE); 1947 } 1948 if (strcasecmp(word, "answer") == 0) { 1949 if (answer != NULL) 1950 show_message(stdout, answer, "Answer:"); 1951 return (STATUS_MORE); 1952 } 1953 if (strcasecmp(word, "key") == 0) { 1954 usegsstsig = ISC_FALSE; 1955 return (evaluate_key(cmdline)); 1956 } 1957 if (strcasecmp(word, "realm") == 0) 1958 return (evaluate_realm(cmdline)); 1959 if (strcasecmp(word, "gsstsig") == 0) { 1960#ifdef GSSAPI 1961 usegsstsig = ISC_TRUE; 1962 use_win2k_gsstsig = ISC_FALSE; 1963#else 1964 fprintf(stderr, "gsstsig not supported\n"); 1965#endif 1966 return (STATUS_MORE); 1967 } 1968 if (strcasecmp(word, "oldgsstsig") == 0) { 1969#ifdef GSSAPI 1970 usegsstsig = ISC_TRUE; 1971 use_win2k_gsstsig = ISC_TRUE; 1972#else 1973 fprintf(stderr, "gsstsig not supported\n"); 1974#endif 1975 return (STATUS_MORE); 1976 } 1977 if (strcasecmp(word, "help") == 0) { 1978 fprintf(stdout, 1979"local address [port] (set local resolver)\n" 1980"server address [port] (set master server for zone)\n" 1981"send (send the update request)\n" 1982"show (show the update request)\n" 1983"answer (show the answer to the last request)\n" 1984"quit (quit, any pending update is not sent\n" 1985"help (display this message_\n" 1986"key [hmac:]keyname secret (use TSIG to sign the request)\n" 1987"gsstsig (use GSS_TSIG to sign the request)\n" 1988"oldgsstsig (use Microsoft's GSS_TSIG to sign the request)\n" 1989"zone name (set the zone to be updated)\n" 1990"class CLASS (set the zone's DNS class, e.g. IN (default), CH)\n" 1991"[prereq] nxdomain name (does this name not exist)\n" 1992"[prereq] yxdomain name (does this name exist)\n" 1993"[prereq] nxrrset .... (does this RRset exist)\n" 1994"[prereq] yxrrset .... (does this RRset not exist)\n" 1995"[update] add .... (add the given record to the zone)\n" 1996"[update] del[ete] .... (remove the given record(s) from the zone)\n"); 1997 return (STATUS_MORE); 1998 } 1999 fprintf(stderr, "incorrect section name: %s\n", word); 2000 return (STATUS_SYNTAX); 2001} 2002 2003static isc_uint16_t 2004get_next_command(void) { 2005 isc_uint16_t result = STATUS_QUIT; 2006 char cmdlinebuf[MAXCMD]; 2007 char *cmdline; 2008 2009 isc_app_block(); 2010 if (interactive) { 2011#ifdef HAVE_READLINE 2012 cmdline = readline("> "); 2013 add_history(cmdline); 2014#else 2015 fprintf(stdout, "> "); 2016 fflush(stdout); 2017 cmdline = fgets(cmdlinebuf, MAXCMD, input); 2018#endif 2019 } else 2020 cmdline = fgets(cmdlinebuf, MAXCMD, input); 2021 isc_app_unblock(); 2022 2023 if (cmdline != NULL) { 2024 char *tmp = cmdline; 2025 2026 /* 2027 * Normalize input by removing any eol as readline() 2028 * removes eol but fgets doesn't. 2029 */ 2030 (void)nsu_strsep(&tmp, "\r\n"); 2031 result = do_next_command(cmdline); 2032 } 2033#ifdef HAVE_READLINE 2034 if (interactive) 2035 free(cmdline); 2036#endif 2037 return (result); 2038} 2039 2040static isc_boolean_t 2041user_interaction(void) { 2042 isc_uint16_t result = STATUS_MORE; 2043 2044 ddebug("user_interaction()"); 2045 while ((result == STATUS_MORE) || (result == STATUS_SYNTAX)) { 2046 result = get_next_command(); 2047 if (!interactive && result == STATUS_SYNTAX) 2048 fatal("syntax error"); 2049 } 2050 if (result == STATUS_SEND) 2051 return (ISC_TRUE); 2052 return (ISC_FALSE); 2053 2054} 2055 2056static void 2057done_update(void) { 2058 isc_event_t *event = global_event; 2059 ddebug("done_update()"); 2060 isc_task_send(global_task, &event); 2061} 2062 2063static void 2064check_tsig_error(dns_rdataset_t *rdataset, isc_buffer_t *b) { 2065 isc_result_t result; 2066 dns_rdata_t rdata = DNS_RDATA_INIT; 2067 dns_rdata_any_tsig_t tsig; 2068 2069 result = dns_rdataset_first(rdataset); 2070 check_result(result, "dns_rdataset_first"); 2071 dns_rdataset_current(rdataset, &rdata); 2072 result = dns_rdata_tostruct(&rdata, &tsig, NULL); 2073 check_result(result, "dns_rdata_tostruct"); 2074 if (tsig.error != 0) { 2075 if (isc_buffer_remaininglength(b) < 1) 2076 check_result(ISC_R_NOSPACE, "isc_buffer_remaininglength"); 2077 isc__buffer_putstr(b, "(" /*)*/); 2078 result = dns_tsigrcode_totext(tsig.error, b); 2079 check_result(result, "dns_tsigrcode_totext"); 2080 if (isc_buffer_remaininglength(b) < 1) 2081 check_result(ISC_R_NOSPACE, "isc_buffer_remaininglength"); 2082 isc__buffer_putstr(b, /*(*/ ")"); 2083 } 2084} 2085 2086static void 2087update_completed(isc_task_t *task, isc_event_t *event) { 2088 dns_requestevent_t *reqev = NULL; 2089 isc_result_t result; 2090 dns_request_t *request; 2091 2092 UNUSED(task); 2093 2094 ddebug("update_completed()"); 2095 2096 requests--; 2097 2098 REQUIRE(event->ev_type == DNS_EVENT_REQUESTDONE); 2099 reqev = (dns_requestevent_t *)event; 2100 request = reqev->request; 2101 2102 if (shuttingdown) { 2103 dns_request_destroy(&request); 2104 isc_event_free(&event); 2105 maybeshutdown(); 2106 return; 2107 } 2108 2109 if (reqev->result != ISC_R_SUCCESS) { 2110 fprintf(stderr, "; Communication with server failed: %s\n", 2111 isc_result_totext(reqev->result)); 2112 seenerror = ISC_TRUE; 2113 goto done; 2114 } 2115 2116 result = dns_message_create(mctx, DNS_MESSAGE_INTENTPARSE, &answer); 2117 check_result(result, "dns_message_create"); 2118 result = dns_request_getresponse(request, answer, 2119 DNS_MESSAGEPARSE_PRESERVEORDER); 2120 switch (result) { 2121 case ISC_R_SUCCESS: 2122 if (answer->verify_attempted) 2123 ddebug("tsig verification successful"); 2124 break; 2125 case DNS_R_CLOCKSKEW: 2126 case DNS_R_EXPECTEDTSIG: 2127 case DNS_R_TSIGERRORSET: 2128 case DNS_R_TSIGVERIFYFAILURE: 2129 case DNS_R_UNEXPECTEDTSIG: 2130 case ISC_R_FAILURE: 2131#if 0 2132 if (usegsstsig && answer->rcode == dns_rcode_noerror) { 2133 /* 2134 * For MS DNS that violates RFC 2845, section 4.2 2135 */ 2136 break; 2137 } 2138#endif 2139 fprintf(stderr, "; TSIG error with server: %s\n", 2140 isc_result_totext(result)); 2141 seenerror = ISC_TRUE; 2142 break; 2143 default: 2144 check_result(result, "dns_request_getresponse"); 2145 } 2146 2147 if (answer->rcode != dns_rcode_noerror) { 2148 seenerror = ISC_TRUE; 2149 if (!debugging) { 2150 char buf[64]; 2151 isc_buffer_t b; 2152 dns_rdataset_t *rds; 2153 2154 isc_buffer_init(&b, buf, sizeof(buf) - 1); 2155 result = dns_rcode_totext(answer->rcode, &b); 2156 check_result(result, "dns_rcode_totext"); 2157 rds = dns_message_gettsig(answer, NULL); 2158 if (rds != NULL) 2159 check_tsig_error(rds, &b); 2160 fprintf(stderr, "update failed: %.*s\n", 2161 (int)isc_buffer_usedlength(&b), buf); 2162 } 2163 } 2164 if (debugging) 2165 show_message(stderr, answer, "\nReply from update query:"); 2166 2167 done: 2168 dns_request_destroy(&request); 2169 if (usegsstsig) { 2170 dns_name_free(&tmpzonename, mctx); 2171 dns_name_free(&restart_master, mctx); 2172 } 2173 isc_event_free(&event); 2174 done_update(); 2175} 2176 2177static void 2178send_update(dns_name_t *zonename, isc_sockaddr_t *master, 2179 isc_sockaddr_t *srcaddr) 2180{ 2181 isc_result_t result; 2182 dns_request_t *request = NULL; 2183 unsigned int options = DNS_REQUESTOPT_CASE; 2184 2185 ddebug("send_update()"); 2186 2187 setzone(zonename); 2188 2189 if (usevc) 2190 options |= DNS_REQUESTOPT_TCP; 2191 if (tsigkey == NULL && sig0key != NULL) { 2192 result = dns_message_setsig0key(updatemsg, sig0key); 2193 check_result(result, "dns_message_setsig0key"); 2194 } 2195 if (debugging) { 2196 char addrbuf[ISC_SOCKADDR_FORMATSIZE]; 2197 2198 isc_sockaddr_format(master, addrbuf, sizeof(addrbuf)); 2199 fprintf(stderr, "Sending update to %s\n", addrbuf); 2200 } 2201 2202 /* Windows doesn't like the tsig name to be compressed. */ 2203 if (updatemsg->tsigname) 2204 updatemsg->tsigname->attributes |= DNS_NAMEATTR_NOCOMPRESS; 2205 2206 result = dns_request_createvia3(requestmgr, updatemsg, srcaddr, 2207 master, options, tsigkey, timeout, 2208 udp_timeout, udp_retries, global_task, 2209 update_completed, NULL, &request); 2210 check_result(result, "dns_request_createvia3"); 2211 2212 if (debugging) 2213 show_message(stdout, updatemsg, "Outgoing update query:"); 2214 2215 requests++; 2216} 2217 2218static void 2219recvsoa(isc_task_t *task, isc_event_t *event) { 2220 dns_requestevent_t *reqev = NULL; 2221 dns_request_t *request = NULL; 2222 isc_result_t result, eresult; 2223 dns_message_t *rcvmsg = NULL; 2224 dns_section_t section; 2225 dns_name_t *name = NULL; 2226 dns_rdataset_t *soaset = NULL; 2227 dns_rdata_soa_t soa; 2228 dns_rdata_t soarr = DNS_RDATA_INIT; 2229 int pass = 0; 2230 dns_name_t master; 2231 nsu_requestinfo_t *reqinfo; 2232 dns_message_t *soaquery = NULL; 2233 isc_sockaddr_t *addr; 2234 isc_boolean_t seencname = ISC_FALSE; 2235 dns_name_t tname; 2236 unsigned int nlabels; 2237 2238 UNUSED(task); 2239 2240 ddebug("recvsoa()"); 2241 2242 requests--; 2243 2244 REQUIRE(event->ev_type == DNS_EVENT_REQUESTDONE); 2245 reqev = (dns_requestevent_t *)event; 2246 request = reqev->request; 2247 eresult = reqev->result; 2248 reqinfo = reqev->ev_arg; 2249 soaquery = reqinfo->msg; 2250 addr = reqinfo->addr; 2251 2252 if (shuttingdown) { 2253 dns_request_destroy(&request); 2254 dns_message_destroy(&soaquery); 2255 isc_mem_put(mctx, reqinfo, sizeof(nsu_requestinfo_t)); 2256 isc_event_free(&event); 2257 maybeshutdown(); 2258 return; 2259 } 2260 2261 if (eresult != ISC_R_SUCCESS) { 2262 char addrbuf[ISC_SOCKADDR_FORMATSIZE]; 2263 2264 isc_sockaddr_format(addr, addrbuf, sizeof(addrbuf)); 2265 fprintf(stderr, "; Communication with %s failed: %s\n", 2266 addrbuf, isc_result_totext(eresult)); 2267 if (userserver != NULL) 2268 fatal("could not talk to specified name server"); 2269 else if (++ns_inuse >= lwconf->nsnext) 2270 fatal("could not talk to any default name server"); 2271 ddebug("Destroying request [%p]", request); 2272 dns_request_destroy(&request); 2273 dns_message_renderreset(soaquery); 2274 dns_message_settsigkey(soaquery, NULL); 2275 sendrequest(localaddr, &servers[ns_inuse], soaquery, &request); 2276 isc_mem_put(mctx, reqinfo, sizeof(nsu_requestinfo_t)); 2277 isc_event_free(&event); 2278 setzoneclass(dns_rdataclass_none); 2279 return; 2280 } 2281 2282 isc_mem_put(mctx, reqinfo, sizeof(nsu_requestinfo_t)); 2283 reqinfo = NULL; 2284 isc_event_free(&event); 2285 reqev = NULL; 2286 2287 ddebug("About to create rcvmsg"); 2288 result = dns_message_create(mctx, DNS_MESSAGE_INTENTPARSE, &rcvmsg); 2289 check_result(result, "dns_message_create"); 2290 result = dns_request_getresponse(request, rcvmsg, 2291 DNS_MESSAGEPARSE_PRESERVEORDER); 2292 if (result == DNS_R_TSIGERRORSET && userserver != NULL) { 2293 dns_message_destroy(&rcvmsg); 2294 ddebug("Destroying request [%p]", request); 2295 dns_request_destroy(&request); 2296 reqinfo = isc_mem_get(mctx, sizeof(nsu_requestinfo_t)); 2297 if (reqinfo == NULL) 2298 fatal("out of memory"); 2299 reqinfo->msg = soaquery; 2300 reqinfo->addr = addr; 2301 dns_message_renderreset(soaquery); 2302 ddebug("retrying soa request without TSIG"); 2303 result = dns_request_createvia3(requestmgr, soaquery, 2304 localaddr, addr, 0, NULL, 2305 FIND_TIMEOUT * 20, 2306 FIND_TIMEOUT, 3, 2307 global_task, recvsoa, reqinfo, 2308 &request); 2309 check_result(result, "dns_request_createvia"); 2310 requests++; 2311 return; 2312 } 2313 check_result(result, "dns_request_getresponse"); 2314 section = DNS_SECTION_ANSWER; 2315 POST(section); 2316 if (debugging) 2317 show_message(stderr, rcvmsg, "Reply from SOA query:"); 2318 2319 if (rcvmsg->rcode != dns_rcode_noerror && 2320 rcvmsg->rcode != dns_rcode_nxdomain) 2321 fatal("response to SOA query was unsuccessful"); 2322 2323 if (userzone != NULL && rcvmsg->rcode == dns_rcode_nxdomain) { 2324 char namebuf[DNS_NAME_FORMATSIZE]; 2325 dns_name_format(userzone, namebuf, sizeof(namebuf)); 2326 error("specified zone '%s' does not exist (NXDOMAIN)", 2327 namebuf); 2328 dns_message_destroy(&rcvmsg); 2329 dns_request_destroy(&request); 2330 dns_message_destroy(&soaquery); 2331 ddebug("Out of recvsoa"); 2332 done_update(); 2333 seenerror = ISC_TRUE; 2334 return; 2335 } 2336 2337 lookforsoa: 2338 if (pass == 0) 2339 section = DNS_SECTION_ANSWER; 2340 else if (pass == 1) 2341 section = DNS_SECTION_AUTHORITY; 2342 else 2343 goto droplabel; 2344 2345 result = dns_message_firstname(rcvmsg, section); 2346 if (result != ISC_R_SUCCESS) { 2347 pass++; 2348 goto lookforsoa; 2349 } 2350 while (result == ISC_R_SUCCESS) { 2351 name = NULL; 2352 dns_message_currentname(rcvmsg, section, &name); 2353 soaset = NULL; 2354 result = dns_message_findtype(name, dns_rdatatype_soa, 0, 2355 &soaset); 2356 if (result == ISC_R_SUCCESS) 2357 break; 2358 if (section == DNS_SECTION_ANSWER) { 2359 dns_rdataset_t *tset = NULL; 2360 if (dns_message_findtype(name, dns_rdatatype_cname, 0, 2361 &tset) == ISC_R_SUCCESS || 2362 dns_message_findtype(name, dns_rdatatype_dname, 0, 2363 &tset) == ISC_R_SUCCESS ) { 2364 seencname = ISC_TRUE; 2365 break; 2366 } 2367 } 2368 2369 result = dns_message_nextname(rcvmsg, section); 2370 } 2371 2372 if (soaset == NULL && !seencname) { 2373 pass++; 2374 goto lookforsoa; 2375 } 2376 2377 if (seencname) 2378 goto droplabel; 2379 2380 if (debugging) { 2381 char namestr[DNS_NAME_FORMATSIZE]; 2382 dns_name_format(name, namestr, sizeof(namestr)); 2383 fprintf(stderr, "Found zone name: %s\n", namestr); 2384 } 2385 2386 result = dns_rdataset_first(soaset); 2387 check_result(result, "dns_rdataset_first"); 2388 2389 dns_rdata_init(&soarr); 2390 dns_rdataset_current(soaset, &soarr); 2391 result = dns_rdata_tostruct(&soarr, &soa, NULL); 2392 check_result(result, "dns_rdata_tostruct"); 2393 2394 dns_name_init(&master, NULL); 2395 dns_name_clone(&soa.origin, &master); 2396 2397 if (userzone != NULL) 2398 zonename = userzone; 2399 else 2400 zonename = name; 2401 2402 if (debugging) { 2403 char namestr[DNS_NAME_FORMATSIZE]; 2404 dns_name_format(&master, namestr, sizeof(namestr)); 2405 fprintf(stderr, "The master is: %s\n", namestr); 2406 } 2407 2408 if (userserver != NULL) 2409 serveraddr = userserver; 2410 else { 2411 char serverstr[DNS_NAME_MAXTEXT+1]; 2412 isc_buffer_t buf; 2413 2414 isc_buffer_init(&buf, serverstr, sizeof(serverstr)); 2415 result = dns_name_totext(&master, ISC_TRUE, &buf); 2416 check_result(result, "dns_name_totext"); 2417 serverstr[isc_buffer_usedlength(&buf)] = 0; 2418 get_address(serverstr, dnsport, &tempaddr); 2419 serveraddr = &tempaddr; 2420 } 2421 dns_rdata_freestruct(&soa); 2422 2423#ifdef GSSAPI 2424 if (usegsstsig) { 2425 dns_name_init(&tmpzonename, NULL); 2426 dns_name_dup(zonename, mctx, &tmpzonename); 2427 dns_name_init(&restart_master, NULL); 2428 dns_name_dup(&master, mctx, &restart_master); 2429 start_gssrequest(&master); 2430 } else { 2431 send_update(zonename, serveraddr, localaddr); 2432 setzoneclass(dns_rdataclass_none); 2433 } 2434#else 2435 send_update(zonename, serveraddr, localaddr); 2436 setzoneclass(dns_rdataclass_none); 2437#endif 2438 2439 dns_message_destroy(&soaquery); 2440 dns_request_destroy(&request); 2441 2442 out: 2443 dns_message_destroy(&rcvmsg); 2444 ddebug("Out of recvsoa"); 2445 return; 2446 2447 droplabel: 2448 result = dns_message_firstname(soaquery, DNS_SECTION_QUESTION); 2449 INSIST(result == ISC_R_SUCCESS); 2450 name = NULL; 2451 dns_message_currentname(soaquery, DNS_SECTION_QUESTION, &name); 2452 nlabels = dns_name_countlabels(name); 2453 if (nlabels == 1) 2454 fatal("could not find enclosing zone"); 2455 dns_name_init(&tname, NULL); 2456 dns_name_getlabelsequence(name, 1, nlabels - 1, &tname); 2457 dns_name_clone(&tname, name); 2458 dns_request_destroy(&request); 2459 dns_message_renderreset(soaquery); 2460 dns_message_settsigkey(soaquery, NULL); 2461 if (userserver != NULL) 2462 sendrequest(localaddr, userserver, soaquery, &request); 2463 else 2464 sendrequest(localaddr, &servers[ns_inuse], soaquery, &request); 2465 goto out; 2466} 2467 2468static void 2469sendrequest(isc_sockaddr_t *srcaddr, isc_sockaddr_t *destaddr, 2470 dns_message_t *msg, dns_request_t **request) 2471{ 2472 isc_result_t result; 2473 nsu_requestinfo_t *reqinfo; 2474 2475 reqinfo = isc_mem_get(mctx, sizeof(nsu_requestinfo_t)); 2476 if (reqinfo == NULL) 2477 fatal("out of memory"); 2478 reqinfo->msg = msg; 2479 reqinfo->addr = destaddr; 2480 result = dns_request_createvia3(requestmgr, msg, srcaddr, destaddr, 0, 2481 (userserver != NULL) ? tsigkey : NULL, 2482 FIND_TIMEOUT * 20, FIND_TIMEOUT, 3, 2483 global_task, recvsoa, reqinfo, request); 2484 check_result(result, "dns_request_createvia"); 2485 requests++; 2486} 2487 2488#ifdef GSSAPI 2489 2490/* 2491 * Get the realm from the users kerberos ticket if possible 2492 */ 2493static void 2494get_ticket_realm(isc_mem_t *mctx) 2495{ 2496 krb5_context ctx; 2497 krb5_error_code rc; 2498 krb5_ccache ccache; 2499 krb5_principal princ; 2500 char *name, *ticket_realm; 2501 2502 rc = krb5_init_context(&ctx); 2503 if (rc != 0) 2504 return; 2505 2506 rc = krb5_cc_default(ctx, &ccache); 2507 if (rc != 0) { 2508 krb5_free_context(ctx); 2509 return; 2510 } 2511 2512 rc = krb5_cc_get_principal(ctx, ccache, &princ); 2513 if (rc != 0) { 2514 krb5_cc_close(ctx, ccache); 2515 krb5_free_context(ctx); 2516 return; 2517 } 2518 2519 rc = krb5_unparse_name(ctx, princ, &name); 2520 if (rc != 0) { 2521 krb5_free_principal(ctx, princ); 2522 krb5_cc_close(ctx, ccache); 2523 krb5_free_context(ctx); 2524 return; 2525 } 2526 2527 ticket_realm = strrchr(name, '@'); 2528 if (ticket_realm != NULL) { 2529 realm = isc_mem_strdup(mctx, ticket_realm); 2530 } 2531 2532 free(name); 2533 krb5_free_principal(ctx, princ); 2534 krb5_cc_close(ctx, ccache); 2535 krb5_free_context(ctx); 2536 if (realm != NULL && debugging) 2537 fprintf(stderr, "Found realm from ticket: %s\n", realm+1); 2538} 2539 2540 2541static void 2542start_gssrequest(dns_name_t *master) { 2543 gss_ctx_id_t context; 2544 isc_buffer_t buf; 2545 isc_result_t result; 2546 isc_uint32_t val = 0; 2547 dns_message_t *rmsg; 2548 dns_request_t *request = NULL; 2549 dns_name_t *servname; 2550 dns_fixedname_t fname; 2551 char namestr[DNS_NAME_FORMATSIZE]; 2552 char keystr[DNS_NAME_FORMATSIZE]; 2553 char *err_message = NULL; 2554 2555 debug("start_gssrequest"); 2556 usevc = ISC_TRUE; 2557 2558 if (gssring != NULL) 2559 dns_tsigkeyring_detach(&gssring); 2560 gssring = NULL; 2561 result = dns_tsigkeyring_create(mctx, &gssring); 2562 2563 if (result != ISC_R_SUCCESS) 2564 fatal("dns_tsigkeyring_create failed: %s", 2565 isc_result_totext(result)); 2566 2567 dns_name_format(master, namestr, sizeof(namestr)); 2568 if (kserver == NULL) { 2569 kserver = isc_mem_get(mctx, sizeof(isc_sockaddr_t)); 2570 if (kserver == NULL) 2571 fatal("out of memory"); 2572 } 2573 if (userserver == NULL) 2574 get_address(namestr, dnsport, kserver); 2575 else 2576 (void)memcpy(kserver, userserver, sizeof(isc_sockaddr_t)); 2577 2578 dns_fixedname_init(&fname); 2579 servname = dns_fixedname_name(&fname); 2580 2581 if (realm == NULL) 2582 get_ticket_realm(mctx); 2583 2584 result = isc_string_printf(servicename, sizeof(servicename), 2585 "DNS/%s%s", namestr, realm ? realm : ""); 2586 if (result != ISC_R_SUCCESS) 2587 fatal("isc_string_printf(servicename) failed: %s", 2588 isc_result_totext(result)); 2589 isc_buffer_init(&buf, servicename, strlen(servicename)); 2590 isc_buffer_add(&buf, strlen(servicename)); 2591 result = dns_name_fromtext(servname, &buf, dns_rootname, 0, NULL); 2592 if (result != ISC_R_SUCCESS) 2593 fatal("dns_name_fromtext(servname) failed: %s", 2594 isc_result_totext(result)); 2595 2596 dns_fixedname_init(&fkname); 2597 keyname = dns_fixedname_name(&fkname); 2598 2599 isc_random_get(&val); 2600 result = isc_string_printf(keystr, sizeof(keystr), "%u.sig-%s", 2601 val, namestr); 2602 if (result != ISC_R_SUCCESS) 2603 fatal("isc_string_printf(keystr) failed: %s", 2604 isc_result_totext(result)); 2605 isc_buffer_init(&buf, keystr, strlen(keystr)); 2606 isc_buffer_add(&buf, strlen(keystr)); 2607 2608 result = dns_name_fromtext(keyname, &buf, dns_rootname, 0, NULL); 2609 if (result != ISC_R_SUCCESS) 2610 fatal("dns_name_fromtext(keyname) failed: %s", 2611 isc_result_totext(result)); 2612 2613 /* Windows doesn't recognize name compression in the key name. */ 2614 keyname->attributes |= DNS_NAMEATTR_NOCOMPRESS; 2615 2616 rmsg = NULL; 2617 result = dns_message_create(mctx, DNS_MESSAGE_INTENTRENDER, &rmsg); 2618 if (result != ISC_R_SUCCESS) 2619 fatal("dns_message_create failed: %s", 2620 isc_result_totext(result)); 2621 2622 /* Build first request. */ 2623 context = GSS_C_NO_CONTEXT; 2624 result = dns_tkey_buildgssquery(rmsg, keyname, servname, NULL, 0, 2625 &context, use_win2k_gsstsig, 2626 mctx, &err_message); 2627 if (result == ISC_R_FAILURE) 2628 fatal("tkey query failed: %s", 2629 err_message != NULL ? err_message : "unknown error"); 2630 if (result != ISC_R_SUCCESS) 2631 fatal("dns_tkey_buildgssquery failed: %s", 2632 isc_result_totext(result)); 2633 2634 send_gssrequest(localaddr, kserver, rmsg, &request, context); 2635} 2636 2637static void 2638send_gssrequest(isc_sockaddr_t *srcaddr, isc_sockaddr_t *destaddr, 2639 dns_message_t *msg, dns_request_t **request, 2640 gss_ctx_id_t context) 2641{ 2642 isc_result_t result; 2643 nsu_gssinfo_t *reqinfo; 2644 unsigned int options = 0; 2645 2646 debug("send_gssrequest"); 2647 reqinfo = isc_mem_get(mctx, sizeof(nsu_gssinfo_t)); 2648 if (reqinfo == NULL) 2649 fatal("out of memory"); 2650 reqinfo->msg = msg; 2651 reqinfo->addr = destaddr; 2652 reqinfo->context = context; 2653 2654 options |= DNS_REQUESTOPT_TCP; 2655 result = dns_request_createvia3(requestmgr, msg, srcaddr, destaddr, 2656 options, tsigkey, FIND_TIMEOUT * 20, 2657 FIND_TIMEOUT, 3, global_task, recvgss, 2658 reqinfo, request); 2659 check_result(result, "dns_request_createvia3"); 2660 if (debugging) 2661 show_message(stdout, msg, "Outgoing update query:"); 2662 requests++; 2663} 2664 2665static void 2666recvgss(isc_task_t *task, isc_event_t *event) { 2667 dns_requestevent_t *reqev = NULL; 2668 dns_request_t *request = NULL; 2669 isc_result_t result, eresult; 2670 dns_message_t *rcvmsg = NULL; 2671 nsu_gssinfo_t *reqinfo; 2672 dns_message_t *tsigquery = NULL; 2673 isc_sockaddr_t *addr; 2674 gss_ctx_id_t context; 2675 isc_buffer_t buf; 2676 dns_name_t *servname; 2677 dns_fixedname_t fname; 2678 char *err_message = NULL; 2679 2680 UNUSED(task); 2681 2682 ddebug("recvgss()"); 2683 2684 requests--; 2685 2686 REQUIRE(event->ev_type == DNS_EVENT_REQUESTDONE); 2687 reqev = (dns_requestevent_t *)event; 2688 request = reqev->request; 2689 eresult = reqev->result; 2690 reqinfo = reqev->ev_arg; 2691 tsigquery = reqinfo->msg; 2692 context = reqinfo->context; 2693 addr = reqinfo->addr; 2694 2695 if (shuttingdown) { 2696 dns_request_destroy(&request); 2697 dns_message_destroy(&tsigquery); 2698 isc_mem_put(mctx, reqinfo, sizeof(nsu_gssinfo_t)); 2699 isc_event_free(&event); 2700 maybeshutdown(); 2701 return; 2702 } 2703 2704 if (eresult != ISC_R_SUCCESS) { 2705 char addrbuf[ISC_SOCKADDR_FORMATSIZE]; 2706 2707 isc_sockaddr_format(addr, addrbuf, sizeof(addrbuf)); 2708 fprintf(stderr, "; Communication with %s failed: %s\n", 2709 addrbuf, isc_result_totext(eresult)); 2710 if (userserver != NULL) 2711 fatal("could not talk to specified name server"); 2712 else if (++ns_inuse >= lwconf->nsnext) 2713 fatal("could not talk to any default name server"); 2714 ddebug("Destroying request [%p]", request); 2715 dns_request_destroy(&request); 2716 dns_message_renderreset(tsigquery); 2717 sendrequest(localaddr, &servers[ns_inuse], tsigquery, 2718 &request); 2719 isc_mem_put(mctx, reqinfo, sizeof(nsu_gssinfo_t)); 2720 isc_event_free(&event); 2721 return; 2722 } 2723 isc_mem_put(mctx, reqinfo, sizeof(nsu_gssinfo_t)); 2724 2725 isc_event_free(&event); 2726 reqev = NULL; 2727 2728 ddebug("recvgss creating rcvmsg"); 2729 result = dns_message_create(mctx, DNS_MESSAGE_INTENTPARSE, &rcvmsg); 2730 check_result(result, "dns_message_create"); 2731 2732 result = dns_request_getresponse(request, rcvmsg, 2733 DNS_MESSAGEPARSE_PRESERVEORDER); 2734 check_result(result, "dns_request_getresponse"); 2735 2736 if (debugging) 2737 show_message(stderr, rcvmsg, 2738 "recvmsg reply from GSS-TSIG query"); 2739 2740 if (rcvmsg->rcode == dns_rcode_formerr && !tried_other_gsstsig) { 2741 ddebug("recvgss trying %s GSS-TSIG", 2742 use_win2k_gsstsig ? "Standard" : "Win2k"); 2743 if (use_win2k_gsstsig) 2744 use_win2k_gsstsig = ISC_FALSE; 2745 else 2746 use_win2k_gsstsig = ISC_TRUE; 2747 tried_other_gsstsig = ISC_TRUE; 2748 start_gssrequest(&restart_master); 2749 goto done; 2750 } 2751 2752 if (rcvmsg->rcode != dns_rcode_noerror && 2753 rcvmsg->rcode != dns_rcode_nxdomain) 2754 fatal("response to GSS-TSIG query was unsuccessful"); 2755 2756 2757 dns_fixedname_init(&fname); 2758 servname = dns_fixedname_name(&fname); 2759 isc_buffer_init(&buf, servicename, strlen(servicename)); 2760 isc_buffer_add(&buf, strlen(servicename)); 2761 result = dns_name_fromtext(servname, &buf, dns_rootname, 0, NULL); 2762 check_result(result, "dns_name_fromtext"); 2763 2764 tsigkey = NULL; 2765 result = dns_tkey_gssnegotiate(tsigquery, rcvmsg, servname, 2766 &context, &tsigkey, gssring, 2767 use_win2k_gsstsig, 2768 &err_message); 2769 switch (result) { 2770 2771 case DNS_R_CONTINUE: 2772 send_gssrequest(localaddr, kserver, tsigquery, &request, 2773 context); 2774 break; 2775 2776 case ISC_R_SUCCESS: 2777 /* 2778 * XXXSRA Waaay too much fun here. There's no good 2779 * reason why we need a TSIG here (the people who put 2780 * it into the spec admitted at the time that it was 2781 * not a security issue), and Windows clients don't 2782 * seem to work if named complies with the spec and 2783 * includes the gratuitous TSIG. So we're in the 2784 * bizarre situation of having to choose between 2785 * complying with a useless requirement in the spec 2786 * and interoperating. This is nuts. If we can 2787 * confirm this behavior, we should ask the WG to 2788 * consider removing the requirement for the 2789 * gratuitous TSIG here. For the moment, we ignore 2790 * the TSIG -- this too is a spec violation, but it's 2791 * the least insane thing to do. 2792 */ 2793#if 0 2794 /* 2795 * Verify the signature. 2796 */ 2797 rcvmsg->state = DNS_SECTION_ANY; 2798 dns_message_setquerytsig(rcvmsg, NULL); 2799 result = dns_message_settsigkey(rcvmsg, tsigkey); 2800 check_result(result, "dns_message_settsigkey"); 2801 result = dns_message_checksig(rcvmsg, NULL); 2802 ddebug("tsig verification: %s", dns_result_totext(result)); 2803 check_result(result, "dns_message_checksig"); 2804#endif /* 0 */ 2805 2806 send_update(&tmpzonename, serveraddr, localaddr); 2807 setzoneclass(dns_rdataclass_none); 2808 break; 2809 2810 default: 2811 fatal("dns_tkey_negotiategss: %s %s", 2812 isc_result_totext(result), 2813 err_message != NULL ? err_message : ""); 2814 } 2815 2816 done: 2817 dns_request_destroy(&request); 2818 dns_message_destroy(&tsigquery); 2819 2820 dns_message_destroy(&rcvmsg); 2821 ddebug("Out of recvgss"); 2822} 2823#endif 2824 2825static void 2826start_update(void) { 2827 isc_result_t result; 2828 dns_rdataset_t *rdataset = NULL; 2829 dns_name_t *name = NULL; 2830 dns_request_t *request = NULL; 2831 dns_message_t *soaquery = NULL; 2832 dns_name_t *firstname; 2833 dns_section_t section = DNS_SECTION_UPDATE; 2834 2835 ddebug("start_update()"); 2836 2837 if (answer != NULL) 2838 dns_message_destroy(&answer); 2839 2840 if (userzone != NULL && userserver != NULL && ! usegsstsig) { 2841 send_update(userzone, userserver, localaddr); 2842 setzoneclass(dns_rdataclass_none); 2843 return; 2844 } 2845 2846 result = dns_message_create(mctx, DNS_MESSAGE_INTENTRENDER, 2847 &soaquery); 2848 check_result(result, "dns_message_create"); 2849 2850 if (userserver == NULL) 2851 soaquery->flags |= DNS_MESSAGEFLAG_RD; 2852 2853 result = dns_message_gettempname(soaquery, &name); 2854 check_result(result, "dns_message_gettempname"); 2855 2856 result = dns_message_gettemprdataset(soaquery, &rdataset); 2857 check_result(result, "dns_message_gettemprdataset"); 2858 2859 dns_rdataset_makequestion(rdataset, getzoneclass(), dns_rdatatype_soa); 2860 2861 if (userzone != NULL) { 2862 dns_name_init(name, NULL); 2863 dns_name_clone(userzone, name); 2864 } else { 2865 dns_rdataset_t *tmprdataset; 2866 result = dns_message_firstname(updatemsg, section); 2867 if (result == ISC_R_NOMORE) { 2868 section = DNS_SECTION_PREREQUISITE; 2869 result = dns_message_firstname(updatemsg, section); 2870 } 2871 if (result != ISC_R_SUCCESS) { 2872 dns_message_puttempname(soaquery, &name); 2873 dns_rdataset_disassociate(rdataset); 2874 dns_message_puttemprdataset(soaquery, &rdataset); 2875 dns_message_destroy(&soaquery); 2876 done_update(); 2877 return; 2878 } 2879 firstname = NULL; 2880 dns_message_currentname(updatemsg, section, &firstname); 2881 dns_name_init(name, NULL); 2882 dns_name_clone(firstname, name); 2883 /* 2884 * Looks to see if the first name references a DS record 2885 * and if that name is not the root remove a label as DS 2886 * records live in the parent zone so we need to start our 2887 * search one label up. 2888 */ 2889 tmprdataset = ISC_LIST_HEAD(firstname->list); 2890 if (section == DNS_SECTION_UPDATE && 2891 !dns_name_equal(firstname, dns_rootname) && 2892 tmprdataset->type == dns_rdatatype_ds) { 2893 unsigned int labels = dns_name_countlabels(name); 2894 dns_name_getlabelsequence(name, 1, labels - 1, name); 2895 } 2896 } 2897 2898 ISC_LIST_INIT(name->list); 2899 ISC_LIST_APPEND(name->list, rdataset, link); 2900 dns_message_addname(soaquery, name, DNS_SECTION_QUESTION); 2901 2902 if (userserver != NULL) 2903 sendrequest(localaddr, userserver, soaquery, &request); 2904 else { 2905 ns_inuse = 0; 2906 sendrequest(localaddr, &servers[ns_inuse], soaquery, &request); 2907 } 2908} 2909 2910static void 2911cleanup(void) { 2912 ddebug("cleanup()"); 2913 2914 if (answer != NULL) 2915 dns_message_destroy(&answer); 2916 2917#ifdef GSSAPI 2918 if (tsigkey != NULL) { 2919 ddebug("detach tsigkey x%p", tsigkey); 2920 dns_tsigkey_detach(&tsigkey); 2921 } 2922 if (gssring != NULL) { 2923 ddebug("Detaching GSS-TSIG keyring"); 2924 dns_tsigkeyring_detach(&gssring); 2925 } 2926 if (kserver != NULL) { 2927 isc_mem_put(mctx, kserver, sizeof(isc_sockaddr_t)); 2928 kserver = NULL; 2929 } 2930 if (realm != NULL) { 2931 isc_mem_free(mctx, realm); 2932 realm = NULL; 2933 } 2934#endif 2935 2936 if (sig0key != NULL) 2937 dst_key_free(&sig0key); 2938 2939 ddebug("Shutting down task manager"); 2940 isc_taskmgr_destroy(&taskmgr); 2941 2942 ddebug("Destroying event"); 2943 isc_event_free(&global_event); 2944 2945 ddebug("Shutting down socket manager"); 2946 isc_socketmgr_destroy(&socketmgr); 2947 2948 ddebug("Shutting down timer manager"); 2949 isc_timermgr_destroy(&timermgr); 2950 2951 ddebug("Destroying hash context"); 2952 isc_hash_destroy(); 2953 2954 ddebug("Destroying name state"); 2955 dns_name_destroy(); 2956 2957 ddebug("Removing log context"); 2958 isc_log_destroy(&lctx); 2959 2960 ddebug("Destroying memory context"); 2961 if (memdebugging) 2962 isc_mem_stats(mctx, stderr); 2963 isc_mem_destroy(&mctx); 2964} 2965 2966static void 2967getinput(isc_task_t *task, isc_event_t *event) { 2968 isc_boolean_t more; 2969 2970 UNUSED(task); 2971 2972 if (shuttingdown) { 2973 maybeshutdown(); 2974 return; 2975 } 2976 2977 if (global_event == NULL) 2978 global_event = event; 2979 2980 reset_system(); 2981 more = user_interaction(); 2982 if (!more) { 2983 isc_app_shutdown(); 2984 return; 2985 } 2986 start_update(); 2987 return; 2988} 2989 2990int 2991main(int argc, char **argv) { 2992 isc_result_t result; 2993 style = &dns_master_style_debug; 2994 2995 input = stdin; 2996 2997 interactive = ISC_TF(isatty(0)); 2998 2999 isc_app_start(); 3000 3001 pre_parse_args(argc, argv); 3002 3003 result = isc_mem_create(0, 0, &mctx); 3004 check_result(result, "isc_mem_create"); 3005 3006 parse_args(argc, argv, mctx, &entropy); 3007 3008 setup_system(); 3009 3010 result = isc_app_onrun(mctx, global_task, getinput, NULL); 3011 check_result(result, "isc_app_onrun"); 3012 3013 (void)isc_app_run(); 3014 3015 cleanup(); 3016 3017 isc_app_finish(); 3018 3019 if (seenerror) 3020 return (2); 3021 else 3022 return (0); 3023} 3024