diff options
author | Martin Nagy <mnagy@redhat.com> | 2009-03-10 10:10:45 +0100 |
---|---|---|
committer | Martin Nagy <mnagy@redhat.com> | 2009-03-16 15:45:47 +0100 |
commit | 2ed654359d3c45298ad9c8446c017908dcd07ef0 (patch) | |
tree | 381b094ffa20135c8fe76e49fed99fedaf913df4 | |
parent | 038f85774090e12e0c8c61aadaea50f99da1e32b (diff) | |
download | ldap_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.c | 1 | ||||
-rw-r--r-- | ldap_helper.c | 240 | ||||
-rw-r--r-- | ldap_helper.h | 8 | ||||
-rw-r--r-- | str.c | 36 | ||||
-rw-r--r-- | str.h | 1 |
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, ®ion); + + /* 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_ */ @@ -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. */ @@ -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); |