From 1240c70ff4aceb57e99a2bd3b64a514053eeeb77 Mon Sep 17 00:00:00 2001 From: Howard Chu Date: Sat, 20 Sep 2003 03:23:10 +0000 Subject: [PATCH] ITS#2497, implement value-level ACLs: access to attr=foo val.regex=bar.* --- servers/slapd/acl.c | 53 +++++++++++++++++++++++++++++++++++++--- servers/slapd/aclparse.c | 39 ++++++++++++++++++++++++++++- servers/slapd/slap.h | 3 +++ 3 files changed, 90 insertions(+), 5 deletions(-) diff --git a/servers/slapd/acl.c b/servers/slapd/acl.c index 5b1f0434b8..17f4459e00 100644 --- a/servers/slapd/acl.c +++ b/servers/slapd/acl.c @@ -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 ) { diff --git a/servers/slapd/aclparse.c b/servers/slapd/aclparse.c index 581d447f11..206b6053ff 100644 --- a/servers/slapd/aclparse.c +++ b/servers/slapd/aclparse.c @@ -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 got \"%s\"\n", @@ -1298,7 +1328,7 @@ acl_usage( void ) " ::= access to " "[ by [ ] ]+ \n" " ::= * | [dn[.]=] [filter=] [attrs=]\n" - " ::= | , \n" + " ::= [val[.