static Avlnode *CfOcTree;
 
 static int config_add_internal( CfBackInfo *cfb, Entry *e, ConfigArgs *ca,
-       SlapReply *rs, int *renumber );
+       SlapReply *rs, int *renumber, Operation *op );
 
 static ConfigDriver config_fname;
 static ConfigDriver config_cfdir;
                setup_cookie *sc = op->o_callback->sc_private;
 
                sc->cfb->cb_got_ldif = 1;
-               rs->sr_err = config_add_internal( sc->cfb, rs->sr_entry, sc->ca, NULL, NULL );
+               rs->sr_err = config_add_internal( sc->cfb, rs->sr_entry, sc->ca, NULL, NULL, NULL );
                if ( rs->sr_err != LDAP_SUCCESS ) {
                        Debug( LDAP_DEBUG_ANY, "config error processing %s: %s\n",
                                rs->sr_entry->e_name.bv_val, sc->ca->msg, 0 );
 
 /* Parse an LDAP entry into config directives */
 static int
-config_add_internal( CfBackInfo *cfb, Entry *e, ConfigArgs *ca, SlapReply *rs, int *renum )
+config_add_internal( CfBackInfo *cfb, Entry *e, ConfigArgs *ca, SlapReply *rs,
+       int *renum, Operation *op )
 {
        CfEntryInfo *ce, *last;
        ConfigOCs **colst;
                return LDAP_NO_SUCH_OBJECT;
        }
 
+       if ( op ) {
+               /* No parent, must be root. This will never happen... */
+               if ( !last && !be_isroot( op ) && !be_shadow_update( op ))
+                       return LDAP_NO_SUCH_OBJECT;
+               if ( !access_allowed( op, last->ce_entry, slap_schema.si_ad_children,
+                       NULL, ACL_WADD, NULL ))
+                       return LDAP_INSUFFICIENT_ACCESS;
+       }
+
        oc_at = attr_find( e->e_attrs, slap_schema.si_ad_objectClass );
        if ( !oc_at ) return LDAP_OBJECT_CLASS_VIOLATION;
 
        int renumber;
        ConfigArgs ca;
 
-       if ( !be_isroot( op ) ) {
+       if ( !access_allowed( op, op->ora_e, slap_schema.si_ad_entry,
+               NULL, ACL_WADD, NULL )) {
                rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
                goto out;
        }
         */
        /* NOTE: by now we do not accept adds that require renumbering */
        renumber = -1;
-       rs->sr_err = config_add_internal( cfb, op->ora_e, &ca, rs, &renumber );
+       rs->sr_err = config_add_internal( cfb, op->ora_e, &ca, rs, &renumber, op );
        if ( rs->sr_err != LDAP_SUCCESS ) {
                rs->sr_text = ca.msg;
                goto out2;
        char *ptr;
        AttributeDescription *rad = NULL;
 
-       if ( !be_isroot( op ) ) {
-               rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
-               goto out;
-       }
-
        cfb = (CfBackInfo *)op->o_bd->be_private;
 
        ce = config_find_base( cfb->cb_root, &op->o_req_ndn, &last );
                goto out;
        }
 
+       if ( !acl_check_modlist( op, ce->ce_entry, op->orm_modlist )) {
+               rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
+               goto out;
+       }
+
        /* Get type of RDN */
        rdn = ce->ce_entry->e_nname;
        ptr = strchr( rdn.bv_val, '=' );
        CfBackInfo *cfb;
        CfEntryInfo *ce, *last;
 
-       if ( !be_isroot( op ) ) {
-               rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
-               goto out;
-       }
-
        cfb = (CfBackInfo *)op->o_bd->be_private;
 
        ce = config_find_base( cfb->cb_root, &op->o_req_ndn, &last );
                rs->sr_err = LDAP_NO_SUCH_OBJECT;
                goto out;
        }
+       if ( !access_allowed( op, ce->ce_entry, slap_schema.si_ad_entry,
+               NULL, ACL_WRITE, NULL )) {
+               rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
+               goto out;
+       }
+       { Entry *parent;
+               if ( ce->ce_parent )
+                       parent = ce->ce_parent->ce_entry;
+               else
+                       parent = (Entry *)&slap_entry_root;
+               if ( !access_allowed( op, parent, slap_schema.si_ad_children,
+                       NULL, ACL_WRITE, NULL )) {
+                       rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
+                       goto out;
+               }
+       }
 
        /* We don't allow moving objects to new parents.
         * Generally we only allow reordering a set of ordered entries.
 {
        CfBackInfo *cfb;
        CfEntryInfo *ce, *last;
-
-       if ( !be_isroot( op ) ) {
-               rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
-               goto out;
-       }
+       slap_mask_t mask;
 
        cfb = (CfBackInfo *)op->o_bd->be_private;
 
                rs->sr_err = LDAP_NO_SUCH_OBJECT;
                goto out;
        }
+       if ( !access_allowed_mask( op, ce->ce_entry, slap_schema.si_ad_entry, NULL,
+               ACL_SEARCH, NULL, &mask ))
+       {
+               if ( !ACL_GRANT( mask, ACL_DISCLOSE )) {
+                       rs->sr_err = LDAP_NO_SUCH_OBJECT;
+               } else {
+                       rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
+               }
+               goto out;
+       }
        switch ( op->ors_scope ) {
        case LDAP_SCOPE_BASE:
        case LDAP_SCOPE_SUBTREE:
        ConfigArgs ca;
 
        if ( bi && bi->bi_tool_entry_put &&
-               config_add_internal( cfb, e, &ca, NULL, NULL ) == 0 )
+               config_add_internal( cfb, e, &ca, NULL, NULL, NULL ) == 0 )
                return bi->bi_tool_entry_put( &cfb->cb_db, e, text );
        else
                return NOID;
 
        bi->bi_chk_referrals = 0;
 
-       bi->bi_access_allowed = slap_access_always_allowed;
+       bi->bi_access_allowed = slap_access_allowed;
 
        bi->bi_connection_init = 0;
        bi->bi_connection_destroy = 0;