123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493 |
- /*
- * $Id$
- *
- * Kamailio LDAP Module
- *
- * Copyright (C) 2007 University of North Carolina
- *
- * Original author: Christian Schlatter, [email protected]
- *
- *
- * This file is part of Kamailio, a free SIP server.
- *
- * Kamailio is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version
- *
- * Kamailio is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * History:
- * --------
- * 2007-02-18: Initial version
- */
- #include <unistd.h>
- #include <stdarg.h>
- #include "../../ut.h"
- #include <ldap.h>
- #include "ldap_api_fn.h"
- #include "api.h"
- #include "ldap_connect.h"
- #include "ldap_escape.h"
- #include "ld_session.h"
- static LDAP* last_ldap_handle = NULL;
- static LDAPMessage* last_ldap_result = NULL;
- int get_connected_ldap_session(
- char* _lds_name,
- struct ld_session** _lds);
- int lds_search(char* _lds_name,
- char* _dn,
- int _scope,
- char* _filter,
- char** _attrs,
- struct timeval* _search_timeout,
- int* _ld_result_count,
- int* _ld_error);
- int load_ldap(ldap_api_t *api)
- {
- if (api == NULL)
- {
- return -1;
- }
- api->ldap_params_search = ldap_params_search;
- api->ldap_url_search = ldap_url_search;
- api->ldap_result_attr_vals = ldap_get_attr_vals;
- api->ldap_value_free_len = ldap_value_free_len;
- api->ldap_result_next = ldap_inc_result_pointer;
- api->ldap_str2scope = ldap_str2scope;
- api->ldap_rfc4515_escape = ldap_rfc4515_escape;
- api->get_ldap_handle = get_ldap_handle;
- api->get_last_ldap_result = get_last_ldap_result;
- return 1;
- }
- int get_ldap_handle(char* _lds_name, LDAP** _ldap_handle)
- {
- int rc;
- struct ld_session* lds;
- rc = get_connected_ldap_session(_lds_name, &lds);
- if (rc == 0)
- {
- *_ldap_handle = lds->handle;
- }
- return rc;
- }
- int get_connected_ldap_session(char* _lds_name, struct ld_session** _lds)
- {
- /*
- * get ld session
- */
- if ((*_lds = get_ld_session(_lds_name)) == NULL)
- {
- LM_ERR("[%s]: ldap_session not found\n", _lds_name);
- return -1;
- }
- /* try to reconnect if ldap session handle is NULL */
- if ((*_lds)->handle == NULL)
- {
- if (ldap_reconnect(_lds_name) == 0)
- {
- if ((*_lds = get_ld_session(_lds_name)) == NULL)
- {
- LM_ERR("[%s]: ldap_session not found\n", _lds_name);
- return -1;
- }
- }
- else
- {
- if (last_ldap_result != NULL)
- {
- ldap_msgfree(last_ldap_result);
- last_ldap_result = NULL;
- }
- ldap_disconnect(_lds_name);
- LM_ERR("[%s]: reconnect failed\n", _lds_name);
- return -1;
- }
- }
- /* free old last_ldap_result */
- /*
- * this is done now in lds_search
- *
- if (last_ldap_result != NULL) {
- ldap_msgfree(last_ldap_result);
- last_ldap_result = NULL;
- }
- */
-
- return 0;
- }
- void get_last_ldap_result(LDAP** _last_ldap_handle, LDAPMessage** _last_ldap_result)
- {
- *_last_ldap_handle = last_ldap_handle;
- *_last_ldap_result = last_ldap_result;
- }
- int ldap_params_search(
- int* _ld_result_count,
- char* _lds_name,
- char* _dn,
- int _scope,
- char** _attrs,
- char* _filter,
- ...)
- {
- int rc;
- static char filter_str[LDAP_MAX_FILTER_LEN];
- char *filter_ptr = NULL;
- va_list filter_vars;
- /*
- * check _scope
- */
- switch (_scope)
- {
- case LDAP_SCOPE_ONELEVEL:
- case LDAP_SCOPE_BASE:
- case LDAP_SCOPE_SUBTREE:
- break;
- default:
- LM_ERR("[%s]: invalid scope argument [%d]\n", _lds_name, _scope);
- return -1;
- }
- if (_filter) {
- /*
- * vsnprintf
- */
- va_start(filter_vars, _filter);
- rc = vsnprintf(filter_str, (size_t)LDAP_MAX_FILTER_LEN, _filter,
- filter_vars);
- va_end(filter_vars);
- if (rc >= LDAP_MAX_FILTER_LEN)
- {
- LM_ERR( "[%s]: filter string too long (len [%d], max len [%d])\n",
- _lds_name,
- rc,
- LDAP_MAX_FILTER_LEN);
- return -1;
- }
- else if (rc < 0)
- {
- LM_ERR("vsnprintf failed\n");
- return -1;
- }
- filter_ptr = filter_str;
- }
- /*
- * ldap search
- */
- if (lds_search(_lds_name,
- _dn,
- _scope,
- filter_ptr,
- _attrs,
- NULL,
- _ld_result_count,
- &rc)
- != 0)
- {
- /* try again if LDAP API ERROR */
- if (LDAP_API_ERROR(rc) &&
- (lds_search(_lds_name,
- _dn,
- _scope,
- filter_str,
- _attrs,
- NULL,
- _ld_result_count,
- &rc) != 0))
- {
- LM_ERR( "[%s]: LDAP search (dn [%s], scope [%d],"
- " filter [%s]) failed: %s\n",
- _lds_name,
- _dn,
- _scope,
- filter_str,
- ldap_err2string(rc));
- return -1;
- }
- }
-
- LM_DBG( "[%s]: [%d] LDAP entries found\n",
- _lds_name,
- *_ld_result_count);
-
- return 0;
- }
- int ldap_url_search(
- char* _ldap_url,
- int* _ld_result_count)
- {
- LDAPURLDesc *ludp;
- int rc;
- if (ldap_url_parse(_ldap_url, &ludp) != 0) {
- LM_ERR("invalid LDAP URL [%s]\n", ZSW(_ldap_url));
- if (ludp != NULL) {
- ldap_free_urldesc(ludp);
- }
- return -2;
- }
- if (ludp->lud_host == NULL)
- {
- LM_ERR( "no ldap session name found in ldap URL [%s]\n",
- ZSW(_ldap_url));
- return -2;
- }
- LM_DBG( "LDAP URL parsed into session_name"
- " [%s], base [%s], scope [%d], filter [%s]\n",
- ZSW(ludp->lud_host),
- ZSW(ludp->lud_dn),
- ludp->lud_scope,
- ZSW(ludp->lud_filter));
- rc = ldap_params_search(_ld_result_count,
- ludp->lud_host,
- ludp->lud_dn,
- ludp->lud_scope,
- ludp->lud_attrs,
- ludp->lud_filter);
- ldap_free_urldesc(ludp);
- return rc;
- }
- int ldap_inc_result_pointer(void)
- {
- LDAPMessage *next_result = NULL;
- /*
- * check for last_ldap_result
- */
- if (last_ldap_result == NULL) {
- LM_ERR("last_ldap_result == NULL\n");
- return -1;
- }
- if (last_ldap_handle == NULL)
- {
- LM_ERR("last_ldap_handle == NULL\n");
- return -1;
- }
- /*
- * get next LDAP result pointer
- */
- if ((next_result = ldap_next_entry(last_ldap_handle, last_ldap_result))
- == NULL)
- {
- /* no more LDAP entries */
- return 1;
- }
- last_ldap_result = next_result;
- return 0;
- }
- int ldap_get_attr_vals(str *_attr_name, struct berval ***_vals)
- {
- BerElement *ber;
- char *a;
- /*
- * check for last_ldap_result
- */
- if (last_ldap_result == NULL) {
- LM_ERR("last_ldap_result == NULL\n");
- return -1;
- }
- if (last_ldap_handle == NULL)
- {
- LM_ERR("last_ldap_handle == NULL\n");
- return -1;
- }
- /*
- * search for attribute named _attr_name
- */
- *_vals = NULL;
- for (a = ldap_first_attribute(last_ldap_handle,
- last_ldap_result,
- &ber);
- a != NULL;
- a = ldap_next_attribute(last_ldap_handle,
- last_ldap_result,
- ber))
- {
- if (strncmp(a, _attr_name->s, _attr_name->len) == 0) {
- *_vals = ldap_get_values_len(
- last_ldap_handle,
- last_ldap_result,
- a);
- ldap_memfree(a);
- break;
- }
- ldap_memfree(a);
- }
- if (ber != NULL) {
- ber_free(ber, 0);
- }
- if (*_vals != NULL)
- {
- return 0;
- } else {
- return 1;
- }
- }
- int ldap_str2scope(char* scope_str)
- {
- if ( strcasecmp( scope_str, "one" ) == 0 ) {
- return LDAP_SCOPE_ONELEVEL;
- } else if ( strcasecmp( scope_str, "onelevel" ) == 0 ) {
- return LDAP_SCOPE_ONELEVEL;
- } else if ( strcasecmp( scope_str, "base" ) == 0 ) {
- return LDAP_SCOPE_BASE;
- } else if ( strcasecmp( scope_str, "sub" ) == 0 ) {
- return LDAP_SCOPE_SUBTREE;
- } else if ( strcasecmp( scope_str, "subtree" ) == 0 ) {
- return LDAP_SCOPE_SUBTREE;
- };
- return( -1 );
- }
- /*
- * sets last_ldap_result and last_ldap_handle
- */
- int lds_search(
- char* _lds_name,
- char* _dn,
- int _scope,
- char* _filter,
- char** _attrs,
- struct timeval* _search_timeout,
- int* _ld_result_count,
- int* _ld_error)
- {
- struct ld_session* lds;
- #ifdef LDAP_PERF
- struct timeval before_search = { 0, 0 }, after_search = { 0, 0 };
- #endif
- /*
- * get ld_handle
- */
- if (get_connected_ldap_session(_lds_name, &lds) != 0)
- {
- LM_ERR("[%s]: couldn't get ldap session\n", _lds_name);
- return -1;
- }
- /*
- * free last_ldap_result
- */
- if (last_ldap_result != NULL) {
- ldap_msgfree(last_ldap_result);
- last_ldap_result = NULL;
- }
-
- LM_DBG( "[%s]: performing LDAP search: dn [%s],"
- " scope [%d], filter [%s], client_timeout [%d] usecs\n",
- _lds_name,
- _dn,
- _scope,
- _filter,
- (int)(lds->client_search_timeout.tv_sec * 1000000
- + lds->client_search_timeout.tv_usec));
-
- #ifdef LDAP_PERF
- gettimeofday(&before_search, NULL);
- #endif
- /*
- * perform ldap search
- */
- *_ld_error = ldap_search_ext_s(
- lds->handle,
- _dn,
- _scope,
- _filter,
- _attrs,
- 0,
- NULL,
- NULL,
- &lds->client_search_timeout,
- 0,
- &last_ldap_result);
- #ifdef LDAP_PERF
- gettimeofday(&after_search, NULL);
- LM_INFO("[%s]: LDAP search took [%d] usecs\n",
- _lds_name,
- (int)((after_search.tv_sec * 1000000 + after_search.tv_usec)
- - (before_search.tv_sec * 1000000 + before_search.tv_usec)));
- #endif
- if (*_ld_error != LDAP_SUCCESS)
- {
- if (last_ldap_result != NULL)
- {
- ldap_msgfree(last_ldap_result);
- last_ldap_result = NULL;
- }
- if (LDAP_API_ERROR(*_ld_error))
- {
- ldap_disconnect(_lds_name);
- }
-
- LM_DBG( "[%s]: ldap_search_ext_st failed: %s\n",
- _lds_name,
- ldap_err2string(*_ld_error));
- return -1;
- }
- last_ldap_handle = lds->handle;
- *_ld_result_count = ldap_count_entries(lds->handle, last_ldap_result);
- if (*_ld_result_count < 0)
- {
- LM_DBG("[%s]: ldap_count_entries failed\n", _lds_name);
- return -1;
- }
- return 0;
- }
|