mirror of
https://git.openldap.org/openldap/openldap.git
synced 2025-01-06 10:46:21 +08:00
More for loading config from LDIF
This commit is contained in:
parent
3f45b796b4
commit
fda662bd34
@ -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
|
||||
|
@ -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
|
||||
|
@ -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 );
|
||||
|
@ -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", "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 = ' ';
|
||||
|
@ -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];
|
||||
|
Loading…
Reference in New Issue
Block a user