From efc8c43b73acce404ed82c9d442433d237873c9c Mon Sep 17 00:00:00 2001 From: Howard Chu Date: Sun, 20 Feb 2005 18:33:40 +0000 Subject: [PATCH] Adding back-config pieces --- servers/slapd/Makefile.in | 4 +- servers/slapd/bconfig.c | 343 ++++++++++++++++++++++++++++++++++++++ servers/slapd/config.c | 74 ++++++-- servers/slapd/config.h | 23 ++- servers/slapd/slap.h | 4 + 5 files changed, 432 insertions(+), 16 deletions(-) create mode 100644 servers/slapd/bconfig.c 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 */ }; -- 2.39.5