From 361ec726cb1c90448517794de414f083e7e1629d Mon Sep 17 00:00:00 2001 From: Mark Andrews Date: Wed, 3 Jul 2019 16:42:15 +1000 Subject: [PATCH] allow per type record counts to be specified --- bin/named/zoneconf.c | 39 ++++++++++++++----- .../system/checkconf/bad-update-policy16.conf | 18 +++++++++ .../checkconf/good-update-policy13.conf | 18 +++++++++ lib/bind9/check.c | 25 +++++++++++- lib/dns/include/dns/ssu.h | 9 ++++- lib/dns/ssu.c | 29 +++++++------- 6 files changed, 110 insertions(+), 28 deletions(-) create mode 100644 bin/tests/system/checkconf/bad-update-policy16.conf create mode 100644 bin/tests/system/checkconf/good-update-policy13.conf diff --git a/bin/named/zoneconf.c b/bin/named/zoneconf.c index 7cad6c6b7a..785d392e7b 100644 --- a/bin/named/zoneconf.c +++ b/bin/named/zoneconf.c @@ -237,7 +237,7 @@ configure_zone_ssutable(const cfg_obj_t *zconfig, dns_zone_t *zone, dns_ssumatchtype_t mtype = dns_ssumatchtype_name; dns_fixedname_t fname, fident; isc_buffer_t b; - dns_rdatatype_t *types; + dns_ssuruletype_t *types; unsigned int i, n; str = cfg_obj_asstring(mode); @@ -290,7 +290,7 @@ configure_zone_ssutable(const cfg_obj_t *zconfig, dns_zone_t *zone, if (n == 0) { types = NULL; } else { - types = isc_mem_get(mctx, n * sizeof(dns_rdatatype_t)); + types = isc_mem_get(mctx, n * sizeof(*types)); } i = 0; @@ -298,22 +298,43 @@ configure_zone_ssutable(const cfg_obj_t *zconfig, dns_zone_t *zone, element2 = cfg_list_next(element2)) { const cfg_obj_t *typeobj; + const char *bracket; isc_textregion_t r; + unsigned long max = 0; INSIST(i < n); typeobj = cfg_listelt_value(element2); str = cfg_obj_asstring(typeobj); DE_CONST(str, r.base); - r.length = strlen(str); - result = dns_rdatatype_fromtext(&types[i++], &r); + bracket = strchr(str, '(' /*)*/); + if (bracket != NULL) { + char *end = NULL; + r.length = bracket - str; + max = strtoul(bracket + 1, &end, 10); + if (max > 0xffff || end[0] != /*(*/ ')' || + end[1] != 0) { + cfg_obj_log(identity, named_g_lctx, + ISC_LOG_ERROR, + "'%s' is not a valid count", + bracket); + isc_mem_put(mctx, types, + n * sizeof(*types)); + goto cleanup; + } + } else { + r.length = strlen(str); + } + types[i].max = max; + + result = dns_rdatatype_fromtext(&types[i++].type, &r); if (result != ISC_R_SUCCESS) { cfg_obj_log(identity, named_g_lctx, ISC_LOG_ERROR, - "'%s' is not a valid type", str); - isc_mem_put(mctx, types, - n * sizeof(dns_rdatatype_t)); + "'%.*s' is not a valid type", + (int)r.length, str); + isc_mem_put(mctx, types, n * sizeof(types)); goto cleanup; } } @@ -323,7 +344,7 @@ configure_zone_ssutable(const cfg_obj_t *zconfig, dns_zone_t *zone, table, grant, dns_fixedname_name(&fident), mtype, dns_fixedname_name(&fname), n, types); if (types != NULL) { - isc_mem_put(mctx, types, n * sizeof(dns_rdatatype_t)); + isc_mem_put(mctx, types, n * sizeof(*types)); } if (result != ISC_R_SUCCESS) { goto cleanup; @@ -336,7 +357,7 @@ configure_zone_ssutable(const cfg_obj_t *zconfig, dns_zone_t *zone, * update-policy { grant zonesub any; }; */ if (autoddns) { - dns_rdatatype_t any = dns_rdatatype_any; + dns_ssuruletype_t any = { dns_rdatatype_any, 0 }; if (named_g_server->session_keyname == NULL) { isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, diff --git a/bin/tests/system/checkconf/bad-update-policy16.conf b/bin/tests/system/checkconf/bad-update-policy16.conf new file mode 100644 index 0000000000..6870e65e62 --- /dev/null +++ b/bin/tests/system/checkconf/bad-update-policy16.conf @@ -0,0 +1,18 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * 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/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +zone "example.com" { + type master; + file "example.com.db"; + update-policy { + grant * tcp-self . "ptr(10 )"; + }; +}; diff --git a/bin/tests/system/checkconf/good-update-policy13.conf b/bin/tests/system/checkconf/good-update-policy13.conf new file mode 100644 index 0000000000..e67e01f319 --- /dev/null +++ b/bin/tests/system/checkconf/good-update-policy13.conf @@ -0,0 +1,18 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * 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/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +zone "example.com" { + type master; + file "example.com.db"; + update-policy { + grant * tcp-self . ptr(1); + }; +}; diff --git a/lib/bind9/check.c b/lib/bind9/check.c index fdb0f42378..9e761f4832 100644 --- a/lib/bind9/check.c +++ b/lib/bind9/check.c @@ -45,6 +45,7 @@ #include #include #include +#include #include #include #include @@ -1850,15 +1851,35 @@ check_update_policy(const cfg_obj_t *policy, isc_log_t *logctx) { element2 = cfg_list_next(element2)) { const cfg_obj_t *typeobj; + const char *bracket; typeobj = cfg_listelt_value(element2); DE_CONST(cfg_obj_asstring(typeobj), r.base); - r.length = strlen(r.base); + + bracket = strchr(r.base, '(' /*)*/); + if (bracket != NULL) { + char *end = NULL; + unsigned long max; + + r.length = bracket - r.base; + max = strtoul(bracket + 1, &end, 10); + if (max > 0xffff || end[0] != /*(*/ ')' || + end[1] != 0) { + cfg_obj_log(typeobj, logctx, + ISC_LOG_ERROR, + "'%s' is not a valid count", + bracket); + result = DNS_R_SYNTAX; + } + } else { + r.length = strlen(r.base); + } tresult = dns_rdatatype_fromtext(&type, &r); if (tresult != ISC_R_SUCCESS) { cfg_obj_log(typeobj, logctx, ISC_LOG_ERROR, - "'%s' is not a valid type", r.base); + "'%.*s' is not a valid type", + (int)r.length, r.base); result = tresult; } } diff --git a/lib/dns/include/dns/ssu.h b/lib/dns/include/dns/ssu.h index e2ead5bc05..19f49f0b5b 100644 --- a/lib/dns/include/dns/ssu.h +++ b/lib/dns/include/dns/ssu.h @@ -47,6 +47,11 @@ typedef enum { dns_ssumatchtype_dlz = 16 /* intentionally higher than _max */ } dns_ssumatchtype_t; +typedef struct dns_ssuruletype { + dns_rdatatype_t type; /* type allowed */ + unsigned int max; /* maximum number of records allowed. */ +} dns_ssuruletype_t; + isc_result_t dns_ssutable_create(isc_mem_t *mctx, dns_ssutable_t **table); /*%< @@ -103,7 +108,7 @@ isc_result_t dns_ssutable_addrule(dns_ssutable_t *table, bool grant, const dns_name_t *identity, dns_ssumatchtype_t matchtype, const dns_name_t *name, unsigned int ntypes, - dns_rdatatype_t *types); + dns_ssuruletype_t *types); /*%< * Adds a new rule to a simple-secure-update rule table. The rule * either grants or denies update privileges of an identity (or set of @@ -191,7 +196,7 @@ dns_name_t * dns_ssurule_name(const dns_ssurule_t *rule); /*% Accessor functions to extract rule components */ unsigned int -dns_ssurule_types(const dns_ssurule_t *rule, dns_rdatatype_t **types); +dns_ssurule_types(const dns_ssurule_t *rule, dns_ssuruletype_t **types); isc_result_t dns_ssutable_firstrule(const dns_ssutable_t *table, dns_ssurule_t **rule); diff --git a/lib/dns/ssu.c b/lib/dns/ssu.c index 47758b8cf6..c2647b6619 100644 --- a/lib/dns/ssu.c +++ b/lib/dns/ssu.c @@ -44,7 +44,7 @@ struct dns_ssurule { dns_name_t *identity; /*%< the identity to match */ dns_name_t *name; /*%< the name being updated */ unsigned int ntypes; /*%< number of data types covered */ - dns_rdatatype_t *types; /*%< the data types. Can include */ + dns_ssuruletype_t *types; /*%< the data types. Can include */ /* ANY. if NULL, defaults to all */ /* types except SIG, SOA, and NS */ ISC_LINK(dns_ssurule_t) link; @@ -86,15 +86,16 @@ destroy(dns_ssutable_t *table) { dns_ssurule_t *rule = ISC_LIST_HEAD(table->rules); if (rule->identity != NULL) { dns_name_free(rule->identity, mctx); - isc_mem_put(mctx, rule->identity, sizeof(dns_name_t)); + isc_mem_put(mctx, rule->identity, + sizeof(*rule->identity)); } if (rule->name != NULL) { dns_name_free(rule->name, mctx); - isc_mem_put(mctx, rule->name, sizeof(dns_name_t)); + isc_mem_put(mctx, rule->name, sizeof(*rule->name)); } if (rule->types != NULL) { isc_mem_put(mctx, rule->types, - rule->ntypes * sizeof(dns_rdatatype_t)); + rule->ntypes * sizeof(*rule->types)); } ISC_LIST_UNLINK(table->rules, rule, link); rule->magic = 0; @@ -133,7 +134,7 @@ isc_result_t dns_ssutable_addrule(dns_ssutable_t *table, bool grant, const dns_name_t *identity, dns_ssumatchtype_t matchtype, const dns_name_t *name, unsigned int ntypes, - dns_rdatatype_t *types) { + dns_ssuruletype_t *types) { dns_ssurule_t *rule; isc_mem_t *mctx; @@ -149,7 +150,7 @@ dns_ssutable_addrule(dns_ssutable_t *table, bool grant, } mctx = table->mctx; - rule = isc_mem_get(mctx, sizeof(dns_ssurule_t)); + rule = isc_mem_get(mctx, sizeof(*rule)); rule->identity = NULL; rule->name = NULL; @@ -157,11 +158,11 @@ dns_ssutable_addrule(dns_ssutable_t *table, bool grant, rule->grant = grant; - rule->identity = isc_mem_get(mctx, sizeof(dns_name_t)); + rule->identity = isc_mem_get(mctx, sizeof(*rule->identity)); dns_name_init(rule->identity, NULL); dns_name_dup(identity, mctx, rule->identity); - rule->name = isc_mem_get(mctx, sizeof(dns_name_t)); + rule->name = isc_mem_get(mctx, sizeof(*rule->name)); dns_name_init(rule->name, NULL); dns_name_dup(name, mctx, rule->name); @@ -169,9 +170,8 @@ dns_ssutable_addrule(dns_ssutable_t *table, bool grant, rule->ntypes = ntypes; if (ntypes > 0) { - rule->types = isc_mem_get(mctx, - ntypes * sizeof(dns_rdatatype_t)); - memmove(rule->types, types, ntypes * sizeof(dns_rdatatype_t)); + rule->types = isc_mem_get(mctx, ntypes * sizeof(*rule->types)); + memmove(rule->types, types, ntypes * sizeof(*rule->types)); } else { rule->types = NULL; } @@ -513,8 +513,8 @@ dns_ssutable_checkrules(dns_ssutable_t *table, const dns_name_t *signer, } } else { for (i = 0; i < rule->ntypes; i++) { - if (rule->types[i] == dns_rdatatype_any || - rule->types[i] == type) { + if (rule->types[i].type == dns_rdatatype_any || + rule->types[i].type == type) { break; } } @@ -553,7 +553,7 @@ dns_ssurule_name(const dns_ssurule_t *rule) { } unsigned int -dns_ssurule_types(const dns_ssurule_t *rule, dns_rdatatype_t **types) { +dns_ssurule_types(const dns_ssurule_t *rule, dns_ssuruletype_t **types) { REQUIRE(VALID_SSURULE(rule)); REQUIRE(types != NULL && *types != NULL); *types = rule->types; @@ -599,7 +599,6 @@ dns_ssutable_createdlz(isc_mem_t *mctx, dns_ssutable_t **tablep, rule->identity = NULL; rule->name = NULL; - rule->types = NULL; rule->grant = true; rule->matchtype = dns_ssumatchtype_dlz; rule->ntypes = 0;