Commit ac21f918 authored by Evan Hunt's avatar Evan Hunt
Browse files

3109. [func] The also-notify option now uses the same syntax

			as a zone's masters clause.  This means it is
			now possible to specify a TSIG key to use when
			sending notifies to a given server, or to include
			an explicit named masters list in an also-notfiy
			statement.  [RT #23508]
parent 8fcfce39
3109. [func] The also-notify option now uses the same syntax
as a zone's masters clause. This means it is
now possible to specify a TSIG key to use when
sending notifies to a given server, or to include
an explicit named masters list in an also-notfiy
statement. [RT #23508]
3108. [cleanup] dnssec-signzone: Clarified some error and
warning messages; removed #ifdef ALLOW_KSKLESS_ZONES
code (use -P instead). [RT #20852]
......
......@@ -17,7 +17,7 @@
- PERFORMANCE OF THIS SOFTWARE.
-->
<!-- $Id: named.conf.docbook,v 1.51 2011/02/23 03:08:08 marka Exp $ -->
<!-- $Id: named.conf.docbook,v 1.52 2011/05/06 21:23:50 each Exp $ -->
<refentry>
<refentryinfo>
<date>Aug 13, 2004</date>
......@@ -326,7 +326,8 @@ options {
notify-delay <replaceable>seconds</replaceable>;
notify-to-soa <replaceable>boolean</replaceable>;
also-notify <optional> port <replaceable>integer</replaceable> </optional> { ( <replaceable>ipv4_address</replaceable> | <replaceable>ipv6_address</replaceable> )
<optional> port <replaceable>integer</replaceable> </optional>; ... };
<optional> port <replaceable>integer</replaceable> </optional>; ...
<optional> key <replaceable>keyname</replaceable> </optional> ... };
allow-notify { <replaceable>address_match_element</replaceable>; ... };
forward ( first | only );
......@@ -513,7 +514,8 @@ view <replaceable>string</replaceable> <replaceable>optional_class</replaceable>
notify-delay <replaceable>seconds</replaceable>;
notify-to-soa <replaceable>boolean</replaceable>;
also-notify <optional> port <replaceable>integer</replaceable> </optional> { ( <replaceable>ipv4_address</replaceable> | <replaceable>ipv6_address</replaceable> )
<optional> port <replaceable>integer</replaceable> </optional>; ... };
<optional> port <replaceable>integer</replaceable> </optional>; ...
<optional> key <replaceable>keyname</replaceable> </optional> ... };
allow-notify { <replaceable>address_match_element</replaceable>; ... };
forward ( first | only );
......@@ -609,7 +611,8 @@ zone <replaceable>string</replaceable> <replaceable>optional_class</replaceable>
notify-delay <replaceable>seconds</replaceable>;
notify-to-soa <replaceable>boolean</replaceable>;
also-notify <optional> port <replaceable>integer</replaceable> </optional> { ( <replaceable>ipv4_address</replaceable> | <replaceable>ipv6_address</replaceable> )
<optional> port <replaceable>integer</replaceable> </optional>; ... };
<optional> port <replaceable>integer</replaceable> </optional>; ...
<optional> key <replaceable>keyname</replaceable> </optional> ... };
allow-notify { <replaceable>address_match_element</replaceable>; ... };
forward ( first | only );
......
......@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: zoneconf.c,v 1.175 2011/04/29 21:37:14 each Exp $ */
/* $Id: zoneconf.c,v 1.176 2011/05/06 21:23:50 each Exp $ */
/*% */
......@@ -999,17 +999,18 @@ ns_zone_configure(const cfg_obj_t *config, const cfg_obj_t *vconfig,
obj = NULL;
result = ns_config_get(maps, "also-notify", &obj);
if (result == ISC_R_SUCCESS) {
isc_sockaddr_t *addrs = NULL;
isc_uint32_t addrcount;
result = ns_config_getiplist(config, obj, 0, mctx,
&addrs, &addrcount);
if (result != ISC_R_SUCCESS)
return (result);
result = dns_zone_setalsonotify(zone, addrs,
addrcount);
ns_config_putiplist(mctx, &addrs, addrcount);
if (result != ISC_R_SUCCESS)
return (result);
addrs = NULL;
keynames = NULL;
RETERR(ns_config_getipandkeylist(config, obj, mctx,
&addrs, &keynames,
&addrcount));
result = dns_zone_setalsonotifywithkeys(zone, addrs,
keynames,
addrcount);
ns_config_putipandkeylist(mctx, &addrs, &keynames,
addrcount);
RETERR(result);
} else
RETERR(dns_zone_setalsonotify(zone, NULL, 0));
......
......@@ -15,7 +15,7 @@
# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
# PERFORMANCE OF THIS SOFTWARE.
# $Id: clean.sh,v 1.22 2011/02/03 12:18:11 tbox Exp $
# $Id: clean.sh,v 1.23 2011/05/06 21:23:50 each Exp $
#
# Clean up after zone transfer tests.
......@@ -26,7 +26,7 @@ rm -f dig.out.ns1 dig.out.ns2 dig.out.ns1.after ns1/*.jnl ns2/*.jnl \
rm -f nsupdate.out
rm -f random.data
rm -f ns2/example.bk
rm -f ns2/update.bk
rm -f ns2/update.bk ns2/update.alt.bk
rm -f */named.memstats
rm -f nsupdate.out
rm -f ns3/example.db.jnl ns3/example.db
......
......@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: named.conf,v 1.19 2009/07/29 23:47:43 tbox Exp $ */
/* $Id: named.conf,v 1.20 2011/05/06 21:23:50 each Exp $ */
controls { /* empty */ };
......@@ -41,6 +41,11 @@ controls {
inet 10.53.0.1 port 9953 allow { any; } keys { rndc_key; };
};
key altkey {
algorithm hmac-md5;
secret "1234abcd8765";
};
include "ddns.key";
zone "example.nil" {
......@@ -62,11 +67,16 @@ zone "other.nil" {
allow-transfer { any; };
};
masters othermasters {
10.53.0.2 port 5300;
10.53.0.2 port 5300 key altkey;
};
zone "update.nil" {
type master;
file "update.db";
check-integrity no;
allow-update { any; };
allow-transfer { any; };
also-notify { 10.53.0.2; };
also-notify { othermasters; };
};
......@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: named.conf,v 1.14 2007/06/18 23:47:30 tbox Exp $ */
/* $Id: named.conf,v 1.15 2011/05/06 21:23:50 each Exp $ */
controls { /* empty */ };
......@@ -32,18 +32,36 @@ options {
notify yes;
};
zone "example.nil" {
type slave;
masters { 10.53.0.1; };
file "example.bk";
allow-transfer { any; };
key altkey {
algorithm hmac-md5;
secret "1234abcd8765";
};
zone "update.nil" {
type slave;
masters { 10.53.0.1; };
file "update.bk";
allow-transfer { any; };
view alternate {
match-clients { key altkey; };
zone "update.nil" {
type slave;
masters { 10.53.0.1; };
file "update.alt.bk";
allow-transfer { any; };
};
};
view primary {
match-clients { any; };
zone "example.nil" {
type slave;
masters { 10.53.0.1; };
file "example.bk";
allow-transfer { any; };
};
zone "update.nil" {
type slave;
masters { 10.53.0.1; };
file "update.bk";
allow-transfer { any; };
};
};
......@@ -15,7 +15,7 @@
# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
# PERFORMANCE OF THIS SOFTWARE.
# $Id: setup.sh,v 1.16 2010/12/07 23:47:02 tbox Exp $
# $Id: setup.sh,v 1.17 2011/05/06 21:23:50 each Exp $
SYSTEMTESTTOP=..
. $SYSTEMTESTTOP/conf.sh
......@@ -25,6 +25,7 @@ SYSTEMTESTTOP=..
#
rm -f ns1/*.jnl ns1/example.db ns2/*.jnl ns2/example.bk
rm -f ns2/update.bk ns2/update.alt.bk
rm -f ns3/example.db.jnl
cp -f ns1/example1.db ns1/example.db
......
......@@ -15,7 +15,7 @@
# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
# PERFORMANCE OF THIS SOFTWARE.
# $Id: tests.sh,v 1.35 2011/03/18 02:08:45 each Exp $
# $Id: tests.sh,v 1.36 2011/05/06 21:23:50 each Exp $
SYSTEMTESTTOP=..
. $SYSTEMTESTTOP/conf.sh
......@@ -352,5 +352,17 @@ then
echo "I:failed"; status=1
fi
n=`expr $n + 1`
ret=0
echo "I:check notify with TSIG worked ($n)"
# if the alternate view received a notify--meaning, the notify was
# validly signed by "altkey"--then the zonefile update.alt.bk will
# will have been created.
[ -f ns2/update.alt.bk ] || ret=1
if [ $ret -ne 0 ]; then
echo "I:failed"
status=1
fi
echo "I:exit status: $status"
exit $status
......@@ -18,7 +18,7 @@
- PERFORMANCE OF THIS SOFTWARE.
-->
 
<!-- File: $Id: Bv9ARM-book.xml,v 1.485 2011/04/29 21:37:14 each Exp $ -->
<!-- File: $Id: Bv9ARM-book.xml,v 1.486 2011/05/06 21:23:50 each Exp $ -->
<book xmlns:xi="http://www.w3.org/2001/XInclude">
<title>BIND 9 Administrator Reference Manual</title>
 
......@@ -5106,8 +5106,9 @@ badresp:1,adberr:0,findfail:0,valfail:0]
<optional> notify-source (<replaceable>ip4_addr</replaceable> | <constant>*</constant>) <optional>port <replaceable>ip_port</replaceable></optional> ; </optional>
<optional> notify-source-v6 (<replaceable>ip6_addr</replaceable> | <constant>*</constant>) <optional>port <replaceable>ip_port</replaceable></optional> ; </optional>
<optional> notify-to-soa <replaceable>yes_or_no</replaceable> ; </optional>
<optional> also-notify { <replaceable>ip_addr</replaceable> <optional>port <replaceable>ip_port</replaceable></optional> ;
<optional> <replaceable>ip_addr</replaceable> <optional>port <replaceable>ip_port</replaceable></optional> ; ... </optional> }; </optional>
<optional> also-notify { <replaceable>ip_addr</replaceable>
<optional>port <replaceable>ip_port</replaceable></optional> <optional>key <replaceable>keyname</replaceable></optional> ;
<optional> <replaceable>ip_addr</replaceable> <optional>port <replaceable>ip_port</replaceable></optional> <optional>key <replaceable>keyname</replaceable></optional> ; ... </optional> }; </optional>
<optional> max-ixfr-log-size <replaceable>number</replaceable>; </optional>
<optional> max-journal-size <replaceable>size_spec</replaceable>; </optional>
<optional> coresize <replaceable>size_spec</replaceable> ; </optional>
......@@ -7554,6 +7555,11 @@ avoid-v6-udp-ports {};
<command>also-notify</command> address to send
the notify messages to a port other than the
default of 53.
An optional TSIG key can also be specified with each
address to cause the notify messages to be signed; this
can be useful when sending notifies to multiple views.
</para>
<para>
If an <command>also-notify</command> list
is given in a <command>zone</command> statement,
it will override
......@@ -10048,8 +10054,9 @@ zone <replaceable>zone_name</replaceable> <optional><replaceable>class</replacea
<optional> dnssec-loadkeys-interval <replaceable>number</replaceable>; </optional>
<optional> dnssec-secure-to-insecure <replaceable>yes_or_no</replaceable> ; </optional>
<optional> try-tcp-refresh <replaceable>yes_or_no</replaceable>; </optional>
<optional> also-notify { <replaceable>ip_addr</replaceable> <optional>port <replaceable>ip_port</replaceable></optional> ;
<optional> <replaceable>ip_addr</replaceable> <optional>port <replaceable>ip_port</replaceable></optional> ; ... </optional> }; </optional>
<optional> also-notify { <replaceable>ip_addr</replaceable>
<optional>port <replaceable>ip_port</replaceable></optional> <optional>key <replaceable>keyname</replaceable></optional> ;
<optional> <replaceable>ip_addr</replaceable> <optional>port <replaceable>ip_port</replaceable></optional> ; ... </optional> <optional>key <replaceable>keyname</replaceable></optional> ; ... </optional> }; </optional>
<optional> check-names (<constant>warn</constant>|<constant>fail</constant>|<constant>ignore</constant>) ; </optional>
<optional> dialup <replaceable>dialup_option</replaceable> ; </optional>
<optional> file <replaceable>string</replaceable> ; </optional>
......@@ -10560,6 +10567,9 @@ zone <replaceable>zone_name</replaceable> <optional><replaceable>class</replacea
with each <command>also-notify</command>
address to send the notify
messages to a port other than the default of 53.
A TSIG key may also be specified to cause the
<literal>NOTIFY</literal> to be signed by the
given key.
<command>also-notify</command> is not
meaningful for stub zones.
The default is the empty list.
......
......@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: zone.h,v 1.187 2011/04/29 21:37:15 each Exp $ */
/* $Id: zone.h,v 1.188 2011/05/06 21:23:51 each Exp $ */
#ifndef DNS_ZONE_H
#define DNS_ZONE_H 1
......@@ -557,10 +557,16 @@ dns_zone_setmasterswithkeys(dns_zone_t *zone,
isc_result_t
dns_zone_setalsonotify(dns_zone_t *zone, const isc_sockaddr_t *notify,
isc_uint32_t count);
isc_result_t
dns_zone_setalsonotifywithkeys(dns_zone_t *zone, const isc_sockaddr_t *notify,
dns_name_t **keynames, isc_uint32_t count);
/*%<
* Set the list of additional servers to be notified when
* a zone changes. To clear the list use 'count = 0'.
*
* dns_zone_alsonotifywithkeys() allows each notify address to
* be associated with a TSIG key.
*
* Require:
*\li 'zone' to be a valid zone.
*\li 'notify' to be non-NULL if count != 0.
......
......@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: zone.c,v 1.603 2011/04/29 23:47:18 tbox Exp $ */
/* $Id: zone.c,v 1.604 2011/05/06 21:23:51 each Exp $ */
/*! \file */
......@@ -229,6 +229,7 @@ struct dns_zone {
isc_sockaddr_t masteraddr;
dns_notifytype_t notifytype;
isc_sockaddr_t *notify;
dns_name_t **notifykeynames;
unsigned int notifycnt;
isc_sockaddr_t notifyfrom;
isc_task_t *task;
......@@ -448,6 +449,7 @@ struct dns_notify {
dns_request_t *request;
dns_name_t ns;
isc_sockaddr_t dst;
dns_tsigkey_t *key;
ISC_LINK(dns_notify_t) link;
};
......@@ -787,6 +789,7 @@ dns_zone_create(dns_zone_t **zonep, isc_mem_t *mctx) {
zone->masterscnt = 0;
zone->curmaster = 0;
zone->notify = NULL;
zone->notifykeynames = NULL;
zone->notifytype = dns_notifytype_yes;
zone->notifycnt = 0;
zone->task = NULL;
......@@ -4194,48 +4197,8 @@ dns_zone_getnotifysrc6(dns_zone_t *zone) {
return (&zone->notifysrc6);
}
isc_result_t
dns_zone_setalsonotify(dns_zone_t *zone, const isc_sockaddr_t *notify,
isc_uint32_t count)
{
isc_sockaddr_t *new;
REQUIRE(DNS_ZONE_VALID(zone));
REQUIRE(count == 0 || notify != NULL);
LOCK_ZONE(zone);
if (zone->notify != NULL) {
isc_mem_put(zone->mctx, zone->notify,
zone->notifycnt * sizeof(*new));
zone->notify = NULL;
zone->notifycnt = 0;
}
if (count != 0) {
new = isc_mem_get(zone->mctx, count * sizeof(*new));
if (new == NULL) {
UNLOCK_ZONE(zone);
return (ISC_R_NOMEMORY);
}
memcpy(new, notify, count * sizeof(*new));
zone->notify = new;
zone->notifycnt = count;
}
UNLOCK_ZONE(zone);
return (ISC_R_SUCCESS);
}
isc_result_t
dns_zone_setmasters(dns_zone_t *zone, const isc_sockaddr_t *masters,
isc_uint32_t count)
{
isc_result_t result;
result = dns_zone_setmasterswithkeys(zone, masters, NULL, count);
return (result);
}
static isc_boolean_t
same_masters(const isc_sockaddr_t *old, const isc_sockaddr_t *new,
same_addrs(const isc_sockaddr_t *old, const isc_sockaddr_t *new,
isc_uint32_t count)
{
unsigned int i;
......@@ -4265,15 +4228,172 @@ same_keynames(dns_name_t **old, dns_name_t **new, isc_uint32_t count) {
return (ISC_TRUE);
}
static void
clear_addresskeylist(isc_sockaddr_t **addrsp, dns_name_t ***keynamesp,
unsigned int *countp, isc_mem_t *mctx)
{
unsigned int count;
isc_sockaddr_t *addrs;
dns_name_t **keynames;
REQUIRE(countp != NULL && addrsp != NULL && keynamesp != NULL);
count = *countp;
addrs = *addrsp;
keynames = *keynamesp;
if (addrs != NULL) {
isc_mem_put(mctx, addrs, count * sizeof(isc_sockaddr_t));
addrs = *addrsp = NULL;
}
if (keynames != NULL) {
unsigned int i;
for (i = 0; i < count; i++) {
if (keynames[i] != NULL) {
dns_name_free(keynames[i], mctx);
isc_mem_put(mctx, keynames[i],
sizeof(dns_name_t));
keynames[i] = NULL;
}
}
isc_mem_put(mctx, keynames, count * sizeof(dns_name_t *));
keynames = *keynamesp = NULL;
}
count = *countp = 0;
}
static isc_result_t
set_addrkeylist(unsigned int count,
const isc_sockaddr_t *addrs, isc_sockaddr_t **newaddrsp,
dns_name_t **names, dns_name_t ***newnamesp,
isc_mem_t *mctx)
{
isc_result_t result;
isc_sockaddr_t *newaddrs = NULL;
dns_name_t **newnames = NULL;
unsigned int i;
REQUIRE(newaddrsp != NULL && *newaddrsp == NULL);
REQUIRE(newnamesp != NULL && *newnamesp == NULL);
newaddrs = isc_mem_get(mctx, count * sizeof(*newaddrs));
if (newaddrs == NULL)
return (ISC_R_NOMEMORY);
memcpy(newaddrs, addrs, count * sizeof(*newaddrs));
newnames = NULL;
if (names != NULL) {
newnames = isc_mem_get(mctx, count * sizeof(*newnames));
if (newnames == NULL) {
isc_mem_put(mctx, newaddrs, count * sizeof(*newaddrs));
return (ISC_R_NOMEMORY);
}
for (i = 0; i < count; i++)
newnames[i] = NULL;
for (i = 0; i < count; i++) {
if (names[i] != NULL) {
newnames[i] = isc_mem_get(mctx,
sizeof(dns_name_t));
if (newnames[i] == NULL)
goto allocfail;
dns_name_init(newnames[i], NULL);
result = dns_name_dup(names[i], mctx,
newnames[i]);
if (result != ISC_R_SUCCESS) {
allocfail:
for (i = 0; i < count; i++)
if (newnames[i] != NULL)
dns_name_free(
newnames[i],
mctx);
isc_mem_put(mctx, newaddrs,
count * sizeof(*newaddrs));
isc_mem_put(mctx, newnames,
count * sizeof(*newnames));
return (ISC_R_NOMEMORY);
}
}
}
}
*newaddrsp = newaddrs;
*newnamesp = newnames;
return (ISC_R_SUCCESS);
}
isc_result_t
dns_zone_setalsonotify(dns_zone_t *zone, const isc_sockaddr_t *notify,
isc_uint32_t count)
{
return (dns_zone_setalsonotifywithkeys(zone, notify, NULL, count));
}
isc_result_t
dns_zone_setalsonotifywithkeys(dns_zone_t *zone, const isc_sockaddr_t *notify,
dns_name_t **keynames, isc_uint32_t count)
{
isc_result_t result;
isc_sockaddr_t *newaddrs = NULL;
dns_name_t **newnames = NULL;
REQUIRE(DNS_ZONE_VALID(zone));
REQUIRE(count == 0 || notify != NULL);
if (keynames != NULL)
REQUIRE(count != 0);
LOCK_ZONE(zone);
if (count == zone->notifycnt &&
same_addrs(zone->notify, notify, count) &&
same_keynames(zone->notifykeynames, keynames, count))
goto unlock;
clear_addresskeylist(&zone->notify, &zone->notifykeynames,
&zone->notifycnt, zone->mctx);
if (count == 0)
goto unlock;
/*
* Set up the notify and notifykey lists
*/
result = set_addrkeylist(count, notify, &newaddrs,
keynames, &newnames, zone->mctx);
if (result != ISC_R_SUCCESS)
goto unlock;
/*
* Everything is ok so attach to the zone.
*/
zone->notify = newaddrs;
zone->notifykeynames = newnames;
zone->notifycnt = count;
unlock:
UNLOCK_ZONE(zone);
return (ISC_R_SUCCESS);
}
isc_result_t
dns_zone_setmasters(dns_zone_t *zone, const isc_sockaddr_t *masters,
isc_uint32_t count)
{
isc_result_t result;
result = dns_zone_setmasterswithkeys(zone, masters, NULL, count);
return (result);
}
isc_result_t
dns_zone_setmasterswithkeys(dns_zone_t *zone,
const isc_sockaddr_t *masters,
dns_name_t **keynames,
isc_uint32_t count)
{
isc_sockaddr_t *new;
isc_result_t result = ISC_R_SUCCESS;
dns_name_t **newname;
isc_sockaddr_t *newaddrs = NULL;
dns_name_t **newnames = NULL;
isc_boolean_t *newok;
unsigned int i;
......@@ -4291,38 +4411,24 @@ dns_zone_setmasterswithkeys(dns_zone_t *zone,
* unlock and exit.
*/
if (count != zone->masterscnt ||
!same_masters(zone->masters, masters, count) ||
!same_addrs(zone->masters, masters, count) ||
!same_keynames(zone->masterkeynames, keynames, count)) {
if (zone->request != NULL)
dns_request_cancel(zone->request);
} else
goto unlock;
if (zone->masters != NULL) {
isc_mem_put(zone->mctx, zone->masters,
zone->masterscnt * sizeof(*new));
zone->masters = NULL;
}
if (zone->masterkeynames != NULL) {
for (i = 0; i < zone->masterscnt; i++) {
if (zone->masterkeynames[i] != NULL) {
dns_name_free(zone->masterkeynames[i],
zone->mctx);
isc_mem_put(zone->mctx,
zone->masterkeynames[i],
sizeof(dns_name_t));
zone->masterkeynames[i] = NULL;
}
}
isc_mem_put(zone->mctx, zone->masterkeynames,
zone->masterscnt * sizeof(dns_name_t *));
zone->masterkeynames = NULL;
}
/*
* This needs to happen before clear_addresskeylist() sets
* zone->masterscnt to 0:
*/
if (zone->mastersok != NULL) {
isc_mem_put(zone->mctx, zone->mastersok,
zone->masterscnt * sizeof(isc_boolean_t));
zone->mastersok = NULL;
}
zone->masterscnt = 0;
clear_addresskeylist(&zone->masters, &zone->masterkeynames,
&zone->masterscnt, zone->mctx);