]> git.sur5r.net Git - openldap/commitdiff
add to 'val[.<style>=<value>' ACLs special match styles for DN-valued attributes...
authorPierangelo Masarati <ando@openldap.org>
Tue, 16 Dec 2003 00:49:10 +0000 (00:49 +0000)
committerPierangelo Masarati <ando@openldap.org>
Tue, 16 Dec 2003 00:49:10 +0000 (00:49 +0000)
doc/man/man5/slapd.access.5
servers/slapd/acl.c
servers/slapd/aclparse.c
servers/slapd/ad.c
servers/slapd/back-bdb/search.c
servers/slapd/controls.c
servers/slapd/repl.c
servers/slapd/search.c
servers/slapd/sessionlog.c
servers/slapd/slap.h
servers/slapd/slapi/slapi_ops.c

index 219a5addaaddd991b90e55db3305f80e7e149a09..e1496e29f2286008d7ec13213639b3665008b374 100644 (file)
@@ -74,7 +74,7 @@ It can have the forms
        *
        [dn[.<dnstyle>]=<DN>] 
        [filter=<ldapfilter>]
-       [attrs=<attrlist>]
+       [attrs=<attrlist>[ val[.<style>]=<attrval>]]
 .fi
 .LP
 The wildcard
@@ -124,6 +124,20 @@ indicating access to the entry itself, and
 indicating access to the entry's children. ObjectClass names may also
 be specified in this list, which will affect all the attributes that
 are required and/or allowed by that objectClass.
+Actually, names in 
+.B <attrlist>
+that are prefixed by
+.B +
+are directly treated as objectClass names, while names that 
+do not correspond to an attribute type are also searched 
+in the objectclass set.
+This latter behavior is deprecated and might not be supported
+in future releases.
+A name prefixed by
+.B !
+is also treated as an objectClass, but in this case the access rule
+affects the attributes that are not required nor allowed 
+by that objectClass.
 .LP
 Using the form
 .B attrs=<attr> val[.<style>]=<value>
@@ -133,11 +147,20 @@ In this case, only a single attribute type may be given. A value
 of
 .B exact
 (the default) uses the attribute's equality matching rule to compare the
-value. If the
+value. If the value
 .B <style>
 is
 .BR regex ,
 the provided value is used as a regular expression pattern.
+If the attribute has DN syntax, the value
+.B <style>
+can be any of
+.BR base ,
+.BR onelevel ,
+.B subtree
+or
+.BR children ,
+resulting in base, onelevel, subtree or children match, respectively.
 .LP
 The dn, filter, and attrs statements are additive; they can be used in sequence 
 to select entities the access rule applies to based on naming context,
index c648d4ef6fb6dcabf90ac232bfe29f5b718c7231..dae8743f1734a2405e10e0cf36f389477c50b70c 100644 (file)
@@ -668,11 +668,70 @@ acl_mask(
                                "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 ( a->acl_attrs[0].an_desc->ad_type->sat_syntax != slap_schema.si_syn_distinguishedName ) {
+                               if (value_match( &match, desc,
+                                       desc->ad_type->sat_equality, 0,
+                                       val, &a->acl_attrval, &text ) != LDAP_SUCCESS ||
+                                               match )
+                                       return ACL_BREAK;
+                               
+                       } else {
+                               int             patlen, vdnlen, rc, got_match = 0;
+                               struct berval   vdn = { 0, NULL };
+
+                               /* it is a DN */
+                               assert( a->acl_attrs[0].an_desc->ad_type->sat_syntax == slap_schema.si_syn_distinguishedName );
+
+                               rc = dnNormalize( 0, NULL, NULL, val, &vdn,
+                                               op->o_tmpmemctx );
+                               if ( rc != LDAP_SUCCESS ) {
+                                       /* error */
+                                       return ACL_BREAK;
+                               }
+
+                               patlen = a->acl_attrval.bv_len;
+                               vdnlen = vdn.bv_len;
+
+                               if ( vdnlen < patlen )
+                                       goto attrval_cleanup;
+
+                               if ( a->acl_dn_style == ACL_STYLE_BASE ) {
+                                       if ( vdnlen > patlen )
+                                               goto attrval_cleanup;
+
+                               } else if ( a->acl_dn_style == ACL_STYLE_ONE ) {
+                                       int rdnlen = -1;
+
+                                       if ( !DN_SEPARATOR( vdn.bv_val[vdnlen - patlen - 1] ) )
+                                               goto attrval_cleanup;
+
+                                       rdnlen = dn_rdnlen( NULL, &vdn );
+                                       if ( rdnlen != vdnlen - patlen - 1 )
+                                               goto attrval_cleanup;
+
+                               } else if ( a->acl_dn_style == ACL_STYLE_SUBTREE ) {
+                                       if ( vdnlen > patlen && !DN_SEPARATOR( vdn.bv_val[vdnlen - patlen - 1] ) )
+                                               goto attrval_cleanup;
+
+                               } else if ( a->acl_dn_style == ACL_STYLE_CHILDREN ) {
+                                       if ( vdnlen <= patlen )
+                                               goto attrval_cleanup;
+
+                                       if ( !DN_SEPARATOR( vdn.bv_val[vdnlen - patlen - 1] ) )
+                                               goto attrval_cleanup;
+                               }
+
+                               got_match = strcmp( a->acl_attrval.bv_val, vdn.bv_val + vdnlen - patlen );
+
+attrval_cleanup:;
+                               if ( vdn.bv_val )
+                                       free( vdn.bv_val );
+
+                               if ( !got_match )
+                                       return ACL_BREAK;
+                               
+                       }
                }
        }
 
index f559ae3e1c7d9f69936e1538072907e7a0738ed1..383f0b9d3d9979feba0644f8239aa187d2ed749e 100644 (file)
@@ -279,7 +279,33 @@ parse_acl(
                                                }
                                                a->acl_attrval_style = ACL_STYLE_REGEX;
                                        } else {
-                                               a->acl_attrval_style = ACL_STYLE_BASE;
+                                               /* FIXME: if the attribute has DN syntax,
+                                                * we might allow subtree and children styles as well */
+                                               if ( !strcasecmp( style, "exact" ) ) {
+                                                       a->acl_attrval_style = ACL_STYLE_BASE;
+
+                                               } else if ( a->acl_attrs[0].an_desc->ad_type->sat_syntax == slap_schema.si_syn_distinguishedName ) {
+                                                       if ( !strcasecmp( style, "base" ) ) {
+                                                               a->acl_attrval_style = ACL_STYLE_BASE;
+                                                       } else if ( !strcasecmp( style, "children" ) ) {
+                                                               a->acl_attrval_style = ACL_STYLE_CHILDREN;
+                                                       } else if ( !strcasecmp( style, "onelevel" ) || !strcasecmp( style, "one" ) ) {
+                                                               a->acl_attrval_style = ACL_STYLE_ONE;
+                                                       } else if ( !strcasecmp( style, "subtree" ) || !strcasecmp( style, "sub" ) ) {
+                                                               a->acl_attrval_style = ACL_STYLE_SUBTREE;
+                                                       } else {
+                                                               fprintf( stderr, 
+                                                                       "%s: line %d: unknown val.<style>, got \"%s\" (ignored)\n",
+                                                                           fname, lineno, style );
+                                                               a->acl_attrval_style = ACL_STYLE_BASE;
+                                                       }
+                                                       
+                                               } else {
+                                                       fprintf( stderr, 
+                                                               "%s: line %d: unknown val.<style>, got \"%s\" (ignored)\n",
+                                                                   fname, lineno, style );
+                                                       a->acl_attrval_style = ACL_STYLE_BASE;
+                                               }
                                        }
                                        
                                } else {
@@ -1692,6 +1718,9 @@ print_acl( Backend *be, AccessControl *a )
                        if ( ! first ) {
                                fprintf( stderr, "," );
                        }
+                       if (an->an_oc) {
+                               fputc( an->an_oc_exclude ? '!' : '+', stderr);
+                       }
                        fputs( an->an_name.bv_val, stderr );
                        first = 0;
                }
index db1eb06d2a6038e384e6bd0b75718172cc557ab8..51399c39345306ff4ac2c68cd082ad2d311a8437 100644 (file)
@@ -537,12 +537,18 @@ int ad_inlist(
                oc = attrs->an_oc;
                if( oc == NULL && attrs->an_name.bv_val ) {
                        switch( attrs->an_name.bv_val[0] ) {
-                       case '+': { /* new way */
+                       case '+': /* new way */
+                       case '!': { /* exclude */
                                        struct berval ocname;
                                        ocname.bv_len = attrs->an_name.bv_len - 1;
                                        ocname.bv_val = &attrs->an_name.bv_val[1];
                                        oc = oc_bvfind( &ocname );
+                                       attrs->an_oc_exclude = 0;
+                                       if ( oc && attrs->an_name.bv_val[0] == '!' ) {
+                                               attrs->an_oc_exclude = 1;
+                                       }
                                } break;
+
                        default: /* old (deprecated) way */
                                oc = oc_bvfind( &attrs->an_name );
                        }
@@ -689,7 +695,8 @@ an_find(
  * add on to an existing list if it was given.  If the string
  * is not a valid attribute name, if a '-' is prepended it is 
  * skipped and the remaining name is tried again; if a '+' is
- * prepended, an objectclass name is searched instead.
+ * prepended, an objectclass name is searched instead; if a
+ * '!' is prepended, the objectclass name is negated.
  * 
  * NOTE: currently, if a valid attribute name is not found,
  * the same string is also checked as valid objectclass name;
@@ -727,6 +734,7 @@ str2anlist( AttributeName *an, char *in, const char *brkstr )
        {
                anew->an_desc = NULL;
                anew->an_oc = NULL;
+               anew->an_oc_exclude = 0;
                ber_str2bv(s, 0, 1, &anew->an_name);
                slap_bv2ad(&anew->an_name, &anew->an_desc, &text);
                if ( !anew->an_desc ) {
@@ -747,7 +755,8 @@ str2anlist( AttributeName *an, char *in, const char *brkstr )
                                        }
                                } break;
 
-                       case '+': {
+                       case '+':
+                       case '!': {
                                        struct berval ocname;
                                        ocname.bv_len = anew->an_name.bv_len - 1;
                                        ocname.bv_val = &anew->an_name.bv_val[1];
@@ -761,6 +770,10 @@ str2anlist( AttributeName *an, char *in, const char *brkstr )
                                                strcpy( in, s );
                                                return NULL;
                                        }
+
+                                       if ( anew->an_name.bv_val[0] == '!' ) {
+                                               anew->an_oc_exclude = 1;
+                                       }
                                } break;
 
                        default:
index 3d498b7e31319e873e65687342f78c195a664713..98c23d2309f18d870e989374140acc5035e185ce 100644 (file)
@@ -481,6 +481,7 @@ bdb_do_search( Operation *op, SlapReply *rs, Operation *sop,
 
        null_attr.an_desc = NULL;
        null_attr.an_oc = NULL;
+       null_attr.an_oc_exclude = 0;
        null_attr.an_name.bv_len = 0;
        null_attr.an_name.bv_val = NULL;
 
@@ -493,6 +494,7 @@ bdb_do_search( Operation *op, SlapReply *rs, Operation *sop,
                attrs = uuid_attr;
                attrs[0].an_desc = NULL;
                attrs[0].an_oc = NULL;
+               attrs[0].an_oc_exclude = 0;
                attrs[0].an_name.bv_len = 0;
                attrs[0].an_name.bv_val = NULL;
        }
index 1ede30038f801a69dea0035ed98969a8e9321ddc..530857c47830dbbf001ffadfa898fa204f3c62b0 100644 (file)
@@ -1018,10 +1018,17 @@ static int parsePreRead (
        }
 
        for( i=0; i<siz; i++ ) {
-               const char *dummy;
+               int             rc = LDAP_SUCCESS;
+               const char      *dummy = NULL;
+
                an[i].an_desc = NULL;
                an[i].an_oc = NULL;
-               slap_bv2ad( &an[i].an_name, &an[i].an_desc, &dummy );
+               an[i].an_oc_exclude = 0;
+               rc = slap_bv2ad( &an[i].an_name, &an[i].an_desc, &dummy );
+               if ( rc != LDAP_SUCCESS && ctrl->ldctl_iscritical ) {
+                       rs->sr_text = dummy ? dummy : "postread control: unknown attributeType";
+                       return rc;
+               }
        }
 
        op->o_preread = ctrl->ldctl_iscritical
@@ -1067,10 +1074,17 @@ static int parsePostRead (
        }
 
        for( i=0; i<siz; i++ ) {
-               const char *dummy;
+               int             rc = LDAP_SUCCESS;
+               const char      *dummy = NULL;
+
                an[i].an_desc = NULL;
                an[i].an_oc = NULL;
-               slap_bv2ad( &an[i].an_name, &an[i].an_desc, &dummy );
+               an[i].an_oc_exclude = 0;
+               rc = slap_bv2ad( &an[i].an_name, &an[i].an_desc, &dummy );
+               if ( rc != LDAP_SUCCESS && ctrl->ldctl_iscritical ) {
+                       rs->sr_text = dummy ? dummy : "postread control: unknown attributeType";
+                       return rc;
+               }
        }
 
        op->o_postread = ctrl->ldctl_iscritical
index 0e5f69e3f7cd4ba27537a8c88111958aaef59038..6683515ca1deebbd542a1080df5c6235966271d7 100644 (file)
@@ -344,6 +344,7 @@ replog1(
                                if ( ( !is_in && !ri->ri_exclude ) || ( is_in && ri->ri_exclude ) ) {
                                        continue;
                                }
+
                                /* If the list includes objectClass names,
                                 * only include those classes in the
                                 * objectClass attribute
@@ -357,11 +358,27 @@ replog1(
                                        for ( an = ri->ri_attrs; an->an_name.bv_val; an++ ) {
                                                if ( an->an_oc ) {
                                                        int i;
+
+                                                       /* FIXME: need to 
+                                                        * handle 
+                                                        * an_oc_exclude */
                                                        for ( i=0; a->a_vals[i].bv_val; i++ ) {
-                                                               if ( a->a_vals[i].bv_len == an->an_name.bv_len
-                                                                       && !strcasecmp(a->a_vals[i].bv_val,
-                                                                               an->an_name.bv_val ) ) {
-                                                                       ocs = 1;
+                                                               if ( an->an_oc_exclude ) {
+                                                                       if ( a->a_vals[i].bv_len != an->an_name.bv_len
+                                                                               || strcasecmp(a->a_vals[i].bv_val,
+                                                                                       an->an_name.bv_val ) ) {
+                                                                               ocs = 1;
+                                                                       }
+
+                                                               } else {
+                                                                       if ( a->a_vals[i].bv_len == an->an_name.bv_len
+                                                                               && !strcasecmp(a->a_vals[i].bv_val,
+                                                                                       an->an_name.bv_val ) ) {
+                                                                               ocs = 1;
+                                                                       }
+                                                               }
+
+                                                               if ( ocs )  {
                                                                        vals[0] = an->an_name;
                                                                        print_vals( fp, &a->a_desc->ad_cname, vals );
                                                                        break;
index 816df11c40041e09535737d48ae5f8bc0e8d92a3..d842c6419b7420db6ede11d184395fd4f4bb5e65 100644 (file)
@@ -177,6 +177,7 @@ do_search(
                const char *dummy;      /* ignore msgs from bv2ad */
                op->ors_attrs[i].an_desc = NULL;
                op->ors_attrs[i].an_oc = NULL;
+               op->ors_attrs[i].an_oc_exclude = 0;
                slap_bv2ad(&op->ors_attrs[i].an_name, &op->ors_attrs[i].an_desc, &dummy);
        }
 
index edcd5f9f4996cc6e981158da2642638d4a853360..d2b1242a548d8017825a4429093cc188fbf020bb 100644 (file)
@@ -45,6 +45,7 @@ slap_send_session_log(
 
        uuid_attr[0].an_desc = NULL;
        uuid_attr[0].an_oc = NULL;
+       uuid_attr[0].an_oc_exclude = NULL;
        uuid_attr[0].an_name.bv_len = 0;
        uuid_attr[0].an_name.bv_val = NULL;
        e.e_attrs = NULL;
index 7dc3b219a779c8f24e03193665bdf4b0e71a8a78..07eef92ae4ab564ef2dbfe92c628c6676c3e23d9 100644 (file)
@@ -720,6 +720,7 @@ typedef struct slap_attr_desc {
 typedef struct slap_attr_name {
        struct berval an_name;
        AttributeDescription *an_desc;
+       int an_oc_exclude;
        ObjectClass *an_oc;
 } AttributeName;
 
index f423d550e6d89c7cc17cbd4637e5d0f1d967817b..8cfc95d74c745c8b5aadd60397f22bda3c4d1a85 100644 (file)
@@ -1152,6 +1152,7 @@ slapi_search_internal_bind(
                for (i = 0; attrs[i] != 0; i++) {
                        an[i].an_desc = NULL;
                        an[i].an_oc = NULL;
+                       an[i].an_oc_exclude = 0;
                        an[i].an_name.bv_val = slapi_ch_strdup(attrs[i]);
                        an[i].an_name.bv_len = strlen(attrs[i]);
                        slap_bv2ad( &an[i].an_name, &an[i].an_desc, &text );