mirror of
https://git.openldap.org/openldap/openldap.git
synced 2024-12-21 03:10:25 +08:00
add to 'val[.<style>=<value>' ACLs special match styles for DN-valued attributes; add negated objectClass to attribute name lists for ACLs and partial replication
This commit is contained in:
parent
6e6bef8f56
commit
ee34f3fb64
@ -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,
|
||||
|
@ -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;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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:
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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 );
|
||||
|
Loading…
Reference in New Issue
Block a user