Commit e708781b authored by Quanah Gibson-Mount's avatar Quanah Gibson-Mount
Browse files

ITS#6814

parent 43e0ae8d
......@@ -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)
......
......@@ -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 );
}
......
......@@ -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 *
......
......@@ -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,
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment