/* * 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 SWITCH_MODULE_LOAD_FUNCTION(mod_ldap_load); SWITCH_MODULE_DEFINITION(mod_ldap, mod_ldap_load, NULL, NULL); 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_t mod_ldap_open(switch_directory_handle_t *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))) == 0) { 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_info = context; return SWITCH_STATUS_SUCCESS; } static switch_status_t mod_ldap_close(switch_directory_handle_t *dh) { struct ldap_context *context; context = dh->private_info; switch_assert(context != NULL); ldap_unbind_s(context->ld); return SWITCH_STATUS_SUCCESS; } static switch_status_t mod_ldap_query(switch_directory_handle_t *dh, char *base, char *query) { struct ldap_context *context; char **attrs = NULL; context = dh->private_info; switch_assert(context != NULL); #if _MSC_VER >= 1500 /* Silence warning from incorrect code analysis signature. attrs == NULL indicates to return all attrs */ /* http://msdn2.microsoft.com/en-us/library/aa908101.aspx */ __analysis_assume(attrs); #endif if (ldap_search_s(context->ld, base, LDAP_SCOPE_SUBTREE, query, attrs, 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_t mod_ldap_next(switch_directory_handle_t *dh) { struct ldap_context *context; context = dh->private_info; switch_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; } static switch_status_t mod_ldap_next_pair(switch_directory_handle_t *dh, char **var, char **val) { struct ldap_context *context; context = dh->private_info; switch_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)) != 0) { goto itter; } } return SWITCH_STATUS_FALSE; } SWITCH_MODULE_LOAD_FUNCTION(mod_ldap_load) { switch_directory_interface_t *dir_interface; /* connect my internal structure to the blank pointer passed to me */ *module_interface = switch_loadable_module_create_module_interface(pool, modname); dir_interface = switch_loadable_module_create_interface(*module_interface, SWITCH_DIRECTORY_INTERFACE); dir_interface->interface_name = "ldap"; dir_interface->directory_open = mod_ldap_open; dir_interface->directory_close = mod_ldap_close; dir_interface->directory_query = mod_ldap_query; dir_interface->directory_next = mod_ldap_next; dir_interface->directory_next_pair = mod_ldap_next_pair; /* indicate that the module should continue to be loaded */ return SWITCH_STATUS_SUCCESS; } /* For Emacs: * Local Variables: * mode:c * indent-tabs-mode:t * tab-width:4 * c-basic-offset:4 * End: * For VIM: * vim:set softtabstop=4 shiftwidth=4 tabstop=4: */