diff --git a/CHANGES b/CHANGES index 6b2ac4c97e..3d4ea160dc 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,8 @@ +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] + 4761. [protocol] Add support for DOA. [RT #45612] 4759. [func] Add logging channel "trust-anchor-telementry" to diff --git a/bin/named/include/named/globals.h b/bin/named/include/named/globals.h index bfe00eb908..68738f5a1c 100644 --- a/bin/named/include/named/globals.h +++ b/bin/named/include/named/globals.h @@ -171,6 +171,7 @@ EXTERN isc_boolean_t ns_g_notcp INIT(ISC_FALSE); EXTERN isc_boolean_t ns_g_disable6 INIT(ISC_FALSE); EXTERN isc_boolean_t ns_g_disable4 INIT(ISC_FALSE); EXTERN unsigned int ns_g_tat_interval INIT(24*3600); +EXTERN isc_boolean_t ns_g_fixedlocal INIT(ISC_FALSE); #ifdef HAVE_GEOIP diff --git a/bin/named/interfacemgr.c b/bin/named/interfacemgr.c index 9a69c04b8f..00a228a7ce 100644 --- a/bin/named/interfacemgr.c +++ b/bin/named/interfacemgr.c @@ -15,8 +15,6 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: interfacemgr.c,v 1.101 2011/11/09 18:44:03 each Exp $ */ - /*! \file */ #include @@ -949,11 +947,22 @@ do_scan(ns_interfacemgr_t *mgr, ns_listenlist_t *ext_listen, } if (adjusting == ISC_FALSE) { + /* + * If running with -T fixedlocal, then we only + * want 127.0.0.1 and ::1 in the localhost ACL. + */ + if (ns_g_fixedlocal && + !isc_netaddr_isloopback(&interface.address)) + { + goto listenon; + } + result = setup_locals(mgr, &interface); if (result != ISC_R_SUCCESS) goto ignore_interface; } + listenon: ll = (family == AF_INET) ? mgr->listenon4 : mgr->listenon6; dolistenon = ISC_TRUE; for (le = ISC_LIST_HEAD(ll->elts); diff --git a/bin/named/main.c b/bin/named/main.c index 7240906ce4..8a0eb2855e 100644 --- a/bin/named/main.c +++ b/bin/named/main.c @@ -611,17 +611,25 @@ parse_command_line(int argc, char *argv[]) { dns_zone_mkey_month = atoi(p); if (dns_zone_mkey_month < dns_zone_mkey_day) ns_main_earlyfatal("bad mkeytimer"); - } else if (!strcmp(isc_commandline_argument, "notcp")) + } else if (!strcmp(isc_commandline_argument, "notcp")) { ns_g_notcp = ISC_TRUE; - else if (!strncmp(isc_commandline_argument, "tat=", 4)) + } else if (!strncmp(isc_commandline_argument, + "tat=", 4)) + { ns_g_tat_interval = atoi(isc_commandline_argument + 4); - else if (!strcmp(isc_commandline_argument, - "keepstderr")) + } else if (!strcmp(isc_commandline_argument, + "keepstderr")) + { ns_g_keepstderr = ISC_TRUE; - else + } else if (!strcmp(isc_commandline_argument, + "fixedlocal")) + { + ns_g_fixedlocal = ISC_TRUE; + } else { fprintf(stderr, "unknown -T flag '%s\n", isc_commandline_argument); + } break; case 'U': ns_g_udpdisp = parse_int(isc_commandline_argument, diff --git a/bin/named/update.c b/bin/named/update.c index 694c5b8378..950f173dba 100644 --- a/bin/named/update.c +++ b/bin/named/update.c @@ -813,8 +813,11 @@ typedef struct { /* The signature's name if the request was signed. */ dns_name_t *signer; - /* The address of the client if the request was received via TCP. */ - isc_netaddr_t *tcpaddr; + /* The address of the client. */ + isc_netaddr_t *addr; + + /* Whether the request was sent via TCP. */ + isc_boolean_t tcp; /* The ssu table to check against. */ dns_ssutable_t *table; @@ -835,16 +838,17 @@ ssu_checkrule(void *data, dns_rdataset_t *rrset) { if (rrset->type == dns_rdatatype_rrsig || rrset->type == dns_rdatatype_nsec) return (ISC_R_SUCCESS); - result = dns_ssutable_checkrules(ssuinfo->table, ssuinfo->signer, - ssuinfo->name, ssuinfo->tcpaddr, - rrset->type, ssuinfo->key); + result = dns_ssutable_checkrules2(ssuinfo->table, ssuinfo->signer, + ssuinfo->name, ssuinfo->addr, + ssuinfo->tcp, &ns_g_server->aclenv, + rrset->type, ssuinfo->key); return (result == ISC_TRUE ? ISC_R_SUCCESS : ISC_R_FAILURE); } static isc_boolean_t ssu_checkall(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name, dns_ssutable_t *ssutable, dns_name_t *signer, - isc_netaddr_t *tcpaddr, dst_key_t *key) + isc_netaddr_t *addr, isc_boolean_t tcp, dst_key_t *key) { isc_result_t result; ssu_check_t ssuinfo; @@ -852,7 +856,8 @@ ssu_checkall(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name, ssuinfo.name = name; ssuinfo.table = ssutable; ssuinfo.signer = signer; - ssuinfo.tcpaddr = tcpaddr; + ssuinfo.addr = addr; + ssuinfo.tcp = tcp; ssuinfo.key = key; result = foreach_rrset(db, ver, name, ssu_checkrule, &ssuinfo); return (ISC_TF(result == ISC_R_SUCCESS)); @@ -2686,38 +2691,33 @@ update_action(isc_task_t *task, isc_event_t *event) { } if (ssutable != NULL) { - isc_netaddr_t *tcpaddr, netaddr; + isc_netaddr_t netaddr; dst_key_t *tsigkey = NULL; - /* - * If this is a TCP connection then pass the - * address of the client through for tcp-self - * and 6to4-self otherwise pass NULL. This - * provides weak address based authentication. - */ - if (TCPCLIENT(client)) { - isc_netaddr_fromsockaddr(&netaddr, - &client->peeraddr); - tcpaddr = &netaddr; - } else - tcpaddr = NULL; + isc_netaddr_fromsockaddr(&netaddr, &client->peeraddr); if (client->message->tsigkey != NULL) tsigkey = client->message->tsigkey->key; if (rdata.type != dns_rdatatype_any) { - if (!dns_ssutable_checkrules(ssutable, - client->signer, - name, tcpaddr, - rdata.type, - tsigkey)) + if (!dns_ssutable_checkrules2 + (ssutable, client->signer, name, &netaddr, + ISC_TF(TCPCLIENT(client)), + &ns_g_server->aclenv, + rdata.type, tsigkey)) + { FAILC(DNS_R_REFUSED, "rejected by secure update"); + } } else { if (!ssu_checkall(db, ver, name, ssutable, - client->signer, tcpaddr, + client->signer, + &netaddr, + ISC_TF(TCPCLIENT(client)), tsigkey)) + { FAILC(DNS_R_REFUSED, "rejected by secure update"); + } } } } diff --git a/bin/named/zoneconf.c b/bin/named/zoneconf.c index b6c2393258..f188beb100 100644 --- a/bin/named/zoneconf.c +++ b/bin/named/zoneconf.c @@ -378,7 +378,7 @@ configure_zone_ssutable(const cfg_obj_t *zconfig, dns_zone_t *zone, result = dns_ssutable_addrule(table, ISC_TRUE, ns_g_server->session_keyname, - DNS_SSUMATCHTYPE_SUBDOMAIN, + DNS_SSUMATCHTYPE_LOCAL, dns_zone_getorigin(zone), 1, &any); diff --git a/bin/tests/system/nsupdate/clean.sh b/bin/tests/system/nsupdate/clean.sh index f933292c40..bb6390f136 100644 --- a/bin/tests/system/nsupdate/clean.sh +++ b/bin/tests/system/nsupdate/clean.sh @@ -20,13 +20,12 @@ # rm -f */named.memstats -rm -f */named.run +rm -f */named.run */ans.run rm -f Kxxx.* rm -f dig.out.* rm -f jp.out.ns3.* rm -f ns*/named.lock -rm -f ns1/*.jnl ns2/*.jnl ns3/*.jnl -rm -f ns1/example.db ns1/unixtime.db ns1/update.db ns1/other.db ns1/keytests.db +rm -f */*.jnl rm -f ns1/example.db ns1/unixtime.db ns1/yyyymmddvv.db ns1/update.db ns1/other.db ns1/keytests.db rm -f ns1/many.test.db rm -f ns1/md5.key ns1/sha1.key ns1/sha224.key ns1/sha256.key ns1/sha384.key @@ -42,6 +41,7 @@ rm -f ns3/example.db rm -f ns3/many.test.bk rm -f ns3/nsec3param.test.db rm -f ns3/too-big.test.db +rm -f ns5/local.db rm -f nsupdate.out* rm -f typelist.out.* rm -f ns1/sample.db diff --git a/bin/tests/system/nsupdate/ns5/local.db.in b/bin/tests/system/nsupdate/ns5/local.db.in new file mode 100644 index 0000000000..707d1be598 --- /dev/null +++ b/bin/tests/system/nsupdate/ns5/local.db.in @@ -0,0 +1,20 @@ +; Copyright (C) 2017 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/. + +$ORIGIN . +$TTL 300 ; 5 minutes +local.nil IN SOA ns5.local.nil. hostmaster.local.nil. ( + 1 ; serial + 2000 ; refresh (2000 seconds) + 2000 ; retry (2000 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) +local.nil. NS ns5.local.nil. +ns5.local.nil. A 10.53.0.5 + +$ORIGIN local.nil. +a A 10.10.10.10 diff --git a/bin/tests/system/nsupdate/ns5/named.args b/bin/tests/system/nsupdate/ns5/named.args new file mode 100644 index 0000000000..4bc1583651 --- /dev/null +++ b/bin/tests/system/nsupdate/ns5/named.args @@ -0,0 +1 @@ +-m record,size,mctx -T clienttest -c named.conf -d 99 -g -U 4 -T fixedlocal diff --git a/bin/tests/system/nsupdate/ns5/named.conf b/bin/tests/system/nsupdate/ns5/named.conf new file mode 100644 index 0000000000..3632c7cb99 --- /dev/null +++ b/bin/tests/system/nsupdate/ns5/named.conf @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2017 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/. + */ + +controls { /* empty */ }; + +options { + query-source address 10.53.0.5; + notify-source 10.53.0.5; + transfer-source 10.53.0.5; + port 5300; + pid-file "named.pid"; + session-keyfile "session.key"; + listen-on { 10.53.0.5; }; + recursion no; + notify yes; + minimal-responses no; +}; + +key rndc_key { + secret "1234abcd8765"; + algorithm hmac-sha256; +}; + +controls { + inet 10.53.0.5 port 9953 allow { any; } keys { rndc_key; }; +}; + +zone "local.nil" { + type master; + file "local.db"; + update-policy local; +}; diff --git a/bin/tests/system/nsupdate/setup.sh b/bin/tests/system/nsupdate/setup.sh index 3af90835b9..3a4ca49fbe 100644 --- a/bin/tests/system/nsupdate/setup.sh +++ b/bin/tests/system/nsupdate/setup.sh @@ -66,3 +66,5 @@ $DDNSCONFGEN -q -r $RANDFILE -a hmac-sha512 -k sha512-key -z keytests.nil > ns1/ cp ns1/sample.db.in ns1/sample.db cp ns2/sample.db.in ns2/sample.db + +cp -f ns5/local.db.in ns5/local.db diff --git a/bin/tests/system/nsupdate/tests.sh b/bin/tests/system/nsupdate/tests.sh index 4c37d5712e..ad6536a5c7 100755 --- a/bin/tests/system/nsupdate/tests.sh +++ b/bin/tests/system/nsupdate/tests.sh @@ -475,6 +475,44 @@ then echo "I:failed"; status=1 fi +n=`expr $n + 1` +ret=0 +echo "I:check that 'update-policy local' works from localhost address ($n)" +$NSUPDATE -p 5300 -k ns5/session.key > nsupdate.out.$n 2>&1 << END || ret=1 +server 10.53.0.5 5300 +local 127.0.0.1 5300 +update add fromlocal.local.nil. 600 A 1.2.3.4 +send +END +grep REFUSED nsupdate.out.$n > /dev/null 2>&1 && ret=1 +$DIG @10.53.0.5 -p 5300 \ + +tcp +noadd +nosea +nostat +noquest +nocomm +nocmd \ + fromlocal.local.nil. > dig.out.ns5.$n || ret=1 +grep fromlocal dig.out.ns5.$n > /dev/null 2>&1 || ret=1 +if test $ret -ne 0 +then +echo "I:failed"; status=1 +fi + +n=`expr $n + 1` +ret=0 +echo "I:check that 'update-policy local' fails from non-localhost address ($n)" +$NSUPDATE -p 5300 -k ns5/session.key > nsupdate.out.$n 2>&1 << END && ret=1 +server 10.53.0.5 5300 +local 10.53.0.1 5300 +update add nonlocal.local.nil. 600 A 4.3.2.1 +send +END +grep REFUSED nsupdate.out.$n > /dev/null 2>&1 || ret=1 +$DIG @10.53.0.5 -p 5300 \ + +tcp +noadd +nosea +nostat +noquest +nocomm +nocmd \ + nonlocal.local.nil. > dig.out.ns5.$n || ret=1 +grep nonlocal dig.out.ns5.$n > /dev/null 2>&1 && ret=1 +if test $ret -ne 0 +then +echo "I:failed"; status=1 +fi + n=`expr $n + 1` ret=0 echo "I:check that changes to the DNSKEY RRset TTL do not have side effects ($n)" diff --git a/doc/arm/Bv9ARM-book.xml b/doc/arm/Bv9ARM-book.xml index 1a2c1f7bb4..76dd85b2b5 100644 --- a/doc/arm/Bv9ARM-book.xml +++ b/doc/arm/Bv9ARM-book.xml @@ -12184,38 +12184,52 @@ example.com. NS ns2.example.net. is present, it is a configuration error for the allow-update statement to be present. The update-policy statement - only examines the signer of a message; the source + (except when set to local) only + examines the signer of a message; the source address is not relevant. - There is a pre-defined update-policy - rule which can be switched on with the command + A pre-defined update-policy rule can be + switched on with the command update-policy local;. Switching on this rule in a zone causes - named to generate a TSIG session - key and place it in a file, and to allow that key - to update the zone. (By default, the file is - /var/run/named/session.key, the key - name is "local-ddns" and the key algorithm is HMAC-SHA256, - but these values are configurable with the + named to generate a TSIG session key and + place it in a file. That key will then be allowed to update + the zone, if the update request is sent from localhost. + By default, the session key is stored in the file + /var/run/named/session.key; the key name + is "local-ddns" and the key algorithm is HMAC-SHA256. + These values are configurable with the session-keyfile, session-keyname and session-keyalg options, respectively). - A client running on the local system, and with appropriate - permissions, may read that file and use the key to sign update - requests. The zone's update policy will be set to allow that - key to change any record within the zone. Assuming the - key name is "local-ddns", this policy is equivalent to: + A client on the local system, if it is run with appropriate + permissions, may read the session key from the key file and + use the key to sign update requests. The zone's update + policy will be set to allow that key to change any record + within the zone. Assuming the key name is "local-ddns", + this policy is: update-policy { grant local-ddns zonesub any; }; - The command nsupdate -l sends update - requests to localhost, and signs them using the session key. + ...with an additional restriction that only clients + connecting from the local system will be permitted to send + updates. + + + Note that only one session key is generated; all zones + configured to use update-policy local + will accept the same key. + + + The command nsupdate -l implements this + feature, sending requests to localhost and signing them using + the key retrieved from the session key file. diff --git a/doc/arm/notes.xml b/doc/arm/notes.xml index cc2560f2ef..8cef881124 100644 --- a/doc/arm/notes.xml +++ b/doc/arm/notes.xml @@ -134,6 +134,15 @@ bind.keys. [RT #46155] + + + Previously, update-policy local; accepted + updates from any source so long as they were signed by the + locally-generated session key. This has been further restricted; + updates are now only accepted from locally configured addresses. + [RT #45492] + + dig +ednsopt now accepts the names diff --git a/lib/dns/include/dns/ssu.h b/lib/dns/include/dns/ssu.h index fbe01c3d66..7d1fc647fd 100644 --- a/lib/dns/include/dns/ssu.h +++ b/lib/dns/include/dns/ssu.h @@ -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 +#include #include #include @@ -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. */ diff --git a/lib/dns/ssu.c b/lib/dns/ssu.c index 7adb769cf3..3834cd5e4d 100644 --- a/lib/dns/ssu.c +++ b/lib/dns/ssu.c @@ -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; } diff --git a/lib/isc/include/isc/netaddr.h b/lib/isc/include/isc/netaddr.h index 28d741e6bc..bf31ccceae 100644 --- a/lib/isc/include/isc/netaddr.h +++ b/lib/isc/include/isc/netaddr.h @@ -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 */ diff --git a/lib/isc/netaddr.c b/lib/isc/netaddr.c index 64a285095d..f1ecec1516 100644 --- a/lib/isc/netaddr.c +++ b/lib/isc/netaddr.c @@ -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); + } +}