]> git.sur5r.net Git - openldap/blobdiff - servers/slapd/acl.c
Commit of the Proxy Cache contribution (ITS#2062)
[openldap] / servers / slapd / acl.c
index 281d96e66a588e538f91fa1b8dc81bcf5af149c0..404842ad1490a38d181bdb4ca22e2f609593a9cd 100644 (file)
@@ -1,7 +1,7 @@
 /* acl.c - routines to parse and check acl's */
 /* $OpenLDAP$ */
 /*
- * Copyright 1998-2002 The OpenLDAP Foundation, All Rights Reserved.
+ * Copyright 1998-2003 The OpenLDAP Foundation, All Rights Reserved.
  * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
  */
 
@@ -121,7 +121,7 @@ access_allowed(
 {
        int                             ret = 1;
        int                             count;
-       AccessControl   *a;
+       AccessControl                   *a = NULL;
 
 #ifdef LDAP_DEBUG
        char accessmaskbuf[ACCESSMASK_MAXLEN];
@@ -130,6 +130,9 @@ access_allowed(
        slap_control_t control;
        const char *attr;
        regmatch_t matches[MAXREMATCHES];
+       int        st_same_attr = 0;
+       int        st_initialized = 0;
+       static AccessControlState state_init = ACL_STATE_INIT;
 
        assert( e != NULL );
        assert( desc != NULL );
@@ -139,7 +142,7 @@ access_allowed(
 
        assert( attr != NULL );
 
-       if( state && state->as_recorded ) { 
+       if( state && state->as_recorded && state->as_vd_ad==desc) { 
                if( state->as_recorded & ACL_STATE_RECORDED_NV &&
                        val == NULL )
                {
@@ -150,6 +153,9 @@ access_allowed(
                {
                        return state->as_result;
                }
+               st_same_attr = 1;
+       } if (state) {
+               state->as_vd_ad=desc;
        }
 
 #ifdef NEW_LOGGING
@@ -246,7 +252,7 @@ access_allowed(
        ret = 0;
        control = ACL_BREAK;
 
-       if( state && ( state->as_recorded & ACL_STATE_RECORDED_VD )) {
+       if( st_same_attr ) {
                assert( state->as_vd_acl != NULL );
 
                a = state->as_vd_acl;
@@ -290,6 +296,18 @@ access_allowed(
 #endif
                }
 
+               if (state) {
+                       if (state->as_vi_acl == a && (state->as_recorded & ACL_STATE_RECORDED_NV)) {
+                               Debug( LDAP_DEBUG_ACL, "access_allowed: result from state (%s)\n", attr, 0, 0 );
+                               return state->as_result;
+                       } else if (!st_initialized) {
+                               Debug( LDAP_DEBUG_ACL, "access_allowed: no res from state (%s)\n", attr, 0, 0);
+                           *state = state_init;
+                               state->as_vd_ad=desc;
+                               st_initialized=1;
+                       }
+               }
+
 vd_access:
                control = acl_mask( a, &mask, be, conn, op,
                        e, desc, val, matches, count, state );
@@ -342,6 +360,9 @@ vd_access:
 
 done:
        if( state != NULL ) {
+               /* If not value-dependent, save ACL in case of more attrs */
+               if ( !(state->as_recorded & ACL_STATE_RECORDED_VD) )
+                       state->as_vi_acl = a;
                state->as_recorded |= ACL_STATE_RECORDED;
                state->as_result = ret;
        }
@@ -867,7 +888,10 @@ dn_match_cleanup:;
                                at != NULL;
                                at = attrs_find( at->a_next, b->a_dn_at ) )
                        {
-                               if( value_find( b->a_dn_at, at->a_vals, &bv ) == 0 ) {
+                               if( value_find_ex( b->a_dn_at,
+                                       SLAP_MR_ASSERTED_VALUE_NORMALIZED_MATCH,
+                                       at->a_vals, &bv ) == 0 )
+                               {
                                        /* found it */
                                        match = 1;
                                        break;
@@ -880,8 +904,8 @@ dn_match_cleanup:;
                                 */
                                if ( b->a_dn_self ) {
                                        /* check if the target is an attribute. */
-                                       if ( val == NULL )
-                                               continue;
+                                       if ( val == NULL ) continue;
+
                                        /* target is attribute, check if the attribute value
                                         * is the op dn.
                                         */
@@ -960,7 +984,16 @@ dn_match_cleanup:;
                }
 
                if ( b->a_set_pat.bv_len != 0 ) {
-                       if (aci_match_set( &b->a_set_pat, be, e, conn, op, 0 ) == 0) {
+                       struct berval bv;
+                       char buf[ACL_BUF_SIZE];
+                       if( b->a_set_style == ACL_STYLE_REGEX ){
+                               bv.bv_len = sizeof(buf) - 1;
+                               bv.bv_val = buf;
+                               string_expand( &bv, &b->a_set_pat, e->e_ndn, matches );
+                       }else{
+                               bv = b->a_set_pat;
+                       }
+                       if (aci_match_set( &bv, be, e, conn, op, 0 ) == 0) {
                                continue;
                        }
                }
@@ -1200,6 +1233,7 @@ acl_check_modlist(
 )
 {
        struct berval *bv;
+       AccessControlState state = ACL_STATE_INIT;
 
        assert( be != NULL );
 
@@ -1254,9 +1288,6 @@ acl_check_modlist(
        }
 
        for ( ; mlist != NULL; mlist = mlist->sml_next ) {
-               static AccessControlState state_init = ACL_STATE_INIT;
-               AccessControlState state;
-
                /*
                 * no-user-modification operational attributes are ignored
                 * by ACL_WRITE checking as any found here are not provided
@@ -1275,8 +1306,6 @@ acl_check_modlist(
                        continue;
                }
 
-               state = state_init;
-
                switch ( mlist->sml_op ) {
                case LDAP_MOD_REPLACE:
                        /*
@@ -1784,7 +1813,7 @@ aci_mask(
                        at != NULL;
                        at = attrs_find( at->a_next, ad ) )
                {
-                       if (value_find( ad, at->a_vals, &bv) == 0 ) {
+                       if (value_find_ex( ad, SLAP_MR_ASSERTED_VALUE_NORMALIZED_MATCH, at->a_vals, &bv) == 0 ) {
                                rc = 1;
                                break;
                        }