More for loading config from LDIF

This commit is contained in:
Howard Chu 2005-03-20 09:13:48 +00:00
parent 3f45b796b4
commit fda662bd34
5 changed files with 519 additions and 85 deletions

View File

@ -111,12 +111,13 @@ static ConfigOCs bdbocs[] = {
{ "( OLcfgOc:1.1 "
"NAME 'bdbConfig' "
"DESC 'BDB backend configuration' "
"AUXILIARY "
"MAY ( dbDirectory $ dbCacheSize $ dbCheckpoint $ dbNoSync $ "
"SUP olcDatabaseConfig "
"MUST dbDirectory "
"MAY ( dbCacheSize $ dbCheckpoint $ dbNoSync $ "
"dbDirtyRead $ dbIDLcacheSize $ dbIndex $ dbLinearIndex $ "
"dbLockDetect $ dbMode $ dbSearchStack $ dbShmKey ) )",
&bdb_oc },
{ NULL, NULL }
Cft_Database, &bdb_oc },
{ NULL, 0, NULL }
};
static int

View File

@ -65,10 +65,10 @@ static ConfigOCs ldifocs[] = {
{ "( OLcfgOc:2.1 "
"NAME 'ldifConfig' "
"DESC 'LDIF backend configuration' "
"AUXILIARY "
"MAY ( dbDirectory ) )",
"SUP olcDatabaseConfig "
"MUST ( dbDirectory ) )", Cft_Database,
&ldif_oc },
{ NULL, NULL }
{ NULL, 0, NULL }
};
static int

View File

@ -59,21 +59,14 @@ typedef struct ConfigFile {
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;
@ -81,6 +74,7 @@ typedef struct CfEntryInfo {
typedef struct {
ConfigFile *cb_config;
CfEntryInfo *cb_root;
BackendDB *cb_be; /* config backend */
BackendDB cb_db; /* underlying database */
int cb_got_ldif;
} CfBackInfo;
@ -101,7 +95,7 @@ static struct berval cfdir;
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;
@ -111,6 +105,7 @@ static Avlnode *CfOcTree;
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;
@ -261,7 +256,7 @@ ConfigTable config_back_cf_table[] = {
"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,
@ -572,8 +567,8 @@ static ConfigOCs cf_ocs[] = {
"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 "
@ -588,18 +583,24 @@ static ConfigOCs cf_ocs[] = {
"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' "
@ -608,19 +609,20 @@ static ConfigOCs cf_ocs[] = {
"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
@ -828,6 +830,8 @@ config_generic(ConfigArgs *c) {
*/
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);
@ -895,7 +899,7 @@ config_generic(ConfigArgs *c) {
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:
@ -1064,7 +1068,7 @@ config_fname(ConfigArgs *c) {
value_add_one( &c->rvalue_vals, &cf->c_file );
return 0;
}
return(1);
return(0);
}
static int
@ -1073,7 +1077,7 @@ config_cfdir(ConfigArgs *c) {
value_add_one( &c->rvalue_vals, &cfdir );
return 0;
}
return(1);
return(0);
}
static int
@ -1277,8 +1281,11 @@ config_suffix(ConfigArgs *c) {
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;
@ -1340,7 +1347,7 @@ config_rootpw(ConfigArgs *c) {
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;
@ -1904,15 +1911,15 @@ config_include(ConfigArgs *c) {
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);
}
@ -2547,25 +2554,11 @@ config_ldif_resp( Operation *op, SlapReply *rs )
{
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 */
@ -2675,6 +2668,7 @@ config_register_schema(ConfigTable *ct, ConfigOCs *ocs) {
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 );
}
}
@ -2684,6 +2678,7 @@ config_register_schema(ConfigTable *ct, ConfigOCs *ocs) {
int
read_config(const char *fname, const char *dir) {
BackendDB *be;
CfBackInfo *cfb;
/* Setup the config backend */
be = backend_db_init( "config" );
@ -2696,6 +2691,7 @@ read_config(const char *fname, const char *dir) {
#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
@ -2745,6 +2741,333 @@ config_send( Operation *op, SlapReply *rs, CfEntryInfo *ce, int depth )
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 )
{
@ -2845,13 +3168,15 @@ config_build_entry( ConfigArgs *c, Entry *e, ObjectClass *oc,
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;
@ -2910,6 +3235,10 @@ config_build_entry( ConfigArgs *c, Entry *e, ObjectClass *oc,
}
}
}
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;
}
@ -2935,7 +3264,7 @@ config_build_includes( ConfigArgs *c, Entry *parent,
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;
@ -2995,12 +3324,17 @@ config_back_db_open( BackendDB *be )
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;
@ -3021,7 +3355,7 @@ config_back_db_open( BackendDB *be )
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 );
@ -3056,7 +3390,7 @@ config_back_db_open( BackendDB *be )
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 );
@ -3083,7 +3417,7 @@ config_back_db_open( BackendDB *be )
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 );
@ -3117,6 +3451,7 @@ config_back_db_init( Backend *be )
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 );

View File

@ -101,6 +101,13 @@ new_config_args( BackendDB *be, const char *fname, int lineno, int argc, char **
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;
@ -111,18 +118,22 @@ ConfigTable *config_find_keyword(ConfigTable *Conf, ConfigArgs *c) {
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);
@ -185,7 +196,7 @@ int config_add_vals(ConfigTable *Conf, ConfigArgs *c) {
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);
@ -198,9 +209,11 @@ int config_add_vals(ConfigTable *Conf, ConfigArgs *c) {
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 );
@ -211,11 +224,27 @@ int config_add_vals(ConfigTable *Conf, ConfigArgs *c) {
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);
@ -251,7 +280,7 @@ int config_add_vals(ConfigTable *Conf, ConfigArgs *c) {
c->log, Conf->name, 0 );
return(ARG_BAD_CONF);
}
ch_free(cc); /* potential memory leak */
ch_free(cc);
}
*(char **)ptr = c->value_string;
break;
@ -260,7 +289,21 @@ int config_add_vals(ConfigTable *Conf, ConfigArgs *c) {
*(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
@ -409,6 +452,45 @@ init_config_ocs( ConfigOCs *ocs ) {
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)
{
@ -431,8 +513,7 @@ 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 ) {
@ -447,6 +528,8 @@ read_config_file(const char *fname, int depth, ConfigArgs *cf)
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' ) {
@ -457,8 +540,10 @@ read_config_file(const char *fname, int depth, ConfigArgs *cf)
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 ) {
@ -477,10 +562,12 @@ read_config_file(const char *fname, int depth, ConfigArgs *cf)
/* 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 ) {
@ -503,7 +590,8 @@ read_config_file(const char *fname, int depth, ConfigArgs *cf)
c->log, *c->argv, 0);
continue;
default:
goto badline;
rc = 1;
goto leave;
}
}
@ -528,7 +616,8 @@ read_config_file(const char *fname, int depth, ConfigArgs *cf)
c->log, *c->argv, 0);
continue;
default:
goto badline;
rc = 1;
goto leave;
}
}
@ -542,7 +631,8 @@ read_config_file(const char *fname, int depth, ConfigArgs *cf)
c->log, *c->argv, 0);
continue;
default:
goto badline;
rc = 1;
goto leave;
}
}
@ -555,8 +645,6 @@ read_config_file(const char *fname, int depth, ConfigArgs *cf)
}
}
fclose(fp);
if ( BER_BVISNULL( &frontendDB->be_schemadn ) ) {
ber_str2bv( SLAPD_SCHEMA_DN, STRLENOF( SLAPD_SCHEMA_DN ), 1,
&frontendDB->be_schemadn );
@ -569,16 +657,14 @@ read_config_file(const char *fname, int depth, ConfigArgs *cf)
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 */
@ -874,12 +960,12 @@ static int
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", &quote_ptr);
c->tline = ch_strdup(c->line);
token = strtok_quote(c->tline, " \t", &quote_ptr);
if(token) for(i = 0; hide[i]; i++) if(!strcasecmp(token, hide[i])) break;
if(quote_ptr) *quote_ptr = ' ';

View File

@ -27,6 +27,16 @@ typedef struct ConfigTable {
void *notify;
} ConfigTable;
typedef enum {
Cft_Abstract = 0,
Cft_Global,
Cft_Schema,
Cft_Backend,
Cft_Database,
Cft_Overlay,
Cft_Include,
} ConfigType;
#define ARGS_USERLAND 0x00000fff
#define ARGS_TYPES 0x000ff000
#define ARGS_POINTER 0x0003f000
@ -59,6 +69,7 @@ extern ConfigTable config_back_cf_table[];
typedef struct ConfigOCs {
char *def;
ConfigType cft;
ObjectClass **oc;
} ConfigOCs;
@ -67,6 +78,7 @@ typedef struct config_args_s {
char **argv;
int argv_size;
char *line;
char *tline;
const char *fname;
unsigned long lineno;
char log[PATH_MAX + STRLENOF(": line 18446744073709551615") + 1];