]> git.sur5r.net Git - openldap/commitdiff
ITS#2497, implement value-level ACLs:
authorHoward Chu <hyc@openldap.org>
Sat, 20 Sep 2003 03:23:10 +0000 (03:23 +0000)
committerHoward Chu <hyc@openldap.org>
Sat, 20 Sep 2003 03:23:10 +0000 (03:23 +0000)
access to attr=foo val.regex=bar.*

servers/slapd/acl.c
servers/slapd/aclparse.c
servers/slapd/slap.h

index 5b1f0434b84f1e19589728a7ec6502811c334519..17f4459e00b502bebe73bf1bc57ea28532f7651a 100644 (file)
@@ -50,6 +50,7 @@ static AccessControl * acl_get(
        AccessControl *ac, int *count,
        Operation *op, Entry *e,
        AttributeDescription *desc,
+       struct berval *val,
        int nmatches, regmatch_t *matches );
 
 static slap_control_t acl_mask(
@@ -286,7 +287,7 @@ access_allowed(
                memset(matches, '\0', sizeof(matches));
        }
 
-       while((a = acl_get( a, &count, op, e, desc,
+       while((a = acl_get( a, &count, op, e, desc, val,
                MAXREMATCHES, matches )) != NULL)
        {
                int i;
@@ -379,10 +380,11 @@ 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) )
+               if ( !(state->as_recorded & ACL_STATE_RECORDED_VD) ) {
                        state->as_vi_acl = a;
+                       state->as_result = ret;
+               }
                state->as_recorded |= ACL_STATE_RECORDED;
-               state->as_result = ret;
        }
        if (be_null) op->o_bd = NULL;
        return ret;
@@ -401,6 +403,7 @@ acl_get(
        Operation       *op,
        Entry           *e,
        AttributeDescription *desc,
+       struct berval   *val,
        int                     nmatch,
        regmatch_t      *matches )
 {
@@ -515,7 +518,7 @@ acl_get(
                Debug( LDAP_DEBUG_ACL, "=> acl_get: [%d] check attr %s\n",
                       *count, attr, 0);
 #endif
-               if ( attr == NULL || a->acl_attrs == NULL ||
+               if ( a->acl_attrs == NULL ||
                        ad_inlist( desc, a->acl_attrs ) )
                {
 #ifdef NEW_LOGGING
@@ -612,6 +615,48 @@ acl_mask(
                accessmask2str( *mask, accessmaskbuf ) );
 #endif
 
+       /* Is this ACL only for a specific value? */
+       if ( a->acl_attrval.bv_len ) {
+               if ( state && !state->as_vd_acl ) {
+                       state->as_vd_acl = a;
+                       state->as_vd_access = a->acl_access;
+                       state->as_vd_access_count = 1;
+               }
+               if ( val == NULL ) {
+                       return ACL_BREAK;
+               }
+               if ( a->acl_attrval_style == ACL_STYLE_REGEX ) {
+#ifdef NEW_LOGGING
+                       LDAP_LOG( ACL, DETAIL1, 
+                               "acl_get: valpat %s\n",
+                               a->acl_attrval.bv_val, 0, 0 );
+#else
+                       Debug( LDAP_DEBUG_ACL,
+                               "acl_get: valpat %s\n",
+                               a->acl_attrval.bv_val, 0, 0 );
+#endif
+                       if (regexec(&a->acl_attrval_re, val->bv_val, 0, NULL, 0))
+                               return ACL_BREAK;
+               } else {
+                       int match = 0;
+                       const char *text;
+#ifdef NEW_LOGGING
+                       LDAP_LOG( ACL, DETAIL1, 
+                               "acl_get: val %s\n",
+                               a->acl_attrval.bv_val, 0, 0 );
+#else
+                       Debug( LDAP_DEBUG_ACL,
+                               "acl_get: val %s\n",
+                               a->acl_attrval.bv_val, 0, 0 );
+#endif
+                       if (value_match( &match, desc,
+                               desc->ad_type->sat_equality, 0,
+                               val, &a->acl_attrval, &text ) != LDAP_SUCCESS ||
+                                       match )
+                               return ACL_BREAK;
+               }
+       }
+
        if( state && ( state->as_recorded & ACL_STATE_RECORDED_VD )
                && state->as_vd_acl == a )
        {
index 581d447f112d9f6b2fb5bf5eb7265c644e4cd285..206b6053ff70ceb6873db16ee67eba387cb50a6c 100644 (file)
@@ -233,6 +233,36 @@ parse_acl(
                                                acl_usage();
                                        }
 
+                               } else if ( strncasecmp( left, "val", 3 ) == 0 ) {
+                                       if ( a->acl_attrval.bv_len ) {
+                                               fprintf( stderr,
+                               "%s: line %d: attr val already specified in to clause.\n",
+                                                       fname, lineno );
+                                               acl_usage();
+                                       }
+                                       if ( a->acl_attrs == NULL || a->acl_attrs[1].an_name.bv_val ) {
+                                               fprintf( stderr,
+                               "%s: line %d: attr val requires a single attribute.\n",
+                                                       fname, lineno );
+                                               acl_usage();
+                                       }
+                                       ber_str2bv( right, 0, 1, &a->acl_attrval );
+                                       if ( style && strcasecmp( style, "regex" ) == 0 ) {
+                                               int e = regcomp( &a->acl_attrval_re, a->acl_attrval.bv_val,
+                                                       REG_EXTENDED | REG_ICASE | REG_NOSUB );
+                                               if ( e ) {
+                                                       char buf[512];
+                                                       regerror( e, &a->acl_attrval_re, buf, sizeof(buf) );
+                                                       fprintf( stderr, "%s: line %d: "
+                                                               "regular expression \"%s\" bad because of %s\n",
+                                                               fname, lineno, right, buf );
+                                                       acl_usage();
+                                               }
+                                               a->acl_attrval_style = ACL_STYLE_REGEX;
+                                       } else {
+                                               a->acl_attrval_style = ACL_STYLE_BASE;
+                                       }
+                                       
                                } else {
                                        fprintf( stderr,
                                                "%s: line %d: expecting <what> got \"%s\"\n",
@@ -1298,7 +1328,7 @@ acl_usage( void )
                "<access clause> ::= access to <what> "
                                "[ by <who> <access> [ <control> ] ]+ \n"
                "<what> ::= * | [dn[.<dnstyle>]=<DN>] [filter=<filter>] [attrs=<attrlist>]\n"
-               "<attrlist> ::= <attr> | <attr> , <attrlist>\n"
+               "<attrlist> ::= <attr> [val[.<style>]=<value>] | <attr> , <attrlist>\n"
                "<attr> ::= <attrname> | entry | children\n"
                "<who> ::= [ * | anonymous | users | self | dn[.<dnstyle>]=<DN> ]\n"
                        "\t[dnattr=<attrname>]\n"
@@ -1654,6 +1684,13 @@ print_acl( Backend *be, AccessControl *a )
                fprintf(  stderr, "\n" );
        }
 
+       if ( a->acl_attrval.bv_len != 0 ) {
+               to++;
+               fprintf( stderr, " val.%s=%s\n",
+                       style_strings[a->acl_attrval_style], a->acl_attrval.bv_val );
+
+       }
+
        if( !to ) {
                fprintf( stderr, " *\n" );
        }
index 156ef3a225f4b355125cc310f555802e341f1936..3367a8e3eff636993df155df4ac73fa8f8a03cb4 100644 (file)
@@ -1173,6 +1173,9 @@ typedef struct slap_acl {
        regex_t         acl_dn_re;
        struct berval   acl_dn_pat;
        AttributeName   *acl_attrs;
+       slap_style_t    acl_attrval_style;
+       regex_t         acl_attrval_re;
+       struct berval   acl_attrval;
 
        /* "by" part: list of who has what access to the entries */
        Access  *acl_access;