typedef struct CfOcInfo {
struct berval *co_name;
ConfigTable *co_table;
+ ConfigType co_type;
} CfOcInfo;
-typedef enum {
- Cf_Global = 1,
- Cf_Include,
- Cf_Backend,
- Cf_Database,
- Cf_Overlay
-} CfEtypes;
-
typedef struct CfEntryInfo {
struct CfEntryInfo *ce_sibs;
struct CfEntryInfo *ce_kids;
Entry *ce_entry;
- CfEtypes ce_type;
+ ConfigType ce_type;
BackendInfo *ce_bi;
BackendDB *ce_be;
} CfEntryInfo;
typedef struct {
ConfigFile *cb_config;
CfEntryInfo *cb_root;
+ BackendDB *cb_be; /* config backend */
BackendDB cb_db; /* underlying database */
int cb_got_ldif;
} CfBackInfo;
static AttributeDescription *cfAd_backend, *cfAd_database, *cfAd_overlay,
*cfAd_include;
-static ObjectClass *cfOc_global, *cfOc_backend, *cfOc_database,
+static ObjectClass *cfOc_schema, *cfOc_global, *cfOc_backend, *cfOc_database,
*cfOc_include, *cfOc_overlay;
static ConfigFile cf_prv, *cfn = &cf_prv;
static int add_syncrepl LDAP_P(( Backend *, char **, int ));
static int parse_syncrepl_line LDAP_P(( char **, int, syncinfo_t *));
static void syncrepl_unparse LDAP_P (( syncinfo_t *, struct berval *));
+static int config_add_internal( CfBackInfo *cfb, Entry *e, SlapReply *rs );
static ConfigDriver config_fname;
static ConfigDriver config_cfdir;
"DESC 'A type of backend' "
"EQUALITY caseIgnoreMatch "
"SYNTAX OMsDirectoryString X-ORDERED 'VALUES' )", NULL, NULL },
- { "concurrency", "level", 2, 2, 0, ARG_INT|ARG_NONZERO|ARG_MAGIC|CFG_CONCUR,
+ { "concurrency", "level", 2, 2, 0, ARG_INT|ARG_MAGIC|CFG_CONCUR,
&config_generic, "( OLcfgAt:10 NAME 'olcConcurrency' "
"SYNTAX OMsInteger SINGLE-VALUE )", NULL, NULL },
{ "conn_max_pending", "max", 2, 2, 0, ARG_INT,
"NAME 'olcConfig' "
"DESC 'OpenLDAP configuration object' "
"ABSTRACT SUP top "
- "MAY ( cn $ olcConfigFile ) )", NULL },
- { "( OLcfgOc:3 "
+ "MAY ( cn $ olcConfigFile ) )", Cft_Abstract, NULL },
+ { "( OLcfgOc:2 "
"NAME 'olcGlobal' "
"DESC 'OpenLDAP Global configuration options' "
"SUP olcConfig STRUCTURAL "
"olcPlugin $ olcPluginLogFile $ olcReadOnly $ olcReferral $ "
"olcReplicaPidFile $ olcReplicaArgsFile $ olcReplicationInterval $ "
"olcReplogFile $ olcRequires $ olcRestrict $ olcReverseLookup $ "
- "olcRootDSE $ olcSaslHost $ olcSaslRealm $ olcSaslSecProps $ "
+ "olcRootDSE $ olcRootPW $ olcSaslHost $ olcSaslRealm $ olcSaslSecProps $ "
"olcSchemaCheck $ olcSchemaDN $ olcSecurity $ olcSizeLimit $ "
"olcSockbufMaxIncoming $ olcSockbufMaxIncomingAuth $ olcSrvtab $ "
"olcThreads $ olcTimeLimit $ olcTLSCACertificateFile $ "
"olcTLSCACertificatePath $ olcTLSCertificateFile $ "
"olcTLSCertificateKeyFile $ olcTLSCipherSuite $ olcTLSCRLCheck $ "
- "olcTLSRandFile $ olcTLSVerifyClient ) )", &cfOc_global },
+ "olcTLSRandFile $ olcTLSVerifyClient ) )", Cft_Global, &cfOc_global },
+ { "( OLcfgOc:3 "
+ "NAME 'olcSchemaConfig' "
+ "DESC 'OpenLDAP schema object' "
+ "SUP olcConfig STRUCTURAL "
+ "MAY ( olcObjectIdentifier $ attributeTypes $ objectClasses $ "
+ "ditContentRules ) )", Cft_Schema, &cfOc_schema },
{ "( OLcfgOc:4 "
"NAME 'olcBackendConfig' "
"DESC 'OpenLDAP Backend-specific options' "
"SUP olcConfig STRUCTURAL "
- "MAY ( olcBackend ) )", &cfOc_backend },
+ "MAY ( olcBackend ) )", Cft_Backend, &cfOc_backend },
{ "( OLcfgOc:5 "
"NAME 'olcDatabaseConfig' "
"DESC 'OpenLDAP Database-specific options' "
"olcMaxDerefDepth $ olcPlugin $ olcReadOnly $ olcReplica $ "
"olcReplogFile $ olcRequires $ olcRestrict $ olcRootDN $ olcRootPW $ "
"olcSchemaDN $ olcSecurity $ olcSizeLimit $ olcSuffix $ olcSyncrepl $ "
- "olcTimeLimit $ olcUpdateDN $ olcUpdateRef ) )", &cfOc_database },
+ "olcTimeLimit $ olcUpdateDN $ olcUpdateRef ) )",
+ Cft_Database, &cfOc_database },
{ "( OLcfgOc:6 "
+ "NAME 'olcOverlayConfig' "
+ "DESC 'OpenLDAP Overlay-specific options' "
+ "SUP olcConfig STRUCTURAL "
+ "MAY ( olcOverlay ) )", Cft_Overlay, &cfOc_overlay },
+ { "( OLcfgOc:7 "
"NAME 'olcIncludeFile' "
"DESC 'OpenLDAP configuration include file' "
"SUP olcConfig STRUCTURAL "
"MAY ( olcInclude $ olcModuleLoad $ olcModulePath $ olcRootDSE ) )",
- &cfOc_include },
- { "( OLcfgOc:7 "
- "NAME 'olcOverlayConfig' "
- "DESC 'OpenLDAP Overlay-specific options' "
- "SUP olcConfig STRUCTURAL "
- "MAY ( olcOverlay ) )", &cfOc_overlay },
- { NULL, NULL }
+ Cft_Include, &cfOc_include },
+ { NULL, 0, NULL }
};
static int
*/
if ( !strcasecmp( c->argv[1], "config" )) {
c->be = backendDB;
+ } else if ( !strcasecmp( c->argv[1], "frontend" )) {
+ c->be = frontendDB;
} else if(!(c->be = backend_db_init(c->argv[1]))) {
Debug(LDAP_DEBUG_ANY, "%s: "
"database %s failed init!\n", c->log, c->argv[1], 0);
break;
case CFG_OID:
- if(parse_oidm(c->fname, c->lineno, c->argc, c->argv)) return(1);
+ if(parse_oidm(c->fname, c->lineno, c->argc, c->argv)) return(0);
break;
case CFG_OC:
value_add_one( &c->rvalue_vals, &cf->c_file );
return 0;
}
- return(1);
+ return(0);
}
static int
value_add_one( &c->rvalue_vals, &cfdir );
return 0;
}
- return(1);
+ return(0);
}
static int
Backend *tbe;
struct berval pdn, ndn;
int rc;
+
+ if (c->be == frontendDB) return 1;
+
if (c->op == SLAP_CONFIG_EMIT) {
- if ( !BER_BVISNULL( &c->be->be_suffix[0] )) {
+ if (!BER_BVISNULL( &c->be->be_suffix[0] )) {
value_add( &c->rvalue_vals, c->be->be_suffix );
value_add( &c->rvalue_nvals, c->be->be_nsuffix );
return 0;
Backend *tbe;
if (c->op == SLAP_CONFIG_EMIT) {
if (!BER_BVISEMPTY(&c->be->be_rootpw)) {
- c->value_string=ch_strdup("*");
+ c->value_string=c->be->be_rootpw.bv_val;
return 0;
}
return 1;
cfn->c_kids = cf;
}
cfn = cf;
+ ber_str2bv( c->argv[1], 0, 1, &cf->c_file );
rc = read_config_file(c->argv[1], c->depth + 1, c);
c->lineno = savelineno - 1;
cfn = cfsave;
if ( rc ) {
if ( cf2 ) cf2->c_sibs = NULL;
else cfn->c_kids = NULL;
+ ch_free( cf->c_file.bv_val );
ch_free( cf );
- } else {
- ber_str2bv( c->argv[1], 0, 1, &cf->c_file );
}
return(rc);
}
{
if ( rs->sr_type == REP_SEARCH ) {
CfBackInfo *cfb = op->o_callback->sc_private;
- CfEntryInfo *ce, *last;
cfb->cb_got_ldif = 1;
- config_find_base( cfb->cb_root, &rs->sr_entry->e_nname, &last );
- ce = ch_calloc( 1, sizeof(CfEntryInfo) );
- ce->ce_entry = entry_dup( rs->sr_entry );
- ce->ce_entry->e_private = ce;
- if ( !last ) {
- cfb->cb_root = ce;
- } else if ( last->ce_kids ) {
- CfEntryInfo *c2;
-
- for (c2=last->ce_kids; c2 && c2->ce_sibs; c2 = c2->ce_sibs);
- c2->ce_sibs = ce;
- } else {
- last->ce_kids = ce;
- }
+ rs->sr_err = config_add_internal( cfb, rs->sr_entry, NULL );
}
- return 0;
+ return rs->sr_err;
}
/* Configure and read the underlying back-ldif store */
co = ch_malloc( sizeof(CfOcInfo) );
co->co_name = &(*ocs[i].oc)->soc_cname;
co->co_table = ct;
+ co->co_type = ocs[i].cft;
avl_insert( &CfOcTree, co, CfOcInfo_cmp, avl_dup_error );
}
}
int
read_config(const char *fname, const char *dir) {
BackendDB *be;
+ CfBackInfo *cfb;
/* Setup the config backend */
be = backend_db_init( "config" );
#if 0 /* not yet
/* If we read the config from back-ldif, nothing to do here */
+ cfb = be->be_private;
if ( cfb->cb_got_ldif )
return 0;
#endif
return rc;
}
+static ConfigTable *
+config_find_table( CfOcInfo *co, AttributeDescription *ad )
+{
+ int i;
+
+ for (i=0; co->co_table[i].name; i++)
+ if ( co->co_table[i].ad == ad )
+ return &co->co_table[i];
+ return NULL;
+}
+
+/* Sort the values in an X-ORDERED attribute.
+ * If the values have no index, leave them in their given order.
+ * If the values have indexes, sort them and then strip the index.
+ * If some are indexed and some are not, return Error.
+ *
+ * FIXME: This function probably belongs in the frontend somewhere,
+ * like slap_mods_check.
+ */
+static int
+sort_vals( Attribute *a )
+{
+ int i;
+ int index = 0, noindex = 0;
+
+ /* count attrs, look for index */
+ for (i=0; a->a_vals[i].bv_val; i++) {
+ if ( a->a_vals[i].bv_val[0] == '{' ) {
+ char *ptr;
+ index = 1;
+ ptr = strchr( a->a_vals[i].bv_val, '}' );
+ if ( !ptr || !ptr[1] )
+ return LDAP_INVALID_SYNTAX;
+ if ( noindex )
+ return LDAP_INVALID_SYNTAX;
+ } else {
+ noindex = 1;
+ if ( index )
+ return LDAP_INVALID_SYNTAX;
+ }
+ }
+
+ if ( index ) {
+ int vals = i, *indexes, j, idx;
+ struct berval tmp, ntmp;
+ char *ptr;
+
+ /* Strip index from normalized values */
+ if ( !a->a_nvals || a->a_vals == a->a_nvals ) {
+ a->a_nvals = ch_malloc( (vals+1)*sizeof(struct berval));
+ for ( i=0; i<vals; i++ ) {
+ ptr = strchr(a->a_vals[i].bv_val, '}') + 1;
+ a->a_nvals[i].bv_len = a->a_vals[i].bv_len -
+ (ptr - a->a_vals[i].bv_val);
+ a->a_nvals[i].bv_val = ch_malloc( a->a_nvals[i].bv_len + 1);
+ strcpy(a->a_nvals[i].bv_val, ptr );
+ }
+ } else {
+ for ( i=0; i<vals; i++ ) {
+ ptr = strchr(a->a_nvals[i].bv_val, '}') + 1;
+ a->a_nvals[i].bv_len -= ptr - a->a_nvals[i].bv_val;
+ strcpy(a->a_nvals[i].bv_val, ptr);
+ }
+ }
+
+ indexes = ch_malloc( vals * sizeof(int) );
+ for ( i=0; i<vals; i++)
+ indexes[i] = atoi(a->a_vals[i].bv_val+1);
+
+ /* Insertion sort */
+ for ( i=1; i<vals; i++ ) {
+ idx = indexes[i];
+ tmp = a->a_vals[i];
+ ntmp = a->a_nvals[i];
+ j = i;
+ while ((j > 0) && (indexes[j-1] > idx)) {
+ indexes[j] = indexes[j-1];
+ a->a_vals[j] = a->a_vals[j-1];
+ a->a_nvals[j] = a->a_nvals[j-1];
+ j--;
+ }
+ indexes[j] = idx;
+ a->a_vals[j] = tmp;
+ a->a_nvals[j] = ntmp;
+ }
+ }
+ return 0;
+}
+
+static int
+check_attr( ConfigTable *ct, ConfigArgs *ca, Attribute *a )
+{
+ int i, rc = 0;
+
+ if ( a->a_desc->ad_type->sat_flags & SLAP_AT_ORDERED ) {
+ rc = sort_vals( a );
+ if ( rc )
+ return rc;
+ }
+ for ( i=0; a->a_nvals[i].bv_val; i++ ) {
+ ca->line = a->a_nvals[i].bv_val;
+ rc = config_parse_vals( ct, ca, i );
+ if ( rc )
+ break;
+ }
+ return rc;
+}
+
+/* Parse an LDAP entry into config directives */
+static int
+config_add_internal( CfBackInfo *cfb, Entry *e, SlapReply *rs )
+{
+ CfEntryInfo *ce, *last;
+ CfOcInfo co, *coptr, **colst = NULL;
+ Attribute *a, *oc_at, *type_attr;
+ AttributeDescription *type_ad = NULL;
+ int i, j, nocs, rc;
+ ConfigArgs ca = {0};
+ struct berval pdn;
+ Entry *xe = NULL;
+ ConfigTable *ct, *type_ct = NULL;
+
+ /* Make sure parent exists and entry does not */
+ ce = config_find_base( cfb->cb_root, &e->e_nname, &last );
+ if ( ce )
+ return LDAP_ALREADY_EXISTS;
+
+ dnParent( &e->e_nname, &pdn );
+
+ /* If last is NULL, the new entry is the root/suffix entry,
+ * otherwise last should be the parent.
+ */
+ if ( last && !dn_match( &last->ce_entry->e_nname, &pdn )) {
+ if ( rs )
+ rs->sr_matched = last->ce_entry->e_name.bv_val;
+ return LDAP_NO_SUCH_OBJECT;
+ }
+
+ oc_at = attr_find( e->e_attrs, slap_schema.si_ad_objectClass );
+ if ( !oc_at ) return LDAP_OBJECT_CLASS_VIOLATION;
+
+ /* count the objectclasses */
+ for ( i=0; oc_at->a_nvals[i].bv_val; i++ );
+ nocs = i;
+ colst = (CfOcInfo **)ch_malloc( nocs * sizeof(CfOcInfo *));
+
+ for ( i=0, j=0; i<nocs; i++) {
+ co.co_name = &oc_at->a_nvals[i];
+ coptr = avl_find( CfOcTree, &co, CfOcInfo_cmp );
+
+ /* ignore non-config objectclasses. probably should be
+ * an error, general data doesn't belong here.
+ */
+ if ( !coptr ) continue;
+
+ /* Ignore the root objectclass, it has no implementation.
+ */
+ if ( coptr->co_type == Cft_Abstract ) continue;
+ colst[j++] = coptr;
+ }
+ nocs = j;
+
+ /* Only the root can be Cft_Global, everything else must
+ * have a parent. Only limited nesting arrangements are allowed.
+ */
+ switch( colst[0]->co_type ) {
+ case Cft_Global:
+ if ( last ) {
+ rc = LDAP_CONSTRAINT_VIOLATION;
+ goto leave;
+ }
+ break;
+ case Cft_Schema:
+ case Cft_Backend:
+ case Cft_Database:
+ case Cft_Include:
+ if ( !last || ( last->ce_type != Cft_Global &&
+ last->ce_type != colst[0]->co_type )) {
+ rc = LDAP_CONSTRAINT_VIOLATION;
+ goto leave;
+ }
+ break;
+ case Cft_Overlay:
+ if ( !last || ( last->ce_type != Cft_Global &&
+ last->ce_type != Cft_Database &&
+ last->ce_type != colst[0]->co_type )) {
+ rc = LDAP_CONSTRAINT_VIOLATION;
+ goto leave;
+ }
+ break;
+ }
+
+ /* Parse all the values and check for simple syntax errors before
+ * performing any set actions.
+ */
+ switch (colst[0]->co_type) {
+ case Cft_Global: /* */
+ case Cft_Schema:
+ ca.be = cfb->cb_be;
+ break;
+ case Cft_Backend:
+ if ( last->ce_type == Cft_Backend )
+ ca.bi = last->ce_bi;
+ else
+ type_ad = cfAd_backend;
+ break;
+ case Cft_Database:
+ if ( last->ce_type == Cft_Database ) {
+ ca.be = last->ce_be;
+ } else {
+ type_ad = cfAd_database;
+ /* dummy, just to get past check_attr */
+ ca.be = frontendDB;
+ }
+ break;
+
+ case Cft_Overlay:
+ ca.be = last->ce_be;
+ type_ad = cfAd_overlay;
+
+ case Cft_Include:
+ if ( !rs ) /* ignored */
+ break;
+ type_ad = cfAd_include;
+ }
+ init_config_argv( &ca );
+ if ( type_ad ) {
+ type_attr = attr_find( e->e_attrs, type_ad );
+ if ( !type_attr ) {
+ rc = LDAP_OBJECT_CLASS_VIOLATION;
+ goto leave;
+ }
+ for ( i=0; i<nocs; i++ ) {
+ type_ct = config_find_table( colst[i], type_ad );
+ if ( type_ct ) break;
+ }
+ if ( !type_ct ) {
+ rc = LDAP_OBJECT_CLASS_VIOLATION;
+ goto leave;
+ }
+ rc = check_attr( type_ct, &ca, type_attr );
+ if ( rc ) goto leave;
+ }
+ for ( a=e->e_attrs; a; a=a->a_next ) {
+ if ( a == type_attr || a == oc_at ) continue;
+ ct = NULL;
+ for ( i=0; i<nocs; i++ ) {
+ ct = config_find_table( colst[i], a->a_desc );
+ if ( ct ) break;
+ }
+ if ( !ct ) continue; /* user data? */
+ rc = check_attr( ct, &ca, a );
+ if ( rc ) goto leave;
+ }
+
+ /* Basic syntax checks are OK. Do the actual settings. */
+ if ( type_ct ) {
+ ca.line = type_attr->a_nvals[0].bv_val;
+ rc = config_parse_add( type_ct, &ca, 0 );
+ if ( rc ) goto leave;
+ }
+ for ( a=e->e_attrs; a; a=a->a_next ) {
+ if ( a == type_attr || a == oc_at ) continue;
+ ct = NULL;
+ for ( i=0; i<nocs; i++ ) {
+ ct = config_find_table( colst[i], a->a_desc );
+ if ( ct ) break;
+ }
+ if ( !ct ) continue; /* user data? */
+ for (i=0; a->a_nvals[i].bv_val; i++) {
+ ca.line = a->a_nvals[i].bv_val;
+ rc = config_parse_add( ct, &ca, i );
+ if ( rc ) goto leave;
+ }
+ }
+ ce = ch_calloc( 1, sizeof(CfEntryInfo) );
+ ce->ce_entry = entry_dup( e );
+ ce->ce_entry->e_private = ce;
+ ce->ce_type = colst[0]->co_type;
+ if ( !last ) {
+ cfb->cb_root = ce;
+ } else if ( last->ce_kids ) {
+ CfEntryInfo *c2;
+
+ for (c2=last->ce_kids; c2 && c2->ce_sibs; c2 = c2->ce_sibs);
+ c2->ce_sibs = ce;
+ } else {
+ last->ce_kids = ce;
+ }
+
+leave:
+ ch_free( ca.argv );
+ if ( colst ) ch_free( colst );
+ return rc;
+}
+
+/* Parse an LDAP entry into config directives, then store in underlying
+ * database.
+ */
+static int
+config_back_add( Operation *op, SlapReply *rs )
+{
+ CfBackInfo *cfb;
+ CfEntryInfo *ce, *last;
+
+ if ( !be_isroot( op ) ) {
+ rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
+ send_ldap_result( op, rs );
+ }
+
+ cfb = (CfBackInfo *)op->o_bd->be_private;
+
+ ldap_pvt_thread_pool_pause( &connection_pool );
+
+ /* Strategy:
+ * 1) check for existence of entry
+ * 2) perform internal add
+ * 3) store entry in underlying database
+ */
+
+ ldap_pvt_thread_pool_resume( &connection_pool );
+
+out:
+ send_ldap_result( op, rs );
+ return rs->sr_err;
+}
+
static int
config_back_modify( Operation *op, SlapReply *rs )
{
int rc, i;
char *ptr;
const char *text;
+ char textbuf[SLAP_TEXT_BUFLEN];
+ size_t textlen = sizeof(textbuf);
AttributeType **at;
+ Attribute *oc_at;
BER_BVZERO( &vals[1] );
vals[0] = oc->soc_cname;
attr_merge(e, slap_schema.si_ad_objectClass, vals, NULL );
- attr_merge(e, slap_schema.si_ad_structuralObjectClass, vals, NULL );
ptr = strchr(rdn->bv_val, '=');
ad_name.bv_val = rdn->bv_val;
ad_name.bv_len = ptr - rdn->bv_val;
}
}
}
+ oc_at = attr_find( e->e_attrs, slap_schema.si_ad_objectClass );
+ rc = structural_class(oc_at->a_vals, vals, NULL, &text, textbuf, textlen);
+ BER_BVZERO( &vals[1] );
+ attr_merge(e, slap_schema.si_ad_structuralObjectClass, vals, NULL );
return 0;
}
op->ora_e = e;
op->o_bd->be_add( op, rs );
ce = e->e_private;
- ce->ce_type = Cf_Include;
+ ce->ce_type = Cft_Include;
ce->ce_bi = c->bi;
if ( !ceparent->ce_kids ) {
ceparent->ce_kids = ce;
config_build_entry( &c, e, cfOc_global, &rdn, ct, NO_TABLE );
op->ora_e = e;
op->o_bd->be_add( op, &rs );
- ce->ce_type = Cf_Global;
+ ce->ce_type = Cft_Global;
ce->ce_bi = c.bi;
parent = e;
ceparent = ce;
+ /* Create schema nodes... cn=schema will contain the hardcoded core
+ * schema, read-only. Child objects will contain runtime loaded schema
+ * files. FIXME
+ */
+
/* Create includeFile nodes... */
if ( cfb->cb_config->c_kids ) {
c.line = (char *)cfb->cb_config->c_kids;
rdn.bv_len = sprintf(rdn.bv_val, "%s=%s", cfAd_backend->ad_cname.bv_val, bi->bi_type);
e = config_alloc_entry( &parent->e_nname, &rdn );
ce = e->e_private;
- ce->ce_type = Cf_Backend;
+ ce->ce_type = Cft_Backend;
ce->ce_bi = bi;
c.bi = bi;
config_build_entry( &c, e, cfOc_backend, &rdn, ct, BI_TABLE );
ce = e->e_private;
c.be = bptr;
c.bi = bi;
- ce->ce_type = Cf_Database;
+ ce->ce_type = Cft_Database;
ce->ce_be = c.be;
ce->ce_bi = c.bi;
config_build_entry( &c, e, cfOc_database, &rdn, ct, BE_TABLE );
ce = oe->e_private;
c.be = bptr;
c.bi = &on->on_bi;
- ce->ce_type = Cf_Overlay;
+ ce->ce_type = Cft_Overlay;
ce->ce_be = c.be;
ce->ce_bi = c.bi;
config_build_entry( &c, oe, cfOc_overlay, &rdn, ct, BI_TABLE );
cfb = ch_calloc( 1, sizeof(CfBackInfo));
cfb->cb_config = &cf_prv;
+ cfb->cb_be = be;
be->be_private = cfb;
ber_dupbv( &be->be_rootdn, &config_rdn );
return(c);
}
+void
+init_config_argv( ConfigArgs *c )
+{
+ c->argv = ch_calloc( ARGS_STEP + 1, sizeof( *c->argv ) );
+ c->argv_size = ARGS_STEP + 1;
+}
+
ConfigTable *config_find_keyword(ConfigTable *Conf, ConfigArgs *c) {
int i;
return Conf+i;
}
-int config_add_vals(ConfigTable *Conf, ConfigArgs *c) {
+int config_check_vals(ConfigTable *Conf, ConfigArgs *c, int check_only ) {
int i, rc, arg_user, arg_type, iarg;
long larg;
ber_len_t barg;
void *ptr;
-
+
arg_type = Conf->arg_type;
if(arg_type == ARG_IGNORED) {
Debug(LDAP_DEBUG_CONFIG, "%s: keyword <%s> ignored\n",
c->log, Conf->name, 0);
return(0);
}
+ if((arg_type & ARG_DN) && c->argc == 1) {
+ c->argc = 2;
+ c->argv[1] = "";
+ }
if(Conf->min_args && (c->argc < Conf->min_args)) {
Debug(LDAP_DEBUG_CONFIG, "%s: keyword <%s> missing <%s> argument\n",
c->log, Conf->name, Conf->what);
break;
}
j = (arg_type & ARG_NONZERO) ? 1 : 0;
- if(iarg < j || larg < j || barg < j ) {
+ if(iarg < j && larg < j && barg < j ) {
larg = larg ? larg : (barg ? barg : iarg);
Debug(LDAP_DEBUG_CONFIG, "%s: " , c->log, 0, 0);
Debug(LDAP_DEBUG_CONFIG, "invalid %s value (%ld) in <%s> line\n", Conf->what, larg, Conf->name);
case ARG_BER_LEN_T: c->value_ber_t = barg; break;
}
} else if(arg_type & ARG_STRING) {
- c->value_string = ch_strdup(c->argv[1]);
+ if ( !check_only )
+ c->value_string = ch_strdup(c->argv[1]);
} else if(arg_type & ARG_BERVAL) {
- ber_str2bv( c->argv[1], 0, 1, &c->value_bv );
+ if ( !check_only )
+ ber_str2bv( c->argv[1], 0, 1, &c->value_bv );
} else if(arg_type & ARG_DN) {
struct berval bv;
ber_str2bv( c->argv[1], 0, 0, &bv );
Conf->name, rc, ldap_err2string( rc ));
return(ARG_BAD_CONF);
}
+ if ( check_only ) {
+ ch_free( c->value_ndn.bv_val );
+ ch_free( c->value_dn.bv_val );
+ }
}
+ return 0;
+}
+
+int config_set_vals(ConfigTable *Conf, ConfigArgs *c) {
+ int i, rc, arg_type, iarg;
+ long larg;
+ ber_len_t barg;
+ void *ptr;
+
+ arg_type = Conf->arg_type;
if(arg_type & ARG_MAGIC) {
if(!c->be) c->be = frontendDB;
rc = (*((ConfigDriver*)Conf->arg_item))(c);
+#if 0
if(c->be == frontendDB) c->be = NULL;
+#endif
if(rc) {
Debug(LDAP_DEBUG_CONFIG, "%s: handler for <%s> exited with %d!\n",
c->log, Conf->name, rc);
c->log, Conf->name, 0 );
return(ARG_BAD_CONF);
}
- ch_free(cc); /* potential memory leak */
+ ch_free(cc);
}
*(char **)ptr = c->value_string;
break;
*(struct berval *)ptr = c->value_bv;
break;
}
- return(arg_user);
+ return(0);
+}
+
+int config_add_vals(ConfigTable *Conf, ConfigArgs *c) {
+ int i, rc, arg_type, iarg;
+
+ arg_type = Conf->arg_type;
+ if(arg_type == ARG_IGNORED) {
+ Debug(LDAP_DEBUG_CONFIG, "%s: keyword <%s> ignored\n",
+ c->log, Conf->name, 0);
+ return(0);
+ }
+ rc = config_check_vals( Conf, c, 0 );
+ if ( rc ) return rc;
+ return config_set_vals( Conf, c );
}
int
return 0;
}
+int
+config_parse_vals(ConfigTable *ct, ConfigArgs *c, int valx)
+{
+ int rc = 0;
+
+ snprintf( c->log, sizeof( c->log ), "%s: value #%d",
+ ct->ad->ad_cname.bv_val, valx );
+ c->argc = 1;
+ c->argv[0] = ct->ad->ad_cname.bv_val;
+ if ( fp_parse_line( c ) ) {
+ rc = 1;
+ } else {
+ rc = config_check_vals( ct, c, 1 );
+ }
+
+ ch_free( c->tline );
+ return rc;
+}
+
+int
+config_parse_add(ConfigTable *ct, ConfigArgs *c, int valx)
+{
+ int rc = 0;
+
+ snprintf( c->log, sizeof( c->log ), "%s: value #%d",
+ ct->ad->ad_cname.bv_val, valx );
+ c->argc = 1;
+ c->argv[0] = ct->ad->ad_cname.bv_val;
+ if ( fp_parse_line( c ) ) {
+ rc = 1;
+ } else {
+ c->op = LDAP_MOD_ADD;
+ rc = config_add_vals( ct, c );
+ }
+
+ ch_free( c->tline );
+ return rc;
+}
+
int
read_config_file(const char *fname, int depth, ConfigArgs *cf)
{
}
c->fname = fname;
- c->argv = ch_calloc( ARGS_STEP + 1, sizeof( *c->argv ) );
- c->argv_size = ARGS_STEP + 1;
+ init_config_argv( c );
fp = fopen( fname, "r" );
if ( fp == NULL ) {
fp_getline_init(c);
+ c->tline = NULL;
+
while ( fp_getline( fp, c ) ) {
/* skip comments and blank lines */
if ( c->line[0] == '#' || c->line[0] == '\0' ) {
c->fname, c->lineno );
c->argc = 0;
+ ch_free( c->tline );
if ( fp_parse_line( c ) ) {
- goto badline;
+ rc = 1;
+ goto leave;
}
if ( c->argc < 1 ) {
/* XXX a usertype would be opaque here */
Debug(LDAP_DEBUG_CONFIG, "%s: unknown user type <%s>\n",
c->log, c->argv[0], 0);
- goto badline;
+ rc = 1;
+ goto leave;
} else if ( rc == ARG_BAD_CONF ) {
- goto badline;
+ rc = 1;
+ goto leave;
}
} else if ( c->bi ) {
c->log, *c->argv, 0);
continue;
default:
- goto badline;
+ rc = 1;
+ goto leave;
}
}
c->log, *c->argv, 0);
continue;
default:
- goto badline;
+ rc = 1;
+ goto leave;
}
}
c->log, *c->argv, 0);
continue;
default:
- goto badline;
+ rc = 1;
+ goto leave;
}
}
}
}
- fclose(fp);
-
if ( BER_BVISNULL( &frontendDB->be_schemadn ) ) {
ber_str2bv( SLAPD_SCHEMA_DN, STRLENOF( SLAPD_SCHEMA_DN ), 1,
&frontendDB->be_schemadn );
assert( 0 );
}
}
+ rc = 0;
- ch_free(c->argv);
- ch_free(c);
- return(0);
-
-badline:
+leave:
+ ch_free(c->tline);
fclose(fp);
ch_free(c->argv);
ch_free(c);
- return(1);
+ return(rc);
}
/* restrictops, allows, disallows, requires, loglevel */
fp_parse_line(ConfigArgs *c)
{
char *token;
- char *tline = ch_strdup(c->line);
char *hide[] = { "rootpw", "replica", "bindpw", "pseudorootpw", "dbpasswd", '\0' };
char *quote_ptr;
int i;
- token = strtok_quote(tline, " \t", "e_ptr);
+ c->tline = ch_strdup(c->line);
+ token = strtok_quote(c->tline, " \t", "e_ptr);
if(token) for(i = 0; hide[i]; i++) if(!strcasecmp(token, hide[i])) break;
if(quote_ptr) *quote_ptr = ' ';