mirror of
https://git.openldap.org/openldap/openldap.git
synced 2024-12-21 03:10:25 +08:00
ITS#2497, implement value-level ACLs:
access to attr=foo val.regex=bar.*
This commit is contained in:
parent
8f3d3cf3c9
commit
1240c70ff4
@ -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 )
|
||||
{
|
||||
|
@ -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" );
|
||||
}
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user