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