]> git.sur5r.net Git - openldap/blobdiff - servers/slapd/bconfig.c
Switch example slapd.conf to use mdb instead of bdb
[openldap] / servers / slapd / bconfig.c
index 55f9dcdf032b05ebbcf0e6cd11bf41d9cfe5a870..f9b5531e8bef57ff6b3792f99ac433c13121d580 100644 (file)
@@ -2,7 +2,7 @@
 /* $OpenLDAP$ */
 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
  *
- * Copyright 2005-2011 The OpenLDAP Foundation.
+ * Copyright 2005-2013 The OpenLDAP Foundation.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -84,6 +84,7 @@ static char   *logfileName;
 #ifdef SLAP_AUTH_REWRITE
 static BerVarray authz_rewrites;
 #endif
+static AccessControl *defacl_parsed = NULL;
 
 static struct berval cfdir;
 
@@ -195,6 +196,10 @@ enum {
        CFG_ACL_ADD,
        CFG_SYNC_SUBENTRY,
        CFG_LTHREADS,
+       CFG_IX_HASH64,
+       CFG_DISABLED,
+       CFG_THREADQS,
+       CFG_TLS_ECNAME,
 
        CFG_LAST
 };
@@ -241,7 +246,7 @@ static OidRec OidMacros[] = {
  * OLcfg{Bk|Db}{Oc|At}:0               -> common
  * OLcfg{Bk|Db}{Oc|At}:1               -> back-bdb(/back-hdb)
  * OLcfg{Bk|Db}{Oc|At}:2               -> back-ldif
- * OLcfg{Bk|Db}{Oc|At}:3               -> back-ldap
+ * OLcfg{Bk|Db}{Oc|At}:3               -> back-ldap/meta
  * OLcfg{Bk|Db}{Oc|At}:4               -> back-monitor
  * OLcfg{Bk|Db}{Oc|At}:5               -> back-relay
  * OLcfg{Bk|Db}{Oc|At}:6               -> back-sql(/back-ndb)
@@ -249,6 +254,8 @@ static OidRec OidMacros[] = {
  * OLcfg{Bk|Db}{Oc|At}:8               -> back-null
  * OLcfg{Bk|Db}{Oc|At}:9               -> back-passwd
  * OLcfg{Bk|Db}{Oc|At}:10              -> back-shell
+ * OLcfg{Bk|Db}{Oc|At}:11              -> back-perl
+ * OLcfg{Bk|Db}{Oc|At}:12              -> back-mdb
  */
 
 /*
@@ -318,6 +325,7 @@ static ConfigTable config_back_cf_table[] = {
                &config_generic, "( OLcfgGlAt:4 NAME 'olcAttributeTypes' "
                        "DESC 'OpenLDAP attributeTypes' "
                        "EQUALITY caseIgnoreMatch "
+                       "SUBSTR caseIgnoreSubstringsMatch "
                        "SYNTAX OMsDirectoryString X-ORDERED 'VALUES' )",
                                NULL, NULL },
        { "authid-rewrite", NULL, 2, 0, STRLENOF( "authid-rewrite" ),
@@ -359,6 +367,9 @@ static ConfigTable config_back_cf_table[] = {
        { "defaultSearchBase", "dn", 2, 2, 0, ARG_PRE_BI|ARG_PRE_DB|ARG_DN|ARG_QUOTE|ARG_MAGIC,
                &config_search_base, "( OLcfgGlAt:14 NAME 'olcDefaultSearchBase' "
                        "SYNTAX OMsDN SINGLE-VALUE )", NULL, NULL },
+       { "disabled", "on|off", 2, 2, 0, ARG_DB|ARG_ON_OFF|ARG_MAGIC|CFG_DISABLED,
+               &config_generic, "( OLcfgDbAt:0.21 NAME 'olcDisabled' "
+                       "SYNTAX OMsBoolean SINGLE-VALUE )", NULL, NULL },
        { "disallows", "features", 2, 0, 8, ARG_PRE_DB|ARG_MAGIC,
                &config_disallows, "( OLcfgGlAt:15 NAME 'olcDisallows' "
                        "EQUALITY caseIgnoreMatch "
@@ -367,6 +378,7 @@ static ConfigTable config_back_cf_table[] = {
                &config_generic, "( OLcfgGlAt:16 NAME 'olcDitContentRules' "
                        "DESC 'OpenLDAP DIT content rules' "
                        "EQUALITY caseIgnoreMatch "
+                       "SUBSTR caseIgnoreSubstringsMatch "
                        "SYNTAX OMsDirectoryString X-ORDERED 'VALUES' )",
                        NULL, NULL },
        { "extra_attrs", "attrlist", 2, 2, 0, ARG_DB|ARG_MAGIC,
@@ -390,19 +402,22 @@ static ConfigTable config_back_cf_table[] = {
        { "include", "file", 2, 2, 0, ARG_MAGIC,
                &config_include, "( OLcfgGlAt:19 NAME 'olcInclude' "
                        "SUP labeledURI )", NULL, NULL },
+       { "index_hash64", "on|off", 2, 2, 0, ARG_ON_OFF|ARG_MAGIC|CFG_IX_HASH64,
+               &config_generic, "( OLcfgGlAt:94 NAME 'olcIndexHash64' "
+                       "SYNTAX OMsBoolean SINGLE-VALUE )", NULL, NULL },
        { "index_substr_if_minlen", "min", 2, 2, 0, ARG_UINT|ARG_NONZERO|ARG_MAGIC|CFG_SSTR_IF_MIN,
                &config_generic, "( OLcfgGlAt:20 NAME 'olcIndexSubstrIfMinLen' "
                        "SYNTAX OMsInteger SINGLE-VALUE )", NULL, NULL },
        { "index_substr_if_maxlen", "max", 2, 2, 0, ARG_UINT|ARG_NONZERO|ARG_MAGIC|CFG_SSTR_IF_MAX,
                &config_generic, "( OLcfgGlAt:21 NAME 'olcIndexSubstrIfMaxLen' "
                        "SYNTAX OMsInteger SINGLE-VALUE )", NULL, NULL },
-       { "index_substr_any_len", "len", 2, 2, 0, ARG_INT|ARG_NONZERO,
+       { "index_substr_any_len", "len", 2, 2, 0, ARG_UINT|ARG_NONZERO,
                &index_substr_any_len, "( OLcfgGlAt:22 NAME 'olcIndexSubstrAnyLen' "
                        "SYNTAX OMsInteger SINGLE-VALUE )", NULL, NULL },
-       { "index_substr_any_step", "step", 2, 2, 0, ARG_INT|ARG_NONZERO,
+       { "index_substr_any_step", "step", 2, 2, 0, ARG_UINT|ARG_NONZERO,
                &index_substr_any_step, "( OLcfgGlAt:23 NAME 'olcIndexSubstrAnyStep' "
                        "SYNTAX OMsInteger SINGLE-VALUE )", NULL, NULL },
-       { "index_intlen", "len", 2, 2, 0, ARG_INT|ARG_MAGIC|CFG_IX_INTLEN,
+       { "index_intlen", "len", 2, 2, 0, ARG_UINT|ARG_MAGIC|CFG_IX_INTLEN,
                &config_generic, "( OLcfgGlAt:84 NAME 'olcIndexIntLen' "
                        "SYNTAX OMsInteger SINGLE-VALUE )", NULL, NULL },
        { "lastmod", "on|off", 2, 2, 0, ARG_DB|ARG_ON_OFF|ARG_MAGIC|CFG_LASTMOD,
@@ -413,6 +428,7 @@ static ConfigTable config_back_cf_table[] = {
                &config_generic, "( OLcfgGlAt:85 NAME 'olcLdapSyntaxes' "
                        "DESC 'OpenLDAP ldapSyntax' "
                        "EQUALITY caseIgnoreMatch "
+                       "SUBSTR caseIgnoreSubstringsMatch "
                        "SYNTAX OMsDirectoryString X-ORDERED 'VALUES' )",
                                NULL, NULL },
        { "limits", "limits", 2, 0, 0, ARG_DB|ARG_MAGIC|CFG_LIMITS,
@@ -468,11 +484,13 @@ static ConfigTable config_back_cf_table[] = {
                &config_generic, "( OLcfgGlAt:32 NAME 'olcObjectClasses' "
                "DESC 'OpenLDAP object classes' "
                "EQUALITY caseIgnoreMatch "
+               "SUBSTR caseIgnoreSubstringsMatch "
                "SYNTAX OMsDirectoryString X-ORDERED 'VALUES' )",
                        NULL, NULL },
        { "objectidentifier", "name> <oid",     3, 3, 0, ARG_MAGIC|CFG_OID,
                &config_generic, "( OLcfgGlAt:33 NAME 'olcObjectIdentifier' "
                        "EQUALITY caseIgnoreMatch "
+                       "SUBSTR caseIgnoreSubstringsMatch "
                        "SYNTAX OMsDirectoryString X-ORDERED 'VALUES' )", NULL, NULL },
        { "overlay", "overlay", 2, 2, 0, ARG_MAGIC,
                &config_overlay, "( OLcfgGlAt:34 NAME 'olcOverlay' "
@@ -667,10 +685,18 @@ static ConfigTable config_back_cf_table[] = {
 #endif
                "( OLcfgGlAt:66 NAME 'olcThreads' "
                        "SYNTAX OMsInteger SINGLE-VALUE )", NULL, NULL },
+       { "threadqueues", "count", 2, 2, 0,
+#ifdef NO_THREADS
+               ARG_IGNORED, NULL,
+#else
+               ARG_INT|ARG_MAGIC|CFG_THREADQS, &config_generic,
+#endif
+               "( OLcfgGlAt:95 NAME 'olcThreadQueues' "
+                       "SYNTAX OMsInteger SINGLE-VALUE )", NULL, NULL },
        { "timelimit", "limit", 2, 0, 0, ARG_MAY_DB|ARG_MAGIC,
                &config_timelimit, "( OLcfgGlAt:67 NAME 'olcTimeLimit' "
                        "SYNTAX OMsDirectoryString )", NULL, NULL },
-       { "TLSCACertificateFile", NULL, 0, 0, 0,
+       { "TLSCACertificateFile", NULL, 2, 2, 0,
 #ifdef HAVE_TLS
                CFG_TLS_CA_FILE|ARG_STRING|ARG_MAGIC, &config_tls_option,
 #else
@@ -678,7 +704,7 @@ static ConfigTable config_back_cf_table[] = {
 #endif
                "( OLcfgGlAt:68 NAME 'olcTLSCACertificateFile' "
                        "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
-       { "TLSCACertificatePath", NULL, 0, 0, 0,
+       { "TLSCACertificatePath", NULL, 2, 2, 0,
 #ifdef HAVE_TLS
                CFG_TLS_CA_PATH|ARG_STRING|ARG_MAGIC, &config_tls_option,
 #else
@@ -686,7 +712,7 @@ static ConfigTable config_back_cf_table[] = {
 #endif
                "( OLcfgGlAt:69 NAME 'olcTLSCACertificatePath' "
                        "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
-       { "TLSCertificateFile", NULL, 0, 0, 0,
+       { "TLSCertificateFile", NULL, 2, 2, 0,
 #ifdef HAVE_TLS
                CFG_TLS_CERT_FILE|ARG_STRING|ARG_MAGIC, &config_tls_option,
 #else
@@ -694,7 +720,7 @@ static ConfigTable config_back_cf_table[] = {
 #endif
                "( OLcfgGlAt:70 NAME 'olcTLSCertificateFile' "
                        "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
-       { "TLSCertificateKeyFile", NULL, 0, 0, 0,
+       { "TLSCertificateKeyFile", NULL, 2, 2, 0,
 #ifdef HAVE_TLS
                CFG_TLS_CERT_KEY|ARG_STRING|ARG_MAGIC, &config_tls_option,
 #else
@@ -702,7 +728,7 @@ static ConfigTable config_back_cf_table[] = {
 #endif
                "( OLcfgGlAt:71 NAME 'olcTLSCertificateKeyFile' "
                        "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
-       { "TLSCipherSuite",     NULL, 0, 0, 0,
+       { "TLSCipherSuite",     NULL, 2, 2, 0,
 #ifdef HAVE_TLS
                CFG_TLS_CIPHER|ARG_STRING|ARG_MAGIC, &config_tls_option,
 #else
@@ -710,7 +736,7 @@ static ConfigTable config_back_cf_table[] = {
 #endif
                "( OLcfgGlAt:72 NAME 'olcTLSCipherSuite' "
                        "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
-       { "TLSCRLCheck", NULL, 0, 0, 0,
+       { "TLSCRLCheck", NULL, 2, 2, 0,
 #if defined(HAVE_TLS) && defined(HAVE_OPENSSL_CRL)
                CFG_TLS_CRLCHECK|ARG_STRING|ARG_MAGIC, &config_tls_config,
 #else
@@ -718,7 +744,7 @@ static ConfigTable config_back_cf_table[] = {
 #endif
                "( OLcfgGlAt:73 NAME 'olcTLSCRLCheck' "
                        "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
-       { "TLSCRLFile", NULL, 0, 0, 0,
+       { "TLSCRLFile", NULL, 2, 2, 0,
 #if defined(HAVE_GNUTLS)
                CFG_TLS_CRL_FILE|ARG_STRING|ARG_MAGIC, &config_tls_option,
 #else
@@ -726,7 +752,7 @@ static ConfigTable config_back_cf_table[] = {
 #endif
                "( OLcfgGlAt:82 NAME 'olcTLSCRLFile' "
                        "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
-       { "TLSRandFile", NULL, 0, 0, 0,
+       { "TLSRandFile", NULL, 2, 2, 0,
 #ifdef HAVE_TLS
                CFG_TLS_RAND|ARG_STRING|ARG_MAGIC, &config_tls_option,
 #else
@@ -734,7 +760,7 @@ static ConfigTable config_back_cf_table[] = {
 #endif
                "( OLcfgGlAt:74 NAME 'olcTLSRandFile' "
                        "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
-       { "TLSVerifyClient", NULL, 0, 0, 0,
+       { "TLSVerifyClient", NULL, 2, 2, 0,
 #ifdef HAVE_TLS
                CFG_TLS_VERIFY|ARG_STRING|ARG_MAGIC, &config_tls_config,
 #else
@@ -742,7 +768,7 @@ static ConfigTable config_back_cf_table[] = {
 #endif
                "( OLcfgGlAt:75 NAME 'olcTLSVerifyClient' "
                        "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
-       { "TLSDHParamFile", NULL, 0, 0, 0,
+       { "TLSDHParamFile", NULL, 2, 2, 0,
 #ifdef HAVE_TLS
                CFG_TLS_DH_FILE|ARG_STRING|ARG_MAGIC, &config_tls_option,
 #else
@@ -750,7 +776,15 @@ static ConfigTable config_back_cf_table[] = {
 #endif
                "( OLcfgGlAt:77 NAME 'olcTLSDHParamFile' "
                        "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
-       { "TLSProtocolMin",     NULL, 0, 0, 0,
+       { "TLSECName", NULL, 2, 2, 0,
+#ifdef HAVE_TLS
+               CFG_TLS_ECNAME|ARG_STRING|ARG_MAGIC, &config_tls_option,
+#else
+               ARG_IGNORED, NULL,
+#endif
+               "( OLcfgGlAt:96 NAME 'olcTLSECName' "
+                       "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
+       { "TLSProtocolMin",     NULL, 2, 2, 0,
 #ifdef HAVE_TLS
                CFG_TLS_PROTOCOL_MIN|ARG_STRING|ARG_MAGIC, &config_tls_config,
 #else
@@ -818,8 +852,9 @@ static ConfigOCs cf_ocs[] = {
                 "olcConnMaxPending $ olcConnMaxPendingAuth $ "
                 "olcDisallows $ olcGentleHUP $ olcIdleTimeout $ "
                 "olcIndexSubstrIfMaxLen $ olcIndexSubstrIfMinLen $ "
-                "olcIndexSubstrAnyLen $ olcIndexSubstrAnyStep $ olcIndexIntLen $ "
-                "olcLocalSSF $ olcLogFile $ olcLogLevel $ "
+                "olcIndexSubstrAnyLen $ olcIndexSubstrAnyStep $ olcIndexHash64 $ "
+                "olcIndexIntLen $ "
+                "olcListenerThreads $ olcLocalSSF $ olcLogFile $ olcLogLevel $ "
                 "olcPasswordCryptSaltFormat $ olcPasswordHash $ olcPidFile $ "
                 "olcPluginLogFile $ olcReadOnly $ olcReferral $ "
                 "olcReplogFile $ olcRequires $ olcRestrict $ olcReverseLookup $ "
@@ -829,19 +864,20 @@ static ConfigOCs cf_ocs[] = {
                 "olcSecurity $ olcServerID $ olcSizeLimit $ "
                 "olcSockbufMaxIncoming $ olcSockbufMaxIncomingAuth $ "
                 "olcTCPBuffer $ "
-                "olcThreads $ olcTimeLimit $ olcTLSCACertificateFile $ "
+                "olcThreads $ olcThreadQueues $ "
+                "olcTimeLimit $ olcTLSCACertificateFile $ "
                 "olcTLSCACertificatePath $ olcTLSCertificateFile $ "
                 "olcTLSCertificateKeyFile $ olcTLSCipherSuite $ olcTLSCRLCheck $ "
-                "olcTLSRandFile $ olcTLSVerifyClient $ olcTLSDHParamFile $ "
-                "olcTLSCRLFile $ olcToolThreads $ olcWriteTimeout $ "
+                "olcTLSRandFile $ olcTLSVerifyClient $ olcTLSDHParamFile $ olcTLSECName $ "
+                "olcTLSCRLFile $ olcTLSProtocolMin $ olcToolThreads $ olcWriteTimeout $ "
                 "olcObjectIdentifier $ olcAttributeTypes $ olcObjectClasses $ "
                 "olcDitContentRules $ olcLdapSyntaxes ) )", Cft_Global },
        { "( OLcfgGlOc:2 "
                "NAME 'olcSchemaConfig' "
                "DESC 'OpenLDAP schema object' "
                "SUP olcConfig STRUCTURAL "
-               "MAY ( cn $ olcObjectIdentifier $ olcAttributeTypes $ "
-                "olcObjectClasses $ olcDitContentRules $ olcLdapSyntaxes ) )",
+               "MAY ( cn $ olcObjectIdentifier $ olcLdapSyntaxes $ "
+                "olcAttributeTypes $ olcObjectClasses $ olcDitContentRules ) )",
                        Cft_Schema, NULL, cfAddSchema },
        { "( OLcfgGlOc:3 "
                "NAME 'olcBackendConfig' "
@@ -853,7 +889,7 @@ static ConfigOCs cf_ocs[] = {
                "DESC 'OpenLDAP Database-specific options' "
                "SUP olcConfig STRUCTURAL "
                "MUST olcDatabase "
-               "MAY ( olcHidden $ olcSuffix $ olcSubordinate $ olcAccess $ "
+               "MAY ( olcDisabled $ olcHidden $ olcSuffix $ olcSubordinate $ olcAccess $ "
                 "olcAddContentAcl $ olcLastMod $ olcLimits $ "
                 "olcMaxDerefDepth $ olcPlugin $ olcReadOnly $ olcReplica $ "
                 "olcReplicaArgsFile $ olcReplicaPidFile $ olcReplicationInterval $ "
@@ -866,7 +902,8 @@ static ConfigOCs cf_ocs[] = {
                "NAME 'olcOverlayConfig' "
                "DESC 'OpenLDAP Overlay-specific options' "
                "SUP olcConfig STRUCTURAL "
-               "MUST olcOverlay )", Cft_Overlay, NULL, cfAddOverlay },
+               "MUST olcOverlay "
+               "MAY olcDisabled )", Cft_Overlay, NULL, cfAddOverlay },
        { "( OLcfgGlOc:6 "
                "NAME 'olcIncludeFile' "
                "DESC 'OpenLDAP configuration include file' "
@@ -903,6 +940,7 @@ typedef struct ServerID {
 } ServerID;
 
 static ServerID *sid_list;
+static ServerID *sid_set;
 
 typedef struct voidList {
        struct voidList *vl_next;
@@ -929,6 +967,9 @@ config_generic(ConfigArgs *c) {
                case CFG_THREADS:
                        c->value_int = connection_pool_max;
                        break;
+               case CFG_THREADQS:
+                       c->value_int = connection_pool_queues;
+                       break;
                case CFG_TTHREADS:
                        c->value_int = slap_tool_thread_max;
                        break;
@@ -1030,6 +1071,23 @@ config_generic(ConfigArgs *c) {
                case CFG_DEPTH:
                        c->value_int = c->be->be_max_deref_depth;
                        break;
+               case CFG_DISABLED:
+                       if ( c->bi ) {
+                               /* overlay */
+                               if ( c->bi->bi_flags & SLAPO_BFLAG_DISABLED ) {
+                                       c->value_int = 1;
+                               } else {
+                                       rc = 1;
+                               }
+                       } else {
+                               /* database */
+                               if ( SLAP_DBDISABLED( c->be )) {
+                                       c->value_int = 1;
+                               } else {
+                                       rc = 1;
+                               }
+                       }
+                       break;
                case CFG_HIDDEN:
                        if ( SLAP_DBHIDDEN( c->be )) {
                                c->value_int = 1;
@@ -1177,7 +1235,7 @@ config_generic(ConfigArgs *c) {
                        break;
                case CFG_MIRRORMODE:
                        if ( SLAP_SHADOW(c->be))
-                               c->value_int = (SLAP_SINGLE_SHADOW(c->be) == 0);
+                               c->value_int = (SLAP_MULTIMASTER(c->be) != 0);
                        else
                                rc = 1;
                        break;
@@ -1190,6 +1248,9 @@ config_generic(ConfigArgs *c) {
                case CFG_SSTR_IF_MIN:
                        c->value_uint = index_substr_if_minlen;
                        break;
+               case CFG_IX_HASH64:
+                       c->value_int = slap_hash64( -1 );
+                       break;
                case CFG_IX_INTLEN:
                        c->value_int = index_intlen;
                        break;
@@ -1276,13 +1337,13 @@ config_generic(ConfigArgs *c) {
                /* single-valued attrs, no-ops */
                case CFG_CONCUR:
                case CFG_THREADS:
+               case CFG_THREADQS:
                case CFG_TTHREADS:
                case CFG_LTHREADS:
                case CFG_RO:
                case CFG_AZPOLICY:
                case CFG_DEPTH:
                case CFG_LASTMOD:
-               case CFG_MIRRORMODE:
                case CFG_MONITORING:
                case CFG_SASLSECP:
                case CFG_SSTR_IF_MAX:
@@ -1299,6 +1360,12 @@ config_generic(ConfigArgs *c) {
                        snprintf(c->log, sizeof( c->log ), "change requires slapd restart");
                        break;
 
+               case CFG_MIRRORMODE:
+                       SLAP_DBFLAGS(c->be) &= ~SLAP_DBFLAG_MULTI_SHADOW;
+                       if(SLAP_SHADOW(c->be))
+                               SLAP_DBFLAGS(c->be) |= SLAP_DBFLAG_SINGLE_SHADOW;
+                       break;
+
 #if defined(HAVE_CYRUS_SASL) && defined(SLAP_AUXPROP_DONTUSECOPY)
                case CFG_AZDUC:
                        if ( c->valx < 0 ) {
@@ -1349,6 +1416,8 @@ config_generic(ConfigArgs *c) {
                                si; si = *sip, i++ ) {
                                if ( c->valx == -1 || i == c->valx ) {
                                        *sip = si->si_next;
+                                       if ( sid_set == si )
+                                               sid_set = NULL;
                                        ch_free( si );
                                        if ( c->valx >= 0 )
                                                break;
@@ -1362,6 +1431,25 @@ config_generic(ConfigArgs *c) {
                        c->be->be_flags &= ~SLAP_DBFLAG_HIDDEN;
                        break;
 
+               case CFG_DISABLED:
+                       if ( c->bi ) {
+                               c->bi->bi_flags &= ~SLAP_DBFLAG_DISABLED;
+                               if ( c->bi->bi_db_open ) {
+                                       BackendInfo *bi_orig = c->be->bd_info;
+                                       c->be->bd_info = c->bi;
+                                       rc = c->bi->bi_db_open( c->be, &c->reply );
+                                       c->be->bd_info = bi_orig;
+                               }
+                       } else {
+                               c->be->be_flags &= ~SLAP_DBFLAG_DISABLED;
+                               rc = backend_startup_one( c->be, &c->reply );
+                       }
+                       break;
+
+               case CFG_IX_HASH64:
+                       slap_hash64( 0 );
+                       break;
+
                case CFG_IX_INTLEN:
                        index_intlen = SLAP_INDEX_INTLEN_DEFAULT;
                        index_intlen_strlen = SLAP_INDEX_INTLEN_STRLEN(
@@ -1385,6 +1473,12 @@ config_generic(ConfigArgs *c) {
                                *prev = a->acl_next;
                                acl_free( a );
                        }
+                       if ( SLAP_CONFIG( c->be ) && !c->be->be_acl ) {
+                               Debug( LDAP_DEBUG_CONFIG, "config_generic (CFG_ACL): "
+                                               "Last explicit ACL for back-config removed. "
+                                               "Using hardcoded default\n", 0, 0, 0 );
+                               c->be->be_acl = defacl_parsed;
+                       }
                        break;
 
                case CFG_OC: {
@@ -1623,6 +1717,20 @@ config_generic(ConfigArgs *c) {
                        connection_pool_max = c->value_int;     /* save for reference */
                        break;
 
+               case CFG_THREADQS:
+                       if ( c->value_int < 1 ) {
+                               snprintf( c->cr_msg, sizeof( c->cr_msg ),
+                                       "threadqueuess=%d smaller than minimum value 1",
+                                       c->value_int );
+                               Debug(LDAP_DEBUG_ANY, "%s: %s.\n",
+                                       c->log, c->cr_msg, 0 );
+                               return 1;
+                       }
+                       if ( slapMode & SLAP_SERVER_MODE )
+                               ldap_pvt_thread_pool_queues(&connection_pool, c->value_int);
+                       connection_pool_queues = c->value_int;  /* save for reference */
+                       break;
+
                case CFG_TTHREADS:
                        if ( slapMode & SLAP_TOOL_MODE )
                                ldap_pvt_thread_pool_maxthreads(&connection_pool, c->value_int);
@@ -1760,7 +1868,8 @@ config_generic(ConfigArgs *c) {
                                        int i;
                                        for (i=0, oc = cfn->c_oc_head; i<c->valx; i++) {
                                                prev = oc;
-                                               oc_next( &oc );
+                                               if ( !oc_next( &oc ))
+                                                       break;
                                        }
                                } else
                                /* If adding the first, and head exists, find its prev */
@@ -1773,7 +1882,7 @@ config_generic(ConfigArgs *c) {
                                /* else prev is NULL, append to end of global list */
                        }
                        if(parse_oc(c, &oc, prev)) return(1);
-                       if (!cfn->c_oc_head) cfn->c_oc_head = oc;
+                       if (!cfn->c_oc_head || !c->valx) cfn->c_oc_head = oc;
                        if (cfn->c_oc_tail == prev) cfn->c_oc_tail = oc;
                        }
                        break;
@@ -1792,7 +1901,8 @@ config_generic(ConfigArgs *c) {
                                        int i;
                                        for (i=0, at = cfn->c_at_head; i<c->valx; i++) {
                                                prev = at;
-                                               at_next( &at );
+                                               if ( !at_next( &at ))
+                                                       break;
                                        }
                                } else
                                /* If adding the first, and head exists, find its prev */
@@ -1805,7 +1915,7 @@ config_generic(ConfigArgs *c) {
                                /* else prev is NULL, append to end of global list */
                        }
                        if(parse_at(c, &at, prev)) return(1);
-                       if (!cfn->c_at_head) cfn->c_at_head = at;
+                       if (!cfn->c_at_head || !c->valx) cfn->c_at_head = at;
                        if (cfn->c_at_tail == prev) cfn->c_at_tail = at;
                        }
                        break;
@@ -1824,7 +1934,8 @@ config_generic(ConfigArgs *c) {
                                        int i;
                                        for ( i = 0, syn = cfn->c_syn_head; i < c->valx; i++ ) {
                                                prev = syn;
-                                               syn_next( &syn );
+                                               if ( !syn_next( &syn ))
+                                                       break;
                                        }
                                } else
                                /* If adding the first, and head exists, find its prev */
@@ -1837,7 +1948,7 @@ config_generic(ConfigArgs *c) {
                                /* else prev is NULL, append to end of global list */
                        }
                        if ( parse_syn( c, &syn, prev ) ) return(1);
-                       if ( !cfn->c_syn_head ) cfn->c_syn_head = syn;
+                       if ( !cfn->c_syn_head || !c->valx ) cfn->c_syn_head = syn;
                        if ( cfn->c_syn_tail == prev ) cfn->c_syn_tail = syn;
                        }
                        break;
@@ -1860,6 +1971,11 @@ config_generic(ConfigArgs *c) {
                                        return(1);
                        break;
 
+               case CFG_IX_HASH64:
+                       if ( slap_hash64( c->value_int != 0 ))
+                               return 1;
+                       break;
+
                case CFG_IX_INTLEN:
                        if ( c->value_int < SLAP_INDEX_INTLEN_DEFAULT )
                                c->value_int = SLAP_INDEX_INTLEN_DEFAULT;
@@ -1869,7 +1985,7 @@ config_generic(ConfigArgs *c) {
                        index_intlen_strlen = SLAP_INDEX_INTLEN_STRLEN(
                                index_intlen );
                        break;
-                       
+
                case CFG_SORTVALS: {
                        ADlist *svnew = NULL, *svtail, *sv;
 
@@ -1918,6 +2034,9 @@ sortval_reject:
                        break;
 
                case CFG_ACL:
+                       if ( SLAP_CONFIG( c->be ) && c->be->be_acl == defacl_parsed) {
+                               c->be->be_acl = NULL;
+                       }
                        /* Don't append to the global ACL if we're on a specific DB */
                        i = c->valx;
                        if ( c->valx == -1 ) {
@@ -1927,6 +2046,9 @@ sortval_reject:
                                        i++;
                        }
                        if ( parse_acl(c->be, c->fname, c->lineno, c->argc, c->argv, i ) ) {
+                               if ( SLAP_CONFIG( c->be ) && !c->be->be_acl) {
+                                       c->be->be_acl = defacl_parsed;
+                               }
                                return 1;
                        }
                        break;
@@ -2007,6 +2129,7 @@ sortval_reject:
                                        Debug( LDAP_DEBUG_CONFIG,
                                                "%s: SID=0x%03x\n",
                                                c->log, slap_serverID, 0 );
+                                       sid_set = si;
                                }
                                si->si_next = NULL;
                                si->si_num = num;
@@ -2016,11 +2139,20 @@ sortval_reject:
                                if (( slapMode & SLAP_SERVER_MODE ) && c->argc > 2 ) {
                                        Listener *l = config_check_my_url( c->argv[2], lud );
                                        if ( l ) {
+                                               if ( sid_set ) {
+                                                       ldap_free_urldesc( lud );
+                                                       snprintf( c->cr_msg, sizeof( c->cr_msg ),
+                                                               "<%s> multiple server ID URLs matched, only one is allowed", c->argv[0] );
+                                                       Debug(LDAP_DEBUG_ANY, "%s: %s %s\n",
+                                                               c->log, c->cr_msg, c->argv[1] );
+                                                       return 1;
+                                               }
                                                slap_serverID = si->si_num;
                                                Debug( LDAP_DEBUG_CONFIG,
                                                        "%s: SID=0x%03x (listener=%s)\n",
                                                        c->log, slap_serverID,
                                                        l->sl_url.bv_val );
+                                               sid_set = si;
                                        }
                                }
                                if ( c->argc > 2 )
@@ -2056,10 +2188,13 @@ sortval_reject:
                                        c->log, c->cr_msg, 0 );
                                return(1);
                        }
-                       if(c->value_int)
+                       if(c->value_int) {
                                SLAP_DBFLAGS(c->be) &= ~SLAP_DBFLAG_SINGLE_SHADOW;
-                       else
+                               SLAP_DBFLAGS(c->be) |= SLAP_DBFLAG_MULTI_SHADOW;
+                       } else {
                                SLAP_DBFLAGS(c->be) |= SLAP_DBFLAG_SINGLE_SHADOW;
+                               SLAP_DBFLAGS(c->be) &= ~SLAP_DBFLAG_MULTI_SHADOW;
+                       }
                        break;
 
                case CFG_MONITORING:
@@ -2069,6 +2204,29 @@ sortval_reject:
                                SLAP_DBFLAGS(c->be) &= ~SLAP_DBFLAG_MONITORING;
                        break;
 
+               case CFG_DISABLED:
+                       if ( c->bi ) {
+                               if (c->value_int) {
+                                       if ( c->bi->bi_db_close ) {
+                                               BackendInfo *bi_orig = c->be->bd_info;
+                                               c->be->bd_info = c->bi;
+                                               c->bi->bi_db_close( c->be, &c->reply );
+                                               c->be->bd_info = bi_orig;
+                                       }
+                                       c->bi->bi_flags |= SLAPO_BFLAG_DISABLED;
+                               } else {
+                                       c->bi->bi_flags &= ~SLAPO_BFLAG_DISABLED;
+                               }
+                       } else {
+                               if (c->value_int) {
+                                       backend_shutdown( c->be );
+                                       SLAP_DBFLAGS(c->be) |= SLAP_DBFLAG_DISABLED;
+                               } else {
+                                       SLAP_DBFLAGS(c->be) &= ~SLAP_DBFLAG_DISABLED;
+                               }
+                       }
+                       break;
+
                case CFG_HIDDEN:
                        if (c->value_int)
                                SLAP_DBFLAGS(c->be) |= SLAP_DBFLAG_HIDDEN;
@@ -3026,7 +3184,8 @@ config_suffix(ConfigArgs *c)
        }
 #endif
 
-       if (SLAP_DB_ONE_SUFFIX( c->be ) && c->be->be_suffix ) {
+       if (SLAP_DB_ONE_SUFFIX( c->be ) && c->be->be_suffix &&
+               !BER_BVISNULL( &c->be->be_suffix[0] )) {
                snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> Only one suffix is allowed on this %s backend",
                        c->argv[0], c->be->bd_info->bi_type );
                Debug(LDAP_DEBUG_ANY, "%s: %s\n",
@@ -3170,8 +3329,8 @@ config_restrict(ConfigArgs *c) {
                if ( !c->line ) {
                        c->be->be_restrictops = 0;
                } else {
-                       restrictops = verb_to_mask( c->line, restrictable_ops );
-                       c->be->be_restrictops ^= restrictops;
+                       i = verb_to_mask( c->line, restrictable_ops );
+                       c->be->be_restrictops &= ~restrictable_ops[i].mask;
                }
                return 0;
        }
@@ -3206,8 +3365,8 @@ config_allows(ConfigArgs *c) {
                if ( !c->line ) {
                        global_allows = 0;
                } else {
-                       allows = verb_to_mask( c->line, allowable_ops );
-                       global_allows ^= allows;
+                       i = verb_to_mask( c->line, allowable_ops );
+                       global_allows &= ~allowable_ops[i].mask;
                }
                return 0;
        }
@@ -3241,8 +3400,8 @@ config_disallows(ConfigArgs *c) {
                if ( !c->line ) {
                        global_disallows = 0;
                } else {
-                       disallows = verb_to_mask( c->line, disallowable_ops );
-                       global_disallows ^= disallows;
+                       i = verb_to_mask( c->line, disallowable_ops );
+                       global_disallows &= ~disallowable_ops[i].mask;
                }
                return 0;
        }
@@ -3277,8 +3436,8 @@ config_requires(ConfigArgs *c) {
                if ( !c->line ) {
                        c->be->be_requires = 0;
                } else {
-                       requires = verb_to_mask( c->line, requires_ops );
-                       c->be->be_requires ^= requires;
+                       i = verb_to_mask( c->line, requires_ops );
+                       c->be->be_requires &= ~requires_ops[i].mask;
                }
                return 0;
        }
@@ -3501,6 +3660,10 @@ loglevel2bvarray( int l, BerVarray *bva )
                loglevel_init();
        }
 
+       if ( l == 0 ) {
+               return value_add_one( bva, ber_bvstr( "0" ) );
+       }
+
        return mask_to_verbs( loglevel_ops, l, bva );
 }
 
@@ -3548,8 +3711,8 @@ config_loglevel(ConfigArgs *c) {
                if ( !c->line ) {
                        config_syslog = 0;
                } else {
-                       int level = verb_to_mask( c->line, loglevel_ops );
-                       config_syslog ^= level;
+                       i = verb_to_mask( c->line, loglevel_ops );
+                       config_syslog &= ~loglevel_ops[i].mask;
                }
                if ( slapMode & SLAP_SERVER_MODE ) {
                        ldap_syslog = config_syslog;
@@ -3771,7 +3934,9 @@ config_shadow( ConfigArgs *c, slap_mask_t flag )
                }
 
        } else {
-               SLAP_DBFLAGS(c->be) |= (SLAP_DBFLAG_SHADOW | SLAP_DBFLAG_SINGLE_SHADOW | flag);
+               SLAP_DBFLAGS(c->be) |= (SLAP_DBFLAG_SHADOW | flag);
+               if ( !SLAP_MULTIMASTER( c->be ))
+                       SLAP_DBFLAGS(c->be) |= SLAP_DBFLAG_SINGLE_SHADOW;
        }
 
        return 0;
@@ -3873,6 +4038,7 @@ config_tls_cleanup(ConfigArgs *c) {
                int opt = 1;
 
                ldap_pvt_tls_ctx_free( slap_tls_ctx );
+               slap_tls_ctx = NULL;
 
                /* Force new ctx to be created */
                rc = ldap_pvt_tls_set_option( slap_tls_ld, LDAP_OPT_X_TLS_NEWCTX, &opt );
@@ -3881,6 +4047,11 @@ config_tls_cleanup(ConfigArgs *c) {
                        ldap_pvt_tls_get_option( slap_tls_ld, LDAP_OPT_X_TLS_CTX, &slap_tls_ctx );
                        /* This is a no-op if it's already loaded */
                        load_extop( &slap_EXOP_START_TLS, 0, starttls_extop );
+               } else {
+                       if ( rc == LDAP_NOT_SUPPORTED )
+                               rc = LDAP_UNWILLING_TO_PERFORM;
+                       else
+                               rc = LDAP_OTHER;
                }
        }
        return rc;
@@ -3898,6 +4069,7 @@ config_tls_option(ConfigArgs *c) {
        case CFG_TLS_CA_PATH:   flag = LDAP_OPT_X_TLS_CACERTDIR;        break;
        case CFG_TLS_CA_FILE:   flag = LDAP_OPT_X_TLS_CACERTFILE;       break;
        case CFG_TLS_DH_FILE:   flag = LDAP_OPT_X_TLS_DHFILE;   break;
+       case CFG_TLS_ECNAME:    flag = LDAP_OPT_X_TLS_ECNAME;   break;
 #ifdef HAVE_GNUTLS
        case CFG_TLS_CRL_FILE:  flag = LDAP_OPT_X_TLS_CRLFILE;  break;
 #endif
@@ -3940,7 +4112,7 @@ config_tls_config(ConfigArgs *c) {
        }
        ch_free( c->value_string );
        c->cleanup = config_tls_cleanup;
-       if ( isdigit( (unsigned char)c->argv[1][0] ) ) {
+       if ( isdigit( (unsigned char)c->argv[1][0] ) && c->type != CFG_TLS_PROTOCOL_MIN ) {
                if ( lutil_atoi( &i, c->argv[1] ) != 0 ) {
                        Debug(LDAP_DEBUG_ANY, "%s: "
                                "unable to parse %s \"%s\"\n",
@@ -4327,6 +4499,13 @@ done:
                        assert( 0 );
                }
        }
+       if ( rc == 0 && ( slapMode & SLAP_SERVER_MODE ) && sid_list ) {
+               if ( !BER_BVISEMPTY( &sid_list->si_url ) && !sid_set ) {
+                       Debug(LDAP_DEBUG_ANY, "read_config: no serverID / URL match found. "
+                               "Check slapd -h arguments.\n", 0,0,0 );
+                       rc = LDAP_OTHER;
+               }
+       }
        return rc;
 }
 
@@ -4712,9 +4891,34 @@ check_name_index( CfEntryInfo *parent, ConfigType ce_type, Entry *e,
                }
        }
 
-       /* count related kids */
-       for (nsibs=0, ce=parent->ce_kids; ce; ce=ce->ce_sibs) {
-               if ( ce->ce_type == ce_type ) nsibs++;
+       /* count related kids.
+        * For entries of type Cft_Misc, only count siblings with same RDN type
+        */
+       if ( ce_type == Cft_Misc ) {
+               rdn.bv_val = e->e_nname.bv_val;
+               ptr1 = strchr( rdn.bv_val, '=' );
+               assert( ptr1 != NULL );
+
+               rdn.bv_len = ptr1 - rdn.bv_val;
+
+               for (nsibs=0, ce=parent->ce_kids; ce; ce=ce->ce_sibs) {
+                       struct berval rdn2;
+                       if ( ce->ce_type != ce_type )
+                               continue;
+
+                       dnRdn( &ce->ce_entry->e_nname, &rdn2 );
+
+                       ptr1 = strchr( rdn2.bv_val, '=' );
+                       assert( ptr1 != NULL );
+
+                       rdn2.bv_len = ptr1 - rdn2.bv_val;
+                       if ( bvmatch( &rdn, &rdn2 ))
+                               nsibs++;
+               }
+       } else {
+               for (nsibs=0, ce=parent->ce_kids; ce; ce=ce->ce_sibs) {
+                       if ( ce->ce_type == ce_type ) nsibs++;
+               }
        }
 
        /* account for -1 frontend */
@@ -4748,12 +4952,19 @@ check_name_index( CfEntryInfo *parent, ConfigType ce_type, Entry *e,
        return rc;
 }
 
+/* Insert all superior classes of the given class */
 static int
 count_oc( ObjectClass *oc, ConfigOCs ***copp, int *nocs )
 {
        ConfigOCs       co, *cop;
        ObjectClass     **sups;
 
+       for ( sups = oc->soc_sups; sups && *sups; sups++ ) {
+               if ( count_oc( *sups, copp, nocs ) ) {
+                       return -1;
+               }
+       }
+
        co.co_name = &oc->soc_cname;
        cop = avl_find( CfOcTree, &co, CfOc_cmp );
        if ( cop ) {
@@ -4777,27 +4988,23 @@ count_oc( ObjectClass *oc, ConfigOCs ***copp, int *nocs )
                }
        }
 
-       for ( sups = oc->soc_sups; sups && *sups; sups++ ) {
-               if ( count_oc( *sups, copp, nocs ) ) {
-                       return -1;
-               }
-       }
-
        return 0;
 }
 
+/* Find all superior classes of the given objectclasses,
+ * return list in order of most-subordinate first.
+ *
+ * Special / auxiliary / Cft_Misc classes always take precedence.
+ */
 static ConfigOCs **
 count_ocs( Attribute *oc_at, int *nocs )
 {
-       int             i;
+       int             i, j, misc = -1;
        ConfigOCs       **colst = NULL;
 
        *nocs = 0;
 
-       for ( i = 0; !BER_BVISNULL( &oc_at->a_nvals[i] ); i++ )
-               /* count attrs */ ;
-
-       for ( ; i--; ) {
+       for ( i = oc_at->a_numvals; i--; ) {
                ObjectClass     *oc = oc_bvfind( &oc_at->a_nvals[i] );
 
                assert( oc != NULL );
@@ -4807,6 +5014,25 @@ count_ocs( Attribute *oc_at, int *nocs )
                }
        }
 
+       /* invert order */
+       i = 0;
+       j = *nocs - 1;
+       while ( i < j ) {
+               ConfigOCs *tmp = colst[i];
+               colst[i] = colst[j];
+               colst[j] = tmp;
+               if (tmp->co_type == Cft_Misc)
+                       misc = j;
+               i++; j--;
+       }
+       /* Move misc class to front of list */
+       if (misc > 0) {
+               ConfigOCs *tmp = colst[misc];
+               for (i=misc; i>0; i--)
+                       colst[i] = colst[i-1];
+               colst[0] = tmp;
+       }
+
        return colst;
 }
 
@@ -5545,6 +5771,11 @@ config_modify_internal( CfEntryInfo *ce, Operation *op, SlapReply *rs,
        oc_at = attr_find( e->e_attrs, slap_schema.si_ad_objectClass );
        if ( !oc_at ) return LDAP_OBJECT_CLASS_VIOLATION;
 
+       for (ml = op->orm_modlist; ml; ml=ml->sml_next) {
+               if (ml->sml_desc == slap_schema.si_ad_objectClass)
+                       return rc;
+       }
+
        colst = count_ocs( oc_at, &nocs );
 
        /* make sure add/del flags are clear; should always be true */
@@ -5768,6 +5999,8 @@ config_modify_internal( CfEntryInfo *ce, Operation *op, SlapReply *rs,
                        /* FALLTHRU: LDAP_MOD_REPLACE && vals */
 
                case LDAP_MOD_ADD:
+                       if ( !a )
+                               break;
                        for (i=0; ml->sml_values[i].bv_val; i++) {
                                ca->line = ml->sml_values[i].bv_val;
                                ca->valx = -1;
@@ -5825,8 +6058,11 @@ out:
                ca->reply = msg;
        }
 
-       if ( ca->cleanup )
-               ca->cleanup( ca );
+       if ( ca->cleanup ) {
+               i = ca->cleanup( ca );
+               if (rc == LDAP_SUCCESS)
+                       rc = i;
+       }
 out_noop:
        if ( rc == LDAP_SUCCESS ) {
                attrs_free( save_attrs );
@@ -6161,36 +6397,65 @@ config_back_delete( Operation *op, SlapReply *rs )
                        rs->sr_matched = last->ce_entry->e_name.bv_val;
                rs->sr_err = LDAP_NO_SUCH_OBJECT;
        } else if ( ce->ce_kids ) {
-               rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
+               rs->sr_err = LDAP_NOT_ALLOWED_ON_NONLEAF;
        } else if ( op->o_abandon ) {
                rs->sr_err = SLAPD_ABANDON;
-       } else if ( ce->ce_type == Cft_Overlay || ce->ce_type == Cft_Database ){
+       } else if ( ce->ce_type == Cft_Overlay ||
+                       ce->ce_type == Cft_Database ||
+                       ce->ce_type == Cft_Misc ){
                char *iptr;
                int count, ixold;
 
                ldap_pvt_thread_pool_pause( &connection_pool );
 
                if ( ce->ce_type == Cft_Overlay ){
-                       if ( SLAP_ISGLOBALOVERLAY(ce->ce_be ) ) {
-                               rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
-                               rs->sr_text = "Cannot delete global overlays";
-                               ldap_pvt_thread_pool_resume( &connection_pool );
-                               goto out;
-                       } else if ( ce->ce_be == op->o_bd->bd_self ) {
-                               rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
-                               rs->sr_text = "Cannot delete cn=config overlays";
+                       overlay_remove( ce->ce_be, (slap_overinst *)ce->ce_bi, op );
+               } else if ( ce->ce_type == Cft_Misc ) {
+                       /*
+                        * only Cft_Misc objects that have a co_lddel handler set in
+                        * the ConfigOCs struct can be deleted. This code also
+                        * assumes that the entry can be only have one objectclass
+                        * with co_type == Cft_Misc
+                        */
+                       ConfigOCs co, *coptr;
+                       Attribute *oc_at;
+                       int i;
+
+                       oc_at = attr_find( ce->ce_entry->e_attrs,
+                                       slap_schema.si_ad_objectClass );
+                       if ( !oc_at ) {
+                               rs->sr_err = LDAP_OTHER;
+                               rs->sr_text = "objectclass not found";
                                ldap_pvt_thread_pool_resume( &connection_pool );
                                goto out;
-                       } else {
-                               overlay_remove( ce->ce_be, (slap_overinst *)ce->ce_bi );
                        }
-               } else { /* Cft_Database*/
+                       for ( i=0; !BER_BVISNULL(&oc_at->a_nvals[i]); i++ ) {
+                               co.co_name = &oc_at->a_nvals[i];
+                               coptr = avl_find( CfOcTree, &co, CfOc_cmp );
+                               if ( coptr == NULL || coptr->co_type != Cft_Misc ) {
+                                       continue;
+                               }
+                               if ( ! coptr->co_lddel || coptr->co_lddel( ce, op ) ){
+                                       rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
+                                       if ( ! coptr->co_lddel ) {
+                                               rs->sr_text = "No delete handler found";
+                                       } else {
+                                               rs->sr_err = LDAP_OTHER;
+                                               /* FIXME: We should return a helpful error message
+                                                * here */
+                                       }
+                                       ldap_pvt_thread_pool_resume( &connection_pool );
+                                       goto out;
+                               }
+                               break;
+                       }
+               } else if (ce->ce_type == Cft_Database ) {
                        if ( ce->ce_be == frontendDB || ce->ce_be == op->o_bd ){
                                rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
                                rs->sr_text = "Cannot delete config or frontend database";
                                ldap_pvt_thread_pool_resume( &connection_pool );
                                goto out;
-                       } 
+                       }
                        if ( ce->ce_be->bd_info->bi_db_close ) {
                                ce->ce_be->bd_info->bi_db_close( ce->ce_be, NULL );
                        }
@@ -6254,10 +6519,10 @@ config_back_delete( Operation *op, SlapReply *rs )
        } else {
                rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
        }
+out:
 #else
        rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
 #endif /* SLAP_CONFIG_DELETE */
-out:
        send_ldap_result( op, rs );
        return rs->sr_err;
 }
@@ -6560,11 +6825,12 @@ config_build_schema_inc( ConfigArgs *c, CfEntryInfo *ceparent,
                        bv.bv_len );
                c->value_dn.bv_len += bv.bv_len;
                c->value_dn.bv_val[c->value_dn.bv_len] ='\0';
-               rdn = c->value_dn;
+               rdnNormalize( 0, NULL, NULL, &c->value_dn, &rdn, NULL );
 
                c->ca_private = cf;
                e = config_build_entry( op, rs, ceparent, c, &rdn,
                        &CFOC_SCHEMA, NULL );
+               ch_free( rdn.bv_val );
                if ( !e ) {
                        return -1;
                } else if ( e && cf->c_kids ) {
@@ -6721,14 +6987,23 @@ config_back_db_open( BackendDB *be, ConfigReply *cr )
        slap_callback cb = { NULL, slap_null_cb, NULL, NULL };
        SlapReply rs = {REP_RESULT};
        void *thrctx = NULL;
+       AccessControl *save_access;
 
        Debug( LDAP_DEBUG_TRACE, "config_back_db_open\n", 0, 0, 0);
 
        /* If we have no explicitly configured ACLs, don't just use
         * the global ACLs. Explicitly deny access to everything.
         */
-       if ( !be->bd_self->be_acl ) {
-               parse_acl(be->bd_self, "config_back_db_open", 0, 6, (char **)defacl, 0 );
+       save_access = be->bd_self->be_acl;
+       be->bd_self->be_acl = NULL;
+       parse_acl(be->bd_self, "config_back_db_open", 0, 6, (char **)defacl, 0 );
+       defacl_parsed = be->bd_self->be_acl;
+       if ( save_access ) {
+               be->bd_self->be_acl = save_access;
+       } else {
+               Debug( LDAP_DEBUG_CONFIG, "config_back_db_open: "
+                               "No explicit ACL for back-config configured. "
+                               "Using hardcoded default\n", 0, 0, 0 );
        }
 
        thrctx = ldap_pvt_thread_pool_context();
@@ -6973,6 +7248,11 @@ config_back_db_close( BackendDB *be, ConfigReply *cr )
                backend_shutdown( &cfb->cb_db );
        }
 
+       if ( defacl_parsed && be->be_acl != defacl_parsed ) {
+               acl_free( defacl_parsed );
+               defacl_parsed = NULL;
+       }
+
        return 0;
 }
 
@@ -7132,6 +7412,7 @@ config_tool_entry_put( BackendDB *be, Entry *e, struct berval *text )
        Operation *op = NULL;
        void *thrctx;
        int isFrontend = 0;
+       int isFrontendChild = 0;
 
        /* Create entry for frontend database if it does not exist already */
        if ( !entry_put_got_frontend ) {
@@ -7180,13 +7461,55 @@ config_tool_entry_put( BackendDB *be, Entry *e, struct berval *text )
                                        return NOID;
                                }
                        } else {
+                               if ( !strncmp( e->e_nname.bv_val + 
+                                       STRLENOF( "olcDatabase" ), "=frontend",
+                                       STRLENOF( "=frontend" ) ) )
+                               {
+                                       struct berval rdn, pdn, ndn;
+                                       dnParent( &e->e_nname, &pdn );
+                                       rdn.bv_val = ca.log;
+                                       rdn.bv_len = snprintf(rdn.bv_val, sizeof( ca.log ),
+                                               "%s=" SLAP_X_ORDERED_FMT "%s",
+                                               cfAd_database->ad_cname.bv_val, -1,
+                                               frontendDB->bd_info->bi_type );
+                                       build_new_dn( &ndn, &pdn, &rdn, NULL );
+                                       ber_memfree( e->e_name.bv_val );
+                                       e->e_name = ndn;
+                                       ber_bvreplace( &e->e_nname, &e->e_name );
+                               }
                                entry_put_got_frontend++;
                                isFrontend = 1;
                        }
                }
        }
+
+       /* Child entries of the frontend database, e.g. slapo-chain's back-ldap
+        * instances, may appear before the config database entry in the ldif, skip
+        * auto-creation of olcDatabase={0}config in such a case */
+       if ( !entry_put_got_config &&
+                       !strncmp( e->e_nname.bv_val, "olcDatabase", STRLENOF( "olcDatabase" ))) {
+               struct berval pdn;
+               dnParent( &e->e_nname, &pdn );
+               while ( pdn.bv_len ) {
+                       if ( !strncmp( pdn.bv_val, "olcDatabase",
+                                       STRLENOF( "olcDatabase" ))) {
+                               if ( !strncmp( pdn.bv_val +
+                                               STRLENOF( "olcDatabase" ), "={-1}frontend",
+                                               STRLENOF( "={-1}frontend" )) ||
+                                               !strncmp( pdn.bv_val +
+                                               STRLENOF( "olcDatabase" ), "=frontend",
+                                               STRLENOF( "=frontend" ))) {
+
+                                       isFrontendChild = 1;
+                                       break;
+                               }
+                       }
+                       dnParent( &pdn, &pdn );
+               }
+       }
+
        /* Create entry for config database if it does not exist already */
-       if ( !entry_put_got_config && !isFrontend ) {
+       if ( !entry_put_got_config && !isFrontend && !isFrontendChild ) {
                if ( !strncmp( e->e_nname.bv_val, "olcDatabase",
                                STRLENOF( "olcDatabase" ))) {
                        if ( strncmp( e->e_nname.bv_val +