| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033 |
- /** BEGIN COPYRIGHT BLOCK
- * Copyright (C) 2001 Sun Microsystems, Inc. Used by permission.
- * Copyright (C) 2005 Red Hat, Inc.
- * All rights reserved.
- *
- * License: GPL (version 3 or any later version).
- * See LICENSE for details.
- * END COPYRIGHT BLOCK **/
- #ifdef HAVE_CONFIG_H
- # include <config.h>
- #endif
- /* filterentry.c - apply a filter to an entry */
- #include <stdio.h>
- #include <string.h>
- #include <sys/types.h>
- #include <sys/socket.h>
- #include "slap.h"
- static int test_filter_list();
- static int test_extensible_filter();
- static int vattr_test_filter_list();
- static int test_filter_access( Slapi_PBlock *pb, Slapi_Entry*e,
- char * attr_type, struct berval *attr_val);
- static int slapi_vattr_filter_test_ext_internal( Slapi_PBlock *pb, Slapi_Entry *e,
- struct slapi_filter *f, int verify_access, int only_check_access, int *access_check_done);
- static char *opt_str = 0;
- static int opt = 0;
- static int optimise_filter_acl_tests()
- {
- if(!opt_str)
- {
- opt_str = getenv( "NS_DS_OPT_FILT_ACL_EVAL" );
- if(opt_str)
- opt = !strcasecmp(opt_str, "false");
- else
- opt = 0;
- if(!opt_str)
- opt_str = "dummy";
- }
- return opt;
- }
- /*
- * slapi_filter_test - test a filter against a single entry.
- * returns 0 filter matched
- * -1 filter did not match
- * >0 an ldap error code
- */
- int
- slapi_filter_test(
- Slapi_PBlock *pb,
- Slapi_Entry *e,
- struct slapi_filter *f,
- int verify_access
- )
- {
- return slapi_filter_test_ext(pb,e,f,verify_access,0);
- }
- /*
- * slapi_filter_test_simple - test without checking access control
- *
- * returns 0 filter matched
- * -1 filter did not match
- * >0 an ldap error code
- */
- int
- slapi_filter_test_simple(
- Slapi_Entry *e,
- struct slapi_filter *f
- )
- {
- return slapi_vattr_filter_test_ext(NULL,e,f,0,0);
- }
- /*
- * slapi_filter_test_ext - full-feature filter test function
- *
- * returns 0 filter matched
- * -1 filter did not match
- * >0 an ldap error code
- */
- int
- slapi_filter_test_ext_internal(
- Slapi_PBlock *pb,
- Slapi_Entry *e,
- struct slapi_filter *f,
- int verify_access,
- int only_check_access,
- int *access_check_done
- )
- {
- int rc;
- LDAPDebug( LDAP_DEBUG_FILTER, "=> slapi_filter_test_ext\n", 0, 0, 0 );
- /*
- * RJP: Not sure if this is semantically right, but we have to
- * return something if f is NULL. If there is no filter,
- * then we say that it did match and return 0.
- */
- if ( f == NULL) {
- return(0);
- }
- switch ( f->f_choice ) {
- case LDAP_FILTER_EQUALITY:
- LDAPDebug( LDAP_DEBUG_FILTER, " EQUALITY\n", 0, 0, 0 );
- rc = test_ava_filter( pb, e, e->e_attrs, &f->f_ava, LDAP_FILTER_EQUALITY,
- verify_access , only_check_access, access_check_done);
- break;
- case LDAP_FILTER_SUBSTRINGS:
- LDAPDebug( LDAP_DEBUG_FILTER, " SUBSTRINGS\n", 0, 0, 0 );
- rc = test_substring_filter( pb, e, f, verify_access , only_check_access, access_check_done);
- break;
- case LDAP_FILTER_GE:
- LDAPDebug( LDAP_DEBUG_FILTER, " GE\n", 0, 0, 0 );
- rc = test_ava_filter( pb, e, e->e_attrs, &f->f_ava, LDAP_FILTER_GE,
- verify_access , only_check_access, access_check_done);
- break;
- case LDAP_FILTER_LE:
- LDAPDebug( LDAP_DEBUG_FILTER, " LE\n", 0, 0, 0 );
- rc = test_ava_filter( pb, e, e->e_attrs, &f->f_ava, LDAP_FILTER_LE,
- verify_access , only_check_access, access_check_done);
- break;
- case LDAP_FILTER_PRESENT:
- LDAPDebug( LDAP_DEBUG_FILTER, " PRESENT\n", 0, 0, 0 );
- rc = test_presence_filter( pb, e, f->f_type, verify_access , only_check_access, access_check_done);
- break;
- case LDAP_FILTER_APPROX:
- LDAPDebug( LDAP_DEBUG_FILTER, " APPROX\n", 0, 0, 0 );
- rc = test_ava_filter( pb, e, e->e_attrs, &f->f_ava, LDAP_FILTER_APPROX,
- verify_access , only_check_access, access_check_done);
- break;
- case LDAP_FILTER_EXTENDED:
- LDAPDebug( LDAP_DEBUG_FILTER, " EXTENDED\n", 0, 0, 0 );
- rc = test_extensible_filter( pb, e, &f->f_mr, verify_access , only_check_access, access_check_done);
- break;
- case LDAP_FILTER_AND:
- LDAPDebug( LDAP_DEBUG_FILTER, " AND\n", 0, 0, 0 );
- rc = test_filter_list( pb, e, f->f_and,
- LDAP_FILTER_AND , verify_access, only_check_access, access_check_done);
- break;
- case LDAP_FILTER_OR:
- LDAPDebug( LDAP_DEBUG_FILTER, " OR\n", 0, 0, 0 );
- rc = test_filter_list( pb, e, f->f_or,
- LDAP_FILTER_OR , verify_access, only_check_access, access_check_done);
- break;
- case LDAP_FILTER_NOT:
- LDAPDebug( LDAP_DEBUG_FILTER, " NOT\n", 0, 0, 0 );
- rc = slapi_filter_test_ext_internal( pb, e, f->f_not , verify_access, only_check_access, access_check_done);
- if(!(verify_access && only_check_access)) /* dont play with access control return codes */
- {
- if(verify_access && !rc && !(*access_check_done))
- {
- /* the filter failed so access control was not checked
- * for NOT filters this is significant so we must ensure
- * access control is checked
- */
- /* check access control only */
- rc = slapi_filter_test_ext_internal( pb, e, f->f_not , verify_access, -1 /*only_check_access*/, access_check_done);
- /* preserve error code if any */
- if(!rc)
- rc = !rc;
- }
- else
- rc = !rc;
- }
- break;
- default:
- LDAPDebug( LDAP_DEBUG_ANY, " unknown filter type 0x%lX\n",
- f->f_choice, 0, 0 );
- rc = -1;
- }
- LDAPDebug( LDAP_DEBUG_FILTER, "<= slapi_filter_test %d\n", rc, 0, 0 );
- return( rc );
- }
- int
- slapi_filter_test_ext(
- Slapi_PBlock *pb,
- Slapi_Entry *e,
- struct slapi_filter *f,
- int verify_access,
- int only_check_access
- )
- {
- int rc = 0; /* a no op request succeeds */
- int access_check_done = 0;
- switch ( f->f_choice ) {
- case LDAP_FILTER_AND:
- case LDAP_FILTER_OR:
- case LDAP_FILTER_NOT:
- /*
- * optimize acl checking by only doing it once it is
- * known that the whole filter passes and so the entry
- * is eligible to be returned.
- * then we check the filter only for access
- *
- * complex filters really benefit from
- * separate stages, filter eval, followed by acl check...
- */
- if(!only_check_access)
- {
- rc = slapi_filter_test_ext_internal(pb,e,f,0,0, &access_check_done);
- }
- if(rc == 0 && verify_access)
- {
- rc = slapi_filter_test_ext_internal(pb,e,f,-1,-1, &access_check_done);
- }
- break;
- default:
- /*
- * ...but simple filters are better off doing eval and
- * acl check at once
- */
- rc = slapi_filter_test_ext_internal(pb,e,f,verify_access,only_check_access, &access_check_done);
- break;
- }
- return rc;
- }
- int test_ava_filter(
- Slapi_PBlock *pb,
- Slapi_Entry *e,
- Slapi_Attr *a,
- struct ava *ava,
- int ftype,
- int verify_access,
- int only_check_access,
- int *access_check_done
- )
- {
- int rc;
-
- LDAPDebug( LDAP_DEBUG_FILTER, "=> test_ava_filter\n", 0, 0, 0 );
- *access_check_done = 0;
- if(optimise_filter_acl_tests())
- {
- rc = 0;
- if(!only_check_access)
- {
- rc = -1;
- for ( ; a != NULL; a = a->a_next ) {
- if ( slapi_attr_type_cmp( ava->ava_type, a->a_type, SLAPI_TYPE_CMP_SUBTYPE ) == 0 ) {
- rc = plugin_call_syntax_filter_ava( a, ftype, ava );
- if ( rc == 0 ) {
- break;
- }
- }
- }
- }
- if ( rc == 0 && verify_access && pb != NULL ) {
- char *attrs[2] = { NULL, NULL };
- attrs[0] = ava->ava_type;
- rc = plugin_call_acl_plugin( pb, e, attrs, &ava->ava_value,
- SLAPI_ACL_SEARCH, ACLPLUGIN_ACCESS_DEFAULT, NULL );
- *access_check_done = -1;
- }
- }
- else
- {
- if ( verify_access && pb != NULL ) {
- char *attrs[2] = { NULL, NULL };
- attrs[0] = ava->ava_type;
- rc = plugin_call_acl_plugin( pb, e, attrs, &ava->ava_value,
- SLAPI_ACL_SEARCH, ACLPLUGIN_ACCESS_DEFAULT, NULL );
- *access_check_done = -1;
- if ( only_check_access || rc != LDAP_SUCCESS ) {
- LDAPDebug( LDAP_DEBUG_FILTER, "<= test_ava_filter %d\n",
- rc, 0, 0 );
- return( rc );
- }
- }
- rc = -1;
- for ( ; a != NULL; a = a->a_next ) {
- if ( slapi_attr_type_cmp( ava->ava_type, a->a_type, SLAPI_TYPE_CMP_SUBTYPE ) == 0 ) {
- rc = plugin_call_syntax_filter_ava( a, ftype, ava );
- if ( rc == 0 ) {
- break;
- }
- }
- }
- }
- LDAPDebug( LDAP_DEBUG_FILTER, "<= test_ava_filter %d\n", rc, 0, 0 );
- return( rc );
- }
- int
- test_presence_filter(
- Slapi_PBlock *pb,
- Slapi_Entry *e,
- char *type,
- int verify_access,
- int only_check_access,
- int *access_check_done
- )
- {
- int rc;
- void *hint = NULL;
- *access_check_done = 0;
- if(optimise_filter_acl_tests())
- {
- rc = 0;
- /* Use attrlist_find_ex to get subtype matching */
- if(!only_check_access)
- {
- rc = attrlist_find_ex( e->e_attrs, type,
- NULL, NULL, &hint ) != NULL ? 0 : -1;
- }
- if (rc == 0 && verify_access && pb != NULL) {
- char *attrs[2] = { NULL, NULL };
- attrs[0] = type;
- rc = plugin_call_acl_plugin( pb, e, attrs, NULL, SLAPI_ACL_SEARCH,
- ACLPLUGIN_ACCESS_DEFAULT, NULL );
- *access_check_done = -1;
- }
- }
- else
- {
- if (verify_access && pb != NULL) {
- char *attrs[2] = { NULL, NULL };
- attrs[0] = type;
- rc = plugin_call_acl_plugin( pb, e, attrs, NULL, SLAPI_ACL_SEARCH,
- ACLPLUGIN_ACCESS_DEFAULT, NULL );
- *access_check_done = -1;
- if ( only_check_access || rc != LDAP_SUCCESS ) {
- return( rc );
- }
- }
- /* Use attrlist_find_ex to get subtype matching */
- rc = attrlist_find_ex( e->e_attrs, type,
- NULL, NULL, &hint ) != NULL ? 0 : -1;
- }
- return rc;
- }
- /*
- * Convert a DN into a list of attribute values.
- * The caller must free the returned attributes.
- */
- static Slapi_Attr*
- dn2attrs(const char *dn)
- {
- int rc= 0;
- Slapi_Attr* dnAttrs = NULL;
- char** rdns = slapi_ldap_explode_dn (dn, 0);
- if (rdns)
- {
- char** rdn = rdns;
- for (; !rc && *rdn; ++rdn)
- {
- char** avas = slapi_ldap_explode_rdn (*rdn, 0);
- if (avas)
- {
- char** ava = avas;
- for (; !rc && *ava; ++ava)
- {
- char* val = strchr (*ava, '=');
- if (val)
- {
- struct berval bv;
- struct berval* bvec[] = {NULL, NULL};
- size_t type_len = val - *ava;
- char* type = slapi_ch_malloc (type_len + 1);
- memcpy (type, *ava, type_len);
- type[type_len] = '\0';
- ++val; /* skip the '=' */
- bv.bv_val = val;
- bv.bv_len = strlen(val);
- bvec[0] = &bv;
- attrlist_merge (&dnAttrs, type, bvec);
- slapi_ch_free_string( &type );
- }
- }
- slapi_ldap_value_free (avas);
- }
- }
- slapi_ldap_value_free (rdns);
- }
- return dnAttrs;
- }
- static int
- test_extensible_filter(
- Slapi_PBlock *callers_pb,
- Slapi_Entry *e,
- mr_filter_t *mrf,
- int verify_access,
- int only_check_access,
- int *access_check_done
- )
- {
- /*
- * The ABNF for extensible filters is
- *
- * attr [":dn"] [":" matchingrule] ":=" value
- * [":dn"] ":" matchingrule ":=" value
- *
- * So, sigh, there are six possible combinations:
- *
- * A) attr ":=" value
- * B) attr ":dn" ":=" value
- * C) attr ":" matchingrule ":=" value
- * D) attr ":dn" ":" matchingrule ":=" value
- * E) ":" matchingrule ":=" value
- * F) ":dn" ":" matchingrule ":=" value
- */
- int rc;
-
- LDAPDebug( LDAP_DEBUG_FILTER, "=> test_extensible_filter\n", 0, 0, 0 );
- *access_check_done = 0;
- if(optimise_filter_acl_tests())
- {
- rc = LDAP_SUCCESS;
- if(!only_check_access)
- {
- if (mrf->mrf_match==NULL)
- {
- /*
- * Could be A or B
- * No matching function. So use a regular equality filter.
- * Check the regular attributes for the attribute value.
- */
- struct ava a;
- a.ava_type= mrf->mrf_type;
- a.ava_value.bv_len= mrf->mrf_value.bv_len;
- a.ava_value.bv_val = mrf->mrf_value.bv_val;
- a.ava_private = NULL;
- rc= test_ava_filter( callers_pb, e, e->e_attrs, &a, LDAP_FILTER_EQUALITY, 0 /* Don't Verify Access */ , 0 /* don't just verify access */, access_check_done );
- if(rc!=LDAP_SUCCESS && mrf->mrf_dnAttrs)
- {
- /* B) Also check the DN attributes for the attribute value */
- Slapi_Attr* dnattrs= dn2attrs(slapi_entry_get_dn_const(e));
- rc= test_ava_filter( callers_pb, e, dnattrs, &a, LDAP_FILTER_EQUALITY, 0 /* Don't Verify Access */ , 0 /* don't just verify access */, access_check_done );
- attrlist_free( dnattrs );
- }
- }
- else
- {
- /*
- * Could be C, D, E, or F
- * We have a matching rule.
- */
- rc = mrf->mrf_match (mrf->mrf_object, e, e->e_attrs);
- if(rc!=LDAP_SUCCESS && mrf->mrf_dnAttrs)
- {
- /* D & F) Also check the DN attributes for the attribute value */
- Slapi_Attr* dnattrs= dn2attrs(slapi_entry_get_dn_const(e));
- mrf->mrf_match (mrf->mrf_object, e, dnattrs);
- attrlist_free( dnattrs );
- }
- }
- }
- if(rc == 0 && mrf->mrf_type!=NULL && verify_access)
- {
- char *attrs[2] = { NULL, NULL };
- /* Could be A, B, C, or D */
- /* Check we have access to this attribute on this entry */
- attrs[0] = mrf->mrf_type;
- rc= plugin_call_acl_plugin (callers_pb, e, attrs, &(mrf->mrf_value),
- SLAPI_ACL_SEARCH, ACLPLUGIN_ACCESS_DEFAULT, NULL );
- *access_check_done = -1;
- }
- }
- else
- {
- rc = LDAP_SUCCESS;
- if(mrf->mrf_type!=NULL && verify_access)
- {
- char *attrs[2] = { NULL, NULL };
- /* Could be A, B, C, or D */
- /* Check we have access to this attribute on this entry */
- attrs[0] = mrf->mrf_type;
- rc= plugin_call_acl_plugin (callers_pb, e, attrs, &(mrf->mrf_value),
- SLAPI_ACL_SEARCH, ACLPLUGIN_ACCESS_DEFAULT, NULL );
- *access_check_done = -1;
- if ( only_check_access ) {
- return rc;
- }
- }
- if(rc==LDAP_SUCCESS)
- {
- if (mrf->mrf_match==NULL)
- {
- /*
- * Could be A or B
- * No matching function. So use a regular equality filter.
- * Check the regular attributes for the attribute value.
- */
- struct ava a;
- a.ava_type= mrf->mrf_type;
- a.ava_value.bv_len= mrf->mrf_value.bv_len;
- a.ava_value.bv_val = mrf->mrf_value.bv_val;
- a.ava_private = NULL;
- rc= test_ava_filter( callers_pb, e, e->e_attrs, &a, LDAP_FILTER_EQUALITY, 0 /* Don't Verify Access */ , 0 /* don't just verify access */, access_check_done );
- if(rc!=LDAP_SUCCESS && mrf->mrf_dnAttrs)
- {
- /* B) Also check the DN attributes for the attribute value */
- Slapi_Attr* dnattrs= dn2attrs(slapi_entry_get_dn_const(e));
- rc= test_ava_filter( callers_pb, e, dnattrs, &a, LDAP_FILTER_EQUALITY, 0 /* Don't Verify Access */ , 0 /* don't just verify access */, access_check_done );
- attrlist_free( dnattrs );
- }
- }
- else
- {
- /*
- * Could be C, D, E, or F
- * We have a matching rule.
- */
- rc = mrf->mrf_match (mrf->mrf_object, e, e->e_attrs);
- if(rc!=LDAP_SUCCESS && mrf->mrf_dnAttrs)
- {
- /* D & F) Also check the DN attributes for the attribute value */
- Slapi_Attr* dnattrs= dn2attrs(slapi_entry_get_dn_const(e));
- mrf->mrf_match (mrf->mrf_object, e, dnattrs);
- attrlist_free( dnattrs );
- }
- }
- }
- }
- LDAPDebug( LDAP_DEBUG_FILTER, "<= test_extensible_filter %d\n", rc, 0, 0 );
- return( rc );
- }
- static int
- test_filter_list(
- Slapi_PBlock *pb,
- Slapi_Entry *e,
- struct slapi_filter *flist,
- int ftype,
- int verify_access,
- int only_check_access,
- int *access_check_done
- )
- {
- int nomatch;
- struct slapi_filter *f;
- int access_check_tmp = -1;
- LDAPDebug( LDAP_DEBUG_FILTER, "=> test_filter_list\n", 0, 0, 0 );
- *access_check_done = -1;
- nomatch = 1;
- for ( f = flist; f != NULL; f = f->f_next ) {
- if ( slapi_filter_test_ext_internal( pb, e, f, verify_access, only_check_access, &access_check_tmp ) != 0 ) {
- /* optimize AND evaluation */
- if ( ftype == LDAP_FILTER_AND ) {
- /* one false is failure */
- nomatch = 1;
- break;
- }
- } else {
- nomatch = 0;
- /* optimize OR evaluation too */
- if ( ftype == LDAP_FILTER_OR ) {
- /* only one needs to be true */
- break;
- }
- }
- if(!access_check_tmp)
- *access_check_done = 0;
- }
- LDAPDebug( LDAP_DEBUG_FILTER, "<= test_filter_list %d\n", nomatch, 0, 0 );
- return( nomatch );
- }
- char *
- filter_strcpy_special_ext( char *d, char *s, int flags )
- {
- for ( ; *s; s++ ) {
- switch ( *s ) {
- case '.':
- case '\\':
- case '[':
- case ']':
- case '*':
- case '+':
- case '^':
- case '$':
- *d++ = '\\';
- break;
- case '(':
- case ')':
- case '}':
- case '{':
- case '|':
- case '?':
- if (flags & FILTER_STRCPY_ESCAPE_RECHARS) {
- *d++ = '\\';
- }
- break;
- default:
- break;
- }
- *d++ = *s;
- }
- *d = '\0';
- return d;
- }
- char *
- filter_strcpy_special( char *d, char *s )
- {
- return filter_strcpy_special_ext(d, s, 0);
- }
- int test_substring_filter(
- Slapi_PBlock *pb,
- Slapi_Entry *e,
- struct slapi_filter *f,
- int verify_access,
- int only_check_access,
- int *access_check_done
- )
- {
- Slapi_Attr *a;
- int rc;
- LDAPDebug( LDAP_DEBUG_FILTER, "=> test_substring_filter\n", 0, 0, 0 );
- *access_check_done = 0;
- if(optimise_filter_acl_tests())
- {
- rc = 0;
- if(!only_check_access)
- {
- rc = -1;
- for ( a = e->e_attrs; a != NULL; a = a->a_next ) {
- if ( slapi_attr_type_cmp( f->f_sub_type, a->a_type, SLAPI_TYPE_CMP_SUBTYPE ) == 0 ) {
- rc = plugin_call_syntax_filter_sub( pb, a, &f->f_sub );
- if ( rc == 0 ) {
- break;
- }
- }
- }
- }
- if ( rc == 0 && verify_access && pb != NULL) {
- char *attrs[2] = { NULL, NULL };
- attrs[0] = f->f_sub_type;
- rc = plugin_call_acl_plugin( pb, e, attrs, NULL,
- SLAPI_ACL_SEARCH, ACLPLUGIN_ACCESS_DEFAULT, NULL );
- *access_check_done = -1;
- }
- }
- else
- {
- if ( verify_access && pb != NULL) {
- char *attrs[2] = { NULL, NULL };
- attrs[0] = f->f_sub_type;
- rc = plugin_call_acl_plugin( pb, e, attrs, NULL,
- SLAPI_ACL_SEARCH, ACLPLUGIN_ACCESS_DEFAULT, NULL );
- *access_check_done = -1;
- if ( only_check_access || rc != LDAP_SUCCESS ) {
- return( rc );
- }
- }
- rc = -1;
- for ( a = e->e_attrs; a != NULL; a = a->a_next ) {
- if ( slapi_attr_type_cmp( f->f_sub_type, a->a_type, SLAPI_TYPE_CMP_SUBTYPE ) == 0 ) {
- rc = plugin_call_syntax_filter_sub( pb, a, &f->f_sub );
- if ( rc == 0 || rc == LDAP_TIMELIMIT_EXCEEDED ) {
- break;
- }
- }
- }
- }
- LDAPDebug( LDAP_DEBUG_FILTER, "<= test_substring_filter %d\n",
- rc, 0, 0 );
- return( rc );
- }
- /*
- * Here's a duplicate vattr filter test code modified to support vattrs.
- */
- /*
- * slapi_vattr_filter_test - test a filter against a single entry.
- *
- * Supports the case where the filter mentions virtual attributes.
- * Performance for a real attr only filter is same as for slapi_filter_test()
- * No explicit support for vattrs in extended filters because:
- * 1. the matching rules must support virtual attributes themselves.
- * 2. if no matching rule is specified it defaults to equality so
- * could just use a normal filter with equality.
- * 3. virtual naming attributes are probably too complex to support.
- *
- * returns 0 filter matched
- * -1 filter did not match
- * >0 an ldap error code
- */
- int
- slapi_vattr_filter_test(
- Slapi_PBlock *pb,
- Slapi_Entry *e,
- struct slapi_filter *f,
- int verify_access
- )
- {
- return slapi_vattr_filter_test_ext(pb,e,f,verify_access,0);
- }
- /*
- * vattr_filter_test_ext - full-feature filter test function
- *
- * returns 0 filter matched
- * -1 filter did not match
- * >0 an ldap error code
- */
- int
- slapi_vattr_filter_test_ext(
- Slapi_PBlock *pb,
- Slapi_Entry *e,
- struct slapi_filter *f,
- int verify_access,
- int only_check_access
- )
- {
- int rc = 0; /* a no op request succeeds */
- int access_check_done = 0;
- switch ( f->f_choice ) {
- case LDAP_FILTER_AND:
- case LDAP_FILTER_OR:
- case LDAP_FILTER_NOT:
- /*
- * optimize acl checking by only doing it once it is
- * known that the whole filter passes and so the entry
- * is eligible to be returned.
- * then we check the filter only for access
- *
- * complex filters really benefit from
- * separate stages, filter eval, followed by acl check...
- */
- if(!only_check_access)
- {
- rc = slapi_vattr_filter_test_ext_internal(pb,e,f,0,0, &access_check_done);
- }
- if(rc == 0 && verify_access)
- {
- rc = slapi_vattr_filter_test_ext_internal(pb,e,f,-1,-1, &access_check_done);
- }
- break;
- default:
- /*
- * ...but simple filters are better off doing eval and
- * acl check at once
- */
- rc = slapi_vattr_filter_test_ext_internal(pb,e,f,verify_access,only_check_access, &access_check_done);
- break;
- }
- return rc;
- }
- static int
- slapi_vattr_filter_test_ext_internal(
- Slapi_PBlock *pb,
- Slapi_Entry *e,
- struct slapi_filter *f,
- int verify_access,
- int only_check_access,
- int *access_check_done
- )
- {
- int rc = LDAP_SUCCESS;
- LDAPDebug( LDAP_DEBUG_FILTER, "=> slapi_vattr_filter_test_ext\n", 0, 0, 0 );
- /*
- * RJP: Not sure if this is semantically right, but we have to
- * return something if f is NULL. If there is no filter,
- * then we say that it did match and return 0.
- */
- if ( f == NULL) {
- return(0);
- }
- LDAPDebug( LDAP_DEBUG_FILTER, "=> test_substring_filter\n", 0, 0, 0 );
- switch ( f->f_choice ) {
- case LDAP_FILTER_EQUALITY:
- LDAPDebug( LDAP_DEBUG_FILTER, " EQUALITY\n", 0, 0, 0 );
- if ( verify_access ) {
- rc = test_filter_access( pb, e, f->f_ava.ava_type,
- &f->f_ava.ava_value);
- *access_check_done = 1;
- }
- if ( only_check_access || rc != LDAP_SUCCESS ) {
- return( rc );
- }
- rc = vattr_test_filter( pb, e, f, FILTER_TYPE_AVA, f->f_ava.ava_type );
- break;
- case LDAP_FILTER_SUBSTRINGS:
- LDAPDebug( LDAP_DEBUG_FILTER, " SUBSTRINGS\n", 0, 0, 0 );
- if ( verify_access ) {
- rc = test_filter_access( pb, e, f->f_sub_type, NULL);
- *access_check_done = 1;
- }
- if ( only_check_access || rc != LDAP_SUCCESS ) {
- return( rc );
- }
- rc = vattr_test_filter( pb, e, f, FILTER_TYPE_SUBSTRING, f->f_sub_type);
- break;
- case LDAP_FILTER_GE:
- LDAPDebug( LDAP_DEBUG_FILTER, " GE\n", 0, 0, 0 );
- if ( verify_access ) {
- rc = test_filter_access( pb, e, f->f_ava.ava_type,
- &f->f_ava.ava_value);
- *access_check_done = 1;
- }
- if ( only_check_access || rc != LDAP_SUCCESS ) {
- return( rc );
- }
- rc = vattr_test_filter( pb, e, f, FILTER_TYPE_AVA, f->f_ava.ava_type);
- break;
- case LDAP_FILTER_LE:
- LDAPDebug( LDAP_DEBUG_FILTER, " LE\n", 0, 0, 0 );
- if ( verify_access ) {
- rc = test_filter_access( pb, e, f->f_ava.ava_type,
- &f->f_ava.ava_value);
- *access_check_done = 1;
- }
- if ( only_check_access || rc != LDAP_SUCCESS ) {
- return( rc );
- }
- rc = vattr_test_filter( pb, e, f, FILTER_TYPE_AVA, f->f_ava.ava_type);
- break;
- case LDAP_FILTER_PRESENT:
- LDAPDebug( LDAP_DEBUG_FILTER, " PRESENT\n", 0, 0, 0 );
- if ( verify_access ) {
- rc = test_filter_access( pb, e, f->f_type, NULL);
- *access_check_done = 1;
- }
- if ( only_check_access || rc != LDAP_SUCCESS ) {
- return( rc );
- }
- rc = vattr_test_filter( pb, e, f, FILTER_TYPE_PRES, f->f_type);
- break;
- case LDAP_FILTER_APPROX:
- LDAPDebug( LDAP_DEBUG_FILTER, " APPROX\n", 0, 0, 0 );
- if ( verify_access ) {
- rc = test_filter_access( pb, e, f->f_ava.ava_type,
- &f->f_ava.ava_value);
- *access_check_done = 1;
- }
- if ( only_check_access || rc != LDAP_SUCCESS ) {
- return( rc );
- }
- rc = vattr_test_filter( pb, e, f, FILTER_TYPE_AVA, f->f_ava.ava_type);
- break;
- case LDAP_FILTER_EXTENDED:
- LDAPDebug( LDAP_DEBUG_FILTER, " EXTENDED\n", 0, 0, 0 );
- rc = test_extensible_filter( pb, e, &f->f_mr, verify_access ,
- only_check_access, access_check_done);
- break;
- case LDAP_FILTER_AND:
- LDAPDebug( LDAP_DEBUG_FILTER, " AND\n", 0, 0, 0 );
- rc = vattr_test_filter_list( pb, e, f->f_and,
- LDAP_FILTER_AND , verify_access, only_check_access, access_check_done);
- break;
- case LDAP_FILTER_OR:
- LDAPDebug( LDAP_DEBUG_FILTER, " OR\n", 0, 0, 0 );
- rc = vattr_test_filter_list( pb, e, f->f_or,
- LDAP_FILTER_OR , verify_access, only_check_access, access_check_done);
- break;
- case LDAP_FILTER_NOT:
- LDAPDebug( LDAP_DEBUG_FILTER, " NOT\n", 0, 0, 0 );
- rc = slapi_vattr_filter_test_ext_internal( pb, e, f->f_not , verify_access, only_check_access, access_check_done);
- if(!(verify_access && only_check_access)) /* dont play with access control return codes */
- {
- if(verify_access && !rc && !(*access_check_done))
- {
- /* the filter failed so access control was not checked
- * for NOT filters this is significant so we must ensure
- * access control is checked
- */
- /* check access control only */
- rc = slapi_vattr_filter_test_ext_internal( pb, e, f->f_not , verify_access, -1 /*only_check_access*/, access_check_done);
- /* preserve error code if any */
- if(!rc)
- rc = !rc;
- }
- else
- rc = !rc;
- }
- break;
- default:
- LDAPDebug( LDAP_DEBUG_ANY, " unknown filter type 0x%lX\n",
- f->f_choice, 0, 0 );
- rc = -1;
- }
- LDAPDebug( LDAP_DEBUG_FILTER, "<= slapi_vattr_filter_test %d\n", rc, 0, 0 );
- return( rc );
- }
- static int test_filter_access( Slapi_PBlock *pb,
- Slapi_Entry *e,
- char *attr_type,
- struct berval *attr_val) {
- /*
- * attr_type--attr_type to test for.
- * attr_val--attr value to test for
- */
- int rc;
- char *attrs[2] = { NULL, NULL };
- attrs[0] = attr_type;
-
- rc = plugin_call_acl_plugin( pb, e, attrs, attr_val,
- SLAPI_ACL_SEARCH, ACLPLUGIN_ACCESS_DEFAULT, NULL );
- return(rc);
- }
- static int
- vattr_test_filter_list(
- Slapi_PBlock *pb,
- Slapi_Entry *e,
- struct slapi_filter *flist,
- int ftype,
- int verify_access,
- int only_check_access,
- int *access_check_done
- )
- {
- int nomatch;
- struct slapi_filter *f;
- LDAPDebug( LDAP_DEBUG_FILTER, "=> vattr_test_filter_list\n", 0, 0, 0 );
- nomatch = 1;
- for ( f = flist; f != NULL; f = f->f_next ) {
- if ( slapi_vattr_filter_test_ext_internal( pb, e, f, verify_access, only_check_access, access_check_done ) != 0 ) {
- /* optimize AND evaluation */
- if ( ftype == LDAP_FILTER_AND || verify_access) {
- /* one false is failure
- * for AND all components need to match
- * and for AND and OR access to ALL filter attributes is required
- */
- nomatch = 1;
- break;
- }
- } else {
- nomatch = 0;
- /* optimize OR evaluation too */
- if ( ftype == LDAP_FILTER_OR && !verify_access) {
- /* access to all atributes needs to be evaluated
- * for filter matching
- * only one needs to be true
- */
- break;
- }
- }
- }
- LDAPDebug( LDAP_DEBUG_FILTER, "<= test_filter_list %d\n", nomatch, 0, 0 );
- return( nomatch );
- }
|