scheme.c 14.1 KB
Newer Older
1
/*  Copyright (C) 2017 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
#include "knot/conf/migration.h"
25 26
#include "knot/conf/tools.h"
#include "knot/common/log.h"
27
#include "knot/journal/journal.h"
28 29 30
#include "knot/updates/acl.h"
#include "libknot/rrtype/opt.h"
#include "dnssec/lib/dnssec/tsig.h"
31
#include "dnssec/lib/dnssec/key.h"
32

33 34 35
#define HOURS(x)	((x) * 3600)
#define DAYS(x)		((x) * HOURS(24))

36 37 38 39
#define KILO(x)		(1024LLU * (x))
#define MEGA(x)		(KILO(1024) * (x))
#define GIGA(x)		(MEGA(1024) * (x))
#define TERA(x)		(GIGA(1024) * (x))
40

41
#define VIRT_MEM_TOP_32BIT	GIGA(1)
42 43
#define VIRT_MEM_LIMIT(x)	(((sizeof(void *) < 8) && ((x) > VIRT_MEM_TOP_32BIT)) \
				 ? VIRT_MEM_TOP_32BIT : (x))
44

45 46 47 48 49 50 51
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[] = {
52 53 54 55 56 57 58 59 60
	{ 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 }
};

61 62 63
static const knot_lookup_t dnssec_key_algs[] = {
	{ DNSSEC_KEY_ALGORITHM_DSA_SHA1,          "dsa" },
	{ DNSSEC_KEY_ALGORITHM_RSA_SHA1,          "rsasha1" },
64 65
	{ DNSSEC_KEY_ALGORITHM_DSA_SHA1_NSEC3,    "dsa-nsec3-sha1" },
	{ DNSSEC_KEY_ALGORITHM_RSA_SHA1_NSEC3,    "rsasha1-nsec3-sha1" },
66 67 68 69 70 71 72
	{ 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 }
};

73
const knot_lookup_t acl_actions[] = {
74 75 76
	{ ACL_ACTION_NOTIFY,   "notify" },
	{ ACL_ACTION_TRANSFER, "transfer" },
	{ ACL_ACTION_UPDATE,   "update" },
77 78 79
	{ 0, NULL }
};

80
static const knot_lookup_t serial_policies[] = {
81 82 83 84 85
	{ SERIAL_POLICY_INCREMENT, "increment" },
	{ SERIAL_POLICY_UNIXTIME,  "unixtime" },
	{ 0, NULL }
};

86
static const knot_lookup_t log_severities[] = {
87 88 89 90 91 92 93 94 95
	{ 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 }
};

96 97 98 99 100 101
static const knot_lookup_t journal_modes[] = {
	{ JOURNAL_MODE_ROBUST, "robust" },
	{ JOURNAL_MODE_ASYNC,  "asynchronous" },
	{ 0, NULL }
};

102 103 104 105 106 107 108
static const yp_item_t desc_module[] = {
	{ C_ID,      YP_TSTR, YP_VNONE, YP_FNONE, { check_module_id } },
	{ C_FILE,    YP_TSTR, YP_VNONE },
	{ C_COMMENT, YP_TSTR, YP_VNONE },
	{ NULL }
};

109
static const yp_item_t desc_server[] = {
110 111 112 113 114 115 116 117 118 119 120 121 122 123
	{ 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 } },
124
	{ C_MAX_UDP_PAYLOAD,      YP_TINT,  YP_VINT = { KNOT_EDNS_MIN_DNSSEC_PAYLOAD,
125
	                                                KNOT_EDNS_MAX_UDP_PAYLOAD,
126 127
	                                                KNOT_EDNS_MAX_UDP_PAYLOAD, YP_SSIZE } },
	{ C_MAX_IPV4_UDP_PAYLOAD, YP_TINT,  YP_VINT = { KNOT_EDNS_MIN_DNSSEC_PAYLOAD,
128
	                                                KNOT_EDNS_MAX_UDP_PAYLOAD,
129 130
	                                                KNOT_EDNS_MAX_UDP_PAYLOAD, YP_SSIZE } },
	{ C_MAX_IPV6_UDP_PAYLOAD, YP_TINT,  YP_VINT = { KNOT_EDNS_MIN_DNSSEC_PAYLOAD,
131
	                                                KNOT_EDNS_MAX_UDP_PAYLOAD,
132
	                                                KNOT_EDNS_MAX_UDP_PAYLOAD, YP_SSIZE } },
133 134 135
	{ C_LISTEN,               YP_TADDR, YP_VADDR = { 53 }, YP_FMULTI },
	{ C_COMMENT,              YP_TSTR,  YP_VNONE },
	/* Obsolete items. */
136
	{ C_RATE_LIMIT,           YP_TINT,  YP_VINT = { 0, INT32_MAX, 0 } },
137
	{ C_RATE_LIMIT_SLIP,      YP_TINT,  YP_VINT = { 0, 100, 1 } },
138
	{ C_RATE_LIMIT_TBL_SIZE,  YP_TINT,  YP_VINT = { 1, INT32_MAX, 393241 } },
139
	{ C_RATE_LIMIT_WHITELIST, YP_TNET,  YP_VNONE, YP_FMULTI },
140 141 142
	{ NULL }
};

143 144
static const yp_item_t desc_control[] = {
	{ C_LISTEN,  YP_TSTR, YP_VSTR = { "knot.sock" } },
145
	{ C_TIMEOUT, YP_TINT, YP_VINT = { 0, INT32_MAX / 1000, 5, YP_STIME } },
146 147 148 149 150 151 152
	{ 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
153
	{ C_CTL,     YP_TOPT, YP_VOPT = { log_severities, 0 } },
154 155 156 157 158 159
	{ 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 }
};

160 161 162 163 164 165 166
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 }
};

167 168
static const yp_item_t desc_keystore[] = {
	{ C_ID,      YP_TSTR, YP_VNONE },
169 170 171
	{ 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 },
172 173 174 175 176
	{ C_COMMENT, YP_TSTR, YP_VNONE },
	{ NULL }
};

static const yp_item_t desc_policy[] = {
177 178 179 180
	{ 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 },
181
	{ C_SINGLE_TYPE_SIGNING, YP_TBOOL, YP_VNONE, CONF_IO_FRLD_ZONES },
Jan Včelák's avatar
Jan Včelák committed
182
	{ C_ALG,                 YP_TOPT,  YP_VOPT = { dnssec_key_algs,
183 184 185 186 187 188 189 190 191 192
	                                               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 },
Libor Peltan's avatar
Libor Peltan committed
193 194
	{ C_KSK_LIFETIME,        YP_TINT,  YP_VINT = { 1, UINT32_MAX, DAYS(3650), YP_STIME },
	                                   CONF_IO_FRLD_ZONES },
195
	{ C_PROPAG_DELAY,        YP_TINT,  YP_VINT = { 0, UINT32_MAX, HOURS(1), YP_STIME },
196
	                                   CONF_IO_FRLD_ZONES },
197 198 199 200 201 202 203 204 205
	{ 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 },
206 207
	{ C_KSK_SUBMITTION_CHECK,YP_TREF,  YP_VREF = { C_RMT }, YP_FMULTI | CONF_IO_FRLD_ZONES, { check_ref } },
	{ C_KSK_SUBMITTION_CHECK_INTERVAL, YP_TINT, YP_VINT = { 1, UINT32_MAX, HOURS(1), YP_STIME }, CONF_IO_FRLD_ZONES },
Jan Včelák's avatar
Jan Včelák committed
208
	{ C_COMMENT,             YP_TSTR,  YP_VNONE },
209 210 211
	{ NULL }
};

212 213
static const yp_item_t desc_key[] = {
	{ C_ID,      YP_TDNAME, YP_VNONE },
214
	{ C_ALG,     YP_TOPT,   YP_VOPT = { tsig_key_algs, DNSSEC_TSIG_UNKNOWN } },
215 216 217 218 219 220
	{ C_SECRET,  YP_TB64,   YP_VNONE },
	{ C_COMMENT, YP_TSTR,   YP_VNONE },
	{ NULL }
};

static const yp_item_t desc_acl[] = {
221
	{ C_ID,      YP_TSTR,  YP_VNONE, CONF_IO_FREF },
222
	{ C_ADDR,    YP_TNET,  YP_VNONE, YP_FMULTI },
223 224 225 226
	{ 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 },
227 228 229 230
	{ NULL }
};

static const yp_item_t desc_remote[] = {
231
	{ C_ID,      YP_TSTR,  YP_VNONE, CONF_IO_FREF },
232 233
	{ C_ADDR,    YP_TADDR, YP_VADDR = { 53 }, YP_FMULTI },
	{ C_VIA,     YP_TADDR, YP_VNONE, YP_FMULTI },
234 235 236 237 238
	{ C_KEY,     YP_TREF,  YP_VREF = { C_KEY }, YP_FNONE, { check_ref } },
	{ C_COMMENT, YP_TSTR,  YP_VNONE },
	{ NULL }
};

239 240
#define ZONE_ITEMS(FLAGS) \
	{ C_STORAGE,             YP_TSTR,  YP_VSTR = { STORAGE_DIR }, FLAGS }, \
Daniel Salzman's avatar
Daniel Salzman committed
241
	{ C_FILE,                YP_TSTR,  YP_VNONE, FLAGS }, \
242 243 244 245
	{ 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 } }, \
246
	{ C_SEM_CHECKS,          YP_TBOOL, YP_VNONE, FLAGS }, \
247 248 249
	{ 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 }, \
250 251 252
	{ C_MAX_ZONE_SIZE,       YP_TINT,  YP_VINT = { 0, INT64_MAX, INT64_MAX, YP_SSIZE }, FLAGS }, \
	{ C_MAX_JOURNAL_USAGE,   YP_TINT,  YP_VINT = { KILO(40), INT64_MAX, MEGA(100), YP_SSIZE } }, \
	{ C_MAX_JOURNAL_DEPTH,   YP_TINT,  YP_VINT = { 2, INT64_MAX, INT64_MAX } }, \
253 254
	{ C_DNSSEC_SIGNING,      YP_TBOOL, YP_VNONE, FLAGS }, \
	{ C_DNSSEC_POLICY,       YP_TREF,  YP_VREF = { C_POLICY }, FLAGS, { check_ref_dflt } }, \
255 256 257
	{ 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 }, \
258
	                                   YP_FMULTI | FLAGS, { check_modref } }, \
259 260 261 262
	{ C_COMMENT,             YP_TSTR,  YP_VNONE }, \
	/* Obsolete, old journal items. */ \
	{ C_JOURNAL,             YP_TSTR,  YP_VNONE, FLAGS }, \
	{ C_MAX_JOURNAL_SIZE,    YP_TINT,  YP_VINT = { 0, INT64_MAX, INT64_MAX, YP_SSIZE }, FLAGS }, \
263 264

static const yp_item_t desc_template[] = {
265 266
	{ C_ID, YP_TSTR, YP_VNONE, CONF_IO_FREF },
	ZONE_ITEMS(CONF_IO_FRLD_ZONES)
267 268 269 270
	{ C_TIMER_DB,            YP_TSTR,  YP_VSTR = { "timers" }, CONF_IO_FRLD_ZONES },
	{ C_GLOBAL_MODULE,       YP_TDATA, YP_VDATA = { 0, NULL, mod_id_to_bin, mod_id_to_txt },
	                                   YP_FMULTI | CONF_IO_FRLD_MOD, { check_modref } },
	{ C_JOURNAL_DB,          YP_TSTR,  YP_VSTR = { "journal" }, CONF_IO_FRLD_SRV },
271 272
	{ C_JOURNAL_DB_MODE,     YP_TOPT,  YP_VOPT = { journal_modes, JOURNAL_MODE_ROBUST },
	                                   CONF_IO_FRLD_SRV },
273 274 275
	{ C_MAX_JOURNAL_DB_SIZE, YP_TINT,  YP_VINT = { JOURNAL_MIN_FSLIMIT, VIRT_MEM_LIMIT(TERA(100)),
	                                               VIRT_MEM_LIMIT(GIGA(20)), YP_SSIZE },
	                                               CONF_IO_FRLD_SRV },
276 277 278
	{ C_KASP_DB,             YP_TSTR,  YP_VSTR = { "keys" }, CONF_IO_FRLD_SRV },
	{ C_KASP_DB_MAPSIZE,     YP_TINT,  YP_VINT = { MEGA(10), GIGA(2), MEGA(500), YP_SSIZE },
	                                               CONF_IO_FRLD_SRV },
279 280 281 282
	{ NULL }
};

static const yp_item_t desc_zone[] = {
283 284 285
	{ 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)
286 287 288 289
	{ NULL }
};

const yp_item_t conf_scheme[] = {
290 291
	{ C_MODULE,   YP_TGRP, YP_VGRP = { desc_module }, YP_FMULTI | CONF_IO_FRLD_ALL |
	                                                  CONF_IO_FCHECK_ZONES, { load_module } },
292
	{ C_SRV,      YP_TGRP, YP_VGRP = { desc_server }, CONF_IO_FRLD_SRV, { check_server } },
293
	{ C_CTL,      YP_TGRP, YP_VGRP = { desc_control } },
294
	{ C_LOG,      YP_TGRP, YP_VGRP = { desc_log }, YP_FMULTI | CONF_IO_FRLD_LOG },
295
	{ C_STATS,    YP_TGRP, YP_VGRP = { desc_stats }, CONF_IO_FRLD_SRV },
296 297 298 299
	{ C_KEYSTORE, YP_TGRP, YP_VGRP = { desc_keystore }, YP_FMULTI, { check_keystore } },
	{ 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 } },
300
	{ C_POLICY,   YP_TGRP, YP_VGRP = { desc_policy }, YP_FMULTI, { check_policy } },
301 302 303
	{ 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 } },
304 305 306
	/* Renamed modules. */
	{ C_MOD_ONLINE_SIGN,  YP_TGRP, YP_VGRP = { scheme_mod_online_sign }, YP_FMULTI, { check_mod_online_sign } },
	{ C_MOD_SYNTH_RECORD, YP_TGRP, YP_VGRP = { scheme_mod_synth_record }, YP_FMULTI, { check_mod_synth_record } },
307 308
	{ NULL }
};