]> git.sur5r.net Git - openldap/blobdiff - servers/slapd/acl.c
Commit of the Proxy Cache contribution (ITS#2062)
[openldap] / servers / slapd / acl.c
index c2f8641db8b8110309ce80d0f35509265432a890..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
  */
 
@@ -28,6 +28,7 @@ static struct berval
        aci_bv_br_all           = BER_BVC("[all]"),
        aci_bv_access_id        = BER_BVC("access-id"),
        aci_bv_anonymous        = BER_BVC("anonymous"),
+       aci_bv_public           = BER_BVC("public"),
        aci_bv_users            = BER_BVC("users"),
        aci_bv_self             = BER_BVC("self"),
        aci_bv_dnattr           = BER_BVC("dnattr"),
@@ -120,7 +121,7 @@ access_allowed(
 {
        int                             ret = 1;
        int                             count;
-       AccessControl   *a;
+       AccessControl                   *a = NULL;
 
 #ifdef LDAP_DEBUG
        char accessmaskbuf[ACCESSMASK_MAXLEN];
@@ -129,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 );
@@ -138,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 )
                {
@@ -149,6 +153,9 @@ access_allowed(
                {
                        return state->as_result;
                }
+               st_same_attr = 1;
+       } if (state) {
+               state->as_vd_ad=desc;
        }
 
 #ifdef NEW_LOGGING
@@ -245,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;
@@ -289,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 );
@@ -341,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;
        }
@@ -604,17 +626,17 @@ acl_mask(
                         * user is bound as somebody in the same namespace as
                         * the entry, OR the given dn matches the dn pattern
                         */
-                       if ( ber_bvcmp( &b->a_dn_pat, &aci_bv_anonymous ) == 0 ) {
+                       if ( bvmatch( &b->a_dn_pat, &aci_bv_anonymous ) ) {
                                if ( op->o_ndn.bv_len != 0 ) {
                                        continue;
                                }
 
-                       } else if ( ber_bvcmp( &b->a_dn_pat, &aci_bv_users ) == 0 ) {
+                       } else if ( bvmatch( &b->a_dn_pat, &aci_bv_users ) ) {
                                if ( op->o_ndn.bv_len == 0 ) {
                                        continue;
                                }
 
-                       } else if ( ber_bvcmp( &b->a_dn_pat, &aci_bv_self ) == 0 ) {
+                       } else if ( bvmatch( &b->a_dn_pat, &aci_bv_self ) ) {
                                if ( op->o_ndn.bv_len == 0 ) {
                                        continue;
                                }
@@ -763,7 +785,7 @@ dn_match_cleanup:;
                                        if ( b->a_domain_expand ) {
                                                struct berval bv;
 
-                                               bv.bv_len = sizeof(buf);
+                                               bv.bv_len = sizeof(buf) - 1;
                                                bv.bv_val = buf;
 
                                                string_expand(&bv, &b->a_domain_pat, e->e_ndn, matches);
@@ -866,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;
@@ -879,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.
                                         */
@@ -918,7 +943,6 @@ dn_match_cleanup:;
                }
 
                if ( b->a_group_pat.bv_len ) {
-                       char buf[ACL_BUF_SIZE];
                        struct berval bv;
                        struct berval ndn = { 0, NULL };
                        int rc;
@@ -927,36 +951,49 @@ dn_match_cleanup:;
                                continue;
                        }
 
-                       bv.bv_len = sizeof(buf) - 1;
-                       bv.bv_val = buf; 
-
                        /* b->a_group is an unexpanded entry name, expanded it should be an 
                         * entry with objectclass group* and we test to see if odn is one of
                         * the values in the attribute group
                         */
                        /* see if asker is listed in dnattr */
                        if ( b->a_group_style == ACL_STYLE_REGEX ) {
-                               string_expand(&bv, &b->a_group_pat, e->e_ndn, matches);
-                               if ( dnNormalize2(NULL, &bv, &ndn) != LDAP_SUCCESS ) {
+                               char buf[ACL_BUF_SIZE];
+                               bv.bv_len = sizeof(buf) - 1;
+                               bv.bv_val = buf; 
+
+                               string_expand( &bv, &b->a_group_pat, e->e_ndn, matches );
+                               if ( dnNormalize2( NULL, &bv, &ndn ) != LDAP_SUCCESS ) {
                                        /* did not expand to a valid dn */
                                        continue;
                                }
+
                                bv = ndn;
+
                        } else {
                                bv = b->a_group_pat;
                        }
 
-                       rc = backend_group(be, conn, op, e, &bv, &op->o_ndn,
-                               b->a_group_oc, b->a_group_at);
-                       if ( ndn.bv_val )
-                               free( ndn.bv_val );
+                       rc = backend_group( be, conn, op, e, &bv, &op->o_ndn,
+                               b->a_group_oc, b->a_group_at );
+
+                       if ( ndn.bv_val ) free( ndn.bv_val );
+
                        if ( rc != 0 ) {
                                continue;
                        }
                }
 
                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;
                        }
                }
@@ -1196,6 +1233,7 @@ acl_check_modlist(
 )
 {
        struct berval *bv;
+       AccessControlState state = ACL_STATE_INIT;
 
        assert( be != NULL );
 
@@ -1250,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
@@ -1271,8 +1306,6 @@ acl_check_modlist(
                        continue;
                }
 
-               state = state_init;
-
                switch ( mlist->sml_op ) {
                case LDAP_MOD_REPLACE:
                        /*
@@ -1388,7 +1421,7 @@ aci_set_gather (void *cookie, struct berval *name, struct berval *attr)
                const char *text;
                AttributeDescription *desc = NULL;
                if (slap_bv2ad(attr, &desc, &text) == LDAP_SUCCESS) {
-                       backend_attribute(cp->be, NULL, NULL,
+                       backend_attribute(cp->be, NULL, cp->op,
                                cp->e, &ndn, desc, &bvals);
                }
                free(ndn.bv_val);
@@ -1437,7 +1470,7 @@ aci_match_set (
                        if ( dnNormalize2(NULL, &subjdn, &ndn) == LDAP_SUCCESS
                                && slap_bv2ad(&setat, &desc, &text) == LDAP_SUCCESS )
                        {
-                               backend_attribute(be, NULL, NULL, e,
+                               backend_attribute(be, NULL, op, e,
                                        &ndn, desc, &bvals);
                                if ( bvals != NULL ) {
                                        if ( bvals[0].bv_val != NULL ) {
@@ -1669,11 +1702,12 @@ aci_group_member (
        if (grp_oc != NULL && grp_ad != NULL ) {
                char buf[ACL_BUF_SIZE];
                struct berval bv, ndn;
-               bv.bv_len = sizeof( buf );
+               bv.bv_len = sizeof( buf ) - 1;
                bv.bv_val = (char *)&buf;
                string_expand(&bv, &subjdn, e->e_ndn, matches);
                if ( dnNormalize2(NULL, &bv, &ndn) == LDAP_SUCCESS ) {
-                       rc = (backend_group(be, conn, op, e, &ndn, &op->o_ndn, grp_oc, grp_ad) == 0);
+                       rc = (backend_group(be, conn, op, e, &ndn, &op->o_ndn,
+                               grp_oc, grp_ad) == 0);
                        free( ndn.bv_val );
                }
        }
@@ -1707,6 +1741,8 @@ aci_mask(
 
           See draft-ietf-ldapext-aci-model-04.txt section 9.1 for
           a full description of the format for this attribute.
+          Differences: "this" in the draft is "self" here, and
+          "self" and "public" is in the position of dnType.
 
           For now, this routine only supports scope=entry.
         */
@@ -1743,14 +1779,17 @@ aci_mask(
 
        if (ber_bvstrcasecmp( &aci_bv_access_id, &bv ) == 0) {
                struct berval ndn;
-               rc = 1;
+               rc = 0;
                if ( dnNormalize2(NULL, &sdn, &ndn) == LDAP_SUCCESS ) {
-                       if (!dn_match( &op->o_ndn, &ndn))
-                               rc = 0;
+                       if (dn_match( &op->o_ndn, &ndn))
+                               rc = 1;
                        free(ndn.bv_val);
                }
                return (rc);
 
+       } else if (ber_bvstrcasecmp( &aci_bv_public, &bv ) == 0) {
+               return(1);
+
        } else if (ber_bvstrcasecmp( &aci_bv_self, &bv ) == 0) {
                if (dn_match(&op->o_ndn, &e->e_nname))
                        return(1);
@@ -1774,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;
                        }
@@ -1824,7 +1863,8 @@ string_expand(
 
        flag = 0;
        for ( dp = bv->bv_val, sp = pat->bv_val; size < bv->bv_len &&
-               sp < pat->bv_val + pat->bv_len ; sp++) {
+               sp < pat->bv_val + pat->bv_len ; sp++ )
+       {
                /* did we previously see a $ */
                if ( flag ) {
                        if ( flag == 1 && *sp == '$' ) {
@@ -1832,7 +1872,7 @@ string_expand(
                                size++;
                                flag = 0;
 
-                       } else if ( flag == 1 && *sp == '{') {
+                       } else if ( flag == 1 && *sp == '{' /*'}'*/) {
                                flag = 2;
 
                        } else if ( *sp >= '0' && *sp <= '9' ) {
@@ -1843,13 +1883,13 @@ string_expand(
                                n = *sp - '0';
 
                                if ( flag == 2 ) {
-                                       for ( sp++; *sp != '\0' && *sp != /* { */ '}'; sp++ ) {
+                                       for ( sp++; *sp != '\0' && *sp != /*'{'*/ '}'; sp++ ) {
                                                if ( *sp >= '0' && *sp <= '9' ) {
                                                        n = 10*n + ( *sp - '0' );
                                                }
                                        }
 
-                                       if ( *sp != /* { */ '}' ) {
+                                       if ( *sp != /*'{'*/ '}' ) {
                                                /* error */
                                        }
                                }
@@ -1906,18 +1946,18 @@ regex_matches(
 )
 {
        regex_t re;
-       char newbuf[512];
+       char newbuf[ACL_BUF_SIZE];
        struct berval bv;
        int     rc;
 
-       bv.bv_len = sizeof(newbuf);
+       bv.bv_len = sizeof(newbuf) - 1;
        bv.bv_val = newbuf;
 
        if(str == NULL) str = "";
 
        string_expand(&bv, pat, buf, matches);
        if (( rc = regcomp(&re, newbuf, REG_EXTENDED|REG_ICASE))) {
-               char error[512];
+               char error[ACL_BUF_SIZE];
                regerror(rc, &re, error, sizeof(error));
 
 #ifdef NEW_LOGGING