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
981
			isc_log_write(named_g_lctx, DNS_LOGCATEGORY_SECURITY,
				      NAMED_LOGMODULE_SERVER, ISC_LOG_INFO,
982
983
984
				      "using built-in DLV key for view %s",
				      view->name);

985
			(void)cfg_map_get(named_g_config, "trusted-keys",
986
					  &builtin_keys);
987
			(void)cfg_map_get(named_g_config, "managed-keys",
988
989
990
					  &builtin_managed_keys);
		}

991
992
		if (builtin_keys != NULL)
			CHECK(load_view_keys(builtin_keys, vconfig, view,
993
					     ISC_FALSE, view->dlv, mctx));
994
995
		if (builtin_managed_keys != NULL)
			CHECK(load_view_keys(builtin_managed_keys, vconfig,
996
					     view, ISC_TRUE, view->dlv, mctx));
997
		if (!keyloaded(view, view->dlv)) {
998
999
			isc_log_write(named_g_lctx, DNS_LOGCATEGORY_SECURITY,
				      NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR,
1000
1001
1002
1003
				      "DLV key not loaded");
			result = ISC_R_FAILURE;
			goto cleanup;
		}
1004
1005
	}

1006
1007
1008
1009
1010
	if (auto_root && view->rdclass == dns_rdataclass_in) {
		const cfg_obj_t *builtin_keys = NULL;
		const cfg_obj_t *builtin_managed_keys = NULL;

		/*
1011
		 * If bind.keys exists and is populated, it overrides
1012
		 * the managed-keys clause hard-coded in named_g_config.
1013
1014
		 */
		if (bindkeys != NULL) {
1015
1016
			isc_log_write(named_g_lctx, DNS_LOGCATEGORY_SECURITY,
				      NAMED_LOGMODULE_SERVER, ISC_LOG_INFO,
1017
1018
				      "obtaining root key for view %s "
				      "from '%s'",
1019
				      view->name, named_g_server->bindkeysfile);
1020

1021
1022
1023
1024
			(void)cfg_map_get(bindkeys, "trusted-keys",
					  &builtin_keys);
			(void)cfg_map_get(bindkeys, "managed-keys",
					  &builtin_managed_keys);
1025
1026
1027

			if ((builtin_keys == NULL) &&
			    (builtin_managed_keys == NULL))
1028
				isc_log_write(named_g_lctx,
1029
					      DNS_LOGCATEGORY_SECURITY,
1030
					      NAMED_LOGMODULE_SERVER,
1031
1032
1033
1034
1035
1036
1037
1038
1039
					      ISC_LOG_WARNING,
					      "dnssec-validation auto: "
					      "WARNING: root zone key "
					      "not found");
		}

		if ((builtin_keys == NULL) &&
		    (builtin_managed_keys == NULL))
		{
1040
1041
			isc_log_write(named_g_lctx, DNS_LOGCATEGORY_SECURITY,
				      NAMED_LOGMODULE_SERVER, ISC_LOG_INFO,
1042
1043
1044
				      "using built-in root key for view %s",
				      view->name);

1045
			(void)cfg_map_get(named_g_config, "trusted-keys",
1046
					  &builtin_keys);
1047
			(void)cfg_map_get(named_g_config, "managed-keys",
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
					  &builtin_managed_keys);
		}

		if (builtin_keys != NULL)
			CHECK(load_view_keys(builtin_keys, vconfig, view,
					     ISC_FALSE, dns_rootname, mctx));
		if (builtin_managed_keys != NULL)
			CHECK(load_view_keys(builtin_managed_keys, vconfig,
					     view, ISC_TRUE, dns_rootname,
					     mctx));
1058
1059

		if (!keyloaded(view, dns_rootname)) {
1060
1061
			isc_log_write(named_g_lctx, DNS_LOGCATEGORY_SECURITY,
				      NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR,
1062
1063
1064
1065
				      "root key not loaded");
			result = ISC_R_FAILURE;
			goto cleanup;
		}
1066
1067
1068
1069
1070
1071
1072
	}

	CHECK(load_view_keys(view_keys, vconfig, view, ISC_FALSE,
			     NULL, mctx));
	CHECK(load_view_keys(view_managed_keys, vconfig, view, ISC_TRUE,
			     NULL, mctx));

1073
1074
	if (view->rdclass == dns_rdataclass_in) {
		CHECK(load_view_keys(global_keys, vconfig, view, ISC_FALSE,
1075
				     NULL, mctx));
1076
		CHECK(load_view_keys(global_managed_keys, vconfig, view,
1077
				     ISC_TRUE, NULL, mctx));
1078
1079
1080
1081
1082
1083
	}

	/*
	 * Add key zone for managed-keys.
	 */
	obj = NULL;
1084
	(void)named_config_get(maps, "managed-keys-directory", &obj);
1085
1086
1087
1088
	directory = (obj != NULL ? cfg_obj_asstring(obj) : NULL);
	if (directory != NULL)
		result = isc_file_isdirectory(directory);
	if (result != ISC_R_SUCCESS) {
1089
1090
		isc_log_write(named_g_lctx, DNS_LOGCATEGORY_SECURITY,
			      NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR,
1091
1092
1093
1094
1095
			      "invalid managed-keys-directory %s: %s",
			      directory, isc_result_totext(result));
		goto cleanup;

	}
1096
	CHECK(add_keydata_zone(view, directory, named_g_mctx));
Automatic Updater's avatar
Automatic Updater committed
1097

1098
1099
  cleanup:
	return (result);
1100
}
1101

1102
static isc_result_t
1103
mustbesecure(const cfg_obj_t *mbs, dns_resolver_t *resolver) {
1104
1105
	const cfg_listelt_t *element;
	const cfg_obj_t *obj;
1106
1107
1108
1109
1110
1111
	const char *str;
	dns_fixedname_t fixed;
	dns_name_t *name;
	isc_boolean_t value;
	isc_result_t result;
	isc_buffer_t b;
Automatic Updater's avatar
Automatic Updater committed
1112

1113
1114
1115
1116
1117
1118
1119
1120
	dns_fixedname_init(&fixed);
	name = dns_fixedname_name(&fixed);
	for (element = cfg_list_first(mbs);
	     element != NULL;
	     element = cfg_list_next(element))
	{
		obj = cfg_listelt_value(element);
		str = cfg_obj_asstring(cfg_tuple_get(obj, "name"));
1121
		isc_buffer_constinit(&b, str, strlen(str));
1122
		isc_buffer_add(&b, strlen(str));
1123
		CHECK(dns_name_fromtext(name, &b, dns_rootname, 0, NULL));
1124
1125
1126
1127
1128
		value = cfg_obj_asboolean(cfg_tuple_get(obj, "value"));
		CHECK(dns_resolver_setmustbesecure(resolver, name, value));
	}

	result = ISC_R_SUCCESS;
Automatic Updater's avatar
Automatic Updater committed
1129

1130
1131
1132
 cleanup:
	return (result);
}
1133

1134
/*%
1135
1136
1137
 * Get a dispatch appropriate for the resolver of a given view.
 */
static isc_result_t
Evan Hunt's avatar
Evan Hunt committed
1138
1139
get_view_querysource_dispatch(const cfg_obj_t **maps, int af,
			      dns_dispatch_t **dispatchp, isc_dscp_t *dscpp,
1140
			      isc_boolean_t is_firstview)
1141
{
1142
	isc_result_t result = ISC_R_FAILURE;
1143
1144
1145
	dns_dispatch_t *disp;
	isc_sockaddr_t sa;
	unsigned int attrs, attrmask;
1146
	const cfg_obj_t *obj = NULL;
1147
	unsigned int maxdispatchbuffers = UDPBUFFERS;
Evan Hunt's avatar
Evan Hunt committed
1148
	isc_dscp_t dscp = -1;
1149
1150
1151

	switch (af) {
	case AF_INET: