server.c 390 KB
Newer Older
1
/*
2
 * Copyright (C) 1999-2017  Internet Systems Consortium, Inc. ("ISC")
3
 *
4 5 6
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
7 8
 */

9
/*! \file */
David Lawrence's avatar
David Lawrence committed
10

11 12 13
#include <config.h>

#include <stdlib.h>
14
#include <unistd.h>
15
#include <limits.h>
16 17 18
#include <ctype.h>
#include <sys/types.h>
#include <sys/stat.h>
19

20
#include <isc/aes.h>
21
#include <isc/app.h>
22
#include <isc/base64.h>
Evan Hunt's avatar
Evan Hunt committed
23
#include <isc/commandline.h>
24
#include <isc/dir.h>
25
#include <isc/entropy.h>
26
#include <isc/file.h>
27
#include <isc/hash.h>
28
#include <isc/hex.h>
29
#include <isc/hmacsha.h>
30
#include <isc/httpd.h>
31
#include <isc/lex.h>
32
#include <isc/meminfo.h>
33
#include <isc/parseint.h>
Evan Hunt's avatar
Evan Hunt committed
34
#include <isc/platform.h>
35
#include <isc/portset.h>
36
#include <isc/print.h>
37
#include <isc/random.h>
38
#include <isc/refcount.h>
39
#include <isc/resource.h>
40
#include <isc/sha2.h>
Mark Andrews's avatar
Mark Andrews committed
41
#include <isc/socket.h>
42
#include <isc/stat.h>
43
#include <isc/stats.h>
44
#include <isc/stdio.h>
45
#include <isc/string.h>
46
#include <isc/task.h>
47
#include <isc/timer.h>
Michael Graff's avatar
Michael Graff committed
48
#include <isc/util.h>
49
#include <isc/xml.h>
50

Evan Hunt's avatar
Evan Hunt committed
51
#include <isccfg/grammar.h>
52
#include <isccfg/namedconf.h>
53 54

#include <bind9/check.h>
55

56
#include <dns/adb.h>
Evan Hunt's avatar
Evan Hunt committed
57
#include <dns/badcache.h>
58
#include <dns/cache.h>
59
#include <dns/catz.h>
60
#include <dns/db.h>
Bob Halley's avatar
Bob Halley committed
61
#include <dns/dispatch.h>
62
#include <dns/dlz.h>
63
#include <dns/dnsrps.h>
64
#include <dns/dns64.h>
Evan Hunt's avatar
Evan Hunt committed
65
#include <dns/dyndb.h>
66
#include <dns/events.h>
67
#include <dns/forward.h>
68
#include <dns/fixedname.h>
69
#include <dns/journal.h>
70
#include <dns/keytable.h>
71
#include <dns/keyvalues.h>
72
#include <dns/lib.h>
73
#include <dns/master.h>
74
#include <dns/masterdump.h>
Evan Hunt's avatar
Evan Hunt committed
75
#include <dns/nta.h>
76
#include <dns/order.h>
77
#include <dns/peer.h>
78
#include <dns/portlist.h>
79
#include <dns/private.h>
80
#include <dns/rbt.h>
81
#include <dns/rdataclass.h>
82
#include <dns/rdatalist.h>
83
#include <dns/rdataset.h>
84
#include <dns/rdatastruct.h>
85
#include <dns/resolver.h>
86
#include <dns/rootns.h>
Evan Hunt's avatar
Evan Hunt committed
87
#include <dns/rriterator.h>
88
#include <dns/secalg.h>
89
#include <dns/soa.h>
90
#include <dns/stats.h>
91
#include <dns/tkey.h>
92
#include <dns/tsig.h>
Evan Hunt's avatar
Evan Hunt committed
93
#include <dns/ttl.h>
94
#include <dns/view.h>
95
#include <dns/zone.h>
96
#include <dns/zt.h>
97

98
#include <dst/dst.h>
99
#include <dst/result.h>
100

101 102 103 104
#include <ns/client.h>
#include <ns/listenlist.h>
#include <ns/interfacemgr.h>

105
#include <named/config.h>
106
#include <named/control.h>
107
#ifdef HAVE_GEOIP
Evan Hunt's avatar
Evan Hunt committed
108
#include <named/geoip.h>
109
#endif /* HAVE_GEOIP */
110
#include <named/log.h>
111
#include <named/logconf.h>
112
#include <named/main.h>
113
#include <named/os.h>
Bob Halley's avatar
Bob Halley committed
114
#include <named/server.h>
115
#include <named/statschannel.h>
116 117 118
#include <named/tkeyconf.h>
#include <named/tsigconf.h>
#include <named/zoneconf.h>
119
#ifdef HAVE_LIBSCF
120
#include <named/smf_globals.h>
121 122
#include <stdlib.h>
#endif
123 124 125 126 127 128 129 130 131 132 133

#ifdef HAVE_LMDB
#include <lmdb.h>
#define count_newzones count_newzones_db
#define configure_newzones configure_newzones_db
#define dumpzone dumpzone_db
#else  /* HAVE_LMDB */
#define count_newzones count_newzones_file
#define configure_newzones configure_newzones_file
#define dumpzone dumpzone_file
#endif /* HAVE_LMDB */
134

135 136 137 138
#ifndef PATH_MAX
#define PATH_MAX 1024
#endif

139 140 141 142
#ifndef SIZE_MAX
#define SIZE_MAX ((size_t)-1)
#endif

143 144 145 146
#ifndef SIZE_AS_PERCENT
#define SIZE_AS_PERCENT ((size_t)-2)
#endif

147 148 149 150 151 152 153 154 155 156
#ifdef TUNE_LARGE
#define RESOLVER_NTASKS 523
#define UDPBUFFERS 32768
#define EXCLBUFFERS 32768
#else
#define RESOLVER_NTASKS 31
#define UDPBUFFERS 1000
#define EXCLBUFFERS 4096
#endif /* TUNE_LARGE */

157
/*%
158 159 160 161
 * Check an operation for failure.  Assumes that the function
 * using it has a 'result' variable and a 'cleanup' label.
 */
#define CHECK(op) \
162 163
	do { result = (op);					 \
	       if (result != ISC_R_SUCCESS) goto cleanup;	 \
164 165
	} while (0)

166 167 168
#define TCHECK(op) \
	do { tresult = (op);					 \
		if (tresult != ISC_R_SUCCESS) {			 \
169
			isc_buffer_clear(*text);		 \
170 171 172 173
			goto cleanup;	 			 \
		}						 \
	} while (0)

174
#define CHECKM(op, msg) \
175
	do { result = (op);					  \
176
	       if (result != ISC_R_SUCCESS) {			  \
177 178 179
			isc_log_write(named_g_lctx,		  \
				      NAMED_LOGCATEGORY_GENERAL,	  \
				      NAMED_LOGMODULE_SERVER,	  \
180 181 182 183 184 185 186
				      ISC_LOG_ERROR,		  \
				      "%s: %s", msg,		  \
				      isc_result_totext(result)); \
			goto cleanup;				  \
		}						  \
	} while (0)						  \

Mark Andrews's avatar
Mark Andrews committed
187
#define CHECKMF(op, msg, file) \
188
	do { result = (op);					  \
Mark Andrews's avatar
Mark Andrews committed
189
	       if (result != ISC_R_SUCCESS) {			  \
190 191 192
			isc_log_write(named_g_lctx,		  \
				      NAMED_LOGCATEGORY_GENERAL,	  \
				      NAMED_LOGMODULE_SERVER,	  \
Mark Andrews's avatar
Mark Andrews committed
193 194 195 196 197 198 199
				      ISC_LOG_ERROR,		  \
				      "%s '%s': %s", msg, file,	  \
				      isc_result_totext(result)); \
			goto cleanup;				  \
		}						  \
	} while (0)						  \

200
#define CHECKFATAL(op, msg) \
201
	do { result = (op);					  \
202 203 204 205
	       if (result != ISC_R_SUCCESS)			  \
			fatal(msg, result);			  \
	} while (0)						  \

206 207 208 209 210 211
/*%
 * Maximum ADB size for views that share a cache.  Use this limit to suppress
 * the total of memory footprint, which should be the main reason for sharing
 * a cache.  Only effective when a finite max-cache-size is specified.
 * This is currently defined to be 8MB.
 */
Mark Andrews's avatar
Mark Andrews committed
212
#define MAX_ADB_SIZE_FOR_CACHESHARE	8388608U
213

214
struct named_dispatch {
215 216 217
	isc_sockaddr_t			addr;
	unsigned int			dispatchgen;
	dns_dispatch_t			*dispatch;
218
	ISC_LINK(struct named_dispatch)	link;
219 220
};

221
struct named_cache {
222 223 224 225
	dns_cache_t			*cache;
	dns_view_t			*primaryview;
	isc_boolean_t			needflush;
	isc_boolean_t			adbsizeadjusted;
226
	dns_rdataclass_t		rdclass;
227
	ISC_LINK(named_cache_t)		link;
228 229
};

230 231 232 233
struct dumpcontext {
	isc_mem_t			*mctx;
	isc_boolean_t			dumpcache;
	isc_boolean_t			dumpzones;
Evan Hunt's avatar
Evan Hunt committed
234 235 236
	isc_boolean_t			dumpadb;
	isc_boolean_t			dumpbad;
	isc_boolean_t			dumpfail;
237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258
	FILE				*fp;
	ISC_LIST(struct viewlistentry)	viewlist;
	struct viewlistentry		*view;
	struct zonelistentry		*zone;
	dns_dumpctx_t			*mdctx;
	dns_db_t			*db;
	dns_db_t			*cache;
	isc_task_t			*task;
	dns_dbversion_t			*version;
};

struct viewlistentry {
	dns_view_t			*view;
	ISC_LINK(struct viewlistentry)	link;
	ISC_LIST(struct zonelistentry)	zonelist;
};

struct zonelistentry {
	dns_zone_t			*zone;
	ISC_LINK(struct zonelistentry)	link;
};

259 260
/*%
 * Configuration context to retain for each view that allows
261
 * new zones to be added at runtime.
262
 */
Evan Hunt's avatar
Evan Hunt committed
263
typedef struct ns_cfgctx {
264
	isc_mem_t *			mctx;
265 266
	cfg_parser_t *			conf_parser;
	cfg_parser_t *			add_parser;
267
	cfg_obj_t *			config;
268
	cfg_obj_t *			vconfig;
269
	cfg_obj_t *			nzf_config;
270
	cfg_aclconfctx_t *		actx;
Evan Hunt's avatar
Evan Hunt committed
271
} ns_cfgctx_t;
272

273 274 275 276 277 278
/*%
 * A function to write out added-zone configuration to the new_zone_file
 * specified in 'view'. Maybe called by delete_zoneconf().
 */
typedef isc_result_t (*nzfwriter_t)(const cfg_obj_t *config, dns_view_t *view);

279 280 281 282 283 284
/*%
 * Holds state information for the initial zone loading process.
 * Uses the isc_refcount structure to count the number of views
 * with pending zone loads, dereferencing as each view finishes.
 */
typedef struct {
285
		named_server_t *server;
286
		isc_boolean_t reconfig;
287 288 289
		isc_refcount_t refs;
} ns_zoneload_t;

290
typedef struct {
291
	named_server_t *server;
292 293 294 295 296 297 298 299 300 301 302
} catz_cb_data_t;

typedef struct catz_chgzone_event {
	ISC_EVENT_COMMON(struct catz_chgzone_event);
	dns_catz_entry_t *entry;
	dns_catz_zone_t *origin;
	dns_view_t *view;
	catz_cb_data_t *cbd;
	isc_boolean_t mod;
} catz_chgzone_event_t;

303 304 305
/*
 * These zones should not leak onto the Internet.
 */
306
const char *empty_zones[] = {
307
	/* RFC 1918 */
308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325
	"10.IN-ADDR.ARPA",
	"16.172.IN-ADDR.ARPA",
	"17.172.IN-ADDR.ARPA",
	"18.172.IN-ADDR.ARPA",
	"19.172.IN-ADDR.ARPA",
	"20.172.IN-ADDR.ARPA",
	"21.172.IN-ADDR.ARPA",
	"22.172.IN-ADDR.ARPA",
	"23.172.IN-ADDR.ARPA",
	"24.172.IN-ADDR.ARPA",
	"25.172.IN-ADDR.ARPA",
	"26.172.IN-ADDR.ARPA",
	"27.172.IN-ADDR.ARPA",
	"28.172.IN-ADDR.ARPA",
	"29.172.IN-ADDR.ARPA",
	"30.172.IN-ADDR.ARPA",
	"31.172.IN-ADDR.ARPA",
	"168.192.IN-ADDR.ARPA",
326

327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392
	/* RFC 6598 */
	"64.100.IN-ADDR.ARPA",
	"65.100.IN-ADDR.ARPA",
	"66.100.IN-ADDR.ARPA",
	"67.100.IN-ADDR.ARPA",
	"68.100.IN-ADDR.ARPA",
	"69.100.IN-ADDR.ARPA",
	"70.100.IN-ADDR.ARPA",
	"71.100.IN-ADDR.ARPA",
	"72.100.IN-ADDR.ARPA",
	"73.100.IN-ADDR.ARPA",
	"74.100.IN-ADDR.ARPA",
	"75.100.IN-ADDR.ARPA",
	"76.100.IN-ADDR.ARPA",
	"77.100.IN-ADDR.ARPA",
	"78.100.IN-ADDR.ARPA",
	"79.100.IN-ADDR.ARPA",
	"80.100.IN-ADDR.ARPA",
	"81.100.IN-ADDR.ARPA",
	"82.100.IN-ADDR.ARPA",
	"83.100.IN-ADDR.ARPA",
	"84.100.IN-ADDR.ARPA",
	"85.100.IN-ADDR.ARPA",
	"86.100.IN-ADDR.ARPA",
	"87.100.IN-ADDR.ARPA",
	"88.100.IN-ADDR.ARPA",
	"89.100.IN-ADDR.ARPA",
	"90.100.IN-ADDR.ARPA",
	"91.100.IN-ADDR.ARPA",
	"92.100.IN-ADDR.ARPA",
	"93.100.IN-ADDR.ARPA",
	"94.100.IN-ADDR.ARPA",
	"95.100.IN-ADDR.ARPA",
	"96.100.IN-ADDR.ARPA",
	"97.100.IN-ADDR.ARPA",
	"98.100.IN-ADDR.ARPA",
	"99.100.IN-ADDR.ARPA",
	"100.100.IN-ADDR.ARPA",
	"101.100.IN-ADDR.ARPA",
	"102.100.IN-ADDR.ARPA",
	"103.100.IN-ADDR.ARPA",
	"104.100.IN-ADDR.ARPA",
	"105.100.IN-ADDR.ARPA",
	"106.100.IN-ADDR.ARPA",
	"107.100.IN-ADDR.ARPA",
	"108.100.IN-ADDR.ARPA",
	"109.100.IN-ADDR.ARPA",
	"110.100.IN-ADDR.ARPA",
	"111.100.IN-ADDR.ARPA",
	"112.100.IN-ADDR.ARPA",
	"113.100.IN-ADDR.ARPA",
	"114.100.IN-ADDR.ARPA",
	"115.100.IN-ADDR.ARPA",
	"116.100.IN-ADDR.ARPA",
	"117.100.IN-ADDR.ARPA",
	"118.100.IN-ADDR.ARPA",
	"119.100.IN-ADDR.ARPA",
	"120.100.IN-ADDR.ARPA",
	"121.100.IN-ADDR.ARPA",
	"122.100.IN-ADDR.ARPA",
	"123.100.IN-ADDR.ARPA",
	"124.100.IN-ADDR.ARPA",
	"125.100.IN-ADDR.ARPA",
	"126.100.IN-ADDR.ARPA",
	"127.100.IN-ADDR.ARPA",

393
	/* RFC 5735 and RFC 5737 */
394 395 396 397 398 399 400
	"0.IN-ADDR.ARPA",	/* THIS NETWORK */
	"127.IN-ADDR.ARPA",	/* LOOPBACK */
	"254.169.IN-ADDR.ARPA",	/* LINK LOCAL */
	"2.0.192.IN-ADDR.ARPA",	/* TEST NET */
	"100.51.198.IN-ADDR.ARPA",	/* TEST NET 2 */
	"113.0.203.IN-ADDR.ARPA",	/* TEST NET 3 */
	"255.255.255.255.IN-ADDR.ARPA",	/* BROADCAST */
401 402

	/* Local IPv6 Unicast Addresses */
403 404
	"0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.IP6.ARPA",
	"1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.IP6.ARPA",
Francis Dupont's avatar
Francis Dupont committed
405
	/* LOCALLY ASSIGNED LOCAL ADDRESS SCOPE */
406 407 408 409 410
	"D.F.IP6.ARPA",
	"8.E.F.IP6.ARPA",	/* LINK LOCAL */
	"9.E.F.IP6.ARPA",	/* LINK LOCAL */
	"A.E.F.IP6.ARPA",	/* LINK LOCAL */
	"B.E.F.IP6.ARPA",	/* LINK LOCAL */
411

412
	/* Example Prefix, RFC 3849. */
413
	"8.B.D.0.1.0.0.2.IP6.ARPA",
414

415 416 417
	/* RFC 7534 */
	"EMPTY.AS112.ARPA",

418
	NULL
419 420
};

Francis Dupont's avatar
Francis Dupont committed
421 422
ISC_PLATFORM_NORETURN_PRE static void
fatal(const char *msg, isc_result_t result) ISC_PLATFORM_NORETURN_POST;
David Lawrence's avatar
David Lawrence committed
423 424

static void
425
named_server_reload(isc_task_t *task, isc_event_t *event);
426

427
static isc_result_t
428
ns_listenelt_fromconfig(const cfg_obj_t *listener, const cfg_obj_t *config,
429 430
			cfg_aclconfctx_t *actx, isc_mem_t *mctx,
			isc_uint16_t family, ns_listenelt_t **target);
431
static isc_result_t
432
ns_listenlist_fromconfig(const cfg_obj_t *listenlist, const cfg_obj_t *config,
433 434
			 cfg_aclconfctx_t *actx, isc_mem_t *mctx,
			 isc_uint16_t family, ns_listenlist_t **target);
435

436
static isc_result_t
437
configure_forward(const cfg_obj_t *config, dns_view_t *view,
438 439
		  const dns_name_t *origin, const cfg_obj_t *forwarders,
		  const cfg_obj_t *forwardtype);
440

441
static isc_result_t
442 443
configure_alternates(const cfg_obj_t *config, dns_view_t *view,
		     const cfg_obj_t *alternates);
444

445
static isc_result_t
446 447
configure_zone(const cfg_obj_t *config, const cfg_obj_t *zconfig,
	       const cfg_obj_t *vconfig, isc_mem_t *mctx, dns_view_t *view,
Evan Hunt's avatar
Evan Hunt committed
448
	       dns_viewlist_t *viewlist, cfg_aclconfctx_t *aclconf,
Evan Hunt's avatar
Evan Hunt committed
449 450
	       isc_boolean_t added, isc_boolean_t old_rpz_ok,
	       isc_boolean_t modify);
451

452 453 454 455
static isc_result_t
configure_newzones(dns_view_t *view, cfg_obj_t *config, cfg_obj_t *vconfig,
		   isc_mem_t *mctx, cfg_aclconfctx_t *actx);

456
static isc_result_t
457
add_keydata_zone(dns_view_t *view, const char *directory, isc_mem_t *mctx);
458

459
static void
460
end_reserved_dispatches(named_server_t *server, isc_boolean_t all);
461

462
static void
463
newzone_cfgctx_destroy(void **cfgp);
464

Mark Andrews's avatar
Mark Andrews committed
465
static inline isc_result_t
466
putstr(isc_buffer_t **b, const char *str);
467

468
static isc_result_t
469 470 471 472 473
putmem(isc_buffer_t **b, const char *str, size_t len);

static isc_result_t
putuint8(isc_buffer_t **b, isc_uint8_t val);

Mark Andrews's avatar
Mark Andrews committed
474
static inline isc_result_t
475
putnull(isc_buffer_t **b);
476

477 478 479 480 481 482 483
static int
count_zones(const cfg_obj_t *conf);

#ifdef HAVE_LMDB
static isc_result_t
migrate_nzf(dns_view_t *view);

484 485 486
static isc_result_t
nzd_writable(dns_view_t *view);

487 488 489
static isc_result_t
nzd_open(dns_view_t *view, unsigned int flags, MDB_txn **txnp, MDB_dbi *dbi);

490 491 492 493 494 495
static isc_result_t
nzd_env_reopen(dns_view_t *view);

static void
nzd_env_close(dns_view_t *view);

496 497 498 499 500 501
static isc_result_t
nzd_close(MDB_txn **txnp, isc_boolean_t commit);

static isc_result_t
nzd_count(dns_view_t *view, int *countp);
#else
Evan Hunt's avatar
Evan Hunt committed
502
static isc_result_t
503 504
nzf_append(dns_view_t *view, const cfg_obj_t *zconfig);
#endif
Evan Hunt's avatar
Evan Hunt committed
505

506
/*%
Tatuya JINMEI 神明達哉's avatar
Tatuya JINMEI 神明達哉 committed
507 508
 * Configure a single view ACL at '*aclp'.  Get its configuration from
 * 'vconfig' (for per-view configuration) and maybe from 'config'
509 510
 */
static isc_result_t
511
configure_view_acl(const cfg_obj_t *vconfig, const cfg_obj_t *config,
512 513
		   const char *aclname, const char *acltuplename,
		   cfg_aclconfctx_t *actx, isc_mem_t *mctx, dns_acl_t **aclp)
514 515
{
	isc_result_t result;
516 517
	const cfg_obj_t *maps[3];
	const cfg_obj_t *aclobj = NULL;
518 519
	int i = 0;

520 521
	if (*aclp != NULL)
		dns_acl_detach(aclp);
522 523 524
	if (vconfig != NULL)
		maps[i++] = cfg_tuple_get(vconfig, "options");
	if (config != NULL) {
525
		const cfg_obj_t *options = NULL;
526
		(void)cfg_map_get(config, "options", &options);
527 528 529 530
		if (options != NULL)
			maps[i++] = options;
	}
	maps[i] = NULL;
531

532
	(void)named_config_get(maps, aclname, &aclobj);
533
	if (aclobj == NULL)
534
		/*
535
		 * No value available.	*aclp == NULL.
536
		 */
537 538
		return (ISC_R_SUCCESS);

539 540 541 542 543 544 545 546 547
	if (acltuplename != NULL) {
		/*
		 * If the ACL is given in an optional tuple, retrieve it.
		 * The parser should have ensured that a valid object be
		 * returned.
		 */
		aclobj = cfg_tuple_get(aclobj, acltuplename);
	}

548
	result = cfg_acl_fromconfig(aclobj, config, named_g_lctx,
549 550 551 552 553 554 555 556 557 558 559 560
				    actx, mctx, 0, aclp);

	return (result);
}

/*%
 * Configure a sortlist at '*aclp'.  Essentially the same as
 * configure_view_acl() except it calls cfg_acl_fromconfig with a
 * nest_level value of 2.
 */
static isc_result_t
configure_view_sortlist(const cfg_obj_t *vconfig, const cfg_obj_t *config,
Automatic Updater's avatar
Automatic Updater committed
561 562
			cfg_aclconfctx_t *actx, isc_mem_t *mctx,
			dns_acl_t **aclp)
563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580
{
	isc_result_t result;
	const cfg_obj_t *maps[3];
	const cfg_obj_t *aclobj = NULL;
	int i = 0;

	if (*aclp != NULL)
		dns_acl_detach(aclp);
	if (vconfig != NULL)
		maps[i++] = cfg_tuple_get(vconfig, "options");
	if (config != NULL) {
		const cfg_obj_t *options = NULL;
		(void)cfg_map_get(config, "options", &options);
		if (options != NULL)
			maps[i++] = options;
	}
	maps[i] = NULL;

581
	(void)named_config_get(maps, "sortlist", &aclobj);
582 583 584
	if (aclobj == NULL)
		return (ISC_R_SUCCESS);

Automatic Updater's avatar
Automatic Updater committed
585 586 587 588 589 590
	/*
	 * Use a nest level of 3 for the "top level" of the sortlist;
	 * this means each entry in the top three levels will be stored
	 * as lists of separate, nested ACLs, rather than merged together
	 * into IP tables as is usually done with ACLs.
	 */
591
	result = cfg_acl_fromconfig(aclobj, config, named_g_lctx,
592
				    actx, mctx, 3, aclp);
593 594 595 596

	return (result);
}

597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624
static isc_result_t
configure_view_nametable(const cfg_obj_t *vconfig, const cfg_obj_t *config,
			 const char *confname, const char *conftuplename,
			 isc_mem_t *mctx, dns_rbt_t **rbtp)
{
	isc_result_t result;
	const cfg_obj_t *maps[3];
	const cfg_obj_t *obj = NULL;
	const cfg_listelt_t *element;
	int i = 0;
	dns_fixedname_t fixed;
	dns_name_t *name;
	isc_buffer_t b;
	const char *str;
	const cfg_obj_t *nameobj;

	if (*rbtp != NULL)
		dns_rbt_destroy(rbtp);
	if (vconfig != NULL)
		maps[i++] = cfg_tuple_get(vconfig, "options");
	if (config != NULL) {
		const cfg_obj_t *options = NULL;
		(void)cfg_map_get(config, "options", &options);
		if (options != NULL)
			maps[i++] = options;
	}
	maps[i] = NULL;

625
	(void)named_config_get(maps, confname, &obj);
626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648
	if (obj == NULL)
		/*
		 * No value available.	*rbtp == NULL.
		 */
		return (ISC_R_SUCCESS);

	if (conftuplename != NULL) {
		obj = cfg_tuple_get(obj, conftuplename);
		if (cfg_obj_isvoid(obj))
			return (ISC_R_SUCCESS);
	}

	result = dns_rbt_create(mctx, NULL, NULL, rbtp);
	if (result != ISC_R_SUCCESS)
		return (result);

	dns_fixedname_init(&fixed);
	name = dns_fixedname_name(&fixed);
	for (element = cfg_list_first(obj);
	     element != NULL;
	     element = cfg_list_next(element)) {
		nameobj = cfg_listelt_value(element);
		str = cfg_obj_asstring(nameobj);
649
		isc_buffer_constinit(&b, str, strlen(str));
650
		isc_buffer_add(&b, strlen(str));
651
		CHECK(dns_name_fromtext(name, &b, dns_rootname, 0, NULL));
652 653 654 655 656 657 658
		/*
		 * We don't need the node data, but need to set dummy data to
		 * avoid a partial match with an empty node.  For example, if
		 * we have foo.example.com and bar.example.com, we'd get a match
		 * for baz.example.com, which is not the expected result.
		 * We simply use (void *)1 as the dummy data.
		 */
659 660
		result = dns_rbt_addname(*rbtp, name, (void *)1);
		if (result != ISC_R_SUCCESS) {
661
			cfg_obj_log(nameobj, named_g_lctx, ISC_LOG_ERROR,
662 663 664 665
				    "failed to add %s for %s: %s",
				    str, confname, isc_result_totext(result));
			goto cleanup;
		}
Automatic Updater's avatar
Automatic Updater committed
666

667 668 669 670 671 672 673
	}

	return (result);

  cleanup:
	dns_rbt_destroy(rbtp);
	return (result);
Automatic Updater's avatar
Automatic Updater committed
674

675 676
}

677
static isc_result_t
678 679
dstkey_fromconfig(const cfg_obj_t *vconfig, const cfg_obj_t *key,
		  isc_boolean_t managed, dst_key_t **target, isc_mem_t *mctx)
680 681
{
	dns_rdataclass_t viewclass;
682
	dns_rdata_dnskey_t keystruct;
683
	isc_uint32_t flags, proto, alg;
684
	const char *keystr, *keynamestr;
685 686 687 688 689 690 691 692 693 694 695
	unsigned char keydata[4096];
	isc_buffer_t keydatabuf;
	unsigned char rrdata[4096];
	isc_buffer_t rrdatabuf;
	isc_region_t r;
	dns_fixedname_t fkeyname;
	dns_name_t *keyname;
	isc_buffer_t namebuf;
	isc_result_t result;
	dst_key_t *dstkey = NULL;

696 697
	INSIST(target != NULL && *target == NULL);

698 699 700 701 702 703
	flags = cfg_obj_asuint32(cfg_tuple_get(key, "flags"));
	proto = cfg_obj_asuint32(cfg_tuple_get(key, "protocol"));
	alg = cfg_obj_asuint32(cfg_tuple_get(key, "algorithm"));
	keyname = dns_fixedname_name(&fkeyname);
	keynamestr = cfg_obj_asstring(cfg_tuple_get(key, "name"));

Automatic Updater's avatar
Automatic Updater committed
704 705 706 707
	if (managed) {
		const char *initmethod;
		initmethod = cfg_obj_asstring(cfg_tuple_get(key, "init"));

708
		if (strcasecmp(initmethod, "initial-key") != 0) {
709
			cfg_obj_log(key, named_g_lctx, ISC_LOG_ERROR,
Automatic Updater's avatar
Automatic Updater committed
710 711 712 713 714 715 716
				    "managed key '%s': "
				    "invalid initialization method '%s'",
				    keynamestr, initmethod);
			result = ISC_R_FAILURE;
			goto cleanup;
		}
	}
717

718
	if (vconfig == NULL)
719
		viewclass = dns_rdataclass_in;
720
	else {
721
		const cfg_obj_t *classobj = cfg_tuple_get(vconfig, "class");
722
		CHECK(named_config_getclass(classobj, dns_rdataclass_in,
723
					 &viewclass));
724
	}
725
	keystruct.common.rdclass = viewclass;
726
	keystruct.common.rdtype = dns_rdatatype_dnskey;
727
	/*
728
	 * The key data in keystruct is not dynamically allocated.
729 730 731 732 733
	 */
	keystruct.mctx = NULL;

	ISC_LINK_INIT(&keystruct.common, link);

734
	if (flags > 0xffff)
735
		CHECKM(ISC_R_RANGE, "key flags");
736
	if (proto > 0xff)
737
		CHECKM(ISC_R_RANGE, "key protocol");
738
	if (alg > 0xff)
739
		CHECKM(ISC_R_RANGE, "key algorithm");
740 741 742
	keystruct.flags = (isc_uint16_t)flags;
	keystruct.protocol = (isc_uint8_t)proto;
	keystruct.algorithm = (isc_uint8_t)alg;
743 744 745 746

	isc_buffer_init(&keydatabuf, keydata, sizeof(keydata));
	isc_buffer_init(&rrdatabuf, rrdata, sizeof(rrdata));

747
	keystr = cfg_obj_asstring(cfg_tuple_get(key, "key"));
748
	CHECK(isc_base64_decodestring(keystr, &keydatabuf));
749 750 751 752
	isc_buffer_usedregion(&keydatabuf, &r);
	keystruct.datalen = r.length;
	keystruct.data = r.base;

753 754 755
	if ((keystruct.algorithm == DST_ALG_RSASHA1 ||
	     keystruct.algorithm == DST_ALG_RSAMD5) &&
	    r.length > 1 && r.base[0] == 1 && r.base[1] == 3)
756
		cfg_obj_log(key, named_g_lctx, ISC_LOG_WARNING,
757 758
			    "%s key '%s' has a weak exponent",
			    managed ? "managed" : "trusted",
759 760
			    keynamestr);

761 762 763 764 765
	CHECK(dns_rdata_fromstruct(NULL,
				   keystruct.common.rdclass,
				   keystruct.common.rdtype,
				   &keystruct, &rrdatabuf));
	dns_fixedname_init(&fkeyname);
766
	isc_buffer_constinit(&namebuf, keynamestr, strlen(keynamestr));
767
	isc_buffer_add(&namebuf, strlen(keynamestr));
768
	CHECK(dns_name_fromtext(keyname, &namebuf, dns_rootname, 0, NULL));
769 770 771
	CHECK(dst_key_fromdns(keyname, viewclass, &rrdatabuf,
			      mctx, &dstkey));

772
	*target = dstkey;
773 774 775
	return (ISC_R_SUCCESS);

 cleanup:
776
	if (result == DST_R_NOCRYPTO) {
777
		cfg_obj_log(key, named_g_lctx, ISC_LOG_ERROR,
778 779
			    "ignoring %s key for '%s': no crypto support",
			    managed ? "managed" : "trusted",
780
			    keynamestr);
781
	} else if (result == DST_R_UNSUPPORTEDALG) {
782
		cfg_obj_log(key, named_g_lctx, ISC_LOG_WARNING,
783 784 785
			    "skipping %s key for '%s': %s",
			    managed ? "managed" : "trusted",
			    keynamestr, isc_result_totext(result));
786
	} else {
787
		cfg_obj_log(key, named_g_lctx, ISC_LOG_ERROR,
788 789
			    "configuring %s key for '%s': %s",
			    managed ? "managed" : "trusted",
790 791 792
			    keynamestr, isc_result_totext(result));
		result = ISC_R_FAILURE;
	}
793 794 795 796 797 798 799

	if (dstkey != NULL)
		dst_key_free(&dstkey);

	return (result);
}

800 801
static isc_result_t
load_view_keys(const cfg_obj_t *keys, const cfg_obj_t *vconfig,
802
	       dns_view_t *view, isc_boolean_t managed,
803
	       const dns_name_t *keyname, isc_mem_t *mctx)
804 805
{
	const cfg_listelt_t *elt, *elt2;
806 807
	const cfg_obj_t *key, *keylist;
	dst_key_t *dstkey = NULL;
808 809 810 811
	isc_result_t result;
	dns_keytable_t *secroots = NULL;

	CHECK(dns_view_getsecroots(view, &secroots));
812 813 814 815 816 817 818 819 820 821

	for (elt = cfg_list_first(keys);
	     elt != NULL;
	     elt = cfg_list_next(elt)) {
		keylist = cfg_listelt_value(elt);

		for (elt2 = cfg_list_first(keylist);
		     elt2 != NULL;
		     elt2 = cfg_list_next(elt2)) {
			key = cfg_listelt_value(elt2);
822 823 824 825 826 827 828 829
			result = dstkey_fromconfig(vconfig, key, managed,
						   &dstkey, mctx);
			if (result ==  DST_R_UNSUPPORTEDALG) {
				result = ISC_R_SUCCESS;
				continue;
			}
			if (result != ISC_R_SUCCESS)
				goto cleanup;
830

831 832 833 834
			/*
			 * If keyname was specified, we only add that key.
			 */
			if (keyname != NULL &&
Automatic Updater's avatar
Automatic Updater committed
835
			    !dns_name_equal(keyname, dst_key_name(dstkey)))
836 837 838 839 840
			{
				dst_key_free(&dstkey);
				continue;
			}

841
			CHECK(dns_keytable_add(secroots, managed, &dstkey));
842 843 844 845
		}
	}

 cleanup:
846 847
	if (dstkey != NULL)
		dst_key_free(&dstkey);
848 849
	if (secroots != NULL)
		dns_keytable_detach(&secroots);
850 851
	if (result == DST_R_NOCRYPTO)
		result = ISC_R_SUCCESS;
852
	return (result);
853 854
}

855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877
/*%
 * Check whether a key has been successfully loaded.
 */
static isc_boolean_t
keyloaded(dns_view_t *view, const dns_name_t *name) {
	isc_result_t result;
	dns_keytable_t *secroots = NULL;
	dns_keynode_t *keynode = NULL;

	result = dns_view_getsecroots(view, &secroots);
	if (result != ISC_R_SUCCESS)
		return (ISC_FALSE);

	result = dns_keytable_find(secroots, name, &keynode);

	if (keynode != NULL)
		dns_keytable_detachkeynode(secroots, &keynode);
	if (secroots != NULL)
		dns_keytable_detach(&secroots);

	return (ISC_TF(result == ISC_R_SUCCESS));
}

878
/*%
879
 * Configure DNSSEC keys for a view.
880
 *
881
 * The per-view configuration values and the server-global defaults are read
882
 * from 'vconfig' and 'config'.
883 884
 */
static isc_result_t
885 886
configure_view_dnsseckeys(dns_view_t *view, const cfg_obj_t *vconfig,
			  const cfg_obj_t *config, const cfg_obj_t *bindkeys,
887 888
			  isc_boolean_t auto_dlv, isc_boolean_t auto_root,
			  isc_mem_t *mctx)
889
{
890
	isc_result_t result = ISC_R_SUCCESS;
891 892
	const cfg_obj_t *view_keys = NULL;
	const cfg_obj_t *global_keys = NULL;
893
	const cfg_obj_t *view_managed_keys = NULL;
894
	const cfg_obj_t *global_managed_keys = NULL;
895
	const cfg_obj_t *maps[4];
896
	const cfg_obj_t *voptions = NULL;
897
	const cfg_obj_t *options = NULL;
898 899
	const cfg_obj_t *obj = NULL;
	const char *directory;
900
	int i = 0;
901

902
	/* We don't need trust anchors for the _bind view */
903 904
	if (strcmp(view->name, "_bind") == 0 &&
	    view->rdclass == dns_rdataclass_chaos) {
905 906
		return (ISC_R_SUCCESS);
	}
907

908
	if (vconfig != NULL) {
909
		voptions = cfg_tuple_get(vconfig, "options");
910
		if (voptions != NULL) {
911 912
			(void) cfg_map_get(voptions, "trusted-keys",
					   &view_keys);
913 914
			(void) cfg_map_get(voptions, "managed-keys",
					   &view_managed_keys);
915 916 917
			maps[i++] = voptions;
		}
	}
918

919 920
	if (config != NULL) {
		(void)cfg_map_get(config, "trusted-keys", &global_keys);
921
		(void)cfg_map_get(config, "managed-keys", &global_managed_keys);
922 923 924
		(void)cfg_map_get(config, "options", &options);
		if (options != NULL) {
			maps[i++] = options;
925
		}
926
	}
927

928
	maps[i++] = named_g_defaults;
929 930
	maps[i] = NULL;

931
	result = dns_view_initsecroots(view, mctx);
932
	if (result != ISC_R_SUCCESS) {
933 934
		isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
			      NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR,
935 936 937 938
			      "couldn't create keytable");
		return (ISC_R_UNEXPECTED);
	}

939
	result = dns_view_initntatable(view, named_g_taskmgr, named_g_timermgr);
Evan Hunt's avatar
Evan Hunt committed
940
	if (result != ISC_R_SUCCESS) {
941 942
		isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
			      NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR,
Evan Hunt's avatar
Evan Hunt committed
943 944 945 946
			      "couldn't create NTA table");
		return (ISC_R_UNEXPECTED);
	}

947
	if (auto_dlv && view->rdclass == dns_rdataclass_in) {
948 949 950
		const cfg_obj_t *builtin_keys = NULL;
		const cfg_obj_t *builtin_managed_keys = NULL;

951
		/*
952
		 * If bind.keys exists and is populated, it overrides
953
		 * the managed-keys clause hard-coded in named_g_config.
954
		 */
955
		if (bindkeys != NULL) {
956 957
			isc_log_write(named_g_lctx, DNS_LOGCATEGORY_SECURITY,
				      NAMED_LOGMODULE_SERVER, ISC_LOG_INFO,
958 959
				      "obtaining DLV key for view %s "
				      "from '%s'",
960
				      view->name, named_g_server->bindkeysfile);
961

962 963
			(void)cfg_map_get(bindkeys, "trusted-keys",
					  &builtin_keys);
964 965
			(void)cfg_map_get(bindkeys, "managed-keys",
					  &builtin_managed_keys);
966 967
			if ((builtin_keys == NULL) &&
			    (builtin_managed_keys == NULL))
968
				isc_log_write(named_g_lctx,
969
					      DNS_LOGCATEGORY_SECURITY,
970
					      NAMED_LOGMODULE_SERVER,
971 972 973 974 975 976 977 978 979
					      ISC_LOG_WARNING,
					      "dnssec-lookaside auto: "
					      "WARNING: key for dlv.isc.org "
					      "not found");
		}

		if ((builtin_keys == NULL) &&
		    (builtin_managed_keys == NULL))
		{
980