]> git.sur5r.net Git - openldap/blobdiff - servers/slapd/bconfig.c
Sync with HEAD
[openldap] / servers / slapd / bconfig.c
index a157ee49e8953670586544236ed189517813c727..e702927bc8d7583d0ba25621b26341c65570149a 100644 (file)
@@ -90,8 +90,8 @@ static ConfigFile cf_prv, *cfn = &cf_prv;
 
 static Avlnode *CfOcTree;
 
-static int config_add_internal( CfBackInfo *cfb, Entry *e, SlapReply *rs,
-       int *renumber );
+static int config_add_internal( CfBackInfo *cfb, Entry *e, ConfigArgs *ca,
+       SlapReply *rs, int *renumber );
 
 static ConfigDriver config_fname;
 static ConfigDriver config_cfdir;
@@ -147,7 +147,6 @@ enum {
        CFG_DIT,
        CFG_ATTR,
        CFG_ATOPT,
-       CFG_CHECK,
        CFG_REPLOG,
        CFG_ROOTDSE,
        CFG_LOGFILE,
@@ -235,7 +234,7 @@ static ConfigTable config_back_cf_table[] = {
                &config_generic, "( OLcfgGlAt:5 NAME 'olcAttributeOptions' "
                        "EQUALITY caseIgnoreMatch "
                        "SYNTAX OMsDirectoryString )", NULL, NULL },
-       { "authid-rewrite", NULL, 2, 0, 0,
+       { "authid-rewrite", NULL, 2, 0, STRLENOF( "authid-rewrite" ),
 #ifdef SLAP_AUTH_REWRITE
                ARG_MAGIC|CFG_REWRITE|ARG_NO_INSERT, &config_generic,
 #else
@@ -455,9 +454,6 @@ static ConfigTable config_back_cf_table[] = {
                        "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
        { "saslRegexp", NULL, 3, 3, 0, ARG_MAGIC|CFG_AZREGEXP,
                &config_generic, NULL, NULL, NULL },
-       { "schemacheck", "on|off", 2, 2, 0, ARG_ON_OFF|ARG_MAGIC|CFG_CHECK,
-               &config_generic, "( OLcfgGlAt:57 NAME 'olcSchemaCheck' "
-                       "SYNTAX OMsBoolean SINGLE-VALUE )", NULL, NULL },
        { "schemadn", "dn", 2, 2, 0, ARG_MAY_DB|ARG_DN|ARG_MAGIC,
                &config_schema_dn, "( OLcfgGlAt:58 NAME 'olcSchemaDN' "
                        "SYNTAX OMsDN SINGLE-VALUE )", NULL, NULL },
@@ -604,7 +600,7 @@ static ConfigOCs cf_ocs[] = {
                 "olcReplogFile $ olcRequires $ olcRestrict $ olcReverseLookup $ "
                 "olcRootDSE $ olcRootPW $ "
                 "olcSaslHost $ olcSaslRealm $ olcSaslSecProps $ "
-                "olcSchemaCheck $ olcSecurity $ olcSizeLimit $ "
+                "olcSecurity $ olcSizeLimit $ "
                 "olcSockbufMaxIncoming $ olcSockbufMaxIncomingAuth $ olcSrvtab $ "
                 "olcThreads $ olcTimeLimit $ olcTLSCACertificateFile $ "
                 "olcTLSCACertificatePath $ olcTLSCertificateFile $ "
@@ -652,8 +648,8 @@ static ConfigOCs cf_ocs[] = {
                "NAME 'olcModuleList' "
                "DESC 'OpenLDAP dynamic module info' "
                "SUP olcConfig STRUCTURAL "
-               "MUST ( olcModulePath $ olcModuleLoad ) "
-               "MAY cn )", Cft_Module, NULL, cfAddModule },
+               "MAY ( cn $ olcModulePath $ olcModuleLoad ) )",
+               Cft_Module, NULL, cfAddModule },
 #endif
        { NULL, 0, NULL }
 };
@@ -765,9 +761,6 @@ config_generic(ConfigArgs *c) {
                        }
                        break;
                        
-               case CFG_CHECK:
-                       c->value_int = global_schemacheck;
-                       break;
                case CFG_ACL: {
                        AccessControl *a;
                        char *src, *dst, ibuf[11];
@@ -840,7 +833,8 @@ config_generic(ConfigArgs *c) {
                        break;
                case CFG_MODPATH: {
                        ModPaths *mp = c->private;
-                       value_add_one( &c->rvalue_vals, &mp->mp_path );
+                       if ( !BER_BVISNULL( &mp->mp_path ))
+                               value_add_one( &c->rvalue_vals, &mp->mp_path );
 
                        rc = c->rvalue_vals ? 0 : 1;
                        }
@@ -885,7 +879,6 @@ config_generic(ConfigArgs *c) {
                case CFG_RO:
                case CFG_AZPOLICY:
                case CFG_DEPTH:
-               case CFG_CHECK:
                case CFG_LASTMOD:
                case CFG_SASLSECP:
                case CFG_SSTR_IF_MAX:
@@ -976,11 +969,14 @@ config_generic(ConfigArgs *c) {
                                c->be = LDAP_STAILQ_FIRST(&backendDB);
                        } else if ( !strcasecmp( c->argv[1], "frontend" )) {
                                c->be = frontendDB;
-                       } else if(!(c->be = backend_db_init(c->argv[1]))) {
-                               sprintf( c->msg, "<%s> failed init", c->argv[0] );
-                               Debug(LDAP_DEBUG_ANY, "%s: %s (%s)!\n",
-                                       c->log, c->msg, c->argv[1] );
-                               return(1);
+                       } else {
+                               c->be = backend_db_init(c->argv[1]);
+                               if ( !c->be ) {
+                                       sprintf( c->msg, "<%s> failed init", c->argv[0] );
+                                       Debug(LDAP_DEBUG_ANY, "%s: %s (%s)!\n",
+                                               c->log, c->msg, c->argv[1] );
+                                       return(1);
+                               }
                        }
                        break;
 
@@ -1088,13 +1084,6 @@ config_generic(ConfigArgs *c) {
                                        return(1);
                        break;
 
-               case CFG_CHECK:
-                       global_schemacheck = c->value_int;
-                       if(!global_schemacheck) Debug(LDAP_DEBUG_ANY, "%s: "
-                               "schema checking disabled! your mileage may vary!\n",
-                               c->log, 0, 0);
-                       break;
-
                case CFG_ACL:
                        parse_acl(c->be, c->fname, c->lineno, c->argc, c->argv, c->valx);
                        break;
@@ -1169,21 +1158,35 @@ config_generic(ConfigArgs *c) {
 
 #ifdef SLAPD_MODULES
                case CFG_MODLOAD:
+                       /* If we're just adding a module on an existing modpath,
+                        * make sure we've selected the current path.
+                        */
+                       if ( c->op == LDAP_MOD_ADD && c->private && modcur != c->private ) {
+                               modcur = c->private;
+                               /* This should never fail */
+                               if ( module_path( modcur->mp_path.bv_val )) {
+                                       sprintf( c->msg, "<%s> module path no longer valid",
+                                               c->argv[0] );
+                                       Debug(LDAP_DEBUG_ANY, "%s: %s (%s)\n",
+                                               c->log, c->msg, modcur->mp_path.bv_val );
+                                       return(1);
+                               }
+                       }
                        if(module_load(c->argv[1], c->argc - 2, (c->argc > 2) ? c->argv + 2 : NULL))
                                return(1);
                        /* Record this load on the current path */
                        {
                                struct berval bv;
-                               ModPaths *mp;
-                               char *ptr = c->line + STRLENOF("moduleload");
-                               while (!isspace(*ptr)) ptr++;
-                               while (isspace(*ptr)) ptr++;
+                               char *ptr;
+                               if ( c->op == SLAP_CONFIG_ADD ) {
+                                       ptr = c->line + STRLENOF("moduleload");
+                                       while (!isspace(*ptr)) ptr++;
+                                       while (isspace(*ptr)) ptr++;
+                               } else {
+                                       ptr = c->line;
+                               }
                                ber_str2bv(ptr, 0, 1, &bv);
-                               if ( c->op == SLAP_CONFIG_ADD )
-                                       mp = modcur;
-                               else
-                                       mp = c->private;
-                               ber_bvarray_add( &mp->mp_loads, &bv );
+                               ber_bvarray_add( &modcur->mp_loads, &bv );
                        }
                        break;
 
@@ -1204,8 +1207,7 @@ config_generic(ConfigArgs *c) {
                                mp->mp_loads = NULL;
                                modlast = mp;
                                c->private = mp;
-                               if ( c->op == SLAP_CONFIG_ADD )
-                                       modcur = mp;
+                               modcur = mp;
                        }
                        
                        break;
@@ -1222,9 +1224,27 @@ config_generic(ConfigArgs *c) {
 #ifdef SLAP_AUTH_REWRITE
                case CFG_REWRITE: {
                        struct berval bv;
+                       char *line;
+                       
                        if(slap_sasl_rewrite_config(c->fname, c->lineno, c->argc, c->argv))
                                return(1);
-                       ber_str2bv( c->line, 0, 1, &bv );
+
+                       if ( c->argc > 1 ) {
+                               char    *s;
+
+                               /* quote all args but the first */
+                               line = ldap_charray2str( c->argv, "\" \"" );
+                               ber_str2bv( line, 0, 0, &bv );
+                               s = strchr( bv.bv_val, '"' );
+                               assert( s != NULL );
+                               /* move the trailing quote of argv[0] to the end */
+                               AC_MEMCPY( s, s + 1, bv.bv_len - ( s - bv.bv_val ) );
+                               bv.bv_val[ bv.bv_len - 1 ] = '"';
+
+                       } else {
+                               ber_str2bv( c->argv[ 0 ], 0, 1, &bv );
+                       }
+                       
                        ber_bvarray_add( &authz_rewrites, &bv );
                        }
                        break;
@@ -1815,6 +1835,7 @@ config_loglevel(ConfigArgs *c) {
        int i;
        char *next;
        slap_verbmasks loglevel_ops[] = {
+               { BER_BVC("Any"),       -1 },
                { BER_BVC("Trace"),     LDAP_DEBUG_TRACE },
                { BER_BVC("Packets"),   LDAP_DEBUG_PACKETS },
                { BER_BVC("Args"),      LDAP_DEBUG_ARGS },
@@ -1830,7 +1851,6 @@ config_loglevel(ConfigArgs *c) {
                { BER_BVC("Cache"),     LDAP_DEBUG_CACHE },
                { BER_BVC("Index"),     LDAP_DEBUG_INDEX },
                { BER_BVC("Sync"),      LDAP_DEBUG_SYNC },
-               { BER_BVC("Any"),       -1 },
                { BER_BVNULL,   0 }
        };
 
@@ -2389,14 +2409,19 @@ config_find_base( CfEntryInfo *root, struct berval *dn, CfEntryInfo **last )
        return root;
 }
 
+typedef struct setup_cookie {
+       CfBackInfo *cfb;
+       ConfigArgs *ca;
+} setup_cookie;
+
 static int
 config_ldif_resp( Operation *op, SlapReply *rs )
 {
        if ( rs->sr_type == REP_SEARCH ) {
-               CfBackInfo *cfb = op->o_callback->sc_private;
+               setup_cookie *sc = op->o_callback->sc_private;
 
-               cfb->cb_got_ldif = 1;
-               rs->sr_err = config_add_internal( cfb, rs->sr_entry, NULL, NULL );
+               sc->cfb->cb_got_ldif = 1;
+               rs->sr_err = config_add_internal( sc->cfb, rs->sr_entry, sc->ca, NULL, NULL );
        }
        return rs->sr_err;
 }
@@ -2409,6 +2434,7 @@ config_setup_ldif( BackendDB *be, const char *dir, int readit ) {
        ConfigTable *ct;
        char *argv[3];
        int rc = 0;
+       setup_cookie sc;
        slap_callback cb = { NULL, config_ldif_resp, NULL, NULL };
        Connection conn = {0};
        char opbuf[OPERATION_BUFFER_SIZE];
@@ -2485,7 +2511,9 @@ config_setup_ldif( BackendDB *be, const char *dir, int readit ) {
                op->ors_attrsonly = 0;
 
                op->o_callback = &cb;
-               cb.sc_private = cfb;
+               sc.cfb = cfb;
+               sc.ca = &c;
+               cb.sc_private = &sc;
 
                op->o_bd = &cfb->cb_db;
                rc = op->o_bd->be_search( op, &rs );
@@ -2557,12 +2585,17 @@ read_config(const char *fname, const char *dir) {
                        cfdir = SLAPD_DEFAULT_CONFIGDIR;
                }
                /* if fname is defaulted, try reading .d */
-               if ( config_setup_ldif( be, cfdir, !fname ))
+               rc = config_setup_ldif( be, cfdir, !fname );
+
+               /* It's OK if the base object doesn't exist yet */
+               if ( rc && rc != LDAP_NO_SUCH_OBJECT )
                        return 1;
 
                /* If we read the config from back-ldif, nothing to do here */
-               if ( cfb->cb_got_ldif )
-                       return 0;
+               if ( cfb->cb_got_ldif ) {
+                       rc = 0;
+                       goto done;
+               }
        }
 
        if ( fname )
@@ -2593,6 +2626,20 @@ read_config(const char *fname, const char *dir) {
                }
                break;
        }
+
+done:
+       if ( rc == 0 && BER_BVISNULL( &frontendDB->be_schemadn ) ) {
+               ber_str2bv( SLAPD_SCHEMA_DN, STRLENOF( SLAPD_SCHEMA_DN ), 1,
+                       &frontendDB->be_schemadn );
+               rc = dnNormalize( 0, NULL, NULL, &frontendDB->be_schemadn, &frontendDB->be_schemandn, NULL );
+               if ( rc != LDAP_SUCCESS ) {
+                       Debug(LDAP_DEBUG_ANY, "read_config: "
+                               "unable to normalize default schema DN \"%s\"\n",
+                               frontendDB->be_schemadn.bv_val, 0, 0 );
+                       /* must not happen */
+                       assert( 0 );
+               }
+       }
        return rc;
 }
 
@@ -2974,13 +3021,12 @@ cfAddOverlay( CfEntryInfo *p, Entry *e, struct config_args_s *ca )
 
 /* Parse an LDAP entry into config directives */
 static int
-config_add_internal( CfBackInfo *cfb, Entry *e, SlapReply *rs, int *renum )
+config_add_internal( CfBackInfo *cfb, Entry *e, ConfigArgs *ca, SlapReply *rs, int *renum )
 {
        CfEntryInfo *ce, *last;
        ConfigOCs **colst;
        Attribute *a, *oc_at;
        int i, j, nocs, rc = 0;
-       ConfigArgs ca = {0};
        struct berval pdn;
        ConfigTable *ct;
        char *ptr;
@@ -3004,15 +3050,17 @@ config_add_internal( CfBackInfo *cfb, Entry *e, SlapReply *rs, int *renum )
        oc_at = attr_find( e->e_attrs, slap_schema.si_ad_objectClass );
        if ( !oc_at ) return LDAP_OBJECT_CLASS_VIOLATION;
 
+       memset( ca, 0, sizeof(ConfigArgs));
+
        /* Fake the coordinates based on whether we're part of an
         * LDAP Add or if reading the config dir
         */
        if ( rs ) {
-               ca.fname = "slapd";
-               ca.lineno = 0;
+               ca->fname = "slapd";
+               ca->lineno = 0;
        } else {
-               ca.fname = cfdir.bv_val;
-               ca.lineno = 1;
+               ca->fname = cfdir.bv_val;
+               ca->lineno = 1;
        }
 
        colst = count_ocs( oc_at, &nocs );
@@ -3023,8 +3071,8 @@ config_add_internal( CfBackInfo *cfb, Entry *e, SlapReply *rs, int *renum )
        rc = LDAP_CONSTRAINT_VIOLATION;
        if ( colst[0]->co_type == Cft_Global && !last ) {
                cfn = &cf_prv;
-               ca.private = cfn;
-               ca.be = frontendDB;     /* just to get past check_vals */
+               ca->private = cfn;
+               ca->be = frontendDB;    /* just to get past check_vals */
                rc = LDAP_SUCCESS;
        }
 
@@ -3034,7 +3082,7 @@ config_add_internal( CfBackInfo *cfb, Entry *e, SlapReply *rs, int *renum )
        if ( last ) {
                for ( i=0; i<nocs; i++ ) {
                        if ( colst[i]->co_ldadd &&
-                               ( rc = colst[i]->co_ldadd( last, e, &ca ))
+                               ( rc = colst[i]->co_ldadd( last, e, ca ))
                                        != LDAP_CONSTRAINT_VIOLATION ) {
                                break;
                        }
@@ -3070,7 +3118,7 @@ config_add_internal( CfBackInfo *cfb, Entry *e, SlapReply *rs, int *renum )
        if ( rc )
                goto leave;
 
-       init_config_argv( &ca );
+       init_config_argv( ca );
 
        /* Make sure we process attrs in the required order */
        sort_attrs( e, colst, nocs );
@@ -3079,7 +3127,7 @@ config_add_internal( CfBackInfo *cfb, Entry *e, SlapReply *rs, int *renum )
                if ( a == oc_at ) continue;
                ct = config_find_table( colst, nocs, a->a_desc );
                if ( !ct ) continue;    /* user data? */
-               rc = check_vals( ct, &ca, a, 1 );
+               rc = check_vals( ct, ca, a, 1 );
                if ( rc ) goto leave;
        }
 
@@ -3089,13 +3137,13 @@ config_add_internal( CfBackInfo *cfb, Entry *e, SlapReply *rs, int *renum )
                ct = config_find_table( colst, nocs, a->a_desc );
                if ( !ct ) continue;    /* user data? */
                for (i=0; a->a_vals[i].bv_val; i++) {
-                       ca.line = a->a_vals[i].bv_val;
+                       ca->line = a->a_vals[i].bv_val;
                        if ( a->a_desc->ad_type->sat_flags & SLAP_AT_ORDERED ) {
-                               ptr = strchr( ca.line, '}' );
-                               if ( ptr ) ca.line = ptr+1;
+                               ptr = strchr( ca->line, '}' );
+                               if ( ptr ) ca->line = ptr+1;
                        }
-                       ca.valx = i;
-                       rc = config_parse_add( ct, &ca );
+                       ca->valx = i;
+                       rc = config_parse_add( ct, ca );
                        if ( rc ) {
                                rc = LDAP_OTHER;
                                goto leave;
@@ -3103,14 +3151,40 @@ config_add_internal( CfBackInfo *cfb, Entry *e, SlapReply *rs, int *renum )
                }
        }
 ok:
+       /* Newly added databases and overlays need to be started up */
+       if ( CONFIG_ONLINE_ADD( ca )) {
+               if ( colst[0]->co_type == Cft_Database ) {
+                       rc = backend_startup_one( ca->be );
+
+               } else if ( colst[0]->co_type == Cft_Overlay ) {
+                       if ( ca->bi->bi_db_open ) {
+                               BackendInfo *bi_orig = ca->be->bd_info;
+                               ca->be->bd_info = ca->bi;
+                               rc = ca->bi->bi_db_open( ca->be );
+                               ca->be->bd_info = bi_orig;
+                       }
+               }
+               if ( rc ) {
+                       sprintf( ca->msg, "<%s> failed startup", ca->argv[0] );
+                       Debug(LDAP_DEBUG_ANY, "%s: %s (%s)!\n",
+                               ca->log, ca->msg, ca->argv[1] );
+                       rc = LDAP_OTHER;
+                       if ( colst[0]->co_type == Cft_Database )
+                               backend_destroy_one( ca->be );
+                       else
+                               overlay_destroy_one( ca->be, (slap_overinst *)ca->bi );
+                       goto leave;
+               }
+       }
+
        ce = ch_calloc( 1, sizeof(CfEntryInfo) );
        ce->ce_parent = last;
        ce->ce_entry = entry_dup( e );
        ce->ce_entry->e_private = ce;
        ce->ce_type = colst[0]->co_type;
-       ce->ce_be = ca.be;
-       ce->ce_bi = ca.bi;
-       ce->ce_private = ca.private;
+       ce->ce_be = ca->be;
+       ce->ce_bi = ca->bi;
+       ce->ce_private = ca->private;
        if ( !last ) {
                cfb->cb_root = ce;
        } else if ( last->ce_kids ) {
@@ -3124,7 +3198,7 @@ ok:
        }
 
 leave:
-       ch_free( ca.argv );
+       ch_free( ca->argv );
        if ( colst ) ch_free( colst );
        return rc;
 }
@@ -3138,6 +3212,7 @@ config_back_add( Operation *op, SlapReply *rs )
        CfBackInfo *cfb;
        CfEntryInfo *ce, *last;
        int renumber;
+       ConfigArgs ca;
 
        if ( !be_isroot( op ) ) {
                rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
@@ -3155,8 +3230,10 @@ config_back_add( Operation *op, SlapReply *rs )
         * 4) store entry in underlying database
         * 5) perform any necessary renumbering
         */
-       rs->sr_err = config_add_internal( cfb, op->ora_e, rs, &renumber );
-       if ( rs->sr_err == LDAP_SUCCESS && cfb->cb_use_ldif ) {
+       rs->sr_err = config_add_internal( cfb, op->ora_e, &ca, rs, &renumber );
+       if ( rs->sr_err != LDAP_SUCCESS ) {
+               rs->sr_text = ca.msg;
+       } else if ( cfb->cb_use_ldif ) {
                BackendDB *be = op->o_bd;
                slap_callback sc = { NULL, slap_null_cb, NULL, NULL };
                op->o_bd = &cfb->cb_db;
@@ -3179,7 +3256,7 @@ out:
 typedef struct delrec {
        struct delrec *next;
        int nidx;
-       int idx[0];
+       int idx[1];
 } delrec;
 
 static int
@@ -3238,7 +3315,7 @@ config_modify_internal( CfEntryInfo *ce, Operation *op, SlapReply *rs,
                        if ( ct && ml->sml_values ) {
                                delrec *d;
                                for (i=0; ml->sml_values[i].bv_val; i++);
-                               d = ch_malloc( sizeof(delrec) + * sizeof(int));
+                               d = ch_malloc( sizeof(delrec) + (i - 1)* sizeof(int));
                                d->nidx = i;
                                d->next = NULL;
                                if ( dels ) {
@@ -3317,8 +3394,8 @@ config_modify_internal( CfEntryInfo *ce, Operation *op, SlapReply *rs,
        
        if(rc == LDAP_SUCCESS) {
                /* check that the entry still obeys the schema */
-               rc = entry_schema_check(op->o_bd, e, NULL,
-                                 &rs->sr_text, ca->msg, sizeof(ca->msg) );
+               rc = entry_schema_check(op->o_bd, e, NULL, 0,
+                       &rs->sr_text, ca->msg, sizeof(ca->msg) );
        }
        if ( rc == LDAP_SUCCESS ) {
                /* Basic syntax checks are OK. Do the actual settings. */
@@ -4015,9 +4092,10 @@ config_tool_entry_put( BackendDB *be, Entry *e, struct berval *text )
 {
        CfBackInfo *cfb = be->be_private;
        BackendInfo *bi = cfb->cb_db.bd_info;
+       ConfigArgs ca;
 
        if ( bi && bi->bi_tool_entry_put &&
-               config_add_internal( cfb, e, NULL, NULL ) == 0 )
+               config_add_internal( cfb, e, &ca, NULL, NULL ) == 0 )
                return bi->bi_tool_entry_put( &cfb->cb_db, e, text );
        else
                return NOID;