Commit e27a2c72 authored by Kurt Zeilenga's avatar Kurt Zeilenga
Browse files

Sync with HEAD

parents ad6eb1e0 bd11c2c4
......@@ -1032,8 +1032,8 @@ The general form of the olcAccess configuration is:
> [set=<setspec>]
> [aci=<attrname>]
> <access> ::= [self]{<level>|<priv>}
> <level> ::= none | auth | compare | search | read | write
> <priv> ::= {=|+|-}{w|r|s|c|x|0}+
> <level> ::= none | disclose | auth | compare | search | read | write | manage
> <priv> ::= {=|+|-}{m|w|r|s|c|x|d|0}+
> <control> ::= [stop | continue | break]
where the <what> part selects the entries and/or attributes to which
......@@ -1166,25 +1166,25 @@ As these can easily spoofed, the domain factor should not be avoided.
H3: The access to grant
The kind of <access> granted can be one of the following:
!block table; colaligns="LRL"; coltags="EX,EX,N"; align=Center; \
title="Table 5.4: Access Levels"
Level Privileges Description
none =0 no access
auth =x needed to bind
compare =cx needed to compare
search =scx needed to apply search filters
read =rscx needed to read search results
write =wrscx needed to modify/rename
Level Privileges Description
none =0 no access
disclose =d needed for information disclosure on error
auth =dx needed to authenticate (bind)
compare =cdx needed to compare
search =scdx needed to apply search filters
read =rscdx needed to read search results
write =wrscdx needed to modify/rename
manage =mwrscdx needed to manage
!endblock
Each level implies all lower levels of access. So, for
example, granting someone {{EX:write}} access to an entry also
grants them {{EX:read}}, {{EX:search}}, {{EX:compare}}, and
{{EX:auth}} access. However, one may use the privileges specifier
Each level implies all lower levels of access. So, for example,
granting someone {{EX:write}} access to an entry also grants them
{{EX:read}}, {{EX:search}}, {{EX:compare}}, {{EX:auth}} and
{{EX:disclose}} access. However, one may use the privileges specifier
to grant specific permissions.
......@@ -1192,15 +1192,16 @@ H3: Access Control Evaluation
When evaluating whether some requester should be given access to
an entry and/or attribute, slapd compares the entry and/or attribute
to the {{EX:<what>}} selectors given in the configuration.
For each entry, access controls provided in the database which holds
to the {{EX:<what>}} selectors given in the configuration. For
each entry, access controls provided in the database which holds
the entry (or the first database if not held in any database) apply
first, followed by the global access directives (which are held in
the {{EX:frontend}} database definition). Within this
priority, access directives are examined in the order in which they
appear in the configuration attribute. Slapd stops with the first {{EX:<what>}}
selector that matches the entry and/or attribute. The corresponding
access directive is the one slapd will use to evaluate access.
the {{EX:frontend}} database definition). Within this priority,
access directives are examined in the order in which they appear
in the configuration attribute. Slapd stops with the first
{{EX:<what>}} selector that matches the entry and/or attribute. The
corresponding access directive is the one slapd will use to evaluate
access.
Next, slapd compares the entity requesting access to the {{EX:<who>}}
selectors within the access directive selected above in the order
......
......@@ -705,8 +705,8 @@ access line is:
> [set=<setspec>]
> [aci=<attrname>]
> <access> ::= [self]{<level>|<priv>}
> <level> ::= none | auth | compare | search | read | write
> <priv> ::= {=|+|-}{w|r|s|c|x|0}+
> <level> ::= none | disclose | auth | compare | search | read | write | manage
> <priv> ::= {=|+|-}{m|w|r|s|c|x|d|0}+
> <control> ::= [stop | continue | break]
where the <what> part selects the entries and/or attributes to which
......@@ -839,25 +839,25 @@ As these can easily spoofed, the domain factor should not be avoided.
H3: The access to grant
The kind of <access> granted can be one of the following:
!block table; colaligns="LRL"; coltags="EX,EX,N"; align=Center; \
title="Table 5.4: Access Levels"
Level Privileges Description
none =0 no access
auth =x needed to bind
compare =cx needed to compare
search =scx needed to apply search filters
read =rscx needed to read search results
write =wrscx needed to modify/rename
Level Privileges Description
none =0 no access
disclose =d needed for information disclosure on error
auth =dx needed to authenticate (bind)
compare =cdx needed to compare
search =scdx needed to apply search filters
read =rscdx needed to read search results
write =wrscdx needed to modify/rename
manage =mwrscdx needed to manage
!endblock
Each level implies all lower levels of access. So, for
example, granting someone {{EX:write}} access to an entry also
grants them {{EX:read}}, {{EX:search}}, {{EX:compare}}, and
{{EX:auth}} access. However, one may use the privileges specifier
Each level implies all lower levels of access. So, for example,
granting someone {{EX:write}} access to an entry also grants them
{{EX:read}}, {{EX:search}}, {{EX:compare}}, {{EX:auth}} and
{{EX:disclose}} access. However, one may use the privileges specifier
to grant specific permissions.
......
......@@ -665,8 +665,8 @@ field will have.
Its component are defined as
.LP
.nf
<level> ::= none|disclose|auth|compare|search|read|write
<priv> ::= {=|+|-}{w|r|s|c|x|d|0}+
<level> ::= none|disclose|auth|compare|search|read|write|manage
<priv> ::= {=|+|-}{m|w|r|s|c|x|d|0}+
.fi
.LP
The modifier
......@@ -699,8 +699,8 @@ The possible levels are
and
.BR write .
Each access level implies all the preceding ones, thus
.B write
access will imply all accesses.
.B manage
grants all access including administrative access,
.LP
The
.B none
......@@ -733,6 +733,8 @@ and
.B -
signs add/remove access privileges to the existing ones.
The privileges are
.B m
for manage,
.B w
for write,
.B r
......
......@@ -232,13 +232,13 @@ extern void eb_syslog(int pri, const char *fmt, ...);
#else /* ! LDAP_DEBUG */
/* TODO: in case LDAP_DEBUG is undefined, make sure logs with appropriate
* severity gets thru anyway */
#define Log0( level, severity, fmt )
#define Log1( level, severity, fmt, arg1 )
#define Log2( level, severity, fmt, arg1, arg2 )
#define Log3( level, severity, fmt, arg1, arg2, arg3 )
#define Log4( level, severity, fmt, arg1, arg2, arg3, arg4 )
#define Log5( level, severity, fmt, arg1, arg2, arg3, arg4, arg5 )
#define Debug( level, fmt, arg1, arg2, arg3 )
#define Log0( level, severity, fmt ) ((void)0)
#define Log1( level, severity, fmt, arg1 ) ((void)0)
#define Log2( level, severity, fmt, arg1, arg2 ) ((void)0)
#define Log3( level, severity, fmt, arg1, arg2, arg3 ) ((void)0)
#define Log4( level, severity, fmt, arg1, arg2, arg3, arg4 ) ((void)0)
#define Log5( level, severity, fmt, arg1, arg2, arg3, arg4, arg5 ) ((void)0)
#define Debug( level, fmt, arg1, arg2, arg3 ) ((void)0)
#define LogTest(level) ( 0 )
#endif /* ! LDAP_DEBUG */
......
......@@ -247,7 +247,6 @@ ber_flush2( Sockbuf *sb, BerElement *ber, int freeit )
ber->ber_rwptr += rc;
}
done:;
if ( freeit & LBER_FLUSH_FREE_ON_SUCCESS ) ber_free( ber, 1 );
return 0;
......
......@@ -94,7 +94,6 @@ SLAP_SET_GATHER acl_set_gather2;
* - can be legally called with op->o_bd == NULL
*/
#ifdef SLAP_OVERLAY_ACCESS
int
slap_access_always_allowed(
Operation *op,
......@@ -462,281 +461,6 @@ done:
return ret;
}
#else /* !SLAP_OVERLAY_ACCESS */
int
access_allowed_mask(
Operation *op,
Entry *e,
AttributeDescription *desc,
struct berval *val,
slap_access_t access,
AccessControlState *state,
slap_mask_t *maskp )
{
int ret = 1;
int count;
AccessControl *a = NULL;
Backend *be;
int be_null = 0;
#ifdef LDAP_DEBUG
char accessmaskbuf[ACCESSMASK_MAXLEN];
#endif
slap_mask_t mask;
slap_control_t control;
slap_access_t access_level;
const char *attr;
regmatch_t matches[MAXREMATCHES];
int st_same_attr = 0;
static AccessControlState state_init = ACL_STATE_INIT;
assert( e != NULL );
assert( desc != NULL );
access_level = ACL_LEVEL( access );
assert( access_level > ACL_NONE );
if ( maskp ) ACL_INVALIDATE( *maskp );
attr = desc->ad_cname.bv_val;
assert( attr != NULL );
if ( op ) {
if ( op->o_is_auth_check &&
( access_level == ACL_SEARCH || access_level == ACL_READ ) )
{
access = ACL_AUTH;
} else if ( get_manageDIT( op ) && access_level == ACL_WRITE &&
desc == slap_schema.si_ad_entry )
{
access = ACL_MANAGE;
}
}
if ( state ) {
if ( state->as_vd_ad == desc ) {
if ( ( state->as_recorded & ACL_STATE_RECORDED_NV ) &&
val == NULL )
{
return state->as_result;
} else if ( ( state->as_recorded & ACL_STATE_RECORDED_VD ) &&
val != NULL && state->as_vd_acl == NULL )
{
return state->as_result;
}
st_same_attr = 1;
} else {
*state = state_init;
}
state->as_vd_ad = desc;
}
Debug( LDAP_DEBUG_ACL,
"=> access_allowed: %s access to \"%s\" \"%s\" requested\n",
access2str( access ), e->e_dn, attr );
if ( op == NULL ) {
/* no-op call */
goto done;
}
be = op->o_bd;
if ( be == NULL ) {
be = LDAP_STAILQ_FIRST(&backendDB);
be_null = 1;
#ifdef LDAP_DEVEL
/*
* FIXME: experimental; use first backend rules
* iff there is no global_acl (ITS#3100) */
if ( frontendDB->be_acl == NULL )
#endif
{
op->o_bd = be;
}
}
assert( be != NULL );
/* grant database root access */
if ( be_isroot( op ) ) {
Debug( LDAP_DEBUG_ACL, "<= root access granted\n", 0, 0, 0 );
if ( maskp ) {
mask = ACL_LVL_MANAGE;
}
goto done;
}
/*
* no-user-modification operational attributes are ignored
* by ACL_WRITE checking as any found here are not provided
* by the user
*
* NOTE: but they are not ignored for ACL_MANAGE, because
* if we get here it means a non-root user is trying to
* manage data, so we need to check its privileges.
*/
if ( access_level == ACL_WRITE && is_at_no_user_mod( desc->ad_type )
&& desc != slap_schema.si_ad_entry
&& desc != slap_schema.si_ad_children )
{
Debug( LDAP_DEBUG_ACL, "NoUserMod Operational attribute:"
" %s access granted\n",
attr, 0, 0 );
goto done;
}
/* use backend default access if no backend acls */
if ( be->be_acl == NULL ) {
Debug( LDAP_DEBUG_ACL,
"=> access_allowed: backend default %s "
"access %s to \"%s\"\n",
access2str( access ),
be->be_dfltaccess >= access_level ? "granted" : "denied",
op->o_dn.bv_val ? op->o_dn.bv_val : "(anonymous)" );
ret = be->be_dfltaccess >= access_level;
if ( maskp ) {
int i;
mask = ACL_PRIV_LEVEL;
for ( i = ACL_NONE; i <= be->be_dfltaccess; i++ ) {
mask |= ACL_ACCESS2PRIV( i );
}
}
goto done;
#ifdef notdef
/* be is always non-NULL */
/* use global default access if no global acls */
} else if ( be == NULL && frontendDB->be_acl == NULL ) {
Debug( LDAP_DEBUG_ACL,
"=> access_allowed: global default %s access %s to \"%s\"\n",
access2str( access ),
frontendDB->be_dfltaccess >= access_level ?
"granted" : "denied", op->o_dn.bv_val );
ret = frontendDB->be_dfltaccess >= access_level;
if ( maskp ) {
int i;
mask = ACL_PRIV_LEVEL;
for ( i = ACL_NONE; i <= global_default_access; i++ ) {
mask |= ACL_ACCESS2PRIV( i );
}
}
goto done;
#endif
}
ret = 0;
control = ACL_BREAK;
if ( st_same_attr ) {
assert( state->as_vd_acl != NULL );
a = state->as_vd_acl;
count = state->as_vd_acl_count;
if ( !ACL_IS_INVALID( state->as_vd_acl_mask ) ) {
mask = state->as_vd_acl_mask;
AC_MEMCPY( matches, state->as_vd_acl_matches, sizeof(matches) );
goto vd_access;
}
} else {
if ( state ) state->as_vi_acl = NULL;
a = NULL;
ACL_INIT(mask);
count = 0;
memset( matches, '\0', sizeof(matches) );
}
while ( ( a = slap_acl_get( a, &count, op, e, desc, val,
MAXREMATCHES, matches, state ) ) != NULL )
{
int i;
for ( i = 0; i < MAXREMATCHES && matches[i].rm_so > 0; 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_ACL, "%c", e->e_ndn[n], 0, 0 );
}
}
Debug( LDAP_DEBUG_ARGS, "\n", 0, 0, 0 );
}
if ( state ) {
if ( state->as_vi_acl == a &&
( state->as_recorded & ACL_STATE_RECORDED_NV ) )
{
Debug( LDAP_DEBUG_ACL,
"access_allowed: result from state (%s)\n",
attr, 0, 0 );
ret = state->as_result;
goto done;
} else {
Debug( LDAP_DEBUG_ACL,
"access_allowed: no res from state (%s)\n",
attr, 0, 0 );
}
}
vd_access:
control = slap_acl_mask( a, &mask, op,
e, desc, val, MAXREMATCHES, matches, count, state );
if ( control != ACL_BREAK ) {
break;
}
memset( matches, '\0', sizeof(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 );
goto done;
}
Debug( LDAP_DEBUG_ACL,
"=> access_allowed: %s access %s by %s\n",
access2str( access ),
ACL_GRANT(mask, access) ? "granted" : "denied",
accessmask2str( mask, accessmaskbuf, 1 ) );
ret = ACL_GRANT(mask, access);
done:
if ( state != NULL ) {
/* If not value-dependent, save ACL in case of more attrs */
if ( !( state->as_recorded & ACL_STATE_RECORDED_VD ) ) {
state->as_vi_acl = a;
state->as_result = ret;
}
state->as_recorded |= ACL_STATE_RECORDED;
}
if ( be_null ) op->o_bd = NULL;
if ( maskp ) *maskp = mask;
return ret;
}
#endif /* !SLAP_OVERLAY_ACCESS */
/*
* slap_acl_get - return the acl applicable to entry e, attribute
......
......@@ -2453,11 +2453,6 @@ str2access( const char *str )
return ACL_NONE;
} else if ( strcasecmp( str, "disclose" ) == 0 ) {
#ifndef SLAP_ACL_HONOR_DISCLOSE
Debug( LDAP_DEBUG_ACL, "str2access: warning, "
"\"disclose\" privilege disabled.\n",
0, 0, 0 );
#endif /* SLAP_ACL_HONOR_DISCLOSE */
return ACL_DISCLOSE;
} else if ( strcasecmp( str, "auth" ) == 0 ) {
......
......@@ -66,16 +66,13 @@ dn2entry_retry:
e = ei->bei_e;
if ( rs->sr_err == DB_NOTFOUND ) {
if ( e != NULL ) {
#ifdef SLAP_ACL_HONOR_DISCLOSE
/* return referral only if "disclose" is granted on the object */
if ( ! access_allowed( op, e, slap_schema.si_ad_entry,
NULL, ACL_DISCLOSE, NULL ) )
{
rs->sr_err = LDAP_NO_SUCH_OBJECT;
} else
#endif /* SLAP_ACL_HONOR_DISCLOSE */
{
} else {
rs->sr_matched = ch_strdup( e->e_dn );
rs->sr_ref = is_entry_referral( e )
? get_entry_referrals( op, e )
......@@ -103,15 +100,12 @@ dn2entry_retry:
}
if (!manageDSAit && is_entry_referral( e ) ) {
#ifdef SLAP_ACL_HONOR_DISCLOSE
/* return referral only if "disclose" is granted on the object */
if ( !access_allowed( op, e, slap_schema.si_ad_entry,
NULL, ACL_DISCLOSE, NULL ) )
{
rs->sr_err = LDAP_NO_SUCH_OBJECT;
} else
#endif /* SLAP_ACL_HONOR_DISCLOSE */
{
} else {
/* entry is a referral, don't allow compare */
rs->sr_ref = get_entry_referrals( op, e );
rs->sr_err = LDAP_REFERRAL;
......@@ -131,14 +125,11 @@ dn2entry_retry:
if ( get_assert( op ) &&
( test_filter( op, e, get_assertion( op )) != LDAP_COMPARE_TRUE ))
{
#ifdef SLAP_ACL_HONOR_DISCLOSE
if ( !access_allowed( op, e, slap_schema.si_ad_entry,
NULL, ACL_DISCLOSE, NULL ) )
{
rs->sr_err = LDAP_NO_SUCH_OBJECT;
} else
#endif /* SLAP_ACL_HONOR_DISCLOSE */
{
} else {
rs->sr_err = LDAP_ASSERTION_FAILED;
}
goto return_results;
......@@ -147,16 +138,13 @@ dn2entry_retry:
if ( !access_allowed( op, e, op->oq_compare.rs_ava->aa_desc,
&op->oq_compare.rs_ava->aa_value, ACL_COMPARE, NULL ) )
{
#ifdef SLAP_ACL_HONOR_DISCLOSE
/* return error only if "disclose"
* is granted on the object */
if ( !access_allowed( op, e, slap_schema.si_ad_entry,
NULL, ACL_DISCLOSE, NULL ) )
{
rs->sr_err = LDAP_NO_SUCH_OBJECT;
} else
#endif /* SLAP_ACL_HONOR_DISCLOSE */
{
} else {
rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
}
goto return_results;
......
......@@ -319,9 +319,7 @@ bdb_search( Operation *op, SlapReply *rs )
Entry *matched = NULL;
EntryInfo *ei, ei_root = {0};
struct berval realbase = BER_BVNULL;
#ifdef SLAP_ACL_HONOR_DISCLOSE
slap_mask_t mask;
#endif
int manageDSAit;
int tentries = 0;
ID lastid = NOID;
......@@ -424,7 +422,6 @@ dn2entry_retry:
if ( matched != NULL ) {
BerVarray erefs = NULL;
#ifdef SLAP_ACL_HONOR_DISCLOSE
/* return referral only if "disclose"
* is granted on the object */
if ( ! access_allowed( op, matched,
......@@ -433,9 +430,7 @@ dn2entry_retry:
{
rs->sr_err = LDAP_NO_SUCH_OBJECT;
} else
#endif /* SLAP_ACL_HONOR_DISCLOSE */
{
} else {
ber_dupbv( &matched_dn, &matched->e_name );
erefs = is_entry_referral( matched )
......@@ -483,7 +478,6 @@ dn2entry_retry:
return rs->sr_err;
}
#ifdef SLAP_ACL_HONOR_DISCLOSE
/* NOTE: __NEW__ "search" access is required
* on searchBase object */
if ( ! access_allowed_mask( op, e, slap_schema.si_ad_entry,
......@@ -504,7 +498,6 @@ dn2entry_retry:
send_ldap_result( op, rs );
return rs->sr_err;
}
#endif /* SLAP_ACL_HONOR_DISCLOSE */
if ( !manageDSAit && e != &e_root && is_entry_referral( e ) ) {
/* entry is a referral, don't allow add */
......
......@@ -67,9 +67,7 @@ dnssrv_back_initialize(
bi->bi_connection_init = 0;
bi->bi_connection_destroy = 0;
#ifdef SLAP_OVERLAY_ACCESS
bi->bi_access_allowed = slap_access_always_allowed;
#endif /* SLAP_OVERLAY_ACCESS */
return 0;
}
......
......@@ -306,7 +306,6 @@ ldap_back_freeconn( Operation *op, ldapconn_t *lc, int dolock )
ldap_pvt_thread_mutex_lock( &li->li_conninfo.lai_mutex );
}
assert( lc->lc_refcnt >= 0 );
tmplc = avl_delete( &li->li_conninfo.lai_tree, (caddr_t)lc,
ldap_back_conndnlc_cmp );
assert( LDAP_BACK_CONN_TAINTED( lc ) || tmplc == lc );
......@@ -355,13 +354,15 @@ ldap_back_start_tls(
}
if ( protocol < LDAP_VERSION3 ) {