/* $OpenLDAP$ */
-/*
- * Copyright 1998-2002 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.
+/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
+ *
+ * Copyright 1998-2007 The OpenLDAP Foundation.
+ * All rights reserved.
*
- * search.c
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted only as authorized by the OpenLDAP
+ * Public License.
+ *
+ * A copy of this license is available in the file LICENSE in the
+ * top-level directory of the distribution or, alternatively, at
+ * <http://www.OpenLDAP.org/license.html>.
+ */
+/* Portions Copyright (c) 1990 Regents of the University of Michigan.
+ * All rights reserved.
*/
#include "portable.h"
#include <ac/time.h>
#include "ldap-int.h"
-
+#include "ldap_log.h"
/*
* ldap_search_ext - initiate an ldap search operation.
*
* ld LDAP descriptor
* base DN of the base object
- * scope the search scope - one of LDAP_SCOPE_BASE,
- * LDAP_SCOPE_ONELEVEL, LDAP_SCOPE_SUBTREE
+ * scope the search scope - one of
+ * LDAP_SCOPE_BASE (baseObject),
+ * LDAP_SCOPE_ONELEVEL (oneLevel),
+ * LDAP_SCOPE_SUBTREE (subtree), or
+ * LDAP_SCOPE_SUBORDINATE (children) -- OpenLDAP extension
* filter a string containing the search filter
* (e.g., "(|(cn=bob)(sn=bob))")
* attrs list of attribute types to return for matches
int rc;
BerElement *ber;
int timelimit;
+ ber_int_t id;
Debug( LDAP_DEBUG_TRACE, "ldap_search_ext\n", 0, 0, 0 );
/*
* if timeout is provided, both tv_sec and tv_usec must
- * be non-zero
+ * not be zero
*/
if( timeout != NULL ) {
if( timeout->tv_sec == 0 && timeout->tv_usec == 0 ) {
}
ber = ldap_build_search_req( ld, base, scope, filter, attrs,
- attrsonly, sctrls, cctrls, timelimit, sizelimit );
+ attrsonly, sctrls, cctrls, timelimit, sizelimit, &id );
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 );
+ *msgidp = ldap_send_initial_request( ld, LDAP_REQ_SEARCH, base, ber, id );
if( *msgidp < 0 )
return ld->ld_errno;
return( rc );
}
- rc = ldap_result( ld, msgid, 1, timeout, res );
+ rc = ldap_result( ld, msgid, LDAP_MSG_ALL, timeout, res );
if( rc <= 0 ) {
/* error(-1) or timeout(0) */
return( ld->ld_errno );
}
- if( rc == LDAP_RES_SEARCH_REFERENCE || rc == LDAP_RES_EXTENDED_PARTIAL ) {
+ if( rc == LDAP_RES_SEARCH_REFERENCE || rc == LDAP_RES_INTERMEDIATE ) {
return( ld->ld_errno );
}
*
* ld LDAP descriptor
* base DN of the base object
- * scope the search scope - one of LDAP_SCOPE_BASE,
- * LDAP_SCOPE_ONELEVEL, LDAP_SCOPE_SUBTREE
+ * scope the search scope - one of
+ * LDAP_SCOPE_BASE (baseObject),
+ * LDAP_SCOPE_ONELEVEL (oneLevel),
+ * LDAP_SCOPE_SUBTREE (subtree), or
+ * LDAP_SCOPE_SUBORDINATE (children) -- OpenLDAP extension
* filter a string containing the search filter
* (e.g., "(|(cn=bob)(sn=bob))")
* attrs list of attribute types to return for matches
char **attrs, int attrsonly )
{
BerElement *ber;
+ ber_int_t id;
Debug( LDAP_DEBUG_TRACE, "ldap_search\n", 0, 0, 0 );
assert( LDAP_VALID( ld ) );
ber = ldap_build_search_req( ld, base, scope, filter, attrs,
- attrsonly, NULL, NULL, -1, -1 );
+ attrsonly, NULL, NULL, -1, -1, &id );
if ( ber == NULL ) {
return( -1 );
}
-#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;
- return( ld->ld_msgid );
- }
- ldap_add_request_to_cache( ld, LDAP_REQ_SEARCH, ber );
- }
-#endif /* LDAP_NOCACHE */
/* send the message */
- return ( ldap_send_initial_request( ld, LDAP_REQ_SEARCH, base, ber ));
+ return ( ldap_send_initial_request( ld, LDAP_REQ_SEARCH, base, ber, id ));
}
LDAPControl **sctrls,
LDAPControl **cctrls,
ber_int_t timelimit,
- ber_int_t sizelimit )
+ ber_int_t sizelimit,
+ ber_int_t *idp)
{
BerElement *ber;
int err;
}
}
+ LDAP_NEXT_MSGID( ld, *idp );
#ifdef LDAP_CONNECTIONLESS
if ( LDAP_IS_UDP(ld) ) {
- err = ber_write( ber, ld->ld_options.ldo_peer,
- sizeof(struct sockaddr), 0);
+ struct sockaddr sa = {0};
+ /* dummy, filled with ldo_peer in request.c */
+ err = ber_write( ber, &sa, sizeof( sa ), 0 );
}
if ( LDAP_IS_UDP(ld) && ld->ld_options.ldo_version == LDAP_VERSION2) {
char *dn = ld->ld_options.ldo_cldapdn;
if (!dn) dn = "";
- err = ber_printf( ber, "{ist{seeiib", ++ld->ld_msgid, dn,
+ err = ber_printf( ber, "{ist{seeiib", *idp, dn,
LDAP_REQ_SEARCH, base, (ber_int_t) scope, ld->ld_deref,
(sizelimit < 0) ? ld->ld_sizelimit : sizelimit,
(timelimit < 0) ? ld->ld_timelimit : timelimit,
} else
#endif
{
- err = ber_printf( ber, "{it{seeiib", ++ld->ld_msgid,
+ err = ber_printf( ber, "{it{seeiib", *idp,
LDAP_REQ_SEARCH, base, (ber_int_t) scope, ld->ld_deref,
(sizelimit < 0) ? ld->ld_sizelimit : sizelimit,
(timelimit < 0) ? ld->ld_timelimit : timelimit,
filter = "(objectclass=*)";
}
- err = ldap_int_put_filter( ber, filter );
+ err = ldap_pvt_put_filter( ber, filter );
if ( err == -1 ) {
ld->ld_errno = LDAP_FILTER_ERROR;
return( NULL );
}
+#ifdef LDAP_DEBUG
+ if ( ldap_debug & LDAP_DEBUG_ARGS ) {
+ char buf[ BUFSIZ ] = { ' ', '*', '\0' };
+
+ if ( attrs != NULL ) {
+ char *ptr;
+ int i;
+
+ for ( ptr = buf, i = 0;
+ attrs[ i ] != NULL && ptr < &buf[ sizeof( buf ) ];
+ i++ )
+ {
+ ptr += snprintf( ptr, sizeof( buf ) - ( ptr - buf ),
+ " %s", attrs[ i ] );
+ }
+
+ if ( ptr >= &buf[ sizeof( buf ) ] ) {
+ AC_MEMCPY( &buf[ sizeof( buf ) - STRLENOF( "...(truncated)" ) - 1 ],
+ "...(truncated)", STRLENOF( "...(truncated)" ) + 1 );
+ }
+ }
+
+ Debug( LDAP_DEBUG_ARGS, "ldap_build_search_req ATTRS:%s\n", buf, 0, 0 );
+ }
+#endif /* LDAP_DEBUG */
+
if ( ber_printf( ber, /*{*/ "{v}N}", attrs ) == -1 ) {
ld->ld_errno = LDAP_ENCODING_ERROR;
ber_free( ber, 1 );
== -1 )
return( ld->ld_errno );
- if ( ldap_result( ld, msgid, 1, timeout, res ) == -1 )
+ if ( ldap_result( ld, msgid, LDAP_MSG_ALL, timeout, res ) == -1 || !*res )
return( ld->ld_errno );
if ( ld->ld_errno == LDAP_TIMEOUT ) {
== -1 )
return( ld->ld_errno );
- if ( ldap_result( ld, msgid, 1, (struct timeval *) NULL, res ) == -1 )
+ if ( ldap_result( ld, msgid, LDAP_MSG_ALL, (struct timeval *) NULL, res ) == -1 || !*res )
return( ld->ld_errno );
return( ldap_result2error( ld, *res, 0 ) );
}
+static char escape[128] = {
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 1, 1, 1, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 0,
+
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 1
+};
+#define NEEDFLTESCAPE(c) ((c) & 0x80 || escape[ (unsigned)(c) ])
+
+/*
+ * compute the length of the escaped value
+ */
+ber_len_t
+ldap_bv2escaped_filter_value_len( struct berval *in )
+{
+ ber_len_t i, l;
+
+ assert( in != NULL );
+
+ if ( in->bv_len == 0 ) {
+ return 0;
+ }
+
+ for( l = 0, i = 0; i < in->bv_len; l++, i++ ) {
+ char c = in->bv_val[ i ];
+ if ( NEEDFLTESCAPE( c ) ) {
+ l += 2;
+ }
+ }
+
+ return l;
+}
+
+int
+ldap_bv2escaped_filter_value( struct berval *in, struct berval *out )
+{
+ return ldap_bv2escaped_filter_value_x( in, out, 0, NULL );
+}
+
+int
+ldap_bv2escaped_filter_value_x( struct berval *in, struct berval *out, int inplace, void *ctx )
+{
+ ber_len_t i, l;
+
+ assert( in != NULL );
+ assert( out != NULL );
+
+ BER_BVZERO( out );
+
+ if ( in->bv_len == 0 ) {
+ return 0;
+ }
+
+ /* assume we'll escape everything */
+ l = ldap_bv2escaped_filter_value_len( in );
+ if ( l == in->bv_len ) {
+ if ( inplace ) {
+ *out = *in;
+ } else {
+ ber_dupbv( out, in );
+ }
+ return 0;
+ }
+ out->bv_val = LDAP_MALLOCX( l + 1, ctx );
+ if ( out->bv_val == NULL ) {
+ return -1;
+ }
+
+ for ( i = 0; i < in->bv_len; i++ ) {
+ char c = in->bv_val[ i ];
+ if ( NEEDFLTESCAPE( c ) ) {
+ assert( out->bv_len < l - 2 );
+ out->bv_val[out->bv_len++] = '\\';
+ out->bv_val[out->bv_len++] = "0123456789ABCDEF"[0x0f & (c>>4)];
+ out->bv_val[out->bv_len++] = "0123456789ABCDEF"[0x0f & c];
+
+ } else {
+ assert( out->bv_len < l );
+ out->bv_val[out->bv_len++] = c;
+ }
+ }
+
+ out->bv_val[out->bv_len] = '\0';
+
+ return 0;
+}
+