mirror of
https://git.openldap.org/openldap/openldap.git
synced 2025-12-31 03:59:34 -05:00
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:
parent
10e886a601
commit
f6829ee903
11 changed files with 742 additions and 352 deletions
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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" );
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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 );
|
||||
|
|
|
|||
|
|
@ -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) */
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
Loading…
Reference in a new issue