Commit 2f2627c3 authored by Daniel Salzman's avatar Daniel Salzman

Merge branch 'acl_ext' into 'master'

ACL update action granularity

See merge request !953
parents 573569a1 2b6f5912
......@@ -99,6 +99,9 @@ If there are multiple ACL rules for a single zone, they are applied in the order
of appearance in the :ref:`zone_acl` configuration item of a zone or a template.
The first one to match the given remote is applied, the rest is ignored.
For dynamic updates, additional rules may be specified, which will allow or deny updates
according to the type or owner of Resource Records in the update.
See the following examples and :ref:`ACL section`.
::
......@@ -137,6 +140,16 @@ See the following examples and :ref:`ACL section`.
- domain: acl2.example.com
acl: [deny_all, key_rule]
::
acl
- id: owner_type_rule
action: update
update-owner: name # The allowed owners are specified by the list on the next line
update-owner-name: [a.example.com, b.example.com, c.example.com]
update-owner-type: [A, AAAA, MX] # Updates are only allowed to update records of the specified types
update-owner-match: equal # The owners of records in an update must be exactly equal to the names in the list
.. NOTE::
If more conditions (address ranges and/or a key)
are given in a single ACL rule, all of them have to be satisfied for the rule to match.
......
......@@ -388,6 +388,10 @@ acl:
key: key_id ...
action: notify | transfer | update ...
deny: BOOL
update\-type: STR ...
update\-owner: key | zone | name
update\-owner\-match: sub\-or\-equal | equal | sub
update\-owner\-name: STR ...
.ft P
.fi
.UNINDENT
......@@ -429,6 +433,56 @@ If enabled, instead of allowing, deny the specified \fI\%action\fP,
items. If no action is specified, deny all actions.
.sp
\fIDefault:\fP off
.SS update\-type
.sp
A list of allowed types of Resource Records in a zone update. Every record in an update
must match one of the specified types.
.sp
\fIDefault:\fP not set
.SS update\-owner
.sp
This option restricts possible owners of Resource Records in a zone update by comparing
them to either the \fI\%TSIG key\fP identity, the current zone name, or to a list of
domain names given by the \fI\%update\-owner\-name\fP option.
The comparison method is given by the \fI\%update\-owner\-match\fP option.
.sp
Possible values:
.INDENT 0.0
.IP \(bu 2
\fBkey\fP — The owner of each updated RR must match the identity of the TSIG key if used.
.IP \(bu 2
\fBname\fP — The owner of each updated RR must match at least one name in the
\fI\%update\-owner\-name\fP list.
.IP \(bu 2
\fBzone\fP — The owner of each updated RR must match the current zone name.
.UNINDENT
.sp
\fIDefault:\fP not set
.SS update\-owner\-match
.sp
This option defines how the owners of Resource Records in an update are matched to the domain name(s)
set by the \fI\%update\-owner\fP option.
.sp
Possible values:
.INDENT 0.0
.IP \(bu 2
\fBsub\-or\-equal\fP — The owner of each Resource Record in an update must either be equal to
or be a subdomain of at least one domain set by \fI\%update\-owner\fP\&.
.IP \(bu 2
\fBequal\fP — The owner of each updated RR must be equal to at least one domain set by
\fI\%update\-owner\fP\&.
.IP \(bu 2
\fBsub\fP — The owner of each updated RR must be a subdomain of, but MUST NOT be equal to at least
one domain set by \fI\%update\-owner\fP\&.
.UNINDENT
.sp
\fIDefault:\fP sub\-or\-equal
.SS update\-owner\-name
.sp
A list of allowed owners of RRs in a zone update used with \fI\%update\-owner\fP
set to \fBname\fP\&.
.sp
\fIDefault:\fP not set
.SH CONTROL SECTION
.sp
Configuration of the server control interface.
......
......@@ -416,6 +416,10 @@ update, etc.).
key: key_id ...
action: notify | transfer | update ...
deny: BOOL
update-type: STR ...
update-owner: key | zone | name
update-owner-match: sub-or-equal | equal | sub
update-owner-name: STR ...
.. _acl_id:
......@@ -470,6 +474,64 @@ items. If no action is specified, deny all actions.
*Default:* off
.. _acl_update_type:
update-type
-----------
A list of allowed types of Resource Records in a zone update. Every record in an update
must match one of the specified types.
*Default:* not set
.. _acl_update_owner:
update-owner
------------
This option restricts possible owners of Resource Records in a zone update by comparing
them to either the :ref:`TSIG key<acl_key>` identity, the current zone name, or to a list of
domain names given by the :ref:`update-owner-name<acl_update_owner_name>` option.
The comparison method is given by the :ref:`update-owner-match<acl_update_owner_match>` option.
Possible values:
- ``key`` — The owner of each updated RR must match the identity of the TSIG key if used.
- ``name`` — The owner of each updated RR must match at least one name in the
:ref:`update-owner-name<acl_update_owner_name>` list.
- ``zone`` — The owner of each updated RR must match the current zone name.
*Default:* not set
.. _acl_update_owner_match:
update-owner-match
------------------
This option defines how the owners of Resource Records in an update are matched to the domain name(s)
set by the :ref:`update-owner<acl_update_owner>` option.
Possible values:
- ``sub-or-equal`` — The owner of each Resource Record in an update must either be equal to
or be a subdomain of at least one domain set by :ref:`update-owner<acl_update_owner>`.
- ``equal`` — The owner of each updated RR must be equal to at least one domain set by
:ref:`update-owner<acl_update_owner>`.
- ``sub`` — The owner of each updated RR must be a subdomain of, but MUST NOT be equal to at least
one domain set by :ref:`update-owner<acl_update_owner>`.
*Default:* sub-or-equal
.. _acl_update_owner_name:
update-owner-name
-----------------
A list of allowed owners of RRs in a zone update used with :ref:`update-owner<acl_update_owner>`
set to ``name``.
*Default:* not set
.. _Control section:
Control section
......@@ -751,7 +813,7 @@ Possible values:
ksk-size
--------
A length of newly generated :abbr:`KSK (Key Signing Key)` or
A length of newly generated :abbr:`KSK (Key Signing Key)` or
:abbr:`CSK (Combined Signing Key)` keys.
*Default:* 2048 (rsa*), 256 (ecdsap256), 384 (ecdsap384), 256 (ed25519)
......
......@@ -404,15 +404,8 @@ void conf_val(
if (val->data != NULL && val->code != KNOT_EOF) {
return;
}
assert(val->blob != NULL);
wire_ctx_t ctx = wire_ctx_init_const(val->blob, val->blob_len);
uint16_t len = wire_ctx_read_u16(&ctx);
assert(ctx.error == KNOT_EOK);
val->data = ctx.position;
val->len = len;
val->code = KNOT_EOK;
// Otherwise set to the first value.
conf_val_reset(val);
} else {
// Check for empty data.
if (val->blob_len == 0) {
......@@ -459,6 +452,22 @@ void conf_val_next(
}
}
void conf_val_reset(conf_val_t *val)
{
assert(val != NULL);
assert(val->code == KNOT_EOK || val->code == KNOT_EOF);
assert(val->item->flags & YP_FMULTI);
assert(val->blob != NULL);
wire_ctx_t ctx = wire_ctx_init_const(val->blob, val->blob_len);
uint16_t len = wire_ctx_read_u16(&ctx);
assert(ctx.error == KNOT_EOK);
val->data = ctx.position;
val->len = len;
val->code = KNOT_EOK;
}
bool conf_val_equal(
conf_val_t *val1,
conf_val_t *val2)
......
......@@ -352,7 +352,7 @@ void conf_val(
);
/*!
* Moves to the next item value.
* Moves to the next value of a multi-valued item.
*
* \param[in] val Item value.
*/
......@@ -360,6 +360,15 @@ void conf_val_next(
conf_val_t *val
);
/*!
* Resets to the first value of a multi-valued item.
*
* \param[in] val Item value.
*/
void conf_val_reset(
conf_val_t *val
);
/*!
* Gets the number of values if multivalued item.
*
......
......@@ -86,6 +86,20 @@ const knot_lookup_t acl_actions[] = {
{ 0, NULL }
};
const knot_lookup_t acl_update_owner[] = {
{ ACL_UPDATE_OWNER_KEY, "key" },
{ ACL_UPDATE_OWNER_ZONE, "zone" },
{ ACL_UPDATE_OWNER_NAME, "name" },
{ 0, NULL }
};
const knot_lookup_t acl_update_owner_match[] = {
{ ACL_UPDATE_MATCH_SUBEQ, "sub-or-equal" },
{ ACL_UPDATE_MATCH_EQ, "equal" },
{ ACL_UPDATE_MATCH_SUB, "sub" },
{ 0, NULL }
};
static const knot_lookup_t serial_policies[] = {
{ SERIAL_POLICY_INCREMENT, "increment" },
{ SERIAL_POLICY_UNIXTIME, "unixtime" },
......@@ -204,12 +218,17 @@ static const yp_item_t desc_key[] = {
};
static const yp_item_t desc_acl[] = {
{ C_ID, YP_TSTR, YP_VNONE, CONF_IO_FREF },
{ C_ADDR, YP_TNET, YP_VNONE, YP_FMULTI },
{ 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 },
{ C_ID, YP_TSTR, YP_VNONE, CONF_IO_FREF },
{ C_ADDR, YP_TNET, YP_VNONE, YP_FMULTI },
{ 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_UPDATE_OWNER, YP_TOPT, YP_VOPT = { acl_update_owner, ACL_UPDATE_OWNER_NONE } },
{ C_UPDATE_OWNER_MATCH, YP_TOPT, YP_VOPT = { acl_update_owner_match, ACL_UPDATE_MATCH_SUBEQ } },
{ C_UPDATE_OWNER_NAME, YP_TDNAME, YP_VNONE, YP_FMULTI },
{ C_UPDATE_TYPE, YP_TDATA, YP_VDATA = { 0, NULL, rrtype_to_bin, rrtype_to_txt },
YP_FMULTI, },
{ C_COMMENT, YP_TSTR, YP_VNONE },
{ NULL }
};
......
......@@ -110,6 +110,10 @@
#define C_TIMER_DB "\x08""timer-db"
#define C_TPL "\x08""template"
#define C_UDP_WORKERS "\x0B""udp-workers"
#define C_UPDATE_OWNER "\x0C""update-owner"
#define C_UPDATE_OWNER_MATCH "\x12""update-owner-match"
#define C_UPDATE_OWNER_NAME "\x11""update-owner-name"
#define C_UPDATE_TYPE "\x0B""update-type"
#define C_USER "\x04""user"
#define C_VERSION "\x07""version"
#define C_VIA "\x03""via"
......
......@@ -182,6 +182,35 @@ int edns_opt_to_txt(
YP_CHECK_RET;
}
int rrtype_to_bin(
YP_TXT_BIN_PARAMS)
{
YP_CHECK_PARAMS_BIN;
uint16_t type;
int ret = knot_rrtype_from_string((char *)in->position, &type);
if (ret != 0) {
return KNOT_EINVAL;
}
wire_ctx_write_u64(out, type);
YP_CHECK_RET;
}
int rrtype_to_txt(
YP_BIN_TXT_PARAMS)
{
YP_CHECK_PARAMS_TXT;
uint16_t type = (uint16_t)wire_ctx_read_u64(in);
int ret = knot_rrtype_to_string(type, (char *)out->position, out->size);
if (ret != 0) {
return KNOT_EINVAL;
}
YP_CHECK_RET;
}
int check_ref(
knotd_conf_check_args_t *args)
{
......
......@@ -50,6 +50,14 @@ int edns_opt_to_txt(
YP_BIN_TXT_PARAMS
);
int rrtype_to_bin(
YP_TXT_BIN_PARAMS
);
int rrtype_to_txt(
YP_BIN_TXT_PARAMS
);
int check_ref(
knotd_conf_check_args_t *args
);
......
......@@ -108,7 +108,7 @@ static void axfr_query_cleanup(knotd_qdata_t *qdata)
static int axfr_query_check(knotd_qdata_t *qdata)
{
NS_NEED_ZONE(qdata, KNOT_RCODE_NOTAUTH);
NS_NEED_AUTH(qdata, qdata->extra->zone->name, ACL_ACTION_TRANSFER);
NS_NEED_AUTH(qdata, ACL_ACTION_TRANSFER);
NS_NEED_ZONE_CONTENTS(qdata, KNOT_RCODE_SERVFAIL);
return KNOT_STATE_DONE;
......
/* Copyright (C) 2015 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
/* Copyright (C) 2018 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
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
......@@ -13,14 +13,6 @@
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
/*!
* \file
*
* \brief Chaos class processing.
*
* \addtogroup query_processing
* @{
*/
#pragma once
......@@ -30,5 +22,3 @@
* \brief Create a response for a given query in the CHAOS class.
*/
int knot_chaos_answer(knot_pkt_t *pkt);
/*! @} */
......@@ -646,7 +646,7 @@ int internet_process_query(knot_pkt_t *pkt, knotd_qdata_t *qdata)
/* No applicable ACL, refuse transaction security. */
if (knot_pkt_has_tsig(qdata->query)) {
/* We have been challenged... */
NS_NEED_AUTH(qdata, qdata->extra->zone->name, ACL_ACTION_NONE);
NS_NEED_AUTH(qdata, ACL_ACTION_NONE);
/* Reserve space for TSIG. */
int ret = knot_pkt_reserve(pkt, knot_tsig_wire_size(&qdata->sign.tsig_key));
......
......@@ -57,8 +57,8 @@ int internet_process_query(knot_pkt_t *pkt, knotd_qdata_t *qdata);
}
/*! \brief Require authentication. */
#define NS_NEED_AUTH(qdata, zone_name, action) \
if (!process_query_acl_check(conf(), (zone_name), (action), (qdata)) || \
#define NS_NEED_AUTH(qdata, action) \
if (!process_query_acl_check(conf(), (action), (qdata)) || \
process_query_verify(qdata) != KNOT_EOK) { \
return KNOT_STATE_FAIL; \
}
......
......@@ -113,7 +113,7 @@ static int ixfr_load_chsets(chgset_ctx_list_t *chgsets, zone_t *zone,
static int ixfr_query_check(knotd_qdata_t *qdata)
{
NS_NEED_ZONE(qdata, KNOT_RCODE_NOTAUTH);
NS_NEED_AUTH(qdata, qdata->extra->zone->name, ACL_ACTION_TRANSFER);
NS_NEED_AUTH(qdata, ACL_ACTION_TRANSFER);
NS_NEED_ZONE_CONTENTS(qdata, KNOT_RCODE_SERVFAIL);
/* Need SOA authority record. */
......
......@@ -32,7 +32,7 @@
static int notify_check_query(knotd_qdata_t *qdata)
{
NS_NEED_ZONE(qdata, KNOT_RCODE_NOTAUTH);
NS_NEED_AUTH(qdata, qdata->extra->zone->name, ACL_ACTION_NOTIFY);
NS_NEED_AUTH(qdata, ACL_ACTION_NOTIFY);
/* RFC1996 requires SOA question. */
NS_NEED_QTYPE(qdata, KNOT_RRTYPE_SOA, KNOT_RCODE_FORMERR);
......
......@@ -606,9 +606,10 @@ finish:
return next_state;
}
bool process_query_acl_check(conf_t *conf, const knot_dname_t *zone_name,
acl_action_t action, knotd_qdata_t *qdata)
bool process_query_acl_check(conf_t *conf, acl_action_t action,
knotd_qdata_t *qdata)
{
const knot_dname_t *zone_name = qdata->extra->zone->name;
knot_pkt_t *query = qdata->query;
const struct sockaddr_storage *query_source = qdata->params->remote;
knot_tsig_key_t tsig = { 0 };
......@@ -626,7 +627,7 @@ bool process_query_acl_check(conf_t *conf, const knot_dname_t *zone_name,
/* Check if authenticated. */
conf_val_t acl = conf_zone_get(conf, C_ACL, zone_name);
if (!acl_allowed(conf, &acl, action, query_source, &tsig)) {
if (!acl_allowed(conf, &acl, action, query_source, &tsig, zone_name, query)) {
char addr_str[SOCKADDR_STRLEN] = { 0 };
sockaddr_tostr(addr_str, sizeof(addr_str), (struct sockaddr *)query_source);
const knot_lookup_t *act = knot_lookup_by_id((knot_lookup_t *)acl_actions,
......
......@@ -61,13 +61,12 @@ struct rrsig_info {
* \brief Check current query against ACL.
*
* \param conf Configuration.
* \param zone_name Current zone name.
* \param action ACL action.
* \param qdata Query data.
* \return true if accepted, false if denied.
*/
bool process_query_acl_check(conf_t *conf, const knot_dname_t *zone_name,
acl_action_t action, knotd_qdata_t *qdata);
bool process_query_acl_check(conf_t *conf, acl_action_t action,
knotd_qdata_t *qdata);
/*!
* \brief Verify current query transaction security and update query data.
......
......@@ -460,8 +460,7 @@ int update_process_query(knot_pkt_t *pkt, knotd_qdata_t *qdata)
NS_NEED_ZONE(qdata, KNOT_RCODE_NOTAUTH);
/* Need valid transaction security. */
zone_t *zone = (zone_t *)qdata->extra->zone;
NS_NEED_AUTH(qdata, zone->name, ACL_ACTION_UPDATE);
NS_NEED_AUTH(qdata, ACL_ACTION_UPDATE);
/* Check expiration. */
NS_NEED_ZONE_CONTENTS(qdata, KNOT_RCODE_SERVFAIL);
/* Check frozen zone. */
......@@ -470,7 +469,7 @@ int update_process_query(knot_pkt_t *pkt, knotd_qdata_t *qdata)
/* Restore original QNAME for DDNS ACL checks. */
process_query_qname_case_restore(qdata->query, qdata);
/* Store update into DDNS queue. */
int ret = update_enqueue(zone, qdata);
int ret = update_enqueue((zone_t *)qdata->extra->zone, qdata);
if (ret != KNOT_EOK) {
return KNOT_STATE_FAIL;
}
......
......@@ -16,11 +16,136 @@
#include "knot/updates/acl.h"
static bool match_type(uint16_t type, conf_val_t *types)
{
if (types == NULL) {
return true;
}
conf_val_reset(types);
while (types->code == KNOT_EOK) {
if (type == knot_wire_read_u64(types->data)) {
return true;
}
conf_val_next(types);
}
return false;
}
static bool match_name(const knot_dname_t *rr_owner, const knot_dname_t *name,
acl_update_owner_match_t match)
{
if (name == NULL) {
return true;
}
int ret = knot_dname_in_bailiwick(rr_owner, name);
switch (match) {
case ACL_UPDATE_MATCH_SUBEQ:
return (ret >= 0);
case ACL_UPDATE_MATCH_EQ:
return (ret == 0);
case ACL_UPDATE_MATCH_SUB:
return (ret > 0);
default:
return false;
}
}
static bool match_names(const knot_dname_t *rr_owner, conf_val_t *names,
acl_update_owner_match_t match)
{
if (names == NULL) {
return true;
}
conf_val_reset(names);
while (names->code == KNOT_EOK) {
if (match_name(rr_owner, conf_dname(names), match)) {
return true;
}
conf_val_next(names);
}
return false;
}
static bool update_match(conf_t *conf, conf_val_t *acl, knot_dname_t *key_name,
const knot_dname_t *zone_name, knot_pkt_t *query)
{
if (query == NULL) {
return true;
}
conf_val_t val_types = conf_id_get(conf, C_ACL, C_UPDATE_TYPE, acl);
conf_val_t *types = (conf_val_count(&val_types) > 0) ? &val_types : NULL;
conf_val_t val = conf_id_get(conf, C_ACL, C_UPDATE_OWNER, acl);
acl_update_owner_t owner = conf_opt(&val);
/* Return if no specific requirements configured. */
if (types == NULL && owner == ACL_UPDATE_OWNER_NONE) {
return true;
}
acl_update_owner_match_t match;
if (owner != ACL_UPDATE_OWNER_NONE) {
val = conf_id_get(conf, C_ACL, C_UPDATE_OWNER_MATCH, acl);
match = conf_opt(&val);
}
conf_val_t *names = NULL;
conf_val_t val_names;
if (owner == ACL_UPDATE_OWNER_NAME) {
val_names = conf_id_get(conf, C_ACL, C_UPDATE_OWNER_NAME, acl);
if (conf_val_count(&val_names) > 0) {
names = &val_names;
}
}
/* Updated RRs are contained in the Authority section of the query
* (RFC 2136 Section 2.2)
*/
uint16_t pos = query->sections[KNOT_AUTHORITY].pos;
uint16_t count = query->sections[KNOT_AUTHORITY].count;
for (int i = pos; i < pos + count; i++) {
knot_rrset_t *rr = &query->rr[i];
if (!match_type(rr->type, types)) {
return false;
}
switch (owner) {
case ACL_UPDATE_OWNER_NAME:
if (!match_names(rr->owner, names, match)) {
return false;
}
break;
case ACL_UPDATE_OWNER_KEY:
if (!match_name(rr->owner, key_name, match)) {
return false;
}
break;
case ACL_UPDATE_OWNER_ZONE:
if (!match_name(rr->owner, zone_name, match)) {
return false;
}
break;
default:
break;
}
}
return true;
}
bool acl_allowed(conf_t *conf, conf_val_t *acl, acl_action_t action,
const struct sockaddr_storage *addr, knot_tsig_key_t *tsig)
const struct sockaddr_storage *addr, knot_tsig_key_t *tsig,
const knot_dname_t *zone_name, knot_pkt_t *query)
{
if (acl == NULL || addr == NULL || tsig == NULL) {
return NULL;
return false;
}
while (acl->code == KNOT_EOK) {
......@@ -83,6 +208,12 @@ bool acl_allowed(conf_t *conf, conf_val_t *acl, acl_action_t action,
}
}
/* If the action is update, check for update rule match. */
if (action == ACL_ACTION_UPDATE &&
!update_match(conf, acl, tsig->name, zone_name, query)) {
goto next_acl;
}
/* Check if denied. */
val = conf_id_get(conf, C_ACL, C_DENY, acl);
if (conf_bool(&val)) {
......
/* Copyright (C) 2016 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
/* Copyright (C) 2018 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
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
......@@ -13,14 +13,6 @@
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
/*!
* \file
*
* Access control list.
*
* \addtogroup server
* @{
*/
#pragma once
......@@ -38,20 +30,36 @@ typedef enum {
ACL_ACTION_UPDATE = 3
} acl_action_t;
/*! \brief ACL update owner matching options. */
typedef enum {
ACL_UPDATE_OWNER_NONE = 0,
ACL_UPDATE_OWNER_KEY = 1,
ACL_UPDATE_OWNER_ZONE = 2,
ACL_UPDATE_OWNER_NAME = 3,
} acl_update_owner_t;
/*! \bref ACL update owner comparison options. */
typedef enum {
ACL_UPDATE_MATCH_SUBEQ = 0,
ACL_UPDATE_MATCH_EQ = 1,
ACL_UPDATE_MATCH_SUB = 2,
} acl_update_owner_match_t;
/*!
* \brief Checks if the address and/or tsig key matches given ACL list.
*
* If a proper ACL rule is found and tsig.name is not empty, tsig.secret is filled.
*
* \param conf Configuration.
* \param acl Pointer to ACL config multivalued identifier.
* \param action ACL action.
* \param addr IP address.
* \param tsig TSIG parameters.
* \param conf Configuration.
* \param acl Pointer to ACL config multivalued identifier.
* \param action ACL action.
* \param addr IP address.
* \param tsig TSIG parameters.
* \param zone_name Zone name.
* \param query Update query.
*
* \retval True if authenticated.
*/
bool acl_allowed(conf_t *conf, conf_val_t *acl, acl_action_t action,
const struct sockaddr_storage *addr, knot_tsig_key_t *tsig);
/*! @} */
const struct sockaddr_storage *addr, knot_tsig_key_t *tsig,
const knot_dname_t *zone_name, knot_pkt_t *query);
/* Copyright (C) 2017 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
/* Copyright (C) 2018 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
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
......@@ -13,14 +13,6 @@
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
/*!
* \file
*
* \brief Dynamic updates processing.
*
* \addtogroup ddns
* @{
*/
#pragma once
......@@ -53,5 +45,3 @@ int ddns_process_prereqs(const knot_pkt_t *query, zone_update_t *update,
*/
int ddns_process_update(const zone_t *zone, const knot_pkt_t *query,
zone_update_t *update, uint16_t *rcode);
/*! @} */
......@@ -13,14 +13,6 @@
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
/*!
* \file
*
* Zone contents structure and API for manipulating it.
*
* \addtogroup zone
* @{
*/