Initial commit of new ACL engine. Engine supports descrete access

privs, additive/substractive rules, and rule continuation.  Existing
rules that use 'defaultaccess none' should be 100% compatible.  Rules
that rely other defaultaccess settings will require addition of
explicit clauses granting the access.
Needs additional testing and tuning of logs
This commit is contained in:
Kurt Zeilenga 1999-10-21 17:53:56 +00:00
parent 10e886a601
commit f6829ee903
11 changed files with 742 additions and 352 deletions

View file

@ -67,13 +67,11 @@ overridden in a backend definition. Arguments that should be replaced by
actual text are shown in brackets <>.
.TP
.B
access to <what> [ by <who> <accesslevel> ]+
Grant access (specified by <accesslevel>) to a set of entries and/or
access to <what> [ by <who> <access> <control> ]+
Grant access (specified by <access>) to a set of entries and/or
attributes (specified by <what>) by one or more requestors (specified
by <who>). Refer to "The SLAPD and SLURPD Administrator's Guide" for
information on using the
.B slapd
access-control mechanisms.
by <who>).
See Developer's FAQ (http://www.openldap.org/faq/) for details.
.TP
.B
attributetype ( <oid> [NAME <name>] [DESC <description>] [OBSOLETE] \
@ -136,9 +134,13 @@ distinguished name
.RE
.TP
.B
defaultaccess [self]{ none | compare | search | read | write }
Specify the default access to grant requestors not matched by
any other access line. The default behavior is to grant read access.
defaultaccess { none | auth | compare | search | read | write }
Specify the default access level to grant requestors when
no access directives were provided for the database.
The default behavior is to grant 'read' access. It is
recommended that
.B access
directives be used instead.
.TP
.B idletimeout <integer>
Specify the number of seconds to wait before forcibly closing

View file

@ -15,9 +15,24 @@
#include "slap.h"
static AccessControl * acl_get(
AccessControl *ac, int *count,
Backend *be, Operation *op,
Entry *e, char *attr,
int nmatches, regmatch_t *matches );
static slap_control_t acl_mask(
AccessControl *ac, slap_access_mask_t *mask,
Backend *be, Connection *conn, Operation *op,
Entry *e, char *attr, struct berval *val,
regmatch_t *matches );
#ifdef SLAPD_ACI_ENABLED
int aci_access_allowed (struct berval *aci, char *attr, Backend *be, Entry *e,
Operation *op, int access, char *edn, regmatch_t *matches);
static int aci_access_allowed(
Backend *be,
Operation *op,
Entry *e, char *attr, struct berval *aci,
regmatch_t *matches );
#endif
static int regex_matches(char *pat, char *str, char *buf, regmatch_t *matches);
@ -28,12 +43,16 @@ static void string_expand(char *newbuf, int bufsiz, char *pattern,
/*
* access_allowed - check whether op->o_ndn is allowed the requested access
* to entry e, attribute attr, value val. if val is null, access to
* the whole attribute is assumed (all values). this routine finds
* the applicable acl and calls acl_access_allowed() to make the
* decision.
* the whole attribute is assumed (all values).
*
* returns 0 access NOT allowed
* 1 access allowed
* This routine loops through all access controls and calls
* acl_mask() on each applicable access control.
* The loop exits when a definitive answer is reached or
* or no more controls remain.
*
* returns:
* 0 access denied
* 1 access granted
*/
int
@ -44,105 +63,167 @@ access_allowed(
Entry *e,
char *attr,
struct berval *val,
int access
slap_access_t access
)
{
int rc;
int count;
AccessControl *a;
char *edn;
slap_access_mask_t mask;
slap_control_t control;
regmatch_t matches[MAXREMATCHES];
int i;
int n;
if ( be == NULL ) {
return( 0 );
Debug( LDAP_DEBUG_ACL,
"=> access_allowed: %s access to \"%s\" \"%s\" requested\n",
access2str( access ),
e->e_dn, attr );
assert( be != NULL );
assert( e != NULL );
assert( attr != NULL );
assert( access > ACL_NONE );
/* grant database root access */
if ( be != NULL && be_isroot( be, op->o_ndn ) ) {
Debug( LDAP_DEBUG_ACL,
"<= root access granted\n",
0, 0, 0 );
return 1;
}
edn = e->e_ndn;
Debug( LDAP_DEBUG_ACL, "\n=> access_allowed: entry (%s) attr (%s)\n",
e->e_dn, attr, 0 );
/* the lastmod attributes are ignored by ACL checking */
/* no user modify operational attributes are ignored by ACL checking */
if ( oc_check_no_usermod_attr( attr ) ) {
Debug( LDAP_DEBUG_ACL, "Operational attribute: %s access allowed\n",
Debug( LDAP_DEBUG_ACL, "NoUserMod Operational attribute:"
" %s access granted\n",
attr, 0, 0 );
return(1);
return 1;
}
/* use backend default access if no backend acls */
if( be != NULL && be->be_acl == NULL ) {
Debug( LDAP_DEBUG_ACL,
"=> access_allowed: backend default %s access %s to \"%s\"\n",
access2str( access ),
be->be_dfltaccess >= access ? "granted" : "denied", op->o_dn );
return be->be_dfltaccess >= access;
#ifdef notdef
/* be is always non-NULL */
/* use global default access if no global acls */
} else if ( be == NULL && global_acl == NULL ) {
Debug( LDAP_DEBUG_ACL,
"=> access_allowed: global default %s access %s to \"%s\"\n",
access2str( access ),
global_default_access >= access ? "granted" : "denied", op->o_dn );
return global_default_access >= access;
#endif
}
ACL_INIT(mask);
memset(matches, 0, sizeof(matches));
control = ACL_BREAK;
a = NULL;
count = 0;
a = acl_get_applicable( be, op, e, attr, MAXREMATCHES, matches );
while( a = acl_get( a, &count, be, op, e, attr, MAXREMATCHES, matches ) )
{
int i;
if (a) {
for (i = 0; i < MAXREMATCHES && matches[i].rm_so > 0; i++) {
Debug( LDAP_DEBUG_ARGS, "=> match[%d]: %d %d ", i,
Debug( LDAP_DEBUG_ACL, "=> match[%d]: %d %d ", i,
(int)matches[i].rm_so, (int)matches[i].rm_eo );
if( matches[i].rm_so <= matches[0].rm_eo ) {
int n;
for ( n = matches[i].rm_so; n < matches[i].rm_eo; n++) {
Debug( LDAP_DEBUG_ARGS, "%c", edn[n], 0, 0 );
Debug( LDAP_DEBUG_ACL, "%c", e->e_ndn[n], 0, 0 );
}
}
Debug( LDAP_DEBUG_ARGS, "\n", 0, 0, 0 );
}
control = acl_mask( a, &mask, be, conn, op,
e, attr, val, matches );
if ( control != ACL_BREAK ) {
break;
}
memset(matches, 0, sizeof(matches));
}
rc = acl_access_allowed( a, attr, be, conn, e, val, op, access, edn, matches );
if ( ACL_IS_INVALID( mask ) ) {
Debug( LDAP_DEBUG_ACL,
"=> access_allowed: \"%s\" (%s) invalid!\n",
e->e_dn, attr, 0 );
ACL_INIT( mask );
Debug( LDAP_DEBUG_ACL, "\n=> access_allowed: exit (%s) attr (%s)\n",
e->e_dn, attr, 0);
} else if ( control == ACL_BREAK ) {
Debug( LDAP_DEBUG_ACL,
"=> access_allowed: no more rules\n", 0, 0, 0);
ACL_INIT( mask );
}
return( rc );
Debug( LDAP_DEBUG_ACL,
"=> access_allowed: %s access %s to \"%s\"\n",
access2str( access ),
ACL_GRANT(mask, access) ? "granted" : "denied", op->o_dn );
return ACL_GRANT(mask, access);
}
/*
* acl_get_applicable - return the acl applicable to entry e, attribute
* acl_get - return the acl applicable to entry e, attribute
* attr. the acl returned is suitable for use in subsequent calls to
* acl_access_allowed().
*/
AccessControl *
acl_get_applicable(
static AccessControl *
acl_get(
AccessControl *a,
int *count,
Backend *be,
Operation *op,
Operation *op,
Entry *e,
char *attr,
int nmatch,
regmatch_t *matches
)
{
int i;
AccessControl *a;
char *edn;
AccessControl *next;
Debug( LDAP_DEBUG_ACL, "\n=> acl_get: entry (%s) attr (%s)\n",
e->e_dn, attr, 0 );
assert( e != NULL );
assert( count != NULL );
if ( be_isroot( be, op->o_ndn ) ) {
Debug( LDAP_DEBUG_ACL,
"<= acl_get: no acl applicable to database root\n", 0, 0,
0 );
return( NULL );
if( a == NULL ) {
if( be == NULL ) {
a = global_acl;
} else {
a = be->be_acl;
}
assert( a != NULL );
} else {
a = a->acl_next;
}
edn = e->e_ndn;
for ( ; a != NULL; a = a->acl_next ) {
(*count) ++;
Debug( LDAP_DEBUG_ARGS, "=> acl_get: edn %s\n", edn, 0, 0 );
/* check for a backend-specific acl that matches the entry */
for ( i = 1, a = be->be_acl; a != NULL; a = a->acl_next, i++ ) {
if (a->acl_dn_pat != NULL) {
Debug( LDAP_DEBUG_TRACE, "=> dnpat: [%d] %s nsub: %d\n",
i, a->acl_dn_pat, (int) a->acl_dn_re.re_nsub);
Debug( LDAP_DEBUG_ACL, "=> dnpat: [%d] %s nsub: %d\n",
*count, a->acl_dn_pat, (int) a->acl_dn_re.re_nsub );
if (regexec(&a->acl_dn_re, edn, nmatch, matches, 0)) {
if (regexec(&a->acl_dn_re, e->e_ndn, nmatch, matches, 0)) {
continue;
} else {
Debug( LDAP_DEBUG_TRACE, "=> acl_get:[%d] backend ACL match\n",
i, 0, 0);
Debug( LDAP_DEBUG_ACL, "=> acl_get: ACL [%d] matched\n",
*count, 0, 0);
}
}
@ -152,58 +233,27 @@ acl_get_applicable(
}
}
Debug( LDAP_DEBUG_ARGS, "=> acl_get: [%d] check attr %s\n", i, attr, 0);
Debug( LDAP_DEBUG_ACL, "=> acl_get: [%d] check attr %s\n",
*count, attr, 0);
if ( attr == NULL || a->acl_attrs == NULL ||
charray_inlist( a->acl_attrs, attr ) )
{
Debug( LDAP_DEBUG_ACL, "<= acl_get: [%d] backend acl %s attr: %s\n",
i, e->e_dn, attr );
return( a );
Debug( LDAP_DEBUG_ACL,
"<= acl_get: [%d] acl %s attr: %s\n",
*count, e->e_dn, attr );
return a;
}
matches[0].rm_so = matches[0].rm_eo = -1;
}
/* check for a global acl that matches the entry */
for ( i = 1, a = global_acl; a != NULL; a = a->acl_next, i++ ) {
if (a->acl_dn_pat != NULL) {
Debug( LDAP_DEBUG_TRACE, "=> dn pat: [%d] %s nsub: %d\n",
i, a->acl_dn_pat, (int) a->acl_dn_re.re_nsub);
if (regexec(&a->acl_dn_re, edn, nmatch, matches, 0)) {
continue;
} else {
Debug( LDAP_DEBUG_TRACE, "=> acl_get: [%d] global ACL match\n",
i, 0, 0);
}
}
if ( a->acl_filter != NULL ) {
if ( test_filter( NULL, NULL, NULL, e, a->acl_filter ) != 0 ) {
continue;
}
}
Debug( LDAP_DEBUG_ARGS, "=> acl_get: [%d] check attr\n", i, 0, 0);
if ( attr == NULL || a->acl_attrs == NULL ||
charray_inlist( a->acl_attrs, attr ) )
{
Debug( LDAP_DEBUG_ACL, "<= acl_get: [%d] global acl %s attr: %s\n",
i, e->e_dn, attr );
return( a );
}
matches[0].rm_so = matches[0].rm_eo = -1;
}
Debug( LDAP_DEBUG_ACL, "<= acl_get: no match\n", 0, 0, 0 );
Debug( LDAP_DEBUG_ACL, "<= acl_get: done.\n", 0, 0, 0 );
return( NULL );
}
/*
* acl_access_allowed - check whether the given acl allows dn the
* acl_mask - modifies mask based upon the given acl and the
* requested access to entry e, attribute attr, value val. if val
* is null, access to the whole attribute is assumed (all values).
*
@ -211,54 +261,43 @@ acl_get_applicable(
* 1 access allowed
*/
int
acl_access_allowed(
static slap_control_t
acl_mask(
AccessControl *a,
char *attr,
slap_access_mask_t *mask,
Backend *be,
Connection *conn,
Connection *conn,
Operation *op,
Entry *e,
char *attr,
struct berval *val,
Operation *op,
int access,
char *edn,
regmatch_t *matches
)
{
int i;
Access *b;
int default_access;
assert( a != NULL );
assert( mask != NULL );
Debug( LDAP_DEBUG_ACL,
"\n=> acl_access_allowed: %s access to entry \"%s\"\n",
access2str( access ), e->e_dn, 0 );
"=> acl_mask: access to entry \"%s\", attr \"%s\"\n requested\n",
e->e_dn, attr, 0 );
Debug( LDAP_DEBUG_ACL,
"\n=> acl_access_allowed: %s access to value \"%s\" by \"%s\"\n",
access2str( access ),
"=> acl_mask: to value \"%s\" by \"%s\", (%s) \n",
val ? val->bv_val : "any",
op->o_ndn ? op->o_ndn : "" );
if ( be_isroot( be, op->o_ndn ) ) {
Debug( LDAP_DEBUG_ACL,
"<= acl_access_allowed: granted to database root\n",
0, 0, 0 );
return( 1 );
}
default_access = be->be_dfltaccess ? be->be_dfltaccess : global_default_access;
if ( a == NULL ) {
Debug( LDAP_DEBUG_ACL,
"<= acl_access_allowed: %s by default (no matching to)\n",
default_access >= access ? "granted" : "denied", 0, 0 );
return( default_access >= access );
}
op->o_ndn ? op->o_ndn : "",
accessmask2str( *mask ) );
for ( i = 1, b = a->acl_access; b != NULL; b = b->a_next, i++ ) {
slap_access_mask_t oldmask, modmask;
ACL_INVALIDATE( modmask );
/* AND <who> clauses */
if ( b->a_dn_pat != NULL ) {
Debug( LDAP_DEBUG_TRACE, "<= check a_dn_pat: %s\n",
Debug( LDAP_DEBUG_ACL, "<= check a_dn_pat: %s\n",
b->a_dn_pat, 0, 0);
/*
* if access applies to the entry itself, and the
@ -275,60 +314,60 @@ acl_access_allowed(
continue;
}
if ( e->e_dn == NULL || strcmp( edn, op->o_ndn ) != 0 ) {
if ( e->e_dn == NULL || strcmp( e->e_ndn, op->o_ndn ) != 0 ) {
continue;
}
} else if ( strcmp( b->a_dn_pat, ".*" ) != 0 &&
!regex_matches( b->a_dn_pat, op->o_ndn, edn, matches ) )
!regex_matches( b->a_dn_pat, op->o_ndn, e->e_ndn, matches ) )
{
continue;
}
}
if ( b->a_sockurl_pat != NULL ) {
Debug( LDAP_DEBUG_ARGS, "<= check a_sockurl_pat: %s\n",
Debug( LDAP_DEBUG_ACL, "<= check a_sockurl_pat: %s\n",
b->a_sockurl_pat, 0, 0 );
if ( strcmp( b->a_sockurl_pat, ".*" ) != 0 &&
!regex_matches( b->a_sockurl_pat, conn->c_listener_url,
edn, matches ) )
e->e_ndn, matches ) )
{
continue;
}
}
if ( b->a_domain_pat != NULL ) {
Debug( LDAP_DEBUG_ARGS, "<= check a_domain_pat: %s\n",
Debug( LDAP_DEBUG_ACL, "<= check a_domain_pat: %s\n",
b->a_domain_pat, 0, 0 );
if ( strcmp( b->a_domain_pat, ".*" ) != 0 &&
!regex_matches( b->a_domain_pat, conn->c_peer_domain,
edn, matches ) )
e->e_ndn, matches ) )
{
continue;
}
}
if ( b->a_peername_pat != NULL ) {
Debug( LDAP_DEBUG_ARGS, "<= check a_peername_path: %s\n",
Debug( LDAP_DEBUG_ACL, "<= check a_peername_path: %s\n",
b->a_peername_pat, 0, 0 );
if ( strcmp( b->a_peername_pat, ".*" ) != 0 &&
!regex_matches( b->a_peername_pat, conn->c_peer_name,
edn, matches ) )
e->e_ndn, matches ) )
{
continue;
}
}
if ( b->a_sockname_pat != NULL ) {
Debug( LDAP_DEBUG_ARGS, "<= check a_sockname_path: %s\n",
Debug( LDAP_DEBUG_ACL, "<= check a_sockname_path: %s\n",
b->a_sockname_pat, 0, 0 );
if ( strcmp( b->a_sockname_pat, ".*" ) != 0 &&
!regex_matches( b->a_sockname_pat, conn->c_sock_name,
edn, matches ) )
e->e_ndn, matches ) )
{
continue;
}
@ -338,7 +377,7 @@ acl_access_allowed(
Attribute *at;
struct berval bv;
Debug( LDAP_DEBUG_ARGS, "<= check a_dn_at: %s\n",
Debug( LDAP_DEBUG_ACL, "<= check a_dn_at: %s\n",
b->a_dn_at, 0, 0);
bv.bv_val = op->o_ndn;
@ -348,14 +387,14 @@ acl_access_allowed(
if ( (at = attr_find( e->e_attrs, b->a_dn_at )) != NULL &&
value_find( at->a_vals, &bv, at->a_syntax, 3 ) == 0 )
{
if ( ACL_IS_SELF(b->a_access) &&
if ( b->a_dn_self &&
(val == NULL || value_cmp( &bv, val, at->a_syntax, 2 )) )
{
continue;
}
/* asker not listed in dnattr - check for self access */
} else if ( ! ACL_IS_SELF(b->a_access) || val == NULL ||
} else if ( ! b->a_dn_self || val == NULL ||
value_cmp( &bv, val, at->a_syntax, 2 ) != 0 )
{
continue;
@ -370,7 +409,7 @@ acl_access_allowed(
* the values in the attribute group
*/
/* see if asker is listed in dnattr */
string_expand(buf, sizeof(buf), b->a_group_pat, edn, matches);
string_expand(buf, sizeof(buf), b->a_group_pat, e->e_ndn, matches);
if ( dn_normalize(buf) == NULL ) {
/* did not expand to a valid dn */
continue;
@ -384,12 +423,12 @@ acl_access_allowed(
}
#ifdef SLAPD_ACI_ENABLED
if ( b->a_aci_at != NULL ) {
if ( b->a_aci_at != NULL ) {
Attribute *at;
/* this case works different from the others above.
* since aci's themselves give permissions, we need
* to first check b->a_access, the ACL's access level.
* to first check b->a_mask, the ACL's access level.
*/
if( op->o_ndn == NULL || op->o_ndn[0] == '\0' ) {
@ -403,7 +442,7 @@ acl_access_allowed(
/* first check if the right being requested is
* higher than allowed by the ACL clause.
*/
if ( ! ACL_GRANT( b->a_access, access ) ) {
if ( ! ACL_GRANT( b->a_mask, access ) ) {
continue;
}
@ -418,39 +457,71 @@ acl_access_allowed(
* rights given by the acis.
*/
for ( i = 0; at->a_vals[i] != NULL; i++ ) {
if ( aci_access_allowed( at->a_vals[i], attr, be, e, op, access, edn, matches ) ) {
if ( aci_access_allowed( be, op,
e, attr, at->a_vals[i],
matches ) )
{
Debug( LDAP_DEBUG_ACL,
"<= acl_access_allowed: matched by clause #%d access granted\n",
"<= acl_mask: matched by clause #%d access granted\n",
i, 0, 0 );
return(1);
break;
}
}
continue;
}
if( ACL_IS_INVALID( modmask ) ) {
continue;
}
} else
#endif
{
modmask = b->a_mask;
}
Debug( LDAP_DEBUG_ACL,
"<= acl_access_allowed: matched by clause #%d access %s\n",
i,
ACL_GRANT(b->a_access, access) ? "granted" : "denied",
0 );
"<= acl_mask: matched clause #%d\n",
i, 0, 0 );
return ACL_GRANT(b->a_access, access );
oldmask = *mask;
if( ACL_IS_ADDITIVE(modmask) ) {
ACL_PRIV_CLR( *mask, ACL_PRIV_LEVEL );
ACL_PRIV_SET( *mask, modmask );
} else if( ACL_IS_SUBTRACTIVE(modmask) ) {
ACL_PRIV_CLR( *mask, ACL_PRIV_LEVEL );
ACL_PRIV_CLR( *mask, modmask );
} else {
ACL_PRIV_ASSIGN( *mask, modmask );
}
Debug( LDAP_DEBUG_ACL,
"<= acl_mask: old (%s) mod (%s) new (%s)\n",
accessmask2str(oldmask),
accessmask2str(modmask),
accessmask2str(*mask) );
if( b->a_type == ACL_CONTINUE ) {
continue;
} else if ( b->a_type == ACL_BREAK ) {
return ACL_BREAK;
} else {
break;
}
}
Debug( LDAP_DEBUG_ACL,
"<= acl_access_allowed: %s by default (no matching by)\n",
default_access >= access ? "granted" : "denied", 0, 0 );
return( default_access >= access );
return ACL_STOP;
}
/*
* acl_check_modlist - check access control on the given entry to see if
* it allows the given modifications by the user associated with op.
* returns LDAP_SUCCESS mods allowed ok
* anything else mods not allowed - return is an error
* code indicating the problem
* returns 1 if mods allowed ok
* 0 mods not allowed
*/
int
@ -463,8 +534,38 @@ acl_check_modlist(
)
{
int i;
AccessControl *a;
char *edn = e->e_ndn;
assert( be != NULL );
/* short circuit root database access */
if ( be_isroot( be, op->o_ndn ) ) {
Debug( LDAP_DEBUG_ACL,
"<= acl_access_allowed: granted to database root\n",
0, 0, 0 );
return 1;
}
/* use backend default access if no backend acls */
if( be != NULL && be->be_acl == NULL ) {
Debug( LDAP_DEBUG_ACL,
"=> access_allowed: backend default %s access %s to \"%s\"\n",
access2str( ACL_WRITE ),
be->be_dfltaccess >= ACL_WRITE ? "granted" : "denied", op->o_dn );
return be->be_dfltaccess >= ACL_WRITE;
#ifdef notdef
/* be is always non-NULL */
/* use global default access if no global acls */
} else if ( be == NULL && global_acl == NULL ) {
Debug( LDAP_DEBUG_ACL,
"=> access_allowed: global default %s access %s to \"%s\"\n",
access2str( ACL_WRITE ),
global_default_access >= ACL_WRITE ? "granted" : "denied", op->o_dn );
return global_default_access >= ACL_WRITE;
#endif
}
for ( ; mlist != NULL; mlist = mlist->ml_next ) {
regmatch_t matches[MAXREMATCHES];
@ -476,9 +577,6 @@ acl_check_modlist(
continue;
}
a = acl_get_applicable( be, op, e, mlist->ml_type,
MAXREMATCHES, matches );
switch ( mlist->ml_op & ~LDAP_MOD_BVALUES ) {
case LDAP_MOD_REPLACE:
case LDAP_MOD_ADD:
@ -486,35 +584,38 @@ acl_check_modlist(
break;
}
for ( i = 0; mlist->ml_bvalues[i] != NULL; i++ ) {
if ( ! acl_access_allowed( a, mlist->ml_type, be, conn, e, mlist->ml_bvalues[i],
op, ACL_WRITE, edn, matches) )
if ( ! access_allowed( be, conn, op, e,
mlist->ml_type, mlist->ml_bvalues[i],
ACL_WRITE ) )
{
return( LDAP_INSUFFICIENT_ACCESS );
return( 0 );
}
}
break;
case LDAP_MOD_DELETE:
if ( mlist->ml_bvalues == NULL ) {
if ( ! acl_access_allowed( a, mlist->ml_type, be, conn, e,
NULL, op, ACL_WRITE, edn, matches) )
if ( ! access_allowed( be, conn, op, e,
mlist->ml_type, NULL,
ACL_WRITE ) )
{
return( LDAP_INSUFFICIENT_ACCESS );
return( 0 );
}
break;
}
for ( i = 0; mlist->ml_bvalues[i] != NULL; i++ ) {
if ( ! acl_access_allowed( a, mlist->ml_type, be, conn, e, mlist->ml_bvalues[i],
op, ACL_WRITE, edn, matches) )
if ( ! access_allowed( be, conn, op, e,
mlist->ml_type, mlist->ml_bvalues[i],
ACL_WRITE ) )
{
return( LDAP_INSUFFICIENT_ACCESS );
return( 0 );
}
}
break;
}
}
return( LDAP_SUCCESS );
return( 1 );
}
#ifdef SLAPD_ACI_ENABLED
@ -583,10 +684,14 @@ aci_get_part (struct berval *list, int ix, char sep, struct berval *bv)
}
static int
aci_list_has_right (struct berval *list, int access, int action)
aci_list_has_right(
struct berval *list,
slap_access_t access,
int action)
{
struct berval bv;
int i, right;
int i;
slap_access_t right;
for (i = 0; aci_get_part(list, i, ',', &bv) >= 0; i++) {
if (bv.bv_len <= 0)
@ -680,7 +785,10 @@ aci_list_has_attr_right (struct berval *list, char *attr, int access, int action
}
static int
aci_list_has_permission (struct berval *list, char *attr, int access)
aci_list_has_permission(
struct berval *list,
char *attr,
slap_access_t access)
{
struct berval perm, actn;
int i, action, specific, general;
@ -720,7 +828,6 @@ aci_group_member (
Backend *be,
Entry *e,
Operation *op,
char *edn,
regmatch_t *matches
)
{
@ -747,7 +854,7 @@ aci_group_member (
grpdn = (char *)ch_malloc(1024);
if (grpoc != NULL && grpat != NULL && grpdn != NULL) {
string_expand(grpdn, 1024, subjdn, edn, matches);
string_expand(grpdn, 1024, subjdn, e->e_ndn, matches);
if ( dn_normalize(grpdn) != NULL ) {
rc = (backend_group(be, e, grpdn, op->o_ndn, grpoc, grpat) == 0);
}
@ -761,15 +868,14 @@ aci_group_member (
return(rc);
}
int
static int
aci_access_allowed (
struct berval *aci,
char *attr,
Backend *be,
Entry *e,
Operation *op,
int access,
char *edn,
slap_access_t access,
regmatch_t *matches
)
{
@ -778,11 +884,11 @@ aci_access_allowed (
int rc;
Debug( LDAP_DEBUG_ACL,
"\n=> aci_access_allowed: %s access to entry \"%s\"\n",
"=> aci_access_allowed: %s access to entry \"%s\"\n",
access2str( access ), e->e_dn, 0 );
Debug( LDAP_DEBUG_ACL,
"\n=> aci_access_allowed: %s access to attribute \"%s\" by \"%s\"\n",
"=> aci_access_allowed: %s access to attribute \"%s\" by \"%s\"\n",
access2str( access ),
attr,
op->o_ndn ? op->o_ndn : "" );
@ -833,15 +939,15 @@ aci_access_allowed (
}
if (aci_strbvcmp( "self", &bv ) == 0) {
return(strcasecmp(op->o_ndn, edn) == 0);
return(strcasecmp(op->o_ndn, e->e_ndn) == 0);
}
if (aci_strbvcmp( "group", &bv ) == 0) {
return(aci_group_member(&sdn, "groupOfNames", "member", be, e, op, edn, matches));
return(aci_group_member(&sdn, "groupOfNames", "member", be, e, op, matches));
}
if (aci_strbvcmp( "role", &bv ) == 0) {
return(aci_group_member(&sdn, "organizationalRole", "roleOccupant", be, e, op, edn, matches));
return(aci_group_member(&sdn, "organizationalRole", "roleOccupant", be, e, op, matches));
}
return(0);

View file

@ -18,11 +18,11 @@
#include "slap.h"
static void split(char *line, int splitchar, char **left, char **right);
static void acl_append(AccessControl **l, AccessControl *a);
static void access_append(Access **l, Access *a);
static void acl_usage(void) LDAP_GCCATTR((noreturn));
#ifdef LDAP_DEBUG
static void print_acl(AccessControl *a);
static void print_acl(Backend *be, AccessControl *a);
static void print_access(Access *b);
#endif
@ -179,12 +179,15 @@ parse_acl(
fname, lineno );
acl_usage();
}
/*
* by clause consists of <who> and <access>
*/
b = (Access *) ch_calloc( 1, sizeof(Access) );
ACL_INVALIDATE( b->a_mask );
if ( ++i == argc ) {
fprintf( stderr,
"%s: line %d: premature eol: expecting <who>\n",
@ -344,16 +347,92 @@ parse_acl(
}
#endif
/* get <access> */
if ( ACL_IS_INVALID(ACL_SET(b->a_access, str2access( left ))) ) {
fprintf( stderr,
"%s: line %d: expecting <access> got \"%s\"\n",
fname, lineno, left );
acl_usage();
if( right != NULL ) {
/* unsplit */
right[-1] = '=';
}
access_append( &a->acl_access, b );
break;
}
if( i == argc || ( strcasecmp( left, "stop" ) == 0 )) {
/* out of arguments or plain stop */
ACL_PRIV_ASSIGN(b->a_mask, ACL_NONE);
b->a_type = ACL_STOP;
access_append( &a->acl_access, b );
continue;
}
if( strcasecmp( left, "continue" ) == 0 ) {
/* plain continue */
ACL_PRIV_ASSIGN(b->a_mask, ACL_NONE);
b->a_type = ACL_CONTINUE;
access_append( &a->acl_access, b );
continue;
}
if( strcasecmp( left, "break" ) == 0 ) {
/* plain continue */
ACL_PRIV_ASSIGN(b->a_mask, ACL_NONE);
b->a_type = ACL_BREAK;
access_append( &a->acl_access, b );
continue;
}
if ( strcasecmp( left, "by" ) == 0 ) {
/* we've gone too far */
--i;
ACL_PRIV_ASSIGN(b->a_mask, ACL_NONE);
b->a_type = ACL_STOP;
access_append( &a->acl_access, b );
continue;
}
/* get <access> */
if( strncasecmp( left, "self", 4 ) == 0 ) {
b->a_dn_self = 1;
ACL_PRIV_ASSIGN( b->a_mask, str2accessmask( &left[4] ) );
} else {
ACL_PRIV_ASSIGN( b->a_mask, str2accessmask( left ) );
}
if( ACL_IS_INVALID( b->a_mask ) ) {
fprintf( stderr,
"%s: line %d: expecting <access> got \"%s\"\n",
fname, lineno, left );
acl_usage();
}
b->a_type = ACL_STOP;
if( ++i == argc ) {
/* out of arguments or plain stop */
access_append( &a->acl_access, b );
continue;
}
if( strcasecmp( argv[i], "continue" ) == 0 ) {
/* plain continue */
b->a_type = ACL_CONTINUE;
} else if( strcasecmp( argv[i], "break" ) == 0 ) {
/* plain continue */
b->a_type = ACL_BREAK;
} else if ( strcasecmp( argv[i], "stop" ) != 0 ) {
/* gone to far */
i--;
}
access_append( &a->acl_access, b );
} else {
fprintf( stderr,
"%s: line %d: expecting \"to\" or \"by\" got \"%s\"\n",
@ -372,7 +451,7 @@ parse_acl(
#ifdef LDAP_DEBUG
if (ldap_debug & LDAP_DEBUG_ACL)
print_acl(a);
print_acl(be, a);
#endif
if ( a->acl_access == NULL ) {
@ -390,72 +469,165 @@ parse_acl(
}
char *
access2str( int access )
accessmask2str( slap_access_mask_t mask )
{
static char buf[12];
static char buf[sizeof("unknown (+wrsca0)")];
int none=1;
if ( ACL_IS_SELF( access ) ) {
strcpy( buf, "self" );
} else {
buf[0] = '\0';
if ( ACL_IS_INVALID( mask ) ) {
return "invalid";
}
if ( ACL_IS_NONE(access) ) {
strcat( buf, "none" );
} else if ( ACL_IS_AUTH(access) ) {
strcat( buf, "auth" );
} else if ( ACL_IS_COMPARE(access) ) {
strcat( buf, "compare" );
} else if ( ACL_IS_SEARCH(access) ) {
strcat( buf, "search" );
} else if ( ACL_IS_READ(access) ) {
strcat( buf, "read" );
} else if ( ACL_IS_WRITE(access) ) {
strcat( buf, "write" );
buf[0] = '\0';
} else {
strcat( buf, "unknown" );
if ( ACL_IS_LEVEL( mask ) ) {
if ( ACL_LVL_IS_NONE(mask) ) {
strcat( buf, "none" );
} else if ( ACL_LVL_IS_AUTH(mask) ) {
strcat( buf, "auth" );
} else if ( ACL_LVL_IS_COMPARE(mask) ) {
strcat( buf, "compare" );
} else if ( ACL_LVL_IS_SEARCH(mask) ) {
strcat( buf, "search" );
} else if ( ACL_LVL_IS_READ(mask) ) {
strcat( buf, "read" );
} else if ( ACL_LVL_IS_WRITE(mask) ) {
strcat( buf, "write" );
} else {
strcat( buf, "unknown" );
}
strcat(buf, " (");
}
return( buf );
if( ACL_IS_ADDITIVE( mask ) ) {
strcat( buf, "+" );
} else if( ACL_IS_SUBTRACTIVE( mask ) ) {
strcat( buf, "-" );
} else {
strcat( buf, "=" );
}
if ( ACL_PRIV_ISSET(mask, ACL_PRIV_WRITE) ) {
none = 0;
strcat( buf, "w" );
}
if ( ACL_PRIV_ISSET(mask, ACL_PRIV_READ) ) {
none = 0;
strcat( buf, "r" );
}
if ( ACL_PRIV_ISSET(mask, ACL_PRIV_SEARCH) ) {
none = 0;
strcat( buf, "s" );
}
if ( ACL_PRIV_ISSET(mask, ACL_PRIV_COMPARE) ) {
none = 0;
strcat( buf, "c" );
}
if ( ACL_PRIV_ISSET(mask, ACL_PRIV_AUTH) ) {
none = 0;
strcat( buf, "x" );
}
if ( none && ACL_PRIV_ISSET(mask, ACL_PRIV_NONE) ) {
strcat( buf, "0" );
}
if ( ACL_IS_LEVEL( mask ) ) {
strcat(buf, ")");
}
return buf;
}
int
str2access( char *str )
slap_access_mask_t
str2accessmask( const char *str )
{
int access;
slap_access_mask_t mask;
ACL_CLR(access);
if( !isalpha(str[0]) ) {
int i;
if ( strncasecmp( str, "self", 4 ) == 0 ) {
ACL_SET_SELF(access);
str += 4;
if ( str[0] == '=' ) {
ACL_INIT(mask);
} else if( str[0] == '+' ) {
ACL_PRIV_ASSIGN(mask, ACL_PRIV_ADDITIVE);
} else if( str[0] == '-' ) {
ACL_PRIV_ASSIGN(mask, ACL_PRIV_SUBSTRACTIVE);
} else {
ACL_INVALIDATE(mask);
return mask;
}
for( i=1; str[i] != '\0'; i++ ) {
if( TOLOWER(str[i]) == 'w' ) {
ACL_PRIV_SET(mask, ACL_PRIV_WRITE);
} else if( TOLOWER(str[0]) == 'r' ) {
ACL_PRIV_SET(mask, ACL_PRIV_READ);
} else if( TOLOWER(str[0]) == 's' ) {
ACL_PRIV_SET(mask, ACL_PRIV_SEARCH);
} else if( TOLOWER(str[0]) == 'c' ) {
ACL_PRIV_SET(mask, ACL_PRIV_COMPARE);
} else if( TOLOWER(str[0]) == 'x' ) {
ACL_PRIV_SET(mask, ACL_PRIV_AUTH);
} else {
ACL_INVALIDATE(mask);
return mask;
}
}
return mask;
}
if ( strcasecmp( str, "none" ) == 0 ) {
ACL_SET_NONE(access);
ACL_LVL_ASSIGN_NONE(mask);
} else if ( strcasecmp( str, "auth" ) == 0 ) {
ACL_SET_AUTH(access);
ACL_LVL_ASSIGN_AUTH(mask);
} else if ( strcasecmp( str, "compare" ) == 0 ) {
ACL_SET_COMPARE(access);
ACL_LVL_ASSIGN_COMPARE(mask);
} else if ( strcasecmp( str, "search" ) == 0 ) {
ACL_SET_SEARCH(access);
ACL_LVL_ASSIGN_SEARCH(mask);
} else if ( strcasecmp( str, "read" ) == 0 ) {
ACL_SET_READ(access);
ACL_LVL_ASSIGN_READ(mask);
} else if ( strcasecmp( str, "write" ) == 0 ) {
ACL_SET_WRITE(access);
ACL_LVL_ASSIGN_WRITE(mask);
} else {
ACL_SET_INVALID(access);
ACL_INVALIDATE( mask );
}
return( access );
return mask;
}
static void
acl_usage( void )
{
fprintf( stderr, "\n"
"<access clause> ::= access to <what> [ by <who> <access> ]+ \n"
"<access clause> ::= access to <what> "
"[ by <who> <access> <control> ]+ \n"
"<what> ::= * | [dn=<regex>] [filter=<ldapfilter>] [attrs=<attrlist>]\n"
"<attrlist> ::= <attr> | <attr> , <attrlist>\n"
"<attr> ::= <attrname> | entry | children\n"
@ -467,7 +639,10 @@ acl_usage( void )
#ifdef SLAPD_ACI_ENABLED
"\t[aci=<attrname>]\n"
#endif
"<access> ::= [self]{none|auth|compare|search|read|write}\n"
"<access> ::= [self]{<level>|<priv>}\n"
"<level> ::= none | auth | compare | search | read | write\n"
"<priv> ::= {=|+|-}{w|r|s|c|x}+\n"
"<control> ::= [ stop | continue | break ]\n"
);
exit( EXIT_FAILURE );
}
@ -495,7 +670,7 @@ access_append( Access **l, Access *a )
*l = a;
}
static void
void
acl_append( AccessControl **l, AccessControl *a )
{
for ( ; *l != NULL; l = &(*l)->acl_next )
@ -542,6 +717,7 @@ print_access( Access *b )
if ( b->a_peername_pat != NULL ) {
fprintf( stderr, " peername=%s", b->a_peername_pat );
}
if ( b->a_sockname_pat != NULL ) {
fprintf( stderr, " sockname=%s", b->a_sockname_pat );
}
@ -560,31 +736,91 @@ print_access( Access *b )
}
#endif
fprintf( stderr, " %s%s",
b->a_dn_self ? "self" : "",
accessmask2str( b->a_mask ) );
fprintf( stderr, "\n" );
}
static void
print_acl( AccessControl *a )
char *
access2str( slap_access_t access )
{
int i;
if ( access == ACL_NONE ) {
return "none";
} else if ( access == ACL_AUTH ) {
return "auth";
} else if ( access == ACL_COMPARE ) {
return "compare";
} else if ( access == ACL_SEARCH ) {
return "search";
} else if ( access == ACL_READ ) {
return "read";
} else if ( access == ACL_WRITE ) {
return "write";
}
return "unknown";
}
slap_access_t
str2access( const char *str )
{
if ( strcasecmp( str, "none" ) == 0 ) {
return ACL_NONE;
} else if ( strcasecmp( str, "auth" ) == 0 ) {
return ACL_AUTH;
} else if ( strcasecmp( str, "compare" ) == 0 ) {
return ACL_COMPARE;
} else if ( strcasecmp( str, "search" ) == 0 ) {
return ACL_SEARCH;
} else if ( strcasecmp( str, "read" ) == 0 ) {
return ACL_READ;
} else if ( strcasecmp( str, "write" ) == 0 ) {
return ACL_WRITE;
}
return( ACL_INVALID_ACCESS );
}
static void
print_acl( Backend *be, AccessControl *a )
{
int to = 0;
Access *b;
if ( a == NULL ) {
fprintf( stderr, "NULL\n" );
}
fprintf( stderr, "ACL: access to" );
if ( a->acl_filter != NULL ) {
fprintf( stderr," filter=" );
filter_print( a->acl_filter );
}
if ( a->acl_dn_pat != NULL ) {
fprintf( stderr, " dn=" );
fprintf( stderr, a->acl_dn_pat );
}
if ( a->acl_attrs != NULL ) {
int first = 1;
fprintf( stderr, "%s ACL: access to",
be == NULL ? "Global" : "Backend" );
fprintf( stderr, "\n attrs=" );
if ( a->acl_dn_pat != NULL ) {
to++;
fprintf( stderr, " dn=%s\n",
a->acl_dn_pat );
}
if ( a->acl_filter != NULL ) {
to++;
fprintf( stderr, " filter=" );
filter_print( a->acl_filter );
fprintf( stderr, "\n" );
}
if ( a->acl_attrs != NULL ) {
int i, first = 1;
to++;
fprintf( stderr, " attrs=" );
for ( i = 0; a->acl_attrs[i] != NULL; i++ ) {
if ( ! first ) {
fprintf( stderr, "," );
@ -592,11 +828,17 @@ print_acl( AccessControl *a )
fprintf( stderr, a->acl_attrs[i] );
first = 0;
}
fprintf( stderr, "\n" );
}
fprintf( stderr, "\n" );
if( !to ) {
fprintf( stderr, " *\n" );
}
for ( b = a->acl_access; b != NULL; b = b->a_next ) {
print_access( b );
}
fprintf( stderr, "\n" );
}

View file

@ -28,8 +28,8 @@ bdb2i_back_modify_internal(
Debug(LDAP_DEBUG_ARGS, "bdb2i_back_modify:\n", 0, 0, 0);
if ( (err = acl_check_modlist( be, conn, op, e, modlist )) != LDAP_SUCCESS ) {
send_ldap_result( conn, op, err,
if ( !acl_check_modlist( be, conn, op, e, modlist )) {
send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS,
NULL, NULL, NULL, NULL );
goto error_return;
}

View file

@ -38,10 +38,8 @@ int ldbm_modify_internal(
Attribute *a;
Attribute *save_attrs;
if ( (err = acl_check_modlist( be, conn, op, e, modlist ))
!= LDAP_SUCCESS )
{
send_ldap_result( conn, op, err,
if ( !acl_check_modlist( be, conn, op, e, modlist )) {
send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS,
NULL, NULL, NULL, NULL );
return -1;
}

View file

@ -222,6 +222,9 @@ int backend_startup(Backend *be)
/* open each backend database */
for( i = 0; i < nBackendDB; i++ ) {
/* append global access controls */
acl_append( &backendDB[i].be_acl, global_acl );
if ( backendDB[i].bd_info->bi_db_open ) {
rc = backendDB[i].bd_info->bi_db_open(
&backendDB[i] );
@ -376,6 +379,7 @@ backend_db_init(
be->bd_info = bi;
be->be_sizelimit = defsize;
be->be_timelimit = deftime;
be->be_dfltaccess = global_default_access;
/* assign a default depth limit for alias deref */
be->be_max_deref_depth = SLAPD_DEFAULT_MAXDEREFDEPTH;

View file

@ -27,7 +27,7 @@
int defsize = SLAPD_DEFAULT_SIZELIMIT;
int deftime = SLAPD_DEFAULT_TIMELIMIT;
AccessControl *global_acl = NULL;
int global_default_access = ACL_AUTH;
slap_access_t global_default_access = ACL_READ;
int global_readonly = 0;
char *replogfile;
int global_lastmod = ON;
@ -478,31 +478,29 @@ read_config( const char *fname )
/* specify default access control info */
} else if ( strcasecmp( cargv[0], "defaultaccess" ) == 0 ) {
slap_access_t access;
if ( cargc < 2 ) {
Debug( LDAP_DEBUG_ANY,
"%s: line %d: missing limit in \"defaultaccess <access>\" line\n",
fname, lineno, 0 );
return( 1 );
}
access = str2access( cargv[1] );
if ( access == ACL_INVALID_ACCESS ) {
Debug( LDAP_DEBUG_ANY,
"%s: line %d: bad access level \"%s\", "
"expecting none|auth|compare|search|read|write\n",
fname, lineno, cargv[1] );
return( 1 );
}
if ( be == NULL ) {
if ( ACL_IS_INVALID(ACL_SET(global_default_access,
str2access(cargv[1]))) )
{
Debug( LDAP_DEBUG_ANY,
"%s: line %d: bad access \"%s\" expecting [self]{none|auth|compare|search|read|write}\n",
fname, lineno, cargv[1] );
return( 1 );
}
global_default_access = access;
} else {
if ( ACL_IS_INVALID(ACL_SET(be->be_dfltaccess,
str2access(cargv[1]))) )
{
Debug( LDAP_DEBUG_ANY,
"%s: line %d: bad access \"%s\", "
"expecting [self]{none|auth|compare|search|read|write}\n",
fname, lineno, cargv[1] );
return( 1 );
}
be->be_dfltaccess = access;
}
/* debug level to log things to syslog */

View file

@ -16,16 +16,7 @@ LDAP_BEGIN_DECL
int access_allowed LDAP_P(( Backend *be, Connection *conn,
Operation *op, Entry *e,
char *attr, struct berval *val, int access ));
AccessControl * acl_get_applicable LDAP_P(( Backend *be,
Operation *op, Entry *e,
char *attr, int nmatches, regmatch_t *matches ));
int acl_access_allowed LDAP_P((
AccessControl *a, char *attr, Backend *be, Connection *conn, Entry *e,
struct berval *val, Operation *op, int access, char *edn,
regmatch_t *matches ));
char *attr, struct berval *val, slap_access_t access ));
int acl_check_modlist LDAP_P(( Backend *be,
Connection *conn,
@ -33,6 +24,8 @@ int acl_check_modlist LDAP_P(( Backend *be,
Entry *e,
LDAPModList *ml ));
void acl_append( AccessControl **l, AccessControl *a );
/*
* aclparse.c
*/
@ -41,8 +34,12 @@ void parse_acl LDAP_P(( Backend *be,
const char *fname,
int lineno,
int argc, char **argv ));
char * access2str LDAP_P(( int access ));
int str2access LDAP_P(( char *str ));
char * access2str LDAP_P(( slap_access_t access ));
slap_access_t str2access LDAP_P(( const char *str ));
char * accessmask2str LDAP_P(( slap_access_mask_t mask ));
slap_access_mask_t str2accessmask LDAP_P(( const char *str ));
/*
* attr.c
@ -432,7 +429,7 @@ extern int active_threads;
extern int defsize;
extern int deftime;
extern int g_argc;
extern int global_default_access;
extern slap_access_t global_default_access;
extern int global_readonly;
extern int global_lastmod;
extern int global_idletimeout;

View file

@ -572,12 +572,11 @@ send_search_entry(
}
}
acl = acl_get_applicable( be, op, e, a->a_type,
MAXREMATCHES, matches );
if ( ! acl_access_allowed( acl, a->a_type, be, conn, e,
NULL, op, ACL_READ, edn, matches ) )
if ( ! access_allowed( be, conn, op, e,
a->a_type, NULL, ACL_READ ) )
{
Debug( LDAP_DEBUG_ACL, "acl: access to attribute %s not allowed\n",
a->a_type, 0, 0 );
continue;
}
@ -591,10 +590,12 @@ send_search_entry(
if ( ! attrsonly ) {
for ( i = 0; a->a_vals[i] != NULL; i++ ) {
if ( a->a_syntax & SYNTAX_DN &&
! acl_access_allowed( acl, a->a_type, be, conn, e, a->a_vals[i], op,
ACL_READ, edn, matches) )
if ( ! access_allowed( be, conn, op, e,
a->a_type, a->a_vals[i], ACL_READ ) )
{
Debug( LDAP_DEBUG_ACL,
"acl: access to attribute %s, value %d not allowed\n",
a->a_type, i, 0 );
continue;
}
@ -647,12 +648,11 @@ send_search_entry(
}
}
acl = acl_get_applicable( be, op, e, a->a_type,
MAXREMATCHES, matches );
if ( ! acl_access_allowed( acl, a->a_type, be, conn, e,
NULL, op, ACL_READ, edn, matches ) )
if ( ! access_allowed( be, conn, op, e,
a->a_type, NULL, ACL_READ ) )
{
Debug( LDAP_DEBUG_ACL, "acl: access to attribute %s not allowed\n",
a->a_type, 0, 0 );
continue;
}
@ -666,13 +666,16 @@ send_search_entry(
if ( ! attrsonly ) {
for ( i = 0; a->a_vals[i] != NULL; i++ ) {
if ( a->a_syntax & SYNTAX_DN &&
! acl_access_allowed( acl, a->a_type, be, conn, e, a->a_vals[i], op,
ACL_READ, edn, matches) )
if ( ! access_allowed( be, conn, op, e,
a->a_type, a->a_vals[i], ACL_READ ) )
{
Debug( LDAP_DEBUG_ACL,
"acl: access to attribute %s, value %d not allowed\n",
a->a_type, i, 0 );
continue;
}
if (( rc = ber_printf( ber, "O", a->a_vals[i] )) == -1 ) {
Debug( LDAP_DEBUG_ANY,
"ber_printf failed\n", 0, 0, 0 );

View file

@ -226,49 +226,91 @@ typedef struct slap_entry {
* represents an access control list
*/
typedef enum slap_access_e {
ACL_INVALID_ACCESS = -1,
ACL_NONE = 0,
ACL_AUTH,
ACL_COMPARE,
ACL_SEARCH,
ACL_READ,
ACL_WRITE
} slap_access_t;
typedef enum slap_control_e {
ACL_INVALID_CONTROL = 0,
ACL_STOP,
ACL_CONTINUE,
ACL_BREAK
} slap_control_t;
typedef unsigned long slap_access_mask_t;
/* the "by" part */
typedef struct slap_access {
slap_control_t a_type;
#define ACL_NONE 0x0001
#define ACL_AUTH 0x0004
#define ACL_COMPARE 0x0008
#define ACL_SEARCH 0x0010
#define ACL_READ 0x0020
#define ACL_WRITE 0x0040
#define ACL_PRIV_MASK 0x00ff
#define ACL_ACCESS2PRIV(access) (0x01U << (access))
#define ACL_SELF 0x4000
#define ACL_INVALID (-1)
#define ACL_PRIV_NONE ACL_ACCESS2PRIV( ACL_NONE )
#define ACL_PRIV_AUTH ACL_ACCESS2PRIV( ACL_AUTH )
#define ACL_PRIV_COMPARE ACL_ACCESS2PRIV( ACL_COMPARE )
#define ACL_PRIV_SEARCH ACL_ACCESS2PRIV( ACL_SEARCH )
#define ACL_PRIV_READ ACL_ACCESS2PRIV( ACL_READ )
#define ACL_PRIV_WRITE ACL_ACCESS2PRIV( ACL_WRITE )
#define ACL_IS(a,lvl) (((a) & (lvl)) == (lvl))
#define ACL_PRIV_MASK 0x00ffUL
#define ACL_IS_NONE(a) ACL_IS((a),ACL_SELF)
#define ACL_IS_AUTH(a) ACL_IS((a),ACL_AUTH)
#define ACL_IS_COMPARE(a) ACL_IS((a),ACL_COMPARE)
#define ACL_IS_SEARCH(a) ACL_IS((a),ACL_SEARCH)
#define ACL_IS_READ(a) ACL_IS((a),ACL_READ)
#define ACL_IS_WRITE(a) ACL_IS((a),ACL_WRITE)
#define ACL_IS_SELF(a) ACL_IS((a),ACL_SELF)
#define ACL_IS_INVALID(a) ((a) == ACL_INVALID)
/* priv flags */
#define ACL_PRIV_LEVEL 0x1000UL
#define ACL_PRIV_ADDITIVE 0x2000UL
#define ACL_PRIV_SUBSTRACTIVE 0x4000UL
#define ACL_CLR(a) ((a) = 0)
#define ACL_SET(a,lvl) ((a) |= (lvl))
#define ACL_SET_NONE(a) ACL_SET((a),ACL_SELF)
#define ACL_SET_AUTH(a) ACL_SET((a),ACL_AUTH)
#define ACL_SET_COMPARE(a) ACL_SET((a),ACL_COMPARE)
#define ACL_SET_SEARCH(a) ACL_SET((a),ACL_SEARCH)
#define ACL_SET_READ(a) ACL_SET((a),ACL_READ)
#define ACL_SET_WRITE(a) ACL_SET((a),ACL_WRITE)
#define ACL_SET_SELF(a) ACL_SET((a),ACL_SELF)
#define ACL_SET_INVALID(a) ((a) = ACL_INVALID)
/* invalid privs */
#define ACL_PRIV_INVALID 0x0UL
#define ACL_PRIV(a) ((a) & ACL_PRIV_MASK)
#define ACL_GRANT(a,lvl) (ACL_PRIV(a) >= (lvl))
#define ACL_PRIV_ISSET(m,p) (((m) & (p)) == (p))
#define ACL_PRIV_ASSIGN(m,p) do { (m) = (p); } while(0)
#define ACL_PRIV_SET(m,p) do { (m) |= (p); } while(0)
#define ACL_PRIV_CLR(m,p) do { (m) &= ~(p); } while(0)
int a_access;
#define ACL_INIT(m) ACL_PRIV_ASSIGN(m, ACL_PRIV_NONE)
#define ACL_INVALIDATE(m) ACL_PRIV_ASSIGN(m, ACL_PRIV_INVALID)
#define ACL_GRANT(m,a) ACL_PRIV_ISSET((m),ACL_ACCESS2PRIV(a))
#define ACL_IS_INVALID(m) ((m) == ACL_PRIV_INVALID)
#define ACL_IS_LEVEL(m) ACL_PRIV_ISSET((m),ACL_PRIV_LEVEL)
#define ACL_IS_ADDITIVE(m) ACL_PRIV_ISSET((m),ACL_PRIV_ADDITIVE)
#define ACL_IS_SUBTRACTIVE(m) ACL_PRIV_ISSET((m),ACL_PRIV_SUBSTRACTIVE)
#define ACL_LVL_NONE (ACL_PRIV_NONE|ACL_PRIV_LEVEL)
#define ACL_LVL_AUTH (ACL_PRIV_AUTH|ACL_LVL_NONE)
#define ACL_LVL_COMPARE (ACL_PRIV_COMPARE|ACL_LVL_AUTH)
#define ACL_LVL_SEARCH (ACL_PRIV_SEARCH|ACL_LVL_COMPARE)
#define ACL_LVL_READ (ACL_PRIV_READ|ACL_LVL_SEARCH)
#define ACL_LVL_WRITE (ACL_PRIV_WRITE|ACL_LVL_READ)
#define ACL_LVL(m,l) (((m)&ACL_PRIV_MASK) == ((l)&ACL_PRIV_MASK))
#define ACL_LVL_IS_NONE(m) ACL_LVL((m),ACL_LVL_NONE)
#define ACL_LVL_IS_AUTH(m) ACL_LVL((m),ACL_LVL_AUTH)
#define ACL_LVL_IS_COMPARE(m) ACL_LVL((m),ACL_LVL_COMPARE)
#define ACL_LVL_IS_SEARCH(m) ACL_LVL((m),ACL_LVL_SEARCH)
#define ACL_LVL_IS_READ(m) ACL_LVL((m),ACL_LVL_READ)
#define ACL_LVL_IS_WRITE(m) ACL_LVL((m),ACL_LVL_WRITE)
#define ACL_LVL_ASSIGN_NONE(m) ACL_PRIV_ASSIGN((m),ACL_LVL_NONE)
#define ACL_LVL_ASSIGN_AUTH(m) ACL_PRIV_ASSIGN((m),ACL_LVL_AUTH)
#define ACL_LVL_ASSIGN_COMPARE(m) ACL_PRIV_ASSIGN((m),ACL_LVL_COMPARE)
#define ACL_LVL_ASSIGN_SEARCH(m) ACL_PRIV_ASSIGN((m),ACL_LVL_SEARCH)
#define ACL_LVL_ASSIGN_READ(m) ACL_PRIV_ASSIGN((m),ACL_LVL_READ)
#define ACL_LVL_ASSIGN_WRITE(m) ACL_PRIV_ASSIGN((m),ACL_LVL_WRITE)
slap_access_mask_t a_mask;
char *a_dn_pat;
char *a_dn_at;
int a_dn_self;
char *a_peername_pat;
char *a_sockname_pat;
@ -469,7 +511,7 @@ struct slap_backend_db {
int be_sizelimit; /* size limit for this backend */
int be_timelimit; /* time limit for this backend */
AccessControl *be_acl; /* access control list for this backend */
int be_dfltaccess; /* access given if no acl matches */
slap_access_t be_dfltaccess; /* access given if no acl matches */
char **be_replica; /* replicas of this backend (in master) */
char *be_replogfile; /* replication log file (in master) */
char *be_update_ndn; /* allowed to make changes (in replicas) */

View file

@ -6,9 +6,7 @@
include %SYSCONFDIR%/slapd.at.conf
include %SYSCONFDIR%/slapd.oc.conf
# Using ACLs to control access is wise. When ACLs are used,
# "defaultaccess none" is recommended (default is 'auth').
defaultaccess read
# Define global ACLs to disable default read access.
# Do not enable referrals until AFTER you have a working directory
# service AND an understanding of referrals.