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