From e708781bbdf6d588772e056b59ef566b31f5af1d Mon Sep 17 00:00:00 2001 From: Quanah Gibson-Mount <quanah@openldap.org> Date: Mon, 31 Jan 2011 20:46:54 +0000 Subject: [PATCH] ITS#6814 --- CHANGES | 1 + servers/slapd/back-ldap/search.c | 108 +++++++++++++++---------------- servers/slapd/filter.c | 44 +++++++++---- servers/slapd/proto-slap.h | 3 +- 4 files changed, 84 insertions(+), 72 deletions(-) diff --git a/CHANGES b/CHANGES index 7e3165f58e..b33b930244 100644 --- a/CHANGES +++ b/CHANGES @@ -78,6 +78,7 @@ OpenLDAP 2.4.24 Engineering Fixed slapd-ldap chaining with ppolicy (ITS#6540) Fixed slapd-ldap with SASL/EXTERNAL (ITS#6642) Fixed slapd-ldap crasher on matchedDN (ITS#6793) + Fixed slapd-ldap with unknown objectClasses (ITS#6814) Fixed slapd-ldif error strings (ITS#6731) Fixed slapd-ndb to honor rootpw setting (ITS#6661) Fixed slapd-ndb hasSubordinates generation (ITS#6712) diff --git a/servers/slapd/back-ldap/search.c b/servers/slapd/back-ldap/search.c index 0b569fe2f1..1d213b9276 100644 --- a/servers/slapd/back-ldap/search.c +++ b/servers/slapd/back-ldap/search.c @@ -40,77 +40,57 @@ ldap_build_entry( Operation *op, LDAPMessage *e, Entry *ent, struct berval *bdn ); /* - * Quick'n'dirty rewrite of filter in case of error, to deal with - * <draft-zeilenga-ldap-t-f>. + * replaces (&) with (objectClass=*) and (|) with (!(objectClass=*)) + * as the best replacement for RFC 4526 absolute true/absolute false + * filters; the only difference (AFAIK) is that they require search + * access to objectClass. + * + * filter->bv_val may be alloc'd on the thread's slab, if equal to + * op->ors_filterstr.bv_val, or realloc'd on the thread's slab otherwise. */ static int ldap_back_munge_filter( Operation *op, - struct berval *filter, - int *freeit ) + struct berval *filter ) { - ldapinfo_t *li = (ldapinfo_t *) op->o_bd->be_private; - - char *ptr; - int gotit = 0; + char *ptr; + int gotit = 0; Debug( LDAP_DEBUG_ARGS, "=> ldap_back_munge_filter \"%s\"\n", filter->bv_val, 0, 0 ); - for ( ptr = strstr( filter->bv_val, "(?=" ); + for ( ptr = strchr( filter->bv_val, '(' ); ptr; - ptr = strstr( ptr, "(?=" ) ) + ptr = strchr( ptr, '(' ) ) { static struct berval - bv_true = BER_BVC( "(?=true)" ), - bv_false = BER_BVC( "(?=false)" ), - bv_undefined = BER_BVC( "(?=undefined)" ), bv_t = BER_BVC( "(&)" ), bv_f = BER_BVC( "(|)" ), bv_T = BER_BVC( "(objectClass=*)" ), bv_F = BER_BVC( "(!(objectClass=*))" ); - struct berval *oldbv = NULL, - *newbv = NULL, - oldfilter = BER_BVNULL; - - if ( strncmp( ptr, bv_true.bv_val, bv_true.bv_len ) == 0 ) { - oldbv = &bv_true; - if ( LDAP_BACK_T_F( li ) ) { - newbv = &bv_t; - - } else { - newbv = &bv_T; - } + struct berval *oldbv = NULL, + *newbv = NULL, + oldfilter = BER_BVNULL; - } else if ( strncmp( ptr, bv_false.bv_val, bv_false.bv_len ) == 0 ) - { - oldbv = &bv_false; - if ( LDAP_BACK_T_F( li ) ) { - newbv = &bv_f; - - } else { - newbv = &bv_F; - } + if ( ptr[2] != ')' ) { + ptr++; + continue; + } - } else if ( strncmp( ptr, bv_undefined.bv_val, bv_undefined.bv_len ) == 0 ) - { - /* if undef or invalid filter is not allowed, - * don't rewrite filter */ - if ( LDAP_BACK_NOUNDEFFILTER( li ) ) { - if ( filter->bv_val != op->ors_filterstr.bv_val ) { - op->o_tmpfree( filter->bv_val, op->o_tmpmemctx ); - } - BER_BVZERO( filter ); - gotit = -1; - goto done; - } + switch ( ptr[1] ) { + case '&': + oldbv = &bv_t; + newbv = &bv_T; + break; - oldbv = &bv_undefined; + case '|': + oldbv = &bv_f; newbv = &bv_F; + break; - } else { - gotit = 0; - goto done; + default: + /* should be an error */ + continue; } oldfilter = *filter; @@ -120,9 +100,8 @@ ldap_back_munge_filter( op->o_tmpmemctx ); AC_MEMCPY( filter->bv_val, op->ors_filterstr.bv_val, - op->ors_filterstr.bv_len + 1 ); + ptr - oldfilter.bv_val ); - *freeit = 1; } else { filter->bv_val = op->o_tmprealloc( filter->bv_val, filter->bv_len + 1, op->o_tmpmemctx ); @@ -136,10 +115,10 @@ ldap_back_munge_filter( AC_MEMCPY( ptr, newbv->bv_val, newbv->bv_len ); ptr += newbv->bv_len; - gotit = 1; + + gotit++; } -done:; Debug( LDAP_DEBUG_ARGS, "<= ldap_back_munge_filter \"%s\" (%d)\n", filter->bv_val, gotit, 0 ); @@ -164,7 +143,7 @@ ldap_back_search( filter = BER_BVNULL; int i; char **attrs = NULL; - int freetext = 0, freefilter = 0; + int freetext = 0, filter_undef = 0; int do_retry = 1, dont_retry = 0; LDAPControl **ctrls = NULL; char **references = NULL; @@ -218,6 +197,14 @@ ldap_back_search( /* deal with <draft-zeilenga-ldap-t-f> filters */ filter = op->ors_filterstr; retry: + /* this goes after retry because ldap_back_munge_filter() + * optionally replaces RFC 4526 T-F filters (&) (|) + * if already computed, they will be re-installed + * by filter2bv_undef_x() later */ + if ( !LDAP_BACK_T_F( li ) ) { + ldap_back_munge_filter( op, &filter ); + } + rs->sr_err = ldap_pvt_search( lc->lc_ld, op->o_req_dn.bv_val, op->ors_scope, filter.bv_val, attrs, op->ors_attrsonly, ctrls, NULL, @@ -245,7 +232,14 @@ retry: goto finish; case LDAP_FILTER_ERROR: - if (ldap_back_munge_filter( op, &filter, &freefilter ) > 0 ) { + /* first try? */ + if ( !filter_undef && + strstr( filter.bv_val, "(?" ) && + !LDAP_BACK_NOUNDEFFILTER( li ) ) + { + BER_BVZERO( &filter ); + filter2bv_undef_x( op, op->ors_filter, 1, &filter ); + filter_undef = 1; goto retry; } @@ -566,7 +560,7 @@ finish:; ldap_back_quarantine( op, rs ); } - if ( freefilter && filter.bv_val != op->ors_filterstr.bv_val ) { + if ( filter.bv_val != op->ors_filterstr.bv_val ) { op->o_tmpfree( filter.bv_val, op->o_tmpmemctx ); } diff --git a/servers/slapd/filter.c b/servers/slapd/filter.c index 246b4ac6b1..372f414d80 100644 --- a/servers/slapd/filter.c +++ b/servers/slapd/filter.c @@ -585,6 +585,12 @@ filter_free( Filter *f ) void filter2bv_x( Operation *op, Filter *f, struct berval *fstr ) +{ + return filter2bv_undef_x( op, f, 0, fstr ); +} + +void +filter2bv_undef_x( Operation *op, Filter *f, int noundef, struct berval *fstr ) { int i; Filter *p; @@ -595,10 +601,12 @@ filter2bv_x( Operation *op, Filter *f, struct berval *fstr ) ber_bvundefined = BER_BVC( "(?=undefined)" ), ber_bverror = BER_BVC( "(?=error)" ), ber_bvunknown = BER_BVC( "(?=unknown)" ), - ber_bvnone = BER_BVC( "(?=none)" ); + ber_bvnone = BER_BVC( "(?=none)" ), + ber_bvF = BER_BVC( "(|)" ), + ber_bvT = BER_BVC( "(&)" ); ber_len_t len; ber_tag_t choice; - int undef; + int undef, undef2; char *sign; if ( f == NULL ) { @@ -607,6 +615,7 @@ filter2bv_x( Operation *op, Filter *f, struct berval *fstr ) } undef = f->f_choice & SLAPD_FILTER_UNDEFINED; + undef2 = (undef && !noundef); choice = f->f_choice & SLAPD_FILTER_MASK; switch ( choice ) { @@ -644,12 +653,12 @@ simple: * is legal for that attribute's syntax */ fstr->bv_len += f->f_av_desc->ad_cname.bv_len + tmp.bv_len; - if ( undef ) + if ( undef2 ) fstr->bv_len++; fstr->bv_val = op->o_tmpalloc( fstr->bv_len + 1, op->o_tmpmemctx ); snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s%s%s%s)", - undef ? "?" : "", + undef2 ? "?" : "", f->f_av_desc->ad_cname.bv_val, sign, tmp.bv_len ? tmp.bv_val : "" ); @@ -663,12 +672,12 @@ simple: case LDAP_FILTER_SUBSTRINGS: fstr->bv_len = f->f_sub_desc->ad_cname.bv_len + STRLENOF("(=*)"); - if ( undef ) + if ( undef2 ) fstr->bv_len++; fstr->bv_val = op->o_tmpalloc( fstr->bv_len + 128, op->o_tmpmemctx ); snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s%s=*)", - undef ? "?" : "", + undef2 ? "?" : "", f->f_sub_desc->ad_cname.bv_val ); if ( f->f_sub_initial.bv_val != NULL ) { @@ -737,13 +746,13 @@ simple: case LDAP_FILTER_PRESENT: fstr->bv_len = f->f_desc->ad_cname.bv_len + STRLENOF("(=*)"); - if ( undef ) + if ( undef2 ) fstr->bv_len++; fstr->bv_val = op->o_tmpalloc( fstr->bv_len + 1, op->o_tmpmemctx ); snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s%s=*)", - undef ? "?" : "", + undef2 ? "?" : "", f->f_desc->ad_cname.bv_val ); break; @@ -760,7 +769,7 @@ simple: for ( p = f->f_list; p != NULL; p = p->f_next ) { len = fstr->bv_len; - filter2bv_x( op, p, &tmp ); + filter2bv_undef_x( op, p, noundef, &tmp ); fstr->bv_len += tmp.bv_len; fstr->bv_val = op->o_tmprealloc( fstr->bv_val, fstr->bv_len + 1, @@ -792,13 +801,14 @@ simple: } fstr->bv_len = ad.bv_len + + ( undef2 ? 1 : 0 ) + ( f->f_mr_dnattrs ? STRLENOF(":dn") : 0 ) + - ( f->f_mr_rule_text.bv_len ? f->f_mr_rule_text.bv_len+1 : 0 ) + + ( f->f_mr_rule_text.bv_len ? f->f_mr_rule_text.bv_len + STRLENOF(":") : 0 ) + tmp.bv_len + STRLENOF("(:=)"); fstr->bv_val = op->o_tmpalloc( fstr->bv_len + 1, op->o_tmpmemctx ); snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s%s%s%s%s:=%s)", - undef ? "?" : "", + undef2 ? "?" : "", ad.bv_val, f->f_mr_dnattrs ? ":dn" : "", f->f_mr_rule_text.bv_len ? ":" : "", @@ -810,11 +820,11 @@ simple: case SLAPD_FILTER_COMPUTED: switch ( f->f_result ) { case LDAP_COMPARE_FALSE: - tmp = ber_bvfalse; + tmp = ( noundef ? ber_bvF : ber_bvfalse ); break; case LDAP_COMPARE_TRUE: - tmp = ber_bvtrue; + tmp = ( noundef ? ber_bvT : ber_bvtrue ); break; case SLAPD_COMPARE_UNDEFINED: @@ -837,6 +847,12 @@ simple: void filter2bv( Filter *f, struct berval *fstr ) +{ + return filter2bv_undef( f, 0, fstr ); +} + +void +filter2bv_undef( Filter *f, int noundef, struct berval *fstr ) { Operation op; Opheader ohdr; @@ -845,7 +861,7 @@ filter2bv( Filter *f, struct berval *fstr ) op.o_tmpmemctx = NULL; op.o_tmpmfuncs = &ch_mfuncs; - filter2bv_x( &op, f, fstr ); + filter2bv_undef_x( &op, f, noundef, fstr ); } Filter * diff --git a/servers/slapd/proto-slap.h b/servers/slapd/proto-slap.h index 6c06130627..c8331a0e10 100644 --- a/servers/slapd/proto-slap.h +++ b/servers/slapd/proto-slap.h @@ -1078,7 +1078,8 @@ LDAP_SLAPD_F (int) get_filter LDAP_P(( LDAP_SLAPD_F (void) filter_free LDAP_P(( Filter *f )); LDAP_SLAPD_F (void) filter_free_x LDAP_P(( Operation *op, Filter *f, int freeme )); LDAP_SLAPD_F (void) filter2bv LDAP_P(( Filter *f, struct berval *bv )); -LDAP_SLAPD_F (void) filter2bv_x LDAP_P(( Operation *op, Filter *f, struct berval *bv )); +LDAP_SLAPD_F (void) filter2bv_undef LDAP_P(( Filter *f, int noundef, struct berval *bv )); +LDAP_SLAPD_F (void) filter2bv_undef_x LDAP_P(( Operation *op, Filter *f, int noundef, struct berval *bv )); LDAP_SLAPD_F (Filter *) filter_dup LDAP_P(( Filter *f, void *memctx )); LDAP_SLAPD_F (int) get_vrFilter LDAP_P(( Operation *op, BerElement *ber, -- GitLab