Commit 80095256 authored by Curtis Blackburn's avatar Curtis Blackburn
Browse files

3682. [bug] Correct the behavior of rndc retransfer to allow

	 		inline-signing slave zones to retain NSEC3 parameters instead of
			reverting to NSEC [RT #34745]
parent 545b8a72
3682. [bug] Correct the behavior of rndc retransfer to allow
inline-signing slave zones to retain NSEC3 parameters instead of
reverting to NSEC [RT #34745]
3681. [port] Update the Windows build system to support feature
selection and WIN64 builds. This is a work in
progress. [RT #34160]
......
......@@ -241,7 +241,15 @@
<term><userinput>retransfer <replaceable>zone</replaceable> <optional><replaceable>class</replaceable> <optional><replaceable>view</replaceable></optional></optional></userinput></term>
<listitem>
<para>
Retransfer the given zone from the master.
Retransfer the given slave zone from the master server.
</para>
<para>
If the zone is configured to use
<command>inline-signing</command>, the signed
version of the zone is discarded; after the
retransfer of the unsigned version is complete, the
signed version will be regenerated with all new
signatures.
</para>
</listitem>
</varlistentry>
......
......@@ -60,6 +60,10 @@ rm -f ns3/retransfer.bk
rm -f ns3/retransfer.bk.jnl
rm -f ns3/retransfer.bk.signed
rm -f ns3/retransfer.bk.signed.jnl
rm -f ns3/retransfer3.bk
rm -f ns3/retransfer3.bk.jnl
rm -f ns3/retransfer3.bk.signed
rm -f ns3/retransfer3.bk.signed.jnl
rm -f ns3/externalkey.db
rm -f ns3/externalkey.db.signed
rm -f ns3/externalkey.db.signed.jnl
......
......@@ -53,3 +53,6 @@ ns3.nsec3. A 10.53.0.3
externalkey. NS ns3.externalkey.
ns3.externalkey. A 10.53.0.3
retransfer3. NS ns3.retransfer.
ns3.retransfer3. A 10.53.0.3
......@@ -48,3 +48,10 @@ zone "retransfer" {
allow-update { any; };
notify no;
};
zone "retransfer3" {
type master;
file "retransfer.db";
allow-update { any; };
notify no;
};
......@@ -111,3 +111,11 @@ zone "externalkey" {
allow-update { any; };
file "externalkey.db";
};
zone "retransfer3" {
type slave;
masters { 10.53.0.2; };
inline-signing yes;
auto-dnssec maintain;
file "retransfer3.bk";
};
......@@ -80,6 +80,13 @@ rm -f K${zone}.+*+*.private
keyname=`$KEYGEN -q -r $RANDFILE -a NSEC3RSASHA1 -b 1024 -n zone -f KSK $zone`
$DSFROMKEY -T 1200 $keyname >> ../ns1/root.db
zone=retransfer3
rm -f K${zone}.+*+*.key
rm -f K${zone}.+*+*.private
keyname=`$KEYGEN -q -r $RANDFILE -a NSEC3RSASHA1 -b 768 -n zone $zone`
keyname=`$KEYGEN -q -r $RANDFILE -a NSEC3RSASHA1 -b 1024 -n zone -f KSK $zone`
$DSFROMKEY -T 1200 $keyname >> ../ns1/root.db
for s in a c d h k l m q z
do
zone=test-$s
......
......@@ -25,7 +25,7 @@ RANDFILE=random.data
status=0
n=0
$RNDC -c ../common/rndc.conf -s 10.53.0.3 -p 9953 signing -nsec3param 1 0 0 - nsec3
$RNDC -c ../common/rndc.conf -s 10.53.0.3 -p 9953 signing -nsec3param 1 0 0 - nsec3 > /dev/null 2>&1
for i in 1 2 3 4 5 6 7 8 9 0
do
......@@ -34,6 +34,21 @@ do
sleep 1
done
# Loop until retransfer3 has been transferred.
for i in 1 2 3 4 5 6 7 8 9 0
do
ans=0
$RNDC -c ../common/rndc.conf -s 10.53.0.3 -p 9953 signing -nsec3param 1 0 0 - retransfer3 > /dev/null 2>&1 || ans=1
[ $ans = 0 ] && break
done
for i in 1 2 3 4 5 6 7 8 9 0
do
nsec3param=`$DIG +short @10.53.0.3 -p 5300 nsec3param retransfer3.`
test -n "$nsec3param" && break
sleep 1
done
n=`expr $n + 1`
echo "I:checking that rrsigs are replaced with ksk only"
ret=0
......@@ -761,6 +776,32 @@ n=`expr $n + 1`
if [ $ret != 0 ]; then echo "I:failed"; fi
status=`expr $status + $ret`
echo "I:check rndc retransfer of a inline nsec3 slave retains nsec3 ($n)"
ret=0
for i in 0 1 2 3 4 5 6 7 8 9
do
ans=0
$DIG $DIGOPTS @10.53.0.3 -p 5300 nonexist.retransfer3 A > dig.out.ns3.pre.test$n
grep "status: NXDOMAIN" dig.out.ns3.pre.test$n > /dev/null || ans=1
grep "NSEC3" dig.out.ns3.pre.test$n > /dev/null || ans=1
[ $ans = 0 ] && break
sleep 1
done
$RNDC -c ../common/rndc.conf -s 10.53.0.3 -p 9953 retransfer retransfer3 2>&1 || ret=1
for i in 0 1 2 3 4 5 6 7 8 9
do
ans=0
$DIG $DIGOPTS @10.53.0.3 -p 5300 nonexist.retransfer3 A > dig.out.ns3.post.test$n
grep "status: NXDOMAIN" dig.out.ns3.post.test$n > /dev/null || ans=1
grep "NSEC3" dig.out.ns3.post.test$n > /dev/null || ans=1
[ $ans = 0 ] && break
sleep 1
done
[ $ans = 1 ] && ret=1
n=`expr $n + 1`
if [ $ret != 0 ]; then echo "I:failed"; fi
status=`expr $status + $ret`
n=`expr $n + 1`
echo "I:stop bump in the wire signer server ($n)"
ret=0
......
......@@ -799,6 +799,20 @@ static const char *dbargv_default[] = { "rbt" };
} \
} while (0)
typedef struct nsec3param nsec3param_t;
struct nsec3param {
unsigned char data[DNS_NSEC3PARAM_BUFFERSIZE + 1];
unsigned int length;
isc_boolean_t nsec;
isc_boolean_t replace;
ISC_LINK(nsec3param_t) link;
};
typedef ISC_LIST(nsec3param_t) nsec3paramlist_t;
struct np3event {
isc_event_t event;
nsec3param_t params;
};
/*%
* Increment resolver-related statistics counters. Zone must be locked.
*/
......@@ -13407,6 +13421,203 @@ checkandaddsoa(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
0, NULL));
}
/*
* This function should populate an nsec3paramlist_t with the
* nsecparam_t data from a zone.
*/
static isc_result_t
save_nsec3param(dns_zone_t *zone, nsec3paramlist_t *nsec3list) {
isc_result_t result;
dns_dbnode_t *node = NULL;
dns_rdataset_t rdataset, prdataset;
dns_rdata_t rdata_in, prdata_in, prdata_out;
dns_dbversion_t *version = NULL;
nsec3param_t *nsec3param = NULL;
nsec3param_t *nsec3p = NULL;
nsec3param_t *next;
dns_db_t *db = NULL;
unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE];
REQUIRE(DNS_ZONE_VALID(zone));
REQUIRE(nsec3list != NULL);
REQUIRE(ISC_LIST_EMPTY(*nsec3list));
dns_db_attach(zone->db, &db);
CHECK(dns_db_getoriginnode(db, &node));
dns_rdataset_init(&rdataset);
dns_db_currentversion(db, &version);
result = dns_db_findrdataset(db, node, version,
dns_rdatatype_nsec3param,
dns_rdatatype_none, 0, &rdataset, NULL);
if (result != ISC_R_SUCCESS)
goto getprivate;
/*
* walk nsec3param rdataset making a list of parameters (note that
* multiple simultaneous nsec3 chains are annoyingly legal -- this
* is why we use an nsec3list, even tho we will usually only have
* one)
*/
for (result = dns_rdataset_first(&rdataset);
result == ISC_R_SUCCESS;
result = dns_rdataset_next(&rdataset))
{
dns_rdata_init(&rdata_in);
dns_rdataset_current(&rdataset, &rdata_in);
isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
DNS_LOGMODULE_ZONE, ISC_LOG_DEBUG(3),
"looping through nsec3param data");
nsec3param = isc_mem_get(zone->mctx, sizeof(nsec3param_t));
if (nsec3param == NULL)
CHECK(ISC_R_NOMEMORY);
ISC_LINK_INIT(nsec3param, link);
/*
* now transfer the data from the rdata to
* the nsec3param
*/
dns_rdata_init(&prdata_out);
dns_nsec3param_toprivate(&rdata_in, &prdata_out,
zone->privatetype, nsec3param->data,
sizeof(nsec3param->data));
nsec3param->length = prdata_out.length;
ISC_LIST_APPEND(*nsec3list, nsec3param, link);
}
getprivate:
dns_rdataset_init(&prdataset);
result = dns_db_findrdataset(db, node, version, zone->privatetype,
dns_rdatatype_none, 0, &prdataset, NULL);
if (result != ISC_R_SUCCESS)
goto done;
/*
* walk private type records, converting them to nsec3 parameters
* using dns_nsec3param_fromprivate(), do the right thing based on
* CREATE and REMOVE flags
*/
for (result = dns_rdataset_first(&prdataset);
result == ISC_R_SUCCESS;
result = dns_rdataset_next(&prdataset))
{
dns_rdata_init(&prdata_in);
dns_rdataset_current(&prdataset, &prdata_in);
isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
DNS_LOGMODULE_ZONE, ISC_LOG_DEBUG(3),
"looping through nsec3param private data");
if (!dns_nsec3param_fromprivate(&prdata_in, &prdata_out,
buf, sizeof(buf)))
continue;
if ((prdata_out.data[1] & DNS_NSEC3FLAG_REMOVE) !=0) {
prdata_out.data[1] = 0;
for (nsec3p = ISC_LIST_HEAD(*nsec3list);
nsec3p != NULL;
nsec3p = next)
{
next = ISC_LIST_NEXT(nsec3p, link);
if (memcmp(prdata_out.data, nsec3p->data,
sizeof(nsec3p->data)) == 0) {
ISC_LIST_UNLINK(*nsec3list,
nsec3p, link);
isc_mem_put(zone->mctx, nsec3p,
sizeof(nsec3param_t));
}
}
continue;
}
nsec3param = isc_mem_get(zone->mctx, sizeof(nsec3param_t));
if (nsec3param == NULL)
CHECK(ISC_R_NOMEMORY);
ISC_LINK_INIT(nsec3param, link);
dns_rdata_init(&prdata_out);
dns_nsec3param_toprivate(&prdata_in, &prdata_out,
zone->privatetype, nsec3param->data,
sizeof(nsec3param->data));
nsec3param->length = prdata_out.length;
ISC_LIST_APPEND(*nsec3list, nsec3param, link);
}
done:
if (result == ISC_R_NOMORE || result == ISC_R_NOTFOUND)
result = ISC_R_SUCCESS;
failure:
if (node != NULL)
dns_db_detachnode(db, &node);
if (version != NULL)
dns_db_closeversion(db, &version, ISC_FALSE);
if (db != NULL)
dns_db_detach(&db);
if (dns_rdataset_isassociated(&rdataset))
dns_rdataset_disassociate(&rdataset);
if (dns_rdataset_isassociated(&prdataset))
dns_rdataset_disassociate(&prdataset);
return (result);
}
/*
* Walk the list of the nsec3 chains desired for the zone, converting
* parameters to private type records using dns_nsec3param_toprivate(),
* and insert them into the new zone db.
*/
static isc_result_t
restore_nsec3param(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *version,
nsec3paramlist_t *nsec3list)
{
isc_result_t result;
dns_diff_t diff;
dns_rdata_t rdata;
nsec3param_t *nsec3p = NULL;
nsec3param_t *next;
REQUIRE(DNS_ZONE_VALID(zone));
REQUIRE(!ISC_LIST_EMPTY(*nsec3list));
dns_diff_init(zone->mctx, &diff);
/*
* Loop through the list of private-type records, set the INITIAL
* and CREATE flags, and the add the record to the apex of the tree
* in db.
*/
for (nsec3p = ISC_LIST_HEAD(*nsec3list);
nsec3p != NULL;
nsec3p = next)
{
next = ISC_LIST_NEXT(nsec3p, link);
dns_rdata_init(&rdata);
nsec3p->data[2] = DNS_NSEC3FLAG_CREATE | DNS_NSEC3FLAG_INITIAL;
rdata.length = nsec3p->length;
rdata.data = nsec3p->data;
rdata.type = zone->privatetype;
rdata.rdclass = zone->rdclass;
CHECK(update_one_rr(db, version, &diff, DNS_DIFFOP_ADD,
&zone->origin, 0, &rdata));
}
result = ISC_R_SUCCESS;
failure:
for (nsec3p = ISC_LIST_HEAD(*nsec3list);
nsec3p != NULL;
nsec3p = next)
{
next = ISC_LIST_NEXT(nsec3p, link);
ISC_LIST_UNLINK(*nsec3list, nsec3p, link);
isc_mem_put(zone->mctx, nsec3p, sizeof(nsec3param_t));
}
dns_diff_clear(&diff);
return (result);
}
static void
receive_secure_db(isc_task_t *task, isc_event_t *event) {
isc_result_t result;
......@@ -13422,9 +13633,12 @@ receive_secure_db(isc_task_t *task, isc_event_t *event) {
isc_time_t loadtime;
unsigned int oldserial = 0;
isc_boolean_t have_oldserial = ISC_FALSE;
nsec3paramlist_t nsec3list;
UNUSED(task);
ISC_LIST_INIT(nsec3list);
zone = event->ev_arg;
rawdb = ((struct secure_event *)event)->db;
isc_event_free(&event);
......@@ -13445,6 +13659,16 @@ receive_secure_db(isc_task_t *task, isc_event_t *event) {
result = dns_db_getsoaserial(zone->db, NULL, &oldserial);
if (result == ISC_R_SUCCESS)
have_oldserial = ISC_TRUE;
/*
* assemble nsec3parameters from the old zone, and set a flag
* if any are found
*/
result = save_nsec3param(zone, &nsec3list);
if (result != ISC_R_SUCCESS) {
ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
goto failure;
}
}
ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
......@@ -13506,8 +13730,16 @@ receive_secure_db(isc_task_t *task, isc_event_t *event) {
dns_db_detachnode(rawdb, &rawnode);
dns_db_detachnode(db, &node);
}
/*
* Call restore_nsec3param() to create private-type records from
* the old nsec3 parameters and insert them into db
*/
if (!ISC_LIST_EMPTY(nsec3list))
restore_nsec3param(zone, db, version, &nsec3list);
dns_db_closeversion(db, &version, ISC_TRUE);
/*
* Lock hierarchy: zmgr, zone, raw.
*/
......@@ -17202,14 +17434,6 @@ dns_zone_keydone(dns_zone_t *zone, const char *keystr) {
return (result);
}
struct nsec3param {
isc_event_t event;
unsigned char data[DNS_NSEC3PARAM_BUFFERSIZE + 1];
unsigned int length;
isc_boolean_t nsec;
isc_boolean_t replace;
};
static void
setnsec3param(isc_task_t *task, isc_event_t *event) {
const char *me = "setnsec3param";
......@@ -17221,7 +17445,8 @@ setnsec3param(isc_task_t *task, isc_event_t *event) {
dns_dbnode_t *node = NULL;
dns_rdataset_t prdataset, nrdataset;
dns_diff_t diff;
struct nsec3param *np = (struct nsec3param *)event;
struct np3event *npe = (struct np3event *)event;
nsec3param_t *np;
dns_update_log_t log = { update_log_cb, NULL };
dns_rdata_t rdata;
isc_boolean_t nseconly;
......@@ -17233,6 +17458,8 @@ setnsec3param(isc_task_t *task, isc_event_t *event) {
INSIST(DNS_ZONE_VALID(zone));
ENTER;
np = &npe->params;
dns_rdataset_init(&prdataset);
dns_rdataset_init(&nrdataset);
......@@ -17385,7 +17612,8 @@ dns_zone_setnsec3param(dns_zone_t *zone, isc_uint8_t hash, isc_uint8_t flags,
dns_rdata_t nrdata = DNS_RDATA_INIT;
dns_rdata_t prdata = DNS_RDATA_INIT;
unsigned char nbuf[DNS_NSEC3PARAM_BUFFERSIZE];
struct nsec3param *np;
struct np3event *npe;
nsec3param_t *np;
dns_zone_t *dummy = NULL;
isc_buffer_t b;
isc_event_t *e;
......@@ -17396,13 +17624,15 @@ dns_zone_setnsec3param(dns_zone_t *zone, isc_uint8_t hash, isc_uint8_t flags,
LOCK_ZONE(zone);
e = isc_event_allocate(zone->mctx, zone, DNS_EVENT_SETNSEC3PARAM,
setnsec3param, zone, sizeof(struct nsec3param));
setnsec3param, zone, sizeof(struct np3event));
if (e == NULL) {
result = ISC_R_NOMEMORY;
goto failure;
}
np = (struct nsec3param *) e;
npe = (struct np3event *) e;
np = &npe->params;
np->replace = replace;
if (hash == 0) {
np->length = 0;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment