int ret = 1;
int count;
AccessControl *a = NULL;
- Backend *be;
- int be_null = 0;
+ Backend *be;
+ int be_null = 0;
#ifdef LDAP_DEBUG
- char accessmaskbuf[ACCESSMASK_MAXLEN];
+ char accessmaskbuf[ACCESSMASK_MAXLEN];
#endif
- slap_mask_t mask;
- slap_control_t control;
- const char *attr;
- regmatch_t matches[MAXREMATCHES];
- int st_same_attr = 0;
- static AccessControlState state_init = ACL_STATE_INIT;
+ 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 );
- assert( access > ACL_NONE );
+
+ 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 && op->o_is_auth_check &&
- ( access == ACL_SEARCH || access == ACL_READ ))
+ ( access_level == ACL_SEARCH || access_level == ACL_READ ))
{
access = ACL_AUTH;
}
* by ACL_WRITE checking as any found here are not provided
* by the user
*/
- if ( access >= ACL_WRITE && is_at_no_user_mod( desc->ad_type )
+ 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,
"=> access_allowed: backend default %s access %s to \"%s\"\n",
access2str( access ),
- be->be_dfltaccess >= access ? "granted" : "denied",
+ be->be_dfltaccess >= access_level ? "granted" : "denied",
op->o_dn.bv_val ? op->o_dn.bv_val : "(anonymous)" );
- ret = be->be_dfltaccess >= access;
+ ret = be->be_dfltaccess >= access_level;
if ( maskp ) {
int i;
Debug( LDAP_DEBUG_ACL,
"=> access_allowed: global default %s access %s to \"%s\"\n",
access2str( access ),
- frontendDB->be_dfltaccess >= access ? "granted" : "denied", op->o_dn.bv_val );
- ret = frontendDB->be_dfltaccess >= access;
+ frontendDB->be_dfltaccess >= access_level ? "granted" : "denied", op->o_dn.bv_val );
+ ret = frontendDB->be_dfltaccess >= access_level;
if ( maskp ) {
int i;
* This prevents abuse from selfwriters.
*/
if ( ! access_allowed( op, e,
- mlist->sml_desc, NULL, ACL_WRITE, &state ) )
+ mlist->sml_desc, NULL, ACL_WDEL, &state ) )
{
ret = 0;
goto done;
bv->bv_val != NULL; bv++ )
{
if ( ! access_allowed( op, e,
- mlist->sml_desc, bv, ACL_WRITE, &state ) )
+ mlist->sml_desc, bv, ACL_WADD, &state ) )
{
ret = 0;
goto done;
case LDAP_MOD_DELETE:
if ( mlist->sml_values == NULL ) {
if ( ! access_allowed( op, e,
- mlist->sml_desc, NULL, ACL_WRITE, NULL ) )
+ mlist->sml_desc, NULL, ACL_WDEL, NULL ) )
{
ret = 0;
goto done;
bv->bv_val != NULL; bv++ )
{
if ( ! access_allowed( op, e,
- mlist->sml_desc, bv, ACL_WRITE, &state ) )
+ mlist->sml_desc, bv, ACL_WDEL, &state ) )
{
ret = 0;
goto done;
} else if ( ACL_LVL_IS_WRITE(mask) ) {
ptr = lutil_strcopy( ptr, "write" );
+ } else if ( ACL_LVL_IS_WADD(mask) ) {
+ ptr = lutil_strcopy( ptr, "add" );
+
+ } else if ( ACL_LVL_IS_WDEL(mask) ) {
+ ptr = lutil_strcopy( ptr, "delete" );
+
} else if ( ACL_LVL_IS_MANAGE(mask) ) {
ptr = lutil_strcopy( ptr, "manage" );
*ptr++ = 'w';
}
+ if ( ACL_PRIV_ISSET(mask, ACL_PRIV_WADD) ) {
+ none = 0;
+ *ptr++ = 'a';
+ }
+
+ if ( ACL_PRIV_ISSET(mask, ACL_PRIV_WDEL) ) {
+ none = 0;
+ *ptr++ = 'z';
+ }
+
if ( ACL_PRIV_ISSET(mask, ACL_PRIV_READ) ) {
none = 0;
*ptr++ = 'r';
if ( none && ACL_PRIV_ISSET(mask, ACL_PRIV_NONE) ) {
none = 0;
- *ptr++ = 'n';
+ *ptr++ = '0';
}
if ( none ) {
} else if( TOLOWER((unsigned char) str[i]) == 'w' ) {
ACL_PRIV_SET(mask, ACL_PRIV_WRITE);
+ } else if( TOLOWER((unsigned char) str[i]) == 'a' ) {
+ ACL_PRIV_SET(mask, ACL_PRIV_WADD);
+
+ } else if( TOLOWER((unsigned char) str[i]) == 'z' ) {
+ ACL_PRIV_SET(mask, ACL_PRIV_WDEL);
+
} else if( TOLOWER((unsigned char) str[i]) == 'r' ) {
ACL_PRIV_SET(mask, ACL_PRIV_READ);
} else if ( strcasecmp( str, "read" ) == 0 ) {
ACL_LVL_ASSIGN_READ(mask);
+ } else if ( strcasecmp( str, "add" ) == 0 ) {
+ ACL_LVL_ASSIGN_WADD(mask);
+
+ } else if ( strcasecmp( str, "delete" ) == 0 ) {
+ ACL_LVL_ASSIGN_WDEL(mask);
+
} else if ( strcasecmp( str, "write" ) == 0 ) {
ACL_LVL_ASSIGN_WRITE(mask);
"<peernamestyle> ::= exact | regex | ip | path\n"
"<domainstyle> ::= exact | regex | base(Object) | sub(tree)\n"
"<access> ::= [[real]self]{<level>|<priv>}\n"
- "<level> ::= none|disclose|auth|compare|search|read|write|manage\n"
- "<priv> ::= {=|+|-}{0|d|x|c|s|r|w|m}+\n"
+ "<level> ::= none|disclose|auth|compare|search|read|{write|add|delete}|manage\n"
+ "<priv> ::= {=|+|-}{0|d|x|c|s|r|{w|a|z}|m}+\n"
"<control> ::= [ stop | continue | break ]\n"
);
exit( EXIT_FAILURE );
} else if ( access == ACL_WRITE ) {
return "write";
+ } else if ( access == ACL_WADD ) {
+ return "add";
+
+ } else if ( access == ACL_WDEL ) {
+ return "delete";
+
} else if ( access == ACL_MANAGE ) {
return "manage";
} else if ( strcasecmp( str, "write" ) == 0 ) {
return ACL_WRITE;
+ } else if ( strcasecmp( str, "add" ) == 0 ) {
+ return ACL_WADD;
+
+ } else if ( strcasecmp( str, "delete" ) == 0 ) {
+ return ACL_WDEL;
+
} else if ( strcasecmp( str, "manage" ) == 0 ) {
return ACL_MANAGE;
}
}
rs->sr_err = access_allowed( op, p,
- children, NULL, ACL_WRITE, NULL );
+ children, NULL, ACL_WADD, NULL );
if ( ! rs->sr_err ) {
switch( opinfo.boi_err ) {
}
rs->sr_err = access_allowed( op, op->oq_add.rs_e,
- entry, NULL, ACL_WRITE, NULL );
+ entry, NULL, ACL_WADD, NULL );
if ( ! rs->sr_err ) {
switch( opinfo.boi_err ) {
/* check parent for "children" acl */
rs->sr_err = access_allowed( op, p,
- children, NULL, ACL_WRITE, NULL );
+ children, NULL, ACL_WDEL, NULL );
if ( !rs->sr_err ) {
switch( opinfo.boi_err ) {
/* check parent for "children" acl */
rs->sr_err = access_allowed( op, p,
- children, NULL, ACL_WRITE, NULL );
+ children, NULL, ACL_WDEL, NULL );
p = NULL;
}
rs->sr_err = access_allowed( op, e,
- entry, NULL, ACL_WRITE, NULL );
+ entry, NULL, ACL_WDEL, NULL );
if ( !rs->sr_err ) {
switch( opinfo.boi_err ) {
/* check parent for "children" acl */
rs->sr_err = access_allowed( op, p,
- children, NULL, ACL_WRITE, NULL );
+ children, NULL,
+ op->oq_modrdn.rs_newSup == NULL ?
+ ACL_WRITE : ACL_WDEL,
+ NULL );
if ( ! rs->sr_err ) {
switch( opinfo.boi_err ) {
/* check parent for "children" acl */
rs->sr_err = access_allowed( op, p,
- children, NULL, ACL_WRITE, NULL );
+ children, NULL,
+ op->oq_modrdn.rs_newSup == NULL ?
+ ACL_WRITE : ACL_WDEL,
+ NULL );
p = NULL;
/* check newSuperior for "children" acl */
rs->sr_err = access_allowed( op, np, children,
- NULL, ACL_WRITE, NULL );
+ NULL, ACL_WADD, NULL );
if( ! rs->sr_err ) {
switch( opinfo.boi_err ) {
/* check parent for "children" acl */
rs->sr_err = access_allowed( op, np,
- children, NULL, ACL_WRITE, NULL );
+ children, NULL, ACL_WADD, NULL );
np = NULL;
#endif
if ( !access_allowed( op, op->oq_add.rs_e,
- entry, NULL, ACL_WRITE, NULL ) )
+ entry, NULL, ACL_WADD, NULL ) )
{
Debug( LDAP_DEBUG_TRACE, "no write access to entry\n", 0,
0, 0 );
return rs->sr_err;
}
- if ( ! access_allowed( op, p, children, NULL, ACL_WRITE, NULL ) ) {
+ if ( ! access_allowed( op, p, children, NULL, ACL_WADD, NULL ) ) {
/* free parent and writer lock */
cache_return_entry_w( &li->li_cache, p );
ldap_pvt_thread_rdwr_wunlock(&li->li_giant_rwlock);
}
/* check entry for "entry" acl */
- if ( ! access_allowed( op, e,
- entry, NULL, ACL_WRITE, NULL ) )
+ if ( ! access_allowed( op, e, entry, NULL, ACL_WDEL, NULL ) )
{
Debug( LDAP_DEBUG_TRACE,
"<=- ldbm_back_delete: no write access to entry\n", 0,
/* check parent for "children" acl */
if ( ! access_allowed( op, p,
- children, NULL, ACL_WRITE, NULL ) )
+ children, NULL, ACL_WDEL, NULL ) )
{
Debug( LDAP_DEBUG_TRACE,
"<=- ldbm_back_delete: no access to parent\n", 0,
p = (Entry *)&slap_entry_root;
rc = access_allowed( op, p,
- children, NULL, ACL_WRITE, NULL );
+ children, NULL, ACL_WDEL, NULL );
p = NULL;
/* check parent for "children" acl */
}
/* check entry for "entry" acl */
- if ( ! access_allowed( op, e,
- entry, NULL, ACL_WRITE, NULL ) )
+ if ( ! access_allowed( op, e, entry, NULL, ACL_WRITE, NULL ) )
{
Debug( LDAP_DEBUG_TRACE,
"<=- ldbm_back_modrdn: no write access to entry\n", 0,
}
/* check parent for "children" acl */
- if ( ! access_allowed( op, p,
- children, NULL, ACL_WRITE, NULL ) )
+ if ( ! access_allowed( op, p, children, NULL,
+ op->oq_modrdn.rs_newSup != NULL ?
+ ACL_WDEL : ACL_WRITE,
+ NULL ) )
{
Debug( LDAP_DEBUG_TRACE, "no access to parent\n", 0,
0, 0 );
p = (Entry *)&slap_entry_root;
can_access = access_allowed( op, p,
- children, NULL, ACL_WRITE, NULL );
+ children, NULL,
+ op->oq_modrdn.rs_newSup ?
+ ACL_WDEL : ACL_WRITE,
+ NULL );
p = NULL;
/* check parent for "children" acl */
/* check newSuperior for "children" acl */
if ( !access_allowed( op, np, children, NULL,
- ACL_WRITE, NULL ) )
+ ACL_WADD, NULL ) )
{
Debug( LDAP_DEBUG_TRACE,
"ldbm_back_modrdn: no wr to newSup children\n",
np = (Entry *)&slap_entry_root;
can_access = access_allowed( op, np,
- children, NULL, ACL_WRITE, NULL );
+ children, NULL, ACL_WADD, NULL );
np = NULL;
/* check parent for "children" acl */
}
if ( ! access_allowed( op, op->oq_add.rs_e,
- entry, NULL, ACL_WRITE, NULL ) )
+ entry, NULL, ACL_WADD, NULL ) )
{
send_ldap_error( op, rs, LDAP_INSUFFICIENT_ACCESS, NULL );
return -1;
e.e_private = NULL;
if ( ! access_allowed( op, &e,
- entry, NULL, ACL_WRITE, NULL ) )
+ entry, NULL, ACL_WDEL, NULL ) )
{
send_ldap_error( op, rs, LDAP_INSUFFICIENT_ACCESS, NULL );
return -1;
e.e_bv.bv_val = NULL;
e.e_private = NULL;
- if ( ! access_allowed( op, &e,
- entry, NULL, ACL_WRITE, NULL ) )
+ if ( ! access_allowed( op, &e, entry, NULL,
+ op->oq_modrdn.rs_newSup ? ACL_WDEL : ACL_WRITE,
+ NULL ) )
{
send_ldap_error( op, rs, LDAP_INSUFFICIENT_ACCESS, NULL );
return -1;
fprintf( wfp, "dn: %s\n", op->o_req_dn.bv_val );
fprintf( wfp, "newrdn: %s\n", op->oq_modrdn.rs_newrdn.bv_val );
fprintf( wfp, "deleteoldrdn: %d\n", op->oq_modrdn.rs_deleteoldrdn ? 1 : 0 );
- if (op->oq_modrdn.rs_newSup != NULL) {
+ if ( op->oq_modrdn.rs_newSup != NULL ) {
fprintf( wfp, "newSuperior: %s\n", op->oq_modrdn.rs_newSup->bv_val );
}
fclose( wfp );
/* check "children" pseudo-attribute access to parent */
if ( !access_allowed( op, &p, slap_schema.si_ad_children,
- NULL, ACL_WRITE, NULL ) )
+ NULL, ACL_WADD, NULL ) )
{
rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
e = &p;
if ( !access_allowed_mask( op, op->ora_e,
slap_schema.si_ad_entry,
- NULL, ACL_WRITE, NULL, &mask ) )
+ NULL, ACL_WADD, NULL, &mask ) )
{
rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
e = op->ora_e;
}
if ( !access_allowed( op, &d, slap_schema.si_ad_entry,
- NULL, ACL_WRITE, NULL ) )
+ NULL, ACL_WDEL, NULL ) )
{
Debug( LDAP_DEBUG_TRACE, " backsql_delete(): "
"no write access to entry\n",
/* check parent for "children" acl */
if ( !access_allowed( op, &p, slap_schema.si_ad_children,
- NULL, ACL_WRITE, NULL ) )
+ NULL, ACL_WDEL, NULL ) )
{
Debug( LDAP_DEBUG_TRACE, " backsql_delete(): "
"no write access to parent\n",
goto done;
}
- if ( !access_allowed( op, &p, slap_schema.si_ad_children,
- NULL, ACL_WRITE, NULL ) ) {
+ if ( !access_allowed( op, &p, slap_schema.si_ad_children, NULL,
+ newSuperior ? ACL_WDEL : ACL_WRITE, NULL ) )
+ {
Debug( LDAP_DEBUG_TRACE, " no access to parent\n", 0, 0, 0 );
rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
goto done;
#endif /* ! BACKSQL_ARBITRARY_KEY */
if ( !access_allowed( op, &n, slap_schema.si_ad_children,
- NULL, ACL_WRITE, NULL ) ) {
+ NULL, ACL_WADD, NULL ) ) {
Debug( LDAP_DEBUG_TRACE, " backsql_modrdn(): "
"no access to new parent \"%s\"\n",
new_pdn->bv_val, 0, 0 );
/* ACL check of newly added attrs */
if ( op->o_bd && !access_allowed( op, e, desc,
- &new_rdn[a_cnt]->la_value, ACL_WRITE, NULL ) ) {
+ &new_rdn[a_cnt]->la_value, ACL_WADD, NULL ) ) {
Debug( LDAP_DEBUG_TRACE,
"slap_modrdn2modlist: access to attr \"%s\" "
"(new) not allowed\n",
goto done;
}
- /* ACL check of newly added attrs */
+ /* ACL check of old rdn attrs removal */
if ( op->o_bd && !access_allowed( op, e, desc,
- &old_rdn[d_cnt]->la_value, ACL_WRITE,
+ &old_rdn[d_cnt]->la_value, ACL_WDEL,
NULL ) ) {
Debug( LDAP_DEBUG_TRACE,
"slap_modrdn2modlist: access "
ACL_SEARCH,
ACL_READ,
ACL_WRITE,
- ACL_MANAGE
+ ACL_MANAGE,
+
+ /* ACL level mask and modifiers */
+ ACL_LEVEL_MASK = 0x000f,
+ ACL_QUALIFIER1 = 0x0100,
+ ACL_QUALIFIER2 = 0x0200,
+ ACL_QUALIFIER3 = 0x0400,
+ ACL_QUALIFIER4 = 0x0800,
+ ACL_QUALIFIER_MASK = 0x0f00,
+
+ /* write granularity */
+ ACL_WADD = ACL_WRITE|ACL_QUALIFIER1,
+ ACL_WDEL = ACL_WRITE|ACL_QUALIFIER2
} slap_access_t;
typedef enum slap_control_e {
typedef struct slap_access {
slap_control_t a_type;
-#define ACL_ACCESS2PRIV(access) (0x01U << (access))
+/* strip qualifiers */
+#define ACL_LEVEL(p) ((p) & ACL_LEVEL_MASK)
+#define ACL_QUALIFIERS(p) ((p) & ~ACL_LEVEL_MASK)
+
+#define ACL_ACCESS2PRIV(access) ((0x01U << ACL_LEVEL((access))) | ACL_QUALIFIERS((access)))
#define ACL_PRIV_NONE ACL_ACCESS2PRIV( ACL_NONE )
#define ACL_PRIV_DISCLOSE ACL_ACCESS2PRIV( ACL_DISCLOSE )
#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_WADD ACL_ACCESS2PRIV( ACL_WADD )
+#define ACL_PRIV_WDEL ACL_ACCESS2PRIV( ACL_WDEL )
+#define ACL_PRIV_WRITE ( ACL_PRIV_WADD | ACL_PRIV_WDEL )
#define ACL_PRIV_MANAGE ACL_ACCESS2PRIV( ACL_MANAGE )
-#define ACL_PRIV_MASK 0x00ffUL
+/* NOTE: always use the highest level; current: 0x00ffUL */
+#define ACL_PRIV_MASK ((ACL_PRIV_MANAGE - 1) | ACL_QUALIFIER_MASK)
/* priv flags */
#define ACL_PRIV_LEVEL 0x1000UL
#define ACL_PRIV_ADDITIVE 0x2000UL
-#define ACL_PRIV_SUBSTRACTIVE 0x4000UL
+#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_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_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_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_IS_SUBTRACTIVE(m) ACL_PRIV_ISSET((m),ACL_PRIV_SUBSTRACTIVE)
#define ACL_LVL_NONE (ACL_PRIV_NONE|ACL_PRIV_LEVEL)
#define ACL_LVL_DISCLOSE (ACL_PRIV_DISCLOSE|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_WADD (ACL_PRIV_WADD|ACL_LVL_READ)
+#define ACL_LVL_WDEL (ACL_PRIV_WDEL|ACL_LVL_READ)
#define ACL_LVL_WRITE (ACL_PRIV_WRITE|ACL_LVL_READ)
#define ACL_LVL_MANAGE (ACL_PRIV_MANAGE|ACL_LVL_WRITE)
#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_DISCLOSE(m) ACL_LVL((m),ACL_LVL_DISCLOSE)
+#define ACL_LVL_IS_DISCLOSE(m) ACL_LVL((m),ACL_LVL_DISCLOSE)
#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_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_WADD(m) ACL_LVL((m),ACL_LVL_WADD)
+#define ACL_LVL_IS_WDEL(m) ACL_LVL((m),ACL_LVL_WDEL)
#define ACL_LVL_IS_WRITE(m) ACL_LVL((m),ACL_LVL_WRITE)
-#define ACL_LVL_IS_MANAGE(m) ACL_LVL((m),ACL_LVL_MANAGE)
+#define ACL_LVL_IS_MANAGE(m) ACL_LVL((m),ACL_LVL_MANAGE)
#define ACL_LVL_ASSIGN_NONE(m) ACL_PRIV_ASSIGN((m),ACL_LVL_NONE)
#define ACL_LVL_ASSIGN_DISCLOSE(m) ACL_PRIV_ASSIGN((m),ACL_LVL_DISCLOSE)
#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_WADD(m) ACL_PRIV_ASSIGN((m),ACL_LVL_WADD)
+#define ACL_LVL_ASSIGN_WDEL(m) ACL_PRIV_ASSIGN((m),ACL_LVL_WDEL)
#define ACL_LVL_ASSIGN_WRITE(m) ACL_PRIV_ASSIGN((m),ACL_LVL_WRITE)
#define ACL_LVL_ASSIGN_MANAGE(m) ACL_PRIV_ASSIGN((m),ACL_LVL_MANAGE)
case SLAPI_ACL_DELETE:
case SLAPI_ACL_ADD:
case SLAPI_ACL_SELF:
+ /* FIXME: handle ACL_WADD/ACL_WDEL */
slap_access = ACL_WRITE;
break;
default:
switch ( access ) {
case ACL_WRITE:
+ /* FIXME: handle ACL_WADD/ACL_WDEL */
slap_access |= SLAPI_ACL_ADD | SLAPI_ACL_DELETE | SLAPI_ACL_WRITE;
break;
case ACL_READ:
telephoneNumber: +1 313 555 0895
# Using ldapsearch to retrieve all the entries...
+dn: ou=Add/Delete,dc=example,dc=com
+objectClass: organizationalUnit
+ou: Add/Delete
+
+dn: cn=Added by Bjorn (must succeed),ou=Add/Delete,dc=example,dc=com
+objectClass: inetOrgPerson
+cn: Added by Bjorn (must succeed)
+sn: None
+description: this attribute value has been added __after__entry creation
+description: Bjorn will try to delete this attribute value (should fail)
+
+dn: cn=Added by Bjorn (renamed by Jaj),ou=Add/Delete,dc=example,dc=com
+objectClass: inetOrgPerson
+sn: None
+cn: Added by Bjorn (renamed by Jaj)
+
dn: cn=All Staff,ou=Groups,dc=example,dc=com
member: cn=Manager,dc=example,dc=com
member: cn=Barbara Jensen,ou=Information Technology Division,ou=People,dc=exam
access to filter="(name=X*Y*Z)"
by * continue
+access to dn.subtree="ou=Add/Delete,dc=example,dc=com"
+ by dn.exact="cn=Bjorn Jensen,ou=Information Technology Division,ou=People,dc=example,dc=com" add
+ by dn.exact="cn=Barbara Jensen,ou=Information Technology Division,ou=People,dc=example,dc=com" delete
+ by dn.exact="cn=James A Jones 1,ou=Alumni Association,ou=People,dc=example,dc=com" write
+ by * read
+
# fall into global ACLs
#monitor#database monitor
-
EOMODS6
+$LDAPMODIFY -D "$MANAGERDN" -h $LOCALHOST -p $PORT1 -w $PASSWD >> \
+ $TESTOUT 2>&1 << EOMODS7
+dn: ou=Add/Delete,dc=example,dc=com
+changetype: add
+objectClass: organizationalUnit
+ou: Add/Delete
+EOMODS7
+
+$LDAPMODIFY -D "$BABSDN" -h $LOCALHOST -p $PORT1 -w bjensen >> \
+ $TESTOUT 2>&1 << EOMODS8
+dn: cn=Added by Babs (must fail),ou=Add/Delete,dc=example,dc=com
+changetype: add
+objectClass: inetOrgPerson
+cn: Added by Babs (must fail)
+sn: None
+EOMODS8
+
+$LDAPMODIFY -D "$BJORNSDN" -h $LOCALHOST -p $PORT1 -w bjorn >> \
+ $TESTOUT 2>&1 << EOMODS9
+dn: cn=Added by Bjorn (must succeed),ou=Add/Delete,dc=example,dc=com
+changetype: add
+objectClass: inetOrgPerson
+cn: Added by Bjorn (must succeed)
+sn: None
+
+dn: cn=Added by Bjorn (will be deleted),ou=Add/Delete,dc=example,dc=com
+changetype: add
+objectClass: inetOrgPerson
+cn: Added by Bjorn (will be deleted)
+sn: None
+
+dn: cn=Added by Bjorn (will be renamed),ou=Add/Delete,dc=example,dc=com
+changetype: add
+objectClass: inetOrgPerson
+cn: Added by Bjorn (will be renamed)
+sn: None
+
+dn: cn=Added by Bjorn (must succeed),ou=Add/Delete,dc=example,dc=com
+changetype: modify
+add: description
+description: this attribute value has been added __after__entry creation
+description: this attribute value will be deleted by Babs (must succeed)
+description: Bjorn will try to delete this attribute value (should fail)
+-
+EOMODS9
+
+$LDAPMODIFY -D "$BJORNSDN" -h $LOCALHOST -p $PORT1 -w bjorn >> \
+ $TESTOUT 2>&1 << EOMODS10
+dn: cn=Added by Bjorn (will be deleted),ou=Add/Delete,dc=example,dc=com
+changetype: delete
+EOMODS10
+
+$LDAPMODIFY -D "$BJORNSDN" -h $LOCALHOST -p $PORT1 -w bjorn >> \
+ $TESTOUT 2>&1 << EOMODS11
+dn: cn=Added by Bjorn (will be renamed),ou=Add/Delete,dc=example,dc=com
+changetype: modrdn
+newrdn: cn=Added by Bjorn (renamed by Bjorn)
+deleteoldrdn: 1
+EOMODS11
+
+$LDAPMODIFY -D "$BABSDN" -h $LOCALHOST -p $PORT1 -w bjensen >> \
+ $TESTOUT 2>&1 << EOMODS12
+dn: cn=Added by Bjorn (will be renamed),ou=Add/Delete,dc=example,dc=com
+changetype: modrdn
+newrdn: cn=Added by Bjorn (renamed by Babs)
+deleteoldrdn: 1
+EOMODS12
+
+$LDAPMODIFY -D "$JAJDN" -h $LOCALHOST -p $PORT1 -w jaj >> \
+ $TESTOUT 2>&1 << EOMODS13
+dn: cn=Added by Bjorn (will be renamed),ou=Add/Delete,dc=example,dc=com
+changetype: modrdn
+newrdn: cn=Added by Bjorn (renamed by Jaj)
+deleteoldrdn: 1
+EOMODS13
+
+$LDAPMODIFY -D "$BJORNSDN" -h $LOCALHOST -p $PORT1 -w bjorn >> \
+ $TESTOUT 2>&1 << EOMODS14
+dn: cn=Added by Bjorn (must succeed),ou=Add/Delete,dc=example,dc=com
+changetype: modify
+delete: description
+description: Bjorn will try to delete this attribute value (should fail)
+-
+EOMODS14
+
+$LDAPMODIFY -D "$BABSDN" -h $LOCALHOST -p $PORT1 -w bjensen >> \
+ $TESTOUT 2>&1 << EOMODS15
+dn: cn=Added by Bjorn (will be deleted),ou=Add/Delete,dc=example,dc=com
+changetype: delete
+
+dn: cn=Added by Bjorn (must succeed),ou=Add/Delete,dc=example,dc=com
+changetype: modify
+delete: description
+description: this attribute value will be deleted by Babs (must succeed)
+-
+EOMODS15
+
echo "Using ldapsearch to retrieve all the entries..."
echo "# Using ldapsearch to retrieve all the entries..." >> $SEARCHOUT
$LDAPSEARCH -S "" -b "$BASEDN" -h $LOCALHOST -p $PORT1 \