From 6ab23ef92678e8833c5bbb769ab80183288c2f01 Mon Sep 17 00:00:00 2001 From: Pierangelo Masarati Date: Fri, 25 Nov 2005 10:41:33 +0000 Subject: [PATCH] add more versatile private API for filter escaping --- include/ldap_pvt.h | 7 ++ libraries/libldap/search.c | 115 +++++++++++++++++++++++--------- servers/slapd/overlays/unique.c | 15 +++-- 3 files changed, 100 insertions(+), 37 deletions(-) diff --git a/include/ldap_pvt.h b/include/ldap_pvt.h index 54246b402f..384f9f3f2d 100644 --- a/include/ldap_pvt.h +++ b/include/ldap_pvt.h @@ -212,6 +212,13 @@ ldap_pvt_find_wildcard LDAP_P(( const char *s )); LDAP_F( ber_slen_t ) ldap_pvt_filter_value_unescape LDAP_P(( char *filter )); +LDAP_F( ber_len_t ) +ldap_bv2escaped_filter_value_len LDAP_P(( struct berval *in )); + +LDAP_F( int ) +ldap_bv2escaped_filter_value_x LDAP_P(( struct berval *in, struct berval *out, + int inplace, void *ctx )); + /* string.c */ LDAP_F( char * ) ldap_pvt_str2upper LDAP_P(( char *str )); diff --git a/libraries/libldap/search.c b/libraries/libldap/search.c index afa63ef9ae..0d4fe706b1 100644 --- a/libraries/libldap/search.c +++ b/libraries/libldap/search.c @@ -365,53 +365,106 @@ ldap_search_s( return( ldap_result2error( ld, *res, 0 ) ); } +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 +}; +#define NEEDFLTESCAPE(c) ((c) & 0x80 || escape[ (unsigned)(c) ]) + +/* + * compute the length of the escaped value; + * returns ((ber_len_t)(-1)) if no escaping is required. + */ +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; + } + + /* assume we'll escape everything */ + 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; } diff --git a/servers/slapd/overlays/unique.c b/servers/slapd/overlays/unique.c index 7120b1f69b..38ada8877a 100644 --- a/servers/slapd/overlays/unique.c +++ b/servers/slapd/overlays/unique.c @@ -301,7 +301,8 @@ static char *build_filter( unique_data *ud, AttributeDescription *ad, BerVarray b, - char *kp + char *kp, + void *ctx ) { unique_attrs *up; @@ -332,9 +333,11 @@ static char *build_filter( for ( i = 0; b[i].bv_val; i++ ) { struct berval bv; - ldap_bv2escaped_filter_value( &b[i], &bv ); + ldap_bv2escaped_filter_value_x( &b[i], &bv, 1, ctx ); kp += sprintf( kp, "(%s=%s)", ad->ad_cname.bv_val, bv.bv_val ); - ldap_memfree( bv.bv_val ); + if ( bv.bv_val != b[i].bv_val ) { + ber_memfree_x( bv.bv_val, ctx ); + } } } else if ( ud->strict ) { kp += sprintf( kp, "(%s=*)", ad->ad_cname.bv_val ); @@ -440,7 +443,7 @@ static int unique_add( kp = key + sprintf(key, "(|"); for(a = op->ora_e->e_attrs; a; a = a->a_next) { - kp = build_filter(ud, a->a_desc, a->a_vals, kp); + kp = build_filter(ud, a->a_desc, a->a_vals, kp, op->o_tmpmemctx); } sprintf(kp, ")"); @@ -492,7 +495,7 @@ static int unique_modify( for(m = op->orm_modlist; m; m = m->sml_next) { if ((m->sml_op & LDAP_MOD_OP) == LDAP_MOD_DELETE) continue; - kp = build_filter(ud, m->sml_desc, m->sml_values, kp); + kp = build_filter(ud, m->sml_desc, m->sml_values, kp, op->o_tmpmemctx); } sprintf(kp, ")"); @@ -555,7 +558,7 @@ static int unique_modrdn( for(i = 0; newrdn[i]; i++) { bv[0] = newrdn[i]->la_value; - kp = build_filter(ud, newrdn[i]->la_private, bv, kp); + kp = build_filter(ud, newrdn[i]->la_private, bv, kp, op->o_tmpmemctx); } sprintf(kp, ")"); -- 2.39.5