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