Hello,
This patch set contains necessary changes for supporting root master zone in
LDAP. I had to remove one hack so now we follow BIND semantics for forwarders.
Please see commit messages.
https://fedorahosted.org/bind-dyndb-ldap/ticket/122
--
Petr^2 Spacek
From 21f7ecd4eb4f977392975034fc9de3b61958e2aa Mon Sep 17 00:00:00 2001
From: Petr Spacek <[email protected]>
Date: Fri, 6 Jun 2014 19:28:13 +0200
Subject: [PATCH] Refactor DN->DNS name conversion.
Original code was fragile and unable to parse name of root zone
(idnsName=.).
https://fedorahosted.org/bind-dyndb-ldap/ticket/122
Signed-off-by: Petr Spacek <[email protected]>
---
src/ldap_convert.c | 275 +++++++++++++++++++++--------------------------------
1 file changed, 106 insertions(+), 169 deletions(-)
diff --git a/src/ldap_convert.c b/src/ldap_convert.c
index 89c371d27447b34e28bd24ddcaefb58fcaf1dd07..be5c2e1d4dc903b4d9e72cc07ed1d9fc32fef0d1 100644
--- a/src/ldap_convert.c
+++ b/src/ldap_convert.c
@@ -40,164 +40,149 @@
#include "util.h"
#include "zone_register.h"
-static isc_result_t explode_dn(const char *dn, char ***explodedp, int notypes) ATTR_NONNULLS ATTR_CHECKRESULT;
-static isc_result_t explode_rdn(const char *rdn, char ***explodedp,
- int notypes) ATTR_NONNULLS ATTR_CHECKRESULT;
-
-
-isc_result_t
-dn_to_dnsname(isc_mem_t *mctx, const char *dn, dns_name_t *target,
- dns_name_t *otarget)
-{
- isc_result_t result;
- DECLARE_BUFFERED_NAME(name);
- DECLARE_BUFFERED_NAME(origin);
- ld_string_t *str = NULL;
- ld_string_t *ostr = NULL;
- isc_buffer_t buffer;
-
- REQUIRE(dn != NULL);
-
- INIT_BUFFERED_NAME(name);
- CHECK(str_new(mctx, &str));
-
- if (otarget != NULL) {
- INIT_BUFFERED_NAME(origin);
- CHECK(str_new(mctx, &ostr));
- }
-
- CHECK(dn_to_text(dn, str, ostr));
- str_to_isc_buffer(str, &buffer);
- CHECK(dns_name_fromtext(&name, &buffer, NULL, 0, NULL));
-
- if (otarget != NULL) {
- str_to_isc_buffer(ostr, &buffer);
- CHECK(dns_name_fromtext(&origin, &buffer, NULL, 0, NULL));
- }
-
-cleanup:
- if (result == ISC_R_SUCCESS)
- result = dns_name_dupwithoffsets(&name, mctx, target);
- else
- log_error_r("failed to convert dn %s to DNS name", dn);
-
- if (otarget != NULL && result == ISC_R_SUCCESS)
- result = dns_name_dupwithoffsets(&origin, mctx, otarget);
-
- if (result != ISC_R_SUCCESS) {
- if (dns_name_dynamic(target))
- dns_name_free(target, mctx);
- if (otarget) {
- if (dns_name_dynamic(otarget))
- dns_name_free(otarget, mctx);
- }
- }
-
- str_destroy(&str);
- if (otarget != NULL)
- str_destroy(&ostr);
-
- return result;
-}
-
/**
- * Convert LDAP DN to absolute DNS name.
+ * Convert LDAP DN to absolute DNS names.
*
* @param[in] dn LDAP DN with one or two idnsName components at the
* beginning.
- * @param[out] target Absolute DNS name derived from the all idnsNames.
+ * @param[out] target Absolute DNS name derived from the first two idnsNames.
* @param[out] origin Absolute DNS name derived from the last idnsName
* component of DN, i.e. zone. Can be NULL.
*
* @code
* Examples:
- * dn = "idnsName=foo, idnsName=bar, idnsName=example.org,"
- * "cn=dns, dc=example, dc=org"
+ * dn = "idnsName=foo.bar, idnsName=example.org., cn=dns, dc=example, dc=org"
* target = "foo.bar.example.org."
* origin = "example.org."
*
- * dn = "idnsname=89, idnsname=4.34.10.in-addr.arpa.",
- * " cn=dns, dc=example, dc=org"
+ * dn = "idnsname=89, idnsname=4.34.10.in-addr.arpa, cn=dns, dc=example, dc=org"
* target = "89.4.34.10.in-addr.arpa."
* origin = "4.34.10.in-addr.arpa."
- * (The dot at the end is not doubled when it's already present.)
+ *
+ * dn = "idnsname=third.test., idnsname=test., cn=dns, dc=example, dc=org"
+ * target = "third.test."
+ * origin = "test."
* @endcode
*/
isc_result_t
-dn_to_text(const char *dn, ld_string_t *target, ld_string_t *origin)
+dn_to_dnsname(isc_mem_t *mctx, const char *dn_str, dns_name_t *target,
+ dns_name_t *otarget)
{
+ LDAPDN dn = NULL;
+ LDAPRDN rdn = NULL;
+ LDAPAVA *attr = NULL;
+ int idx;
+ int ret;
+
+ DECLARE_BUFFERED_NAME(name);
+ DECLARE_BUFFERED_NAME(origin);
+ isc_buffer_t name_buf;
+ isc_buffer_t origin_buf;
isc_result_t result;
- char **exploded_dn = NULL;
- char **exploded_rdn = NULL;
- unsigned int i;
- REQUIRE(dn != NULL);
+ REQUIRE(dn_str != NULL);
REQUIRE(target != NULL);
- CHECK(explode_dn(dn, &exploded_dn, 0));
- str_clear(target);
- for (i = 0; exploded_dn[i] != NULL; i++) {
- if (strncasecmp(exploded_dn[i], "idnsName", 8) != 0)
+ INIT_BUFFERED_NAME(name);
+ INIT_BUFFERED_NAME(origin);
+ isc_buffer_initnull(&name_buf);
+ isc_buffer_initnull(&origin_buf);
+
+ /* Example DN: cn=a+sn=b, ou=people */
+
+ ret = ldap_str2dn(dn_str, &dn, LDAP_DN_FORMAT_LDAPV3);
+ if (ret != LDAP_SUCCESS || dn == NULL) {
+ log_bug("ldap_str2dn failed: %u", ret);
+ CLEANUP_WITH(ISC_R_UNEXPECTED);
+ }
+
+ /* iterate over DN components: e.g. cn=a+sn=b */
+ for (idx = 0; dn[idx] != NULL; idx++) {
+ rdn = dn[idx];
+
+ /* "iterate" over RDN components: e.g. cn=a */
+ INSIST(rdn[0] != NULL); /* RDN without (attr=value)?! */
+ if (rdn[1] != NULL) {
+ log_bug("multi-valued RDNs are not supported");
+ CLEANUP_WITH(ISC_R_NOTIMPLEMENTED);
+ }
+
+ /* attribute in current RDN component */
+ attr = rdn[0];
+ if ((attr->la_flags & LDAP_AVA_STRING) == 0) {
+ log_error("non-string attribute detected: position %u",
+ idx);
+ CLEANUP_WITH(ISC_R_NOTIMPLEMENTED);
+ }
+
+ if (strncasecmp("idnsName", attr->la_attr.bv_val,
+ attr->la_attr.bv_len) == 0) {
+ if (idx == 0) {
+ isc_buffer_init(&name_buf,
+ attr->la_value.bv_val,
+ attr->la_value.bv_len);
+ isc_buffer_add(&name_buf,
+ attr->la_value.bv_len);
+ } else if (idx == 1) {
+ isc_buffer_init(&origin_buf,
+ attr->la_value.bv_val,
+ attr->la_value.bv_len);
+ isc_buffer_add(&origin_buf,
+ attr->la_value.bv_len);
+ } else { /* more than two idnsNames?! */
+ break;
+ }
+ } else { /* no match - idx holds position */
break;
-
- if (exploded_rdn != NULL) {
- ldap_value_free(exploded_rdn);
- exploded_rdn = NULL;
}
-
- CHECK(explode_rdn(exploded_dn[i], &exploded_rdn, 1));
- if (exploded_rdn[0] == NULL || exploded_rdn[1] != NULL) {
- log_error("idnsName component of DN has to have "
- "exactly one value: DN '%s'", dn);
- CLEANUP_WITH(ISC_R_NOTIMPLEMENTED);
- }
- CHECK(str_cat_char(target, exploded_rdn[0]));
- if (str_buf(target)[str_len(target)-1] != '.')
- CHECK(str_cat_char(target, "."));
}
/* filter out unsupported cases */
- if (i <= 0) {
- log_error("no idnsName component found in DN '%s'", dn);
+ if (idx <= 0) {
+ log_error("no idnsName component found in DN");
CLEANUP_WITH(ISC_R_UNEXPECTEDEND);
- } else if (i == 1) { /* zone only - nothing to check */
- ;
- } else if (i == 2) {
- if (exploded_dn[0][strlen(exploded_dn[0])-1] == '.') {
- log_error("absolute record name in DN "
- "is not supported: DN '%s'", dn);
- CLEANUP_WITH(ISC_R_NOTIMPLEMENTED);
+ } else if (idx == 1) { /* zone only */
+ CHECK(dns_name_copy(dns_rootname, &origin, NULL));
+ CHECK(dns_name_fromtext(&name, &name_buf, dns_rootname, 0, NULL));
+ } else if (idx == 2) { /* owner and zone */
+ CHECK(dns_name_fromtext(&origin, &origin_buf, dns_rootname, 0,
+ NULL));
+ CHECK(dns_name_fromtext(&name, &name_buf, &origin, 0, NULL));
+ if (dns_name_issubdomain(&name, &origin) == ISC_FALSE) {
+ log_error("out-of-zone data: first idnsName is not a "
+ "subdomain of the other");
+ CLEANUP_WITH(DNS_R_BADOWNERNAME);
+ } else if (dns_name_equal(&name, &origin) == ISC_TRUE) {
+ log_error("attempt to redefine zone apex: first "
+ "idnsName equals to zone name");
+ CLEANUP_WITH(DNS_R_BADOWNERNAME);
}
} else {
- log_error("unsupported number of idnsName components in DN "
- "'%s': %u components found", dn, i);
+ log_error("unsupported number of idnsName components in DN: "
+ "%u components found", idx);
CLEANUP_WITH(ISC_R_NOTIMPLEMENTED);
}
- if (origin != NULL) {
- str_clear(origin);
+cleanup:
+ if (result == ISC_R_SUCCESS)
+ result = dns_name_dupwithoffsets(&name, mctx, target);
+ else
+ log_error_r("failed to convert DN '%s' to DNS name", dn_str);
- /*
- * If we have DNs with only one idnsName part,
- * treat them as absolute zone name, i.e. origin is root.
- */
- if (i < 2)
- CHECK(str_init_char(origin, "."));
- else {
- CHECK(str_cat_char(origin, exploded_rdn[0]));
- if (str_buf(origin)[str_len(origin)-1] != '.')
- CHECK(str_cat_char(origin, "."));
+ if (result == ISC_R_SUCCESS && otarget != NULL)
+ result = dns_name_dupwithoffsets(&origin, mctx, otarget);
+
+ if (result != ISC_R_SUCCESS) {
+ if (dns_name_dynamic(target))
+ dns_name_free(target, mctx);
+ if (otarget) {
+ if (dns_name_dynamic(otarget))
+ dns_name_free(otarget, mctx);
}
}
- if (str_len(target) == 0)
- CHECK(str_init_char(target, "."));
-
-cleanup:
- if (exploded_dn != NULL)
- ldap_value_free(exploded_dn);
- if (exploded_rdn != NULL)
- ldap_value_free(exploded_rdn);
+ if (dn != NULL)
+ ldap_dnfree(dn);
return result;
}
@@ -309,54 +294,6 @@ cleanup:
return result;
}
-static isc_result_t ATTR_NONNULLS ATTR_CHECKRESULT
-explode_dn(const char *dn, char ***explodedp, int notypes)
-{
- char **exploded;
-
- REQUIRE(dn != NULL);
- REQUIRE(explodedp != NULL && *explodedp == NULL);
-
- exploded = ldap_explode_dn(dn, notypes);
- if (exploded == NULL) {
- if (errno == ENOMEM) {
- return ISC_R_NOMEMORY;
- } else {
- log_error("ldap_explode_dn(\"%s\") failed, "
- "error code %d", dn, errno);
- return ISC_R_FAILURE;
- }
- }
-
- *explodedp = exploded;
-
- return ISC_R_SUCCESS;
-}
-
-static isc_result_t ATTR_NONNULLS ATTR_CHECKRESULT
-explode_rdn(const char *rdn, char ***explodedp, int notypes)
-{
- char **exploded;
-
- REQUIRE(rdn != NULL);
- REQUIRE(explodedp != NULL && *explodedp == NULL);
-
- exploded = ldap_explode_rdn(rdn, notypes);
- if (exploded == NULL) {
- if (errno == ENOMEM) {
- return ISC_R_NOMEMORY;
- } else {
- log_error("ldap_explode_rdn(\"%s\") failed, "
- "error code %d", rdn, errno);
- return ISC_R_FAILURE;
- }
- }
-
- *explodedp = exploded;
-
- return ISC_R_SUCCESS;
-}
-
isc_result_t
dnsname_to_dn(zone_register_t *zr, dns_name_t *name, ld_string_t *target)
{
--
1.9.3
From 3dbfc515aacc089c1849ae1b85fb8e87c64e95f4 Mon Sep 17 00:00:00 2001
From: Petr Spacek <[email protected]>
Date: Fri, 6 Jun 2014 19:30:05 +0200
Subject: [PATCH] Support root master zone in LDAP; Follow BIND semantics for
forwarders.
In this case "support" actually means "remove hack" enforced by mixing
forward/master zones in one object class.
From now on, forwarding configured in LDAP (attributes idnsForward and
idnsForwarders) fully follows BIND behavior for master and forward zones:
- Master zones in LDAP are defined by idnsZone object class.
- Forward zones in LDAP are defined by idnsForward object class.
I.e. idnsForwarders attribute in master zone *does not* change zone type
to forward.
*THIS IS INCOMPATIBLE CHANGE*
https://fedorahosted.org/bind-dyndb-ldap/ticket/122
Signed-off-by: Petr Spacek <[email protected]>
---
src/ldap_helper.c | 22 +++-------------------
1 file changed, 3 insertions(+), 19 deletions(-)
diff --git a/src/ldap_helper.c b/src/ldap_helper.c
index deda6955a215441a40857d78273fb8042275385e..43bacf779f44a709b0cefd638826633b9d2d8891 100644
--- a/src/ldap_helper.c
+++ b/src/ldap_helper.c
@@ -1397,8 +1397,8 @@ cleanup:
* @retval others Some RBT manipulation errors including ISC_R_FAILURE.
*/
static isc_result_t ATTR_NONNULLS ATTR_CHECKRESULT
-configure_zone_forwarders(ldap_entry_t *entry, ldap_instance_t *inst,
- dns_name_t *name)
+configure_zone_forwarders(ldap_entry_t *entry, ldap_instance_t *inst,
+ dns_name_t *name)
{
const char *dn = entry->dn;
isc_result_t result;
@@ -2294,25 +2294,9 @@ ldap_parse_master_zoneentry(ldap_entry_t * const entry, dns_db_t * const olddb,
run_exclusive_enter(task, &lock_state);
- /*
- * TODO: Remove this hack, most probably before Fedora 20.
- * Forwarding has top priority hence when the forwarders are properly
- * set up all others attributes are ignored.
- */
result = configure_zone_forwarders(entry, inst, &name);
- if (result != ISC_R_DISABLED) {
- if (result == ISC_R_SUCCESS) {
- /* forwarding was enabled for the zone
- * => zone type was changed to "forward"
- * => delete "master" zone */
- CHECK(ldap_delete_zone2(inst, &name, ISC_FALSE,
- ISC_TRUE));
- }
- /* DO NOT CHANGE ANYTHING ELSE after forwarders are set up! */
+ if (result != ISC_R_SUCCESS && result != ISC_R_DISABLED)
goto cleanup;
- }
- /* No forwarders are used. Zone was removed from fwdtable.
- * Load the zone. */
result = ldap_entry_getvalues(entry, "idnsSecInlineSigning", &values);
if (result == ISC_R_NOTFOUND || HEAD(values) == NULL)
--
1.9.3
From bcad3a5069e4944db11527eadb580c0d3313df82 Mon Sep 17 00:00:00 2001
From: Petr Spacek <[email protected]>
Date: Fri, 6 Jun 2014 19:40:39 +0200
Subject: [PATCH] Remove unused str_* functions.
Signed-off-by: Petr Spacek <[email protected]>
---
src/str.c | 145 --------------------------------------------------------------
src/str.h | 10 -----
2 files changed, 155 deletions(-)
diff --git a/src/str.c b/src/str.c
index 131bcc047bf858925999ae4128e4cb23ef51c023..c871ad60e9ffd1ce98e4bbe54d5f63f071bc581d 100644
--- a/src/str.c
+++ b/src/str.c
@@ -212,51 +212,6 @@ str_buf(const ld_string_t *src)
return src->data;
}
-/*
- * Copy string from src to dest.
- */
-isc_result_t
-str_copy(ld_string_t *dest, const ld_string_t *src)
-{
- isc_result_t result;
- size_t len;
-
- REQUIRE(dest != NULL);
- REQUIRE(src != NULL);
-
- if (src->data == NULL)
- return ISC_R_SUCCESS;
-
- len = str_len_internal(src);
- CHECK(str_alloc(dest, len));
- memcpy(dest->data, src->data, len + 1);
-
- return ISC_R_SUCCESS;
-
-cleanup:
- return result;
-}
-
-/*
- * Make a new string and copy src to it.
- */
-isc_result_t
-str_clone(ld_string_t **dest, const ld_string_t *src _STR_MEM_FLARG)
-{
- isc_result_t result;
-
- REQUIRE(src != NULL);
- REQUIRE(dest != NULL && *dest == NULL);
-
- CHECK(str__new(src->mctx, dest _STR_MEM_FLARG_PASS));
- CHECK(str_copy(*dest, src));
-
- return ISC_R_SUCCESS;
-
-cleanup:
- return result;
-}
-
void
str_clear(ld_string_t *dest)
{
@@ -324,69 +279,6 @@ cleanup:
return result;
}
-isc_result_t
-str_cat_char_len(ld_string_t *dest, const char *src, size_t len)
-{
- isc_result_t result;
- char *from;
- size_t dest_size;
-
- REQUIRE(dest != NULL);
-
- if (src == NULL || len == 0)
- return ISC_R_SUCCESS;
-
- dest_size = str_len_internal(dest);
-
- CHECK(str_alloc(dest, dest_size + len));
- from = dest->data + dest_size;
- memcpy(from, src, len);
- from[len] = '\0';
-
- return ISC_R_SUCCESS;
-
-cleanup:
- return result;
-}
-
-isc_result_t
-str_cat_isc_region(ld_string_t *dest, const isc_region_t *region)
-{
- REQUIRE(dest != NULL);
- REQUIRE(region != NULL);
-
- return str_cat_char_len(dest, (char *)region->base, region->length);
-}
-
-isc_result_t
-str_cat_isc_buffer(ld_string_t *dest, const isc_buffer_t *buffer)
-{
- isc_region_t region;
- isc_buffer_t *deconst_buffer;
-
- REQUIRE(dest != NULL);
- REQUIRE(ISC_BUFFER_VALID(buffer));
-
- DE_CONST(buffer, deconst_buffer);
- isc_buffer_usedregion(deconst_buffer, ®ion);
-
- return str_cat_isc_region(dest, ®ion);
-}
-
-/*
- * Concatenate string src to string dest.
- */
-isc_result_t
-str_cat(ld_string_t *dest, const ld_string_t *src)
-{
- REQUIRE(dest != NULL);
-
- if (src == NULL || src->data == NULL)
- return ISC_R_SUCCESS;
-
- return str_cat_char(dest, src->data);
-}
-
/*
* A sprintf() like function.
*/
@@ -434,40 +326,3 @@ cleanup:
va_end(backup);
return result;
}
-
-void
-str_toupper(ld_string_t *str)
-{
- char *ptr;
-
- REQUIRE(str != NULL);
-
- if (str->data == NULL)
- return;
-
- for (ptr = str->data; *ptr != '\0'; ptr++)
- *ptr = toupper((unsigned char)*ptr);
-}
-
-void
-str_to_isc_buffer(const ld_string_t *src, isc_buffer_t *dest)
-{
- size_t len;
-
- REQUIRE(src != NULL);
- REQUIRE(dest != NULL);
-
- len = str_len_internal(src);
-
- isc_buffer_init(dest, src->data, len);
- isc_buffer_add(dest, len);
-}
-
-int
-str_casecmp_char(const ld_string_t *s1, const char *s2)
-{
- REQUIRE(s1 != NULL && s1->data != NULL);
- REQUIRE(s2 != NULL);
-
- return strcasecmp(s1->data, s2);
-}
diff --git a/src/str.h b/src/str.h
index 84056d5100a9f599aa2c424eef4c76cf88902823..7f92ed670d360392dbcbc9f2dc022aadcd42c75b 100644
--- a/src/str.h
+++ b/src/str.h
@@ -48,22 +48,12 @@ typedef struct ld_string ld_string_t;
size_t str_len(const ld_string_t *str) ATTR_NONNULLS ATTR_CHECKRESULT;
const char * str_buf(const ld_string_t *src) ATTR_NONNULLS ATTR_CHECKRESULT;
-isc_result_t str_copy(ld_string_t *dest, const ld_string_t *src) ATTR_NONNULLS ATTR_CHECKRESULT;
-isc_result_t str_clone(ld_string_t **dest, const ld_string_t *src _STR_MEM_FLARG) ATTR_NONNULLS ATTR_CHECKRESULT;
void str_clear(ld_string_t *dest) ATTR_NONNULLS;
isc_result_t str_init_char(ld_string_t *dest, const char *src) ATTR_NONNULLS ATTR_CHECKRESULT;
isc_result_t str_cat_char(ld_string_t *dest, const char *src) ATTR_NONNULLS ATTR_CHECKRESULT;
isc_result_t str_cat_char_len(ld_string_t *dest, const char *src, size_t len) ATTR_NONNULLS ATTR_CHECKRESULT;
-isc_result_t str_cat_isc_region(ld_string_t *dest, const isc_region_t *region) ATTR_NONNULLS ATTR_CHECKRESULT;
-isc_result_t str_cat_isc_buffer(ld_string_t *dest, const isc_buffer_t *buffer) ATTR_NONNULLS ATTR_CHECKRESULT;
-isc_result_t str_cat(ld_string_t *dest, const ld_string_t *src) ATTR_NONNULLS ATTR_CHECKRESULT;
isc_result_t str_sprintf(ld_string_t *dest, const char *format, ...) ISC_FORMAT_PRINTF(2, 3) ATTR_NONNULLS ATTR_CHECKRESULT;
isc_result_t str_vsprintf(ld_string_t *dest, const char *format, va_list ap) ATTR_NONNULLS ATTR_CHECKRESULT;
-void str_toupper(ld_string_t *str) ATTR_NONNULLS;
-
-void str_to_isc_buffer(const ld_string_t *src, isc_buffer_t *dest) ATTR_NONNULLS;
-
-int str_casecmp_char(const ld_string_t *s1, const char *s2) ATTR_NONNULLS ATTR_CHECKRESULT;
/* These are pseudo-private functions and shouldn't be called directly. */
isc_result_t str__new(isc_mem_t *mctx, ld_string_t **new_str _STR_MEM_FLARG) ATTR_NONNULLS ATTR_CHECKRESULT;
--
1.9.3
_______________________________________________
Freeipa-devel mailing list
[email protected]
https://www.redhat.com/mailman/listinfo/freeipa-devel