X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=libraries%2Flibldap%2Fsearch.c;h=9d27820f93fa7114993c74e5a2d4165f3e0aab69;hb=df8f7cbb9b79be3be9205d116d1dd0b263d6861a;hp=c9f984a5112844cf7ac4e2fb3349115d6bdf533e;hpb=fcbca73f90d6f4dd09e7ff34533b6ac1baff2135;p=openldap diff --git a/libraries/libldap/search.c b/libraries/libldap/search.c index c9f984a511..9d27820f93 100644 --- a/libraries/libldap/search.c +++ b/libraries/libldap/search.c @@ -1,55 +1,162 @@ /* + * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved. + * COPYING RESTRICTIONS APPLY, see COPYRIGHT file + */ +/* Portions * Copyright (c) 1990 Regents of the University of Michigan. * All rights reserved. * * search.c */ -#ifndef lint -static char copyright[] = "@(#) Copyright (c) 1990 Regents of the University of Michigan.\nAll rights reserved.\n"; -#endif +#include "portable.h" #include -#include -#include - -#ifdef MACOS -#include -#include "macos.h" -#endif /* MACOS */ - -#if defined( DOS ) || defined( _WIN32 ) -#include "msdos.h" -#endif /* DOS */ - -#if !defined(MACOS) && !defined(DOS) && !defined( _WIN32 ) -#include -#include -#include -#endif -#include "lber.h" -#include "ldap.h" + +#include + +#include +#include +#include +#include + #include "ldap-int.h" -#ifdef NEEDPROTOS -static char *find_right_paren( char *s ); -static char *put_complex_filter( BerElement *ber, char *str, - unsigned long tag, int not ); -static int put_filter( BerElement *ber, char *str ); -static int put_simple_filter( BerElement *ber, char *str ); -static int put_substring_filter( BerElement *ber, char *type, char *str ); -static int put_filter_list( BerElement *ber, char *str ); -#else -static char *find_right_paren(); -static char *put_complex_filter(); -static int put_filter(); -static int put_simple_filter(); -static int put_substring_filter(); -static int put_filter_list(); -#endif /* NEEDPROTOS */ +static char *find_right_paren LDAP_P(( + char *s )); + +static char *put_complex_filter LDAP_P(( + BerElement *ber, + char *str, + ber_tag_t tag, + int not )); + +static int put_filter LDAP_P(( + BerElement *ber, + char *str )); + +static int put_simple_filter LDAP_P(( + BerElement *ber, + char *str )); + +static int put_substring_filter LDAP_P(( + BerElement *ber, + char *type, + char *str )); + +static int put_filter_list LDAP_P(( + BerElement *ber, + char *str )); /* - * ldap_search - initiate an ldap (and X.500) search operation. Parameters: + * ldap_search_ext - initiate an ldap search operation. + * + * Parameters: + * + * ld LDAP descriptor + * base DN of the base object + * scope the search scope - one of LDAP_SCOPE_BASE, + * LDAP_SCOPE_ONELEVEL, LDAP_SCOPE_SUBTREE + * filter a string containing the search filter + * (e.g., "(|(cn=bob)(sn=bob))") + * attrs list of attribute types to return for matches + * attrsonly 1 => attributes only 0 => attributes and values + * + * Example: + * char *attrs[] = { "mail", "title", 0 }; + * ldap_search_ext( ld, "c=us@o=UM", LDAP_SCOPE_SUBTREE, "cn~=bob", + * attrs, attrsonly, sctrls, ctrls, timeout, sizelimit, + * &msgid ); + */ +int +ldap_search_ext( + LDAP *ld, + LDAP_CONST char *base, + int scope, + LDAP_CONST char *filter, + char **attrs, + int attrsonly, + LDAPControl **sctrls, + LDAPControl **cctrls, + struct timeval *timeout, + int sizelimit, + int *msgidp ) +{ + BerElement *ber; + int timelimit; + + Debug( LDAP_DEBUG_TRACE, "ldap_search_ext\n", 0, 0, 0 ); + + /* + * if timeout is provided, use only tv_sec as timelimit. + * otherwise, use default. + */ + timelimit = (timeout != NULL) + ? timeout->tv_sec + : -1; + + ber = ldap_build_search_req( ld, base, scope, filter, attrs, + attrsonly, sctrls, cctrls, timelimit, sizelimit ); + + if ( ber == NULL ) { + return ld->ld_errno; + } + +#ifndef LDAP_NOCACHE + if ( ld->ld_cache != NULL ) { + if ( ldap_check_cache( ld, LDAP_REQ_SEARCH, ber ) == 0 ) { + ber_free( ber, 1 ); + ld->ld_errno = LDAP_SUCCESS; + *msgidp = ld->ld_msgid; + return ld->ld_errno; + } + ldap_add_request_to_cache( ld, LDAP_REQ_SEARCH, ber ); + } +#endif /* LDAP_NOCACHE */ + + /* send the message */ + *msgidp = ldap_send_initial_request( ld, LDAP_REQ_SEARCH, base, ber ); + + if( *msgidp < 0 ) + return ld->ld_errno; + + return LDAP_SUCCESS; +} + +int +ldap_search_ext_s( + LDAP *ld, + LDAP_CONST char *base, + int scope, + LDAP_CONST char *filter, + char **attrs, + int attrsonly, + LDAPControl **sctrls, + LDAPControl **cctrls, + struct timeval *timeout, + int sizelimit, + LDAPMessage **res ) +{ + int rc; + int msgid; + + rc = ldap_search_ext( ld, base, scope, filter, attrs, attrsonly, + sctrls, cctrls, timeout, sizelimit, &msgid ); + + if ( rc != LDAP_SUCCESS ) { + return( rc ); + } + + if ( ldap_result( ld, msgid, 1, timeout, res ) == -1 ) + return( ld->ld_errno ); + + return( ldap_result2error( ld, *res, 0 ) ); +} + +/* + * ldap_search - initiate an ldap search operation. + * + * Parameters: * * ld LDAP descriptor * base DN of the base object @@ -66,19 +173,22 @@ static int put_filter_list(); * attrs, attrsonly ); */ int -ldap_search( LDAP *ld, char *base, int scope, char *filter, +ldap_search( + LDAP *ld, LDAP_CONST char *base, int scope, LDAP_CONST char *filter, char **attrs, int attrsonly ) { BerElement *ber; Debug( LDAP_DEBUG_TRACE, "ldap_search\n", 0, 0, 0 ); - if (( ber = ldap_build_search_req( ld, base, scope, filter, attrs, - attrsonly )) == NULLBER ) { + ber = ldap_build_search_req( ld, base, scope, filter, attrs, + attrsonly, NULL, NULL, -1, -1 ); + + if ( ber == NULL ) { return( -1 ); } -#ifndef NO_CACHE +#ifndef LDAP_NOCACHE if ( ld->ld_cache != NULL ) { if ( ldap_check_cache( ld, LDAP_REQ_SEARCH, ber ) == 0 ) { ber_free( ber, 1 ); @@ -87,7 +197,7 @@ ldap_search( LDAP *ld, char *base, int scope, char *filter, } ldap_add_request_to_cache( ld, LDAP_REQ_SEARCH, ber ); } -#endif /* NO_CACHE */ +#endif /* LDAP_NOCACHE */ /* send the message */ return ( ldap_send_initial_request( ld, LDAP_REQ_SEARCH, base, ber )); @@ -95,11 +205,22 @@ ldap_search( LDAP *ld, char *base, int scope, char *filter, BerElement * -ldap_build_search_req( LDAP *ld, char *base, int scope, char *filter, - char **attrs, int attrsonly ) +ldap_build_search_req( + LDAP *ld, + LDAP_CONST char *base_in, + ber_int_t scope, + LDAP_CONST char *filter_in, + char **attrs, + ber_int_t attrsonly, + LDAPControl **sctrls, + LDAPControl **cctrls, + ber_int_t timelimit, + ber_int_t sizelimit ) { BerElement *ber; int err; + char *base; + char *filter; /* * Create the search request. It looks like this: @@ -126,48 +247,72 @@ ldap_build_search_req( LDAP *ld, char *base, int scope, char *filter, */ /* create a message to send */ - if ( (ber = ldap_alloc_ber_with_options( ld )) == NULLBER ) { - return( NULLBER ); + if ( (ber = ldap_alloc_ber_with_options( ld )) == NULL ) { + return( NULL ); + } + + if ( base_in == NULL ) { + /* no base provided, use session default base */ + base = ld->ld_options.ldo_defbase; + } else { + base = (char *) base_in; } if ( base == NULL ) { + /* no session default base, use top */ base = ""; } -#ifdef CLDAP - if ( ld->ld_sb.sb_naddr > 0 ) { +#ifdef LDAP_CONNECTIONLESS + if ( ld->ld_cldapnaddr > 0 ) { err = ber_printf( ber, "{ist{seeiib", ++ld->ld_msgid, - ld->ld_cldapdn, LDAP_REQ_SEARCH, base, scope, ld->ld_deref, - ld->ld_sizelimit, ld->ld_timelimit, attrsonly ); + ld->ld_cldapdn, LDAP_REQ_SEARCH, base, scope, ld->ld_deref, + (sizelimit < 0) ? ld->ld_sizelimit : sizelimit, + (timelimit < 0) ? ld->ld_timelimit : timelimit, + attrsonly ); } else { -#endif /* CLDAP */ +#endif /* LDAP_CONNECTIONLESS */ err = ber_printf( ber, "{it{seeiib", ++ld->ld_msgid, - LDAP_REQ_SEARCH, base, scope, ld->ld_deref, - ld->ld_sizelimit, ld->ld_timelimit, attrsonly ); -#ifdef CLDAP + LDAP_REQ_SEARCH, base, (ber_int_t) scope, ld->ld_deref, + (sizelimit < 0) ? ld->ld_sizelimit : sizelimit, + (timelimit < 0) ? ld->ld_timelimit : timelimit, + attrsonly ); +#ifdef LDAP_CONNECTIONLESS } -#endif /* CLDAP */ +#endif /* LDAP_CONNECTIONLESS */ if ( err == -1 ) { ld->ld_errno = LDAP_ENCODING_ERROR; ber_free( ber, 1 ); - return( NULLBER ); + return( NULL ); } - filter = strdup( filter ); + filter = LDAP_STRDUP( filter_in ); err = put_filter( ber, filter ); - free( filter ); + LDAP_FREE( filter ); if ( err == -1 ) { ld->ld_errno = LDAP_FILTER_ERROR; ber_free( ber, 1 ); - return( NULLBER ); + return( NULL ); } - if ( ber_printf( ber, "{v}}}", attrs ) == -1 ) { + if ( ber_printf( ber, /*{*/ "{v}}", attrs ) == -1 ) { ld->ld_errno = LDAP_ENCODING_ERROR; ber_free( ber, 1 ); - return( NULLBER ); + return( NULL ); + } + + /* Put Server Controls */ + if( ldap_int_put_controls( ld, sctrls, ber ) != LDAP_SUCCESS ) { + ber_free( ber, 1 ); + return( NULL ); + } + + if ( ber_printf( ber, /*{*/ "}", attrs ) == -1 ) { + ld->ld_errno = LDAP_ENCODING_ERROR; + ber_free( ber, 1 ); + return( NULL ); } return( ber ); @@ -199,7 +344,7 @@ find_right_paren( char *s ) } static char * -put_complex_filter( BerElement *ber, char *str, unsigned long tag, int not ) +put_complex_filter( BerElement *ber, char *str, ber_tag_t tag, int not ) { char *next; @@ -211,12 +356,8 @@ put_complex_filter( BerElement *ber, char *str, unsigned long tag, int not ) */ /* put explicit tag */ - if ( ber_printf( ber, "t{", tag ) == -1 ) - return( NULL ); -/* - if ( !not && ber_printf( ber, "{" ) == -1 ) + if ( ber_printf( ber, "t{" /*}*/, tag ) == -1 ) return( NULL ); -*/ str++; if ( (next = find_right_paren( str )) == NULL ) @@ -228,12 +369,8 @@ put_complex_filter( BerElement *ber, char *str, unsigned long tag, int not ) *next++ = ')'; /* flush explicit tagged thang */ - if ( ber_printf( ber, "}" ) == -1 ) + if ( ber_printf( ber, /*{*/ "}" ) == -1 ) return( NULL ); -/* - if ( !not && ber_printf( ber, "}" ) == -1 ) - return( NULL ); -*/ return( next ); } @@ -254,8 +391,9 @@ put_filter( BerElement *ber, char *str ) * substrings [4] SubstringFilter, * greaterOrEqual [5] AttributeValueAssertion, * lessOrEqual [6] AttributeValueAssertion, - * present [7] AttributeType,, - * approxMatch [8] AttributeValueAssertion + * present [7] AttributeType, + * approxMatch [8] AttributeValueAssertion, + * extensibleMatch [9] MatchingRuleAssertion -- LDAPv3 * } * * SubstringFilter ::= SEQUENCE { @@ -266,6 +404,13 @@ put_filter( BerElement *ber, char *str ) * final [2] IA5String * } * } + * + * MatchingRuleAssertion ::= SEQUENCE { -- LDAPv3 + * matchingRule [1] MatchingRuleId OPTIONAL, + * type [2] AttributeDescription OPTIONAL, + * matchValue [3] AssertionValue, + * dnAttributes [4] BOOLEAN DEFAULT FALSE } + * * Note: tags in a choice are always explicit */ @@ -336,7 +481,7 @@ put_filter( BerElement *ber, char *str ) return( -1 ); *next = '\0'; - tmp = strdup( str ); + tmp = LDAP_STRDUP( str ); if ( gotescape ) { escape = 0; for ( s = d = tmp; *s; s++ ) { @@ -350,10 +495,10 @@ put_filter( BerElement *ber, char *str ) *d = '\0'; } if ( put_simple_filter( ber, tmp ) == -1 ) { - free( tmp ); + LDAP_FREE( tmp ); return( -1 ); } - free( tmp ); + LDAP_FREE( tmp ); *next++ = ')'; str = next; parens--; @@ -364,7 +509,7 @@ put_filter( BerElement *ber, char *str ) case ')': Debug( LDAP_DEBUG_TRACE, "put_filter: end\n", 0, 0, 0 ); - if ( ber_printf( ber, "]" ) == -1 ) + if ( ber_printf( ber, /*[*/ "]" ) == -1 ) return( -1 ); str++; parens--; @@ -378,7 +523,7 @@ put_filter( BerElement *ber, char *str ) Debug( LDAP_DEBUG_TRACE, "put_filter: default\n", 0, 0, 0 ); next = strchr( str, '\0' ); - tmp = strdup( str ); + tmp = LDAP_STRDUP( str ); if ( strchr( tmp, '\\' ) != NULL ) { escape = 0; for ( s = d = tmp; *s; s++ ) { @@ -392,10 +537,10 @@ put_filter( BerElement *ber, char *str ) *d = '\0'; } if ( put_simple_filter( ber, tmp ) == -1 ) { - free( tmp ); + LDAP_FREE( tmp ); return( -1 ); } - free( tmp ); + LDAP_FREE( tmp ); str = next; break; } @@ -417,7 +562,7 @@ put_filter_list( BerElement *ber, char *str ) Debug( LDAP_DEBUG_TRACE, "put_filter_list \"%s\"\n", str, 0, 0 ); while ( *str ) { - while ( *str && isspace( *str ) ) + while ( *str && isspace( (unsigned char) *str ) ) str++; if ( *str == '\0' ) break; @@ -439,11 +584,13 @@ put_filter_list( BerElement *ber, char *str ) } static int -put_simple_filter( BerElement *ber, char *str ) +put_simple_filter( + BerElement *ber, + char *str ) { char *s; char *value, savechar; - unsigned long ftype; + ber_tag_t ftype; int rc; Debug( LDAP_DEBUG_TRACE, "put_simple_filter \"%s\"\n", str, 0, 0 ); @@ -467,6 +614,10 @@ put_simple_filter( BerElement *ber, char *str ) ftype = LDAP_FILTER_APPROX; *s = '\0'; break; + case ':': /* LDAPv3 extended filter */ + ftype = LDAP_FILTER_EXTENDED; + return -1; + break; default: if ( strchr( value, '*' ) == NULL ) { ftype = LDAP_FILTER_EQUALITY; @@ -495,12 +646,12 @@ static int put_substring_filter( BerElement *ber, char *type, char *val ) { char *nextstar, gotstar = 0; - unsigned long ftype; + ber_tag_t ftype = LDAP_FILTER_SUBSTRINGS; Debug( LDAP_DEBUG_TRACE, "put_substring_filter \"%s=%s\"\n", type, val, 0 ); - if ( ber_printf( ber, "t{s{", LDAP_FILTER_SUBSTRINGS, type ) == -1 ) + if ( ber_printf( ber, "t{s{", ftype, type ) == -1 ) return( -1 ); while ( val != NULL ) { @@ -525,14 +676,16 @@ put_substring_filter( BerElement *ber, char *type, char *val ) val = nextstar; } - if ( ber_printf( ber, "}}" ) == -1 ) + if ( ber_printf( ber, /* {{ */ "}}" ) == -1 ) return( -1 ); return( 0 ); } int -ldap_search_st( LDAP *ld, char *base, int scope, char *filter, char **attrs, +ldap_search_st( + LDAP *ld, LDAP_CONST char *base, int scope, + LDAP_CONST char *filter, char **attrs, int attrsonly, struct timeval *timeout, LDAPMessage **res ) { int msgid; @@ -554,8 +707,14 @@ ldap_search_st( LDAP *ld, char *base, int scope, char *filter, char **attrs, } int -ldap_search_s( LDAP *ld, char *base, int scope, char *filter, char **attrs, - int attrsonly, LDAPMessage **res ) +ldap_search_s( + LDAP *ld, + LDAP_CONST char *base, + int scope, + LDAP_CONST char *filter, + char **attrs, + int attrsonly, + LDAPMessage **res ) { int msgid;