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