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