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 <pspa...@redhat.com>
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 <pspa...@redhat.com>
---
 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 <pspa...@redhat.com>
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 <pspa...@redhat.com>
---
 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
Freeipa-devel@redhat.com
https://www.redhat.com/mailman/listinfo/freeipa-devel

Reply via email to