[v9_10] further restrict update-policy local

4762.	[func]		"update-policy local" is now restricted to updates
                from local addresses. (Previously, other addresses
                were allowed so long as updates were signed by the
                local session key.) [RT #45492]
This commit is contained in:
Evan Hunt
2017-10-06 15:36:18 -07:00
parent 3402ce550a
commit dddf97d534
18 changed files with 280 additions and 73 deletions

View File

@@ -15,8 +15,6 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: ssu.h,v 1.28 2011/01/06 23:47:00 tbox Exp $ */
#ifndef DNS_SSU_H
#define DNS_SSU_H 1
@@ -24,6 +22,7 @@
#include <isc/lang.h>
#include <dns/acl.h>
#include <dns/types.h>
#include <dst/dst.h>
@@ -42,8 +41,10 @@ ISC_LANG_BEGINDECLS
#define DNS_SSUMATCHTYPE_TCPSELF 10
#define DNS_SSUMATCHTYPE_6TO4SELF 11
#define DNS_SSUMATCHTYPE_EXTERNAL 12
#define DNS_SSUMATCHTYPE_DLZ 13
#define DNS_SSUMATCHTYPE_MAX 12 /* max value */
#define DNS_SSUMATCHTYPE_LOCAL 13
#define DNS_SSUMATCHTYPE_MAX 13 /* max value */
#define DNS_SSUMATCHTYPE_DLZ 14 /* intentionally higher than _MAX */
isc_result_t
dns_ssutable_create(isc_mem_t *mctx, dns_ssutable_t **table);
@@ -132,7 +133,12 @@ dns_ssutable_addrule(dns_ssutable_t *table, isc_boolean_t grant,
isc_boolean_t
dns_ssutable_checkrules(dns_ssutable_t *table, dns_name_t *signer,
dns_name_t *name, isc_netaddr_t *tcpaddr,
dns_name_t *name, isc_netaddr_t *addr,
dns_rdatatype_t type, const dst_key_t *key);
isc_boolean_t
dns_ssutable_checkrules2(dns_ssutable_t *table, dns_name_t *signer,
dns_name_t *name, isc_netaddr_t *addr,
isc_boolean_t tcp, const dns_aclenv_t *env,
dns_rdatatype_t type, const dst_key_t *key);
/*%<
* Checks that the attempted update of (name, type) is allowed according
@@ -140,11 +146,19 @@ dns_ssutable_checkrules(dns_ssutable_t *table, dns_name_t *signer,
* no rules are matched, access is denied.
*
* Notes:
* 'tcpaddr' should only be set if the request received
* via TCP. This provides a weak assurance that the
* request was not spoofed. 'tcpaddr' is to to validate
* DNS_SSUMATCHTYPE_TCPSELF and DNS_SSUMATCHTYPE_6TO4SELF
* rules.
* In dns_ssutable_checkrules(), 'addr' should only be
* set if the request received via TCP. This provides a
* weak assurance that the request was not spoofed.
* 'addr' is to to validate DNS_SSUMATCHTYPE_TCPSELF
* and DNS_SSUMATCHTYPE_6TO4SELF rules.
*
* In dns_ssutable_checkrules2(), 'addr' can also be passed for
* UDP requests and TCP is specified via the 'tcp' parameter.
* In addition to DNS_SSUMATCHTYPE_TCPSELF and
* tcp_ssumatchtype_6to4self rules, the address
* also be used to check DNS_SSUMATCHTYPE_LOCAL rules.
* If 'addr' is set then 'env' must also be set so that
* requests from non-localhost addresses can be rejected.
*
* For DNS_SSUMATCHTYPE_TCPSELF the addresses are mapped to
* the standard reverse names under IN-ADDR.ARPA and IP6.ARPA.
@@ -160,8 +174,10 @@ dns_ssutable_checkrules(dns_ssutable_t *table, dns_name_t *signer,
* Requires:
*\li 'table' is a valid SSU table
*\li 'signer' is NULL or a valid absolute name
*\li 'tcpaddr' is NULL or a valid network address.
*\li 'addr' is NULL or a valid network address.
*\li 'aclenv' is NULL or a valid ACL environment.
*\li 'name' is a valid absolute name
*\li if 'addr' is not NULL, 'env' is not NULL.
*/

View File

@@ -348,9 +348,20 @@ stf_from_address(dns_name_t *stfself, isc_netaddr_t *tcpaddr) {
isc_boolean_t
dns_ssutable_checkrules(dns_ssutable_t *table, dns_name_t *signer,
dns_name_t *name, isc_netaddr_t *tcpaddr,
dns_rdatatype_t type,
const dst_key_t *key)
dns_name_t *name, isc_netaddr_t *addr,
dns_rdatatype_t type, const dst_key_t *key)
{
return (dns_ssutable_checkrules2
(table, signer, name, addr,
addr == NULL ? ISC_FALSE : ISC_TRUE,
NULL, type, key));
}
isc_boolean_t
dns_ssutable_checkrules2(dns_ssutable_t *table, dns_name_t *signer,
dns_name_t *name, isc_netaddr_t *addr,
isc_boolean_t tcp, const dns_aclenv_t *env,
dns_rdatatype_t type, const dst_key_t *key)
{
dns_ssurule_t *rule;
unsigned int i;
@@ -359,12 +370,14 @@ dns_ssutable_checkrules(dns_ssutable_t *table, dns_name_t *signer,
dns_name_t *tcpself;
dns_name_t *stfself;
isc_result_t result;
int match;
REQUIRE(VALID_SSUTABLE(table));
REQUIRE(signer == NULL || dns_name_isabsolute(signer));
REQUIRE(dns_name_isabsolute(name));
REQUIRE(addr == NULL || env != NULL);
if (signer == NULL && tcpaddr == NULL)
if (signer == NULL && addr == NULL)
return (ISC_FALSE);
for (rule = ISC_LIST_HEAD(table->rules);
@@ -373,6 +386,7 @@ dns_ssutable_checkrules(dns_ssutable_t *table, dns_name_t *signer,
{
switch (rule->matchtype) {
case DNS_SSUMATCHTYPE_NAME:
case DNS_SSUMATCHTYPE_LOCAL:
case DNS_SSUMATCHTYPE_SUBDOMAIN:
case DNS_SSUMATCHTYPE_WILDCARD:
case DNS_SSUMATCHTYPE_SELF:
@@ -398,7 +412,7 @@ dns_ssutable_checkrules(dns_ssutable_t *table, dns_name_t *signer,
break;
case DNS_SSUMATCHTYPE_TCPSELF:
case DNS_SSUMATCHTYPE_6TO4SELF:
if (tcpaddr == NULL)
if (!tcp || addr == NULL)
continue;
break;
}
@@ -412,6 +426,20 @@ dns_ssutable_checkrules(dns_ssutable_t *table, dns_name_t *signer,
if (!dns_name_issubdomain(name, rule->name))
continue;
break;
case DNS_SSUMATCHTYPE_LOCAL:
if (addr == NULL) {
continue;
}
if (!dns_name_issubdomain(name, rule->name)) {
continue;
}
dns_acl_match(addr, NULL, env->localhost,
NULL, &match, NULL);
if (match == 0) {
continue;
}
break;
case DNS_SSUMATCHTYPE_WILDCARD:
if (!dns_name_matcheswildcard(name, rule->name))
continue;
@@ -461,7 +489,7 @@ dns_ssutable_checkrules(dns_ssutable_t *table, dns_name_t *signer,
case DNS_SSUMATCHTYPE_TCPSELF:
dns_fixedname_init(&fixed);
tcpself = dns_fixedname_name(&fixed);
reverse_from_address(tcpself, tcpaddr);
reverse_from_address(tcpself, addr);
if (dns_name_iswildcard(rule->identity)) {
if (!dns_name_matcheswildcard(tcpself,
rule->identity))
@@ -476,7 +504,7 @@ dns_ssutable_checkrules(dns_ssutable_t *table, dns_name_t *signer,
case DNS_SSUMATCHTYPE_6TO4SELF:
dns_fixedname_init(&fixed);
stfself = dns_fixedname_name(&fixed);
stf_from_address(stfself, tcpaddr);
stf_from_address(stfself, addr);
if (dns_name_iswildcard(rule->identity)) {
if (!dns_name_matcheswildcard(stfself,
rule->identity))
@@ -490,13 +518,13 @@ dns_ssutable_checkrules(dns_ssutable_t *table, dns_name_t *signer,
break;
case DNS_SSUMATCHTYPE_EXTERNAL:
if (!dns_ssu_external_match(rule->identity, signer,
name, tcpaddr, type, key,
name, addr, type, key,
table->mctx))
continue;
break;
case DNS_SSUMATCHTYPE_DLZ:
if (!dns_dlz_ssumatch(table->dlzdatabase, signer,
name, tcpaddr, type, key))
name, addr, type, key))
continue;
break;
}

View File

@@ -181,6 +181,12 @@ isc_netaddr_prefixok(const isc_netaddr_t *na, unsigned int prefixlen);
* ISC_R_FAILURE extra bits.
*/
isc_boolean_t
isc_netaddr_isloopback(const isc_netaddr_t *na);
/*
* Test whether the netaddr 'na' is a loopback IPv4 or IPv6 address (in
* 127.0.0.0/8 or ::1).
*/
ISC_LANG_ENDDECLS
#endif /* ISC_NETADDR_H */

View File

@@ -448,3 +448,16 @@ isc_netaddr_fromv4mapped(isc_netaddr_t *t, const isc_netaddr_t *s) {
memmove(&t->type.in, (char *)&src->type.in6 + 12, 4);
return;
}
isc_boolean_t
isc_netaddr_isloopback(const isc_netaddr_t *na) {
switch (na->family) {
case AF_INET:
return (ISC_TF((ntohl(na->type.in.s_addr) & 0xff000000U) ==
0x7f000000U));
case AF_INET6:
return (IN6_IS_ADDR_LOOPBACK(&na->type.in6));
default:
return (ISC_FALSE);
}
}