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