summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMartin Nagy <mnagy@redhat.com>2009-03-10 10:10:45 +0100
committerMartin Nagy <mnagy@redhat.com>2009-03-16 15:45:47 +0100
commit2ed654359d3c45298ad9c8446c017908dcd07ef0 (patch)
tree381b094ffa20135c8fe76e49fed99fedaf913df4
parent038f85774090e12e0c8c61aadaea50f99da1e32b (diff)
downloadldap_driver_testing-2ed654359d3c45298ad9c8446c017908dcd07ef0.tar.gz
ldap_driver_testing-2ed654359d3c45298ad9c8446c017908dcd07ef0.tar.xz
ldap_driver_testing-2ed654359d3c45298ad9c8446c017908dcd07ef0.zip
Add write-back support.
-rw-r--r--ldap_convert.c1
-rw-r--r--ldap_helper.c240
-rw-r--r--ldap_helper.h8
-rw-r--r--str.c36
-rw-r--r--str.h1
5 files changed, 281 insertions, 5 deletions
diff --git a/ldap_convert.c b/ldap_convert.c
index c22d2da..8b33132 100644
--- a/ldap_convert.c
+++ b/ldap_convert.c
@@ -250,7 +250,6 @@ dnsname_to_dn(isc_mem_t *mctx, dns_name_t *name, const char *root_dn,
CHECK(str_cat_char(target, root_dn));
}
- log_error("%s", str_buf(target));
cleanup:
str_destroy_split(&split);
str_destroy(&str);
diff --git a/ldap_helper.c b/ldap_helper.c
index 17feb3f..e5bffe0 100644
--- a/ldap_helper.c
+++ b/ldap_helper.c
@@ -226,6 +226,15 @@ static isc_result_t ldap_connect(ldap_instance_t *ldap_inst);
static isc_result_t ldap_query(ldap_instance_t *ldap_inst, const char *base,
int scope, char **attrs, int attrsonly, const char *filter, ...);
+/* Functions for writing to LDAP. */
+static isc_result_t ldap_modify_do(ldap_instance_t *ldap_inst, const char *dn,
+ LDAPMod **mods);
+static isc_result_t ldap_rdatalist_to_ldapmod(isc_mem_t *mctx,
+ dns_rdatalist_t *rdlist, LDAPMod ***change_listp, int mod_op);
+static void free_ldapmod_array(isc_mem_t *mctx, LDAPMod ***change_listp);
+static void free_char_array(isc_mem_t *mctx, char ***valsp);
+static isc_result_t modify_ldap_common(dns_name_t *owner, ldap_db_t *ldap_db,
+ dns_rdatalist_t *rdlist, int mod_op);
isc_result_t
new_ldap_db(isc_mem_t *mctx, dns_view_t *view, ldap_db_t **ldap_dbp,
@@ -998,6 +1007,8 @@ get_connection(ldap_db_t *ldap_db)
{
ldap_instance_t *ldap_inst;
+ REQUIRE(ldap_db != NULL);
+
semaphore_wait(&ldap_db->conn_semaphore);
ldap_inst = HEAD(ldap_db->conn_list);
while (ldap_inst != NULL) {
@@ -1018,6 +1029,9 @@ get_connection(ldap_db_t *ldap_db)
static void
put_connection(ldap_instance_t *ldap_inst)
{
+ if (ldap_inst == NULL)
+ return;
+
if (ldap_inst->dn) {
ldap_memfree(ldap_inst->dn);
ldap_inst->dn = NULL;
@@ -1046,13 +1060,16 @@ put_connection(ldap_instance_t *ldap_inst)
}
-/* FIXME: handle disconect */
+/* FIXME: Handle the case where the LDAP handle is NULL -> try to reconnect. */
static isc_result_t
ldap_query(ldap_instance_t *ldap_inst, const char *base, int scope, char **attrs,
int attrsonly, const char *filter, ...)
{
va_list ap;
int ret;
+ const char *err_string;
+
+ REQUIRE(ldap_inst != NULL);
va_start(ap, filter);
str_vsprintf(ldap_inst->query_string, filter, ap);
@@ -1061,6 +1078,11 @@ ldap_query(ldap_instance_t *ldap_inst, const char *base, int scope, char **attrs
log_debug(2, "querying '%s' with '%s'", base,
str_buf(ldap_inst->query_string));
+ if (ldap_inst->handle == NULL) {
+ err_string = "not connected";
+ goto cleanup;
+ }
+
ret = ldap_search_ext_s(ldap_inst->handle, base, scope,
str_buf(ldap_inst->query_string), attrs,
attrsonly, NULL, NULL, NULL, LDAP_NO_LIMIT,
@@ -1070,6 +1092,11 @@ ldap_query(ldap_instance_t *ldap_inst, const char *base, int scope, char **attrs
ldap_inst->result));
return ISC_R_SUCCESS;
+
+cleanup:
+ log_error("error reading from ldap: %s", err_string);
+
+ return ISC_R_FAILURE;
}
static isc_result_t
@@ -1394,3 +1421,214 @@ cleanup:
return ISC_R_FAILURE;
}
+
+/* FIXME: Handle the case where the LDAP handle is NULL -> try to reconnect. */
+/* FIXME: Handle cases where the entry actually doesn't exist. */
+static isc_result_t
+ldap_modify_do(ldap_instance_t *ldap_inst, const char *dn, LDAPMod **mods)
+{
+ int ret;
+
+ REQUIRE(ldap_inst != NULL);
+ REQUIRE(dn != NULL);
+ REQUIRE(mods != NULL);
+
+ log_debug(2, "writing to to '%s'", dn);
+
+ ret = ldap_modify_ext_s(ldap_inst->handle, dn, mods, NULL, NULL);
+ if (ret != LDAP_SUCCESS) {
+ log_error("error writing to ldap: %s", ldap_err2string(ret));
+ return ISC_R_FAILURE;
+ }
+
+ return ISC_R_SUCCESS;
+}
+
+static isc_result_t
+ldap_rdatalist_to_ldapmod(isc_mem_t *mctx, dns_rdatalist_t *rdlist,
+ LDAPMod ***change_listp, int mod_op)
+{
+ isc_result_t result;
+ unsigned int i;
+ unsigned int rdtype_count;
+ size_t change_list_size;
+ LDAPMod **change_list = NULL;
+ dns_rdatalist_t *node;
+
+ REQUIRE(change_listp != NULL && *change_listp == NULL);
+
+ /* Count number of rdtypes. */
+ rdtype_count = 0;
+ for (node = rdlist; node != NULL; node = NEXT(node, link))
+ rdtype_count++;
+
+ change_list_size = (rdtype_count + 1) * sizeof(LDAPMod *);
+ CHECKED_MEM_GET(mctx, change_list, change_list_size);
+ memset(change_list, 0, change_list_size);
+
+ node = rdlist;
+ for (i = 0; i < rdtype_count && node != NULL; i++) {
+ char **vals;
+ const char *attr_name_c;
+ char *attr_name;
+
+ vals = NULL;
+ CHECKED_MEM_GET_PTR(mctx, change_list[i]);
+ ZERO_PTR(change_list[i]);
+
+ result = rdatatype_to_ldap_attribute(node->type, &attr_name_c);
+ if (result != ISC_R_SUCCESS) {
+ result = ISC_R_FAILURE;
+ goto cleanup;
+ }
+ DE_CONST(attr_name_c, attr_name);
+ CHECK(ldap_rdata_to_char_array(mctx, HEAD(node->rdata),
+ &vals));
+
+ change_list[i]->mod_op = mod_op;
+ change_list[i]->mod_type = attr_name;
+ change_list[i]->mod_values = vals;
+
+ node = NEXT(node, link);
+ }
+
+ *change_listp = change_list;
+ return ISC_R_SUCCESS;
+
+cleanup:
+ free_ldapmod_array(mctx, &change_list);
+
+ return result;
+}
+
+static void
+free_ldapmod_array(isc_mem_t *mctx, LDAPMod ***change_listp)
+{
+ LDAPMod **change_list;
+ unsigned int item;
+
+ REQUIRE(change_listp != NULL);
+
+ change_list = *change_listp;
+ if (change_list == NULL)
+ return;
+
+ for (item = 0; change_list[item] != NULL; item++) {
+ free_char_array(mctx, &change_list[item]->mod_values);
+ SAFE_MEM_PUT_PTR(mctx, change_list[item]);
+ }
+ isc_mem_free(mctx, change_list);
+ *change_listp = NULL;
+}
+
+isc_result_t
+ldap_rdata_to_char_array(isc_mem_t *mctx, dns_rdata_t *rdata_head,
+ char ***valsp)
+{
+ isc_result_t result;
+ char **vals;
+ unsigned int i;
+ unsigned int rdata_count = 0;
+ size_t vals_size;
+ dns_rdata_t *rdata;
+
+ REQUIRE(rdata_head != NULL);
+ REQUIRE(valsp != NULL && *valsp == NULL);
+
+ for (rdata = rdata_head; rdata != NULL; rdata = NEXT(rdata, link))
+ rdata_count++;
+
+ vals_size = (rdata_count + 1) * sizeof(char *);
+ CHECKED_MEM_GET(mctx, vals, vals_size);
+ memset(vals, 0, vals_size);
+
+ rdata = rdata_head;
+ for (i = 0; i < rdata_count && rdata != NULL; i++) {
+ isc_buffer_t buffer;
+ isc_region_t region;
+ char data[MINTSIZ];
+
+ /* Convert rdata to text. */
+ isc_buffer_init(&buffer, data, MINTSIZ);
+ CHECK(dns_rdata_totext(rdata, NULL, &buffer));
+ isc_buffer_usedregion(&buffer, &region);
+
+ /* Now allocate the string with the right size. */
+ CHECKED_MEM_GET(mctx, vals[i], region.length + 1);
+ memcpy(vals[i], region.base, region.length);
+ vals[i][region.length] = '\0';
+
+ rdata = NEXT(rdata, link);
+ }
+
+ *valsp = vals;
+ return ISC_R_SUCCESS;
+
+cleanup:
+ free_char_array(mctx, &vals);
+ return result;
+}
+
+static void
+free_char_array(isc_mem_t *mctx, char ***valsp)
+{
+ char **vals;
+ unsigned int i;
+
+ REQUIRE(valsp != NULL);
+
+ vals = *valsp;
+ if (vals == NULL)
+ return;
+
+ for (i = 0; vals[i] != NULL; i++) {
+ isc_mem_free(mctx, vals[i]);
+ }
+
+ isc_mem_free(mctx, vals);
+ *valsp = NULL;
+}
+
+/*
+ * TODO: Handle updating of the SOA record, use the settings to determine if
+ * this is allowed.
+ */
+static isc_result_t
+modify_ldap_common(dns_name_t *owner, ldap_db_t *ldap_db,
+ dns_rdatalist_t *rdlist, int mod_op)
+{
+ isc_result_t result;
+ isc_mem_t *mctx;
+ ldap_instance_t *ldap_inst;
+ ld_string_t *owner_dn = NULL;
+ LDAPMod **change_list = NULL;
+
+ mctx = ldap_db->mctx;
+ 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(ldap_rdatalist_to_ldapmod(mctx, rdlist, &change_list, mod_op));
+
+ CHECK(ldap_modify_do(ldap_inst, str_buf(owner_dn), change_list));
+
+cleanup:
+ put_connection(ldap_inst);
+ free_ldapmod_array(mctx, &change_list);
+
+ return result;
+}
+
+isc_result_t
+write_to_ldap(dns_name_t *owner, ldap_db_t *ldap_db, dns_rdatalist_t *rdlist)
+{
+ return modify_ldap_common(owner, ldap_db, rdlist, LDAP_MOD_ADD);
+}
+
+isc_result_t
+remove_from_ldap(dns_name_t *owner, ldap_db_t *ldap_db,
+ dns_rdatalist_t *rdlist)
+{
+ return modify_ldap_common(owner, ldap_db, rdlist, LDAP_MOD_DELETE);
+}
diff --git a/ldap_helper.h b/ldap_helper.h
index 2c3c98b..32edd9c 100644
--- a/ldap_helper.h
+++ b/ldap_helper.h
@@ -90,4 +90,12 @@ 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);
+/* Functions for writing to LDAP. */
+isc_result_t ldap_rdata_to_char_array(isc_mem_t *mctx, dns_rdata_t *rdata_head,
+ char ***valsp);
+isc_result_t write_to_ldap(dns_name_t *owner, ldap_db_t *ldap_db,
+ dns_rdatalist_t *rdlist);
+isc_result_t remove_from_ldap(dns_name_t *owner, ldap_db_t *ldap_db,
+ dns_rdatalist_t *rdlist);
+
#endif /* !_LD_LDAP_HELPER_H_ */
diff --git a/str.c b/str.c
index 82edf73..99a1e6d 100644
--- a/str.c
+++ b/str.c
@@ -230,7 +230,7 @@ str_copy(ld_string_t *dest, const ld_string_t *src)
REQUIRE(src != NULL);
IGNORE_R(src->data == NULL);
- CHECK(str_alloc(dest, str_len_internal(src) * sizeof(char)));
+ CHECK(str_alloc(dest, str_len_internal(src)));
strncpy(dest->data, src->data, dest->allocated);
return ISC_R_SUCCESS;
@@ -279,7 +279,7 @@ str_init_char(ld_string_t *dest, const char *src)
REQUIRE(dest != NULL);
IGNORE_R(src == NULL);
- CHECK(str_alloc(dest, strlen(src) * sizeof(char)));
+ CHECK(str_alloc(dest, strlen(src)));
strncpy(dest->data, src, dest->allocated);
return ISC_R_SUCCESS;
@@ -290,6 +290,7 @@ cleanup:
/*
* Concatenate char *src to string dest.
+ * TODO: make str_cat_char() simply use str_cat_char_len()
*/
isc_result_t
str_cat_char(ld_string_t *dest, const char *src)
@@ -305,7 +306,9 @@ str_cat_char(ld_string_t *dest, const char *src)
dest_size = str_len_internal(dest);
src_size = strlen(src);
- CHECK(str_alloc(dest, (dest_size + src_size) * sizeof(char)));
+ IGNORE_R(src_size == 0);
+
+ CHECK(str_alloc(dest, dest_size + src_size));
from = dest->data + dest_size;
strncpy(from, src, src_size + 1);
@@ -315,6 +318,33 @@ 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;
+ size_t src_size;
+
+ REQUIRE(dest != NULL);
+ IGNORE_R(src != NULL);
+
+ 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));
+ from = dest->data + dest_size;
+ strncpy(from, src, src_size);
+ from[src_size - 1] = '\0';
+
+ return ISC_R_SUCCESS;
+
+cleanup:
+ return result;
+}
+
/*
* Concatenate string src to string dest.
*/
diff --git a/str.h b/str.h
index 96786ef..08305b6 100644
--- a/str.h
+++ b/str.h
@@ -51,6 +51,7 @@ isc_result_t str_clone(ld_string_t **dest, const ld_string_t *src _STR_MEM_FLARG
void str_clear(ld_string_t *dest);
isc_result_t str_init_char(ld_string_t *dest, const char *src);
isc_result_t str_cat_char(ld_string_t *dest, const char *src);
+isc_result_t str_cat_char_len(ld_string_t *dest, const char *src, size_t len);
isc_result_t str_cat(ld_string_t *dest, const ld_string_t *src);
isc_result_t str_sprintf(ld_string_t *dest, const char *format, ...);
isc_result_t str_vsprintf(ld_string_t *dest, const char *format, va_list ap);