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] \
.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
#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);
/*
* 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
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 );
- edn = e->e_ndn;
+ assert( be != NULL );
+ assert( e != NULL );
+ assert( attr != NULL );
+ assert( access > ACL_NONE );
- Debug( LDAP_DEBUG_ACL, "\n=> access_allowed: entry (%s) attr (%s)\n",
- e->e_dn, attr, 0 );
+ /* 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;
+ }
- /* 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 );
+
+ } else if ( control == ACL_BREAK ) {
+ Debug( LDAP_DEBUG_ACL,
+ "=> access_allowed: no more rules\n", 0, 0, 0);
+ ACL_INIT( mask );
+ }
- Debug( LDAP_DEBUG_ACL, "\n=> access_allowed: exit (%s) attr (%s)\n",
- e->e_dn, attr, 0);
+ Debug( LDAP_DEBUG_ACL,
+ "=> access_allowed: %s access %s to \"%s\"\n",
+ access2str( access ),
+ ACL_GRANT(mask, access) ? "granted" : "denied", op->o_dn );
- return( rc );
+ 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;
-
- Debug( LDAP_DEBUG_ACL, "\n=> acl_get: entry (%s) attr (%s)\n",
- e->e_dn, attr, 0 );
-
- 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 );
- }
+ AccessControl *next;
- edn = e->e_ndn;
-
- 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);
-
- if (regexec(&a->acl_dn_re, edn, nmatch, matches, 0)) {
- continue;
-
- } else {
- Debug( LDAP_DEBUG_TRACE, "=> acl_get:[%d] backend ACL match\n",
- i, 0, 0);
- }
- }
+ assert( e != NULL );
+ assert( count != NULL );
- if ( a->acl_filter != NULL ) {
- if ( test_filter( NULL, NULL, NULL, e, a->acl_filter ) != 0 ) {
- continue;
- }
+ if( a == NULL ) {
+ if( be == NULL ) {
+ a = global_acl;
+ } else {
+ a = be->be_acl;
}
- Debug( LDAP_DEBUG_ARGS, "=> acl_get: [%d] check attr %s\n", i, attr, 0);
+ assert( a != NULL );
- 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 );
- }
- matches[0].rm_so = matches[0].rm_eo = -1;
+ } else {
+ a = a->acl_next;
}
- /* check for a global acl that matches the entry */
- for ( i = 1, a = global_acl; a != NULL; a = a->acl_next, i++ ) {
+ for ( ; a != NULL; a = a->acl_next ) {
+ (*count) ++;
+
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);
+ 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] global ACL match\n",
- i, 0, 0);
+ Debug( LDAP_DEBUG_ACL, "=> acl_get: ACL [%d] matched\n",
+ *count, 0, 0);
}
}
}
}
- Debug( LDAP_DEBUG_ARGS, "=> acl_get: [%d] check attr\n", i, 0, 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] global 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;
}
- 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).
*
* 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 );
- }
+ op->o_ndn ? op->o_ndn : "",
+ accessmask2str( *mask ) );
- default_access = be->be_dfltaccess ? be->be_dfltaccess : global_default_access;
+ for ( i = 1, b = a->acl_access; b != NULL; b = b->a_next, i++ ) {
+ slap_access_mask_t oldmask, modmask;
- 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 );
- }
+ ACL_INVALIDATE( modmask );
- for ( i = 1, b = a->acl_access; b != NULL; b = b->a_next, i++ ) {
/* 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
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;
}
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;
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;
* 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;
}
#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' ) {
/* 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;
}
* 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;
- Debug( LDAP_DEBUG_ACL,
- "<= acl_access_allowed: %s by default (no matching by)\n",
- default_access >= access ? "granted" : "denied", 0, 0 );
+ 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;
+ }
+ }
- 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
)
{
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];
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:
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
}
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)
}
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;
Backend *be,
Entry *e,
Operation *op,
- char *edn,
regmatch_t *matches
)
{
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);
}
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
)
{
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 : "" );
}
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);
#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
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",
}
#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",
#ifdef LDAP_DEBUG
if (ldap_debug & LDAP_DEBUG_ACL)
- print_acl(a);
+ print_acl(be, a);
#endif
if ( a->acl_access == NULL ) {
}
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';
+
+ 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, " (");
+ }
+
+ if( ACL_IS_ADDITIVE( mask ) ) {
+ strcat( buf, "+" );
+
+ } else if( ACL_IS_SUBTRACTIVE( mask ) ) {
+ strcat( buf, "-" );
} else {
- strcat( buf, "unknown" );
+ strcat( buf, "=" );
}
- return( 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;
+
+ if( !isalpha(str[0]) ) {
+ int i;
+
+ 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);
- ACL_CLR(access);
+ } 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;
+ }
+ }
- if ( strncasecmp( str, "self", 4 ) == 0 ) {
- ACL_SET_SELF(access);
- str += 4;
+ 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"
#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 );
}
*l = a;
}
-static void
+void
acl_append( AccessControl **l, AccessControl *a )
{
for ( ; *l != NULL; l = &(*l)->acl_next )
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 );
}
}
#endif
+ fprintf( stderr, " %s%s",
+ b->a_dn_self ? "self" : "",
+ accessmask2str( b->a_mask ) );
+
fprintf( stderr, "\n" );
}
+char *
+access2str( slap_access_t access )
+{
+ 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( AccessControl *a )
+print_acl( Backend *be, AccessControl *a )
{
- int i;
+ int to = 0;
Access *b;
- if ( a == NULL ) {
- fprintf( stderr, "NULL\n" );
+ fprintf( stderr, "%s ACL: access to",
+ be == NULL ? "Global" : "Backend" );
+
+ if ( a->acl_dn_pat != NULL ) {
+ to++;
+ fprintf( stderr, " dn=%s\n",
+ a->acl_dn_pat );
}
- fprintf( stderr, "ACL: access to" );
+
if ( a->acl_filter != NULL ) {
- fprintf( stderr," filter=" );
+ to++;
+ fprintf( stderr, " filter=" );
filter_print( a->acl_filter );
+ fprintf( stderr, "\n" );
}
- if ( a->acl_dn_pat != NULL ) {
- fprintf( stderr, " dn=" );
- fprintf( stderr, a->acl_dn_pat );
- }
+
if ( a->acl_attrs != NULL ) {
- int first = 1;
+ int i, first = 1;
+ to++;
- fprintf( stderr, "\n attrs=" );
+ fprintf( stderr, " attrs=" );
for ( i = 0; a->acl_attrs[i] != NULL; i++ ) {
if ( ! first ) {
fprintf( stderr, "," );
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" );
}
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;
}
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;
}
/* 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] );
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;
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;
/* 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 */
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,
Entry *e,
LDAPModList *ml ));
+void acl_append( AccessControl **l, AccessControl *a );
+
/*
* aclparse.c
*/
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
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;
}
}
- 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;
}
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;
}
}
}
- 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;
}
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 );
* 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_ACCESS2PRIV(access) (0x01U << (access))
+
+#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_PRIV_MASK 0x00ffUL
+
+/* priv flags */
+#define ACL_PRIV_LEVEL 0x1000UL
+#define ACL_PRIV_ADDITIVE 0x2000UL
+#define ACL_PRIV_SUBSTRACTIVE 0x4000UL
+
+/* invalid privs */
+#define ACL_PRIV_INVALID 0x0UL
+
+#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)
+
+#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)
-#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_SELF 0x4000
-#define ACL_INVALID (-1)
-
-#define ACL_IS(a,lvl) (((a) & (lvl)) == (lvl))
-
-#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)
-
-#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)
-
-#define ACL_PRIV(a) ((a) & ACL_PRIV_MASK)
-#define ACL_GRANT(a,lvl) (ACL_PRIV(a) >= (lvl))
-
- int a_access;
+ 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;
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) */
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.