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>
36 static char *find_right_paren( char *s );
37 static char *put_complex_filter( BerElement *ber, char *str,
38 unsigned long tag, int not );
39 static int put_filter( BerElement *ber, char *str );
40 static int put_simple_filter( BerElement *ber, char *str );
41 static int put_substring_filter( BerElement *ber, char *type, char *str );
42 static int put_filter_list( BerElement *ber, char *str );
44 static char *find_right_paren();
45 static char *put_complex_filter();
46 static int put_filter();
47 static int put_simple_filter();
48 static int put_substring_filter();
49 static int put_filter_list();
50 #endif /* NEEDPROTOS */
53 * ldap_search - initiate an ldap (and X.500) search operation. Parameters:
56 * base DN of the base object
57 * scope the search scope - one of LDAP_SCOPE_BASE,
58 * LDAP_SCOPE_ONELEVEL, LDAP_SCOPE_SUBTREE
59 * filter a string containing the search filter
60 * (e.g., "(|(cn=bob)(sn=bob))")
61 * attrs list of attribute types to return for matches
62 * attrsonly 1 => attributes only 0 => attributes and values
65 * char *attrs[] = { "mail", "title", 0 };
66 * msgid = ldap_search( ld, "c=us@o=UM", LDAP_SCOPE_SUBTREE, "cn~=bob",
70 ldap_search( LDAP *ld, char *base, int scope, char *filter,
71 char **attrs, int attrsonly )
75 Debug( LDAP_DEBUG_TRACE, "ldap_search\n", 0, 0, 0 );
77 if (( ber = ldap_build_search_req( ld, base, scope, filter, attrs,
78 attrsonly )) == NULLBER ) {
83 if ( ld->ld_cache != NULL ) {
84 if ( ldap_check_cache( ld, LDAP_REQ_SEARCH, ber ) == 0 ) {
86 ld->ld_errno = LDAP_SUCCESS;
87 return( ld->ld_msgid );
89 ldap_add_request_to_cache( ld, LDAP_REQ_SEARCH, ber );
93 /* send the message */
94 return ( ldap_send_initial_request( ld, LDAP_REQ_SEARCH, base, ber ));
99 ldap_build_search_req( LDAP *ld, char *base, int scope, char *filter,
100 char **attrs, int attrsonly )
106 * Create the search request. It looks like this:
107 * SearchRequest := [APPLICATION 3] SEQUENCE {
108 * baseObject DistinguishedName,
114 * derefAliases ENUMERATED {
115 * neverDerefaliases (0),
116 * derefInSearching (1),
117 * derefFindingBaseObj (2),
118 * alwaysDerefAliases (3)
120 * sizelimit INTEGER (0 .. 65535),
121 * timelimit INTEGER (0 .. 65535),
124 * attributes SEQUENCE OF AttributeType
126 * wrapped in an ldap message.
129 /* create a message to send */
130 if ( (ber = ldap_alloc_ber_with_options( ld )) == NULLBER ) {
134 if ( base == NULL ) {
139 if ( ld->ld_sb.sb_naddr > 0 ) {
140 err = ber_printf( ber, "{ist{seeiib", ++ld->ld_msgid,
141 ld->ld_cldapdn, LDAP_REQ_SEARCH, base, scope, ld->ld_deref,
142 ld->ld_sizelimit, ld->ld_timelimit, attrsonly );
145 err = ber_printf( ber, "{it{seeiib", ++ld->ld_msgid,
146 LDAP_REQ_SEARCH, base, scope, ld->ld_deref,
147 ld->ld_sizelimit, ld->ld_timelimit, attrsonly );
153 ld->ld_errno = LDAP_ENCODING_ERROR;
158 filter = strdup( filter );
159 err = put_filter( ber, filter );
163 ld->ld_errno = LDAP_FILTER_ERROR;
168 if ( ber_printf( ber, "{v}}}", attrs ) == -1 ) {
169 ld->ld_errno = LDAP_ENCODING_ERROR;
178 find_right_paren( char *s )
184 while ( *s && balance ) {
188 else if ( *s == ')' )
191 if ( *s == '\\' && ! escape )
199 return( *s ? s : NULL );
203 put_complex_filter( BerElement *ber, char *str, unsigned long tag, int not )
208 * We have (x(filter)...) with str sitting on
209 * the x. We have to find the paren matching
210 * the one before the x and put the intervening
211 * filters by calling put_filter_list().
214 /* put explicit tag */
215 if ( ber_printf( ber, "t{", tag ) == -1 )
218 if ( !not && ber_printf( ber, "{" ) == -1 )
223 if ( (next = find_right_paren( str )) == NULL )
227 if ( put_filter_list( ber, str ) == -1 )
231 /* flush explicit tagged thang */
232 if ( ber_printf( ber, "}" ) == -1 )
235 if ( !not && ber_printf( ber, "}" ) == -1 )
243 put_filter( BerElement *ber, char *str )
245 char *next, *tmp, *s, *d;
246 int parens, balance, escape, gotescape;
249 * A Filter looks like this:
250 * Filter ::= CHOICE {
251 * and [0] SET OF Filter,
252 * or [1] SET OF Filter,
254 * equalityMatch [3] AttributeValueAssertion,
255 * substrings [4] SubstringFilter,
256 * greaterOrEqual [5] AttributeValueAssertion,
257 * lessOrEqual [6] AttributeValueAssertion,
258 * present [7] AttributeType,,
259 * approxMatch [8] AttributeValueAssertion
262 * SubstringFilter ::= SEQUENCE {
263 * type AttributeType,
264 * SEQUENCE OF CHOICE {
265 * initial [0] IA5String,
267 * final [2] IA5String
270 * Note: tags in a choice are always explicit
273 Debug( LDAP_DEBUG_TRACE, "put_filter \"%s\"\n", str, 0, 0 );
275 gotescape = parens = 0;
283 Debug( LDAP_DEBUG_TRACE, "put_filter: AND\n",
286 if ( (str = put_complex_filter( ber, str,
287 LDAP_FILTER_AND, 0 )) == NULL )
294 Debug( LDAP_DEBUG_TRACE, "put_filter: OR\n",
297 if ( (str = put_complex_filter( ber, str,
298 LDAP_FILTER_OR, 0 )) == NULL )
305 Debug( LDAP_DEBUG_TRACE, "put_filter: NOT\n",
308 if ( (str = put_complex_filter( ber, str,
309 LDAP_FILTER_NOT, 1 )) == NULL )
316 Debug( LDAP_DEBUG_TRACE, "put_filter: simple\n",
322 while ( *next && balance ) {
326 else if ( *next == ')' )
329 if ( *next == '\\' && ! escape )
330 gotescape = escape = 1;
343 for ( s = d = tmp; *s; s++ ) {
344 if ( *s != '\\' || escape ) {
353 if ( put_simple_filter( ber, tmp ) == -1 ) {
366 Debug( LDAP_DEBUG_TRACE, "put_filter: end\n", 0, 0,
368 if ( ber_printf( ber, "]" ) == -1 )
378 default: /* assume it's a simple type=value filter */
379 Debug( LDAP_DEBUG_TRACE, "put_filter: default\n", 0, 0,
381 next = strchr( str, '\0' );
383 if ( strchr( tmp, '\\' ) != NULL ) {
385 for ( s = d = tmp; *s; s++ ) {
386 if ( *s != '\\' || escape ) {
395 if ( put_simple_filter( ber, tmp ) == -1 ) {
405 return( parens ? -1 : 0 );
409 * Put a list of filters like this "(filter1)(filter2)..."
413 put_filter_list( BerElement *ber, char *str )
418 Debug( LDAP_DEBUG_TRACE, "put_filter_list \"%s\"\n", str, 0, 0 );
421 while ( *str && isspace( *str ) )
426 if ( (next = find_right_paren( str + 1 )) == NULL )
430 /* now we have "(filter)" with str pointing to it */
432 if ( put_filter( ber, str ) == -1 )
443 put_simple_filter( BerElement *ber, char *str )
446 char *value, savechar;
450 Debug( LDAP_DEBUG_TRACE, "put_simple_filter \"%s\"\n", str, 0, 0 );
452 if ( (s = strchr( str, '=' )) == NULL )
460 ftype = LDAP_FILTER_LE;
464 ftype = LDAP_FILTER_GE;
468 ftype = LDAP_FILTER_APPROX;
472 if ( strchr( value, '*' ) == NULL ) {
473 ftype = LDAP_FILTER_EQUALITY;
474 } else if ( strcmp( value, "*" ) == 0 ) {
475 ftype = LDAP_FILTER_PRESENT;
477 rc = put_substring_filter( ber, str, value );
484 if ( ftype == LDAP_FILTER_PRESENT ) {
485 rc = ber_printf( ber, "ts", ftype, str );
487 rc = ber_printf( ber, "t{ss}", ftype, str, value );
492 return( rc == -1 ? rc : 0 );
496 put_substring_filter( BerElement *ber, char *type, char *val )
498 char *nextstar, gotstar = 0;
501 Debug( LDAP_DEBUG_TRACE, "put_substring_filter \"%s=%s\"\n", type,
504 if ( ber_printf( ber, "t{s{", LDAP_FILTER_SUBSTRINGS, type ) == -1 )
507 while ( val != NULL ) {
508 if ( (nextstar = strchr( val, '*' )) != NULL )
511 if ( gotstar == 0 ) {
512 ftype = LDAP_SUBSTRING_INITIAL;
513 } else if ( nextstar == NULL ) {
514 ftype = LDAP_SUBSTRING_FINAL;
516 ftype = LDAP_SUBSTRING_ANY;
518 if ( *val != '\0' ) {
519 if ( ber_printf( ber, "ts", ftype, val ) == -1 )
524 if ( nextstar != NULL )
529 if ( ber_printf( ber, "}}" ) == -1 )
536 ldap_search_st( LDAP *ld, char *base, int scope, char *filter, char **attrs,
537 int attrsonly, struct timeval *timeout, LDAPMessage **res )
541 if ( (msgid = ldap_search( ld, base, scope, filter, attrs, attrsonly ))
543 return( ld->ld_errno );
545 if ( ldap_result( ld, msgid, 1, timeout, res ) == -1 )
546 return( ld->ld_errno );
548 if ( ld->ld_errno == LDAP_TIMEOUT ) {
549 (void) ldap_abandon( ld, msgid );
550 ld->ld_errno = LDAP_TIMEOUT;
551 return( ld->ld_errno );
554 return( ldap_result2error( ld, *res, 0 ) );
558 ldap_search_s( LDAP *ld, char *base, int scope, char *filter, char **attrs,
559 int attrsonly, LDAPMessage **res )
563 if ( (msgid = ldap_search( ld, base, scope, filter, attrs, attrsonly ))
565 return( ld->ld_errno );
567 if ( ldap_result( ld, msgid, 1, (struct timeval *) NULL, res ) == -1 )
568 return( ld->ld_errno );
570 return( ldap_result2error( ld, *res, 0 ) );