From 7b3f889ec16ea8d29b50221f21917864a7779b3c Mon Sep 17 00:00:00 2001 From: Pierangelo Masarati Date: Sat, 26 Oct 2002 16:18:31 +0000 Subject: [PATCH] fix hasSubordinate filtering; now it can be safely turned on --- servers/slapd/back-bdb/external.h | 4 ++ servers/slapd/back-bdb/init.c | 3 ++ servers/slapd/back-bdb/lcup.c | 53 ------------------------ servers/slapd/back-bdb/operational.c | 7 +++- servers/slapd/back-bdb/search.c | 55 ------------------------- servers/slapd/back-ldbm/external.h | 4 ++ servers/slapd/back-ldbm/init.c | 3 ++ servers/slapd/back-ldbm/operational.c | 23 ++++++++++- servers/slapd/back-ldbm/search.c | 49 ---------------------- servers/slapd/back-sql/search.c | 3 +- servers/slapd/filterentry.c | 59 ++++++++++++++++++++++++++- servers/slapd/proto-slap.h | 2 + servers/slapd/slap.h | 12 ++++++ 13 files changed, 114 insertions(+), 163 deletions(-) diff --git a/servers/slapd/back-bdb/external.h b/servers/slapd/back-bdb/external.h index f7c285a808..9e595ef9ff 100644 --- a/servers/slapd/back-bdb/external.h +++ b/servers/slapd/back-bdb/external.h @@ -33,6 +33,10 @@ extern BI_chk_referrals bdb_referrals; extern BI_operational bdb_operational; +#ifdef SLAP_X_FILTER_HASSUBORDINATES +extern BI_has_subordinates bdb_hasSubordinates; +#endif /* SLAP_X_FILTER_HASSUBORDINATES */ + /* tools.c */ extern BI_tool_entry_open bdb_tool_entry_open; extern BI_tool_entry_close bdb_tool_entry_close; diff --git a/servers/slapd/back-bdb/init.c b/servers/slapd/back-bdb/init.c index 0e3cab45de..aa956d2b1e 100644 --- a/servers/slapd/back-bdb/init.c +++ b/servers/slapd/back-bdb/init.c @@ -615,6 +615,9 @@ bdb_initialize( bi->bi_chk_referrals = bdb_referrals; bi->bi_operational = bdb_operational; +#ifdef SLAP_X_FILTER_HASSUBORDINATES + bi->bi_has_subordinates = bdb_hasSubordinates; +#endif /* SLAP_X_FILTER_HASSUBORDINATES */ bi->bi_entry_release_rw = bdb_entry_release; /* diff --git a/servers/slapd/back-bdb/lcup.c b/servers/slapd/back-bdb/lcup.c index 9cf1a1479e..633d8111af 100644 --- a/servers/slapd/back-bdb/lcup.c +++ b/servers/slapd/back-bdb/lcup.c @@ -110,11 +110,6 @@ bdb_psearch( int isroot = 0; int scopeok = 0; -#ifdef SLAP_X_FILTER_HASSUBORDINATES - int filter_hasSubordinates = 0; - Attribute *hasSubordinates = NULL; -#endif /* SLAP_X_FILTER_HASSUBORDINATES */ - u_int32_t locker; DB_LOCK lock; @@ -386,14 +381,6 @@ dn2entry_retry: } } -#ifdef SLAP_X_FILTER_HASSUBORDINATES - /* - * is hasSubordinates used in the filter ? - * FIXME: we may compute this directly when parsing the filter - */ - filter_hasSubordinates = filter_has_subordinates( filter ); -#endif /* SLAP_X_FILTER_HASSUBORDINATES */ - lcupf.f_choice = LDAP_FILTER_AND; lcupf.f_and = &csnfnot; lcupf.f_next = NULL; @@ -568,52 +555,12 @@ dn2entry_retry: goto test_done; } -#ifdef SLAP_X_FILTER_HASSUBORDINATES - /* - * if hasSubordinates is used in the filter, - * append it to the entry's attributes - */ - if ( filter_hasSubordinates ) { - int hs; - - rc = bdb_hasSubordinates( be, ps_conn, ps_op, e, &hs); - if ( rc != LDAP_SUCCESS ) { - goto test_done; - } - - hasSubordinates = slap_operational_hasSubordinate( - hs == LDAP_COMPARE_TRUE ); - - if ( hasSubordinates == NULL ) { - goto test_done; - } - - hasSubordinates->a_next = e->e_attrs; - e->e_attrs = hasSubordinates; - } -#endif /* SLAP_X_FILTER_HASSUBORDINATES */ - if ( psearch_type != LCUP_PSEARCH_BY_SCOPEOUT ) { rc = test_filter( be, ps_conn, ps_op, e, &lcupf ); } else { rc = LDAP_COMPARE_TRUE; } -#ifdef SLAP_X_FILTER_HASSUBORDINATES - if ( hasSubordinates ) { - /* - * FIXME: this is fairly inefficient, because - * if hasSubordinates is among the required - * attrs, it will be added again later; - * maybe we should leave it and check - * check later if it's already present, - * if required - */ - e->e_attrs = e->e_attrs->a_next; - attr_free( hasSubordinates ); - } -#endif /* SLAP_X_FILTER_HASSUBORDINATES */ - if ( rc == LDAP_COMPARE_TRUE ) { struct berval dn; diff --git a/servers/slapd/back-bdb/operational.c b/servers/slapd/back-bdb/operational.c index 1c5d4b14d6..7cead61e7c 100644 --- a/servers/slapd/back-bdb/operational.c +++ b/servers/slapd/back-bdb/operational.c @@ -16,9 +16,9 @@ #include "proto-bdb.h" /* - * sets the supported operational attributes (if required) + * sets *hasSubordinates to LDAP_COMPARE_TRUE/LDAP_COMPARE_FALSE + * if the entry has children or not. */ - int bdb_hasSubordinates( BackendDB *be, @@ -124,6 +124,9 @@ return_results: return rc; } +/* + * sets the supported operational attributes (if required) + */ int bdb_operational( BackendDB *be, diff --git a/servers/slapd/back-bdb/search.c b/servers/slapd/back-bdb/search.c index 03a0a540bc..5d2bdcec14 100644 --- a/servers/slapd/back-bdb/search.c +++ b/servers/slapd/back-bdb/search.c @@ -67,10 +67,6 @@ bdb_search( struct slap_limits_set *limit = NULL; int isroot = 0; -#ifdef SLAP_X_FILTER_HASSUBORDINATES - int filter_hasSubordinates = 0; -#endif /* SLAP_X_FILTER_HASSUBORDINATES */ - u_int32_t locker; DB_LOCK lock; @@ -342,14 +338,6 @@ dn2entry_retry: } } -#ifdef SLAP_X_FILTER_HASSUBORDINATES - /* - * is hasSubordinates used in the filter ? - * FIXME: we may compute this directly when parsing the filter - */ - filter_hasSubordinates = filter_has_subordinates( filter ); -#endif /* SLAP_X_FILTER_HASSUBORDINATES */ - #ifdef LDAP_CLIENT_UPDATE if ( op->o_clientupdate_type & SLAP_LCUP_SYNC ) { lcupf.f_choice = LDAP_FILTER_AND; @@ -382,9 +370,6 @@ dn2entry_retry: id = bdb_idl_next( candidates, &cursor ) ) { int scopeok = 0; -#ifdef SLAP_X_FILTER_HASSUBORDINATES - Attribute *hasSubordinates = NULL; -#endif /* SLAP_X_FILTER_HASSUBORDINATES */ /* check for abandon */ if ( op->o_abandon ) { @@ -548,31 +533,6 @@ id2entry_retry: goto loop_continue; } -#ifdef SLAP_X_FILTER_HASSUBORDINATES - /* - * if hasSubordinates is used in the filter, - * append it to the entry's attributes - */ - if ( filter_hasSubordinates ) { - int hs; - - rc = bdb_hasSubordinates( be, conn, op, e, &hs); - if ( rc != LDAP_SUCCESS ) { - goto loop_continue; - } - - hasSubordinates = slap_operational_hasSubordinate( - hs == LDAP_COMPARE_TRUE ); - - if ( hasSubordinates == NULL ) { - goto loop_continue; - } - - hasSubordinates->a_next = e->e_attrs; - e->e_attrs = hasSubordinates; - } -#endif /* SLAP_X_FILTER_HASSUBORDINATES */ - /* if it matches the filter and scope, send it */ #ifdef LDAP_CLIENT_UPDATE if ( op->o_clientupdate_type & SLAP_LCUP_SYNC ) { @@ -583,21 +543,6 @@ id2entry_retry: rc = test_filter( be, conn, op, e, filter ); } -#ifdef SLAP_X_FILTER_HASSUBORDINATES - if ( hasSubordinates ) { - /* - * FIXME: this is fairly inefficient, because - * if hasSubordinates is among the required - * attrs, it will be added again later; - * maybe we should leave it and check - * check later if it's already present, - * if required - */ - e->e_attrs = e->e_attrs->a_next; - attr_free( hasSubordinates ); - } -#endif /* SLAP_X_FILTER_HASSUBORDINATES */ - if ( rc == LDAP_COMPARE_TRUE ) { struct berval dn; diff --git a/servers/slapd/back-ldbm/external.h b/servers/slapd/back-ldbm/external.h index 7c3faad166..93b40b1dd4 100644 --- a/servers/slapd/back-ldbm/external.h +++ b/servers/slapd/back-ldbm/external.h @@ -43,6 +43,10 @@ extern BI_acl_attribute ldbm_back_attribute; extern BI_operational ldbm_back_operational; +#ifdef SLAP_X_FILTER_HASSUBORDINATES +extern BI_has_subordinates ldbm_back_hasSubordinates; +#endif /* SLAP_X_FILTER_HASSUBORDINATES */ + /* hooks for slap tools */ extern BI_tool_entry_open ldbm_tool_entry_open; extern BI_tool_entry_close ldbm_tool_entry_close; diff --git a/servers/slapd/back-ldbm/init.c b/servers/slapd/back-ldbm/init.c index be55fac73c..327b0b79a9 100644 --- a/servers/slapd/back-ldbm/init.c +++ b/servers/slapd/back-ldbm/init.c @@ -71,6 +71,9 @@ ldbm_back_initialize( bi->bi_acl_attribute = ldbm_back_attribute; bi->bi_chk_referrals = ldbm_back_referrals; bi->bi_operational = ldbm_back_operational; +#ifdef SLAP_X_FILTER_HASSUBORDINATES + bi->bi_has_subordinates = ldbm_back_hasSubordinates; +#endif /* SLAP_X_FILTER_HASSUBORDINATES */ /* * hooks for slap tools diff --git a/servers/slapd/back-ldbm/operational.c b/servers/slapd/back-ldbm/operational.c index 51c0fb710f..bc68116c28 100644 --- a/servers/slapd/back-ldbm/operational.c +++ b/servers/slapd/back-ldbm/operational.c @@ -16,9 +16,30 @@ #include "proto-back-ldbm.h" /* - * sets the supported operational attributes (if required) + * sets *hasSubordinates to LDAP_COMPARE_TRUE/LDAP_COMPARE_FALSE + * if the entry has children or not. */ +int +ldbm_back_hasSubordinates( + BackendDB *be, + Connection *conn, + Operation *op, + Entry *e, + int *hasSubordinates ) +{ + if ( has_children( be, e ) ) { + *hasSubordinates = LDAP_COMPARE_TRUE; + } else { + *hasSubordinates = LDAP_COMPARE_FALSE; + } + + return 0; +} + +/* + * sets the supported operational attributes (if required) + */ int ldbm_back_operational( BackendDB *be, diff --git a/servers/slapd/back-ldbm/search.c b/servers/slapd/back-ldbm/search.c index eac5f831e9..1d41140078 100644 --- a/servers/slapd/back-ldbm/search.c +++ b/servers/slapd/back-ldbm/search.c @@ -57,10 +57,6 @@ ldbm_back_search( struct slap_limits_set *limit = NULL; int isroot = 0; -#ifdef SLAP_X_FILTER_HASSUBORDINATES - int filter_hasSubordinates = 0; -#endif /* SLAP_X_FILTER_HASSUBORDINATES */ - #ifdef NEW_LOGGING LDAP_LOG( BACK_LDBM, ENTRY, "ldbm_back_search: enter\n", 0, 0, 0 ); #else @@ -292,22 +288,11 @@ searchit: /* compute it anyway; root does not use it */ stoptime = op->o_time + tlimit; -#ifdef SLAP_X_FILTER_HASSUBORDINATES - /* - * is hasSubordinates used in the filter ? - * FIXME: we may compute this directly when parsing the filter - */ - filter_hasSubordinates = filter_has_subordinates( filter ); -#endif /* SLAP_X_FILTER_HASSUBORDINATES */ - for ( id = idl_firstid( candidates, &cursor ); id != NOID; id = idl_nextid( candidates, &cursor ) ) { int scopeok = 0; int result = 0; -#ifdef SLAP_X_FILTER_HASSUBORDINATES - Attribute *hasSubordinates = NULL; -#endif /* SLAP_X_FILTER_HASSUBORDINATES */ /* check for abandon */ if ( op->o_abandon ) { @@ -436,43 +421,9 @@ searchit: goto loop_continue; } -#ifdef SLAP_X_FILTER_HASSUBORDINATES - /* - * if hasSubordinates is used in the filter, - * append it to the entry's attributes - */ - if ( filter_hasSubordinates ) { - int hs; - - hs = has_children( be, e ); - hasSubordinates = slap_operational_hasSubordinate( hs ); - if ( hasSubordinates == NULL ) { - goto loop_continue; - } - - hasSubordinates->a_next = e->e_attrs; - e->e_attrs = hasSubordinates; - } -#endif /* SLAP_X_FILTER_HASSUBORDINATES */ - /* if it matches the filter and scope, send it */ result = test_filter( be, conn, op, e, filter ); -#ifdef SLAP_X_FILTER_HASSUBORDINATES - if ( hasSubordinates ) { - /* - * FIXME: this is fairly inefficient, because - * if hasSubordinates is among the required - * attrs, it will be added again later; - * maybe we should leave it and check - * check later if it's already present, - * if required - */ - e->e_attrs = e->e_attrs->a_next; - attr_free( hasSubordinates ); - } -#endif /* SLAP_X_FILTER_HASSUBORDINATES */ - if ( result == LDAP_COMPARE_TRUE ) { struct berval dn; diff --git a/servers/slapd/back-sql/search.c b/servers/slapd/back-sql/search.c index 0032f2ffdf..77428ea18c 100644 --- a/servers/slapd/back-sql/search.c +++ b/servers/slapd/back-sql/search.c @@ -399,7 +399,7 @@ backsql_process_filter( backsql_srch_info *bsi, Filter *f ) */ backsql_strfcat( &bsi->flt_where, &bsi->fwhere_len, "l", (ber_len_t)sizeof( "1=1" ) - 1, "1=1" ); - if ( ad != NULL ) { + if ( ad == slap_schema.si_ad_hasSubordinates ) { /* * We use this flag since we need to parse * the filter anyway; we should have used @@ -407,6 +407,7 @@ backsql_process_filter( backsql_srch_info *bsi, Filter *f ) * filter_has_subordinates() */ bsi->bsi_flags |= BSQL_SF_FILTER_HASSUBORDINATE; + } else { /* * clear attributes to fetch, to require ALL diff --git a/servers/slapd/filterentry.c b/servers/slapd/filterentry.c index 82cd8cd327..eee672a9b9 100644 --- a/servers/slapd/filterentry.c +++ b/servers/slapd/filterentry.c @@ -460,6 +460,41 @@ test_ava_filter( } } +#ifdef SLAP_X_FILTER_HASSUBORDINATES + if ( ava->aa_desc == slap_schema.si_ad_hasSubordinates + && be && be->be_has_subordinates ) { + int hasSubordinates; + struct berval hs; + + /* + * No other match should be allowed ... + */ + assert( type == LDAP_FILTER_EQUALITY ); + + if ( (*be->be_has_subordinates)( be, conn, op, e, &hasSubordinates ) ) { + return LDAP_OTHER; + } + + if ( hasSubordinates == LDAP_COMPARE_TRUE ) { + hs.bv_val = "TRUE"; + hs.bv_len = sizeof( "TRUE" ) - 1; + + } else if ( hasSubordinates == LDAP_COMPARE_FALSE ) { + hs.bv_val = "FALSE"; + hs.bv_len = sizeof( "FALSE" ) - 1; + + } else { + return LDAP_OTHER; + } + + if ( bvmatch( &ava->aa_value, &hs ) ) { + return LDAP_COMPARE_TRUE; + } + + return LDAP_COMPARE_FALSE; + } +#endif /* SLAP_X_FILTER_HASSUBORDINATES */ + return( LDAP_COMPARE_FALSE ); } @@ -473,13 +508,33 @@ test_presence_filter( AttributeDescription *desc ) { + Attribute *a; + if ( !access_allowed( be, conn, op, e, desc, NULL, ACL_SEARCH, NULL ) ) { return LDAP_INSUFFICIENT_ACCESS; } - return attrs_find( e->e_attrs, desc ) != NULL - ? LDAP_COMPARE_TRUE : LDAP_COMPARE_FALSE; + a = attrs_find( e->e_attrs, desc ); + +#ifdef SLAP_X_FILTER_HASSUBORDINATES + if ( a == NULL && desc == slap_schema.si_ad_hasSubordinates ) { + + /* + * XXX: fairly optimistic: if the function is defined, + * then PRESENCE must succeed, because hasSubordinate + * is boolean-valued; I think we may live with this + * simplification by now + */ + if ( be && be->be_has_subordinates ) { + return LDAP_COMPARE_TRUE; + } + + return LDAP_COMPARE_FALSE; + } +#endif /* SLAP_X_FILTER_HASSUBORDINATES */ + + return a != NULL ? LDAP_COMPARE_TRUE : LDAP_COMPARE_FALSE; } diff --git a/servers/slapd/proto-slap.h b/servers/slapd/proto-slap.h index 51dec17aea..3d2bd8065f 100644 --- a/servers/slapd/proto-slap.h +++ b/servers/slapd/proto-slap.h @@ -485,6 +485,8 @@ LDAP_SLAPD_F (void) vrFilter2bv LDAP_P(( ValuesReturnFilter *f, struct berval *f /* * define to honor hasSubordinates operational attribute in search filters + * (in previous use there was a flaw with back-bdb and back-ldbm; now it + * is fixed). */ #undef SLAP_X_FILTER_HASSUBORDINATES diff --git a/servers/slapd/slap.h b/servers/slapd/slap.h index bb611b8fc8..e3cb7d55e6 100644 --- a/servers/slapd/slap.h +++ b/servers/slapd/slap.h @@ -1206,6 +1206,9 @@ struct slap_backend_db { #define be_group bd_info->bi_acl_group #define be_attribute bd_info->bi_acl_attribute #define be_operational bd_info->bi_operational +#ifdef SLAP_X_FILTER_HASSUBORDINATES +#define be_has_subordinates bd_info->bi_has_subordinates +#endif /* SLAP_X_FILTER_HASSUBORDINATES */ #define be_controls bd_info->bi_controls @@ -1406,6 +1409,12 @@ typedef int (BI_operational) LDAP_P((Backend *bd, struct slap_conn *c, struct slap_op *o, Entry *e, AttributeName *attrs, int opattrs, Attribute **a )); +#ifdef SLAP_X_FILTER_HASSUBORDINATES +typedef int (BI_has_subordinates) LDAP_P((Backend *bd, + struct slap_conn *c, struct slap_op *o, + Entry *e, int *has_subordinates )); +#endif /* SLAP_X_FILTER_HASSUBORDINATES */ + typedef int (BI_connection_init) LDAP_P((BackendDB *bd, struct slap_conn *c)); typedef int (BI_connection_destroy) LDAP_P((BackendDB *bd, @@ -1499,6 +1508,9 @@ struct slap_backend_info { BI_acl_attribute *bi_acl_attribute; BI_operational *bi_operational; +#ifdef SLAP_X_FILTER_HASSUBORDINATES + BI_has_subordinates *bi_has_subordinates; +#endif /* SLAP_X_FILTER_HASSUBORDINATES */ BI_connection_init *bi_connection_init; BI_connection_destroy *bi_connection_destroy; -- 2.39.5