1 /* $OpenLDAP: pkg/ldap/libraries/libldap/search.c,v 1.76.2.5 2008/02/11 23:26:41 kurt Exp $ */ 2 /* This work is part of OpenLDAP Software <http://www.openldap.org/>. 3 * 4 * Copyright 1998-2008 The OpenLDAP Foundation. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted only as authorized by the OpenLDAP 9 * Public License. 10 * 11 * A copy of this license is available in the file LICENSE in the 12 * top-level directory of the distribution or, alternatively, at 13 * <http://www.OpenLDAP.org/license.html>. 14 */ 15 /* Portions Copyright (c) 1990 Regents of the University of Michigan. 16 * All rights reserved. 17 */ 18 19 #include "portable.h" 20 21 #include <stdio.h> 22 23 #include <ac/stdlib.h> 24 25 #include <ac/socket.h> 26 #include <ac/string.h> 27 #include <ac/time.h> 28 29 #include "ldap-int.h" 30 #include "ldap_log.h" 31 32 /* 33 * ldap_search_ext - initiate an ldap search operation. 34 * 35 * Parameters: 36 * 37 * ld LDAP descriptor 38 * base DN of the base object 39 * scope the search scope - one of 40 * LDAP_SCOPE_BASE (baseObject), 41 * LDAP_SCOPE_ONELEVEL (oneLevel), 42 * LDAP_SCOPE_SUBTREE (subtree), or 43 * LDAP_SCOPE_SUBORDINATE (children) -- OpenLDAP extension 44 * filter a string containing the search filter 45 * (e.g., "(|(cn=bob)(sn=bob))") 46 * attrs list of attribute types to return for matches 47 * attrsonly 1 => attributes only 0 => attributes and values 48 * 49 * Example: 50 * char *attrs[] = { "mail", "title", 0 }; 51 * ldap_search_ext( ld, "dc=example,dc=com", LDAP_SCOPE_SUBTREE, "cn~=bob", 52 * attrs, attrsonly, sctrls, ctrls, timeout, sizelimit, 53 * &msgid ); 54 */ 55 int 56 ldap_search_ext( 57 LDAP *ld, 58 LDAP_CONST char *base, 59 int scope, 60 LDAP_CONST char *filter, 61 char **attrs, 62 int attrsonly, 63 LDAPControl **sctrls, 64 LDAPControl **cctrls, 65 struct timeval *timeout, 66 int sizelimit, 67 int *msgidp ) 68 { 69 int rc; 70 BerElement *ber; 71 int timelimit; 72 ber_int_t id; 73 74 Debug( LDAP_DEBUG_TRACE, "ldap_search_ext\n", 0, 0, 0 ); 75 76 assert( ld != NULL ); 77 assert( LDAP_VALID( ld ) ); 78 79 /* check client controls */ 80 rc = ldap_int_client_controls( ld, cctrls ); 81 if( rc != LDAP_SUCCESS ) return rc; 82 83 /* 84 * if timeout is provided, both tv_sec and tv_usec must 85 * not be zero 86 */ 87 if( timeout != NULL ) { 88 if( timeout->tv_sec == 0 && timeout->tv_usec == 0 ) { 89 return LDAP_PARAM_ERROR; 90 } 91 92 /* timelimit must be non-zero if timeout is provided */ 93 timelimit = timeout->tv_sec != 0 ? timeout->tv_sec : 1; 94 95 } else { 96 /* no timeout, no timelimit */ 97 timelimit = -1; 98 } 99 100 ber = ldap_build_search_req( ld, base, scope, filter, attrs, 101 attrsonly, sctrls, cctrls, timelimit, sizelimit, &id ); 102 103 if ( ber == NULL ) { 104 return ld->ld_errno; 105 } 106 107 108 /* send the message */ 109 *msgidp = ldap_send_initial_request( ld, LDAP_REQ_SEARCH, base, ber, id ); 110 111 if( *msgidp < 0 ) 112 return ld->ld_errno; 113 114 return LDAP_SUCCESS; 115 } 116 117 int 118 ldap_search_ext_s( 119 LDAP *ld, 120 LDAP_CONST char *base, 121 int scope, 122 LDAP_CONST char *filter, 123 char **attrs, 124 int attrsonly, 125 LDAPControl **sctrls, 126 LDAPControl **cctrls, 127 struct timeval *timeout, 128 int sizelimit, 129 LDAPMessage **res ) 130 { 131 int rc; 132 int msgid; 133 134 rc = ldap_search_ext( ld, base, scope, filter, attrs, attrsonly, 135 sctrls, cctrls, timeout, sizelimit, &msgid ); 136 137 if ( rc != LDAP_SUCCESS ) { 138 return( rc ); 139 } 140 141 rc = ldap_result( ld, msgid, LDAP_MSG_ALL, timeout, res ); 142 143 if( rc <= 0 ) { 144 /* error(-1) or timeout(0) */ 145 return( ld->ld_errno ); 146 } 147 148 if( rc == LDAP_RES_SEARCH_REFERENCE || rc == LDAP_RES_INTERMEDIATE ) { 149 return( ld->ld_errno ); 150 } 151 152 return( ldap_result2error( ld, *res, 0 ) ); 153 } 154 155 /* 156 * ldap_search - initiate an ldap search operation. 157 * 158 * Parameters: 159 * 160 * ld LDAP descriptor 161 * base DN of the base object 162 * scope the search scope - one of 163 * LDAP_SCOPE_BASE (baseObject), 164 * LDAP_SCOPE_ONELEVEL (oneLevel), 165 * LDAP_SCOPE_SUBTREE (subtree), or 166 * LDAP_SCOPE_SUBORDINATE (children) -- OpenLDAP extension 167 * filter a string containing the search filter 168 * (e.g., "(|(cn=bob)(sn=bob))") 169 * attrs list of attribute types to return for matches 170 * attrsonly 1 => attributes only 0 => attributes and values 171 * 172 * Example: 173 * char *attrs[] = { "mail", "title", 0 }; 174 * msgid = ldap_search( ld, "dc=example,dc=com", LDAP_SCOPE_SUBTREE, "cn~=bob", 175 * attrs, attrsonly ); 176 */ 177 int 178 ldap_search( 179 LDAP *ld, LDAP_CONST char *base, int scope, LDAP_CONST char *filter, 180 char **attrs, int attrsonly ) 181 { 182 BerElement *ber; 183 ber_int_t id; 184 185 Debug( LDAP_DEBUG_TRACE, "ldap_search\n", 0, 0, 0 ); 186 187 assert( ld != NULL ); 188 assert( LDAP_VALID( ld ) ); 189 190 ber = ldap_build_search_req( ld, base, scope, filter, attrs, 191 attrsonly, NULL, NULL, -1, -1, &id ); 192 193 if ( ber == NULL ) { 194 return( -1 ); 195 } 196 197 198 /* send the message */ 199 return ( ldap_send_initial_request( ld, LDAP_REQ_SEARCH, base, ber, id )); 200 } 201 202 203 BerElement * 204 ldap_build_search_req( 205 LDAP *ld, 206 LDAP_CONST char *base, 207 ber_int_t scope, 208 LDAP_CONST char *filter, 209 char **attrs, 210 ber_int_t attrsonly, 211 LDAPControl **sctrls, 212 LDAPControl **cctrls, 213 ber_int_t timelimit, 214 ber_int_t sizelimit, 215 ber_int_t *idp) 216 { 217 BerElement *ber; 218 int err; 219 220 /* 221 * Create the search request. It looks like this: 222 * SearchRequest := [APPLICATION 3] SEQUENCE { 223 * baseObject DistinguishedName, 224 * scope ENUMERATED { 225 * baseObject (0), 226 * singleLevel (1), 227 * wholeSubtree (2) 228 * }, 229 * derefAliases ENUMERATED { 230 * neverDerefaliases (0), 231 * derefInSearching (1), 232 * derefFindingBaseObj (2), 233 * alwaysDerefAliases (3) 234 * }, 235 * sizelimit INTEGER (0 .. 65535), 236 * timelimit INTEGER (0 .. 65535), 237 * attrsOnly BOOLEAN, 238 * filter Filter, 239 * attributes SEQUENCE OF AttributeType 240 * } 241 * wrapped in an ldap message. 242 */ 243 244 /* create a message to send */ 245 if ( (ber = ldap_alloc_ber_with_options( ld )) == NULL ) { 246 return( NULL ); 247 } 248 249 if ( base == NULL ) { 250 /* no base provided, use session default base */ 251 base = ld->ld_options.ldo_defbase; 252 253 if ( base == NULL ) { 254 /* no session default base, use top */ 255 base = ""; 256 } 257 } 258 259 LDAP_NEXT_MSGID( ld, *idp ); 260 #ifdef LDAP_CONNECTIONLESS 261 if ( LDAP_IS_UDP(ld) ) { 262 struct sockaddr sa = {0}; 263 /* dummy, filled with ldo_peer in request.c */ 264 err = ber_write( ber, &sa, sizeof( sa ), 0 ); 265 } 266 if ( LDAP_IS_UDP(ld) && ld->ld_options.ldo_version == LDAP_VERSION2) { 267 char *dn = ld->ld_options.ldo_cldapdn; 268 if (!dn) dn = ""; 269 err = ber_printf( ber, "{ist{seeiib", *idp, dn, 270 LDAP_REQ_SEARCH, base, (ber_int_t) scope, ld->ld_deref, 271 (sizelimit < 0) ? ld->ld_sizelimit : sizelimit, 272 (timelimit < 0) ? ld->ld_timelimit : timelimit, 273 attrsonly ); 274 } else 275 #endif 276 { 277 err = ber_printf( ber, "{it{seeiib", *idp, 278 LDAP_REQ_SEARCH, base, (ber_int_t) scope, ld->ld_deref, 279 (sizelimit < 0) ? ld->ld_sizelimit : sizelimit, 280 (timelimit < 0) ? ld->ld_timelimit : timelimit, 281 attrsonly ); 282 } 283 284 if ( err == -1 ) { 285 ld->ld_errno = LDAP_ENCODING_ERROR; 286 ber_free( ber, 1 ); 287 return( NULL ); 288 } 289 290 if( filter == NULL ) { 291 filter = "(objectclass=*)"; 292 } 293 294 err = ldap_pvt_put_filter( ber, filter ); 295 296 if ( err == -1 ) { 297 ld->ld_errno = LDAP_FILTER_ERROR; 298 ber_free( ber, 1 ); 299 return( NULL ); 300 } 301 302 #ifdef LDAP_DEBUG 303 if ( ldap_debug & LDAP_DEBUG_ARGS ) { 304 char buf[ BUFSIZ ] = { ' ', '*', '\0' }; 305 306 if ( attrs != NULL ) { 307 char *ptr; 308 int i; 309 310 for ( ptr = buf, i = 0; 311 attrs[ i ] != NULL && ptr < &buf[ sizeof( buf ) ]; 312 i++ ) 313 { 314 ptr += snprintf( ptr, sizeof( buf ) - ( ptr - buf ), 315 " %s", attrs[ i ] ); 316 } 317 318 if ( ptr >= &buf[ sizeof( buf ) ] ) { 319 AC_MEMCPY( &buf[ sizeof( buf ) - STRLENOF( "...(truncated)" ) - 1 ], 320 "...(truncated)", STRLENOF( "...(truncated)" ) + 1 ); 321 } 322 } 323 324 Debug( LDAP_DEBUG_ARGS, "ldap_build_search_req ATTRS:%s\n", buf, 0, 0 ); 325 } 326 #endif /* LDAP_DEBUG */ 327 328 if ( ber_printf( ber, /*{*/ "{v}N}", attrs ) == -1 ) { 329 ld->ld_errno = LDAP_ENCODING_ERROR; 330 ber_free( ber, 1 ); 331 return( NULL ); 332 } 333 334 /* Put Server Controls */ 335 if( ldap_int_put_controls( ld, sctrls, ber ) != LDAP_SUCCESS ) { 336 ber_free( ber, 1 ); 337 return( NULL ); 338 } 339 340 if ( ber_printf( ber, /*{*/ "N}" ) == -1 ) { 341 ld->ld_errno = LDAP_ENCODING_ERROR; 342 ber_free( ber, 1 ); 343 return( NULL ); 344 } 345 346 return( ber ); 347 } 348 349 int 350 ldap_search_st( 351 LDAP *ld, LDAP_CONST char *base, int scope, 352 LDAP_CONST char *filter, char **attrs, 353 int attrsonly, struct timeval *timeout, LDAPMessage **res ) 354 { 355 int msgid; 356 357 if ( (msgid = ldap_search( ld, base, scope, filter, attrs, attrsonly )) 358 == -1 ) 359 return( ld->ld_errno ); 360 361 if ( ldap_result( ld, msgid, LDAP_MSG_ALL, timeout, res ) == -1 || !*res ) 362 return( ld->ld_errno ); 363 364 if ( ld->ld_errno == LDAP_TIMEOUT ) { 365 (void) ldap_abandon( ld, msgid ); 366 ld->ld_errno = LDAP_TIMEOUT; 367 return( ld->ld_errno ); 368 } 369 370 return( ldap_result2error( ld, *res, 0 ) ); 371 } 372 373 int 374 ldap_search_s( 375 LDAP *ld, 376 LDAP_CONST char *base, 377 int scope, 378 LDAP_CONST char *filter, 379 char **attrs, 380 int attrsonly, 381 LDAPMessage **res ) 382 { 383 int msgid; 384 385 if ( (msgid = ldap_search( ld, base, scope, filter, attrs, attrsonly )) 386 == -1 ) 387 return( ld->ld_errno ); 388 389 if ( ldap_result( ld, msgid, LDAP_MSG_ALL, (struct timeval *) NULL, res ) == -1 || !*res ) 390 return( ld->ld_errno ); 391 392 return( ldap_result2error( ld, *res, 0 ) ); 393 } 394 395 static char escape[128] = { 396 1, 1, 1, 1, 1, 1, 1, 1, 397 1, 1, 1, 1, 1, 1, 1, 1, 398 1, 1, 1, 1, 1, 1, 1, 1, 399 1, 1, 1, 1, 1, 1, 1, 1, 400 401 0, 0, 0, 0, 0, 0, 0, 0, 402 1, 1, 1, 0, 0, 0, 0, 0, 403 0, 0, 0, 0, 0, 0, 0, 0, 404 0, 0, 0, 0, 0, 0, 0, 0, 405 406 0, 0, 0, 0, 0, 0, 0, 0, 407 0, 0, 0, 0, 0, 0, 0, 0, 408 0, 0, 0, 0, 0, 0, 0, 0, 409 0, 0, 0, 0, 1, 0, 0, 0, 410 411 0, 0, 0, 0, 0, 0, 0, 0, 412 0, 0, 0, 0, 0, 0, 0, 0, 413 0, 0, 0, 0, 0, 0, 0, 0, 414 0, 0, 0, 0, 0, 0, 0, 1 415 }; 416 #define NEEDFLTESCAPE(c) ((c) & 0x80 || escape[ (unsigned)(c) ]) 417 418 /* 419 * compute the length of the escaped value 420 */ 421 ber_len_t 422 ldap_bv2escaped_filter_value_len( struct berval *in ) 423 { 424 ber_len_t i, l; 425 426 assert( in != NULL ); 427 428 if ( in->bv_len == 0 ) { 429 return 0; 430 } 431 432 for( l = 0, i = 0; i < in->bv_len; l++, i++ ) { 433 char c = in->bv_val[ i ]; 434 if ( NEEDFLTESCAPE( c ) ) { 435 l += 2; 436 } 437 } 438 439 return l; 440 } 441 442 int 443 ldap_bv2escaped_filter_value( struct berval *in, struct berval *out ) 444 { 445 return ldap_bv2escaped_filter_value_x( in, out, 0, NULL ); 446 } 447 448 int 449 ldap_bv2escaped_filter_value_x( struct berval *in, struct berval *out, int inplace, void *ctx ) 450 { 451 ber_len_t i, l; 452 453 assert( in != NULL ); 454 assert( out != NULL ); 455 456 BER_BVZERO( out ); 457 458 if ( in->bv_len == 0 ) { 459 return 0; 460 } 461 462 /* assume we'll escape everything */ 463 l = ldap_bv2escaped_filter_value_len( in ); 464 if ( l == in->bv_len ) { 465 if ( inplace ) { 466 *out = *in; 467 } else { 468 ber_dupbv( out, in ); 469 } 470 return 0; 471 } 472 out->bv_val = LDAP_MALLOCX( l + 1, ctx ); 473 if ( out->bv_val == NULL ) { 474 return -1; 475 } 476 477 for ( i = 0; i < in->bv_len; i++ ) { 478 char c = in->bv_val[ i ]; 479 if ( NEEDFLTESCAPE( c ) ) { 480 assert( out->bv_len < l - 2 ); 481 out->bv_val[out->bv_len++] = '\\'; 482 out->bv_val[out->bv_len++] = "0123456789ABCDEF"[0x0f & (c>>4)]; 483 out->bv_val[out->bv_len++] = "0123456789ABCDEF"[0x0f & c]; 484 485 } else { 486 assert( out->bv_len < l ); 487 out->bv_val[out->bv_len++] = c; 488 } 489 } 490 491 out->bv_val[out->bv_len] = '\0'; 492 493 return 0; 494 } 495 496