mirror of
https://github.com/isc-projects/bind9.git
synced 2026-06-11 10:29:59 -04:00
Merge branch 'marka-update-per-type-record-limits' into 'master'
allow per type record counts to be specified in update-policy Closes #1657 See merge request isc-projects/bind9!2124
This commit is contained in:
commit
6ace801ddf
14 changed files with 309 additions and 58 deletions
5
CHANGES
5
CHANGES
|
|
@ -1,3 +1,8 @@
|
|||
5410. [func] Add the ability to specify per-type record count
|
||||
limits in an "update-policy" statement, which
|
||||
are enforced when adding records via UPDATE.
|
||||
[GL #1657]
|
||||
|
||||
5409. [performance] When looking up NSEC3 data in a zone database, skip
|
||||
the check for empty non-terminal nodes; the NSEC3
|
||||
tree doesn't have any. [GL #1834]
|
||||
|
|
|
|||
|
|
@ -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 <session-keyname> 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,
|
||||
|
|
|
|||
18
bin/tests/system/checkconf/bad-update-policy16.conf
Normal file
18
bin/tests/system/checkconf/bad-update-policy16.conf
Normal file
|
|
@ -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 )";
|
||||
};
|
||||
};
|
||||
18
bin/tests/system/checkconf/good-update-policy13.conf
Normal file
18
bin/tests/system/checkconf/good-update-policy13.conf
Normal file
|
|
@ -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);
|
||||
};
|
||||
};
|
||||
|
|
@ -60,3 +60,5 @@ rm -f update.out.*
|
|||
rm -f check.out.*
|
||||
rm -f update.out.*
|
||||
rm -f ns*/managed-keys.bind* ns*/*.mkeys*
|
||||
rm -f nextpart.out.*
|
||||
rm -f */named.run.prev
|
||||
|
|
|
|||
|
|
@ -34,5 +34,5 @@ controls {
|
|||
zone "in-addr.arpa" {
|
||||
type master;
|
||||
file "in-addr.db";
|
||||
update-policy { grant * tcp-self . PTR; };
|
||||
update-policy { grant * tcp-self . PTR(1) ANY(2) A; };
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1031,6 +1031,65 @@ grep "UPDATE, status: NOERROR" nsupdate.out-$n > /dev/null 2>&1 || ret=1
|
|||
grep "UPDATE, status: FORMERR" nsupdate.out-$n > /dev/null 2>&1 || ret=1
|
||||
[ $ret = 0 ] || { echo_i "failed"; status=1; }
|
||||
|
||||
n=`expr $n + 1`
|
||||
ret=0
|
||||
echo_i "check that max records is enforced ($n)"
|
||||
nextpart ns6/named.run > /dev/null
|
||||
$NSUPDATE -v > nsupdate.out.$n 2>&1 << END
|
||||
server 10.53.0.6 ${PORT}
|
||||
local 10.53.0.5
|
||||
update del 5.0.53.10.in-addr.arpa.
|
||||
update add 5.0.53.10.in-addr.arpa. 600 PTR localhost.
|
||||
update add 5.0.53.10.in-addr.arpa. 600 PTR other.
|
||||
send
|
||||
END
|
||||
$DIG $DIGOPTS @10.53.0.6 \
|
||||
+tcp +noadd +nosea +nostat +noquest +nocomm +nocmd \
|
||||
-x 10.53.0.5 > dig.out.ns6.$n
|
||||
# the policy is 'grant * tcp-self . PTR(1) ANY(2) A;' so only the
|
||||
# first PTR record should be added.
|
||||
grep localhost. dig.out.ns6.$n > /dev/null 2>&1 || ret=1
|
||||
grep other. dig.out.ns6.$n > /dev/null 2>&1 && ret=1
|
||||
nextpart ns6/named.run > nextpart.out.$n
|
||||
grep "attempt to add more records than permitted by policy" nextpart.out.$n > /dev/null || ret=1
|
||||
if test $ret -ne 0
|
||||
then
|
||||
echo_i "failed"; status=1
|
||||
fi
|
||||
|
||||
n=`expr $n + 1`
|
||||
ret=0
|
||||
echo_i "check that max records for ANY is enforced ($n)"
|
||||
nextpart ns6/named.run > /dev/null
|
||||
$NSUPDATE -v > nsupdate.out.$n 2>&1 << END
|
||||
server 10.53.0.6 ${PORT}
|
||||
local 10.53.0.5
|
||||
update del 5.0.53.10.in-addr.arpa.
|
||||
update add 5.0.53.10.in-addr.arpa. 600 A 1.2.3.4
|
||||
update add 5.0.53.10.in-addr.arpa. 600 A 1.2.3.3
|
||||
update add 5.0.53.10.in-addr.arpa. 600 A 1.2.3.2
|
||||
update add 5.0.53.10.in-addr.arpa. 600 AAAA ::ffff:1.2.3.4
|
||||
update add 5.0.53.10.in-addr.arpa. 600 AAAA ::ffff:1.2.3.3
|
||||
update add 5.0.53.10.in-addr.arpa. 600 AAAA ::ffff:1.2.3.2
|
||||
send
|
||||
END
|
||||
$DIG $DIGOPTS @10.53.0.6 \
|
||||
+tcp +noadd +nosea +nostat +noquest +nocomm +nocmd \
|
||||
ANY -x 10.53.0.5 > dig.out.ns6.test$n
|
||||
nextpart ns6/named.run > nextpart.out.test$n
|
||||
grep "attempt to add more records than permitted by policy" nextpart.out.test$n > /dev/null || ret=1
|
||||
# the policy is 'grant * tcp-self . PTR(1) ANY(2) A;' so all the A
|
||||
# records should have been added as there is no limit and the first 2
|
||||
# of the AAAA records added as they match ANY(2).
|
||||
c1=$(awk '$4 == "A" { print }' dig.out.ns6.test$n | wc -l)
|
||||
c2=$(awk '$4 == "AAAA" { print }' dig.out.ns6.test$n | wc -l)
|
||||
test "$c1" -eq 3 -a "$c2" -eq 2 || ret=1
|
||||
grep "::ffff:1.2.3.2" dig.out.ns6.test$n && ret=1
|
||||
if test $ret -ne 0
|
||||
then
|
||||
echo_i "failed"; status=1
|
||||
fi
|
||||
|
||||
if $FEATURETEST --gssapi ; then
|
||||
n=`expr $n + 1`
|
||||
ret=0
|
||||
|
|
|
|||
|
|
@ -8,16 +8,6 @@
|
|||
See the COPYRIGHT file distributed with this work for additional
|
||||
information regarding copyright ownership.
|
||||
|
||||
..
|
||||
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.
|
||||
|
||||
.. Reference:
|
||||
|
||||
BIND 9 Configuration Reference
|
||||
|
|
@ -5708,6 +5698,29 @@ never be updated). Note that when an attempt is made to delete all
|
|||
records associated with a name, the rules are checked for each existing
|
||||
record type.
|
||||
|
||||
If the type is immediately followed by a number in parentheses,
|
||||
that number is the maximum number of records of that type permitted
|
||||
to exist in the RRset after an update has been applied. For example,
|
||||
``PTR(1)`` indicates that only one PTR record is allowed. If an
|
||||
attempt is made to add two PTR records in an update, the second one
|
||||
will be silently discarded. If a PTR record already exists, both
|
||||
new records will be silently discarded.
|
||||
|
||||
If type ANY is specified with a limit, then that limit applies to
|
||||
all types that are not otherwise specified. For example, ``A PTR(1)
|
||||
ANY(2)`` indicates that an unlimited number of A records can exist,
|
||||
but only one PTR record, and no more than two of any other type.
|
||||
|
||||
Typical use with rule ``grant * tcp-self . PTR(1);`` in the zone
|
||||
2.0.192.IN-ADDR.ARPA::
|
||||
|
||||
nsupdate -v <<EOF
|
||||
local 192.0.2.1
|
||||
del 1.2.0.192.IN-ADDR.ARPA PTR
|
||||
add 1.2.0.192.IN-ADDR.ARPA 0 PTR EXAMPLE.COM
|
||||
send
|
||||
EOF
|
||||
|
||||
The ruletype field has 16 values: ``name``, ``subdomain``, ``wildcard``,
|
||||
``self``, ``selfsub``, ``selfwild``, ``krb5-self``, ``ms-self``,
|
||||
``krb5-selfsub``, ``ms-selfsub``, ``krb5-subdomain``, ``ms-subdomain``,
|
||||
|
|
|
|||
|
|
@ -58,6 +58,10 @@ New Features
|
|||
- ``dig`` and other tools can now print the Extended DNS Error (EDE)
|
||||
option when it appears in a request or response. [GL #1834]
|
||||
|
||||
- Per-type record count limits can now be specified in ``update-policy``
|
||||
statements, to limit the number of records of a particular type
|
||||
that can be added to a domain name via dynamic update. [GL #1657]
|
||||
|
||||
Feature Changes
|
||||
~~~~~~~~~~~~~~~
|
||||
|
||||
|
|
|
|||
|
|
@ -45,6 +45,7 @@
|
|||
#include <dns/rbt.h>
|
||||
#include <dns/rdataclass.h>
|
||||
#include <dns/rdatatype.h>
|
||||
#include <dns/result.h>
|
||||
#include <dns/rrl.h>
|
||||
#include <dns/secalg.h>
|
||||
#include <dns/ssu.h>
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -136,7 +141,7 @@ bool
|
|||
dns_ssutable_checkrules(dns_ssutable_t *table, const dns_name_t *signer,
|
||||
const dns_name_t *name, const isc_netaddr_t *addr,
|
||||
bool tcp, const dns_aclenv_t *env, dns_rdatatype_t type,
|
||||
const dst_key_t *key);
|
||||
const dst_key_t *key, const dns_ssurule_t **rulep);
|
||||
/*%<
|
||||
* Checks that the attempted update of (name, type) is allowed according
|
||||
* to the rules specified in the simple-secure-update rule table. If
|
||||
|
|
@ -180,18 +185,31 @@ dns_ssutable_checkrules(dns_ssutable_t *table, const dns_name_t *signer,
|
|||
/*% Accessor functions to extract rule components */
|
||||
bool
|
||||
dns_ssurule_isgrant(const dns_ssurule_t *rule);
|
||||
|
||||
/*% Accessor functions to extract rule components */
|
||||
dns_name_t *
|
||||
dns_ssurule_identity(const dns_ssurule_t *rule);
|
||||
|
||||
/*% Accessor functions to extract rule components */
|
||||
unsigned int
|
||||
dns_ssurule_matchtype(const dns_ssurule_t *rule);
|
||||
|
||||
/*% Accessor functions to extract rule components */
|
||||
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);
|
||||
|
||||
unsigned int
|
||||
dns_ssurule_max(const dns_ssurule_t *rule, dns_rdatatype_t type);
|
||||
/*%<
|
||||
* Returns the maximum number of records configured for type `type`.
|
||||
* If no maximum has been configured for `type` but one has been
|
||||
* configured for ANY, return that value instead. Otherwise, return
|
||||
* zero, which implies "unlimited".
|
||||
*/
|
||||
|
||||
isc_result_t
|
||||
dns_ssutable_firstrule(const dns_ssutable_t *table, dns_ssurule_t **rule);
|
||||
|
|
|
|||
|
|
@ -39,12 +39,11 @@
|
|||
struct dns_ssurule {
|
||||
unsigned int magic;
|
||||
bool grant; /*%< is this a grant or a deny? */
|
||||
dns_ssumatchtype_t matchtype; /*%< which type of pattern match?
|
||||
* */
|
||||
dns_ssumatchtype_t matchtype; /*%< which type of pattern match? */
|
||||
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 +85,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 +133,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 +149,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 +157,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 +169,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;
|
||||
}
|
||||
|
|
@ -284,15 +283,15 @@ bool
|
|||
dns_ssutable_checkrules(dns_ssutable_t *table, const dns_name_t *signer,
|
||||
const dns_name_t *name, const isc_netaddr_t *addr,
|
||||
bool tcp, const dns_aclenv_t *env, dns_rdatatype_t type,
|
||||
const dst_key_t *key) {
|
||||
dns_ssurule_t *rule;
|
||||
unsigned int i;
|
||||
const dst_key_t *key, const dns_ssurule_t **rulep) {
|
||||
dns_fixedname_t fixed;
|
||||
dns_name_t *wildcard;
|
||||
dns_name_t *tcpself;
|
||||
dns_name_t *stfself;
|
||||
isc_result_t result;
|
||||
dns_name_t *tcpself;
|
||||
dns_name_t *wildcard;
|
||||
dns_ssurule_t *rule;
|
||||
int match;
|
||||
isc_result_t result;
|
||||
unsigned int i;
|
||||
|
||||
REQUIRE(VALID_SSUTABLE(table));
|
||||
REQUIRE(signer == NULL || dns_name_isabsolute(signer));
|
||||
|
|
@ -513,8 +512,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;
|
||||
}
|
||||
}
|
||||
|
|
@ -522,6 +521,9 @@ dns_ssutable_checkrules(dns_ssutable_t *table, const dns_name_t *signer,
|
|||
continue;
|
||||
}
|
||||
}
|
||||
if (rule->grant && rulep != NULL) {
|
||||
*rulep = rule;
|
||||
}
|
||||
return (rule->grant);
|
||||
}
|
||||
|
||||
|
|
@ -553,13 +555,31 @@ 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;
|
||||
return (rule->ntypes);
|
||||
}
|
||||
|
||||
unsigned int
|
||||
dns_ssurule_max(const dns_ssurule_t *rule, dns_rdatatype_t type) {
|
||||
unsigned int i;
|
||||
unsigned int max = 0;
|
||||
|
||||
REQUIRE(VALID_SSURULE(rule));
|
||||
|
||||
for (i = 0; i < rule->ntypes; i++) {
|
||||
if (rule->types[i].type == dns_rdatatype_any) {
|
||||
max = rule->types[i].max;
|
||||
}
|
||||
if (rule->types[i].type == type) {
|
||||
return (rule->types[i].max);
|
||||
}
|
||||
}
|
||||
return (max);
|
||||
}
|
||||
|
||||
isc_result_t
|
||||
dns_ssutable_firstrule(const dns_ssutable_t *table, dns_ssurule_t **rule) {
|
||||
REQUIRE(VALID_SSUTABLE(table));
|
||||
|
|
@ -599,7 +619,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;
|
||||
|
|
|
|||
|
|
@ -1019,9 +1019,10 @@ dns_soa_setretry
|
|||
dns_soa_setserial
|
||||
dns_ssu_external_match
|
||||
dns_ssu_mtypefromstring
|
||||
dns_ssurule_isgrant
|
||||
dns_ssurule_identity
|
||||
dns_ssurule_isgrant
|
||||
dns_ssurule_matchtype
|
||||
dns_ssurule_max
|
||||
dns_ssurule_name
|
||||
dns_ssurule_types
|
||||
dns_ssutable_firstrule
|
||||
|
|
|
|||
|
|
@ -753,6 +753,17 @@ cleanup_node:
|
|||
typedef bool
|
||||
rr_predicate(dns_rdata_t *update_rr, dns_rdata_t *db_rr);
|
||||
|
||||
static isc_result_t
|
||||
count_action(void *data, rr_t *rr) {
|
||||
unsigned int *ui = (unsigned int *)data;
|
||||
|
||||
UNUSED(rr);
|
||||
|
||||
(*ui)++;
|
||||
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
|
||||
/*%
|
||||
* Helper function for rrset_exists().
|
||||
*/
|
||||
|
|
@ -899,8 +910,9 @@ typedef struct {
|
|||
|
||||
static isc_result_t
|
||||
ssu_checkrule(void *data, dns_rdataset_t *rrset) {
|
||||
ssu_check_t *ssuinfo = data;
|
||||
bool result;
|
||||
const dns_ssurule_t *rule = NULL;
|
||||
ssu_check_t *ssuinfo = data;
|
||||
|
||||
/*
|
||||
* If we're deleting all records, it's ok to delete RRSIG and NSEC even
|
||||
|
|
@ -910,9 +922,10 @@ ssu_checkrule(void *data, dns_rdataset_t *rrset) {
|
|||
rrset->type == dns_rdatatype_nsec) {
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
result = dns_ssutable_checkrules(
|
||||
ssuinfo->table, ssuinfo->signer, ssuinfo->name, ssuinfo->addr,
|
||||
ssuinfo->tcp, ssuinfo->aclenv, rrset->type, ssuinfo->key);
|
||||
result = dns_ssutable_checkrules(ssuinfo->table, ssuinfo->signer,
|
||||
ssuinfo->name, ssuinfo->addr,
|
||||
ssuinfo->tcp, ssuinfo->aclenv,
|
||||
rrset->type, ssuinfo->key, &rule);
|
||||
return (result == true ? ISC_R_SUCCESS : ISC_R_FAILURE);
|
||||
}
|
||||
|
||||
|
|
@ -2565,6 +2578,9 @@ update_action(isc_task_t *task, isc_event_t *event) {
|
|||
uint64_t records;
|
||||
dns_aclenv_t *env =
|
||||
ns_interfacemgr_getaclenv(client->manager->interface->mgr);
|
||||
size_t ruleslen = 0;
|
||||
size_t rule;
|
||||
const dns_ssurule_t **rules = NULL;
|
||||
|
||||
INSIST(event->ev_type == DNS_EVENT_UPDATE);
|
||||
|
||||
|
|
@ -2739,15 +2755,24 @@ update_action(isc_task_t *task, isc_event_t *event) {
|
|||
/*
|
||||
* Perform the Update Section Prescan.
|
||||
*/
|
||||
if (ssutable != NULL) {
|
||||
ruleslen = request->counts[DNS_SECTION_UPDATE];
|
||||
rules = isc_mem_get(mctx, sizeof(*rules) * ruleslen);
|
||||
memset(rules, 0, sizeof(*rules) * ruleslen);
|
||||
}
|
||||
|
||||
for (result = dns_message_firstname(request, DNS_SECTION_UPDATE);
|
||||
for (rule = 0,
|
||||
result = dns_message_firstname(request, DNS_SECTION_UPDATE);
|
||||
result == ISC_R_SUCCESS;
|
||||
result = dns_message_nextname(request, DNS_SECTION_UPDATE))
|
||||
rule++, result = dns_message_nextname(request, DNS_SECTION_UPDATE))
|
||||
{
|
||||
dns_name_t *name = NULL;
|
||||
dns_rdata_t rdata = DNS_RDATA_INIT;
|
||||
dns_ttl_t ttl;
|
||||
dns_rdataclass_t update_class;
|
||||
|
||||
INSIST(ssutable == NULL || rule < ruleslen);
|
||||
|
||||
get_current_rr(request, DNS_SECTION_UPDATE, zoneclass, &name,
|
||||
&rdata, &covers, &ttl, &update_class);
|
||||
|
||||
|
|
@ -2820,7 +2845,7 @@ update_action(isc_task_t *task, isc_event_t *event) {
|
|||
if (!dns_ssutable_checkrules(
|
||||
ssutable, client->signer, name,
|
||||
&netaddr, TCPCLIENT(client), env,
|
||||
rdata.type, tsigkey))
|
||||
rdata.type, tsigkey, &rules[rule]))
|
||||
{
|
||||
FAILC(DNS_R_REFUSED, "rejected by "
|
||||
"secure update");
|
||||
|
|
@ -2847,9 +2872,10 @@ update_action(isc_task_t *task, isc_event_t *event) {
|
|||
*/
|
||||
|
||||
options = dns_zone_getoptions(zone);
|
||||
for (result = dns_message_firstname(request, DNS_SECTION_UPDATE);
|
||||
for (rule = 0,
|
||||
result = dns_message_firstname(request, DNS_SECTION_UPDATE);
|
||||
result == ISC_R_SUCCESS;
|
||||
result = dns_message_nextname(request, DNS_SECTION_UPDATE))
|
||||
rule++, result = dns_message_nextname(request, DNS_SECTION_UPDATE))
|
||||
{
|
||||
dns_name_t *name = NULL;
|
||||
dns_rdata_t rdata = DNS_RDATA_INIT;
|
||||
|
|
@ -2857,10 +2883,14 @@ update_action(isc_task_t *task, isc_event_t *event) {
|
|||
dns_rdataclass_t update_class;
|
||||
bool flag;
|
||||
|
||||
INSIST(ssutable == NULL || rule < ruleslen);
|
||||
|
||||
get_current_rr(request, DNS_SECTION_UPDATE, zoneclass, &name,
|
||||
&rdata, &covers, &ttl, &update_class);
|
||||
|
||||
if (update_class == zoneclass) {
|
||||
unsigned int max = 0;
|
||||
|
||||
/*
|
||||
* RFC1123 doesn't allow MF and MD in master zones.
|
||||
*/
|
||||
|
|
@ -2986,6 +3016,24 @@ update_action(isc_task_t *task, isc_event_t *event) {
|
|||
}
|
||||
}
|
||||
|
||||
if (rules != NULL && rules[rule] != NULL) {
|
||||
max = dns_ssurule_max(rules[rule], rdata.type);
|
||||
}
|
||||
if (max != 0) {
|
||||
unsigned int count = 0;
|
||||
CHECK(foreach_rr(db, ver, name, rdata.type,
|
||||
covers, count_action, &count));
|
||||
if (count >= max) {
|
||||
update_log(client, zone,
|
||||
LOGLEVEL_PROTOCOL,
|
||||
"attempt to add more "
|
||||
"records than permitted by "
|
||||
"policy max=%u",
|
||||
max);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (isc_log_wouldlog(ns_lctx, LOGLEVEL_PROTOCOL)) {
|
||||
char namestr[DNS_NAME_FORMATSIZE];
|
||||
char typestr[DNS_RDATATYPE_FORMATSIZE];
|
||||
|
|
@ -3420,6 +3468,10 @@ common:
|
|||
dns_db_detach(&db);
|
||||
}
|
||||
|
||||
if (rules != NULL) {
|
||||
isc_mem_put(mctx, rules, sizeof(*rules) * ruleslen);
|
||||
}
|
||||
|
||||
if (ssutable != NULL) {
|
||||
dns_ssutable_detach(&ssutable);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue