/* * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application * Copyright (C) 2005/2006, Anthony Minessale II * * Version: MPL 1.1 * * The contents of this file are subject to the Mozilla Public License Version * 1.1 (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License * for the specific language governing rights and limitations under the * License. * * The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application * * The Initial Developer of the Original Code is * Anthony Minessale II * Portions created by the Initial Developer are Copyright (C) * the Initial Developer. All Rights Reserved. * * Contributor(s): * * Anthony Minessale II * * * mod_ldap.c -- LDAP * */ #include #ifdef MSLDAP #include #include #include #define LDAP_OPT_SUCCESS LDAP_SUCCESS #else #include #include #endif static const char modname[] = "mod_ldap"; struct ldap_context { LDAP *ld; LDAPMessage* msg; LDAPMessage* entry; BerElement* ber; char* attr; char *var; char *val; char **vals; int itt; int vitt; int vi; }; static switch_status mod_ldap_open(switch_directory_handle *dh, char *source, char *dsn, char *passwd) { struct ldap_context *context; int auth_method = LDAP_AUTH_SIMPLE; int desired_version = LDAP_VERSION3; if (!(context = switch_core_alloc(dh->memory_pool, sizeof(*context)))) { return SWITCH_STATUS_MEMERR; } if ((context->ld = ldap_init(source, LDAP_PORT)) == NULL ) { return SWITCH_STATUS_FALSE; } /* set the LDAP version to be 3 */ if (ldap_set_option(context->ld, LDAP_OPT_PROTOCOL_VERSION, &desired_version) != LDAP_OPT_SUCCESS) { return SWITCH_STATUS_FALSE; } if (ldap_bind_s(context->ld, dsn, passwd, auth_method) != LDAP_SUCCESS ) { return SWITCH_STATUS_FALSE; } dh->private = context; return SWITCH_STATUS_SUCCESS; } static switch_status mod_ldap_close(switch_directory_handle *dh) { struct ldap_context *context; context = dh->private; assert(context != NULL); ldap_unbind_s(context->ld); return SWITCH_STATUS_SUCCESS; } static switch_status mod_ldap_query(switch_directory_handle *dh, char *base, char *query) { struct ldap_context *context; context = dh->private; assert(context != NULL); if (ldap_search_s(context->ld, base, LDAP_SCOPE_SUBTREE, query, NULL, 0, &context->msg) != LDAP_SUCCESS) { return SWITCH_STATUS_FALSE; } if (ldap_count_entries(context->ld, context->msg) <= 0) { return SWITCH_STATUS_FALSE; } return SWITCH_STATUS_SUCCESS; } static switch_status mod_ldap_next(switch_directory_handle *dh) { struct ldap_context *context; context = dh->private; assert(context != NULL); context->vitt = 0; if (!context->itt) { context->entry = ldap_first_entry(context->ld, context->msg); context->itt++; } else if (context->entry) { context->entry = ldap_next_entry(context->ld, context->entry); context->itt++; } if (!context->entry) { return SWITCH_STATUS_FALSE; } return SWITCH_STATUS_SUCCESS; } switch_status mod_ldap_next_pair(switch_directory_handle *dh, char **var, char **val) { struct ldap_context *context; context = dh->private; assert(context != NULL); *var = *val = NULL; if (!context->entry) { return SWITCH_STATUS_FALSE; } if (!context->vitt) { context->var = "dn"; context->val = ldap_get_dn(context->ld, context->entry); context->vitt++; *var = context->var; *val = context->val; return SWITCH_STATUS_SUCCESS; } else { itter: if (context->attr && context->vals) { if ((*val = context->vals[context->vi++])) { *var = context->attr; return SWITCH_STATUS_SUCCESS; } else { ldap_value_free(context->vals); context->vals = NULL; context->vi = 0; } } if (context->vitt == 1) { ldap_memfree(context->val); context->val = NULL; if (context->ber) { ber_free(context->ber,0); context->ber = NULL; } context->attr = ldap_first_attribute(context->ld, context->entry, &context->ber); } else { if (context->attr) { ldap_memfree(context->attr); } context->attr = ldap_next_attribute(context->ld, context->entry, context->ber); } context->vitt++; if (context->entry && context->attr && (context->vals = ldap_get_values(context->ld, context->entry, context->attr))) { goto itter; } } return SWITCH_STATUS_FALSE; } static const switch_directory_interface ldap_directory_interface = { /*.interface_name */ "ldap", /*.directory_open*/ mod_ldap_open, /*.directory_close*/ mod_ldap_close, /*.directory_query*/ mod_ldap_query, /*.directory_next*/ mod_ldap_next, /*.directory_next_pair*/ mod_ldap_next_pair }; static switch_loadable_module_interface skel_module_interface = { /*.module_name */ modname, /*.endpoint_interface */ NULL, /*.timer_interface */ NULL, /*.dialplan_interface */ NULL, /*.codec_interface */ NULL, /*.application_interface */ NULL, /*.api_interface */ NULL, /*.file_interface */ NULL, /*.speech_interface */ NULL, /*.directory_interface */ &ldap_directory_interface }; switch_status switch_module_load(const switch_loadable_module_interface **interface, char *filename) { /* connect my internal structure to the blank pointer passed to me */ *interface = &skel_module_interface; /* indicate that the module should continue to be loaded */ return SWITCH_STATUS_SUCCESS; }