X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=libraries%2Flibldap%2Fsearch.c;h=b90c1663edbe7b0c90fe454c8ade192196e82315;hb=0e3fa1ee145215f6cf63decc11a2da949be0eea0;hp=afa63ef9aed16fb2356d2fca64ebb9cd6a7cc3b8;hpb=c655139449ccfc86c46a107c2a9caf311c4de026;p=openldap
diff --git a/libraries/libldap/search.c b/libraries/libldap/search.c
index afa63ef9ae..b90c1663ed 100644
--- a/libraries/libldap/search.c
+++ b/libraries/libldap/search.c
@@ -1,7 +1,7 @@
/* $OpenLDAP$ */
/* This work is part of OpenLDAP Software .
*
- * Copyright 1998-2005 The OpenLDAP Foundation.
+ * Copyright 1998-2012 The OpenLDAP Foundation.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -65,6 +65,25 @@ ldap_search_ext(
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;
@@ -98,7 +117,7 @@ ldap_search_ext(
}
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;
@@ -127,21 +146,47 @@ ldap_search_ext_s(
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 );
}
@@ -188,7 +233,7 @@ ldap_search(
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 );
@@ -212,6 +257,7 @@ ldap_build_search_req(
LDAPControl **cctrls,
ber_int_t timelimit,
ber_int_t sizelimit,
+ ber_int_t deref,
ber_int_t *idp)
{
BerElement *ber;
@@ -259,14 +305,16 @@ ldap_build_search_req(
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 );
@@ -274,7 +322,8 @@ ldap_build_search_req(
#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 );
@@ -298,6 +347,30 @@ ldap_build_search_req(
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 );
@@ -327,11 +400,13 @@ ldap_search_st(
{
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 ) {
@@ -355,63 +430,116 @@ ldap_search_s(
{
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 )
{
- ber_len_t i;
- static char escape[128] = {
- 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,
- 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, 0
- };
-
- out->bv_len = 0;
- out->bv_val = NULL;
-
- if( in->bv_len == 0 ) return 0;
+ 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 */
- out->bv_val = LDAP_MALLOC( 3 * in->bv_len + 1 );
- if( out->bv_val == NULL ) return -1;
+ 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; ibv_len; i++ ) {
+ for ( i = 0; i < in->bv_len; i++ ) {
char c = in->bv_val[ i ];
- if (c & 0x80 || escape[ (unsigned)c ]) {
+ 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;
}