summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMartin Nagy <mnagy@redhat.com>2009-03-25 15:34:30 +0100
committerMartin Nagy <mnagy@redhat.com>2009-03-25 15:34:30 +0100
commit571bf6b7f2fd9ca6551b207e60f486473c45ba96 (patch)
treeea985b6baf25a9ad6017eca6471f817504c9e6b0
parentec8cb3a754c3ebbaef240d19b06717ee40520a08 (diff)
downloadldap_driver_testing-571bf6b7f2fd9ca6551b207e60f486473c45ba96.tar.gz
ldap_driver_testing-571bf6b7f2fd9ca6551b207e60f486473c45ba96.tar.xz
ldap_driver_testing-571bf6b7f2fd9ca6551b207e60f486473c45ba96.zip
Fix problems with dnsname_to_dn() (rewrite).
-rw-r--r--ldap_convert.c78
-rw-r--r--ldap_convert.h5
-rw-r--r--ldap_helper.c118
-rw-r--r--ldap_helper.h4
-rw-r--r--str.c13
-rw-r--r--util.h13
6 files changed, 172 insertions, 59 deletions
diff --git a/ldap_convert.c b/ldap_convert.c
index 5df83e3..2c02f28 100644
--- a/ldap_convert.c
+++ b/ldap_convert.c
@@ -19,11 +19,11 @@
#include <isc/buffer.h>
#include <isc/mem.h>
-#include <isc/result.h>
#include <isc/util.h>
#include <dns/name.h>
#include <dns/rdatatype.h>
+#include <dns/result.h>
#include <dns/types.h>
#define LDAP_DEPRECATED 1
@@ -34,6 +34,7 @@
#include "str.h"
#include "ldap_convert.h"
+#include "ldap_helper.h"
#include "log.h"
#include "util.h"
@@ -107,13 +108,11 @@ cleanup:
}
/*
- * Convert LDAP dn to DNS name. If root_dn is not NULL then count how much RNDs
- * it contains and ignore that much trailing RNDs from dn.
+ * Convert LDAP dn to DNS name.
*
* Example:
* dn = "idnsName=foo, idnsName=bar, idnsName=example.org, cn=dns,"
* "dc=example, dc=org"
- * root_dn = "cn=dns, dc=example, dc=org"
*
* The resulting string will be "foo.bar.example.org."
*/
@@ -203,55 +202,58 @@ explode_rdn(const char *rdn, char ***explodedp, int notypes)
return ISC_R_SUCCESS;
}
-/*
- * FIXME: Don't assume that the last RDN consists of the last two labels.
- */
isc_result_t
-dnsname_to_dn(isc_mem_t *mctx, dns_name_t *name, const char *root_dn,
- ld_string_t *target)
+dnsname_to_dn(ldap_db_t *ldap_db, dns_name_t *name, ld_string_t *target)
{
isc_result_t result;
- isc_buffer_t target_buffer;
- char target_base[DNS_NAME_MAXTEXT + 1];
- ld_string_t *str;
- ld_split_t *split;
- unsigned int split_count;
- REQUIRE(mctx != NULL);
+ DECLARE_BUFFERED_NAME(zone);
+
+ dns_name_t labels;
+
+ dns_namereln_t reln;
+ int order;
+ unsigned int common_labels;
+ int label_count;
+ const char *zone_dn = NULL;
+
+ REQUIRE(ldap_db != NULL);
REQUIRE(name != NULL);
REQUIRE(target != NULL);
- str = NULL;
- split = NULL;
- CHECK(str_new(mctx, &str));
- CHECK(str_new_split(mctx, &split));
- isc_buffer_init(&target_buffer, target_base, sizeof(target_base));
- CHECK(dns_name_totext(name, isc_boolean_true, &target_buffer));
- target_base[isc_buffer_usedlength(&target_buffer)] = '\0';
- CHECK(str_init_char(str, target_base));
- CHECK(str_split(str, '.', split));
- split_count = str_split_count(split);
+ INIT_BUFFERED_NAME(zone);
- for (unsigned int i = 0; i < split_count - 1; i++) {
- CHECK(str_cat_char(target, "idnsName="));
- CHECK(str_cat_char(target, str_split_get(split, i)));
- if (split_count - i > 2)
- CHECK(str_cat_char(target, ", "));
- }
+ dns_name_init(&labels, NULL);
+
+ /* Find the DN of the zone we belong to. */
+ CHECK(get_zone_dn(ldap_db, name, &zone_dn, &zone));
+
+ reln = dns_name_fullcompare(name, &zone, &order, &common_labels);
+ INSIST(reln == dns_namereln_subdomain || reln == dns_namereln_equal);
+ label_count = dns_name_countlabels(name);
+ label_count -= common_labels;
+
+ str_clear(target);
+ if (label_count > 0) {
+ isc_buffer_t buffer;
+ char target_base[DNS_NAME_MAXTEXT];
+ isc_region_t region;
+
+ isc_buffer_init(&buffer, target_base, sizeof(target_base));
- CHECK(str_cat_char(target, "."));
- CHECK(str_cat_char(target, str_split_get(split, split_count - 1)));
+ dns_name_getlabelsequence(name, 0, label_count, &labels);
+ CHECK(dns_name_totext(&labels, ISC_TRUE, &buffer));
+ isc_buffer_usedregion(&buffer, &region);
- if (root_dn != NULL) {
+ CHECK(str_cat_char(target, "idnsName="));
+ CHECK(str_cat_char_len(target, (char *)region.base,
+ region.length));
CHECK(str_cat_char(target, ", "));
- CHECK(str_cat_char(target, root_dn));
}
+ CHECK(str_cat_char(target, zone_dn));
cleanup:
- str_destroy_split(&split);
- str_destroy(&str);
-
return result;
}
diff --git a/ldap_convert.h b/ldap_convert.h
index 4c166b5..d35144a 100644
--- a/ldap_convert.h
+++ b/ldap_convert.h
@@ -23,6 +23,7 @@
#include <dns/types.h>
#include "str.h"
+#include "ldap_helper.h"
/*
* Convert LDAP DN 'dn', to dns_name_t 'target'. 'target' needs to be
@@ -32,8 +33,8 @@
isc_result_t dn_to_dnsname(isc_mem_t *mctx, const char *dn,
dns_name_t *target);
-isc_result_t dnsname_to_dn(isc_mem_t *mctx, dns_name_t *name,
- const char *root_dn, ld_string_t *target);
+isc_result_t dnsname_to_dn(ldap_db_t *ldap_db, dns_name_t *name,
+ ld_string_t *target);
isc_result_t ldap_record_to_rdatatype(const char *ldap_record,
dns_rdatatype_t *rdtype);
diff --git a/ldap_helper.c b/ldap_helper.c
index e0e66b1..7c0dcb8 100644
--- a/ldap_helper.c
+++ b/ldap_helper.c
@@ -18,6 +18,7 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+#include <dns/rbt.h>
#include <dns/rdata.h>
#include <dns/rdataclass.h>
#include <dns/rdatalist.h>
@@ -32,6 +33,7 @@
#include <isc/mem.h>
#include <isc/mutex.h>
#include <isc/region.h>
+#include <isc/rwlock.h>
#include <isc/util.h>
#define LDAP_DEPRECATED 1
@@ -97,6 +99,10 @@ struct ldap_db {
semaphore_t conn_semaphore;
LIST(ldap_instance_t) conn_list;
+ /* Our own list of zones. */
+ isc_rwlock_t zone_rwlock;
+ dns_rbt_t *zone_names;
+
/* Settings. */
ld_string_t *host;
ld_string_t *base;
@@ -156,7 +162,6 @@ struct ldap_value {
LINK(ldap_value_t) link;
};
-
/*
* Constants.
*/
@@ -176,6 +181,7 @@ const ldap_auth_pair_t supported_ldap_auth[] = {
*/
/* TODO: reorganize this stuff & clean it up. */
+void string_deleter(void *arg1, void *arg2);
static isc_result_t new_ldap_instance(ldap_db_t *ldap_db,
ldap_instance_t **ldap_instp);
static void destroy_ldap_instance(ldap_instance_t **ldap_instp);
@@ -275,14 +281,17 @@ new_ldap_db(isc_mem_t *mctx, dns_view_t *view, ldap_db_t **ldap_dbp,
INIT_LIST(ldap_db->conn_list);
- CHECK(str_new(ldap_db->mctx, &auth_method_str));
- CHECK(str_new(ldap_db->mctx, &ldap_db->host));
- CHECK(str_new(ldap_db->mctx, &ldap_db->base));
- CHECK(str_new(ldap_db->mctx, &ldap_db->bind_dn));
- CHECK(str_new(ldap_db->mctx, &ldap_db->password));
- CHECK(str_new(ldap_db->mctx, &ldap_db->sasl_mech));
- CHECK(str_new(ldap_db->mctx, &ldap_db->sasl_user));
- CHECK(str_new(ldap_db->mctx, &ldap_db->sasl_realm));
+ CHECK(isc_rwlock_init(&ldap_db->zone_rwlock, 0, 0));
+ CHECK(dns_rbt_create(mctx, string_deleter, mctx, &ldap_db->zone_names));
+
+ CHECK(str_new(mctx, &auth_method_str));
+ CHECK(str_new(mctx, &ldap_db->host));
+ CHECK(str_new(mctx, &ldap_db->base));
+ CHECK(str_new(mctx, &ldap_db->bind_dn));
+ CHECK(str_new(mctx, &ldap_db->password));
+ CHECK(str_new(mctx, &ldap_db->sasl_mech));
+ CHECK(str_new(mctx, &ldap_db->sasl_user));
+ CHECK(str_new(mctx, &ldap_db->sasl_realm));
ldap_settings[0].target = ldap_db->host;
ldap_settings[1].target = &ldap_db->connections;
@@ -370,6 +379,9 @@ destroy_ldap_db(ldap_db_t **ldap_dbp)
/* commented out for now, causes named to hang */
//dns_view_detach(&ldap_db->view);
+ dns_rbt_destroy(&ldap_db->zone_names);
+ isc_rwlock_destroy(&ldap_db->zone_rwlock);
+
isc_mem_putanddetach(&ldap_db->mctx, ldap_db, sizeof(ldap_db_t));
*ldap_dbp = NULL;
@@ -487,6 +499,89 @@ get_dn(ldap_instance_t *inst)
}
+
+void
+string_deleter(void *arg1, void *arg2)
+{
+ char *string = (char *)arg1;
+ isc_mem_t *mctx = (isc_mem_t *)arg2;
+
+ REQUIRE(string != NULL);
+ REQUIRE(mctx != NULL);
+
+ isc_mem_free(mctx, string);
+}
+
+isc_result_t
+get_zone_dn(ldap_db_t *ldap_db, dns_name_t *name, const char **dn,
+ dns_name_t *matched_name)
+{
+ isc_result_t result;
+ dns_rbt_t *rbt;
+ void *data = NULL;
+
+ REQUIRE(ldap_db != NULL);
+ REQUIRE(name != NULL);
+ REQUIRE(dn != NULL && *dn == NULL);
+ REQUIRE(matched_name != NULL);
+
+ RWLOCK(&ldap_db->zone_rwlock, isc_rwlocktype_read);
+ rbt = ldap_db->zone_names;
+
+ result = dns_rbt_findname(rbt, name, 0, matched_name, &data);
+ if (result == DNS_R_PARTIALMATCH)
+ result = ISC_R_SUCCESS;
+ if (result == ISC_R_SUCCESS) {
+ INSIST(data != NULL);
+ *dn = data;
+ }
+
+ RWUNLOCK(&ldap_db->zone_rwlock, isc_rwlocktype_read);
+
+ return result;
+}
+
+static isc_result_t
+add_zone_dn(ldap_db_t *ldap_db, dns_name_t *name, const char *dn)
+{
+ isc_result_t result;
+ dns_rbt_t *rbt;
+ void *data = NULL;
+ char *new_dn = NULL;
+
+ REQUIRE(ldap_db != NULL);
+ REQUIRE(name != NULL);
+ REQUIRE(dn != NULL);
+
+ RWLOCK(&ldap_db->zone_rwlock, isc_rwlocktype_write);
+ rbt = ldap_db->zone_names;
+
+ CHECKED_MEM_STRDUP(ldap_db->mctx, dn, new_dn);
+
+ /* First make sure the node doesn't exist. */
+ result = dns_rbt_findname(rbt, name, 0, NULL, &data);
+ if (result == ISC_R_SUCCESS)
+ CHECK(dns_rbt_deletename(rbt, name, ISC_FALSE));
+ else if (result != ISC_R_NOTFOUND && result != DNS_R_PARTIALMATCH)
+ goto cleanup;
+
+ /* Now add it. */
+ CHECK(dns_rbt_addname(rbt, name, (void *)new_dn));
+
+ RWUNLOCK(&ldap_db->zone_rwlock, isc_rwlocktype_write);
+
+ return ISC_R_SUCCESS;
+
+cleanup:
+ RWUNLOCK(&ldap_db->zone_rwlock, isc_rwlocktype_write);
+
+ if (new_dn)
+ isc_mem_free(ldap_db->mctx, new_dn);
+
+ return result;
+}
+
+/* FIXME: Better error handling. */
static isc_result_t
add_or_modify_zone(ldap_db_t *ldap_db, const char *dn, const char *db_name,
dns_zonemgr_t *zmgr)
@@ -526,6 +621,7 @@ add_or_modify_zone(ldap_db_t *ldap_db, const char *dn, const char *db_name,
CHECK(dns_zonemgr_managezone(zmgr, zone));
CHECK(dns_view_addzone(ldap_db->view, zone));
+ CHECK(add_zone_dn(ldap_db, &name, dn));
} else if (result != ISC_R_SUCCESS) {
goto cleanup;
}
@@ -678,7 +774,7 @@ ldapdb_rdatalist_get(isc_mem_t *mctx, ldap_db_t *ldap_db, dns_name_t *name,
INIT_LIST(*rdatalist);
CHECK(str_new(mctx, &string));
- CHECK(dnsname_to_dn(mctx, name, str_buf(ldap_db->base), string));
+ CHECK(dnsname_to_dn(ldap_db, name, string));
CHECK(ldap_query(ldap_inst, str_buf(string), LDAP_SCOPE_BASE, NULL, 0,
"(objectClass=idnsRecord)"));
@@ -1595,7 +1691,7 @@ modify_ldap_common(dns_name_t *owner, ldap_db_t *ldap_db,
ldap_inst = get_connection(ldap_db);
CHECK(str_new(mctx, &owner_dn));
- CHECK(dnsname_to_dn(mctx, owner, str_buf(ldap_db->base), owner_dn));
+ CHECK(dnsname_to_dn(ldap_db, owner, owner_dn));
CHECK(ldap_rdatalist_to_ldapmod(mctx, rdlist, &change[0], mod_op));
CHECK(ldap_modify_do(ldap_inst, str_buf(owner_dn), change));
diff --git a/ldap_helper.h b/ldap_helper.h
index 32edd9c..a0e4aea 100644
--- a/ldap_helper.h
+++ b/ldap_helper.h
@@ -90,6 +90,10 @@ void destroy_ldap_db(ldap_db_t **ldap_db);
isc_result_t refresh_zones_from_ldap(ldap_db_t *ldap_db, const char *name,
dns_zonemgr_t *zmgr);
+isc_result_t
+get_zone_dn(ldap_db_t *ldap_db, dns_name_t *name, const char **dn,
+ dns_name_t *matched_name);
+
/* Functions for writing to LDAP. */
isc_result_t ldap_rdata_to_char_array(isc_mem_t *mctx, dns_rdata_t *rdata_head,
char ***valsp);
diff --git a/str.c b/str.c
index 99a1e6d..684f73a 100644
--- a/str.c
+++ b/str.c
@@ -324,20 +324,17 @@ str_cat_char_len(ld_string_t *dest, const char *src, size_t len)
isc_result_t result;
char *from;
size_t dest_size;
- size_t src_size;
REQUIRE(dest != NULL);
- IGNORE_R(src != NULL);
+ IGNORE_R(src == NULL);
+ IGNORE_R(len == 0);
dest_size = str_len_internal(dest);
- src_size = ISC_MAX(strlen(src), len);
- IGNORE_R(src_size == 0);
-
- CHECK(str_alloc(dest, dest_size + src_size));
+ CHECK(str_alloc(dest, dest_size + len));
from = dest->data + dest_size;
- strncpy(from, src, src_size);
- from[src_size - 1] = '\0';
+ strncpy(from, src, len);
+ from[len] = '\0';
return ISC_R_SUCCESS;
diff --git a/util.h b/util.h
index 6c46516..114bab8 100644
--- a/util.h
+++ b/util.h
@@ -62,4 +62,17 @@
isc_mem_putanddetach(&(target_ptr)->mctx, target_ptr, \
sizeof(*(target_ptr)))
+#define DECLARE_BUFFERED_NAME(name) \
+ dns_name_t name; \
+ isc_buffer_t name##__buffer; \
+ unsigned char name##__base[DNS_NAME_MAXWIRE]
+
+#define INIT_BUFFERED_NAME(name) \
+ do { \
+ isc_buffer_init(&name##__buffer, name##__base, \
+ sizeof(name##__base)); \
+ dns_name_init(&name, NULL); \
+ dns_name_setbuffer(&name, &name##__buffer); \
+ } while (0)
+
#endif /* !_LD_UTIL_H_ */