X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=libraries%2Flibldap%2Fsearch.c;h=b90c1663edbe7b0c90fe454c8ade192196e82315;hb=0e3fa1ee145215f6cf63decc11a2da949be0eea0;hp=a2d97a3e01755b8ee780b5929c7ad56de38a15a9;hpb=dc0eacd40b625258355eea866d62188e5aa7ce3b;p=openldap diff --git a/libraries/libldap/search.c b/libraries/libldap/search.c index a2d97a3e01..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,13 +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 ) +{ + 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; +} +