nsupdate.c revision 245163
1/* 2 * Copyright (C) 2004-2012 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 == NULL || *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 if (cmdline == NULL) { 1158 rdata->flags = DNS_RDATA_UPDATE; 1159 return (STATUS_MORE); 1160 } 1161 1162 while (*cmdline != 0 && isspace((unsigned char)*cmdline)) 1163 cmdline++; 1164 1165 if (*cmdline != 0) { 1166 dns_rdatacallbacks_init(&callbacks); 1167 result = isc_lex_create(mctx, strlen(cmdline), &lex); 1168 check_result(result, "isc_lex_create"); 1169 isc_buffer_init(&source, cmdline, strlen(cmdline)); 1170 isc_buffer_add(&source, strlen(cmdline)); 1171 result = isc_lex_openbuffer(lex, &source); 1172 check_result(result, "isc_lex_openbuffer"); 1173 result = isc_buffer_allocate(mctx, &buf, MAXWIRE); 1174 check_result(result, "isc_buffer_allocate"); 1175 result = dns_rdata_fromtext(NULL, rdataclass, rdatatype, lex, 1176 dns_rootname, 0, mctx, buf, 1177 &callbacks); 1178 isc_lex_destroy(&lex); 1179 if (result == ISC_R_SUCCESS) { 1180 isc_buffer_usedregion(buf, &r); 1181 result = isc_buffer_allocate(mctx, &newbuf, r.length); 1182 check_result(result, "isc_buffer_allocate"); 1183 isc_buffer_putmem(newbuf, r.base, r.length); 1184 isc_buffer_usedregion(newbuf, &r); 1185 dns_rdata_fromregion(rdata, rdataclass, rdatatype, &r); 1186 isc_buffer_free(&buf); 1187 dns_message_takebuffer(msg, &newbuf); 1188 } else { 1189 fprintf(stderr, "invalid rdata format: %s\n", 1190 isc_result_totext(result)); 1191 isc_buffer_free(&buf); 1192 return (STATUS_SYNTAX); 1193 } 1194 } else { 1195 rdata->flags = DNS_RDATA_UPDATE; 1196 } 1197 *cmdlinep = cmdline; 1198 return (STATUS_MORE); 1199} 1200 1201static isc_uint16_t 1202make_prereq(char *cmdline, isc_boolean_t ispositive, isc_boolean_t isrrset) { 1203 isc_result_t result; 1204 char *word; 1205 dns_name_t *name = NULL; 1206 isc_textregion_t region; 1207 dns_rdataset_t *rdataset = NULL; 1208 dns_rdatalist_t *rdatalist = NULL; 1209 dns_rdataclass_t rdataclass; 1210 dns_rdatatype_t rdatatype; 1211 dns_rdata_t *rdata = NULL; 1212 isc_uint16_t retval; 1213 1214 ddebug("make_prereq()"); 1215 1216 /* 1217 * Read the owner name 1218 */ 1219 retval = parse_name(&cmdline, updatemsg, &name); 1220 if (retval != STATUS_MORE) 1221 return (retval); 1222 1223 /* 1224 * If this is an rrset prereq, read the class or type. 1225 */ 1226 if (isrrset) { 1227 word = nsu_strsep(&cmdline, " \t\r\n"); 1228 if (word == NULL || *word == 0) { 1229 fprintf(stderr, "could not read class or type\n"); 1230 goto failure; 1231 } 1232 region.base = word; 1233 region.length = strlen(word); 1234 result = dns_rdataclass_fromtext(&rdataclass, ®ion); 1235 if (result == ISC_R_SUCCESS) { 1236 if (!setzoneclass(rdataclass)) { 1237 fprintf(stderr, "class mismatch: %s\n", word); 1238 goto failure; 1239 } 1240 /* 1241 * Now read the type. 1242 */ 1243 word = nsu_strsep(&cmdline, " \t\r\n"); 1244 if (word == NULL || *word == 0) { 1245 fprintf(stderr, "could not read type\n"); 1246 goto failure; 1247 } 1248 region.base = word; 1249 region.length = strlen(word); 1250 result = dns_rdatatype_fromtext(&rdatatype, ®ion); 1251 if (result != ISC_R_SUCCESS) { 1252 fprintf(stderr, "invalid type: %s\n", word); 1253 goto failure; 1254 } 1255 } else { 1256 rdataclass = getzoneclass(); 1257 result = dns_rdatatype_fromtext(&rdatatype, ®ion); 1258 if (result != ISC_R_SUCCESS) { 1259 fprintf(stderr, "invalid type: %s\n", word); 1260 goto failure; 1261 } 1262 } 1263 } else 1264 rdatatype = dns_rdatatype_any; 1265 1266 result = dns_message_gettemprdata(updatemsg, &rdata); 1267 check_result(result, "dns_message_gettemprdata"); 1268 1269 dns_rdata_init(rdata); 1270 1271 if (isrrset && ispositive) { 1272 retval = parse_rdata(&cmdline, rdataclass, rdatatype, 1273 updatemsg, rdata); 1274 if (retval != STATUS_MORE) 1275 goto failure; 1276 } else 1277 rdata->flags = DNS_RDATA_UPDATE; 1278 1279 result = dns_message_gettemprdatalist(updatemsg, &rdatalist); 1280 check_result(result, "dns_message_gettemprdatalist"); 1281 result = dns_message_gettemprdataset(updatemsg, &rdataset); 1282 check_result(result, "dns_message_gettemprdataset"); 1283 dns_rdatalist_init(rdatalist); 1284 rdatalist->type = rdatatype; 1285 if (ispositive) { 1286 if (isrrset && rdata->data != NULL) 1287 rdatalist->rdclass = rdataclass; 1288 else 1289 rdatalist->rdclass = dns_rdataclass_any; 1290 } else 1291 rdatalist->rdclass = dns_rdataclass_none; 1292 rdatalist->covers = 0; 1293 rdatalist->ttl = 0; 1294 rdata->rdclass = rdatalist->rdclass; 1295 rdata->type = rdatatype; 1296 ISC_LIST_INIT(rdatalist->rdata); 1297 ISC_LIST_APPEND(rdatalist->rdata, rdata, link); 1298 dns_rdataset_init(rdataset); 1299 dns_rdatalist_tordataset(rdatalist, rdataset); 1300 ISC_LIST_INIT(name->list); 1301 ISC_LIST_APPEND(name->list, rdataset, link); 1302 dns_message_addname(updatemsg, name, DNS_SECTION_PREREQUISITE); 1303 return (STATUS_MORE); 1304 1305 failure: 1306 if (name != NULL) 1307 dns_message_puttempname(updatemsg, &name); 1308 return (STATUS_SYNTAX); 1309} 1310 1311static isc_uint16_t 1312evaluate_prereq(char *cmdline) { 1313 char *word; 1314 isc_boolean_t ispositive, isrrset; 1315 1316 ddebug("evaluate_prereq()"); 1317 word = nsu_strsep(&cmdline, " \t\r\n"); 1318 if (word == NULL || *word == 0) { 1319 fprintf(stderr, "could not read operation code\n"); 1320 return (STATUS_SYNTAX); 1321 } 1322 if (strcasecmp(word, "nxdomain") == 0) { 1323 ispositive = ISC_FALSE; 1324 isrrset = ISC_FALSE; 1325 } else if (strcasecmp(word, "yxdomain") == 0) { 1326 ispositive = ISC_TRUE; 1327 isrrset = ISC_FALSE; 1328 } else if (strcasecmp(word, "nxrrset") == 0) { 1329 ispositive = ISC_FALSE; 1330 isrrset = ISC_TRUE; 1331 } else if (strcasecmp(word, "yxrrset") == 0) { 1332 ispositive = ISC_TRUE; 1333 isrrset = ISC_TRUE; 1334 } else { 1335 fprintf(stderr, "incorrect operation code: %s\n", word); 1336 return (STATUS_SYNTAX); 1337 } 1338 return (make_prereq(cmdline, ispositive, isrrset)); 1339} 1340 1341static isc_uint16_t 1342evaluate_server(char *cmdline) { 1343 char *word, *server; 1344 long port; 1345 1346 if (local_only) { 1347 fprintf(stderr, "cannot reset server in localhost-only mode\n"); 1348 return (STATUS_SYNTAX); 1349 } 1350 1351 word = nsu_strsep(&cmdline, " \t\r\n"); 1352 if (word == NULL || *word == 0) { 1353 fprintf(stderr, "could not read server name\n"); 1354 return (STATUS_SYNTAX); 1355 } 1356 server = word; 1357 1358 word = nsu_strsep(&cmdline, " \t\r\n"); 1359 if (word == NULL || *word == 0) 1360 port = dnsport; 1361 else { 1362 char *endp; 1363 port = strtol(word, &endp, 10); 1364 if (*endp != 0) { 1365 fprintf(stderr, "port '%s' is not numeric\n", word); 1366 return (STATUS_SYNTAX); 1367 } else if (port < 1 || port > 65535) { 1368 fprintf(stderr, "port '%s' is out of range " 1369 "(1 to 65535)\n", word); 1370 return (STATUS_SYNTAX); 1371 } 1372 } 1373 1374 if (userserver == NULL) { 1375 userserver = isc_mem_get(mctx, sizeof(isc_sockaddr_t)); 1376 if (userserver == NULL) 1377 fatal("out of memory"); 1378 } 1379 1380 get_address(server, (in_port_t)port, userserver); 1381 1382 return (STATUS_MORE); 1383} 1384 1385static isc_uint16_t 1386evaluate_local(char *cmdline) { 1387 char *word, *local; 1388 long port; 1389 struct in_addr in4; 1390 struct in6_addr in6; 1391 1392 word = nsu_strsep(&cmdline, " \t\r\n"); 1393 if (word == NULL || *word == 0) { 1394 fprintf(stderr, "could not read server name\n"); 1395 return (STATUS_SYNTAX); 1396 } 1397 local = word; 1398 1399 word = nsu_strsep(&cmdline, " \t\r\n"); 1400 if (word == NULL || *word == 0) 1401 port = 0; 1402 else { 1403 char *endp; 1404 port = strtol(word, &endp, 10); 1405 if (*endp != 0) { 1406 fprintf(stderr, "port '%s' is not numeric\n", word); 1407 return (STATUS_SYNTAX); 1408 } else if (port < 1 || port > 65535) { 1409 fprintf(stderr, "port '%s' is out of range " 1410 "(1 to 65535)\n", word); 1411 return (STATUS_SYNTAX); 1412 } 1413 } 1414 1415 if (localaddr == NULL) { 1416 localaddr = isc_mem_get(mctx, sizeof(isc_sockaddr_t)); 1417 if (localaddr == NULL) 1418 fatal("out of memory"); 1419 } 1420 1421 if (have_ipv6 && inet_pton(AF_INET6, local, &in6) == 1) 1422 isc_sockaddr_fromin6(localaddr, &in6, (in_port_t)port); 1423 else if (have_ipv4 && inet_pton(AF_INET, local, &in4) == 1) 1424 isc_sockaddr_fromin(localaddr, &in4, (in_port_t)port); 1425 else { 1426 fprintf(stderr, "invalid address %s", local); 1427 return (STATUS_SYNTAX); 1428 } 1429 1430 return (STATUS_MORE); 1431} 1432 1433static isc_uint16_t 1434evaluate_key(char *cmdline) { 1435 char *namestr; 1436 char *secretstr; 1437 isc_buffer_t b; 1438 isc_result_t result; 1439 dns_fixedname_t fkeyname; 1440 dns_name_t *keyname; 1441 int secretlen; 1442 unsigned char *secret = NULL; 1443 isc_buffer_t secretbuf; 1444 dns_name_t *hmacname = NULL; 1445 isc_uint16_t digestbits = 0; 1446 char *n; 1447 1448 namestr = nsu_strsep(&cmdline, " \t\r\n"); 1449 if (namestr == NULL || *namestr == 0) { 1450 fprintf(stderr, "could not read key name\n"); 1451 return (STATUS_SYNTAX); 1452 } 1453 1454 dns_fixedname_init(&fkeyname); 1455 keyname = dns_fixedname_name(&fkeyname); 1456 1457 n = strchr(namestr, ':'); 1458 if (n != NULL) { 1459 digestbits = parse_hmac(&hmacname, namestr, n - namestr); 1460 namestr = n + 1; 1461 } else 1462 hmacname = DNS_TSIG_HMACMD5_NAME; 1463 1464 isc_buffer_init(&b, namestr, strlen(namestr)); 1465 isc_buffer_add(&b, strlen(namestr)); 1466 result = dns_name_fromtext(keyname, &b, dns_rootname, 0, NULL); 1467 if (result != ISC_R_SUCCESS) { 1468 fprintf(stderr, "could not parse key name\n"); 1469 return (STATUS_SYNTAX); 1470 } 1471 1472 secretstr = nsu_strsep(&cmdline, "\r\n"); 1473 if (secretstr == NULL || *secretstr == 0) { 1474 fprintf(stderr, "could not read key secret\n"); 1475 return (STATUS_SYNTAX); 1476 } 1477 secretlen = strlen(secretstr) * 3 / 4; 1478 secret = isc_mem_allocate(mctx, secretlen); 1479 if (secret == NULL) 1480 fatal("out of memory"); 1481 1482 isc_buffer_init(&secretbuf, secret, secretlen); 1483 result = isc_base64_decodestring(secretstr, &secretbuf); 1484 if (result != ISC_R_SUCCESS) { 1485 fprintf(stderr, "could not create key from %s: %s\n", 1486 secretstr, isc_result_totext(result)); 1487 isc_mem_free(mctx, secret); 1488 return (STATUS_SYNTAX); 1489 } 1490 secretlen = isc_buffer_usedlength(&secretbuf); 1491 1492 if (tsigkey != NULL) 1493 dns_tsigkey_detach(&tsigkey); 1494 result = dns_tsigkey_create(keyname, hmacname, secret, secretlen, 1495 ISC_FALSE, NULL, 0, 0, mctx, NULL, 1496 &tsigkey); 1497 isc_mem_free(mctx, secret); 1498 if (result != ISC_R_SUCCESS) { 1499 fprintf(stderr, "could not create key from %s %s: %s\n", 1500 namestr, secretstr, dns_result_totext(result)); 1501 return (STATUS_SYNTAX); 1502 } 1503 dst_key_setbits(tsigkey->key, digestbits); 1504 return (STATUS_MORE); 1505} 1506 1507static isc_uint16_t 1508evaluate_zone(char *cmdline) { 1509 char *word; 1510 isc_buffer_t b; 1511 isc_result_t result; 1512 1513 word = nsu_strsep(&cmdline, " \t\r\n"); 1514 if (word == NULL || *word == 0) { 1515 fprintf(stderr, "could not read zone name\n"); 1516 return (STATUS_SYNTAX); 1517 } 1518 1519 dns_fixedname_init(&fuserzone); 1520 userzone = dns_fixedname_name(&fuserzone); 1521 isc_buffer_init(&b, word, strlen(word)); 1522 isc_buffer_add(&b, strlen(word)); 1523 result = dns_name_fromtext(userzone, &b, dns_rootname, 0, NULL); 1524 if (result != ISC_R_SUCCESS) { 1525 userzone = NULL; /* Lest it point to an invalid name */ 1526 fprintf(stderr, "could not parse zone name\n"); 1527 return (STATUS_SYNTAX); 1528 } 1529 1530 return (STATUS_MORE); 1531} 1532 1533static isc_uint16_t 1534evaluate_realm(char *cmdline) { 1535#ifdef GSSAPI 1536 char *word; 1537 char buf[1024]; 1538 1539 word = nsu_strsep(&cmdline, " \t\r\n"); 1540 if (word == NULL || *word == 0) { 1541 if (realm != NULL) 1542 isc_mem_free(mctx, realm); 1543 realm = NULL; 1544 return (STATUS_MORE); 1545 } 1546 1547 snprintf(buf, sizeof(buf), "@%s", word); 1548 realm = isc_mem_strdup(mctx, buf); 1549 if (realm == NULL) 1550 fatal("out of memory"); 1551 return (STATUS_MORE); 1552#else 1553 UNUSED(cmdline); 1554 return (STATUS_SYNTAX); 1555#endif 1556} 1557 1558static isc_uint16_t 1559evaluate_ttl(char *cmdline) { 1560 char *word; 1561 isc_result_t result; 1562 isc_uint32_t ttl; 1563 1564 word = nsu_strsep(&cmdline, " \t\r\n"); 1565 if (word == NULL || *word == 0) { 1566 fprintf(stderr, "could not ttl\n"); 1567 return (STATUS_SYNTAX); 1568 } 1569 1570 if (!strcasecmp(word, "none")) { 1571 default_ttl = 0; 1572 default_ttl_set = ISC_FALSE; 1573 return (STATUS_MORE); 1574 } 1575 1576 result = isc_parse_uint32(&ttl, word, 10); 1577 if (result != ISC_R_SUCCESS) 1578 return (STATUS_SYNTAX); 1579 1580 if (ttl > TTL_MAX) { 1581 fprintf(stderr, "ttl '%s' is out of range (0 to %u)\n", 1582 word, TTL_MAX); 1583 return (STATUS_SYNTAX); 1584 } 1585 default_ttl = ttl; 1586 default_ttl_set = ISC_TRUE; 1587 1588 return (STATUS_MORE); 1589} 1590 1591static isc_uint16_t 1592evaluate_class(char *cmdline) { 1593 char *word; 1594 isc_textregion_t r; 1595 isc_result_t result; 1596 dns_rdataclass_t rdclass; 1597 1598 word = nsu_strsep(&cmdline, " \t\r\n"); 1599 if (word == NULL || *word == 0) { 1600 fprintf(stderr, "could not read class name\n"); 1601 return (STATUS_SYNTAX); 1602 } 1603 1604 r.base = word; 1605 r.length = strlen(word); 1606 result = dns_rdataclass_fromtext(&rdclass, &r); 1607 if (result != ISC_R_SUCCESS) { 1608 fprintf(stderr, "could not parse class name: %s\n", word); 1609 return (STATUS_SYNTAX); 1610 } 1611 switch (rdclass) { 1612 case dns_rdataclass_none: 1613 case dns_rdataclass_any: 1614 case dns_rdataclass_reserved0: 1615 fprintf(stderr, "bad default class: %s\n", word); 1616 return (STATUS_SYNTAX); 1617 default: 1618 defaultclass = rdclass; 1619 } 1620 1621 return (STATUS_MORE); 1622} 1623 1624static isc_uint16_t 1625update_addordelete(char *cmdline, isc_boolean_t isdelete) { 1626 isc_result_t result; 1627 dns_name_t *name = NULL; 1628 isc_uint32_t ttl; 1629 char *word; 1630 dns_rdataclass_t rdataclass; 1631 dns_rdatatype_t rdatatype; 1632 dns_rdata_t *rdata = NULL; 1633 dns_rdatalist_t *rdatalist = NULL; 1634 dns_rdataset_t *rdataset = NULL; 1635 isc_textregion_t region; 1636 isc_uint16_t retval; 1637 1638 ddebug("update_addordelete()"); 1639 1640 /* 1641 * Read the owner name. 1642 */ 1643 retval = parse_name(&cmdline, updatemsg, &name); 1644 if (retval != STATUS_MORE) 1645 return (retval); 1646 1647 result = dns_message_gettemprdata(updatemsg, &rdata); 1648 check_result(result, "dns_message_gettemprdata"); 1649 1650 dns_rdata_init(rdata); 1651 1652 /* 1653 * If this is an add, read the TTL and verify that it's in range. 1654 * If it's a delete, ignore a TTL if present (for compatibility). 1655 */ 1656 word = nsu_strsep(&cmdline, " \t\r\n"); 1657 if (word == NULL || *word == 0) { 1658 if (!isdelete) { 1659 fprintf(stderr, "could not read owner ttl\n"); 1660 goto failure; 1661 } 1662 else { 1663 ttl = 0; 1664 rdataclass = dns_rdataclass_any; 1665 rdatatype = dns_rdatatype_any; 1666 rdata->flags = DNS_RDATA_UPDATE; 1667 goto doneparsing; 1668 } 1669 } 1670 result = isc_parse_uint32(&ttl, word, 10); 1671 if (result != ISC_R_SUCCESS) { 1672 if (isdelete) { 1673 ttl = 0; 1674 goto parseclass; 1675 } else if (default_ttl_set) { 1676 ttl = default_ttl; 1677 goto parseclass; 1678 } else { 1679 fprintf(stderr, "ttl '%s': %s\n", word, 1680 isc_result_totext(result)); 1681 goto failure; 1682 } 1683 } 1684 1685 if (isdelete) 1686 ttl = 0; 1687 else if (ttl > TTL_MAX) { 1688 fprintf(stderr, "ttl '%s' is out of range (0 to %u)\n", 1689 word, TTL_MAX); 1690 goto failure; 1691 } 1692 1693 /* 1694 * Read the class or type. 1695 */ 1696 word = nsu_strsep(&cmdline, " \t\r\n"); 1697 parseclass: 1698 if (word == NULL || *word == 0) { 1699 if (isdelete) { 1700 rdataclass = dns_rdataclass_any; 1701 rdatatype = dns_rdatatype_any; 1702 rdata->flags = DNS_RDATA_UPDATE; 1703 goto doneparsing; 1704 } else { 1705 fprintf(stderr, "could not read class or type\n"); 1706 goto failure; 1707 } 1708 } 1709 region.base = word; 1710 region.length = strlen(word); 1711 rdataclass = dns_rdataclass_any; 1712 result = dns_rdataclass_fromtext(&rdataclass, ®ion); 1713 if (result == ISC_R_SUCCESS && rdataclass != dns_rdataclass_any) { 1714 if (!setzoneclass(rdataclass)) { 1715 fprintf(stderr, "class mismatch: %s\n", word); 1716 goto failure; 1717 } 1718 /* 1719 * Now read the type. 1720 */ 1721 word = nsu_strsep(&cmdline, " \t\r\n"); 1722 if (word == NULL || *word == 0) { 1723 if (isdelete) { 1724 rdataclass = dns_rdataclass_any; 1725 rdatatype = dns_rdatatype_any; 1726 rdata->flags = DNS_RDATA_UPDATE; 1727 goto doneparsing; 1728 } else { 1729 fprintf(stderr, "could not read type\n"); 1730 goto failure; 1731 } 1732 } 1733 region.base = word; 1734 region.length = strlen(word); 1735 result = dns_rdatatype_fromtext(&rdatatype, ®ion); 1736 if (result != ISC_R_SUCCESS) { 1737 fprintf(stderr, "'%s' is not a valid type: %s\n", 1738 word, isc_result_totext(result)); 1739 goto failure; 1740 } 1741 } else { 1742 rdataclass = getzoneclass(); 1743 result = dns_rdatatype_fromtext(&rdatatype, ®ion); 1744 if (result != ISC_R_SUCCESS) { 1745 fprintf(stderr, "'%s' is not a valid class or type: " 1746 "%s\n", word, isc_result_totext(result)); 1747 goto failure; 1748 } 1749 } 1750 1751 retval = parse_rdata(&cmdline, rdataclass, rdatatype, updatemsg, 1752 rdata); 1753 if (retval != STATUS_MORE) 1754 goto failure; 1755 1756 if (isdelete) { 1757 if ((rdata->flags & DNS_RDATA_UPDATE) != 0) 1758 rdataclass = dns_rdataclass_any; 1759 else 1760 rdataclass = dns_rdataclass_none; 1761 } else { 1762 if ((rdata->flags & DNS_RDATA_UPDATE) != 0) { 1763 fprintf(stderr, "could not read rdata\n"); 1764 goto failure; 1765 } 1766 } 1767 1768 doneparsing: 1769 1770 result = dns_message_gettemprdatalist(updatemsg, &rdatalist); 1771 check_result(result, "dns_message_gettemprdatalist"); 1772 result = dns_message_gettemprdataset(updatemsg, &rdataset); 1773 check_result(result, "dns_message_gettemprdataset"); 1774 dns_rdatalist_init(rdatalist); 1775 rdatalist->type = rdatatype; 1776 rdatalist->rdclass = rdataclass; 1777 rdatalist->covers = rdatatype; 1778 rdatalist->ttl = (dns_ttl_t)ttl; 1779 ISC_LIST_INIT(rdatalist->rdata); 1780 ISC_LIST_APPEND(rdatalist->rdata, rdata, link); 1781 dns_rdataset_init(rdataset); 1782 dns_rdatalist_tordataset(rdatalist, rdataset); 1783 ISC_LIST_INIT(name->list); 1784 ISC_LIST_APPEND(name->list, rdataset, link); 1785 dns_message_addname(updatemsg, name, DNS_SECTION_UPDATE); 1786 return (STATUS_MORE); 1787 1788 failure: 1789 if (name != NULL) 1790 dns_message_puttempname(updatemsg, &name); 1791 dns_message_puttemprdata(updatemsg, &rdata); 1792 return (STATUS_SYNTAX); 1793} 1794 1795static isc_uint16_t 1796evaluate_update(char *cmdline) { 1797 char *word; 1798 isc_boolean_t isdelete; 1799 1800 ddebug("evaluate_update()"); 1801 word = nsu_strsep(&cmdline, " \t\r\n"); 1802 if (word == NULL || *word == 0) { 1803 fprintf(stderr, "could not read operation code\n"); 1804 return (STATUS_SYNTAX); 1805 } 1806 if (strcasecmp(word, "delete") == 0) 1807 isdelete = ISC_TRUE; 1808 else if (strcasecmp(word, "add") == 0) 1809 isdelete = ISC_FALSE; 1810 else { 1811 fprintf(stderr, "incorrect operation code: %s\n", word); 1812 return (STATUS_SYNTAX); 1813 } 1814 return (update_addordelete(cmdline, isdelete)); 1815} 1816 1817static void 1818setzone(dns_name_t *zonename) { 1819 isc_result_t result; 1820 dns_name_t *name = NULL; 1821 dns_rdataset_t *rdataset = NULL; 1822 1823 result = dns_message_firstname(updatemsg, DNS_SECTION_ZONE); 1824 if (result == ISC_R_SUCCESS) { 1825 dns_message_currentname(updatemsg, DNS_SECTION_ZONE, &name); 1826 dns_message_removename(updatemsg, name, DNS_SECTION_ZONE); 1827 for (rdataset = ISC_LIST_HEAD(name->list); 1828 rdataset != NULL; 1829 rdataset = ISC_LIST_HEAD(name->list)) { 1830 ISC_LIST_UNLINK(name->list, rdataset, link); 1831 dns_rdataset_disassociate(rdataset); 1832 dns_message_puttemprdataset(updatemsg, &rdataset); 1833 } 1834 dns_message_puttempname(updatemsg, &name); 1835 } 1836 1837 if (zonename != NULL) { 1838 result = dns_message_gettempname(updatemsg, &name); 1839 check_result(result, "dns_message_gettempname"); 1840 dns_name_init(name, NULL); 1841 dns_name_clone(zonename, name); 1842 result = dns_message_gettemprdataset(updatemsg, &rdataset); 1843 check_result(result, "dns_message_gettemprdataset"); 1844 dns_rdataset_makequestion(rdataset, getzoneclass(), 1845 dns_rdatatype_soa); 1846 ISC_LIST_INIT(name->list); 1847 ISC_LIST_APPEND(name->list, rdataset, link); 1848 dns_message_addname(updatemsg, name, DNS_SECTION_ZONE); 1849 } 1850} 1851 1852static void 1853show_message(FILE *stream, dns_message_t *msg, const char *description) { 1854 isc_result_t result; 1855 isc_buffer_t *buf = NULL; 1856 int bufsz; 1857 1858 ddebug("show_message()"); 1859 1860 setzone(userzone); 1861 1862 bufsz = INITTEXT; 1863 do { 1864 if (bufsz > MAXTEXT) { 1865 fprintf(stderr, "could not allocate large enough " 1866 "buffer to display message\n"); 1867 exit(1); 1868 } 1869 if (buf != NULL) 1870 isc_buffer_free(&buf); 1871 result = isc_buffer_allocate(mctx, &buf, bufsz); 1872 check_result(result, "isc_buffer_allocate"); 1873 result = dns_message_totext(msg, style, 0, buf); 1874 bufsz *= 2; 1875 } while (result == ISC_R_NOSPACE); 1876 if (result != ISC_R_SUCCESS) { 1877 fprintf(stderr, "could not convert message to text format.\n"); 1878 isc_buffer_free(&buf); 1879 return; 1880 } 1881 fprintf(stream, "%s\n%.*s", description, 1882 (int)isc_buffer_usedlength(buf), (char*)isc_buffer_base(buf)); 1883 isc_buffer_free(&buf); 1884} 1885 1886 1887static isc_uint16_t 1888get_next_command(void) { 1889 char cmdlinebuf[MAXCMD]; 1890 char *cmdline; 1891 char *word; 1892 char *tmp; 1893 1894 ddebug("get_next_command()"); 1895 if (interactive) { 1896 fprintf(stdout, "> "); 1897 fflush(stdout); 1898 } 1899 isc_app_block(); 1900 cmdline = fgets(cmdlinebuf, MAXCMD, input); 1901 isc_app_unblock(); 1902 if (cmdline == NULL) 1903 return (STATUS_QUIT); 1904 1905 /* 1906 * Normalize input by removing any eol. 1907 */ 1908 tmp = cmdline; 1909 (void)nsu_strsep(&tmp, "\r\n"); 1910 1911 word = nsu_strsep(&cmdline, " \t\r\n"); 1912 1913 if (feof(input)) 1914 return (STATUS_QUIT); 1915 if (word == NULL || *word == 0) 1916 return (STATUS_SEND); 1917 if (word[0] == ';') 1918 return (STATUS_MORE); 1919 if (strcasecmp(word, "quit") == 0) 1920 return (STATUS_QUIT); 1921 if (strcasecmp(word, "prereq") == 0) 1922 return (evaluate_prereq(cmdline)); 1923 if (strcasecmp(word, "update") == 0) 1924 return (evaluate_update(cmdline)); 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 delete .... (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_boolean_t 2004user_interaction(void) { 2005 isc_uint16_t result = STATUS_MORE; 2006 2007 ddebug("user_interaction()"); 2008 while ((result == STATUS_MORE) || (result == STATUS_SYNTAX)) { 2009 result = get_next_command(); 2010 if (!interactive && result == STATUS_SYNTAX) 2011 fatal("syntax error"); 2012 } 2013 if (result == STATUS_SEND) 2014 return (ISC_TRUE); 2015 return (ISC_FALSE); 2016 2017} 2018 2019static void 2020done_update(void) { 2021 isc_event_t *event = global_event; 2022 ddebug("done_update()"); 2023 isc_task_send(global_task, &event); 2024} 2025 2026static void 2027check_tsig_error(dns_rdataset_t *rdataset, isc_buffer_t *b) { 2028 isc_result_t result; 2029 dns_rdata_t rdata = DNS_RDATA_INIT; 2030 dns_rdata_any_tsig_t tsig; 2031 2032 result = dns_rdataset_first(rdataset); 2033 check_result(result, "dns_rdataset_first"); 2034 dns_rdataset_current(rdataset, &rdata); 2035 result = dns_rdata_tostruct(&rdata, &tsig, NULL); 2036 check_result(result, "dns_rdata_tostruct"); 2037 if (tsig.error != 0) { 2038 if (isc_buffer_remaininglength(b) < 1) 2039 check_result(ISC_R_NOSPACE, "isc_buffer_remaininglength"); 2040 isc__buffer_putstr(b, "(" /*)*/); 2041 result = dns_tsigrcode_totext(tsig.error, b); 2042 check_result(result, "dns_tsigrcode_totext"); 2043 if (isc_buffer_remaininglength(b) < 1) 2044 check_result(ISC_R_NOSPACE, "isc_buffer_remaininglength"); 2045 isc__buffer_putstr(b, /*(*/ ")"); 2046 } 2047} 2048 2049static void 2050update_completed(isc_task_t *task, isc_event_t *event) { 2051 dns_requestevent_t *reqev = NULL; 2052 isc_result_t result; 2053 dns_request_t *request; 2054 2055 UNUSED(task); 2056 2057 ddebug("update_completed()"); 2058 2059 requests--; 2060 2061 REQUIRE(event->ev_type == DNS_EVENT_REQUESTDONE); 2062 reqev = (dns_requestevent_t *)event; 2063 request = reqev->request; 2064 2065 if (shuttingdown) { 2066 dns_request_destroy(&request); 2067 isc_event_free(&event); 2068 maybeshutdown(); 2069 return; 2070 } 2071 2072 if (reqev->result != ISC_R_SUCCESS) { 2073 fprintf(stderr, "; Communication with server failed: %s\n", 2074 isc_result_totext(reqev->result)); 2075 seenerror = ISC_TRUE; 2076 goto done; 2077 } 2078 2079 result = dns_message_create(mctx, DNS_MESSAGE_INTENTPARSE, &answer); 2080 check_result(result, "dns_message_create"); 2081 result = dns_request_getresponse(request, answer, 2082 DNS_MESSAGEPARSE_PRESERVEORDER); 2083 switch (result) { 2084 case ISC_R_SUCCESS: 2085 if (answer->verify_attempted) 2086 ddebug("tsig verification successful"); 2087 break; 2088 case DNS_R_CLOCKSKEW: 2089 case DNS_R_EXPECTEDTSIG: 2090 case DNS_R_TSIGERRORSET: 2091 case DNS_R_TSIGVERIFYFAILURE: 2092 case DNS_R_UNEXPECTEDTSIG: 2093 case ISC_R_FAILURE: 2094#if 0 2095 if (usegsstsig && answer->rcode == dns_rcode_noerror) { 2096 /* 2097 * For MS DNS that violates RFC 2845, section 4.2 2098 */ 2099 break; 2100 } 2101#endif 2102 fprintf(stderr, "; TSIG error with server: %s\n", 2103 isc_result_totext(result)); 2104 seenerror = ISC_TRUE; 2105 break; 2106 default: 2107 check_result(result, "dns_request_getresponse"); 2108 } 2109 2110 if (answer->rcode != dns_rcode_noerror) { 2111 seenerror = ISC_TRUE; 2112 if (!debugging) { 2113 char buf[64]; 2114 isc_buffer_t b; 2115 dns_rdataset_t *rds; 2116 2117 isc_buffer_init(&b, buf, sizeof(buf) - 1); 2118 result = dns_rcode_totext(answer->rcode, &b); 2119 check_result(result, "dns_rcode_totext"); 2120 rds = dns_message_gettsig(answer, NULL); 2121 if (rds != NULL) 2122 check_tsig_error(rds, &b); 2123 fprintf(stderr, "update failed: %.*s\n", 2124 (int)isc_buffer_usedlength(&b), buf); 2125 } 2126 } 2127 if (debugging) 2128 show_message(stderr, answer, "\nReply from update query:"); 2129 2130 done: 2131 dns_request_destroy(&request); 2132 if (usegsstsig) { 2133 dns_name_free(&tmpzonename, mctx); 2134 dns_name_free(&restart_master, mctx); 2135 } 2136 isc_event_free(&event); 2137 done_update(); 2138} 2139 2140static void 2141send_update(dns_name_t *zonename, isc_sockaddr_t *master, 2142 isc_sockaddr_t *srcaddr) 2143{ 2144 isc_result_t result; 2145 dns_request_t *request = NULL; 2146 unsigned int options = DNS_REQUESTOPT_CASE; 2147 2148 ddebug("send_update()"); 2149 2150 setzone(zonename); 2151 2152 if (usevc) 2153 options |= DNS_REQUESTOPT_TCP; 2154 if (tsigkey == NULL && sig0key != NULL) { 2155 result = dns_message_setsig0key(updatemsg, sig0key); 2156 check_result(result, "dns_message_setsig0key"); 2157 } 2158 if (debugging) { 2159 char addrbuf[ISC_SOCKADDR_FORMATSIZE]; 2160 2161 isc_sockaddr_format(master, addrbuf, sizeof(addrbuf)); 2162 fprintf(stderr, "Sending update to %s\n", addrbuf); 2163 } 2164 2165 /* Windows doesn't like the tsig name to be compressed. */ 2166 if (updatemsg->tsigname) 2167 updatemsg->tsigname->attributes |= DNS_NAMEATTR_NOCOMPRESS; 2168 2169 result = dns_request_createvia3(requestmgr, updatemsg, srcaddr, 2170 master, options, tsigkey, timeout, 2171 udp_timeout, udp_retries, global_task, 2172 update_completed, NULL, &request); 2173 check_result(result, "dns_request_createvia3"); 2174 2175 if (debugging) 2176 show_message(stdout, updatemsg, "Outgoing update query:"); 2177 2178 requests++; 2179} 2180 2181static void 2182recvsoa(isc_task_t *task, isc_event_t *event) { 2183 dns_requestevent_t *reqev = NULL; 2184 dns_request_t *request = NULL; 2185 isc_result_t result, eresult; 2186 dns_message_t *rcvmsg = NULL; 2187 dns_section_t section; 2188 dns_name_t *name = NULL; 2189 dns_rdataset_t *soaset = NULL; 2190 dns_rdata_soa_t soa; 2191 dns_rdata_t soarr = DNS_RDATA_INIT; 2192 int pass = 0; 2193 dns_name_t master; 2194 nsu_requestinfo_t *reqinfo; 2195 dns_message_t *soaquery = NULL; 2196 isc_sockaddr_t *addr; 2197 isc_boolean_t seencname = ISC_FALSE; 2198 dns_name_t tname; 2199 unsigned int nlabels; 2200 2201 UNUSED(task); 2202 2203 ddebug("recvsoa()"); 2204 2205 requests--; 2206 2207 REQUIRE(event->ev_type == DNS_EVENT_REQUESTDONE); 2208 reqev = (dns_requestevent_t *)event; 2209 request = reqev->request; 2210 eresult = reqev->result; 2211 reqinfo = reqev->ev_arg; 2212 soaquery = reqinfo->msg; 2213 addr = reqinfo->addr; 2214 2215 if (shuttingdown) { 2216 dns_request_destroy(&request); 2217 dns_message_destroy(&soaquery); 2218 isc_mem_put(mctx, reqinfo, sizeof(nsu_requestinfo_t)); 2219 isc_event_free(&event); 2220 maybeshutdown(); 2221 return; 2222 } 2223 2224 if (eresult != ISC_R_SUCCESS) { 2225 char addrbuf[ISC_SOCKADDR_FORMATSIZE]; 2226 2227 isc_sockaddr_format(addr, addrbuf, sizeof(addrbuf)); 2228 fprintf(stderr, "; Communication with %s failed: %s\n", 2229 addrbuf, isc_result_totext(eresult)); 2230 if (userserver != NULL) 2231 fatal("could not talk to specified name server"); 2232 else if (++ns_inuse >= lwconf->nsnext) 2233 fatal("could not talk to any default name server"); 2234 ddebug("Destroying request [%p]", request); 2235 dns_request_destroy(&request); 2236 dns_message_renderreset(soaquery); 2237 dns_message_settsigkey(soaquery, NULL); 2238 sendrequest(localaddr, &servers[ns_inuse], soaquery, &request); 2239 isc_mem_put(mctx, reqinfo, sizeof(nsu_requestinfo_t)); 2240 isc_event_free(&event); 2241 setzoneclass(dns_rdataclass_none); 2242 return; 2243 } 2244 2245 isc_mem_put(mctx, reqinfo, sizeof(nsu_requestinfo_t)); 2246 reqinfo = NULL; 2247 isc_event_free(&event); 2248 reqev = NULL; 2249 2250 ddebug("About to create rcvmsg"); 2251 result = dns_message_create(mctx, DNS_MESSAGE_INTENTPARSE, &rcvmsg); 2252 check_result(result, "dns_message_create"); 2253 result = dns_request_getresponse(request, rcvmsg, 2254 DNS_MESSAGEPARSE_PRESERVEORDER); 2255 if (result == DNS_R_TSIGERRORSET && userserver != NULL) { 2256 dns_message_destroy(&rcvmsg); 2257 ddebug("Destroying request [%p]", request); 2258 dns_request_destroy(&request); 2259 reqinfo = isc_mem_get(mctx, sizeof(nsu_requestinfo_t)); 2260 if (reqinfo == NULL) 2261 fatal("out of memory"); 2262 reqinfo->msg = soaquery; 2263 reqinfo->addr = addr; 2264 dns_message_renderreset(soaquery); 2265 ddebug("retrying soa request without TSIG"); 2266 result = dns_request_createvia3(requestmgr, soaquery, 2267 localaddr, addr, 0, NULL, 2268 FIND_TIMEOUT * 20, 2269 FIND_TIMEOUT, 3, 2270 global_task, recvsoa, reqinfo, 2271 &request); 2272 check_result(result, "dns_request_createvia"); 2273 requests++; 2274 return; 2275 } 2276 check_result(result, "dns_request_getresponse"); 2277 section = DNS_SECTION_ANSWER; 2278 POST(section); 2279 if (debugging) 2280 show_message(stderr, rcvmsg, "Reply from SOA query:"); 2281 2282 if (rcvmsg->rcode != dns_rcode_noerror && 2283 rcvmsg->rcode != dns_rcode_nxdomain) 2284 fatal("response to SOA query was unsuccessful"); 2285 2286 if (userzone != NULL && rcvmsg->rcode == dns_rcode_nxdomain) { 2287 char namebuf[DNS_NAME_FORMATSIZE]; 2288 dns_name_format(userzone, namebuf, sizeof(namebuf)); 2289 error("specified zone '%s' does not exist (NXDOMAIN)", 2290 namebuf); 2291 dns_message_destroy(&rcvmsg); 2292 dns_request_destroy(&request); 2293 dns_message_destroy(&soaquery); 2294 ddebug("Out of recvsoa"); 2295 done_update(); 2296 seenerror = ISC_TRUE; 2297 return; 2298 } 2299 2300 lookforsoa: 2301 if (pass == 0) 2302 section = DNS_SECTION_ANSWER; 2303 else if (pass == 1) 2304 section = DNS_SECTION_AUTHORITY; 2305 else 2306 goto droplabel; 2307 2308 result = dns_message_firstname(rcvmsg, section); 2309 if (result != ISC_R_SUCCESS) { 2310 pass++; 2311 goto lookforsoa; 2312 } 2313 while (result == ISC_R_SUCCESS) { 2314 name = NULL; 2315 dns_message_currentname(rcvmsg, section, &name); 2316 soaset = NULL; 2317 result = dns_message_findtype(name, dns_rdatatype_soa, 0, 2318 &soaset); 2319 if (result == ISC_R_SUCCESS) 2320 break; 2321 if (section == DNS_SECTION_ANSWER) { 2322 dns_rdataset_t *tset = NULL; 2323 if (dns_message_findtype(name, dns_rdatatype_cname, 0, 2324 &tset) == ISC_R_SUCCESS || 2325 dns_message_findtype(name, dns_rdatatype_dname, 0, 2326 &tset) == ISC_R_SUCCESS ) { 2327 seencname = ISC_TRUE; 2328 break; 2329 } 2330 } 2331 2332 result = dns_message_nextname(rcvmsg, section); 2333 } 2334 2335 if (soaset == NULL && !seencname) { 2336 pass++; 2337 goto lookforsoa; 2338 } 2339 2340 if (seencname) 2341 goto droplabel; 2342 2343 if (debugging) { 2344 char namestr[DNS_NAME_FORMATSIZE]; 2345 dns_name_format(name, namestr, sizeof(namestr)); 2346 fprintf(stderr, "Found zone name: %s\n", namestr); 2347 } 2348 2349 result = dns_rdataset_first(soaset); 2350 check_result(result, "dns_rdataset_first"); 2351 2352 dns_rdata_init(&soarr); 2353 dns_rdataset_current(soaset, &soarr); 2354 result = dns_rdata_tostruct(&soarr, &soa, NULL); 2355 check_result(result, "dns_rdata_tostruct"); 2356 2357 dns_name_init(&master, NULL); 2358 dns_name_clone(&soa.origin, &master); 2359 2360 if (userzone != NULL) 2361 zonename = userzone; 2362 else 2363 zonename = name; 2364 2365 if (debugging) { 2366 char namestr[DNS_NAME_FORMATSIZE]; 2367 dns_name_format(&master, namestr, sizeof(namestr)); 2368 fprintf(stderr, "The master is: %s\n", namestr); 2369 } 2370 2371 if (userserver != NULL) 2372 serveraddr = userserver; 2373 else { 2374 char serverstr[DNS_NAME_MAXTEXT+1]; 2375 isc_buffer_t buf; 2376 2377 isc_buffer_init(&buf, serverstr, sizeof(serverstr)); 2378 result = dns_name_totext(&master, ISC_TRUE, &buf); 2379 check_result(result, "dns_name_totext"); 2380 serverstr[isc_buffer_usedlength(&buf)] = 0; 2381 get_address(serverstr, dnsport, &tempaddr); 2382 serveraddr = &tempaddr; 2383 } 2384 dns_rdata_freestruct(&soa); 2385 2386#ifdef GSSAPI 2387 if (usegsstsig) { 2388 dns_name_init(&tmpzonename, NULL); 2389 dns_name_dup(zonename, mctx, &tmpzonename); 2390 dns_name_init(&restart_master, NULL); 2391 dns_name_dup(&master, mctx, &restart_master); 2392 start_gssrequest(&master); 2393 } else { 2394 send_update(zonename, serveraddr, localaddr); 2395 setzoneclass(dns_rdataclass_none); 2396 } 2397#else 2398 send_update(zonename, serveraddr, localaddr); 2399 setzoneclass(dns_rdataclass_none); 2400#endif 2401 2402 dns_message_destroy(&soaquery); 2403 dns_request_destroy(&request); 2404 2405 out: 2406 dns_message_destroy(&rcvmsg); 2407 ddebug("Out of recvsoa"); 2408 return; 2409 2410 droplabel: 2411 result = dns_message_firstname(soaquery, DNS_SECTION_QUESTION); 2412 INSIST(result == ISC_R_SUCCESS); 2413 name = NULL; 2414 dns_message_currentname(soaquery, DNS_SECTION_QUESTION, &name); 2415 nlabels = dns_name_countlabels(name); 2416 if (nlabels == 1) 2417 fatal("could not find enclosing zone"); 2418 dns_name_init(&tname, NULL); 2419 dns_name_getlabelsequence(name, 1, nlabels - 1, &tname); 2420 dns_name_clone(&tname, name); 2421 dns_request_destroy(&request); 2422 dns_message_renderreset(soaquery); 2423 dns_message_settsigkey(soaquery, NULL); 2424 if (userserver != NULL) 2425 sendrequest(localaddr, userserver, soaquery, &request); 2426 else 2427 sendrequest(localaddr, &servers[ns_inuse], soaquery, &request); 2428 goto out; 2429} 2430 2431static void 2432sendrequest(isc_sockaddr_t *srcaddr, isc_sockaddr_t *destaddr, 2433 dns_message_t *msg, dns_request_t **request) 2434{ 2435 isc_result_t result; 2436 nsu_requestinfo_t *reqinfo; 2437 2438 reqinfo = isc_mem_get(mctx, sizeof(nsu_requestinfo_t)); 2439 if (reqinfo == NULL) 2440 fatal("out of memory"); 2441 reqinfo->msg = msg; 2442 reqinfo->addr = destaddr; 2443 result = dns_request_createvia3(requestmgr, msg, srcaddr, destaddr, 0, 2444 (userserver != NULL) ? tsigkey : NULL, 2445 FIND_TIMEOUT * 20, FIND_TIMEOUT, 3, 2446 global_task, recvsoa, reqinfo, request); 2447 check_result(result, "dns_request_createvia"); 2448 requests++; 2449} 2450 2451#ifdef GSSAPI 2452 2453/* 2454 * Get the realm from the users kerberos ticket if possible 2455 */ 2456static void 2457get_ticket_realm(isc_mem_t *mctx) 2458{ 2459 krb5_context ctx; 2460 krb5_error_code rc; 2461 krb5_ccache ccache; 2462 krb5_principal princ; 2463 char *name, *ticket_realm; 2464 2465 rc = krb5_init_context(&ctx); 2466 if (rc != 0) 2467 return; 2468 2469 rc = krb5_cc_default(ctx, &ccache); 2470 if (rc != 0) { 2471 krb5_free_context(ctx); 2472 return; 2473 } 2474 2475 rc = krb5_cc_get_principal(ctx, ccache, &princ); 2476 if (rc != 0) { 2477 krb5_cc_close(ctx, ccache); 2478 krb5_free_context(ctx); 2479 return; 2480 } 2481 2482 rc = krb5_unparse_name(ctx, princ, &name); 2483 if (rc != 0) { 2484 krb5_free_principal(ctx, princ); 2485 krb5_cc_close(ctx, ccache); 2486 krb5_free_context(ctx); 2487 return; 2488 } 2489 2490 ticket_realm = strrchr(name, '@'); 2491 if (ticket_realm != NULL) { 2492 realm = isc_mem_strdup(mctx, ticket_realm); 2493 } 2494 2495 free(name); 2496 krb5_free_principal(ctx, princ); 2497 krb5_cc_close(ctx, ccache); 2498 krb5_free_context(ctx); 2499 if (realm != NULL && debugging) 2500 fprintf(stderr, "Found realm from ticket: %s\n", realm+1); 2501} 2502 2503 2504static void 2505start_gssrequest(dns_name_t *master) { 2506 gss_ctx_id_t context; 2507 isc_buffer_t buf; 2508 isc_result_t result; 2509 isc_uint32_t val = 0; 2510 dns_message_t *rmsg; 2511 dns_request_t *request = NULL; 2512 dns_name_t *servname; 2513 dns_fixedname_t fname; 2514 char namestr[DNS_NAME_FORMATSIZE]; 2515 char keystr[DNS_NAME_FORMATSIZE]; 2516 char *err_message = NULL; 2517 2518 debug("start_gssrequest"); 2519 usevc = ISC_TRUE; 2520 2521 if (gssring != NULL) 2522 dns_tsigkeyring_detach(&gssring); 2523 gssring = NULL; 2524 result = dns_tsigkeyring_create(mctx, &gssring); 2525 2526 if (result != ISC_R_SUCCESS) 2527 fatal("dns_tsigkeyring_create failed: %s", 2528 isc_result_totext(result)); 2529 2530 dns_name_format(master, namestr, sizeof(namestr)); 2531 if (kserver == NULL) { 2532 kserver = isc_mem_get(mctx, sizeof(isc_sockaddr_t)); 2533 if (kserver == NULL) 2534 fatal("out of memory"); 2535 } 2536 if (userserver == NULL) 2537 get_address(namestr, dnsport, kserver); 2538 else 2539 (void)memcpy(kserver, userserver, sizeof(isc_sockaddr_t)); 2540 2541 dns_fixedname_init(&fname); 2542 servname = dns_fixedname_name(&fname); 2543 2544 if (realm == NULL) 2545 get_ticket_realm(mctx); 2546 2547 result = isc_string_printf(servicename, sizeof(servicename), 2548 "DNS/%s%s", namestr, realm ? realm : ""); 2549 if (result != ISC_R_SUCCESS) 2550 fatal("isc_string_printf(servicename) failed: %s", 2551 isc_result_totext(result)); 2552 isc_buffer_init(&buf, servicename, strlen(servicename)); 2553 isc_buffer_add(&buf, strlen(servicename)); 2554 result = dns_name_fromtext(servname, &buf, dns_rootname, 0, NULL); 2555 if (result != ISC_R_SUCCESS) 2556 fatal("dns_name_fromtext(servname) failed: %s", 2557 isc_result_totext(result)); 2558 2559 dns_fixedname_init(&fkname); 2560 keyname = dns_fixedname_name(&fkname); 2561 2562 isc_random_get(&val); 2563 result = isc_string_printf(keystr, sizeof(keystr), "%u.sig-%s", 2564 val, namestr); 2565 if (result != ISC_R_SUCCESS) 2566 fatal("isc_string_printf(keystr) failed: %s", 2567 isc_result_totext(result)); 2568 isc_buffer_init(&buf, keystr, strlen(keystr)); 2569 isc_buffer_add(&buf, strlen(keystr)); 2570 2571 result = dns_name_fromtext(keyname, &buf, dns_rootname, 0, NULL); 2572 if (result != ISC_R_SUCCESS) 2573 fatal("dns_name_fromtext(keyname) failed: %s", 2574 isc_result_totext(result)); 2575 2576 /* Windows doesn't recognize name compression in the key name. */ 2577 keyname->attributes |= DNS_NAMEATTR_NOCOMPRESS; 2578 2579 rmsg = NULL; 2580 result = dns_message_create(mctx, DNS_MESSAGE_INTENTRENDER, &rmsg); 2581 if (result != ISC_R_SUCCESS) 2582 fatal("dns_message_create failed: %s", 2583 isc_result_totext(result)); 2584 2585 /* Build first request. */ 2586 context = GSS_C_NO_CONTEXT; 2587 result = dns_tkey_buildgssquery(rmsg, keyname, servname, NULL, 0, 2588 &context, use_win2k_gsstsig, 2589 mctx, &err_message); 2590 if (result == ISC_R_FAILURE) 2591 fatal("tkey query failed: %s", 2592 err_message != NULL ? err_message : "unknown error"); 2593 if (result != ISC_R_SUCCESS) 2594 fatal("dns_tkey_buildgssquery failed: %s", 2595 isc_result_totext(result)); 2596 2597 send_gssrequest(localaddr, kserver, rmsg, &request, context); 2598} 2599 2600static void 2601send_gssrequest(isc_sockaddr_t *srcaddr, isc_sockaddr_t *destaddr, 2602 dns_message_t *msg, dns_request_t **request, 2603 gss_ctx_id_t context) 2604{ 2605 isc_result_t result; 2606 nsu_gssinfo_t *reqinfo; 2607 unsigned int options = 0; 2608 2609 debug("send_gssrequest"); 2610 reqinfo = isc_mem_get(mctx, sizeof(nsu_gssinfo_t)); 2611 if (reqinfo == NULL) 2612 fatal("out of memory"); 2613 reqinfo->msg = msg; 2614 reqinfo->addr = destaddr; 2615 reqinfo->context = context; 2616 2617 options |= DNS_REQUESTOPT_TCP; 2618 result = dns_request_createvia3(requestmgr, msg, srcaddr, destaddr, 2619 options, tsigkey, FIND_TIMEOUT * 20, 2620 FIND_TIMEOUT, 3, global_task, recvgss, 2621 reqinfo, request); 2622 check_result(result, "dns_request_createvia3"); 2623 if (debugging) 2624 show_message(stdout, msg, "Outgoing update query:"); 2625 requests++; 2626} 2627 2628static void 2629recvgss(isc_task_t *task, isc_event_t *event) { 2630 dns_requestevent_t *reqev = NULL; 2631 dns_request_t *request = NULL; 2632 isc_result_t result, eresult; 2633 dns_message_t *rcvmsg = NULL; 2634 nsu_gssinfo_t *reqinfo; 2635 dns_message_t *tsigquery = NULL; 2636 isc_sockaddr_t *addr; 2637 gss_ctx_id_t context; 2638 isc_buffer_t buf; 2639 dns_name_t *servname; 2640 dns_fixedname_t fname; 2641 char *err_message = NULL; 2642 2643 UNUSED(task); 2644 2645 ddebug("recvgss()"); 2646 2647 requests--; 2648 2649 REQUIRE(event->ev_type == DNS_EVENT_REQUESTDONE); 2650 reqev = (dns_requestevent_t *)event; 2651 request = reqev->request; 2652 eresult = reqev->result; 2653 reqinfo = reqev->ev_arg; 2654 tsigquery = reqinfo->msg; 2655 context = reqinfo->context; 2656 addr = reqinfo->addr; 2657 2658 if (shuttingdown) { 2659 dns_request_destroy(&request); 2660 dns_message_destroy(&tsigquery); 2661 isc_mem_put(mctx, reqinfo, sizeof(nsu_gssinfo_t)); 2662 isc_event_free(&event); 2663 maybeshutdown(); 2664 return; 2665 } 2666 2667 if (eresult != ISC_R_SUCCESS) { 2668 char addrbuf[ISC_SOCKADDR_FORMATSIZE]; 2669 2670 isc_sockaddr_format(addr, addrbuf, sizeof(addrbuf)); 2671 fprintf(stderr, "; Communication with %s failed: %s\n", 2672 addrbuf, isc_result_totext(eresult)); 2673 if (userserver != NULL) 2674 fatal("could not talk to specified name server"); 2675 else if (++ns_inuse >= lwconf->nsnext) 2676 fatal("could not talk to any default name server"); 2677 ddebug("Destroying request [%p]", request); 2678 dns_request_destroy(&request); 2679 dns_message_renderreset(tsigquery); 2680 sendrequest(localaddr, &servers[ns_inuse], tsigquery, 2681 &request); 2682 isc_mem_put(mctx, reqinfo, sizeof(nsu_gssinfo_t)); 2683 isc_event_free(&event); 2684 return; 2685 } 2686 isc_mem_put(mctx, reqinfo, sizeof(nsu_gssinfo_t)); 2687 2688 isc_event_free(&event); 2689 reqev = NULL; 2690 2691 ddebug("recvgss creating rcvmsg"); 2692 result = dns_message_create(mctx, DNS_MESSAGE_INTENTPARSE, &rcvmsg); 2693 check_result(result, "dns_message_create"); 2694 2695 result = dns_request_getresponse(request, rcvmsg, 2696 DNS_MESSAGEPARSE_PRESERVEORDER); 2697 check_result(result, "dns_request_getresponse"); 2698 2699 if (debugging) 2700 show_message(stderr, rcvmsg, 2701 "recvmsg reply from GSS-TSIG query"); 2702 2703 if (rcvmsg->rcode == dns_rcode_formerr && !tried_other_gsstsig) { 2704 ddebug("recvgss trying %s GSS-TSIG", 2705 use_win2k_gsstsig ? "Standard" : "Win2k"); 2706 if (use_win2k_gsstsig) 2707 use_win2k_gsstsig = ISC_FALSE; 2708 else 2709 use_win2k_gsstsig = ISC_TRUE; 2710 tried_other_gsstsig = ISC_TRUE; 2711 start_gssrequest(&restart_master); 2712 goto done; 2713 } 2714 2715 if (rcvmsg->rcode != dns_rcode_noerror && 2716 rcvmsg->rcode != dns_rcode_nxdomain) 2717 fatal("response to GSS-TSIG query was unsuccessful"); 2718 2719 2720 dns_fixedname_init(&fname); 2721 servname = dns_fixedname_name(&fname); 2722 isc_buffer_init(&buf, servicename, strlen(servicename)); 2723 isc_buffer_add(&buf, strlen(servicename)); 2724 result = dns_name_fromtext(servname, &buf, dns_rootname, 0, NULL); 2725 check_result(result, "dns_name_fromtext"); 2726 2727 tsigkey = NULL; 2728 result = dns_tkey_gssnegotiate(tsigquery, rcvmsg, servname, 2729 &context, &tsigkey, gssring, 2730 use_win2k_gsstsig, 2731 &err_message); 2732 switch (result) { 2733 2734 case DNS_R_CONTINUE: 2735 send_gssrequest(localaddr, kserver, tsigquery, &request, 2736 context); 2737 break; 2738 2739 case ISC_R_SUCCESS: 2740 /* 2741 * XXXSRA Waaay too much fun here. There's no good 2742 * reason why we need a TSIG here (the people who put 2743 * it into the spec admitted at the time that it was 2744 * not a security issue), and Windows clients don't 2745 * seem to work if named complies with the spec and 2746 * includes the gratuitous TSIG. So we're in the 2747 * bizarre situation of having to choose between 2748 * complying with a useless requirement in the spec 2749 * and interoperating. This is nuts. If we can 2750 * confirm this behavior, we should ask the WG to 2751 * consider removing the requirement for the 2752 * gratuitous TSIG here. For the moment, we ignore 2753 * the TSIG -- this too is a spec violation, but it's 2754 * the least insane thing to do. 2755 */ 2756#if 0 2757 /* 2758 * Verify the signature. 2759 */ 2760 rcvmsg->state = DNS_SECTION_ANY; 2761 dns_message_setquerytsig(rcvmsg, NULL); 2762 result = dns_message_settsigkey(rcvmsg, tsigkey); 2763 check_result(result, "dns_message_settsigkey"); 2764 result = dns_message_checksig(rcvmsg, NULL); 2765 ddebug("tsig verification: %s", dns_result_totext(result)); 2766 check_result(result, "dns_message_checksig"); 2767#endif /* 0 */ 2768 2769 send_update(&tmpzonename, serveraddr, localaddr); 2770 setzoneclass(dns_rdataclass_none); 2771 break; 2772 2773 default: 2774 fatal("dns_tkey_negotiategss: %s %s", 2775 isc_result_totext(result), 2776 err_message != NULL ? err_message : ""); 2777 } 2778 2779 done: 2780 dns_request_destroy(&request); 2781 dns_message_destroy(&tsigquery); 2782 2783 dns_message_destroy(&rcvmsg); 2784 ddebug("Out of recvgss"); 2785} 2786#endif 2787 2788static void 2789start_update(void) { 2790 isc_result_t result; 2791 dns_rdataset_t *rdataset = NULL; 2792 dns_name_t *name = NULL; 2793 dns_request_t *request = NULL; 2794 dns_message_t *soaquery = NULL; 2795 dns_name_t *firstname; 2796 dns_section_t section = DNS_SECTION_UPDATE; 2797 2798 ddebug("start_update()"); 2799 2800 if (answer != NULL) 2801 dns_message_destroy(&answer); 2802 2803 if (userzone != NULL && userserver != NULL && ! usegsstsig) { 2804 send_update(userzone, userserver, localaddr); 2805 setzoneclass(dns_rdataclass_none); 2806 return; 2807 } 2808 2809 result = dns_message_create(mctx, DNS_MESSAGE_INTENTRENDER, 2810 &soaquery); 2811 check_result(result, "dns_message_create"); 2812 2813 if (userserver == NULL) 2814 soaquery->flags |= DNS_MESSAGEFLAG_RD; 2815 2816 result = dns_message_gettempname(soaquery, &name); 2817 check_result(result, "dns_message_gettempname"); 2818 2819 result = dns_message_gettemprdataset(soaquery, &rdataset); 2820 check_result(result, "dns_message_gettemprdataset"); 2821 2822 dns_rdataset_makequestion(rdataset, getzoneclass(), dns_rdatatype_soa); 2823 2824 if (userzone != NULL) { 2825 dns_name_init(name, NULL); 2826 dns_name_clone(userzone, name); 2827 } else { 2828 dns_rdataset_t *tmprdataset; 2829 result = dns_message_firstname(updatemsg, section); 2830 if (result == ISC_R_NOMORE) { 2831 section = DNS_SECTION_PREREQUISITE; 2832 result = dns_message_firstname(updatemsg, section); 2833 } 2834 if (result != ISC_R_SUCCESS) { 2835 dns_message_puttempname(soaquery, &name); 2836 dns_rdataset_disassociate(rdataset); 2837 dns_message_puttemprdataset(soaquery, &rdataset); 2838 dns_message_destroy(&soaquery); 2839 done_update(); 2840 return; 2841 } 2842 firstname = NULL; 2843 dns_message_currentname(updatemsg, section, &firstname); 2844 dns_name_init(name, NULL); 2845 dns_name_clone(firstname, name); 2846 /* 2847 * Looks to see if the first name references a DS record 2848 * and if that name is not the root remove a label as DS 2849 * records live in the parent zone so we need to start our 2850 * search one label up. 2851 */ 2852 tmprdataset = ISC_LIST_HEAD(firstname->list); 2853 if (section == DNS_SECTION_UPDATE && 2854 !dns_name_equal(firstname, dns_rootname) && 2855 tmprdataset->type == dns_rdatatype_ds) { 2856 unsigned int labels = dns_name_countlabels(name); 2857 dns_name_getlabelsequence(name, 1, labels - 1, name); 2858 } 2859 } 2860 2861 ISC_LIST_INIT(name->list); 2862 ISC_LIST_APPEND(name->list, rdataset, link); 2863 dns_message_addname(soaquery, name, DNS_SECTION_QUESTION); 2864 2865 if (userserver != NULL) 2866 sendrequest(localaddr, userserver, soaquery, &request); 2867 else { 2868 ns_inuse = 0; 2869 sendrequest(localaddr, &servers[ns_inuse], soaquery, &request); 2870 } 2871} 2872 2873static void 2874cleanup(void) { 2875 ddebug("cleanup()"); 2876 2877 if (answer != NULL) 2878 dns_message_destroy(&answer); 2879 2880#ifdef GSSAPI 2881 if (tsigkey != NULL) { 2882 ddebug("detach tsigkey x%p", tsigkey); 2883 dns_tsigkey_detach(&tsigkey); 2884 } 2885 if (gssring != NULL) { 2886 ddebug("Detaching GSS-TSIG keyring"); 2887 dns_tsigkeyring_detach(&gssring); 2888 } 2889 if (kserver != NULL) { 2890 isc_mem_put(mctx, kserver, sizeof(isc_sockaddr_t)); 2891 kserver = NULL; 2892 } 2893 if (realm != NULL) { 2894 isc_mem_free(mctx, realm); 2895 realm = NULL; 2896 } 2897#endif 2898 2899 if (sig0key != NULL) 2900 dst_key_free(&sig0key); 2901 2902 ddebug("Shutting down task manager"); 2903 isc_taskmgr_destroy(&taskmgr); 2904 2905 ddebug("Destroying event"); 2906 isc_event_free(&global_event); 2907 2908 ddebug("Shutting down socket manager"); 2909 isc_socketmgr_destroy(&socketmgr); 2910 2911 ddebug("Shutting down timer manager"); 2912 isc_timermgr_destroy(&timermgr); 2913 2914 ddebug("Destroying hash context"); 2915 isc_hash_destroy(); 2916 2917 ddebug("Destroying name state"); 2918 dns_name_destroy(); 2919 2920 ddebug("Removing log context"); 2921 isc_log_destroy(&lctx); 2922 2923 ddebug("Destroying memory context"); 2924 if (memdebugging) 2925 isc_mem_stats(mctx, stderr); 2926 isc_mem_destroy(&mctx); 2927} 2928 2929static void 2930getinput(isc_task_t *task, isc_event_t *event) { 2931 isc_boolean_t more; 2932 2933 UNUSED(task); 2934 2935 if (shuttingdown) { 2936 maybeshutdown(); 2937 return; 2938 } 2939 2940 if (global_event == NULL) 2941 global_event = event; 2942 2943 reset_system(); 2944 more = user_interaction(); 2945 if (!more) { 2946 isc_app_shutdown(); 2947 return; 2948 } 2949 start_update(); 2950 return; 2951} 2952 2953int 2954main(int argc, char **argv) { 2955 isc_result_t result; 2956 style = &dns_master_style_debug; 2957 2958 input = stdin; 2959 2960 interactive = ISC_TF(isatty(0)); 2961 2962 isc_app_start(); 2963 2964 pre_parse_args(argc, argv); 2965 2966 result = isc_mem_create(0, 0, &mctx); 2967 check_result(result, "isc_mem_create"); 2968 2969 parse_args(argc, argv, mctx, &entropy); 2970 2971 setup_system(); 2972 2973 result = isc_app_onrun(mctx, global_task, getinput, NULL); 2974 check_result(result, "isc_app_onrun"); 2975 2976 (void)isc_app_run(); 2977 2978 cleanup(); 2979 2980 isc_app_finish(); 2981 2982 if (seenerror) 2983 return (2); 2984 else 2985 return (0); 2986} 2987