Hello,

Fix crash triggered by zone objects with unexpected DN.

https://fedorahosted.org/bind-dyndb-ldap/ticket/148

-- 
Petr^2 Spacek
From d9e2bd9a838882706ca95d60eefd459a95ae7579 Mon Sep 17 00:00:00 2001
From: Petr Spacek <pspa...@redhat.com>
Date: Tue, 16 Dec 2014 16:31:16 +0100
Subject: [PATCH] Fix crash triggered by zone objects with unexpected DN.

https://fedorahosted.org/bind-dyndb-ldap/ticket/148
---
 src/ldap_convert.c | 24 ++++++++++++++++++++++++
 src/ldap_convert.h |  4 ++++
 src/ldap_helper.c  | 12 ++++++------
 3 files changed, 34 insertions(+), 6 deletions(-)

diff --git a/src/ldap_convert.c b/src/ldap_convert.c
index b51d402492415d6630a42435b823925c8246a06f..6db90375ca1465208d6cce8772637ddc20a7e48e 100644
--- a/src/ldap_convert.c
+++ b/src/ldap_convert.c
@@ -193,6 +193,30 @@ cleanup:
 }
 
 /**
+ * Evaluate if DN has/does not have expected format with one or two components
+ * and error out if a mismatch is detected.
+ *
+ * @param[in] prefix     Prefix for error messages, usually a function name.
+ * @param[in] dn
+ * @param[in] dniszone   Boolean returned by dn_to_dnsname for given DN.
+ * @param[in] wantszone  ISC_TRUE if DN should be a zone, ISC_FALSE otherwise.
+ * @retval ISC_R_SUCCESS or ISC_R_UNEXPECTED if values do not match.
+ */
+isc_result_t
+dn_want_zone(const char * const prefix, const char * const dn,
+	     isc_boolean_t dniszone, isc_boolean_t wantszone) {
+	if (dniszone != wantszone) {
+		log_error("%s: object '%s' should%s be a zone but DN format "
+			  "suggests that it is%s a zone",
+			  prefix, dn, wantszone ? "" : " not",
+			  dniszone ? "" : " not");
+		return ISC_R_UNEXPECTED;
+	}
+
+	return ISC_R_SUCCESS;
+}
+
+/**
  * WARNING! This function is used to mangle input from network
  *          and it is security sensitive.
  *
diff --git a/src/ldap_convert.h b/src/ldap_convert.h
index f0b09262dbbe588c5c12b074242a9f7db4361880..21107307fc614c7af43b02ff50f9c60bacd224dd 100644
--- a/src/ldap_convert.h
+++ b/src/ldap_convert.h
@@ -42,6 +42,10 @@ isc_result_t dn_to_dnsname(isc_mem_t *mctx, const char *dn,
 			   isc_boolean_t *iszone)
 			   ATTR_NONNULL(1, 2, 3) ATTR_CHECKRESULT;
 
+isc_result_t
+dn_want_zone(const char * const func, const char * const dn,
+		    isc_boolean_t dniszone, isc_boolean_t wantszone);
+
 isc_result_t dnsname_to_dn(zone_register_t *zr, dns_name_t *name, dns_name_t *zone,
 			   ld_string_t *target) ATTR_NONNULLS ATTR_CHECKRESULT;
 
diff --git a/src/ldap_helper.c b/src/ldap_helper.c
index 9427dfbee800bacf3960c623ede2a10a7bc988cb..26630be2183cfb0257e5adfd06952a6dc1ab1eee 100644
--- a/src/ldap_helper.c
+++ b/src/ldap_helper.c
@@ -1407,9 +1407,9 @@ ldap_delete_zone(ldap_instance_t *inst, const char *dn, isc_boolean_t lock,
 	isc_boolean_t iszone;
 	dns_name_t name;
 	dns_name_init(&name, NULL);
-	
+
 	CHECK(dn_to_dnsname(inst->mctx, dn, &name, NULL, &iszone));
-	INSIST(iszone == ISC_TRUE);
+	CHECK(dn_want_zone(__func__, dn, iszone, ISC_TRUE));
 
 	result = ldap_delete_zone2(inst, &name, lock, preserve_forwarding);
 
@@ -1794,7 +1794,7 @@ ldap_parse_fwd_zoneentry(ldap_entry_t *entry, ldap_instance_t *inst)
 	/* Derive the DNS name of the zone from the DN. */
 	dn = entry->dn;
 	CHECK(dn_to_dnsname(inst->mctx, dn, &name, NULL, &iszone));
-	INSIST(iszone == ISC_TRUE);
+	CHECK(dn_want_zone(__func__, dn, iszone, ISC_TRUE));
 
 	CHECK(ldap_entry_getvalues(entry, "idnsZoneActive", &values));
 	if (HEAD(values) != NULL &&
@@ -2445,7 +2445,7 @@ ldap_parse_master_zoneentry(ldap_entry_t * const entry, dns_db_t * const olddb,
 	/* Derive the dns name of the zone from the DN. */
 	dn = entry->dn;
 	CHECK(dn_to_dnsname(inst->mctx, dn, &name, NULL, &iszone));
-	INSIST(iszone == ISC_TRUE);
+	CHECK(dn_want_zone(__func__, dn, iszone, ISC_TRUE));
 
 	run_exclusive_enter(inst, &lock_state);
 
@@ -4422,7 +4422,7 @@ update_zone(isc_task_t *task, isc_event_t *event)
 	CHECK(manager_get_ldap_instance(pevent->dbname, &inst));
 	INSIST(task == inst->task); /* For task-exclusive mode */
 	CHECK(dn_to_dnsname(inst->mctx, pevent->dn, &currname, NULL, &iszone));
-	INSIST(iszone == ISC_TRUE);
+	CHECK(dn_want_zone(__func__, pevent->dn, iszone, ISC_TRUE));
 
 	if (SYNCREPL_DEL(pevent->chgtype)) {
 		CHECK(ldap_delete_zone(inst, pevent->dn, ISC_TRUE, ISC_FALSE));
@@ -4579,7 +4579,7 @@ update_record(isc_task_t *task, isc_event_t *event)
 
 	CHECK(manager_get_ldap_instance(pevent->dbname, &inst));
 	CHECK(dn_to_dnsname(mctx, pevent->dn, &name, &origin, &iszone));
-	INSIST(iszone == ISC_FALSE);
+	CHECK(dn_want_zone(__func__, pevent->dn, iszone, ISC_FALSE));
 	CHECK(zr_get_zone_ptr(inst->zone_register, &origin, &raw, &secure));
 	zone_found = ISC_TRUE;
 
-- 
2.1.0

_______________________________________________
Freeipa-devel mailing list
Freeipa-devel@redhat.com
https://www.redhat.com/mailman/listinfo/freeipa-devel

Reply via email to