Hello, This patch set allows you to change DNSSEC zone configuration at run-time.
-- Petr^2 Spacek
From 080f922b0920105def25f19c28da1d448406ccce Mon Sep 17 00:00:00 2001 From: Petr Spacek <[email protected]> Date: Wed, 4 Jun 2014 21:25:15 +0200 Subject: [PATCH] Delete old database & journal files during zone loading. This prevents inline-signed zones from failing to receive updates from LDAP mysteriously. https://fedorahosted.org/bind-dyndb-ldap/ticket/56 Signed-off-by: Petr Spacek <[email protected]> --- src/ldap_helper.c | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/src/ldap_helper.c b/src/ldap_helper.c index 2eb9c4d63d05486799b90ce4d23cf3fb26c6ca17..3a0ac6ddea237fcd74c146bad7400b516422ff27 100644 --- a/src/ldap_helper.c +++ b/src/ldap_helper.c @@ -782,12 +782,14 @@ delete_bind_zone(dns_zt_t *zt, dns_zone_t **zonep) { return result; } -isc_result_t +static isc_result_t ATTR_NONNULLS cleanup_zone_files(dns_zone_t *zone) { isc_result_t result; isc_boolean_t failure = ISC_FALSE; const char *filename = NULL; dns_zone_t *raw = NULL; + int namelen; + char bck_filename[PATH_MAX]; dns_zone_getraw(zone, &raw); if (raw != NULL) { @@ -804,6 +806,17 @@ cleanup_zone_files(dns_zone_t *zone) { result = fs_file_remove(filename); failure = failure || (result != ISC_R_SUCCESS); + /* Taken from dns_journal_open() from bind-9.9.4-P2: + * Journal backup file name ends with ".jbk" instead of ".jnl". */ + namelen = strlen(filename); + if (namelen > 4 && strcmp(filename + namelen - 4, ".jnl") == 0) + namelen -= 4; + CHECK(isc_string_printf(bck_filename, sizeof(bck_filename), + "%.*s.jbk", namelen, filename)); + CHECK(fs_file_remove(bck_filename)); + +cleanup: + failure = failure || (result != ISC_R_SUCCESS); if (failure == ISC_TRUE) dns_zone_log(zone, ISC_LOG_ERROR, "unable to remove files, expect problems"); @@ -946,6 +959,7 @@ create_zone(ldap_instance_t * const inst, const char * const dn, if (want_secure == ISC_FALSE) { CHECK(dns_zonemgr_managezone(inst->zmgr, raw)); + CHECK(cleanup_zone_files(raw)); } else { CHECK(dns_zone_create(&secure, inst->mctx)); CHECK(dns_zone_setorigin(secure, name)); @@ -957,6 +971,7 @@ create_zone(ldap_instance_t * const inst, const char * const dn, CHECK(dns_zone_link(secure, raw)); dns_zone_rekey(secure, ISC_TRUE); CHECK(configure_paths(inst->mctx, inst, secure, ISC_TRUE)); + CHECK(cleanup_zone_files(secure)); } sync_state_get(inst->sctx, &sync_state); -- 1.9.3
From d89284fc0aafe001e5ce1599d04dac62f48ad108 Mon Sep 17 00:00:00 2001 From: Petr Spacek <[email protected]> Date: Wed, 4 Jun 2014 22:39:46 +0200 Subject: [PATCH] Support run-time changes in idnsSecInlineSigning attribute. https://fedorahosted.org/bind-dyndb-ldap/ticket/56 Signed-off-by: Petr Spacek <[email protected]> --- src/ldap_helper.c | 92 +++++++++++++++++++++++++++++++++++++++++------------ src/zone_register.c | 24 ++++++++------ src/zone_register.h | 7 ++-- 3 files changed, 91 insertions(+), 32 deletions(-) diff --git a/src/ldap_helper.c b/src/ldap_helper.c index 3a0ac6ddea237fcd74c146bad7400b516422ff27..deda6955a215441a40857d78273fb8042275385e 100644 --- a/src/ldap_helper.c +++ b/src/ldap_helper.c @@ -293,6 +293,11 @@ static isc_result_t parse_rdata(isc_mem_t *mctx, ldap_entry_t *entry, dns_name_t *origin, const char *rdata_text, dns_rdata_t **rdatap) ATTR_NONNULLS ATTR_CHECKRESULT; static isc_result_t +ldap_parse_master_zoneentry(ldap_entry_t * const entry, dns_db_t * const olddb, + ldap_instance_t *const inst, + isc_task_t *const task) + ATTR_NONNULL(1,3,4) ATTR_CHECKRESULT; +static isc_result_t ldap_parse_rrentry(isc_mem_t *mctx, ldap_entry_t *entry, dns_name_t *origin, const char *fake_mname, ldapdb_rdatalist_t *rdatalist) ATTR_NONNULLS ATTR_CHECKRESULT; @@ -926,8 +931,9 @@ cleanup: */ static isc_result_t ATTR_NONNULLS ATTR_CHECKRESULT create_zone(ldap_instance_t * const inst, const char * const dn, - dns_name_t * const name, const isc_boolean_t want_secure, - dns_zone_t ** const rawp, dns_zone_t ** const securep) + dns_name_t * const name, dns_db_t * const ldapdb, + const isc_boolean_t want_secure, dns_zone_t ** const rawp, + dns_zone_t ** const securep) { isc_result_t result; dns_zone_t *raw = NULL; @@ -987,7 +993,7 @@ create_zone(ldap_instance_t * const inst, const char * const dn, } } - CHECK(zr_add_zone(inst->zone_register, raw, secure, dn)); + CHECK(zr_add_zone(inst->zone_register, ldapdb, raw, secure, dn)); *rawp = raw; *securep = secure; @@ -2192,11 +2198,6 @@ zone_sync_apex(const ldap_instance_t * const inst, * => do nothing. */ } - /* New zone has to have at least SOA record and NS record. */ - if (new_zone == ISC_TRUE - && (*data_changed == ISC_FALSE || soa_tuple == NULL)) - result = DNS_R_BADZONE; - cleanup: if (soa_tuple_alloc == ISC_TRUE && soa_tuple != NULL) dns_difftuple_free(&soa_tuple); @@ -2208,10 +2209,54 @@ cleanup: return result; } -/* Parse the master zone entry */ +/** + * Change security status of an existing zone. + * + * LDAP database is detached from the original zone, the zone is deleted + * and re-created with different parameters on top of the old LDAP database. + */ static isc_result_t ATTR_NONNULLS ATTR_CHECKRESULT -ldap_parse_master_zoneentry(ldap_entry_t *entry, ldap_instance_t *inst, - isc_task_t *task) +zone_security_change(ldap_entry_t * const entry, dns_name_t * const name, + ldap_instance_t * const inst, isc_task_t * const task) { + isc_result_t result; + dns_db_t *olddb = NULL; + isc_result_t lock_state = ISC_R_IGNORE; + + CHECK(zr_get_zone_dbs(inst->zone_register, name, &olddb, NULL)); + + /* Lock is necessary to ensure that no events from LDAP are lost + * in period where old zone was deleted but the new zone was not + * created yet. */ + run_exclusive_enter(task, &lock_state); + CHECK(ldap_delete_zone2(inst, name, ISC_FALSE, ISC_TRUE)); + CHECK(ldap_parse_master_zoneentry(entry, olddb, inst, task)); + +cleanup: + run_exclusive_exit(task, lock_state); + if (olddb != NULL) + dns_db_detach(&olddb); + return result; +} + +/** + * Parse the master zone entry and configure DNS zone accordingly. + * New zone will be created if it doesn't exist. Existing zone will be + * updated with new settings from LDAP entry. + * + * This function also synchronizes data at zone apex and ensures + * that zone serial is incremented after each change. + * + * @param olddb[in] LDAP database to be used when constructing a new zone. + * Empty database will be created if it is NULL. + * It should be non-NULL only if reconfiguration of + * an existing zone is not possible so the old zone + * was deleted but the new zone should re-use the old + * database. + */ +static isc_result_t +ldap_parse_master_zoneentry(ldap_entry_t * const entry, dns_db_t * const olddb, + ldap_instance_t * const inst, + isc_task_t * const task) { const char *dn; ldap_valuelist_t values; @@ -2279,18 +2324,24 @@ ldap_parse_master_zoneentry(ldap_entry_t *entry, ldap_instance_t *inst, /* Check if we are already serving given zone */ result = zr_get_zone_ptr(inst->zone_register, &name, &raw, &secure); if (result == ISC_R_NOTFOUND || result == DNS_R_PARTIALMATCH) { - CHECK(create_zone(inst, dn, &name, want_secure, &raw, &secure)); + CHECK(create_zone(inst, dn, &name, olddb, want_secure, + &raw, &secure)); new_zone = ISC_TRUE; log_debug(2, "created zone %s: raw %p; secure %p", dn, raw, secure); } else if (result != ISC_R_SUCCESS) goto cleanup; - else { - if (want_secure != ISC_TF(secure != NULL)) { - log_error("zone '%s': inline-signing setting cannot " - "be changed at run-time yet", dn); - CLEANUP_WITH(ISC_R_NOTIMPLEMENTED); - } + else if (want_secure != ISC_TF(secure != NULL)) { + if (want_secure == ISC_TRUE) + dns_zone_log(raw, ISC_LOG_INFO, + "upgrading zone to secure"); + else + dns_zone_log(secure, ISC_LOG_INFO, + "downgrading zone to insecure"); + CHECK(zone_security_change(entry, &name, inst, task)); + goto cleanup; + } else { /* Zone exists and it's security status is unchanged. */ + INSIST(olddb == NULL); } CHECK(zr_get_zone_settings(inst->zone_register, &name, &zone_settings)); @@ -2342,7 +2393,7 @@ ldap_parse_master_zoneentry(ldap_entry_t *entry, ldap_instance_t *inst, CHECK(publish_zone(task, inst, toview)); configured = ISC_TRUE; } - if (data_changed == ISC_TRUE) + if (data_changed == ISC_TRUE || olddb != NULL) CHECK(load_zone(toview)); } @@ -4174,7 +4225,8 @@ update_zone(isc_task_t *task, isc_event_t *event) if (zone_active) { CHECK(ldap_entry_getclass(entry, &objclass)); if (objclass & LDAP_ENTRYCLASS_MASTER) - CHECK(ldap_parse_master_zoneentry(entry, inst, task)); + CHECK(ldap_parse_master_zoneentry(entry, NULL, inst, + task)); else if (objclass & LDAP_ENTRYCLASS_FORWARD) CHECK(ldap_parse_fwd_zoneentry(entry, inst)); diff --git a/src/zone_register.c b/src/zone_register.c index 1d8d8fa5b3bde92d1f6190a086fee748cd00d221..d3712fdc91b4c67f7c38f53531187da788e06750 100644 --- a/src/zone_register.c +++ b/src/zone_register.c @@ -232,11 +232,11 @@ cleanup: * Create a new zone info structure. */ #define PRINT_BUFF_SIZE 255 -static isc_result_t ATTR_NONNULL(1,2,4,5,6,7) +static isc_result_t ATTR_NONNULL(1,2,4,5,6,8) create_zone_info(isc_mem_t * const mctx, dns_zone_t * const raw, dns_zone_t * const secure, const char * const dn, settings_set_t *global_settings, const char *db_name, - zone_info_t **zinfop) + dns_db_t * const ldapdb, zone_info_t **zinfop) { isc_result_t result; zone_info_t *zinfo; @@ -268,10 +268,15 @@ create_zone_info(isc_mem_t * const mctx, dns_zone_t * const raw, "keys/", &zone_dir)); CHECK(fs_dirs_create(str_buf(zone_dir))); - DE_CONST(db_name, argv[0]); - CHECK(ldapdb_create(mctx, dns_zone_getorigin(raw), LDAP_DB_TYPE, - LDAP_DB_RDATACLASS, sizeof(argv)/sizeof(argv[0]), - argv, NULL, &zinfo->ldapdb)); + if (ldapdb == NULL) { /* create new empty database */ + DE_CONST(db_name, argv[0]); + CHECK(ldapdb_create(mctx, dns_zone_getorigin(raw), + LDAP_DB_TYPE, LDAP_DB_RDATACLASS, + sizeof(argv)/sizeof(argv[0]), + argv, NULL, &zinfo->ldapdb)); + } else { /* re-use existing database */ + dns_db_attach(ldapdb, &zinfo->ldapdb); + } cleanup: if (result == ISC_R_SUCCESS) @@ -313,8 +318,9 @@ delete_zone_info(void *arg1, void *arg2) * must be absolute and the zone cannot already be in the zone register. */ isc_result_t -zr_add_zone(zone_register_t * const zr, dns_zone_t * const raw, - dns_zone_t * const secure, const char * const dn) +zr_add_zone(zone_register_t * const zr, dns_db_t * const ldapdb, + dns_zone_t * const raw, dns_zone_t * const secure, + const char * const dn) { isc_result_t result; dns_name_t *name; @@ -346,7 +352,7 @@ zr_add_zone(zone_register_t * const zr, dns_zone_t * const raw, } CHECK(create_zone_info(zr->mctx, raw, secure, dn, zr->global_settings, - ldap_instance_getdbname(zr->ldap_inst), + ldap_instance_getdbname(zr->ldap_inst), ldapdb, &new_zinfo)); CHECK(dns_rbt_addname(zr->rbt, name, new_zinfo)); diff --git a/src/zone_register.h b/src/zone_register.h index 8d331e1f15bf278c6dfcc18e402c11eadf6d8c51..5483338efaf180f40cb79ff65543e9fae2ed021b 100644 --- a/src/zone_register.h +++ b/src/zone_register.h @@ -33,9 +33,10 @@ void zr_destroy(zone_register_t **zrp) ATTR_NONNULLS; isc_result_t -zr_add_zone(zone_register_t * const zr, dns_zone_t * const raw, - dns_zone_t * const secure, const char * const dn) - ATTR_NONNULL(1,2,4) ATTR_CHECKRESULT; +zr_add_zone(zone_register_t * const zr, dns_db_t * const ldapdb, + dns_zone_t * const raw, dns_zone_t * const secure, + const char * const dn) + ATTR_NONNULL(1,3,5) ATTR_CHECKRESULT; isc_result_t zr_del_zone(zone_register_t *zr, dns_name_t *origin) ATTR_NONNULLS ATTR_CHECKRESULT; -- 1.9.3
_______________________________________________ Freeipa-devel mailing list [email protected] https://www.redhat.com/mailman/listinfo/freeipa-devel
