2 * Copyright (c) 1990 Regents of the University of Michigan.
9 static char copyright[] = "@(#) Copyright (c) 1990 Regents of the University of Michigan.\nAll rights reserved.\n";
21 #if defined( DOS ) || defined( _WIN32 )
25 #if !defined(MACOS) && !defined(DOS) && !defined( _WIN32 )
27 #include <sys/types.h>
28 #include <sys/socket.h>
35 static char *find_right_paren( char *s );
36 static char *put_complex_filter( BerElement *ber, char *str,
37 unsigned long tag, int not );
38 static int put_filter( BerElement *ber, char *str );
39 static int put_simple_filter( BerElement *ber, char *str );
40 static int put_substring_filter( BerElement *ber, char *type, char *str );
41 static int put_filter_list( BerElement *ber, char *str );
43 static char *find_right_paren();
44 static char *put_complex_filter();
45 static int put_filter();
46 static int put_simple_filter();
47 static int put_substring_filter();
48 static int put_filter_list();
49 #endif /* NEEDPROTOS */
52 * ldap_search - initiate an ldap (and X.500) search operation. Parameters:
55 * base DN of the base object
56 * scope the search scope - one of LDAP_SCOPE_BASE,
57 * LDAP_SCOPE_ONELEVEL, LDAP_SCOPE_SUBTREE
58 * filter a string containing the search filter
59 * (e.g., "(|(cn=bob)(sn=bob))")
60 * attrs list of attribute types to return for matches
61 * attrsonly 1 => attributes only 0 => attributes and values
64 * char *attrs[] = { "mail", "title", 0 };
65 * msgid = ldap_search( ld, "c=us@o=UM", LDAP_SCOPE_SUBTREE, "cn~=bob",
69 ldap_search( LDAP *ld, char *base, int scope, char *filter,
70 char **attrs, int attrsonly )
74 Debug( LDAP_DEBUG_TRACE, "ldap_search\n", 0, 0, 0 );
76 if (( ber = ldap_build_search_req( ld, base, scope, filter, attrs,
77 attrsonly )) == NULLBER ) {
82 if ( ld->ld_cache != NULL ) {
83 if ( ldap_check_cache( ld, LDAP_REQ_SEARCH, ber ) == 0 ) {
85 ld->ld_errno = LDAP_SUCCESS;
86 return( ld->ld_msgid );
88 ldap_add_request_to_cache( ld, LDAP_REQ_SEARCH, ber );
92 /* send the message */
93 return ( ldap_send_initial_request( ld, LDAP_REQ_SEARCH, base, ber ));
98 ldap_build_search_req( LDAP *ld, char *base, int scope, char *filter,
99 char **attrs, int attrsonly )
105 * Create the search request. It looks like this:
106 * SearchRequest := [APPLICATION 3] SEQUENCE {
107 * baseObject DistinguishedName,
113 * derefAliases ENUMERATED {
114 * neverDerefaliases (0),
115 * derefInSearching (1),
116 * derefFindingBaseObj (2),
117 * alwaysDerefAliases (3)
119 * sizelimit INTEGER (0 .. 65535),
120 * timelimit INTEGER (0 .. 65535),
123 * attributes SEQUENCE OF AttributeType
125 * wrapped in an ldap message.
128 /* create a message to send */
129 if ( (ber = ldap_alloc_ber_with_options( ld )) == NULLBER ) {
133 if ( base == NULL ) {
138 if ( ld->ld_sb.sb_naddr > 0 ) {
139 err = ber_printf( ber, "{ist{seeiib", ++ld->ld_msgid,
140 ld->ld_cldapdn, LDAP_REQ_SEARCH, base, scope, ld->ld_deref,
141 ld->ld_sizelimit, ld->ld_timelimit, attrsonly );
144 err = ber_printf( ber, "{it{seeiib", ++ld->ld_msgid,
145 LDAP_REQ_SEARCH, base, scope, ld->ld_deref,
146 ld->ld_sizelimit, ld->ld_timelimit, attrsonly );
152 ld->ld_errno = LDAP_ENCODING_ERROR;
157 filter = strdup( filter );
158 err = put_filter( ber, filter );
162 ld->ld_errno = LDAP_FILTER_ERROR;
167 if ( ber_printf( ber, "{v}}}", attrs ) == -1 ) {
168 ld->ld_errno = LDAP_ENCODING_ERROR;
177 find_right_paren( char *s )
183 while ( *s && balance ) {
187 else if ( *s == ')' )
190 if ( *s == '\\' && ! escape )
198 return( *s ? s : NULL );
202 put_complex_filter( BerElement *ber, char *str, unsigned long tag, int not )
207 * We have (x(filter)...) with str sitting on
208 * the x. We have to find the paren matching
209 * the one before the x and put the intervening
210 * filters by calling put_filter_list().
213 /* put explicit tag */
214 if ( ber_printf( ber, "t{", tag ) == -1 )
217 if ( !not && ber_printf( ber, "{" ) == -1 )
222 if ( (next = find_right_paren( str )) == NULL )
226 if ( put_filter_list( ber, str ) == -1 )
230 /* flush explicit tagged thang */
231 if ( ber_printf( ber, "}" ) == -1 )
234 if ( !not && ber_printf( ber, "}" ) == -1 )
242 put_filter( BerElement *ber, char *str )
244 char *next, *tmp, *s, *d;
245 int parens, balance, escape, gotescape;
248 * A Filter looks like this:
249 * Filter ::= CHOICE {
250 * and [0] SET OF Filter,
251 * or [1] SET OF Filter,
253 * equalityMatch [3] AttributeValueAssertion,
254 * substrings [4] SubstringFilter,
255 * greaterOrEqual [5] AttributeValueAssertion,
256 * lessOrEqual [6] AttributeValueAssertion,
257 * present [7] AttributeType,,
258 * approxMatch [8] AttributeValueAssertion
261 * SubstringFilter ::= SEQUENCE {
262 * type AttributeType,
263 * SEQUENCE OF CHOICE {
264 * initial [0] IA5String,
266 * final [2] IA5String
269 * Note: tags in a choice are always explicit
272 Debug( LDAP_DEBUG_TRACE, "put_filter \"%s\"\n", str, 0, 0 );
274 gotescape = parens = 0;
282 Debug( LDAP_DEBUG_TRACE, "put_filter: AND\n",
285 if ( (str = put_complex_filter( ber, str,
286 LDAP_FILTER_AND, 0 )) == NULL )
293 Debug( LDAP_DEBUG_TRACE, "put_filter: OR\n",
296 if ( (str = put_complex_filter( ber, str,
297 LDAP_FILTER_OR, 0 )) == NULL )
304 Debug( LDAP_DEBUG_TRACE, "put_filter: NOT\n",
307 if ( (str = put_complex_filter( ber, str,
308 LDAP_FILTER_NOT, 1 )) == NULL )
315 Debug( LDAP_DEBUG_TRACE, "put_filter: simple\n",
321 while ( *next && balance ) {
325 else if ( *next == ')' )
328 if ( *next == '\\' && ! escape )
329 gotescape = escape = 1;
342 for ( s = d = tmp; *s; s++ ) {
343 if ( *s != '\\' || escape ) {
352 if ( put_simple_filter( ber, tmp ) == -1 ) {
365 Debug( LDAP_DEBUG_TRACE, "put_filter: end\n", 0, 0,
367 if ( ber_printf( ber, "]" ) == -1 )
377 default: /* assume it's a simple type=value filter */
378 Debug( LDAP_DEBUG_TRACE, "put_filter: default\n", 0, 0,
380 next = strchr( str, '\0' );
382 if ( strchr( tmp, '\\' ) != NULL ) {
384 for ( s = d = tmp; *s; s++ ) {
385 if ( *s != '\\' || escape ) {
394 if ( put_simple_filter( ber, tmp ) == -1 ) {
404 return( parens ? -1 : 0 );
408 * Put a list of filters like this "(filter1)(filter2)..."
412 put_filter_list( BerElement *ber, char *str )
417 Debug( LDAP_DEBUG_TRACE, "put_filter_list \"%s\"\n", str, 0, 0 );
420 while ( *str && isspace( *str ) )
425 if ( (next = find_right_paren( str + 1 )) == NULL )
429 /* now we have "(filter)" with str pointing to it */
431 if ( put_filter( ber, str ) == -1 )
442 put_simple_filter( BerElement *ber, char *str )
445 char *value, savechar;
449 Debug( LDAP_DEBUG_TRACE, "put_simple_filter \"%s\"\n", str, 0, 0 );
451 if ( (s = strchr( str, '=' )) == NULL )
459 ftype = LDAP_FILTER_LE;
463 ftype = LDAP_FILTER_GE;
467 ftype = LDAP_FILTER_APPROX;
471 if ( strchr( value, '*' ) == NULL ) {
472 ftype = LDAP_FILTER_EQUALITY;
473 } else if ( strcmp( value, "*" ) == 0 ) {
474 ftype = LDAP_FILTER_PRESENT;
476 rc = put_substring_filter( ber, str, value );
483 if ( ftype == LDAP_FILTER_PRESENT ) {
484 rc = ber_printf( ber, "ts", ftype, str );
486 rc = ber_printf( ber, "t{ss}", ftype, str, value );
491 return( rc == -1 ? rc : 0 );
495 put_substring_filter( BerElement *ber, char *type, char *val )
497 char *nextstar, gotstar = 0;
500 Debug( LDAP_DEBUG_TRACE, "put_substring_filter \"%s=%s\"\n", type,
503 if ( ber_printf( ber, "t{s{", LDAP_FILTER_SUBSTRINGS, type ) == -1 )
506 while ( val != NULL ) {
507 if ( (nextstar = strchr( val, '*' )) != NULL )
510 if ( gotstar == 0 ) {
511 ftype = LDAP_SUBSTRING_INITIAL;
512 } else if ( nextstar == NULL ) {
513 ftype = LDAP_SUBSTRING_FINAL;
515 ftype = LDAP_SUBSTRING_ANY;
517 if ( *val != '\0' ) {
518 if ( ber_printf( ber, "ts", ftype, val ) == -1 )
523 if ( nextstar != NULL )
528 if ( ber_printf( ber, "}}" ) == -1 )
535 ldap_search_st( LDAP *ld, char *base, int scope, char *filter, char **attrs,
536 int attrsonly, struct timeval *timeout, LDAPMessage **res )
540 if ( (msgid = ldap_search( ld, base, scope, filter, attrs, attrsonly ))
542 return( ld->ld_errno );
544 if ( ldap_result( ld, msgid, 1, timeout, res ) == -1 )
545 return( ld->ld_errno );
547 if ( ld->ld_errno == LDAP_TIMEOUT ) {
548 (void) ldap_abandon( ld, msgid );
549 ld->ld_errno = LDAP_TIMEOUT;
550 return( ld->ld_errno );
553 return( ldap_result2error( ld, *res, 0 ) );
557 ldap_search_s( LDAP *ld, char *base, int scope, char *filter, char **attrs,
558 int attrsonly, LDAPMessage **res )
562 if ( (msgid = ldap_search( ld, base, scope, filter, attrs, attrsonly ))
564 return( ld->ld_errno );
566 if ( ldap_result( ld, msgid, 1, (struct timeval *) NULL, res ) == -1 )
567 return( ld->ld_errno );
569 return( ldap_result2error( ld, *res, 0 ) );