Print this page
NEX-14547 Get UNIX group info. from AD/LDAP with partial RFC2307 schema
NEX-13132 smbd dumping core in nss_ldap.so.1`getbymember
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
| Split |
Close |
| Expand all |
| Collapse all |
--- old/usr/src/lib/libldap5/sources/ldap/common/search.c
+++ new/usr/src/lib/libldap5/sources/ldap/common/search.c
1 1 /*
2 2 * Copyright 2001-2002 Sun Microsystems, Inc. All rights reserved.
3 3 * Use is subject to license terms.
4 + *
5 + * Copyright 2017 Nexenta Systems, Inc. All rights reserved.
4 6 */
5 7
6 -#pragma ident "%Z%%M% %I% %E% SMI"
7 8
8 -
9 9 /*
10 10 * The contents of this file are subject to the Netscape Public
11 11 * License Version 1.1 (the "License"); you may not use this file
12 12 * except in compliance with the License. You may obtain a copy of
13 13 * the License at http://www.mozilla.org/NPL/
14 14 *
15 15 * Software distributed under the License is distributed on an "AS
16 16 * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
17 17 * implied. See the License for the specific language governing
18 18 * rights and limitations under the License.
19 19 *
20 20 * The Original Code is Mozilla Communicator client code, released
21 21 * March 31, 1998.
22 22 *
23 23 * The Initial Developer of the Original Code is Netscape
24 24 * Communications Corporation. Portions created by Netscape are
25 25 * Copyright (C) 1998-1999 Netscape Communications Corporation. All
26 26 * Rights Reserved.
27 27 *
28 28 * Contributor(s):
29 29 */
30 30 /*
31 31 * Copyright (c) 1990 Regents of the University of Michigan.
32 32 * All rights reserved.
33 33 */
34 34 /*
35 35 * search.c
36 36 */
37 37
38 38 #if 0
39 39 #ifndef lint
40 40 static char copyright[] = "@(#) Copyright (c) 1990 Regents of the University of Michigan.\nAll rights reserved.\n";
41 41 #endif
42 42 #endif
43 43
44 44 #include "ldap-int.h"
45 45
46 46 static int nsldapi_timeval2ldaplimit( struct timeval *timeoutp,
47 47 int defaultvalue );
48 48 static int nsldapi_search( LDAP *ld, const char *base, int scope,
49 49 const char *filter, char **attrs, int attrsonly,
50 50 LDAPControl **serverctrls, LDAPControl **clientctrls,
51 51 int timelimit, int sizelimit, int *msgidp );
52 52 static char *find_right_paren( char *s );
53 53 static char *put_complex_filter( BerElement *ber, char *str,
54 54 ber_tag_t tag, int not );
55 55 static int unescape_filterval( char *str );
56 56 static int hexchar2int( char c );
57 57 static int is_valid_attr( char *a );
58 58 static int put_simple_filter( BerElement *ber, char *str );
59 59 static int put_substring_filter( BerElement *ber, char *type,
60 60 char *str );
61 61 static int put_filter_list( BerElement *ber, char *str );
62 62 static int nsldapi_search_s( LDAP *ld, const char *base, int scope,
63 63 const char *filter, char **attrs, int attrsonly,
64 64 LDAPControl **serverctrls, LDAPControl **clientctrls,
65 65 struct timeval *localtimeoutp, int timelimit, int sizelimit,
66 66 LDAPMessage **res );
67 67
68 68 /*
69 69 * ldap_search - initiate an ldap search operation. Parameters:
70 70 *
71 71 * ld LDAP descriptor
72 72 * base DN of the base object
73 73 * scope the search scope - one of LDAP_SCOPE_BASE,
74 74 * LDAP_SCOPE_ONELEVEL, LDAP_SCOPE_SUBTREE
75 75 * filter a string containing the search filter
76 76 * (e.g., "(|(cn=bob)(sn=bob))")
77 77 * attrs list of attribute types to return for matches
78 78 * attrsonly 1 => attributes only 0 => attributes and values
79 79 *
80 80 * Example:
81 81 * char *attrs[] = { "mail", "title", 0 };
82 82 * msgid = ldap_search( ld, "c=us@o=UM", LDAP_SCOPE_SUBTREE, "cn~=bob",
83 83 * attrs, attrsonly );
84 84 */
85 85 int
86 86 LDAP_CALL
87 87 ldap_search(
88 88 LDAP *ld,
89 89 const char *base,
90 90 int scope,
91 91 const char *filter,
92 92 char **attrs,
93 93 int attrsonly
94 94 )
95 95 {
96 96 int msgid;
97 97
98 98 LDAPDebug( LDAP_DEBUG_TRACE, "ldap_search\n", 0, 0, 0 );
99 99
100 100 if ( ldap_search_ext( ld, base, scope, filter, attrs, attrsonly, NULL,
101 101 NULL, NULL, -1, &msgid ) == LDAP_SUCCESS ) {
102 102 return( msgid );
103 103 } else {
104 104 return( -1 ); /* error is in ld handle */
105 105 }
106 106 }
107 107
108 108
109 109 /*
110 110 * LDAPv3 extended search.
111 111 * Returns an LDAP error code.
112 112 */
113 113 int
114 114 LDAP_CALL
115 115 ldap_search_ext(
116 116 LDAP *ld,
117 117 const char *base,
118 118 int scope,
119 119 const char *filter,
120 120 char **attrs,
121 121 int attrsonly,
122 122 LDAPControl **serverctrls,
123 123 LDAPControl **clientctrls,
124 124 struct timeval *timeoutp, /* NULL means use ld->ld_timelimit */
125 125 int sizelimit,
126 126 int *msgidp
127 127 )
128 128 {
129 129 /*
130 130 * It is an error to pass in a zero'd timeval.
131 131 */
132 132 if ( timeoutp != NULL && timeoutp->tv_sec == 0 &&
133 133 timeoutp->tv_usec == 0 ) {
134 134 if ( ld != NULL ) {
135 135 LDAP_SET_LDERRNO( ld, LDAP_PARAM_ERROR, NULL, NULL );
136 136 }
137 137 return( LDAP_PARAM_ERROR );
138 138 }
139 139
140 140 return( nsldapi_search( ld, base, scope, filter, attrs, attrsonly,
141 141 serverctrls, clientctrls,
142 142 nsldapi_timeval2ldaplimit( timeoutp, -1 ), sizelimit, msgidp ));
143 143 }
144 144
145 145
146 146 /*
147 147 * Like ldap_search_ext() except an integer timelimit is passed instead of
148 148 * using the overloaded struct timeval *timeoutp.
149 149 */
150 150 static int
151 151 nsldapi_search(
152 152 LDAP *ld,
153 153 const char *base,
154 154 int scope,
155 155 const char *filter,
156 156 char **attrs,
157 157 int attrsonly,
158 158 LDAPControl **serverctrls,
159 159 LDAPControl **clientctrls,
160 160 int timelimit, /* -1 means use ld->ld_timelimit */
161 161 int sizelimit, /* -1 means use ld->ld_sizelimit */
162 162 int *msgidp
163 163 )
164 164 {
165 165 BerElement *ber;
166 166 int rc, rc_key;
167 167 unsigned long key; /* XXXmcs: memcache */
168 168
169 169 LDAPDebug( LDAP_DEBUG_TRACE, "ldap_search_ext\n", 0, 0, 0 );
170 170
171 171 if ( !NSLDAPI_VALID_LDAP_POINTER( ld )) {
172 172 return( LDAP_PARAM_ERROR );
173 173 }
174 174
175 175 if ( base == NULL ) {
176 176 base = "";
177 177 }
178 178
179 179 if ( filter == NULL ) {
180 180 filter = "(objectclass=*)";
181 181 }
182 182
183 183 if ( msgidp == NULL || ( scope != LDAP_SCOPE_BASE
184 184 && scope != LDAP_SCOPE_ONELEVEL && scope != LDAP_SCOPE_SUBTREE )
185 185 || ( sizelimit < -1 )) {
186 186 LDAP_SET_LDERRNO( ld, LDAP_PARAM_ERROR, NULL, NULL );
187 187 return( LDAP_PARAM_ERROR );
188 188 }
189 189 LDAP_MUTEX_LOCK( ld, LDAP_MSGID_LOCK );
190 190 *msgidp = ++ld->ld_msgid;
191 191 LDAP_MUTEX_UNLOCK( ld, LDAP_MSGID_LOCK );
192 192
193 193 /*
194 194 * XXXmcs: should use cache function pointers to hook in memcache
195 195 */
196 196 if ( ld->ld_memcache == NULL ) {
197 197 rc_key = LDAP_NOT_SUPPORTED;
198 198 } else if (( rc_key = ldap_memcache_createkey( ld, base, scope, filter,
199 199 attrs, attrsonly, serverctrls, clientctrls, &key)) == LDAP_SUCCESS
200 200 && ldap_memcache_result( ld, *msgidp, key ) == LDAP_SUCCESS ) {
201 201 return LDAP_SUCCESS;
202 202 }
203 203
204 204 /* check the cache */
205 205 if ( ld->ld_cache_on && ld->ld_cache_search != NULL ) {
206 206 LDAP_MUTEX_LOCK( ld, LDAP_CACHE_LOCK );
207 207 if ( (rc = (ld->ld_cache_search)( ld, *msgidp, LDAP_REQ_SEARCH,
208 208 base, scope, filter, attrs, attrsonly )) != 0 ) {
209 209 *msgidp = rc;
210 210 LDAP_MUTEX_UNLOCK( ld, LDAP_CACHE_LOCK );
211 211 return( LDAP_SUCCESS );
212 212 }
213 213 LDAP_MUTEX_UNLOCK( ld, LDAP_CACHE_LOCK );
214 214 }
215 215
216 216 /* caching off or did not find it in the cache - check the net */
217 217 if (( rc = nsldapi_build_search_req( ld, base, scope, filter, attrs,
218 218 attrsonly, serverctrls, clientctrls, timelimit, sizelimit,
219 219 *msgidp, &ber )) != LDAP_SUCCESS ) {
220 220 return( rc );
221 221 }
222 222
223 223 /* send the message */
224 224 rc = nsldapi_send_initial_request( ld, *msgidp, LDAP_REQ_SEARCH,
225 225 (char *) base, ber );
226 226
227 227 /*
228 228 * XXXmcs: should use cache function pointers to hook in memcache
229 229 */
230 230 if ( (rc_key == LDAP_SUCCESS) && (rc >= 0) ) {
231 231 ldap_memcache_new( ld, rc, key, base );
232 232 }
233 233
234 234 *msgidp = rc;
235 235 return( rc < 0 ? LDAP_GET_LDERRNO( ld, NULL, NULL ) : LDAP_SUCCESS );
236 236 }
237 237
238 238
239 239 /*
240 240 * Convert a non-NULL timeoutp to a value in seconds that is appropriate to
241 241 * send in an LDAP search request. If timeoutp is NULL, return defaultvalue.
242 242 */
243 243 static int
244 244 nsldapi_timeval2ldaplimit( struct timeval *timeoutp, int defaultvalue )
245 245 {
246 246 int timelimit;
247 247
248 248 if ( NULL == timeoutp ) {
249 249 timelimit = defaultvalue;
250 250 } else if ( timeoutp->tv_sec > 0 ) {
251 251 timelimit = timeoutp->tv_sec;
252 252 } else if ( timeoutp->tv_usec > 0 ) {
253 253 timelimit = 1; /* minimum we can express in LDAP */
254 254 } else {
255 255 /*
256 256 * both tv_sec and tv_usec are less than one (zero?) so
257 257 * to maintain compatiblity with our "zero means no limit"
258 258 * convention we pass no limit to the server.
259 259 */
260 260 timelimit = 0; /* no limit */
261 261 }
262 262
263 263 return( timelimit );
264 264 }
265 265
266 266
267 267 /* returns an LDAP error code and also sets it in ld */
268 268 int
269 269 nsldapi_build_search_req(
270 270 LDAP *ld,
271 271 const char *base,
272 272 int scope,
273 273 const char *filter,
274 274 char **attrs,
275 275 int attrsonly,
276 276 LDAPControl **serverctrls,
277 277 LDAPControl **clientctrls, /* not used for anything yet */
278 278 int timelimit, /* if -1, ld->ld_timelimit is used */
279 279 int sizelimit, /* if -1, ld->ld_sizelimit is used */
280 280 int msgid,
281 281 BerElement **berp
282 282 )
283 283 {
284 284 BerElement *ber;
285 285 int err;
286 286 char *fdup;
287 287
288 288 /*
289 289 * Create the search request. It looks like this:
290 290 * SearchRequest := [APPLICATION 3] SEQUENCE {
291 291 * baseObject DistinguishedName,
292 292 * scope ENUMERATED {
293 293 * baseObject (0),
294 294 * singleLevel (1),
295 295 * wholeSubtree (2)
296 296 * },
297 297 * derefAliases ENUMERATED {
298 298 * neverDerefaliases (0),
299 299 * derefInSearching (1),
300 300 * derefFindingBaseObj (2),
301 301 * alwaysDerefAliases (3)
302 302 * },
303 303 * sizelimit INTEGER (0 .. 65535),
304 304 * timelimit INTEGER (0 .. 65535),
305 305 * attrsOnly BOOLEAN,
306 306 * filter Filter,
307 307 * attributes SEQUENCE OF AttributeType
308 308 * }
309 309 * wrapped in an ldap message.
310 310 */
311 311
312 312 /* create a message to send */
313 313 if (( err = nsldapi_alloc_ber_with_options( ld, &ber ))
314 314 != LDAP_SUCCESS ) {
315 315 return( err );
316 316 }
317 317
318 318 if ( base == NULL ) {
319 319 base = "";
320 320 }
321 321
322 322 if ( sizelimit == -1 ) {
323 323 sizelimit = ld->ld_sizelimit;
324 324 }
325 325
326 326 if ( timelimit == -1 ) {
327 327 timelimit = ld->ld_timelimit;
328 328 }
329 329
330 330 #ifdef CLDAP
331 331 if ( ld->ld_sbp->sb_naddr > 0 ) {
332 332 err = ber_printf( ber, "{ist{seeiib", msgid,
333 333 ld->ld_cldapdn, LDAP_REQ_SEARCH, base, scope, ld->ld_deref,
334 334 sizelimit, timelimit, attrsonly );
335 335 } else {
336 336 #endif /* CLDAP */
337 337 err = ber_printf( ber, "{it{seeiib", msgid,
338 338 LDAP_REQ_SEARCH, base, scope, ld->ld_deref,
339 339 sizelimit, timelimit, attrsonly );
340 340 #ifdef CLDAP
341 341 }
342 342 #endif /* CLDAP */
343 343
344 344 if ( err == -1 ) {
345 345 LDAP_SET_LDERRNO( ld, LDAP_ENCODING_ERROR, NULL, NULL );
346 346 ber_free( ber, 1 );
347 347 return( LDAP_ENCODING_ERROR );
348 348 }
349 349
350 350 fdup = nsldapi_strdup( filter );
351 351 if (fdup == NULL) {
352 352 LDAP_SET_LDERRNO( ld, LDAP_NO_MEMORY, NULL, NULL );
353 353 ber_free( ber, 1 );
354 354 return( LDAP_NO_MEMORY );
355 355 }
356 356 err = ldap_put_filter( ber, fdup );
357 357 NSLDAPI_FREE( fdup );
358 358
359 359 if ( err == -1 ) {
360 360 LDAP_SET_LDERRNO( ld, LDAP_FILTER_ERROR, NULL, NULL );
361 361 ber_free( ber, 1 );
362 362 return( LDAP_FILTER_ERROR );
363 363 }
364 364
365 365 if ( ber_printf( ber, "{v}}", attrs ) == -1 ) {
366 366 LDAP_SET_LDERRNO( ld, LDAP_ENCODING_ERROR, NULL, NULL );
367 367 ber_free( ber, 1 );
368 368 return( LDAP_ENCODING_ERROR );
369 369 }
370 370
371 371 if ( (err = nsldapi_put_controls( ld, serverctrls, 1, ber ))
372 372 != LDAP_SUCCESS ) {
373 373 ber_free( ber, 1 );
374 374 return( err );
375 375 }
376 376
377 377 *berp = ber;
378 378 return( LDAP_SUCCESS );
379 379 }
380 380
381 381 static char *
382 382 find_right_paren( char *s )
383 383 {
384 384 int balance, escape;
385 385
386 386 balance = 1;
387 387 escape = 0;
388 388 while ( *s && balance ) {
389 389 if ( escape == 0 ) {
390 390 if ( *s == '(' )
391 391 balance++;
392 392 else if ( *s == ')' )
393 393 balance--;
394 394 }
395 395 if ( *s == '\\' && ! escape )
396 396 escape = 1;
397 397 else
398 398 escape = 0;
399 399 if ( balance )
400 400 s++;
401 401 }
402 402
403 403 return( *s ? s : NULL );
404 404 }
405 405
406 406 static char *
407 407 put_complex_filter(
408 408 BerElement *ber,
409 409 char *str,
410 410 ber_tag_t tag,
411 411 int not
412 412 )
413 413 {
414 414 char *next;
415 415
416 416 /*
417 417 * We have (x(filter)...) with str sitting on
418 418 * the x. We have to find the paren matching
419 419 * the one before the x and put the intervening
420 420 * filters by calling put_filter_list().
421 421 */
422 422
423 423 /* put explicit tag */
424 424 if ( ber_printf( ber, "t{", tag ) == -1 )
425 425 return( NULL );
426 426
427 427 str++;
428 428 if ( (next = find_right_paren( str )) == NULL )
429 429 return( NULL );
430 430
431 431 *next = '\0';
432 432 if ( put_filter_list( ber, str ) == -1 )
433 433 return( NULL );
434 434 *next++ = ')';
435 435
436 436 /* flush explicit tagged thang */
437 437 if ( ber_printf( ber, "}" ) == -1 )
438 438 return( NULL );
439 439
440 440 return( next );
441 441 }
442 442
443 443 int
444 444 ldap_put_filter( BerElement *ber, char *str )
445 445 {
446 446 char *next;
447 447 int parens, balance, escape;
448 448
449 449 /*
450 450 * A Filter looks like this:
451 451 * Filter ::= CHOICE {
452 452 * and [0] SET OF Filter,
453 453 * or [1] SET OF Filter,
454 454 * not [2] Filter,
455 455 * equalityMatch [3] AttributeValueAssertion,
456 456 * substrings [4] SubstringFilter,
457 457 * greaterOrEqual [5] AttributeValueAssertion,
458 458 * lessOrEqual [6] AttributeValueAssertion,
459 459 * present [7] AttributeType,,
460 460 * approxMatch [8] AttributeValueAssertion
461 461 * }
462 462 *
463 463 * SubstringFilter ::= SEQUENCE {
464 464 * type AttributeType,
465 465 * SEQUENCE OF CHOICE {
466 466 * initial [0] IA5String,
467 467 * any [1] IA5String,
468 468 * final [2] IA5String
469 469 * }
470 470 * }
471 471 * Note: tags in a choice are always explicit
472 472 */
473 473
474 474 LDAPDebug( LDAP_DEBUG_TRACE, "put_filter \"%s\"\n", str, 0, 0 );
475 475
476 476 parens = 0;
477 477 while ( *str ) {
478 478 switch ( *str ) {
479 479 case '(':
480 480 str++;
481 481 parens++;
482 482 switch ( *str ) {
483 483 case '&':
484 484 LDAPDebug( LDAP_DEBUG_TRACE, "put_filter: AND\n",
485 485 0, 0, 0 );
486 486
487 487 if ( (str = put_complex_filter( ber, str,
488 488 LDAP_FILTER_AND, 0 )) == NULL )
489 489 return( -1 );
490 490
491 491 parens--;
492 492 break;
493 493
494 494 case '|':
495 495 LDAPDebug( LDAP_DEBUG_TRACE, "put_filter: OR\n",
496 496 0, 0, 0 );
497 497
498 498 if ( (str = put_complex_filter( ber, str,
499 499 LDAP_FILTER_OR, 0 )) == NULL )
500 500 return( -1 );
501 501
502 502 parens--;
503 503 break;
504 504
505 505 case '!':
506 506 LDAPDebug( LDAP_DEBUG_TRACE, "put_filter: NOT\n",
507 507 0, 0, 0 );
508 508
509 509 if ( (str = put_complex_filter( ber, str,
510 510 LDAP_FILTER_NOT, 1 )) == NULL )
511 511 return( -1 );
512 512
513 513 parens--;
514 514 break;
515 515
516 516 default:
517 517 LDAPDebug( LDAP_DEBUG_TRACE,
518 518 "put_filter: simple\n", 0, 0, 0 );
519 519
520 520 balance = 1;
521 521 escape = 0;
522 522 next = str;
523 523 while ( *next && balance ) {
524 524 if ( escape == 0 ) {
525 525 if ( *next == '(' )
526 526 balance++;
527 527 else if ( *next == ')' )
528 528 balance--;
529 529 }
530 530 if ( *next == '\\' && ! escape )
531 531 escape = 1;
532 532 else
533 533 escape = 0;
534 534 if ( balance )
535 535 next++;
536 536 }
537 537 if ( balance != 0 )
538 538 return( -1 );
539 539
540 540 *next = '\0';
541 541 if ( put_simple_filter( ber, str ) == -1 ) {
542 542 return( -1 );
543 543 }
544 544 *next++ = ')';
545 545 str = next;
546 546 parens--;
547 547 break;
548 548 }
549 549 break;
550 550
551 551 case ')':
552 552 LDAPDebug( LDAP_DEBUG_TRACE, "put_filter: end\n", 0, 0,
553 553 0 );
554 554 if ( ber_printf( ber, "]" ) == -1 )
555 555 return( -1 );
556 556 str++;
557 557 parens--;
558 558 break;
559 559
560 560 case ' ':
561 561 str++;
562 562 break;
563 563
564 564 default: /* assume it's a simple type=value filter */
565 565 LDAPDebug( LDAP_DEBUG_TRACE, "put_filter: default\n", 0, 0,
566 566 0 );
567 567 next = strchr( str, '\0' );
568 568 if ( put_simple_filter( ber, str ) == -1 ) {
569 569 return( -1 );
570 570 }
571 571 str = next;
572 572 break;
573 573 }
574 574 }
575 575
576 576 return( parens ? -1 : 0 );
577 577 }
578 578
579 579
580 580 /*
581 581 * Put a list of filters like this "(filter1)(filter2)..."
582 582 */
583 583
584 584 static int
585 585 put_filter_list( BerElement *ber, char *str )
586 586 {
587 587 char *next;
588 588 char save;
589 589
590 590 LDAPDebug( LDAP_DEBUG_TRACE, "put_filter_list \"%s\"\n", str, 0, 0 );
591 591
592 592 while ( *str ) {
593 593 while ( *str && isspace( *str ) )
594 594 str++;
595 595 if ( *str == '\0' )
596 596 break;
597 597
598 598 if ( (next = find_right_paren( str + 1 )) == NULL )
599 599 return( -1 );
600 600 save = *++next;
601 601
602 602 /* now we have "(filter)" with str pointing to it */
603 603 *next = '\0';
604 604 if ( ldap_put_filter( ber, str ) == -1 )
605 605 return( -1 );
606 606 *next = save;
607 607
608 608 str = next;
609 609 }
610 610
611 611 return( 0 );
612 612 }
613 613
614 614
615 615 /*
616 616 * is_valid_attr - returns 1 if a is a syntactically valid left-hand side
617 617 * of a filter expression, 0 otherwise. A valid string may contain only
618 618 * letters, numbers, hyphens, semi-colons, colons and periods. examples:
619 619 * cn
620 620 * cn;lang-fr
621 621 * 1.2.3.4;binary;dynamic
622 622 * mail;dynamic
623 623 * cn:dn:1.2.3.4
624 624 *
625 625 * For compatibility with older servers, we also allow underscores in
626 626 * attribute types, even through they are not allowed by the LDAPv3 RFCs.
627 627 */
628 628 static int
629 629 is_valid_attr( char *a )
630 630 {
631 631 for ( ; *a; a++ ) {
632 632 if ( !isascii( *a ) ) {
633 633 return( 0 );
634 634 } else if ( !isalnum( *a ) ) {
635 635 switch ( *a ) {
636 636 case '-':
637 637 case '.':
638 638 case ';':
639 639 case ':':
640 640 case '_':
641 641 break; /* valid */
642 642 default:
643 643 return( 0 );
644 644 }
645 645 }
646 646 }
647 647
648 648 return( 1 );
649 649 }
650 650
651 651 static char *
652 652 find_star( char *s )
653 653 {
654 654 for ( ; *s; ++s ) {
655 655 switch ( *s ) {
656 656 case '*': return s;
657 657 case '\\':
658 658 ++s;
659 659 if ( hexchar2int(s[0]) >= 0 && hexchar2int(s[1]) >= 0 ) ++s;
660 660 default: break;
661 661 }
662 662 }
663 663 return NULL;
664 664 }
665 665
666 666 static int
667 667 put_simple_filter( BerElement *ber, char *str )
668 668 {
669 669 char *s, *s2, *s3, filterop;
670 670 char *value;
671 671 ber_uint_t ftype;
672 672 int rc, len;
673 673 char *oid; /* for v3 extended filter */
674 674 int dnattr; /* for v3 extended filter */
675 675
676 676 LDAPDebug( LDAP_DEBUG_TRACE, "put_simple_filter \"%s\"\n", str, 0, 0 );
677 677
678 678 rc = -1; /* pessimistic */
679 679
680 680 if (( str = nsldapi_strdup( str )) == NULL ) {
681 681 return( rc );
682 682 }
683 683
684 684 if ( (s = strchr( str, '=' )) == NULL ) {
685 685 goto free_and_return;
686 686 }
687 687 value = s + 1;
688 688 *s-- = '\0';
689 689 filterop = *s;
690 690 if ( filterop == '<' || filterop == '>' || filterop == '~' ||
691 691 filterop == ':' ) {
692 692 *s = '\0';
693 693 }
694 694
695 695 if ( ! is_valid_attr( str ) ) {
696 696 goto free_and_return;
697 697 }
698 698
699 699 switch ( filterop ) {
700 700 case '<':
701 701 ftype = LDAP_FILTER_LE;
702 702 break;
703 703 case '>':
704 704 ftype = LDAP_FILTER_GE;
705 705 break;
706 706 case '~':
707 707 ftype = LDAP_FILTER_APPROX;
708 708 break;
709 709 case ':': /* extended filter - v3 only */
710 710 /*
711 711 * extended filter looks like this:
712 712 *
713 713 * [type][':dn'][':'oid]':='value
714 714 *
715 715 * where one of type or :oid is required.
716 716 *
717 717 */
718 718 ftype = LDAP_FILTER_EXTENDED;
719 719 s2 = s3 = NULL;
720 720 if ( (s2 = strrchr( str, ':' )) == NULL ) {
721 721 goto free_and_return;
722 722 }
723 723 if ( strcasecmp( s2, ":dn" ) == 0 ) {
724 724 oid = NULL;
725 725 dnattr = 1;
726 726 *s2 = '\0';
727 727 } else {
728 728 oid = s2 + 1;
729 729 dnattr = 0;
730 730 *s2 = '\0';
731 731 if ( (s3 = strrchr( str, ':' )) != NULL ) {
732 732 if ( strcasecmp( s3, ":dn" ) == 0 ) {
733 733 dnattr = 1;
734 734 } else {
735 735 goto free_and_return;
736 736 }
737 737 *s3 = '\0';
738 738 }
739 739 }
740 740 if ( (rc = ber_printf( ber, "t{", ftype )) == -1 ) {
741 741 goto free_and_return;
742 742 }
743 743 if ( oid != NULL ) {
744 744 if ( (rc = ber_printf( ber, "ts", LDAP_TAG_MRA_OID,
745 745 oid )) == -1 ) {
746 746 goto free_and_return;
747 747 }
748 748 }
749 749 if ( *str != '\0' ) {
750 750 if ( (rc = ber_printf( ber, "ts",
751 751 LDAP_TAG_MRA_TYPE, str )) == -1 ) {
752 752 goto free_and_return;
753 753 }
754 754 }
755 755 if (( len = unescape_filterval( value )) < 0 ||
756 756 ( rc = ber_printf( ber, "totb}", LDAP_TAG_MRA_VALUE,
757 757 value, len, LDAP_TAG_MRA_DNATTRS, dnattr )) == -1 ) {
758 758 goto free_and_return;
759 759 }
760 760 rc = 0;
761 761 goto free_and_return;
762 762 /* break; */
763 763 default:
764 764 if ( find_star( value ) == NULL ) {
765 765 ftype = LDAP_FILTER_EQUALITY;
766 766 } else if ( strcmp( value, "*" ) == 0 ) {
767 767 ftype = LDAP_FILTER_PRESENT;
768 768 } else {
769 769 rc = put_substring_filter( ber, str, value );
770 770 goto free_and_return;
771 771 }
772 772 break;
773 773 }
774 774
775 775 if ( ftype == LDAP_FILTER_PRESENT ) {
776 776 rc = ber_printf( ber, "ts", ftype, str );
777 777 } else if (( len = unescape_filterval( value )) >= 0 ) {
778 778 rc = ber_printf( ber, "t{so}", ftype, str, value, len );
779 779 }
780 780 if ( rc != -1 ) {
781 781 rc = 0;
782 782 }
783 783
784 784 free_and_return:
785 785 NSLDAPI_FREE( str );
786 786 return( rc );
787 787 }
788 788
789 789
790 790 /*
791 791 * Undo in place both LDAPv2 (RFC-1960) and LDAPv3 (hexadecimal) escape
792 792 * sequences within the null-terminated string 'val'. The resulting value
793 793 * may contain null characters.
794 794 *
795 795 * If 'val' contains invalid escape sequences we return -1.
796 796 * Otherwise the length of the unescaped value is returned.
797 797 */
|
↓ open down ↓ |
779 lines elided |
↑ open up ↑ |
798 798 static int
799 799 unescape_filterval( char *val )
800 800 {
801 801 int escape, firstdigit, ival;
802 802 char *s, *d;
803 803
804 804 escape = 0;
805 805 for ( s = d = val; *s; s++ ) {
806 806 if ( escape ) {
807 807 /*
808 + * need to leave escaped comma as-is, i.e.
809 + * val="CN=Last\, First,OU=..."
810 + */
811 + if (*s == ',') {
812 + *d++ = '\\';
813 + *d++ = *s;
814 + escape = 0;
815 + continue;
816 + }
817 + /*
808 818 * first try LDAPv3 escape (hexadecimal) sequence
809 819 */
810 820 if (( ival = hexchar2int( *s )) < 0 ) {
811 821 if ( firstdigit ) {
812 822 /*
813 823 * LDAPv2 (RFC1960) escape sequence
814 824 */
815 825 *d++ = *s;
816 826 escape = 0;
817 827 } else {
818 828 return(-1);
819 829 }
820 830 }
821 831 if ( firstdigit ) {
822 832 *d = ( ival<<4 );
823 833 firstdigit = 0;
824 834 } else {
825 835 *d++ |= ival;
826 836 escape = 0;
827 837 }
828 838
829 839 } else if ( *s != '\\' ) {
830 840 *d++ = *s;
831 841 escape = 0;
832 842
833 843 } else {
834 844 escape = 1;
835 845 firstdigit = 1;
836 846 }
837 847 }
838 848
839 849 return( d - val );
840 850 }
841 851
842 852
843 853 /*
844 854 * convert character 'c' that represents a hexadecimal digit to an integer.
845 855 * if 'c' is not a hexidecimal digit [0-9A-Fa-f], -1 is returned.
846 856 * otherwise the converted value is returned.
847 857 */
848 858 static int
849 859 hexchar2int( char c )
850 860 {
851 861 if ( c >= '0' && c <= '9' ) {
852 862 return( c - '0' );
853 863 }
854 864 if ( c >= 'A' && c <= 'F' ) {
855 865 return( c - 'A' + 10 );
856 866 }
857 867 if ( c >= 'a' && c <= 'f' ) {
858 868 return( c - 'a' + 10 );
859 869 }
860 870 return( -1 );
861 871 }
862 872
863 873 static int
864 874 put_substring_filter( BerElement *ber, char *type, char *val )
865 875 {
866 876 char *nextstar, gotstar = 0;
867 877 ber_uint_t ftype;
868 878 int len;
869 879
870 880 LDAPDebug( LDAP_DEBUG_TRACE, "put_substring_filter \"%s=%s\"\n", type,
871 881 val, 0 );
872 882
873 883 if ( ber_printf( ber, "t{s{", LDAP_FILTER_SUBSTRINGS, type ) == -1 ) {
874 884 return( -1 );
875 885 }
876 886
877 887 for ( ; val != NULL; val = nextstar ) {
878 888 if ( (nextstar = find_star( val )) != NULL ) {
879 889 *nextstar++ = '\0';
880 890 }
881 891
882 892 if ( gotstar == 0 ) {
883 893 ftype = LDAP_SUBSTRING_INITIAL;
884 894 } else if ( nextstar == NULL ) {
885 895 ftype = LDAP_SUBSTRING_FINAL;
886 896 } else {
887 897 ftype = LDAP_SUBSTRING_ANY;
888 898 }
889 899 if ( *val != '\0' ) {
890 900 if (( len = unescape_filterval( val )) < 0 ||
891 901 ber_printf( ber, "to", ftype, val, len ) == -1 ) {
892 902 return( -1 );
893 903 }
894 904 }
895 905
896 906 gotstar = 1;
897 907 }
898 908
899 909 if ( ber_printf( ber, "}}" ) == -1 ) {
900 910 return( -1 );
901 911 }
902 912
903 913 return( 0 );
904 914 }
905 915
906 916 int
907 917 LDAP_CALL
908 918 ldap_search_st(
909 919 LDAP *ld,
910 920 const char *base,
911 921 int scope,
912 922 const char *filter,
913 923 char **attrs,
914 924 int attrsonly,
915 925 struct timeval *timeout,
916 926 LDAPMessage **res
917 927 )
918 928 {
919 929 return( nsldapi_search_s( ld, base, scope, filter, attrs, attrsonly,
920 930 NULL, NULL, timeout, -1, -1, res ));
921 931 }
922 932
923 933 int
924 934 LDAP_CALL
925 935 ldap_search_s(
926 936 LDAP *ld,
927 937 const char *base,
928 938 int scope,
929 939 const char *filter,
930 940 char **attrs,
931 941 int attrsonly,
932 942 LDAPMessage **res
933 943 )
934 944 {
935 945 return( nsldapi_search_s( ld, base, scope, filter, attrs, attrsonly,
936 946 NULL, NULL, NULL, -1, -1, res ));
937 947 }
938 948
939 949 int LDAP_CALL
940 950 ldap_search_ext_s(
941 951 LDAP *ld,
942 952 const char *base,
943 953 int scope,
944 954 const char *filter,
945 955 char **attrs,
946 956 int attrsonly,
947 957 LDAPControl **serverctrls,
948 958 LDAPControl **clientctrls,
949 959 struct timeval *timeoutp,
950 960 int sizelimit,
951 961 LDAPMessage **res
952 962 )
953 963 {
954 964 return( nsldapi_search_s( ld, base, scope, filter, attrs, attrsonly,
955 965 serverctrls, clientctrls, timeoutp,
956 966 nsldapi_timeval2ldaplimit( timeoutp, -1 ), sizelimit, res ));
957 967 }
958 968
959 969
960 970 static int
961 971 nsldapi_search_s(
962 972 LDAP *ld,
963 973 const char *base,
964 974 int scope,
965 975 const char *filter,
966 976 char **attrs,
967 977 int attrsonly,
968 978 LDAPControl **serverctrls,
969 979 LDAPControl **clientctrls,
970 980 struct timeval *localtimeoutp,
971 981 int timelimit, /* -1 means use ld->ld_timelimit */
972 982 int sizelimit, /* -1 means use ld->ld_sizelimit */
973 983 LDAPMessage **res
974 984 )
975 985 {
976 986 int err, msgid;
977 987
978 988 /*
979 989 * It is an error to pass in a zero'd timeval.
980 990 */
981 991 if ( localtimeoutp != NULL && localtimeoutp->tv_sec == 0 &&
982 992 localtimeoutp->tv_usec == 0 ) {
983 993 if ( ld != NULL ) {
984 994 LDAP_SET_LDERRNO( ld, LDAP_PARAM_ERROR, NULL, NULL );
985 995 }
986 996 if ( res != NULL ) {
987 997 *res = NULL;
988 998 }
989 999 return( LDAP_PARAM_ERROR );
990 1000 }
991 1001
992 1002 if (( err = nsldapi_search( ld, base, scope, filter, attrs, attrsonly,
993 1003 serverctrls, clientctrls, timelimit, sizelimit, &msgid ))
994 1004 != LDAP_SUCCESS ) {
995 1005 if ( res != NULL ) {
996 1006 *res = NULL;
997 1007 }
998 1008 return( err );
999 1009 }
1000 1010
1001 1011 if ( ldap_result( ld, msgid, 1, localtimeoutp, res ) == -1 ) {
1002 1012 /*
1003 1013 * Error. ldap_result() sets *res to NULL for us.
1004 1014 */
1005 1015 return( LDAP_GET_LDERRNO( ld, NULL, NULL ) );
1006 1016 }
1007 1017
1008 1018 if ( LDAP_GET_LDERRNO( ld, NULL, NULL ) == LDAP_TIMEOUT ) {
1009 1019 (void) ldap_abandon( ld, msgid );
1010 1020 err = LDAP_TIMEOUT;
1011 1021 LDAP_SET_LDERRNO( ld, err, NULL, NULL );
1012 1022 if ( res != NULL ) {
1013 1023 *res = NULL;
1014 1024 }
1015 1025 return( err );
1016 1026 }
1017 1027
1018 1028 return( ldap_result2error( ld, *res, 0 ) );
1019 1029 }
|
↓ open down ↓ |
202 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX