Dynamic update DNSKEY to secure zone
This commit is contained in:
+11
-4
@@ -828,7 +828,7 @@ dns_dnssec_findzonekeys(dns_db_t *db, dns_dbversion_t *ver, dns_dbnode_t *node,
|
||||
}
|
||||
}
|
||||
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
if (true) {
|
||||
char filename[DNS_NAME_FORMATSIZE +
|
||||
DNS_SECALG_FORMATSIZE +
|
||||
sizeof("key file for //65535")];
|
||||
@@ -857,9 +857,16 @@ dns_dnssec_findzonekeys(dns_db_t *db, dns_dbversion_t *ver, dns_dbnode_t *node,
|
||||
|
||||
isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
|
||||
DNS_LOGMODULE_DNSSEC, ISC_LOG_WARNING,
|
||||
"dns_dnssec_findzonekeys: error "
|
||||
"reading %s: %s",
|
||||
filename, isc_result_totext(result));
|
||||
"dns_dnssec_findzonekeys: reading %s",
|
||||
filename);
|
||||
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
|
||||
DNS_LOGMODULE_DNSSEC, ISC_LOG_WARNING,
|
||||
"dns_dnssec_findzonekeys: error "
|
||||
"reading %s: %s",
|
||||
filename, isc_result_totext(result));
|
||||
}
|
||||
}
|
||||
|
||||
if (result == ISC_R_FILENOTFOUND || result == ISC_R_NOPERM) {
|
||||
|
||||
@@ -2520,6 +2520,9 @@ dns_zone_getserialupdatemethod(dns_zone_t *zone);
|
||||
isc_result_t
|
||||
dns_zone_link(dns_zone_t *zone, dns_zone_t *raw);
|
||||
|
||||
void
|
||||
dns_zone_getsecure(dns_zone_t *zone, dns_zone_t **secure);
|
||||
|
||||
void
|
||||
dns_zone_getraw(dns_zone_t *zone, dns_zone_t **raw);
|
||||
|
||||
|
||||
@@ -22563,6 +22563,19 @@ dns_zone_getraw(dns_zone_t *zone, dns_zone_t **raw) {
|
||||
UNLOCK(&zone->lock);
|
||||
}
|
||||
|
||||
void
|
||||
dns_zone_getsecure(dns_zone_t *zone, dns_zone_t **secure) {
|
||||
REQUIRE(DNS_ZONE_VALID(zone));
|
||||
REQUIRE(secure != NULL && *secure == NULL);
|
||||
|
||||
LOCK(&zone->lock);
|
||||
INSIST(zone != zone->secure);
|
||||
if (zone->secure != NULL) {
|
||||
dns_zone_attach(zone->secure, secure);
|
||||
}
|
||||
UNLOCK(&zone->lock);
|
||||
}
|
||||
|
||||
bool
|
||||
dns_zone_israw(dns_zone_t *zone) {
|
||||
bool result;
|
||||
|
||||
+411
-148
@@ -2606,13 +2606,21 @@ static void
|
||||
update_action(isc_task_t *task, isc_event_t *event) {
|
||||
update_event_t *uev = (update_event_t *)event;
|
||||
dns_zone_t *zone = uev->zone;
|
||||
dns_zone_t *securezone = NULL;
|
||||
dns_zone_t *updatezone = NULL;
|
||||
ns_client_t *client = (ns_client_t *)event->ev_arg;
|
||||
isc_result_t result;
|
||||
dns_db_t *db = NULL;
|
||||
dns_db_t *securedb = NULL;
|
||||
dns_db_t *updatedb = NULL;
|
||||
dns_dbversion_t *oldver = NULL;
|
||||
dns_dbversion_t *ver = NULL;
|
||||
dns_diff_t diff; /* Pending updates. */
|
||||
dns_diff_t temp; /* Pending RR existence assertions. */
|
||||
dns_dbversion_t *secureoldver = NULL;
|
||||
dns_dbversion_t *securever = NULL;
|
||||
dns_dbversion_t *updatever = NULL;
|
||||
dns_diff_t diff; /* Pending updates. */
|
||||
dns_diff_t securediff; /* Pending updates (secure zone). */
|
||||
dns_diff_t temp; /* Pending RR existence assertions. */
|
||||
bool soa_serial_changed = false;
|
||||
isc_mem_t *mctx = client->manager->mctx;
|
||||
dns_rdatatype_t covers;
|
||||
@@ -2634,16 +2642,22 @@ update_action(isc_task_t *task, isc_event_t *event) {
|
||||
size_t ruleslen = 0;
|
||||
size_t rule;
|
||||
const dns_ssurule_t **rules = NULL;
|
||||
bool rawzone_done = false;
|
||||
|
||||
INSIST(event->ev_type == DNS_EVENT_UPDATE);
|
||||
|
||||
dns_diff_init(mctx, &diff);
|
||||
dns_diff_init(mctx, &securediff);
|
||||
dns_diff_init(mctx, &temp);
|
||||
|
||||
CHECK(dns_zone_getdb(zone, &db));
|
||||
zonename = dns_db_origin(db);
|
||||
zoneclass = dns_db_class(db);
|
||||
dns_zone_getssutable(zone, &ssutable);
|
||||
if (dns_zone_israw(zone)) {
|
||||
dns_zone_getsecure(zone, &securezone);
|
||||
CHECK(dns_zone_getdb(securezone, &securedb));
|
||||
}
|
||||
|
||||
/*
|
||||
* Update message processing can leak record existence information
|
||||
@@ -2658,11 +2672,14 @@ update_action(isc_task_t *task, isc_event_t *event) {
|
||||
*/
|
||||
dns_db_currentversion(db, &oldver);
|
||||
CHECK(dns_db_newversion(db, &ver));
|
||||
if (securedb != NULL) {
|
||||
dns_db_currentversion(securedb, &secureoldver);
|
||||
CHECK(dns_db_newversion(securedb, &securever));
|
||||
}
|
||||
|
||||
/*
|
||||
* Check prerequisites.
|
||||
*/
|
||||
|
||||
for (result = dns_message_firstname(request, DNS_SECTION_PREREQUISITE);
|
||||
result == ISC_R_SUCCESS;
|
||||
result = dns_message_nextname(request, DNS_SECTION_PREREQUISITE))
|
||||
@@ -2702,8 +2719,16 @@ update_action(isc_task_t *task, isc_event_t *event) {
|
||||
"satisfied");
|
||||
}
|
||||
} else {
|
||||
CHECK(rrset_exists(db, ver, name, rdata.type,
|
||||
covers, &flag));
|
||||
if (rdata.type == dns_rdatatype_dnskey &&
|
||||
securedb != NULL) {
|
||||
CHECK(rrset_exists(securedb, securever,
|
||||
name, rdata.type,
|
||||
covers, &flag));
|
||||
} else {
|
||||
CHECK(rrset_exists(db, ver, name,
|
||||
rdata.type, covers,
|
||||
&flag));
|
||||
}
|
||||
if (!flag) {
|
||||
/* RRset does not exist. */
|
||||
PREREQFAILNT(DNS_R_NXRRSET, name,
|
||||
@@ -2730,8 +2755,16 @@ update_action(isc_task_t *task, isc_event_t *event) {
|
||||
"satisfied");
|
||||
}
|
||||
} else {
|
||||
CHECK(rrset_exists(db, ver, name, rdata.type,
|
||||
covers, &flag));
|
||||
if (rdata.type == dns_rdatatype_dnskey &&
|
||||
securedb != NULL) {
|
||||
CHECK(rrset_exists(securedb, securever,
|
||||
name, rdata.type,
|
||||
covers, &flag));
|
||||
} else {
|
||||
CHECK(rrset_exists(db, ver, name,
|
||||
rdata.type, covers,
|
||||
&flag));
|
||||
}
|
||||
if (flag) {
|
||||
/* RRset exists. */
|
||||
PREREQFAILNT(DNS_R_YXRRSET, name,
|
||||
@@ -3009,6 +3042,13 @@ update_action(isc_task_t *task, isc_event_t *event) {
|
||||
|
||||
get_current_rr(request, DNS_SECTION_UPDATE, zoneclass, &name,
|
||||
&rdata, &covers, &ttl, &update_class);
|
||||
if (rdata.type == dns_rdatatype_dnskey && securedb != NULL) {
|
||||
updatedb = securedb;
|
||||
updatever = securever;
|
||||
} else {
|
||||
updatedb = db;
|
||||
updatever = ver;
|
||||
}
|
||||
|
||||
if (update_class == zoneclass) {
|
||||
unsigned int max = 0;
|
||||
@@ -3043,7 +3083,7 @@ update_action(isc_task_t *task, isc_event_t *event) {
|
||||
}
|
||||
if (rdata.type == dns_rdatatype_cname) {
|
||||
CHECK(cname_incompatible_rrset_exists(
|
||||
db, ver, name, &flag));
|
||||
updatedb, updatever, name, &flag));
|
||||
if (flag) {
|
||||
update_log(client, zone,
|
||||
LOGLEVEL_PROTOCOL,
|
||||
@@ -3053,7 +3093,7 @@ update_action(isc_task_t *task, isc_event_t *event) {
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
CHECK(rrset_exists(db, ver, name,
|
||||
CHECK(rrset_exists(updatedb, updatever, name,
|
||||
dns_rdatatype_cname, 0,
|
||||
&flag));
|
||||
if (flag && !dns_rdatatype_atcname(rdata.type))
|
||||
@@ -3067,7 +3107,7 @@ update_action(isc_task_t *task, isc_event_t *event) {
|
||||
}
|
||||
if (rdata.type == dns_rdatatype_soa) {
|
||||
bool ok;
|
||||
CHECK(rrset_exists(db, ver, name,
|
||||
CHECK(rrset_exists(updatedb, updatever, name,
|
||||
dns_rdatatype_soa, 0,
|
||||
&flag));
|
||||
if (!flag) {
|
||||
@@ -3077,8 +3117,8 @@ update_action(isc_task_t *task, isc_event_t *event) {
|
||||
"SOA ignored");
|
||||
continue;
|
||||
}
|
||||
CHECK(check_soa_increment(db, ver, &rdata,
|
||||
&ok));
|
||||
CHECK(check_soa_increment(updatedb, updatever,
|
||||
&rdata, &ok));
|
||||
if (!ok) {
|
||||
update_log(client, zone,
|
||||
LOGLEVEL_PROTOCOL,
|
||||
@@ -3087,7 +3127,9 @@ update_action(isc_task_t *task, isc_event_t *event) {
|
||||
"ignoring it");
|
||||
continue;
|
||||
}
|
||||
soa_serial_changed = true;
|
||||
if (updatedb != securedb) {
|
||||
soa_serial_changed = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (dns_rdatatype_atparent(rdata.type) &&
|
||||
@@ -3156,8 +3198,9 @@ update_action(isc_task_t *task, isc_event_t *event) {
|
||||
}
|
||||
if (max != 0) {
|
||||
unsigned int count = 0;
|
||||
CHECK(foreach_rr(db, ver, name, rdata.type,
|
||||
covers, count_action, &count));
|
||||
CHECK(foreach_rr(updatedb, updatever, name,
|
||||
rdata.type, covers,
|
||||
count_action, &count));
|
||||
if (count >= max) {
|
||||
update_log(client, zone,
|
||||
LOGLEVEL_PROTOCOL,
|
||||
@@ -3203,9 +3246,13 @@ update_action(isc_task_t *task, isc_event_t *event) {
|
||||
/* Prepare the affected RRset for the addition. */
|
||||
{
|
||||
add_rr_prepare_ctx_t ctx;
|
||||
ctx.db = db;
|
||||
ctx.ver = ver;
|
||||
ctx.diff = &diff;
|
||||
ctx.db = updatedb;
|
||||
ctx.ver = updatever;
|
||||
if (securedb != NULL) {
|
||||
ctx.diff = &securediff;
|
||||
} else {
|
||||
ctx.diff = &diff;
|
||||
}
|
||||
ctx.name = name;
|
||||
ctx.oldname = name;
|
||||
ctx.update_rr = &rdata;
|
||||
@@ -3213,27 +3260,29 @@ update_action(isc_task_t *task, isc_event_t *event) {
|
||||
ctx.ignore_add = false;
|
||||
dns_diff_init(mctx, &ctx.del_diff);
|
||||
dns_diff_init(mctx, &ctx.add_diff);
|
||||
CHECK(foreach_rr(db, ver, name, rdata.type,
|
||||
covers, add_rr_prepare_action,
|
||||
&ctx));
|
||||
CHECK(foreach_rr(updatedb, updatever, name,
|
||||
rdata.type, covers,
|
||||
add_rr_prepare_action, &ctx));
|
||||
|
||||
if (ctx.ignore_add) {
|
||||
dns_diff_clear(&ctx.del_diff);
|
||||
dns_diff_clear(&ctx.add_diff);
|
||||
} else {
|
||||
result = do_diff(&ctx.del_diff, db, ver,
|
||||
&diff);
|
||||
result = do_diff(&ctx.del_diff,
|
||||
updatedb, updatever,
|
||||
ctx.diff);
|
||||
if (result == ISC_R_SUCCESS) {
|
||||
result = do_diff(&ctx.add_diff,
|
||||
db, ver,
|
||||
&diff);
|
||||
result = do_diff(
|
||||
&ctx.add_diff, updatedb,
|
||||
updatever, ctx.diff);
|
||||
}
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
dns_diff_clear(&ctx.del_diff);
|
||||
dns_diff_clear(&ctx.add_diff);
|
||||
goto failure;
|
||||
}
|
||||
CHECK(update_one_rr(db, ver, &diff,
|
||||
CHECK(update_one_rr(updatedb, updatever,
|
||||
ctx.diff,
|
||||
DNS_DIFFOP_ADD,
|
||||
name, ttl, &rdata));
|
||||
}
|
||||
@@ -3251,16 +3300,36 @@ update_action(isc_task_t *task, isc_event_t *event) {
|
||||
"name '%s'",
|
||||
namestr);
|
||||
}
|
||||
if (dns_name_equal(name, zonename)) {
|
||||
CHECK(delete_if(type_not_soa_nor_ns_p,
|
||||
db, ver, name,
|
||||
dns_rdatatype_any, 0,
|
||||
&rdata, &diff));
|
||||
if (securedb != NULL) {
|
||||
if (dns_name_equal(name, zonename)) {
|
||||
CHECK(delete_if(
|
||||
type_not_soa_nor_ns_p,
|
||||
updatedb, updatever,
|
||||
name, dns_rdatatype_any,
|
||||
0, &rdata,
|
||||
&securediff));
|
||||
} else {
|
||||
CHECK(delete_if(
|
||||
type_not_dnssec,
|
||||
updatedb, updatever,
|
||||
name, dns_rdatatype_any,
|
||||
0, &rdata,
|
||||
&securediff));
|
||||
}
|
||||
} else {
|
||||
CHECK(delete_if(type_not_dnssec, db,
|
||||
ver, name,
|
||||
dns_rdatatype_any, 0,
|
||||
&rdata, &diff));
|
||||
if (dns_name_equal(name, zonename)) {
|
||||
CHECK(delete_if(
|
||||
type_not_soa_nor_ns_p,
|
||||
updatedb, updatever,
|
||||
name, dns_rdatatype_any,
|
||||
0, &rdata, &diff));
|
||||
} else {
|
||||
CHECK(delete_if(
|
||||
type_not_dnssec,
|
||||
updatedb, updatever,
|
||||
name, dns_rdatatype_any,
|
||||
0, &rdata, &diff));
|
||||
}
|
||||
}
|
||||
} else if (dns_name_equal(name, zonename) &&
|
||||
(rdata.type == dns_rdatatype_soa ||
|
||||
@@ -3285,9 +3354,17 @@ update_action(isc_task_t *task, isc_event_t *event) {
|
||||
"deleting rrset at '%s' %s",
|
||||
namestr, typestr);
|
||||
}
|
||||
CHECK(delete_if(true_p, db, ver, name,
|
||||
rdata.type, covers, &rdata,
|
||||
&diff));
|
||||
if (securedb != NULL) {
|
||||
CHECK(delete_if(true_p, updatedb,
|
||||
updatever, name,
|
||||
rdata.type, covers,
|
||||
&rdata, &securediff));
|
||||
} else {
|
||||
CHECK(delete_if(true_p, updatedb,
|
||||
updatever, name,
|
||||
rdata.type, covers,
|
||||
&rdata, &diff));
|
||||
}
|
||||
}
|
||||
} else if (update_class == dns_rdataclass_none) {
|
||||
char namestr[DNS_NAME_FORMATSIZE];
|
||||
@@ -3307,9 +3384,9 @@ update_action(isc_task_t *task, isc_event_t *event) {
|
||||
}
|
||||
if (rdata.type == dns_rdatatype_ns) {
|
||||
int count;
|
||||
CHECK(rr_count(db, ver, name,
|
||||
dns_rdatatype_ns, 0,
|
||||
&count));
|
||||
CHECK(rr_count(updatedb, updatever,
|
||||
name, dns_rdatatype_ns,
|
||||
0, &count));
|
||||
if (count == 1) {
|
||||
update_log(client, zone,
|
||||
LOGLEVEL_PROTOCOL,
|
||||
@@ -3325,8 +3402,15 @@ update_action(isc_task_t *task, isc_event_t *event) {
|
||||
sizeof(typestr));
|
||||
update_log(client, zone, LOGLEVEL_PROTOCOL,
|
||||
"deleting an RR at %s %s", namestr, typestr);
|
||||
CHECK(delete_if(rr_equal_p, db, ver, name, rdata.type,
|
||||
covers, &rdata, &diff));
|
||||
if (securedb != NULL) {
|
||||
CHECK(delete_if(rr_equal_p, updatedb, updatever,
|
||||
name, rdata.type, covers,
|
||||
&rdata, &securediff));
|
||||
} else {
|
||||
CHECK(delete_if(rr_equal_p, updatedb, updatever,
|
||||
name, rdata.type, covers,
|
||||
&rdata, &diff));
|
||||
}
|
||||
}
|
||||
}
|
||||
if (result != ISC_R_NOMORE) {
|
||||
@@ -3338,8 +3422,15 @@ update_action(isc_task_t *task, isc_event_t *event) {
|
||||
* If they don't then back out all changes to DNSKEY/NSEC3PARAM
|
||||
* records.
|
||||
*/
|
||||
if (!ISC_LIST_EMPTY(diff.tuples)) {
|
||||
CHECK(check_dnssec(client, zone, db, ver, &diff));
|
||||
if (securedb != NULL) {
|
||||
if (!ISC_LIST_EMPTY(securediff.tuples)) {
|
||||
CHECK(check_dnssec(client, zone, securedb, securever,
|
||||
&securediff));
|
||||
}
|
||||
} else {
|
||||
if (!ISC_LIST_EMPTY(diff.tuples)) {
|
||||
CHECK(check_dnssec(client, zone, db, ver, &diff));
|
||||
}
|
||||
}
|
||||
|
||||
if (!ISC_LIST_EMPTY(diff.tuples)) {
|
||||
@@ -3353,26 +3444,34 @@ update_action(isc_task_t *task, isc_event_t *event) {
|
||||
goto failure;
|
||||
}
|
||||
}
|
||||
if (!ISC_LIST_EMPTY(diff.tuples)) {
|
||||
result = dns_zone_cdscheck(zone, db, ver);
|
||||
if (result == DNS_R_BADCDS || result == DNS_R_BADCDNSKEY) {
|
||||
update_log(client, zone, LOGLEVEL_PROTOCOL,
|
||||
"update rejected: bad %s RRset",
|
||||
result == DNS_R_BADCDS ? "CDS" : "CDNSKEY");
|
||||
result = DNS_R_REFUSED;
|
||||
goto failure;
|
||||
|
||||
if (securedb != NULL) {
|
||||
if (!ISC_LIST_EMPTY(securediff.tuples)) {
|
||||
result = dns_zone_cdscheck(zone, securedb, securever);
|
||||
}
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
goto failure;
|
||||
} else {
|
||||
if (!ISC_LIST_EMPTY(diff.tuples)) {
|
||||
result = dns_zone_cdscheck(zone, db, ver);
|
||||
}
|
||||
}
|
||||
if (result == DNS_R_BADCDS || result == DNS_R_BADCDNSKEY) {
|
||||
update_log(client, zone, LOGLEVEL_PROTOCOL,
|
||||
"update rejected: bad %s RRset",
|
||||
result == DNS_R_BADCDS ? "CDS" : "CDNSKEY");
|
||||
result = DNS_R_REFUSED;
|
||||
goto failure;
|
||||
}
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
goto failure;
|
||||
}
|
||||
|
||||
/*
|
||||
* If any changes were made, increment the SOA serial number,
|
||||
* update RRSIGs and NSECs (if zone is secure), and write the update
|
||||
* to the journal.
|
||||
*/
|
||||
if (!ISC_LIST_EMPTY(diff.tuples)) {
|
||||
if (!ISC_LIST_EMPTY(diff.tuples) || !ISC_LIST_EMPTY(securediff.tuples))
|
||||
{
|
||||
char *journalfile;
|
||||
dns_journal_t *journal;
|
||||
bool has_dnskey;
|
||||
@@ -3385,40 +3484,82 @@ update_action(isc_task_t *task, isc_event_t *event) {
|
||||
CHECK(update_soa_serial(
|
||||
db, ver, &diff, mctx,
|
||||
dns_zone_getserialupdatemethod(zone)));
|
||||
|
||||
if (securedb != NULL) {
|
||||
CHECK(update_soa_serial(
|
||||
securedb, securever, &securediff, mctx,
|
||||
dns_zone_getserialupdatemethod(
|
||||
securezone)));
|
||||
}
|
||||
}
|
||||
|
||||
CHECK(check_mx(client, zone, db, ver, &diff));
|
||||
|
||||
CHECK(remove_orphaned_ds(db, ver, &diff));
|
||||
|
||||
CHECK(rrset_exists(db, ver, zonename, dns_rdatatype_dnskey, 0,
|
||||
&has_dnskey));
|
||||
if (securedb != NULL) {
|
||||
CHECK(rrset_exists(securedb, securever, zonename,
|
||||
dns_rdatatype_dnskey, 0,
|
||||
&has_dnskey));
|
||||
} else {
|
||||
CHECK(rrset_exists(db, ver, zonename,
|
||||
dns_rdatatype_dnskey, 0,
|
||||
&has_dnskey));
|
||||
}
|
||||
|
||||
#define ALLOW_SECURE_TO_INSECURE(zone) \
|
||||
((dns_zone_getoptions(zone) & DNS_ZONEOPT_SECURETOINSECURE) != 0)
|
||||
|
||||
CHECK(rrset_exists(db, oldver, zonename, dns_rdatatype_dnskey,
|
||||
0, &had_dnskey));
|
||||
if (!ALLOW_SECURE_TO_INSECURE(zone)) {
|
||||
if (had_dnskey && !has_dnskey) {
|
||||
update_log(client, zone, LOGLEVEL_PROTOCOL,
|
||||
"update rejected: all DNSKEY "
|
||||
"records removed and "
|
||||
"'dnssec-secure-to-insecure' "
|
||||
"not set");
|
||||
result = DNS_R_REFUSED;
|
||||
goto failure;
|
||||
if (securedb != NULL) {
|
||||
CHECK(rrset_exists(securedb, secureoldver, zonename,
|
||||
dns_rdatatype_dnskey, 0,
|
||||
&had_dnskey));
|
||||
if (!ALLOW_SECURE_TO_INSECURE(zone)) {
|
||||
if (had_dnskey && !has_dnskey) {
|
||||
update_log(
|
||||
client, securezone,
|
||||
LOGLEVEL_PROTOCOL,
|
||||
"update rejected: all DNSKEY "
|
||||
"records removed and "
|
||||
"'dnssec-secure-to-insecure' "
|
||||
"not set");
|
||||
result = DNS_R_REFUSED;
|
||||
goto failure;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
CHECK(rrset_exists(db, oldver, zonename,
|
||||
dns_rdatatype_dnskey, 0,
|
||||
&had_dnskey));
|
||||
if (!ALLOW_SECURE_TO_INSECURE(zone)) {
|
||||
if (had_dnskey && !has_dnskey) {
|
||||
update_log(
|
||||
client, zone, LOGLEVEL_PROTOCOL,
|
||||
"update rejected: all DNSKEY "
|
||||
"records removed and "
|
||||
"'dnssec-secure-to-insecure' "
|
||||
"not set");
|
||||
result = DNS_R_REFUSED;
|
||||
goto failure;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CHECK(rollback_private(db, privatetype, ver, &diff));
|
||||
|
||||
if (!dns_zone_israw(zone)) {
|
||||
if (securedb != NULL) {
|
||||
CHECK(rollback_private(securedb, privatetype, securever,
|
||||
&securediff));
|
||||
CHECK(add_signing_records(securedb, privatetype,
|
||||
securever, &securediff));
|
||||
CHECK(add_nsec3param_records(client, securezone,
|
||||
securedb, securever,
|
||||
&securediff));
|
||||
} else {
|
||||
CHECK(rollback_private(db, privatetype, ver, &diff));
|
||||
CHECK(add_signing_records(db, privatetype, ver, &diff));
|
||||
CHECK(add_nsec3param_records(client, zone, updatedb,
|
||||
ver, &diff));
|
||||
}
|
||||
|
||||
CHECK(add_nsec3param_records(client, zone, db, ver, &diff));
|
||||
|
||||
if (had_dnskey && !has_dnskey) {
|
||||
/*
|
||||
* We are transitioning from secure to insecure.
|
||||
@@ -3426,12 +3567,36 @@ update_action(isc_task_t *task, isc_event_t *event) {
|
||||
* the last signature for the DNSKEY records are
|
||||
* remove any NSEC chain present will also be removed.
|
||||
*/
|
||||
CHECK(dns_nsec3param_deletechains(db, ver, zone, true,
|
||||
&diff));
|
||||
} else if (!dns_zone_israw(zone) && has_dnskey &&
|
||||
isdnssec(db, ver, privatetype))
|
||||
if (securedb != NULL) {
|
||||
CHECK(dns_nsec3param_deletechains(
|
||||
securedb, securever, securezone, true,
|
||||
&securediff));
|
||||
} else {
|
||||
CHECK(dns_nsec3param_deletechains(db, ver, zone,
|
||||
true, &diff));
|
||||
}
|
||||
} else if (securezone != NULL && has_dnskey &&
|
||||
isdnssec(securedb, securever, privatetype))
|
||||
{
|
||||
dns_update_log_t log;
|
||||
uint32_t interval =
|
||||
dns_zone_getsigvalidityinterval(securezone);
|
||||
|
||||
log.func = update_log_cb;
|
||||
log.arg = client;
|
||||
result = dns_update_signatures(
|
||||
&log, securezone, securedb, secureoldver,
|
||||
securever, &securediff, interval);
|
||||
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
update_log(client, securezone, ISC_LOG_ERROR,
|
||||
"RRSIG/NSEC/NSEC3 update failed: %s",
|
||||
isc_result_totext(result));
|
||||
goto failure;
|
||||
}
|
||||
} else if (zone != NULL && has_dnskey &&
|
||||
isdnssec(db, ver, privatetype)) {
|
||||
dns_update_log_t log;
|
||||
uint32_t interval =
|
||||
dns_zone_getsigvalidityinterval(zone);
|
||||
|
||||
@@ -3448,11 +3613,24 @@ update_action(isc_task_t *task, isc_event_t *event) {
|
||||
}
|
||||
}
|
||||
|
||||
maxrecords = dns_zone_getmaxrecords(zone);
|
||||
if (securezone != NULL) {
|
||||
updatezone = securezone;
|
||||
updatedb = securedb;
|
||||
updatever = securever;
|
||||
} else {
|
||||
updatezone = zone;
|
||||
updatedb = db;
|
||||
updatever = ver;
|
||||
rawzone_done = true;
|
||||
}
|
||||
|
||||
apply_update:
|
||||
maxrecords = dns_zone_getmaxrecords(updatezone);
|
||||
if (maxrecords != 0U) {
|
||||
result = dns_db_getsize(db, ver, &records, NULL);
|
||||
result = dns_db_getsize(updatedb, updatever, &records,
|
||||
NULL);
|
||||
if (result == ISC_R_SUCCESS && records > maxrecords) {
|
||||
update_log(client, zone, ISC_LOG_ERROR,
|
||||
update_log(client, updatezone, ISC_LOG_ERROR,
|
||||
"records in zone (%" PRIu64 ") "
|
||||
"exceeds"
|
||||
" max-"
|
||||
@@ -3464,9 +3642,9 @@ update_action(isc_task_t *task, isc_event_t *event) {
|
||||
}
|
||||
}
|
||||
|
||||
journalfile = dns_zone_getjournal(zone);
|
||||
journalfile = dns_zone_getjournal(updatezone);
|
||||
if (journalfile != NULL) {
|
||||
update_log(client, zone, LOGLEVEL_DEBUG,
|
||||
update_log(client, updatezone, LOGLEVEL_DEBUG,
|
||||
"writing journal %s", journalfile);
|
||||
|
||||
journal = NULL;
|
||||
@@ -3476,7 +3654,13 @@ update_action(isc_task_t *task, isc_event_t *event) {
|
||||
FAILS(result, "journal open failed");
|
||||
}
|
||||
|
||||
result = dns_journal_write_transaction(journal, &diff);
|
||||
if (rawzone_done) {
|
||||
result = dns_journal_write_transaction(journal,
|
||||
&diff);
|
||||
} else {
|
||||
result = dns_journal_write_transaction(
|
||||
journal, &securediff);
|
||||
}
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
dns_journal_destroy(&journal);
|
||||
FAILS(result, "journal write failed");
|
||||
@@ -3490,20 +3674,25 @@ update_action(isc_task_t *task, isc_event_t *event) {
|
||||
* to change to handle databases that need two-phase
|
||||
* commit, but this isn't a priority.
|
||||
*/
|
||||
update_log(client, zone, LOGLEVEL_DEBUG,
|
||||
update_log(client, updatezone, LOGLEVEL_DEBUG,
|
||||
"committing update transaction");
|
||||
|
||||
dns_db_closeversion(db, &ver, true);
|
||||
dns_db_closeversion(updatedb, &updatever, true);
|
||||
if (rawzone_done) {
|
||||
ver = NULL;
|
||||
} else {
|
||||
securever = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Mark the zone as dirty so that it will be written to disk.
|
||||
*/
|
||||
dns_zone_markdirty(zone);
|
||||
dns_zone_markdirty(updatezone);
|
||||
|
||||
/*
|
||||
* Notify secondaries of the change we just made.
|
||||
*/
|
||||
dns_zone_notify(zone);
|
||||
dns_zone_notify(updatezone);
|
||||
|
||||
/*
|
||||
* Cause the zone to be signed with the key that we
|
||||
@@ -3512,76 +3701,134 @@ update_action(isc_task_t *task, isc_event_t *event) {
|
||||
*
|
||||
* Note: we are already committed to this course of action.
|
||||
*/
|
||||
for (tuple = ISC_LIST_HEAD(diff.tuples); tuple != NULL;
|
||||
tuple = ISC_LIST_NEXT(tuple, link))
|
||||
{
|
||||
isc_region_t r;
|
||||
dns_secalg_t algorithm;
|
||||
uint16_t keyid;
|
||||
|
||||
if (tuple->rdata.type != dns_rdatatype_dnskey) {
|
||||
continue;
|
||||
}
|
||||
|
||||
dns_rdata_tostruct(&tuple->rdata, &dnskey, NULL);
|
||||
if ((dnskey.flags &
|
||||
(DNS_KEYFLAG_OWNERMASK | DNS_KEYTYPE_NOAUTH)) !=
|
||||
DNS_KEYOWNER_ZONE)
|
||||
if (rawzone_done) {
|
||||
for (tuple = ISC_LIST_HEAD(diff.tuples); tuple != NULL;
|
||||
tuple = ISC_LIST_NEXT(tuple, link))
|
||||
{
|
||||
continue;
|
||||
isc_region_t r;
|
||||
dns_secalg_t algorithm;
|
||||
uint16_t keyid;
|
||||
|
||||
if (tuple->rdata.type != dns_rdatatype_dnskey) {
|
||||
continue;
|
||||
}
|
||||
|
||||
dns_rdata_tostruct(&tuple->rdata, &dnskey,
|
||||
NULL);
|
||||
if ((dnskey.flags & (DNS_KEYFLAG_OWNERMASK |
|
||||
DNS_KEYTYPE_NOAUTH)) !=
|
||||
DNS_KEYOWNER_ZONE)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
dns_rdata_toregion(&tuple->rdata, &r);
|
||||
algorithm = dnskey.algorithm;
|
||||
keyid = dst_region_computeid(&r);
|
||||
|
||||
result = dns_zone_signwithkey(
|
||||
updatezone, algorithm, keyid,
|
||||
(tuple->op == DNS_DIFFOP_DEL));
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
update_log(client, updatezone,
|
||||
ISC_LOG_ERROR,
|
||||
"dns_zone_signwithkey "
|
||||
"failed: %s",
|
||||
isc_result_totext(result));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (tuple = ISC_LIST_HEAD(securediff.tuples);
|
||||
tuple != NULL; tuple = ISC_LIST_NEXT(tuple, link))
|
||||
{
|
||||
isc_region_t r;
|
||||
dns_secalg_t algorithm;
|
||||
uint16_t keyid;
|
||||
|
||||
if (tuple->rdata.type != dns_rdatatype_dnskey) {
|
||||
continue;
|
||||
}
|
||||
|
||||
dns_rdata_tostruct(&tuple->rdata, &dnskey,
|
||||
NULL);
|
||||
if ((dnskey.flags & (DNS_KEYFLAG_OWNERMASK |
|
||||
DNS_KEYTYPE_NOAUTH)) !=
|
||||
DNS_KEYOWNER_ZONE)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
dns_rdata_toregion(&tuple->rdata, &r);
|
||||
algorithm = dnskey.algorithm;
|
||||
keyid = dst_region_computeid(&r);
|
||||
|
||||
result = dns_zone_signwithkey(
|
||||
updatezone, algorithm, keyid,
|
||||
(tuple->op == DNS_DIFFOP_DEL));
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
update_log(client, updatezone,
|
||||
ISC_LOG_ERROR,
|
||||
"dns_zone_signwithkey "
|
||||
"failed: %s",
|
||||
isc_result_totext(result));
|
||||
}
|
||||
}
|
||||
|
||||
dns_rdata_toregion(&tuple->rdata, &r);
|
||||
algorithm = dnskey.algorithm;
|
||||
keyid = dst_region_computeid(&r);
|
||||
/*
|
||||
* Cause the zone to add/delete NSEC3 chains for the
|
||||
* deferred NSEC3PARAM changes.
|
||||
*
|
||||
* Note: we are already committed to this course of
|
||||
* action.
|
||||
*/
|
||||
for (tuple = ISC_LIST_HEAD(securediff.tuples);
|
||||
tuple != NULL; tuple = ISC_LIST_NEXT(tuple, link))
|
||||
{
|
||||
unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE];
|
||||
dns_rdata_t rdata = DNS_RDATA_INIT;
|
||||
dns_rdata_nsec3param_t nsec3param;
|
||||
|
||||
result = dns_zone_signwithkey(
|
||||
zone, algorithm, keyid,
|
||||
(tuple->op == DNS_DIFFOP_DEL));
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
update_log(client, zone, ISC_LOG_ERROR,
|
||||
"dns_zone_signwithkey failed: %s",
|
||||
isc_result_totext(result));
|
||||
if (tuple->rdata.type != privatetype ||
|
||||
tuple->op != DNS_DIFFOP_ADD) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!dns_nsec3param_fromprivate(&tuple->rdata,
|
||||
&rdata, buf,
|
||||
sizeof(buf))) {
|
||||
continue;
|
||||
}
|
||||
dns_rdata_tostruct(&rdata, &nsec3param, NULL);
|
||||
if (nsec3param.flags == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
result = dns_zone_addnsec3chain(updatezone,
|
||||
&nsec3param);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
update_log(client, updatezone,
|
||||
ISC_LOG_ERROR,
|
||||
"dns_zone_addnsec3chain "
|
||||
"failed: %s",
|
||||
isc_result_totext(result));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Cause the zone to add/delete NSEC3 chains for the
|
||||
* deferred NSEC3PARAM changes.
|
||||
*
|
||||
* Note: we are already committed to this course of action.
|
||||
*/
|
||||
for (tuple = ISC_LIST_HEAD(diff.tuples); tuple != NULL;
|
||||
tuple = ISC_LIST_NEXT(tuple, link))
|
||||
{
|
||||
unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE];
|
||||
dns_rdata_t rdata = DNS_RDATA_INIT;
|
||||
dns_rdata_nsec3param_t nsec3param;
|
||||
|
||||
if (tuple->rdata.type != privatetype ||
|
||||
tuple->op != DNS_DIFFOP_ADD) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!dns_nsec3param_fromprivate(&tuple->rdata, &rdata,
|
||||
buf, sizeof(buf))) {
|
||||
continue;
|
||||
}
|
||||
dns_rdata_tostruct(&rdata, &nsec3param, NULL);
|
||||
if (nsec3param.flags == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
result = dns_zone_addnsec3chain(zone, &nsec3param);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
update_log(client, zone, ISC_LOG_ERROR,
|
||||
"dns_zone_addnsec3chain failed: %s",
|
||||
isc_result_totext(result));
|
||||
}
|
||||
if (!rawzone_done) {
|
||||
updatezone = zone;
|
||||
updatedb = db;
|
||||
updatever = ver;
|
||||
rawzone_done = true;
|
||||
goto apply_update;
|
||||
}
|
||||
|
||||
} else {
|
||||
update_log(client, zone, LOGLEVEL_DEBUG, "redundant request");
|
||||
dns_db_closeversion(db, &ver, true);
|
||||
if (securedb != NULL) {
|
||||
dns_db_closeversion(securedb, &securever, true);
|
||||
}
|
||||
}
|
||||
result = ISC_R_SUCCESS;
|
||||
goto common;
|
||||
@@ -3594,6 +3841,10 @@ failure:
|
||||
update_log(client, zone, LOGLEVEL_DEBUG, "rolling back");
|
||||
dns_db_closeversion(db, &ver, false);
|
||||
}
|
||||
if (securever != NULL) {
|
||||
update_log(client, securezone, LOGLEVEL_DEBUG, "rolling back");
|
||||
dns_db_closeversion(securedb, &securever, false);
|
||||
}
|
||||
|
||||
common:
|
||||
dns_diff_clear(&temp);
|
||||
@@ -3602,10 +3853,16 @@ common:
|
||||
if (oldver != NULL) {
|
||||
dns_db_closeversion(db, &oldver, false);
|
||||
}
|
||||
if (secureoldver != NULL) {
|
||||
dns_db_closeversion(securedb, &secureoldver, false);
|
||||
}
|
||||
|
||||
if (db != NULL) {
|
||||
dns_db_detach(&db);
|
||||
}
|
||||
if (securedb != NULL) {
|
||||
dns_db_detach(&securedb);
|
||||
}
|
||||
|
||||
if (rules != NULL) {
|
||||
isc_mem_put(mctx, rules, sizeof(*rules) * ruleslen);
|
||||
@@ -3626,6 +3883,7 @@ common:
|
||||
isc_task_send(client->manager->task, &event);
|
||||
|
||||
INSIST(ver == NULL);
|
||||
INSIST(securever == NULL);
|
||||
INSIST(event == NULL);
|
||||
}
|
||||
|
||||
@@ -3653,6 +3911,11 @@ updatedone_action(isc_task_t *task, isc_event_t *event) {
|
||||
break;
|
||||
}
|
||||
if (uev->zone != NULL) {
|
||||
dns_zone_t *secure = NULL;
|
||||
if (dns_zone_israw(uev->zone)) {
|
||||
dns_zone_getsecure(uev->zone, &secure);
|
||||
dns_zone_detach(&secure);
|
||||
}
|
||||
dns_zone_detach(&uev->zone);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user