-/* Copyright (C) 2020 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
+/* Copyright (C) 2021 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
static bool check_addr_key(conf_t *conf, conf_val_t *addr_val, conf_val_t *key_val,
bool remote, const struct sockaddr_storage *addr,
- const knot_tsig_key_t *tsig)
+ const knot_tsig_key_t *tsig, bool deny)
{
/* Check if the address matches the acl address list or remote addresses. */
if (addr_val->code != KNOT_ENOENT) {
conf_val_next(key_val);
}
}
- /* Check for key match or empty list without key provided. */
- if (key_val->code != KNOT_EOK &&
- !(key_val->code == KNOT_ENOENT && tsig->name == NULL)) {
+ switch (key_val->code) {
+ case KNOT_EOK:
+ // Key match.
+ break;
+ case KNOT_ENOENT:
+ // Empty list without key provided or denied.
+ if (tsig->name == NULL || deny) {
+ break;
+ }
+ // FALLTHROUGH
+ default:
return false;
}
while (acl->code == KNOT_EOK) {
conf_val_t rmt_val = conf_id_get(conf, C_ACL, C_RMT, acl);
bool remote = (rmt_val.code == KNOT_EOK);
+ conf_val_t deny_val = conf_id_get(conf, C_ACL, C_DENY, acl);
+ bool deny = conf_bool(&deny_val);
/* Check if a remote matches given address and key. */
conf_val_t addr_val, key_val;
while (rmt_val.code == KNOT_EOK) {
addr_val = conf_id_get(conf, C_RMT, C_ADDR, &rmt_val);
key_val = conf_id_get(conf, C_RMT, C_KEY, &rmt_val);
- if (check_addr_key(conf, &addr_val, &key_val, remote, addr, tsig)) {
+ if (check_addr_key(conf, &addr_val, &key_val, remote, addr, tsig, deny)) {
break;
}
conf_val_next(&rmt_val);
if (!remote) {
addr_val = conf_id_get(conf, C_ACL, C_ADDR, acl);
key_val = conf_id_get(conf, C_ACL, C_KEY, acl);
- if (!check_addr_key(conf, &addr_val, &key_val, remote, addr, tsig)) {
+ if (!check_addr_key(conf, &addr_val, &key_val, remote, addr, tsig, deny)) {
goto next_acl;
}
}
}
/* Check if denied. */
- conf_val_t val = conf_id_get(conf, C_ACL, C_DENY, acl);
- if (conf_bool(&val)) {
+ if (deny) {
return false;
}
/* Fill the output with tsig secret if provided. */
if (tsig->name != NULL) {
- val = conf_id_get(conf, C_KEY, C_SECRET, &key_val);
+ conf_val_t val = conf_id_get(conf, C_KEY, C_SECRET, &key_val);
tsig->secret.data = (uint8_t *)conf_bin(&val, &tsig->secret.size);
}
-/* Copyright (C) 2020 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
+/* Copyright (C) 2021 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
#include "contrib/sockaddr.h"
#define ZONE "example.zone"
+#define ZONE2 "example2.zone"
#define KEY1 "key1_md5"
#define KEY2 "key2_md5"
#define KEY3 "key3_sha256"
knot_dname_t *zone_name = knot_dname_from_str_alloc(ZONE);
ok(zone_name != NULL, "create zone dname");
+ knot_dname_t *zone2_name = knot_dname_from_str_alloc(ZONE2);
+ ok(zone2_name != NULL, "create zone2 dname");
knot_dname_t *key1_name = knot_dname_from_str_alloc(KEY1);
ok(key1_name != NULL, "create "KEY1);
knot_dname_t *key2_name = knot_dname_from_str_alloc(KEY2);
" - id: acl_range_addr\n"
" address: [ 100.0.0.0-100.0.0.5, ::0-::5 ]\n"
" action: [ transfer ]\n"
+ " - id: acl_deny_no_action_no_key\n"
+ " address: [ 240.0.0.4 ]\n"
+ " deny: on\n"
+ " - id: acl_notify_key\n"
+ " address: [ 240.0.0.0/24 ]\n"
+ " key: "KEY1"\n"
+ " action: [ notify ]\n"
" - id: acl_update_key\n"
" key: "KEY1"\n"
" update-owner: key\n"
" acl: [ acl_key_addr, acl_deny, acl_no_action_deny ]\n"
" acl: [ acl_multi_addr, acl_multi_key ]\n"
" acl: [ acl_range_addr ]\n"
+ " - domain: "ZONE2"\n"
+ " acl: [ acl_deny_no_action_no_key, acl_notify_key ]\n"
" - domain: "KEY1"\n"
" acl: acl_update_key\n"
" - domain: "KEY2"\n"
ret = acl_allowed(conf(), &acl, ACL_ACTION_TRANSFER, &addr, &key0, zone_name, NULL);
ok(ret == true, "IPv6 address from range, no key, action match");
+ acl = conf_zone_get(conf(), C_ACL, zone2_name);
+ ok(acl.code == KNOT_EOK, "Get zone2 ACL");
+ check_sockaddr_set(&addr, AF_INET, "240.0.0.4", 0);
+ ret = acl_allowed(conf(), &acl, ACL_ACTION_NOTIFY, &addr, &key1, zone2_name, NULL);
+ ok(ret == false, "Address, key, action, denied");
+
+ acl = conf_zone_get(conf(), C_ACL, zone2_name);
+ ok(acl.code == KNOT_EOK, "Get zone2 ACL");
+ check_sockaddr_set(&addr, AF_INET, "240.0.0.1", 0);
+ ret = acl_allowed(conf(), &acl, ACL_ACTION_NOTIFY, &addr, &key1, zone2_name, NULL);
+ ok(ret == true, "Address, key, action, match");
+
knot_rrset_t A;
knot_rrset_init(&A, key1_name, KNOT_RRTYPE_A, KNOT_CLASS_IN, 3600);
knot_rrset_add_rdata(&A, (uint8_t *)"\x00\x00\x00\x00", 4, NULL);
conf_free(conf());
knot_dname_free(zone_name, NULL);
+ knot_dname_free(zone2_name, NULL);
knot_dname_free(key1_name, NULL);
knot_dname_free(key2_name, NULL);
knot_dname_free(key3_name, NULL);