scheme.c 13.7 KB
Newer Older
1
/*  Copyright (C) 2016 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#include <limits.h>
#include <stdbool.h>
#include <stdlib.h>
#include <stdint.h>

#include "knot/conf/scheme.h"
23
#include "knot/conf/confio.h"
24 25 26 27 28
#include "knot/conf/tools.h"
#include "knot/common/log.h"
#include "knot/updates/acl.h"
#include "libknot/rrtype/opt.h"
#include "dnssec/lib/dnssec/tsig.h"
29
#include "dnssec/lib/dnssec/key.h"
30

31
#include "knot/modules/rrl/rrl.h"
32
#include "knot/modules/stats/stats.h"
33 34 35
#include "knot/modules/synth_record/synth_record.h"
#include "knot/modules/dnsproxy/dnsproxy.h"
#include "knot/modules/online_sign/online_sign.h"
36
#ifdef HAVE_ROSEDB
37
#include "knot/modules/rosedb/rosedb.h"
38 39
#endif
#if USE_DNSTAP
40
#include "knot/modules/dnstap/dnstap.h"
41
#endif
42 43
#include "knot/modules/whoami/whoami.h"
#include "knot/modules/noudp/noudp.h"
44

45 46 47
#define HOURS(x)	((x) * 3600)
#define DAYS(x)		((x) * HOURS(24))

48 49
#define FMOD		(YP_FMULTI | CONF_IO_FRLD_MOD | CONF_IO_FRLD_ZONES)

50 51 52 53 54 55 56
static const knot_lookup_t keystore_backends[] = {
	{ KEYSTORE_BACKEND_PEM,    "pem" },
	{ KEYSTORE_BACKEND_PKCS11, "pkcs11" },
	{ 0, NULL }
};

static const knot_lookup_t tsig_key_algs[] = {
57 58 59 60 61 62 63 64 65
	{ DNSSEC_TSIG_HMAC_MD5,    "hmac-md5" },
	{ DNSSEC_TSIG_HMAC_SHA1,   "hmac-sha1" },
	{ DNSSEC_TSIG_HMAC_SHA224, "hmac-sha224" },
	{ DNSSEC_TSIG_HMAC_SHA256, "hmac-sha256" },
	{ DNSSEC_TSIG_HMAC_SHA384, "hmac-sha384" },
	{ DNSSEC_TSIG_HMAC_SHA512, "hmac-sha512" },
	{ 0, NULL }
};

66 67 68
static const knot_lookup_t dnssec_key_algs[] = {
	{ DNSSEC_KEY_ALGORITHM_DSA_SHA1,          "dsa" },
	{ DNSSEC_KEY_ALGORITHM_RSA_SHA1,          "rsasha1" },
69 70
	{ DNSSEC_KEY_ALGORITHM_DSA_SHA1_NSEC3,    "dsa-nsec3-sha1" },
	{ DNSSEC_KEY_ALGORITHM_RSA_SHA1_NSEC3,    "rsasha1-nsec3-sha1" },
71 72 73 74 75 76 77
	{ DNSSEC_KEY_ALGORITHM_RSA_SHA256,        "rsasha256" },
	{ DNSSEC_KEY_ALGORITHM_RSA_SHA512,        "rsasha512" },
	{ DNSSEC_KEY_ALGORITHM_ECDSA_P256_SHA256, "ecdsap256sha256" },
	{ DNSSEC_KEY_ALGORITHM_ECDSA_P384_SHA384, "ecdsap384sha384" },
	{ 0, NULL }
};

78
const knot_lookup_t acl_actions[] = {
79 80 81
	{ ACL_ACTION_NOTIFY,   "notify" },
	{ ACL_ACTION_TRANSFER, "transfer" },
	{ ACL_ACTION_UPDATE,   "update" },
82 83 84
	{ 0, NULL }
};

85
static const knot_lookup_t serial_policies[] = {
86 87 88 89 90
	{ SERIAL_POLICY_INCREMENT, "increment" },
	{ SERIAL_POLICY_UNIXTIME,  "unixtime" },
	{ 0, NULL }
};

91
static const knot_lookup_t log_severities[] = {
92 93 94 95 96 97 98 99 100 101
	{ LOG_UPTO(LOG_CRIT),    "critical" },
	{ LOG_UPTO(LOG_ERR),     "error" },
	{ LOG_UPTO(LOG_WARNING), "warning" },
	{ LOG_UPTO(LOG_NOTICE),  "notice" },
	{ LOG_UPTO(LOG_INFO),    "info" },
	{ LOG_UPTO(LOG_DEBUG),   "debug" },
	{ 0, NULL }
};

static const yp_item_t desc_server[] = {
102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124
	{ C_IDENT,                YP_TSTR,  YP_VNONE },
	{ C_VERSION,              YP_TSTR,  YP_VNONE },
	{ C_NSID,                 YP_THEX,  YP_VNONE },
	{ C_RUNDIR,               YP_TSTR,  YP_VSTR = { RUN_DIR } },
	{ C_USER,                 YP_TSTR,  YP_VNONE },
	{ C_PIDFILE,              YP_TSTR,  YP_VSTR = { "knot.pid" } },
	{ C_UDP_WORKERS,          YP_TINT,  YP_VINT = { 1, 255, YP_NIL } },
	{ C_TCP_WORKERS,          YP_TINT,  YP_VINT = { 1, 255, YP_NIL } },
	{ C_BG_WORKERS,           YP_TINT,  YP_VINT = { 1, 255, YP_NIL } },
	{ C_ASYNC_START,          YP_TBOOL, YP_VNONE },
	{ C_TCP_HSHAKE_TIMEOUT,   YP_TINT,  YP_VINT = { 0, INT32_MAX, 5, YP_STIME } },
	{ C_TCP_IDLE_TIMEOUT,     YP_TINT,  YP_VINT = { 0, INT32_MAX, 20, YP_STIME } },
	{ C_TCP_REPLY_TIMEOUT,    YP_TINT,  YP_VINT = { 0, INT32_MAX, 10, YP_STIME } },
	{ C_MAX_TCP_CLIENTS,      YP_TINT,  YP_VINT = { 0, INT32_MAX, 100 } },
	{ C_MAX_UDP_PAYLOAD,      YP_TINT,  YP_VINT = { KNOT_EDNS_MIN_UDP_PAYLOAD,
	                                                KNOT_EDNS_MAX_UDP_PAYLOAD,
	                                                4096, YP_SSIZE } },
	{ C_MAX_IPV4_UDP_PAYLOAD, YP_TINT,  YP_VINT = { KNOT_EDNS_MIN_UDP_PAYLOAD,
	                                                KNOT_EDNS_MAX_UDP_PAYLOAD,
	                                                4096, YP_SSIZE } },
	{ C_MAX_IPV6_UDP_PAYLOAD, YP_TINT,  YP_VINT = { KNOT_EDNS_MIN_UDP_PAYLOAD,
	                                                KNOT_EDNS_MAX_UDP_PAYLOAD,
	                                                4096, YP_SSIZE } },
125 126 127
	{ C_LISTEN,               YP_TADDR, YP_VADDR = { 53 }, YP_FMULTI },
	{ C_COMMENT,              YP_TSTR,  YP_VNONE },
	/* Obsolete items. */
128
	{ C_RATE_LIMIT,           YP_TINT,  YP_VINT = { 0, INT32_MAX, 0 } },
129
	{ C_RATE_LIMIT_SLIP,      YP_TINT,  YP_VINT = { 0, 100, 1 } },
130 131 132
	{ C_RATE_LIMIT_TBL_SIZE,  YP_TINT,  YP_VINT = { 1, INT32_MAX, 393241 } },
	{ C_RATE_LIMIT_WHITELIST, YP_TDATA, YP_VDATA = { 0, NULL, addr_range_to_bin,
	                                                 addr_range_to_txt }, YP_FMULTI },
133 134 135
	{ NULL }
};

136 137
static const yp_item_t desc_control[] = {
	{ C_LISTEN,  YP_TSTR, YP_VSTR = { "knot.sock" } },
138
	{ C_TIMEOUT, YP_TINT, YP_VINT = { 0, INT32_MAX / 1000, 5, YP_STIME } },
139 140 141 142 143 144 145
	{ C_COMMENT, YP_TSTR, YP_VNONE },
	{ NULL }
};

static const yp_item_t desc_log[] = {
	{ C_TARGET,  YP_TSTR, YP_VNONE },
	{ C_SERVER,  YP_TOPT, YP_VOPT = { log_severities, 0 } },
Daniel Salzman's avatar
Daniel Salzman committed
146
	{ C_CTL,     YP_TOPT, YP_VOPT = { log_severities, 0 } },
147 148 149 150 151 152
	{ C_ZONE,    YP_TOPT, YP_VOPT = { log_severities, 0 } },
	{ C_ANY,     YP_TOPT, YP_VOPT = { log_severities, 0 } },
	{ C_COMMENT, YP_TSTR, YP_VNONE },
	{ NULL }
};

153 154 155 156 157 158 159
static const yp_item_t desc_stats[] = {
	{ C_TIMER,  YP_TINT,  YP_VINT = { 1, UINT32_MAX, 0, YP_STIME } },
	{ C_FILE,   YP_TSTR,  YP_VSTR = { "stats.yaml" } },
	{ C_APPEND, YP_TBOOL, YP_VNONE },
	{ NULL }
};

160 161
static const yp_item_t desc_keystore[] = {
	{ C_ID,      YP_TSTR, YP_VNONE },
162 163 164
	{ C_BACKEND, YP_TOPT, YP_VOPT = { keystore_backends, KEYSTORE_BACKEND_PEM },
	                      CONF_IO_FRLD_ZONES },
	{ C_CONFIG,  YP_TSTR, YP_VSTR = { "keys" }, CONF_IO_FRLD_ZONES },
165 166 167 168 169
	{ C_COMMENT, YP_TSTR, YP_VNONE },
	{ NULL }
};

static const yp_item_t desc_policy[] = {
170 171 172 173
	{ C_ID,                  YP_TSTR,  YP_VNONE, CONF_IO_FREF },
	{ C_KEYSTORE,            YP_TREF,  YP_VREF = { C_KEYSTORE }, CONF_IO_FRLD_ZONES,
	                                   { check_ref_dflt } },
	{ C_MANUAL,              YP_TBOOL, YP_VNONE, CONF_IO_FRLD_ZONES },
Jan Včelák's avatar
Jan Včelák committed
174
	{ C_ALG,                 YP_TOPT,  YP_VOPT = { dnssec_key_algs,
175 176 177 178 179 180 181 182 183 184
	                                               DNSSEC_KEY_ALGORITHM_ECDSA_P256_SHA256 },
	                                   CONF_IO_FRLD_ZONES },
	{ C_KSK_SIZE,            YP_TINT,  YP_VINT = { 0, UINT16_MAX, YP_NIL, YP_SSIZE },
	                                   CONF_IO_FRLD_ZONES },
	{ C_ZSK_SIZE,            YP_TINT,  YP_VINT = { 0, UINT16_MAX, YP_NIL, YP_SSIZE },
	                                   CONF_IO_FRLD_ZONES },
	{ C_DNSKEY_TTL,          YP_TINT,  YP_VINT = { 0, UINT32_MAX, 0, YP_STIME },
	                                   CONF_IO_FRLD_ZONES },
	{ C_ZSK_LIFETIME,        YP_TINT,  YP_VINT = { 1, UINT32_MAX, DAYS(30), YP_STIME },
	                                   CONF_IO_FRLD_ZONES },
185 186
	{ C_PROPAG_DELAY,        YP_TINT,  YP_VINT = { 0, UINT32_MAX, HOURS(1), YP_STIME },
					   CONF_IO_FRLD_ZONES },
187 188 189 190 191 192 193 194 195
	{ C_RRSIG_LIFETIME,      YP_TINT,  YP_VINT = { 1, UINT32_MAX, DAYS(14), YP_STIME },
	                                   CONF_IO_FRLD_ZONES },
	{ C_RRSIG_REFRESH,       YP_TINT,  YP_VINT = { 1, UINT32_MAX, DAYS(7), YP_STIME },
	                                   CONF_IO_FRLD_ZONES },
	{ C_NSEC3,               YP_TBOOL, YP_VNONE, CONF_IO_FRLD_ZONES },
	{ C_NSEC3_ITER,          YP_TINT,  YP_VINT = { 0, UINT16_MAX, 10 }, CONF_IO_FRLD_ZONES },
	{ C_NSEC3_SALT_LEN,      YP_TINT,  YP_VINT = { 0, UINT8_MAX, 8 }, CONF_IO_FRLD_ZONES },
	{ C_NSEC3_SALT_LIFETIME, YP_TINT,  YP_VINT = { 1, UINT32_MAX, DAYS(30), YP_STIME },
	                                   CONF_IO_FRLD_ZONES },
Jan Včelák's avatar
Jan Včelák committed
196
	{ C_COMMENT,             YP_TSTR,  YP_VNONE },
197 198 199
	{ NULL }
};

200 201
static const yp_item_t desc_key[] = {
	{ C_ID,      YP_TDNAME, YP_VNONE },
202
	{ C_ALG,     YP_TOPT,   YP_VOPT = { tsig_key_algs, DNSSEC_TSIG_UNKNOWN } },
203 204 205 206 207 208
	{ C_SECRET,  YP_TB64,   YP_VNONE },
	{ C_COMMENT, YP_TSTR,   YP_VNONE },
	{ NULL }
};

static const yp_item_t desc_acl[] = {
209
	{ C_ID,      YP_TSTR,  YP_VNONE, CONF_IO_FREF },
210 211
	{ C_ADDR,    YP_TDATA, YP_VDATA = { 0, NULL, addr_range_to_bin,
	                                    addr_range_to_txt }, YP_FMULTI },
212 213 214 215
	{ C_KEY,     YP_TREF,  YP_VREF = { C_KEY }, YP_FMULTI, { check_ref } },
	{ C_ACTION,  YP_TOPT,  YP_VOPT = { acl_actions, ACL_ACTION_NONE }, YP_FMULTI },
	{ C_DENY,    YP_TBOOL, YP_VNONE },
	{ C_COMMENT, YP_TSTR,  YP_VNONE },
216 217 218 219
	{ NULL }
};

static const yp_item_t desc_remote[] = {
220
	{ C_ID,      YP_TSTR,  YP_VNONE, CONF_IO_FREF },
221 222
	{ C_ADDR,    YP_TADDR, YP_VADDR = { 53 }, YP_FMULTI },
	{ C_VIA,     YP_TADDR, YP_VNONE, YP_FMULTI },
223 224 225 226 227
	{ C_KEY,     YP_TREF,  YP_VREF = { C_KEY }, YP_FNONE, { check_ref } },
	{ C_COMMENT, YP_TSTR,  YP_VNONE },
	{ NULL }
};

228 229 230 231 232

#define VIRT_MEM_TOP (2LLU * 1024 * 1204 * 1204)
#define VIRT_MEM_LIMIT(x) (((sizeof(void *) < 8) && ((x) > VIRT_MEM_TOP)) ? VIRT_MEM_TOP : (x))


233 234
#define ZONE_ITEMS(FLAGS) \
	{ C_STORAGE,             YP_TSTR,  YP_VSTR = { STORAGE_DIR }, FLAGS }, \
Daniel Salzman's avatar
Daniel Salzman committed
235
	{ C_FILE,                YP_TSTR,  YP_VNONE, FLAGS }, \
236 237 238 239
	{ C_MASTER,              YP_TREF,  YP_VREF = { C_RMT }, YP_FMULTI, { check_ref } }, \
	{ C_DDNS_MASTER,         YP_TREF,  YP_VREF = { C_RMT }, YP_FNONE, { check_ref } }, \
	{ C_NOTIFY,              YP_TREF,  YP_VREF = { C_RMT }, YP_FMULTI, { check_ref } }, \
	{ C_ACL,                 YP_TREF,  YP_VREF = { C_ACL }, YP_FMULTI, { check_ref } }, \
240
	{ C_SEM_CHECKS,          YP_TBOOL, YP_VNONE, FLAGS }, \
241 242 243
	{ C_DISABLE_ANY,         YP_TBOOL, YP_VNONE }, \
	{ C_ZONEFILE_SYNC,       YP_TINT,  YP_VINT = { -1, INT32_MAX, 0, YP_STIME } }, \
	{ C_IXFR_DIFF,           YP_TBOOL, YP_VNONE }, \
244 245 246 247 248
	{ C_MAX_ZONE_SIZE,       YP_TINT,  YP_VINT = { 0, INT64_MAX, INT64_MAX, YP_SSIZE }, \
	                                   FLAGS }, \
	{ C_KASP_DB,             YP_TSTR,  YP_VSTR = { "keys" }, FLAGS }, \
	{ C_DNSSEC_SIGNING,      YP_TBOOL, YP_VNONE, FLAGS }, \
	{ C_DNSSEC_POLICY,       YP_TREF,  YP_VREF = { C_POLICY }, FLAGS, { check_ref_dflt } }, \
249 250 251
	{ C_SERIAL_POLICY,       YP_TOPT,  YP_VOPT = { serial_policies, SERIAL_POLICY_INCREMENT } }, \
	{ C_REQUEST_EDNS_OPTION, YP_TDATA, YP_VDATA = { 0, NULL, edns_opt_to_bin, edns_opt_to_txt } }, \
	{ C_MODULE,              YP_TDATA, YP_VDATA = { 0, NULL, mod_id_to_bin, mod_id_to_txt }, \
252
	                                   YP_FMULTI | FLAGS, { check_modref } }, \
253
	{ C_COMMENT,             YP_TSTR,  YP_VNONE },
254 255

static const yp_item_t desc_template[] = {
256 257 258
	{ C_ID, YP_TSTR, YP_VNONE, CONF_IO_FREF },
	ZONE_ITEMS(CONF_IO_FRLD_ZONES)
	{ C_TIMER_DB,            YP_TSTR,  YP_VSTR = { "timers" }, CONF_IO_FRLD_ZONES }, \
259
	{ C_GLOBAL_MODULE,       YP_TDATA, YP_VDATA = { 0, NULL, mod_id_to_bin, mod_id_to_txt }, \
260
	                                   YP_FMULTI | CONF_IO_FRLD_MOD, { check_modref } }, \
261 262 263
	{ C_JOURNAL,             YP_TSTR,  YP_VSTR = { "journal.db" }, CONF_IO_FRLD_ZONES }, \
	{ C_MAX_JOURNAL_SIZE,    YP_TINT,  YP_VINT = { 1024 * 1024, VIRT_MEM_LIMIT(100LLU * 1024 * 1024 * 1024 * 1024), \
	                                               VIRT_MEM_LIMIT(20LLU * 1024 * 1024 * 1024), YP_SSIZE } }, \
264 265 266 267
	{ NULL }
};

static const yp_item_t desc_zone[] = {
268 269 270
	{ C_DOMAIN, YP_TDNAME, YP_VNONE, CONF_IO_FRLD_ZONE },
	{ C_TPL,    YP_TREF,   YP_VREF = { C_TPL }, CONF_IO_FRLD_ZONE, { check_ref } },
	ZONE_ITEMS(CONF_IO_FRLD_ZONE)
271 272 273 274
	{ NULL }
};

const yp_item_t conf_scheme[] = {
275
	{ C_SRV,      YP_TGRP, YP_VGRP = { desc_server }, CONF_IO_FRLD_SRV, { check_server } },
276
	{ C_CTL,      YP_TGRP, YP_VGRP = { desc_control } },
277
	{ C_LOG,      YP_TGRP, YP_VGRP = { desc_log }, YP_FMULTI | CONF_IO_FRLD_LOG },
278
	{ C_STATS,    YP_TGRP, YP_VGRP = { desc_stats }, CONF_IO_FRLD_SRV },
279 280 281 282 283
	{ C_KEYSTORE, YP_TGRP, YP_VGRP = { desc_keystore }, YP_FMULTI, { check_keystore } },
	{ C_POLICY,   YP_TGRP, YP_VGRP = { desc_policy }, YP_FMULTI, { check_policy } },
	{ C_KEY,      YP_TGRP, YP_VGRP = { desc_key }, YP_FMULTI, { check_key } },
	{ C_ACL,      YP_TGRP, YP_VGRP = { desc_acl }, YP_FMULTI, { check_acl } },
	{ C_RMT,      YP_TGRP, YP_VGRP = { desc_remote }, YP_FMULTI, { check_remote } },
284
/* MODULES */
285 286
	{ C_MOD_RRL,          YP_TGRP, YP_VGRP = { scheme_mod_rrl }, FMOD,
	                                         { check_mod_rrl } },
287
	{ C_MOD_STATS,        YP_TGRP, YP_VGRP = { scheme_mod_stats }, FMOD },
288 289 290 291
	{ C_MOD_SYNTH_RECORD, YP_TGRP, YP_VGRP = { scheme_mod_synth_record }, FMOD,
	                               { check_mod_synth_record } },
	{ C_MOD_DNSPROXY,     YP_TGRP, YP_VGRP = { scheme_mod_dnsproxy }, FMOD,
	                               { check_mod_dnsproxy } },
292
#if HAVE_ROSEDB
293 294
	{ C_MOD_ROSEDB,       YP_TGRP, YP_VGRP = { scheme_mod_rosedb }, FMOD,
	                               { check_mod_rosedb } },
295 296
#endif
#if USE_DNSTAP
297 298
	{ C_MOD_DNSTAP,       YP_TGRP, YP_VGRP = { scheme_mod_dnstap }, FMOD,
	                               { check_mod_dnstap } },
299
#endif
300 301 302
	{ C_MOD_ONLINE_SIGN,  YP_TGRP, YP_VGRP = { scheme_mod_online_sign }, FMOD },
	{ C_MOD_WHOAMI,       YP_TGRP, YP_VGRP = { scheme_mod_whoami }, FMOD },
	{ C_MOD_NOUDP,        YP_TGRP, YP_VGRP = { scheme_mod_noudp }, FMOD },
303
/***********/
304 305 306
	{ C_TPL,  YP_TGRP, YP_VGRP = { desc_template }, YP_FMULTI, { check_template } },
	{ C_ZONE, YP_TGRP, YP_VGRP = { desc_zone }, YP_FMULTI | CONF_IO_FZONE, { check_zone } },
	{ C_INCL, YP_TSTR, YP_VNONE, CONF_IO_FDIFF_ZONES | CONF_IO_FRLD_ALL, { include_file } },
307 308
	{ NULL }
};