diff options
author | Martin Nagy <mnagy@redhat.com> | 2009-02-13 04:25:42 +0100 |
---|---|---|
committer | Martin Nagy <mnagy@redhat.com> | 2009-02-13 04:25:42 +0100 |
commit | 2065d73266fe1abff3ae8a5554096f8dc06d4c33 (patch) | |
tree | ca7027705954f75bcc72d8bd2c0d35221cac7d7e | |
parent | b940e76941d845baaefa7408e7c939d7d73fd277 (diff) | |
download | ldap_driver-2065d73266fe1abff3ae8a5554096f8dc06d4c33.tar.gz ldap_driver-2065d73266fe1abff3ae8a5554096f8dc06d4c33.tar.xz ldap_driver-2065d73266fe1abff3ae8a5554096f8dc06d4c33.zip |
Add another LDAP helper functions.
-rw-r--r-- | ldap_helper.c | 242 |
1 files changed, 242 insertions, 0 deletions
diff --git a/ldap_helper.c b/ldap_helper.c index d5561c8..526adfe 100644 --- a/ldap_helper.c +++ b/ldap_helper.c @@ -55,6 +55,12 @@ typedef struct ldap_auth_pair ldap_auth_pair_t; typedef struct settings settings_t; +typedef struct ldap_value ldap_value_t; +typedef struct ldap_attribute ldap_attribute_t; +typedef struct ldap_entry ldap_entry_t; +typedef LIST(ldap_value_t) ldap_value_list_t; +typedef LIST(ldap_attribute_t) ldap_attribute_list_t; +typedef LIST(ldap_entry_t) ldap_entry_list_t; /* Authentication method. */ typedef enum ldap_auth { @@ -85,6 +91,24 @@ struct ldap_db { ldap_auth_t auth_method; }; +struct ldap_value { + char *value; + LINK(ldap_value_t) link; +}; + +struct ldap_attribute { + char *name; + char **ldap_values; + ldap_value_list_t values; + LINK(ldap_attribute_t) link; +}; + +struct ldap_entry { + LDAPMessage *entry; + ldap_attribute_list_t attributes; + LINK(ldap_entry_t) link; +}; + struct ldap_instance { ldap_db_t *database; isc_mutex_t lock; @@ -95,6 +119,15 @@ struct ldap_instance { LDAP *handle; LDAPMessage *result; + /* Parsing. */ + isc_lex_t *lex; + isc_buffer_t rdata_target; + unsigned char *rdata_target_mem; + + /* Cache. */ + ldap_entry_list_t ldap_entries; + isc_boolean_t cache_active; + /* Temporary stuff. */ LDAPMessage *entry; BerElement *ber; @@ -134,6 +167,20 @@ static isc_result_t ldap_connect(ldap_instance_t *ldap_inst); static isc_result_t ldap_query(ldap_instance_t *ldap_inst, int scope, char **attrs, int attrsonly, const char *filter, ...); + +static ldap_attribute_t * next_named_attribute(ldap_attribute_t *ldap_attr, + const char *name); +static isc_result_t fill_cache_if_empty(ldap_instance_t *inst); +static isc_result_t cache_query_results(ldap_instance_t *inst); +static isc_result_t fill_ldap_entry(ldap_instance_t *inst, + ldap_entry_t *ldap_entry); +static isc_result_t fill_ldap_attribute(ldap_instance_t *inst, + ldap_attribute_t *ldap_attr); +static void free_query_cache(ldap_instance_t *inst); +static void free_ldap_attributes(isc_mem_t *mctx, ldap_entry_t *entry); +static void free_ldap_values(isc_mem_t *mctx, ldap_attribute_t *attr); + + static const LDAPMessage *next_entry(ldap_instance_t *inst); static const char *next_attribute(ldap_instance_t *inst); static const char *get_attribute(ldap_instance_t *inst); @@ -624,6 +671,7 @@ get_connection(ldap_db_t *ldap_db) RUNTIME_CHECK(ldap_inst != NULL); + INIT_LIST(ldap_inst->ldap_entries); /* TODO: find a clever way to not really require this */ str_copy(ldap_inst->base, ldap_db->base); @@ -654,6 +702,8 @@ put_connection(ldap_instance_t *ldap_inst) ldap_inst->result = NULL; } + free_query_cache(ldap_inst); + UNLOCK(&ldap_inst->lock); semaphore_signal(&ldap_inst->database->conn_semaphore); } @@ -684,6 +734,198 @@ ldap_query(ldap_instance_t *ldap_inst, int scope, char **attrs, return ISC_R_SUCCESS; } +static ldap_attribute_t * +next_named_attribute(ldap_attribute_t *ldap_attr, const char *name) +{ + ldap_attribute_t *iterator; + + REQUIRE(ldap_attr != NULL); + REQUIRE(name != NULL); + + iterator = NEXT(ldap_attr, link); + while (iterator != NULL) { + if (strcasecmp(name, iterator->name) == 0) + return iterator; + iterator = NEXT(iterator, link); + } + + return NULL; +} + +static isc_result_t +fill_cache_if_empty(ldap_instance_t *inst) +{ + if (inst->cache_active) + return ISC_R_SUCCESS; + + return cache_query_results(inst); +} + +static isc_result_t +cache_query_results(ldap_instance_t *inst) +{ + isc_result_t result; + LDAP *ld; + LDAPMessage *res; + LDAPMessage *entry; + ldap_entry_t *ldap_entry; + + REQUIRE(inst != NULL); + REQUIRE(EMPTY(inst->ldap_entries)); + REQUIRE(inst->result != NULL); + + INIT_LIST(inst->ldap_entries); + + if (inst->cache_active) + free_query_cache(inst); + + ld = inst->handle; + res = inst->result; + + for (entry = ldap_first_entry(ld, res); + entry != NULL; + entry = ldap_next_entry(ld, entry)) { + CHECKED_MEM_GET_PTR(inst->database->mctx, ldap_entry); + ZERO_PTR(ldap_entry); + + ldap_entry->entry = entry; + INIT_LIST(ldap_entry->attributes); + INIT_LINK(ldap_entry, link); + CHECK(fill_ldap_entry(inst, ldap_entry)); + + APPEND(inst->ldap_entries, ldap_entry, link); + } + + return ISC_R_SUCCESS; + +cleanup: + free_query_cache(inst); + + return result; +} + +static isc_result_t +fill_ldap_entry(ldap_instance_t *inst, ldap_entry_t *ldap_entry) +{ + isc_result_t result; + ldap_attribute_t *ldap_attr; + char *attribute; + BerElement *ber; + LDAPMessage *entry; + + REQUIRE(inst != NULL); + REQUIRE(ldap_entry != NULL); + + result = ISC_R_SUCCESS; + entry = ldap_entry->entry; + + for (attribute = ldap_first_attribute(inst->handle, entry, &ber); + attribute != NULL; + attribute = ldap_next_attribute(inst->handle, entry, ber)) { + CHECKED_MEM_GET_PTR(inst->database->mctx, ldap_attr); + ZERO_PTR(ldap_attr); + + ldap_attr->name = attribute; + INIT_LIST(ldap_attr->values); + INIT_LINK(ldap_attr, link); + CHECK(fill_ldap_attribute(inst, ldap_attr)); + + APPEND(ldap_entry->attributes, ldap_attr, link); + } + + if (ber != NULL) + ber_free(ber, 0); + +cleanup: + if (result != ISC_R_SUCCESS) { + free_ldap_attributes(inst->database->mctx, ldap_entry); + } + + return result; +} + +static isc_result_t +fill_ldap_attribute(ldap_instance_t *inst, ldap_attribute_t *ldap_attr) +{ + isc_result_t result; + char **values; + ldap_value_t *ldap_val; + + REQUIRE(inst != NULL); + REQUIRE(ldap_attr != NULL); + + values = ldap_get_values(inst->handle, inst->result, ldap_attr->name); + /* TODO: proper ldap error handling */ + if (values == NULL) + return ISC_R_FAILURE; + + ldap_attr->ldap_values = values; + + for (unsigned int i = 0; values[i] != NULL; i++) { + CHECKED_MEM_GET_PTR(inst->database->mctx, ldap_val); + ldap_val->value = values[i]; + INIT_LINK(ldap_val, link); + + APPEND(ldap_attr->values, ldap_val, link); + } + + return ISC_R_SUCCESS; + +cleanup: + free_ldap_values(inst->database->mctx, ldap_attr); + ldap_value_free(values); + + return result; +} + +static void +free_query_cache(ldap_instance_t *inst) +{ + ldap_entry_t *entry, *next; + + entry = HEAD(inst->ldap_entries); + while (entry != NULL) { + next = NEXT(entry, link); + UNLINK(inst->ldap_entries, entry, link); + free_ldap_attributes(inst->database->mctx, entry); + isc_mem_put(inst->database->mctx, entry, sizeof(*entry)); + entry = next; + } + + inst->cache_active = isc_boolean_false; +} + +static void +free_ldap_attributes(isc_mem_t *mctx, ldap_entry_t *entry) +{ + ldap_attribute_t *attr, *next; + + attr = HEAD(entry->attributes); + while (attr != NULL) { + next = NEXT(attr, link); + UNLINK(entry->attributes, attr, link); + free_ldap_values(mctx, attr); + ldap_value_free(attr->ldap_values); + ldap_memfree(attr->name); + isc_mem_put(mctx, attr, sizeof(*attr)); + attr = next; + } +} + +static void +free_ldap_values(isc_mem_t *mctx, ldap_attribute_t *attr) +{ + ldap_value_t *value, *next; + + value = HEAD(attr->values); + while (value != NULL) { + next = NEXT(value, link); + UNLINK(attr->values, value, link); + isc_mem_put(mctx, value, sizeof(*value)); + value = next; + } +} + static const LDAPMessage * next_entry(ldap_instance_t *inst) { |