diff --git a/servers/slapd/Makefile.in b/servers/slapd/Makefile.in
index 8c5ed62189..465e26f705 100644
--- a/servers/slapd/Makefile.in
+++ b/servers/slapd/Makefile.in
@@ -23,7 +23,7 @@ SUBDIRS=back-* shell-backends slapi overlays
NT_SRCS = nt_svc.c
NT_OBJS = nt_svc.o ../../libraries/liblutil/slapdmsg.res
-SRCS = main.c globals.c config.c daemon.c \
+SRCS = main.c globals.c bconfig.c config.c daemon.c \
connection.c search.c filter.c add.c cr.c \
attr.c entry.c backend.c result.c operation.c \
dn.c compare.c modify.c delete.c modrdn.c ch_malloc.c \
@@ -40,7 +40,7 @@ SRCS = main.c globals.c config.c daemon.c \
slappasswd.c slaptest.c slapauth.c slapacl.c component.c \
$(@PLAT@_SRCS)
-OBJS = main.o globals.o config.o daemon.o \
+OBJS = main.o globals.o bconfig.o config.o daemon.o \
connection.o search.o filter.o add.o cr.o \
attr.o entry.o backend.o result.o operation.o \
dn.o compare.o modify.o delete.o modrdn.o ch_malloc.o \
diff --git a/servers/slapd/bconfig.c b/servers/slapd/bconfig.c
new file mode 100644
index 0000000000..a1af4a4c98
--- /dev/null
+++ b/servers/slapd/bconfig.c
@@ -0,0 +1,343 @@
+/* bconfig.c - the config backend */
+/* $OpenLDAP$ */
+/* This work is part of OpenLDAP Software .
+ *
+ * Copyright 2005 The OpenLDAP Foundation.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted only as authorized by the OpenLDAP
+ * Public License.
+ *
+ * A copy of this license is available in the file LICENSE in the
+ * top-level directory of the distribution or, alternatively, at
+ * .
+ */
+/* ACKNOWLEDGEMENTS:
+ * This work was originally developed by Howard Chu for inclusion
+ * in OpenLDAP Software.
+ */
+
+#include "portable.h"
+
+#include
+#include
+
+#include "slap.h"
+#include "config.h"
+
+#define CONFIG_DN "cn=config"
+
+typedef struct CfEntryInfo {
+ struct CfEntryInfo *ce_sibs;
+ struct CfEntryInfo *ce_kids;
+ Entry *ce_entry;
+ ConfigTable *ce_table;
+} CfEntryInfo;
+
+typedef struct {
+ ConfigFile *cb_config;
+ CfEntryInfo *cb_root;
+} CfBackInfo;
+
+static int
+config_back_bind( Operation *op, SlapReply *rs )
+{
+ if ( op->orb_method == LDAP_AUTH_SIMPLE && be_isroot_pw( op )) {
+ ber_dupbv( &op->orb_edn, be_root_dn( op->o_bd ));
+ /* frontend sends result */
+ return LDAP_SUCCESS;
+ }
+
+ rs->sr_err = LDAP_INVALID_CREDENTIALS;
+ send_ldap_result( op, rs );
+
+ return rs->sr_err;
+}
+
+static CfEntryInfo *
+config_find_base( CfEntryInfo *root, struct berval *dn, CfEntryInfo **last )
+{
+ struct berval cdn;
+ char *c;
+
+ if ( dn_match( &root->ce_entry->e_nname, dn ))
+ return root;
+
+ c = dn->bv_val+dn->bv_len;
+ for (;*c != ',';c--);
+
+ while(root) {
+ *last = root;
+ for (--c;c>dn->bv_val && *c != ',';c--);
+ if ( *c == ',' )
+ c++;
+ cdn.bv_val = c;
+ cdn.bv_len = dn->bv_len - (c-dn->bv_val);
+
+ root = root->ce_kids;
+
+ for (;root;root=root->ce_sibs) {
+ if ( dn_match( &root->ce_entry->e_nname, &cdn )) {
+ if ( cdn.bv_val == dn->bv_val ) {
+ return root;
+ }
+ break;
+ }
+ }
+ }
+ return root;
+}
+
+static int
+config_send( Operation *op, SlapReply *rs, CfEntryInfo *ce, int depth )
+{
+ int rc = 0;
+
+ if ( test_filter( op, ce->ce_entry, op->ors_filter ) == LDAP_COMPARE_TRUE )
+ {
+ rs->sr_attrs = op->ors_attrs;
+ rs->sr_entry = ce->ce_entry;
+ rc = send_search_entry( op, rs );
+ }
+ if ( op->ors_scope == LDAP_SCOPE_SUBTREE ) {
+ if ( ce->ce_kids ) {
+ rc = config_send( op, rs, ce->ce_kids, 1 );
+ if ( rc ) return rc;
+ }
+ if ( depth ) {
+ for (ce=ce->ce_sibs; ce; ce=ce->ce_sibs) {
+ rc = config_send( op, rs, ce, 0 );
+ if ( rc ) break;
+ }
+ }
+ }
+ return rc;
+}
+
+static int
+config_back_search( Operation *op, SlapReply *rs )
+{
+ CfBackInfo *cfb;
+ CfEntryInfo *ce, *last;
+ int rc;
+
+ if ( !be_isroot( op ) ) {
+ rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
+ send_ldap_result( op, rs );
+ }
+
+ cfb = (CfBackInfo *)op->o_bd->be_private;
+
+ ce = config_find_base( cfb->cb_root, &op->o_req_ndn, &last );
+ if ( !ce ) {
+ if ( last )
+ rs->sr_matched = last->ce_entry->e_name.bv_val;
+ rs->sr_err = LDAP_NO_SUCH_OBJECT;
+ goto out;
+ }
+ switch ( op->ors_scope ) {
+ case LDAP_SCOPE_BASE:
+ case LDAP_SCOPE_SUBTREE:
+ config_send( op, rs, ce, 0 );
+ break;
+
+ case LDAP_SCOPE_ONELEVEL:
+ for (ce = ce->ce_kids; ce; ce=ce->ce_sibs) {
+ config_send( op, rs, ce, 1 );
+ }
+ break;
+ }
+
+ rs->sr_err = LDAP_SUCCESS;
+out:
+ send_ldap_result( op, rs );
+ return 0;
+}
+
+static Entry *
+config_alloc_entry( struct berval *pdn, struct berval *rdn )
+{
+ Entry *e = ch_calloc( 1, sizeof(Entry) );
+ CfEntryInfo *ce = ch_calloc( 1, sizeof(CfEntryInfo) );
+ e->e_private = ce;
+ ce->ce_entry = e;
+ build_new_dn( &e->e_name, pdn, rdn, NULL );
+ ber_dupbv( &e->e_nname, &e->e_name );
+ return e;
+}
+
+static int
+config_build_entry( Entry *e, void *private, char *oc, struct berval *rdn )
+{
+ struct berval vals[2];
+ struct berval ad_name;
+ AttributeDescription *ad = NULL;
+ int rc;
+ char *ptr;
+ const char *text;
+
+ BER_BVZERO( &vals[1] );
+
+ ber_str2bv( oc, 0, 0, &vals[0] );
+ attr_merge(e, slap_schema.si_ad_objectClass, vals, NULL );
+ ptr = strchr(rdn->bv_val, '=');
+ ad_name.bv_val = rdn->bv_val;
+ ad_name.bv_len = ptr - rdn->bv_val;
+ rc = slap_bv2ad( &ad_name, &ad, &text );
+ if ( rc ) {
+ return rc;
+ }
+ vals[0].bv_val = ptr+1;
+ vals[0].bv_len = rdn->bv_len - (vals[0].bv_val - rdn->bv_val);
+ attr_merge(e, ad, vals, NULL );
+ return 0;
+}
+
+static int
+config_back_db_open( BackendDB *be )
+{
+ CfBackInfo *cfb = be->be_private;
+ struct berval rdn;
+ Entry *e, *parent;
+ CfEntryInfo *ce, *ceparent, *ceprev;
+ int i, buflen = 0;
+ char *buf = NULL;
+ BackendInfo *bi;
+ BackendDB *bptr;
+
+ /* create root of tree */
+ ber_str2bv( CONFIG_DN, STRLENOF( CONFIG_DN ), 0, &rdn );
+ e = config_alloc_entry( NULL, &rdn );
+ ce = e->e_private;
+ ce->ce_table = be->bd_info->bi_cf_table;
+ cfb->cb_root = ce;
+
+ config_build_entry( e, be->be_private, "olcGlobal", &rdn );
+
+ parent = e;
+ ceparent = ce;
+
+ /* Create backend nodes. Skip if they don't provide a cf_table.
+ * There usually aren't any of these.
+ */
+ bi = backendInfo;
+ for (i=0; ibi_cf_table) continue;
+ if (!bi->bi_private) continue;
+
+ if ( buflen < STRLENOF("olcbackend=")+strlen(bi->bi_type)+1) {
+ buflen = STRLENOF("olcbackend=") + strlen(bi->bi_type)+1;
+ buf = realloc(buf, buflen);
+ }
+ rdn.bv_val = buf;
+ rdn.bv_len = sprintf(buf, "olcBackend=%s", bi->bi_type);
+ e = config_alloc_entry( &parent->e_nname, &rdn );
+ ce = e->e_private;
+ ce->ce_table = bi->bi_cf_table;
+ config_build_entry( e, bi->bi_private, "olcBackendConfig",
+ &rdn );
+ if ( !ceparent->ce_kids ) {
+ ceparent->ce_kids = ce;
+ } else {
+ ceprev->ce_sibs = ce;
+ }
+ ceprev = ce;
+ }
+
+ /* Create database nodes... */
+ for (i=0; ibd_info;
+ if ( buflen < STRLENOF("olcdatabase={xxxxxxxx}")+strlen(bi->bi_type)+1) {
+ buflen = STRLENOF("olcdatabase={xxxxxxxx}")+strlen(bi->bi_type)+1;
+ buf = realloc(buf, buflen);
+ }
+ rdn.bv_val = buf;
+ rdn.bv_len = sprintf(buf, "olcDatabase={%0x}%s", i, bi->bi_type);
+ e = config_alloc_entry( &parent->e_nname, &rdn );
+ ce = e->e_private;
+ ce->ce_table = bptr->be_cf_table;
+ config_build_entry( e, bptr->be_private, "olcDatabaseConfig",
+ &rdn );
+ if ( !ceparent->ce_kids ) {
+ ceparent->ce_kids = ce;
+ } else {
+ ceprev->ce_sibs = ce;
+ }
+ ceprev = ce;
+ /* Iterate through overlays */
+
+ }
+ /* Create includeFile nodes... */
+
+ return 0;
+}
+
+static int
+config_back_db_destroy( Backend *be )
+{
+ free( be->be_private );
+ return 0;
+}
+
+int
+config_back_initialize( BackendInfo *bi )
+{
+ bi->bi_open = 0;
+ bi->bi_close = 0;
+ bi->bi_config = 0;
+ bi->bi_destroy = 0;
+
+ bi->bi_db_init = 0;
+ bi->bi_db_config = 0;
+ bi->bi_db_open = config_back_db_open;
+ bi->bi_db_close = 0;
+ bi->bi_db_destroy = config_back_db_destroy;
+
+ bi->bi_op_bind = config_back_bind;
+ bi->bi_op_unbind = 0;
+ bi->bi_op_search = config_back_search;
+ bi->bi_op_compare = 0;
+ bi->bi_op_modify = 0;
+ bi->bi_op_modrdn = 0;
+ bi->bi_op_add = 0;
+ bi->bi_op_delete = 0;
+ bi->bi_op_abandon = 0;
+
+ bi->bi_extended = 0;
+
+ bi->bi_chk_referrals = 0;
+
+ bi->bi_connection_init = 0;
+ bi->bi_connection_destroy = 0;
+
+ return 0;
+}
+
+void config_back_init( ConfigFile *cfp, ConfigTable *ct )
+{
+ BackendInfo bi = {0};
+ BackendDB *be;
+ struct berval dn;
+ CfBackInfo *cfb;
+
+ bi.bi_type = "config";
+ bi.bi_init = config_back_initialize;
+ bi.bi_cf_table = ct;
+ backend_add( &bi );
+ be = backend_db_init( bi.bi_type );
+ ber_str2bv( CONFIG_DN, 0, 1, &be->be_rootdn );
+ ber_dupbv( &be->be_rootndn, &be->be_rootdn );
+ ber_dupbv( &dn, &be->be_rootdn );
+ ber_bvarray_add( &be->be_suffix, &dn );
+ ber_dupbv( &dn, &be->be_rootdn );
+ ber_bvarray_add( &be->be_nsuffix, &dn );
+ cfb = ch_calloc( 1, sizeof(CfBackInfo));
+ cfb->cb_config = cfp;
+ be->be_private = cfb;
+}
diff --git a/servers/slapd/config.c b/servers/slapd/config.c
index 6bc3b79b31..0f542a905e 100644
--- a/servers/slapd/config.c
+++ b/servers/slapd/config.c
@@ -89,6 +89,9 @@ static char *strtok_quote(char *line, char *sep);
static int load_ucdata(char *path);
#endif
+/* state info for back-config */
+static ConfigFile cf_prv, *cfn = &cf_prv;
+
int read_config_file(const char *fname, int depth, ConfigArgs *cf);
static int add_syncrepl LDAP_P(( Backend *, char **, int ));
@@ -297,7 +300,7 @@ ConfigTable SystemConfiguration[] = {
&config_generic, "( OLcfgAt:29 NAME 'olcMaxDerefDepth' "
"SYNTAX OMsInteger )", NULL, NULL },
#ifdef SLAPD_MODULES
- { "moduleload", "file", 2, 2, 0, ARG_MAGIC|CFG_MODLOAD,
+ { "moduleload", "file", 2, 0, 0, ARG_MAGIC|CFG_MODLOAD,
&config_generic, "( OLcfgAt:30 NAME 'olcModuleLoad' "
"SYNTAX OMsDirectoryString )", NULL, NULL },
{ "modulepath", "path", 2, 2, 0, ARG_MAGIC|CFG_MODPATH,
@@ -620,7 +623,7 @@ int parse_config_table(ConfigTable *Conf, ConfigArgs *c) {
}
int
-init_config_schema(ConfigTable *ct) {
+init_config_attrs(ConfigTable *ct) {
LDAPAttributeType *at;
int i, code;
const char *err;
@@ -654,13 +657,17 @@ read_config(const char *fname, int depth) {
int i;
char *argv[3];
+ /* Schema initialization should normally be part of bi_open */
for (i=0; OidMacros[i].name; i++ ) {
argv[1] = OidMacros[i].name;
argv[2] = OidMacros[i].oid;
parse_oidm( "slapd", i, 3, argv );
}
- i = init_config_schema(SystemConfiguration);
+ i = init_config_attrs(SystemConfiguration);
if ( i ) return i;
+
+
+ config_back_init( &cf_prv, SystemConfiguration );
return read_config_file(fname, depth, NULL);
}
@@ -696,6 +703,11 @@ read_config_file(const char *fname, int depth, ConfigArgs *cf)
fname, strerror(errno), errno);
return(1);
}
+#ifdef SLAPD_MODULES
+ cfn->c_modlast = &cfn->c_modpaths;
+#endif
+ ber_str2bv( fname, 0, 1, &cfn->c_file );
+ fname = cfn->c_file.bv_val;
Debug(LDAP_DEBUG_CONFIG, "reading config file %s\n", fname, 0, 0);
@@ -827,7 +839,9 @@ config_generic(ConfigArgs *c) {
case CFG_DATABASE:
c->bi = NULL;
- if(!(c->be = backend_db_init(c->argv[1]))) {
+ if ( !strcasecmp( c->argv[1], "config" )) {
+ c->be = backendDB;
+ } 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);
return(1);
@@ -923,12 +937,6 @@ config_generic(ConfigArgs *c) {
parse_acl(c->be, c->fname, c->lineno, c->argc, c->argv);
break;
-#if 0
- case CFG_AUDITLOG:
- c->be->be_auditlogfile = c->value_string;
- break;
-#endif
-
case CFG_REPLOG:
if(SLAP_MONITOR(c->be)) {
Debug(LDAP_DEBUG_ANY, "%s: "
@@ -948,6 +956,11 @@ config_generic(ConfigArgs *c) {
c->log, 0, 0);
return(1);
}
+ {
+ struct berval bv;
+ ber_str2bv( c->argv[1], 0, 1, &bv );
+ ber_bvarray_add( &cfn->c_dseFiles, &bv );
+ }
break;
case CFG_LOGFILE: {
@@ -973,10 +986,31 @@ config_generic(ConfigArgs *c) {
case CFG_MODLOAD:
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;
+ ber_str2bv(c->line, 0, 1, &bv);
+ ber_bvarray_add( &cfn->c_modlast->mp_loads, &bv );
+ }
break;
case CFG_MODPATH:
if(module_path(c->argv[1])) return(1);
+ /* Record which path was used with each module */
+ {
+ ModPaths *mp;
+
+ if (!cfn->c_modpaths.mp_loads)
+ mp = &cfn->c_modpaths;
+ else
+ mp = ch_malloc( sizeof( ModPaths ));
+ ber_str2bv(c->argv[1], 0, 1, &mp->mp_path);
+ mp->mp_next = NULL;
+ mp->mp_loads = NULL;
+ cfn->c_modlast->mp_next = mp;
+ cfn->c_modlast = mp;
+ }
+
break;
#endif
@@ -1635,12 +1669,26 @@ config_updateref(ConfigArgs *c) {
int
config_include(ConfigArgs *c) {
- char *savefname = ch_strdup(c->argv[1]);
unsigned long savelineno = c->lineno;
int rc;
- rc = read_config_file(savefname, c->depth + 1, c);
- free(savefname);
+ ConfigFile *cf = ch_calloc( 1, sizeof(ConfigFile));
+ ConfigFile *cfsave = cfn;
+ ConfigFile *cf2 = NULL;
+ if ( cfn->c_kids ) {
+ for (cf2=cfn->c_kids; cf2 && cf2->c_sibs; cf2=cf2->c_sibs) ;
+ cf2->c_sibs = cf;
+ } else {
+ cfn->c_kids = cf;
+ }
+ cfn = cf;
+ 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 );
+ }
return(rc);
}
diff --git a/servers/slapd/config.h b/servers/slapd/config.h
index 69ed0366fc..3c614e7355 100644
--- a/servers/slapd/config.h
+++ b/servers/slapd/config.h
@@ -15,7 +15,7 @@
* .
*/
-typedef struct config_table_s {
+typedef struct ConfigTable {
char *name;
char *what;
int min_args;
@@ -76,3 +76,24 @@ typedef struct config_args_s {
} ConfigArgs;
typedef int (ConfigDriver)(ConfigArgs *c);
+
+#ifdef SLAPD_MODULES
+typedef struct modpath_s {
+ struct modpath_s *mp_next;
+ struct berval mp_path;
+ BerVarray mp_loads;
+} ModPaths;
+#endif
+
+typedef struct ConfigFile {
+ struct ConfigFile *c_sibs;
+ struct ConfigFile *c_kids;
+ struct berval c_file;
+#ifdef SLAPD_MODULES
+ ModPaths c_modpaths;
+ ModPaths *c_modlast;
+#endif
+ BerVarray c_dseFiles;
+} ConfigFile;
+
+void config_back_init( ConfigFile *cfp, ConfigTable *ct );
diff --git a/servers/slapd/slap.h b/servers/slapd/slap.h
index 799a5b7d8a..58745a592e 100644
--- a/servers/slapd/slap.h
+++ b/servers/slapd/slap.h
@@ -1704,6 +1704,7 @@ struct slap_backend_db {
char *be_realm;
void *be_pb; /* Netscape plugin */
+ struct ConfigTable *be_cf_table;
void *be_private; /* anything the backend database needs */
};
@@ -1911,6 +1912,8 @@ typedef int (BI_tool_id2entry_get) LDAP_P(( BackendDB *be, ID id, Entry **e ));
typedef ID (BI_tool_entry_modify) LDAP_P(( BackendDB *be, Entry *e,
struct berval *text ));
+struct ConfigTable; /* config.h */
+
struct slap_backend_info {
char *bi_type; /* type of backend */
@@ -2033,6 +2036,7 @@ struct slap_backend_info {
char bi_ctrls[SLAP_MAX_CIDS + 1];
unsigned int bi_nDB; /* number of databases of this type */
+ struct ConfigTable *bi_cf_table;
void *bi_private; /* anything the backend type needs */
};