ldap_api_fn.c

Go to the documentation of this file.
00001 /*
00002 * $Id: ldap_api_fn.c 4585 2008-08-06 08:20:30Z klaus_darilion $
00003 *
00004 * Kamailio LDAP Module
00005 *
00006 * Copyright (C) 2007 University of North Carolina
00007 *
00008 * Original author: Christian Schlatter, cs@unc.edu
00009 *
00010 *
00011 * This file is part of Kamailio, a free SIP server.
00012 *
00013 * Kamailio is free software; you can redistribute it and/or modify
00014 * it under the terms of the GNU General Public License as published by
00015 * the Free Software Foundation; either version 2 of the License, or
00016 * (at your option) any later version
00017 *
00018 * Kamailio is distributed in the hope that it will be useful,
00019 * but WITHOUT ANY WARRANTY; without even the implied warranty of
00020 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00021 * GNU General Public License for more details.
00022 *
00023 * You should have received a copy of the GNU General Public License
00024 * along with this program; if not, write to the Free Software
00025 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00026 *
00027 * History:
00028 * --------
00029 * 2007-02-18: Initial version
00030 */
00031 
00032 
00033 #include <unistd.h>
00034 #include <stdarg.h>
00035 
00036 #include "../../ut.h"
00037 
00038 #include <ldap.h>
00039 
00040 #include "ldap_api_fn.h"
00041 #include "api.h"
00042 #include "ldap_connect.h"
00043 #include "ldap_escape.h"
00044 #include "ld_session.h"
00045 
00046 static LDAP* last_ldap_handle = NULL;
00047 static LDAPMessage* last_ldap_result = NULL;
00048 
00049 int get_connected_ldap_session(
00050    char* _lds_name, 
00051    struct ld_session** _lds);
00052    int lds_search(char* _lds_name,
00053    char* _dn,
00054    int _scope,
00055    char* _filter,
00056    char** _attrs,
00057    struct timeval* _search_timeout,
00058    int* _ld_result_count,
00059    int* _ld_error);
00060 
00061 
00062 int load_ldap(ldap_api_t *api)
00063 {
00064    if (api == NULL)
00065    {
00066       return -1;
00067    }
00068 
00069    api->ldap_params_search    = ldap_params_search;
00070    api->ldap_url_search       = ldap_url_search;
00071    api->ldap_result_attr_vals = ldap_get_attr_vals;
00072    api->ldap_value_free_len   = ldap_value_free_len;
00073    api->ldap_result_next      = ldap_inc_result_pointer;
00074    api->ldap_str2scope        = ldap_str2scope;
00075    api->ldap_rfc4515_escape   = ldap_rfc4515_escape;
00076    api->get_ldap_handle       = get_ldap_handle;
00077    api->get_last_ldap_result  = get_last_ldap_result;
00078 
00079    return 1;
00080 }
00081 
00082 int get_ldap_handle(char* _lds_name, LDAP** _ldap_handle)
00083 {
00084    int rc;
00085    struct ld_session* lds;
00086 
00087    rc = get_connected_ldap_session(_lds_name, &lds);
00088    if (rc == 0)
00089    {
00090       *_ldap_handle = lds->handle;
00091    }
00092    return rc;
00093 }
00094 
00095 int get_connected_ldap_session(char* _lds_name, struct ld_session** _lds)
00096 {  
00097    /*
00098    * get ld session
00099    */
00100    if ((*_lds = get_ld_session(_lds_name)) == NULL)
00101    {
00102       LM_ERR("[%s]: ldap_session not found\n", _lds_name);
00103       return -1;
00104    }
00105 
00106    /* try to reconnect if ldap session handle is NULL */
00107    if ((*_lds)->handle == NULL)
00108    {
00109       if (ldap_reconnect(_lds_name) == 0)
00110       {
00111          if ((*_lds = get_ld_session(_lds_name)) == NULL)
00112          {
00113             LM_ERR("[%s]: ldap_session not found\n", _lds_name);
00114             return -1;
00115          }
00116       }
00117       else
00118       {
00119          if (last_ldap_result != NULL)
00120          {
00121             ldap_msgfree(last_ldap_result);
00122             last_ldap_result = NULL;
00123          }
00124          ldap_disconnect(_lds_name);
00125          LM_ERR("[%s]: reconnect failed\n", _lds_name);
00126          return -1;
00127       }
00128    }
00129 
00130    /* free old last_ldap_result */
00131    /*
00132     * this is done now in lds_search
00133     *
00134 
00135    if (last_ldap_result != NULL) {
00136       ldap_msgfree(last_ldap_result);
00137       last_ldap_result = NULL;
00138    }
00139    */
00140    
00141    return 0;
00142 }
00143 
00144 void get_last_ldap_result(LDAP** _last_ldap_handle, LDAPMessage** _last_ldap_result)
00145 {
00146    *_last_ldap_handle = last_ldap_handle;
00147    *_last_ldap_result = last_ldap_result;
00148 }
00149 
00150 int ldap_params_search(
00151    int* _ld_result_count,
00152    char* _lds_name,
00153    char* _dn,
00154    int _scope,
00155    char** _attrs,
00156    char* _filter,
00157    ...)
00158 {
00159    int rc;
00160    static char filter_str[LDAP_MAX_FILTER_LEN];
00161    va_list filter_vars;
00162 
00163    /*
00164    * check _scope
00165    */
00166    switch (_scope)
00167    {
00168    case LDAP_SCOPE_ONELEVEL:
00169    case LDAP_SCOPE_BASE:
00170    case LDAP_SCOPE_SUBTREE:
00171       break;
00172    default:
00173       LM_ERR("[%s]: invalid scope argument [%d]\n", _lds_name, _scope);
00174       return -1;
00175    }
00176 
00177    /*
00178    * vsnprintf
00179    */
00180    va_start(filter_vars, _filter);
00181    rc = vsnprintf(filter_str, (size_t)LDAP_MAX_FILTER_LEN, _filter,
00182          filter_vars);
00183    if (rc >= LDAP_MAX_FILTER_LEN)
00184    {
00185       LM_ERR(  "[%s]: filter string too long (len [%d], max len [%d])\n",
00186          _lds_name,
00187          rc, 
00188          LDAP_MAX_FILTER_LEN);
00189       return -1;
00190    }
00191    else if (rc < 0)
00192    {
00193       LM_ERR("vsnprintf failed\n");
00194       return -1;
00195    }
00196 
00197    /*
00198    * ldap search
00199    */
00200    if (lds_search(_lds_name,
00201          _dn,
00202          _scope,
00203          filter_str,
00204          _attrs,
00205          NULL,
00206          _ld_result_count,
00207          &rc)
00208       != 0)
00209    {
00210       /* try again if LDAP API ERROR */
00211       if (LDAP_API_ERROR(rc) && 
00212             (lds_search(_lds_name,
00213                   _dn,
00214                   _scope,
00215                   filter_str,
00216                   _attrs,
00217                   NULL,
00218                   _ld_result_count,
00219                   &rc) != 0))
00220       {
00221          LM_ERR(  "[%s]: LDAP search (dn [%s], scope [%d],"
00222             " filter [%s]) failed: %s\n",
00223             _lds_name,
00224             _dn,
00225             _scope,
00226             filter_str,
00227             ldap_err2string(rc));
00228          return -1;
00229       }
00230    }
00231    
00232    LM_DBG(  "[%s]: [%d] LDAP entries found\n", 
00233       _lds_name,
00234       *_ld_result_count);
00235    
00236    return 0;
00237 }
00238 
00239 
00240 int ldap_url_search(
00241    char* _ldap_url,
00242    int* _ld_result_count)
00243 {
00244    LDAPURLDesc *ludp;
00245    int rc;
00246 
00247    if (ldap_url_parse(_ldap_url, &ludp) != 0) {
00248       LM_ERR("invalid LDAP URL [%s]\n", ZSW(_ldap_url));
00249       if (ludp != NULL) {
00250          ldap_free_urldesc(ludp);
00251       }
00252       return -2;
00253    }
00254    if (ludp->lud_host == NULL)
00255    {
00256       LM_ERR(  "no ldap session name found in ldap URL [%s]\n",
00257          ZSW(_ldap_url));
00258       return -2;
00259    }
00260 
00261 
00262    LM_DBG(  "LDAP URL parsed into session_name"
00263       " [%s], base [%s], scope [%d], filter [%s]\n",
00264       ZSW(ludp->lud_host),
00265       ZSW(ludp->lud_dn),
00266       ludp->lud_scope,
00267       ZSW(ludp->lud_filter));
00268 
00269    rc = ldap_params_search(_ld_result_count,
00270       ludp->lud_host,
00271       ludp->lud_dn,
00272       ludp->lud_scope,
00273       ludp->lud_attrs,
00274       ludp->lud_filter);
00275    ldap_free_urldesc(ludp);
00276    return rc;
00277 }
00278 
00279 
00280 int ldap_inc_result_pointer(void)
00281 {
00282    LDAPMessage *next_result = NULL;
00283 
00284    /*
00285    * check for last_ldap_result
00286    */
00287    if (last_ldap_result == NULL) {
00288       LM_ERR("last_ldap_result == NULL\n");
00289       return -1;
00290    }
00291    if (last_ldap_handle == NULL)
00292    {
00293       LM_ERR("last_ldap_handle == NULL\n");
00294       return -1;
00295    }
00296 
00297    /*
00298    * get next LDAP result pointer
00299    */
00300    if ((next_result = ldap_next_entry(last_ldap_handle, last_ldap_result))
00301          == NULL)
00302    {
00303       /* no more LDAP entries */
00304       return 1;
00305    }
00306    last_ldap_result = next_result;
00307    return 0;
00308 }
00309 
00310 
00311 int ldap_get_attr_vals(str *_attr_name, struct berval ***_vals)
00312 {
00313    BerElement *ber;
00314    char *a;
00315 
00316    /*
00317    * check for last_ldap_result
00318    */
00319    if (last_ldap_result == NULL) {
00320       LM_ERR("last_ldap_result == NULL\n");
00321       return -1;
00322    }
00323    if (last_ldap_handle == NULL)
00324    {
00325       LM_ERR("last_ldap_handle == NULL\n");
00326       return -1;
00327    }
00328 
00329    /*
00330    * search for attribute named _attr_name
00331    */
00332    *_vals = NULL;
00333    for (a = ldap_first_attribute(last_ldap_handle,
00334          last_ldap_result,
00335          &ber);
00336       a != NULL;
00337       a = ldap_next_attribute(last_ldap_handle,
00338          last_ldap_result,
00339          ber))
00340    {
00341       if (strncmp(a, _attr_name->s, _attr_name->len) == 0) {
00342          *_vals = ldap_get_values_len(
00343             last_ldap_handle,
00344             last_ldap_result,
00345             a);
00346          ldap_memfree(a);
00347          break;
00348       }
00349       ldap_memfree(a);
00350    }
00351 
00352    if (ber != NULL) {
00353       ber_free(ber, 0);
00354    }
00355 
00356    if (*_vals != NULL)
00357    {
00358       return 0;
00359    } else {
00360       return 1;
00361    }
00362 }
00363 
00364 int ldap_str2scope(char* scope_str)
00365 {
00366    if ( strcasecmp( scope_str, "one" ) == 0 ) {
00367       return LDAP_SCOPE_ONELEVEL;
00368 
00369    } else if ( strcasecmp( scope_str, "onelevel" ) == 0 ) {
00370       return LDAP_SCOPE_ONELEVEL;
00371 
00372    } else if ( strcasecmp( scope_str, "base" ) == 0 ) {
00373       return LDAP_SCOPE_BASE;
00374 
00375    } else if ( strcasecmp( scope_str, "sub" ) == 0 ) {
00376       return LDAP_SCOPE_SUBTREE;
00377 
00378    } else if ( strcasecmp( scope_str, "subtree" ) == 0 ) {
00379       return LDAP_SCOPE_SUBTREE;
00380    };
00381 
00382    return( -1 );
00383 }
00384 /*
00385  * sets last_ldap_result and last_ldap_handle
00386  */
00387 int lds_search(
00388    char* _lds_name,
00389    char* _dn,
00390    int _scope,
00391    char* _filter,
00392    char** _attrs,
00393    struct timeval* _search_timeout,
00394    int* _ld_result_count,
00395    int* _ld_error)
00396 {
00397    struct ld_session* lds;
00398 #ifdef LDAP_PERF
00399    struct timeval before_search = { 0, 0 }, after_search = { 0, 0 };
00400 #endif
00401 
00402    /*
00403     * get ld_handle
00404     */
00405    if (get_connected_ldap_session(_lds_name, &lds) != 0)
00406    {
00407       LM_ERR("[%s]: couldn't get ldap session\n", _lds_name);
00408       return -1;
00409    }
00410 
00411    /*
00412     * free last_ldap_result
00413     */
00414         if (last_ldap_result != NULL) {
00415                 ldap_msgfree(last_ldap_result);
00416                 last_ldap_result = NULL;
00417         }
00418 
00419    
00420    LM_DBG(  "[%s]: performing LDAP search: dn [%s],"
00421       " scope [%d], filter [%s], client_timeout [%d] usecs\n",
00422       _lds_name,
00423       _dn,
00424       _scope,
00425       _filter,
00426       (int)(lds->client_search_timeout.tv_sec * 1000000 
00427          + lds->client_search_timeout.tv_usec));
00428    
00429 #ifdef LDAP_PERF
00430    gettimeofday(&before_search, NULL);
00431 #endif
00432 
00433    /*
00434     * perform ldap search
00435     */
00436    *_ld_error = ldap_search_ext_s(
00437       lds->handle,
00438       _dn,
00439       _scope,
00440       _filter,
00441       _attrs,
00442       0,
00443       NULL,
00444       NULL,
00445       &lds->client_search_timeout,
00446       0,
00447       &last_ldap_result);
00448 
00449 #ifdef LDAP_PERF
00450    gettimeofday(&after_search, NULL);
00451 
00452    LM_INFO("[%s]: LDAP search took [%d] usecs\n",
00453       _lds_name,
00454       (int)((after_search.tv_sec * 1000000 + after_search.tv_usec)
00455       - (before_search.tv_sec * 1000000 + before_search.tv_usec)));
00456 #endif
00457 
00458    if (*_ld_error != LDAP_SUCCESS)
00459    {
00460       if (last_ldap_result != NULL)
00461       {
00462          ldap_msgfree(last_ldap_result);
00463          last_ldap_result = NULL;
00464       }
00465 
00466       if (LDAP_API_ERROR(*_ld_error))
00467       {
00468          ldap_disconnect(_lds_name);
00469       }
00470       
00471       LM_DBG( "[%s]: ldap_search_ext_st failed: %s\n",
00472          _lds_name,
00473          ldap_err2string(*_ld_error));
00474       return -1;
00475    }
00476 
00477    last_ldap_handle = lds->handle;
00478    *_ld_result_count = ldap_count_entries(lds->handle, last_ldap_result);
00479    if (*_ld_result_count < 0)
00480    {
00481       LM_DBG("[%s]: ldap_count_entries failed\n", _lds_name);
00482       return -1;
00483    }
00484 
00485    return 0;
00486 }
00487 

Generated on Wed May 23 08:00:57 2012 for Kamailio - The Open Source SIP Server by  doxygen 1.5.6