/* $OpenLDAP$ */
-/*
- * Copyright 1998-2003 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-2012 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"
*
* 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
struct timeval *timeout,
int sizelimit,
int *msgidp )
+{
+ return ldap_pvt_search( ld, base, scope, filter, attrs,
+ attrsonly, sctrls, cctrls, timeout, sizelimit, -1, msgidp );
+}
+
+int
+ldap_pvt_search(
+ 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 deref,
+ int *msgidp )
{
int rc;
BerElement *ber;
int timelimit;
ber_int_t id;
-#ifdef NEW_LOGGING
- LDAP_LOG ( OPERATION, ENTRY, "ldap_search_ext\n", 0, 0, 0 );
-#else
Debug( LDAP_DEBUG_TRACE, "ldap_search_ext\n", 0, 0, 0 );
-#endif
assert( ld != NULL );
assert( LDAP_VALID( ld ) );
/*
* 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, &id );
+ attrsonly, sctrls, cctrls, timelimit, sizelimit, deref, &id );
if ( ber == NULL ) {
return ld->ld_errno;
struct timeval *timeout,
int sizelimit,
LDAPMessage **res )
+{
+ return ldap_pvt_search_s( ld, base, scope, filter, attrs,
+ attrsonly, sctrls, cctrls, timeout, sizelimit, -1, res );
+}
+
+int
+ldap_pvt_search_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,
+ int deref,
+ LDAPMessage **res )
{
int rc;
int msgid;
- rc = ldap_search_ext( ld, base, scope, filter, attrs, attrsonly,
- sctrls, cctrls, timeout, sizelimit, &msgid );
+ *res = NULL;
+
+ rc = ldap_pvt_search( ld, base, scope, filter, attrs, attrsonly,
+ sctrls, cctrls, timeout, sizelimit, deref, &msgid );
if ( rc != LDAP_SUCCESS ) {
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) */
+ if ( ld->ld_errno == LDAP_TIMEOUT ) {
+ /* cleanup request */
+ (void) ldap_abandon( ld, msgid );
+ ld->ld_errno = LDAP_TIMEOUT;
+ }
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
BerElement *ber;
ber_int_t id;
-#ifdef NEW_LOGGING
- LDAP_LOG ( OPERATION, ENTRY, "ldap_search\n", 0, 0, 0 );
-#else
Debug( LDAP_DEBUG_TRACE, "ldap_search\n", 0, 0, 0 );
-#endif
assert( ld != NULL );
assert( LDAP_VALID( ld ) );
ber = ldap_build_search_req( ld, base, scope, filter, attrs,
- attrsonly, NULL, NULL, -1, -1, &id );
+ attrsonly, NULL, NULL, -1, -1, -1, &id );
if ( ber == NULL ) {
return( -1 );
LDAPControl **cctrls,
ber_int_t timelimit,
ber_int_t sizelimit,
+ ber_int_t deref,
ber_int_t *idp)
{
BerElement *ber;
- int err, id;
+ int err;
/*
* Create the search request. It looks like this:
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, (char *) &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", *idp, dn,
- LDAP_REQ_SEARCH, base, (ber_int_t) scope, ld->ld_deref,
+ LDAP_REQ_SEARCH, base, (ber_int_t) scope,
+ (deref < 0) ? ld->ld_deref : deref,
(sizelimit < 0) ? ld->ld_sizelimit : sizelimit,
(timelimit < 0) ? ld->ld_timelimit : timelimit,
attrsonly );
#endif
{
err = ber_printf( ber, "{it{seeiib", *idp,
- LDAP_REQ_SEARCH, base, (ber_int_t) scope, ld->ld_deref,
+ LDAP_REQ_SEARCH, base, (ber_int_t) scope,
+ (deref < 0) ? ld->ld_deref : deref,
(sizelimit < 0) ? ld->ld_sizelimit : sizelimit,
(timelimit < 0) ? ld->ld_timelimit : timelimit,
attrsonly );
return( NULL );
}
+#ifdef LDAP_DEBUG
+ if ( ldap_debug & LDAP_DEBUG_ARGS ) {
+ char buf[ BUFSIZ ], *ptr = " *";
+
+ if ( attrs != NULL ) {
+ int i, len, rest = sizeof( buf );
+
+ for ( i = 0; attrs[ i ] != NULL && rest > 0; i++ ) {
+ ptr = &buf[ sizeof( buf ) - rest ];
+ len = snprintf( ptr, rest, " %s", attrs[ i ] );
+ rest -= (len >= 0 ? len : (int) sizeof( buf ));
+ }
+
+ if ( rest <= 0 ) {
+ AC_MEMCPY( &buf[ sizeof( buf ) - STRLENOF( "...(truncated)" ) - 1 ],
+ "...(truncated)", STRLENOF( "...(truncated)" ) + 1 );
+ }
+ ptr = buf;
+ }
+
+ Debug( LDAP_DEBUG_ARGS, "ldap_build_search_req ATTRS:%s\n", ptr, 0,0 );
+ }
+#endif /* LDAP_DEBUG */
+
if ( ber_printf( ber, /*{*/ "{v}N}", attrs ) == -1 ) {
ld->ld_errno = LDAP_ENCODING_ERROR;
ber_free( ber, 1 );
{
int msgid;
+ *res = NULL;
+
if ( (msgid = ldap_search( ld, base, scope, filter, attrs, attrsonly ))
== -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 ) {
{
int msgid;
+ *res = NULL;
+
if ( (msgid = ldap_search( ld, base, scope, filter, attrs, attrsonly ))
== -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;
+}
+