00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
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
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
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
00131
00132
00133
00134
00135
00136
00137
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
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
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
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
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
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
00299
00300 if ((next_result = ldap_next_entry(last_ldap_handle, last_ldap_result))
00301 == NULL)
00302 {
00303
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
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
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
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
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
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
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