]> git.sur5r.net Git - openldap/commitdiff
ITS#6287 Rewritten the ACL state cache
authorRein Tollevik <rein@openldap.org>
Tue, 8 Sep 2009 21:06:15 +0000 (21:06 +0000)
committerRein Tollevik <rein@openldap.org>
Tue, 8 Sep 2009 21:06:15 +0000 (21:06 +0000)
servers/slapd/acl.c
servers/slapd/slap.h

index 4b11753d38769fcf780c242334c7105ce51e1aa7..bbd89fbd3812edaddc6b3c644ae21bb4d33d7f73 100644 (file)
@@ -53,6 +53,7 @@ static AccessControl * slap_acl_get(
        AttributeDescription *desc,
        struct berval *val,
        AclRegexMatches *matches,
+       slap_mask_t *mask,
        AccessControlState *state );
 
 static slap_control_t slap_acl_mask(
@@ -151,6 +152,7 @@ slap_access_allowed(
        const char                      *attr;
        AclRegexMatches                 matches;
        AccessControlState              acl_state = ACL_STATE_INIT;
+       static AccessControlState       state_init = ACL_STATE_INIT;
 
        assert( op != NULL );
        assert( e != NULL );
@@ -216,25 +218,27 @@ slap_access_allowed(
 
        if ( state == NULL )
                state = &acl_state;
-       if ( state->as_vd_ad == desc ) {
+       if ( state->as_desc == desc &&
+               state->as_access == access &&
+               state->as_vd_acl != NULL )
+       {
                a = state->as_vd_acl;
                count = state->as_vd_acl_count;
                if ( state->as_fe_done )
                        state->as_fe_done--;
+               ACL_PRIV_ASSIGN( mask, state->as_vd_mask );
        } else {
-               state->as_vi_acl = NULL;
+               *state = state_init;
 
                a = NULL;
                count = 0;
+               ACL_PRIV_ASSIGN( mask, *maskp );
        }
-       if ( a == NULL )
-               state->as_fe_done = 0;
 
-       ACL_PRIV_ASSIGN( mask, *maskp );
        MATCHES_MEMSET( &matches );
 
        while ( ( a = slap_acl_get( a, &count, op, e, desc, val,
-               &matches, state ) ) != NULL )
+               &matches, &mask, state ) ) != NULL )
        {
                int i; 
                int dnmaxcount = MATCHES_DNMAXCOUNT( &matches );
@@ -278,22 +282,6 @@ slap_access_allowed(
                        Debug( LDAP_DEBUG_ACL, "\n", 0, 0, 0 );
                }
 
-               if ( state ) {
-                       if ( state->as_vi_acl == a &&
-                               ( state->as_recorded & ACL_STATE_RECORDED_NV ) )
-                       {
-                               Debug( LDAP_DEBUG_ACL,
-                                       "=> slap_access_allowed: result was in cache (%s)\n",
-                                       attr, 0, 0 );
-                               ret = state->as_result;
-                               goto done;
-                       } else {
-                               Debug( LDAP_DEBUG_ACL,
-                                       "=> slap_access_allowed: result not in cache (%s)\n",
-                                       attr, 0, 0 );
-                       }
-               }
-
                control = slap_acl_mask( a, &mask, op,
                        e, desc, val, &matches, count, state, access );
 
@@ -374,7 +362,6 @@ access_allowed_mask(
        slap_mask_t             *maskp )
 {
        int                             ret = 1;
-       AccessControl                   *a = NULL;
        int                             be_null = 0;
 
 #ifdef LDAP_DEBUG
@@ -383,7 +370,6 @@ access_allowed_mask(
        slap_mask_t                     mask;
        slap_access_t                   access_level;
        const char                      *attr;
-       static AccessControlState       state_init = ACL_STATE_INIT;
 
        assert( e != NULL );
        assert( desc != NULL );
@@ -415,16 +401,20 @@ access_allowed_mask(
                }
        }
 
-       if ( state ) {
-               if ( state->as_vd_ad == desc ) {
-                       if ( ( state->as_recorded & ACL_STATE_RECORDED_NV ) &&
-                               val == NULL )
+       if ( state != NULL ) {
+               if ( state->as_desc == desc &&
+                       state->as_access == access &&
+                       state->as_result != -1 &&
+                       state->as_vd_acl == NULL )
                        {
+                       Debug( LDAP_DEBUG_ACL,
+                               "=> access_allowed: result was in cache (%s)\n",
+                               attr, 0, 0 );
                                return state->as_result;
-
-                       }
                } else {
-                       *state = state_init;
+                       Debug( LDAP_DEBUG_ACL,
+                               "=> access_allowed: result not in cache (%s)\n",
+                               attr, 0, 0 );
                }
        }
 
@@ -485,13 +475,9 @@ access_allowed_mask(
 
 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_access = access;
                        state->as_result = ret;
-               }
-               state->as_recorded |= ACL_STATE_RECORDED;
-               state->as_vd_ad = desc;
+               state->as_desc = desc;
        }
        if ( be_null ) op->o_bd = NULL;
        if ( maskp ) ACL_PRIV_ASSIGN( *maskp, mask );
@@ -514,6 +500,7 @@ slap_acl_get(
        AttributeDescription *desc,
        struct berval   *val,
        AclRegexMatches *matches,
+       slap_mask_t *mask,
        AccessControlState *state )
 {
        const char *attr;
@@ -628,10 +615,10 @@ slap_acl_get(
                                continue;
                        }
 
-                       if( !( state->as_recorded & ACL_STATE_RECORDED_VD )) {
-                               state->as_recorded |= ACL_STATE_RECORDED_VD;
+                       if ( state->as_vd_acl == NULL ) {
                                state->as_vd_acl = prev;
                                state->as_vd_acl_count = *count - 1;
+                               ACL_PRIV_ASSIGN ( state->as_vd_mask, *mask );
                        }
 
                        if ( a->acl_attrval_style == ACL_STYLE_REGEX ) {
@@ -727,10 +714,10 @@ slap_acl_get(
  * Record value-dependent access control state
  */
 #define ACL_RECORD_VALUE_STATE do { \
-               if( state && !( state->as_recorded & ACL_STATE_RECORDED_VD )) { \
-                       state->as_recorded |= ACL_STATE_RECORDED_VD; \
+               if( state && state->as_vd_acl == NULL ) { \
                        state->as_vd_acl = a; \
                        state->as_vd_acl_count = count; \
+                       ACL_PRIV_ASSIGN( state->as_vd_mask, *mask ); \
                } \
        } while( 0 )
 
@@ -1024,6 +1011,7 @@ acl_mask_dnattr(
        AccessControl           *a,
        int                     count,
        AccessControlState      *state,
+       slap_mask_t                     *mask,
        slap_dn_access          *bdn,
        struct berval           *opndn )
 {
@@ -1504,7 +1492,7 @@ slap_acl_mask(
 
                if ( b->a_dn_at != NULL ) {
                        if ( acl_mask_dnattr( op, e, val, a,
-                                       count, state,
+                                       count, state, mask,
                                        &b->a_dn, &op->o_ndn ) )
                        {
                                continue;
@@ -1522,7 +1510,7 @@ slap_acl_mask(
                        }
 
                        if ( acl_mask_dnattr( op, e, val, a,
-                                       count, state,
+                                       count, state, mask,
                                        &b->a_realdn, &ndn ) )
                        {
                                continue;
@@ -2019,7 +2007,7 @@ acl_check_modlist(
                                if ( ! access_allowed( op, e,
                                        mlist->sml_desc, NULL,
                                        ( mlist->sml_flags & SLAP_MOD_MANAGING ) ? ACL_MANAGE : ACL_WDEL,
-                                       NULL ) )
+                                       &state ) )
                                {
                                        ret = 0;
                                        goto done;
index 95bc81b8a714c745b0640c59fbe9e59dbb575363..18e11a6e588270b8cb9c4f41669ba8fb7ccdd74a 100644 (file)
@@ -1527,27 +1527,27 @@ typedef struct AccessControl {
        struct AccessControl    *acl_next;
 } AccessControl;
 
-typedef enum {
-       ACL_STATE_NOT_RECORDED                  = 0x0,
-       ACL_STATE_RECORDED_VD                   = 0x1,
-       ACL_STATE_RECORDED_NV                   = 0x2,
-       ACL_STATE_RECORDED                      = ( ACL_STATE_RECORDED_VD | ACL_STATE_RECORDED_NV )
-} slap_acl_state_t;
-
 typedef struct AccessControlState {
        /* Access state */
-       AccessControl *as_vi_acl;
-       AccessControl *as_vd_acl;
-       AttributeDescription *as_vd_ad;
 
+       /* The stored state is valid when requesting as_access access
+        * to the as_desc attributes.    */
+       AttributeDescription *as_desc;
+       slap_access_t   as_access;
 
-       slap_acl_state_t as_recorded;
+       /* Value dependent acl where processing can restart */
+       AccessControl  *as_vd_acl;
        int as_vd_acl_count;
+       slap_mask_t             as_vd_mask;
+
+       /* The cached result after evaluating a value independent attr.
+        * Only valid when != -1 and as_vd_acl == NULL */
        int as_result;
+
+       /* True if started to process frontend ACLs */
        int as_fe_done;
 } AccessControlState;
-#define ACL_STATE_INIT { NULL, NULL, NULL, \
-       ACL_STATE_NOT_RECORDED, 0, 0, 0 }
+#define ACL_STATE_INIT { NULL, ACL_NONE, NULL, 0, ACL_PRIV_NONE, -1, 0 }
 
 typedef struct AclRegexMatches {        
        int dn_count;