X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=servers%2Fslapd%2Fbconfig.c;h=d3f28a9d663af4f43c42b01b745d9500bd6e0abc;hb=3eb87b2faae4b9f59f1270936f70a1781c2abd7a;hp=0faa3a50838d7eabf9549088ac256f5c0f16d933;hpb=3f357270d4cbc812211d69fda6cf685c5963036b;p=openldap diff --git a/servers/slapd/bconfig.c b/servers/slapd/bconfig.c index 0faa3a5083..d3f28a9d66 100644 --- a/servers/slapd/bconfig.c +++ b/servers/slapd/bconfig.c @@ -38,6 +38,8 @@ static struct berval config_rdn = BER_BVC("cn=config"); static struct berval schema_rdn = BER_BVC("cn=schema"); +#define IFMT "{%d}" + #ifdef SLAPD_MODULES typedef struct modpath_s { struct modpath_s *mp_next; @@ -78,7 +80,6 @@ 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; @@ -109,7 +110,8 @@ 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 int config_add_internal( CfBackInfo *cfb, Entry *e, SlapReply *rs, + int *renumber ); static ConfigDriver config_fname; static ConfigDriver config_cfdir; @@ -262,7 +264,7 @@ ConfigTable config_back_cf_table[] = { &config_generic, "( OLcfgAt:9 NAME 'olcBackend' " "DESC 'A type of backend' " "EQUALITY caseIgnoreMatch " - "SYNTAX OMsDirectoryString X-ORDERED 'VALUES' )", NULL, NULL }, + "SYNTAX OMsDirectoryString X-ORDERED 'SIBLINGS' )", NULL, NULL }, { "concurrency", "level", 2, 2, 0, ARG_INT|ARG_MAGIC|CFG_CONCUR, &config_generic, "( OLcfgAt:10 NAME 'olcConcurrency' " "SYNTAX OMsInteger SINGLE-VALUE )", NULL, NULL }, @@ -275,7 +277,7 @@ ConfigTable config_back_cf_table[] = { { "database", "type", 2, 2, 0, ARG_MAGIC|CFG_DATABASE, &config_generic, "( OLcfgAt:13 NAME 'olcDatabase' " "DESC 'The backend type for a database instance' " - "SUP olcBackend X-ORDERED 'VALUES' )", NULL, NULL }, + "SUP olcBackend X-ORDERED 'SIBLINGS' )", NULL, NULL }, { "defaultSearchBase", "dn", 2, 2, 0, ARG_PRE_BI|ARG_PRE_DB|ARG_DN|ARG_MAGIC, &config_search_base, "( OLcfgAt:14 NAME 'olcDefaultSearchBase' " "SYNTAX OMsDN SINGLE-VALUE )", NULL, NULL }, @@ -361,7 +363,7 @@ ConfigTable config_back_cf_table[] = { "SYNTAX OMsDirectoryString X-ORDERED 'VALUES' )", NULL, NULL }, { "overlay", "overlay", 2, 2, 0, ARG_MAGIC, &config_overlay, "( OLcfgAt:34 NAME 'olcOverlay' " - "SUP olcDatabase X-ORDERED 'VALUES' )", NULL, NULL }, + "SUP olcDatabase X-ORDERED 'SIBLINGS' )", NULL, NULL }, { "password-crypt-salt-format", "salt", 2, 2, 0, ARG_STRING|ARG_MAGIC|CFG_SALT, &config_generic, "( OLcfgAt:35 NAME 'olcPasswordCryptSaltFormat' " "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL }, @@ -430,7 +432,7 @@ ConfigTable config_back_cf_table[] = { "SYNTAX OMsDirectoryString )", NULL, NULL }, { "rootpw", "password", 2, 2, 0, ARG_BERVAL|ARG_DB|ARG_MAGIC, &config_rootpw, "( OLcfgAt:52 NAME 'olcRootPW' " - "SYNTAX OMsOctetString SINGLE-VALUE )", NULL, NULL }, + "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL }, { "sasl-authz-policy", NULL, 2, 2, 0, ARG_MAGIC|CFG_AZPOLICY, &config_generic, NULL, NULL, NULL }, { "sasl-host", "host", 2, 2, 0, @@ -540,7 +542,7 @@ ConfigTable config_back_cf_table[] = { "( OLcfgAt:72 NAME 'olcTLSCipherSuite' " "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL }, { "TLSCRLCheck", NULL, 0, 0, 0, -#ifdef HAVE_TLS +#if defined(HAVE_TLS) && defined(HAVE_OPENSSL_CRL) CFG_TLS_CRLCHECK|ARG_STRING|ARG_MAGIC, &config_tls_config, #else ARG_IGNORED, NULL, @@ -579,13 +581,12 @@ static ConfigOCs cf_ocs[] = { { "( OLcfgOc:1 " "NAME 'olcConfig' " "DESC 'OpenLDAP configuration object' " - "ABSTRACT SUP top " - "MAY cn )", Cft_Abstract, NULL }, + "ABSTRACT SUP top )", Cft_Abstract, NULL }, { "( OLcfgOc:2 " "NAME 'olcGlobal' " "DESC 'OpenLDAP Global configuration options' " "SUP olcConfig STRUCTURAL " - "MAY ( olcConfigFile $ olcConfigDir $ olcAllows $ olcArgsFile $ " + "MAY ( cn $ olcConfigFile $ olcConfigDir $ olcAllows $ olcArgsFile $ " "olcAttributeOptions $ olcAttributeTypes $ olcAuthIDRewrite $ " "olcAuthzPolicy $ olcAuthzRegexp $ olcConcurrency $ " "olcConnMaxPending $ olcConnMaxPendingAuth $ olcDefaultSearchBase $ " @@ -610,41 +611,44 @@ static ConfigOCs cf_ocs[] = { "NAME 'olcSchemaConfig' " "DESC 'OpenLDAP schema object' " "SUP olcConfig STRUCTURAL " - "MAY ( olcObjectIdentifier $ olcAttributeTypes $ olcObjectClasses $ " - "olcDitContentRules ) )", Cft_Schema, &cfOc_schema }, + "MAY ( cn $ olcObjectIdentifier $ olcAttributeTypes $ " + "olcObjectClasses $ olcDitContentRules ) )", + Cft_Schema, &cfOc_schema }, { "( OLcfgOc:4 " "NAME 'olcBackendConfig' " "DESC 'OpenLDAP Backend-specific options' " "SUP olcConfig STRUCTURAL " - "MAY ( olcBackend ) )", Cft_Backend, &cfOc_backend }, + "MUST olcBackend )", Cft_Backend, &cfOc_backend }, { "( OLcfgOc:5 " "NAME 'olcDatabaseConfig' " "DESC 'OpenLDAP Database-specific options' " "SUP olcConfig STRUCTURAL " - "MAY ( olcDatabase $ olcAccess $ olcLastMod $ olcLimits $ " + "MUST olcDatabase " + "MAY ( olcSuffix $ olcAccess $ olcLastMod $ olcLimits $ " "olcMaxDerefDepth $ olcPlugin $ olcReadOnly $ olcReplica $ " "olcReplogFile $ olcRequires $ olcRestrict $ olcRootDN $ olcRootPW $ " - "olcSchemaDN $ olcSecurity $ olcSizeLimit $ olcSuffix $ olcSyncrepl $ " + "olcSchemaDN $ olcSecurity $ olcSizeLimit $ olcSyncrepl $ " "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 }, + "MUST olcOverlay )", Cft_Overlay, &cfOc_overlay }, { "( OLcfgOc:7 " "NAME 'olcIncludeFile' " "DESC 'OpenLDAP configuration include file' " "SUP olcConfig STRUCTURAL " - "MAY ( olcInclude $ olcConfigFile $ olcRootDSE ) )", + "MUST olcInclude " + "MAY ( cn $ olcRootDSE ) )", Cft_Include, &cfOc_include }, #ifdef SLAPD_MODULES { "( OLcfgOc:8 " "NAME 'olcModuleList' " "DESC 'OpenLDAP dynamic module info' " "SUP olcConfig STRUCTURAL " - "MUST olcModuleLoad )", - Cft_Module, &cfOc_module }, + "MUST olcModuleLoad " + "MAY cn )", Cft_Module, &cfOc_module }, #endif { NULL, 0, NULL } }; @@ -676,7 +680,7 @@ config_generic(ConfigArgs *c) { int i; for ( i=0; c->be->be_limits[i]; i++ ) { - bv.bv_len = sprintf( buf, "{%d}", i ); + bv.bv_len = sprintf( buf, IFMT, i ); bv.bv_val = buf+bv.bv_len; limits_unparse( c->be->be_limits[i], &bv ); bv.bv_len += bv.bv_val - buf; @@ -764,7 +768,7 @@ config_generic(ConfigArgs *c) { char *src, *dst, ibuf[11]; struct berval bv, abv; for (i=0, a=c->be->be_acl; a; i++,a=a->acl_next) { - abv.bv_len = sprintf( ibuf, "{%x}", i ); + abv.bv_len = sprintf( ibuf, IFMT, i ); acl_unparse( a, &bv ); abv.bv_val = ch_malloc( abv.bv_len + bv.bv_len + 1 ); AC_MEMCPY( abv.bv_val, ibuf, abv.bv_len ); @@ -820,7 +824,7 @@ config_generic(ConfigArgs *c) { for (i=0; !BER_BVISNULL(&mp->mp_loads[i]); i++) { struct berval bv; bv.bv_val = c->log; - bv.bv_len = sprintf( bv.bv_val, "{%d}%s", i, + bv.bv_len = sprintf( bv.bv_val, IFMT "%s", i, mp->mp_loads[i].bv_val ); value_add_one( &c->rvalue_vals, &bv ); } @@ -836,7 +840,7 @@ config_generic(ConfigArgs *c) { if ( BER_BVISNULL( &mp->mp_path ) && !mp->mp_loads ) continue; bv.bv_val = c->log; - bv.bv_len = sprintf( bv.bv_val, "{%d}%s", i, + bv.bv_len = sprintf( bv.bv_val, IFMT "%s", i, mp->mp_path.bv_val ); value_add_one( &c->rvalue_vals, &bv ); } @@ -859,7 +863,7 @@ config_generic(ConfigArgs *c) { idx.bv_val = ibuf; for ( i=0; !BER_BVISNULL( &authz_rewrites[i] ); i++ ) { - idx.bv_len = sprintf( idx.bv_val, "{%d}", i ); + idx.bv_len = sprintf( idx.bv_val, IFMT, i ); bv.bv_len = idx.bv_len + authz_rewrites[i].bv_len; bv.bv_val = ch_malloc( bv.bv_len + 1 ); strcpy( bv.bv_val, idx.bv_val ); @@ -877,6 +881,19 @@ config_generic(ConfigArgs *c) { } p = strchr(c->line,'(' /*')'*/); + if ( c->op == LDAP_MOD_DELETE ) { + int rc = 0; + switch(c->type) { + case CFG_BACKEND: + case CFG_DATABASE: + rc = 1; + break; + case CFG_CONCUR: + ldap_pvt_thread_set_concurrency(c); + break; + + } + } switch(c->type) { case CFG_BACKEND: if(!(c->bi = backend_info(c->argv[1]))) { @@ -891,7 +908,7 @@ config_generic(ConfigArgs *c) { /* NOTE: config is always the first backend! */ if ( !strcasecmp( c->argv[1], "config" )) { - c->be = backendDB; + c->be = LDAP_STAILQ_FIRST(&backendDB); } else if ( !strcasecmp( c->argv[1], "frontend" )) { c->be = frontendDB; } else if(!(c->be = backend_db_init(c->argv[1]))) { @@ -1089,7 +1106,10 @@ config_generic(ConfigArgs *c) { /* Record this load on the current path */ { struct berval bv; - ber_str2bv(c->line, 0, 1, &bv); + char *ptr = c->line + STRLENOF("moduleload"); + while (!isspace(*ptr)) ptr++; + while (isspace(*ptr)) ptr++; + ber_str2bv(ptr, 0, 1, &bv); ber_bvarray_add( &modcur->mp_loads, &bv ); } break; @@ -1370,7 +1390,8 @@ config_suffix(ConfigArgs *c) { struct berval pdn, ndn; int rc; - if (c->be == frontendDB) return 1; + if (c->be == frontendDB || SLAP_MONITOR(c->be) || + SLAP_CONFIG(c->be)) return 1; if (c->op == SLAP_CONFIG_EMIT) { if (!BER_BVISNULL( &c->be->be_suffix[0] )) { @@ -1763,7 +1784,7 @@ replica_unparse( struct slap_replica_info *ri, int i, struct berval *bv ) struct berval bc = {0}; char numbuf[32]; - len = sprintf(numbuf, "{%d}", i ); + len = sprintf(numbuf, IFMT, i ); len += strlen( ri->ri_uri ) + STRLENOF("uri="); if ( ri->ri_nsuffix ) { @@ -1986,6 +2007,11 @@ config_include(ConfigArgs *c) { ConfigFile *cfsave = cfn; ConfigFile *cf2 = NULL; if (c->op == SLAP_CONFIG_EMIT) { + if (c->private) { + ConfigFile *cf = c->private; + value_add_one( &c->rvalue_vals, &cf->c_file ); + return 0; + } return 1; } cf = ch_calloc( 1, sizeof(ConfigFile)); @@ -2014,14 +2040,14 @@ static int config_tls_option(ConfigArgs *c) { int flag; switch(c->type) { - case CFG_TLS_RAND: flag = LDAP_OPT_X_TLS_RANDOM_FILE; break; + case CFG_TLS_RAND: flag = LDAP_OPT_X_TLS_RANDOM_FILE; break; case CFG_TLS_CIPHER: flag = LDAP_OPT_X_TLS_CIPHER_SUITE; break; case CFG_TLS_CERT_FILE: flag = LDAP_OPT_X_TLS_CERTFILE; break; case CFG_TLS_CERT_KEY: flag = LDAP_OPT_X_TLS_KEYFILE; break; case CFG_TLS_CA_PATH: flag = LDAP_OPT_X_TLS_CACERTDIR; break; case CFG_TLS_CA_FILE: flag = LDAP_OPT_X_TLS_CACERTFILE; break; default: Debug(LDAP_DEBUG_ANY, "%s: " - "unknown tls_option <%x>\n", + "unknown tls_option <0x%x>\n", c->log, c->type, 0); } if (c->op == SLAP_CONFIG_EMIT) { @@ -2049,15 +2075,12 @@ config_tls_config(ConfigArgs *c) { { BER_BVNULL, 0 } }, *keys; switch(c->type) { -#ifdef HAVE_OPENSSL_CRL - case CFG_TLS_CRLCHECK: flag = LDAP_OPT_X_TLS_CRLCHECK; keys = crlkeys; - break; -#endif - case CFG_TLS_VERIFY: flag = LDAP_OPT_X_TLS_REQUIRE_CERT; keys = vfykeys; - break; - default: Debug(LDAP_DEBUG_ANY, "%s: " - "unknown tls_option <%x>\n", - c->log, c->type, 0); + case CFG_TLS_CRLCHECK: flag = LDAP_OPT_X_TLS_CRLCHECK; keys = crlkeys; break; + case CFG_TLS_VERIFY: flag = LDAP_OPT_X_TLS_REQUIRE_CERT; keys = vfykeys; break; + default: + Debug(LDAP_DEBUG_ANY, "%s: " + "unknown tls_option <0x%x>\n", + c->log, c->type, 0); } if (c->op == SLAP_CONFIG_EMIT) { ldap_pvt_tls_get_option( NULL, flag, &c->value_int ); @@ -2615,10 +2638,10 @@ config_find_base( CfEntryInfo *root, struct berval *dn, CfEntryInfo **last ) 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); + if ( *c == ',' ) + cdn.bv_val++; + cdn.bv_len = dn->bv_len - (cdn.bv_val - dn->bv_val); root = root->ce_kids; @@ -2641,7 +2664,7 @@ config_ldif_resp( Operation *op, SlapReply *rs ) CfBackInfo *cfb = op->o_callback->sc_private; cfb->cb_got_ldif = 1; - rs->sr_err = config_add_internal( cfb, rs->sr_entry, NULL ); + rs->sr_err = config_add_internal( cfb, rs->sr_entry, NULL, NULL ); } return rs->sr_err; } @@ -2770,13 +2793,14 @@ read_config(const char *fname, const char *dir) { if ( !be ) return 1; + cfb = be->be_private; + /* Setup the underlying back-ldif backend */ if ( config_setup_ldif( be, dir )) return 1; -#if 0 /* not yet +#ifdef SLAP_USE_CONFDIR /* If we read the config from back-ldif, nothing to do here */ - cfb = be->be_private; if ( cfb->cb_got_ldif ) return 0; #endif @@ -2837,9 +2861,9 @@ config_find_table( CfOcInfo *co, AttributeDescription *ad ) return NULL; } -/* Sort the values in an X-ORDERED attribute. +/* Sort the values in an X-ORDERED VALUES 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 the values have indexes, sort them. * If some are indexed and some are not, return Error. * * FIXME: This function probably belongs in the frontend somewhere, @@ -2873,6 +2897,7 @@ sort_vals( Attribute *a ) struct berval tmp, ntmp; char *ptr; +#if 0 /* 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)); @@ -2891,6 +2916,7 @@ sort_vals( Attribute *a ) strcpy(a->a_nvals[i].bv_val, ptr); } } +#endif indexes = ch_malloc( vals * sizeof(int) ); for ( i=0; ia_desc->ad_type->sat_flags & SLAP_AT_ORDERED ) { + sort = 1; 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; + if ( sort ) ca->line = strchr( ca->line, '}' ) + 1; rc = config_parse_vals( ct, ca, i ); if ( rc ) break; @@ -2935,9 +2963,132 @@ check_attr( ConfigTable *ct, ConfigArgs *ca, Attribute *a ) return rc; } +static int +check_name_index( CfEntryInfo *parent, ConfigType ce_type, Entry *e, + SlapReply *rs, int *renum ) +{ + CfEntryInfo *ce; + int index = -1, gotindex = 0, nsibs; + int renumber = 0, tailindex = 0; + char *ptr1, *ptr2; + struct berval rdn; + + if ( renum ) *renum = 0; + + /* These entries don't get indexed/renumbered */ + if ( ce_type == Cft_Global ) return 0; + if ( ce_type == Cft_Schema && parent->ce_type == Cft_Global ) return 0; + + if ( ce_type == Cft_Include || ce_type == Cft_Module ) + tailindex = 1; + + /* See if the rdn has an index already */ + dnRdn( &e->e_name, &rdn ); + ptr1 = strchr( e->e_name.bv_val, '{' ); + if ( ptr1 && ptr1 - e->e_name.bv_val < rdn.bv_len ) { + ptr2 = strchr( ptr1, '}' ); + if (!ptr2 || ptr2 - e->e_name.bv_val > rdn.bv_len) + return LDAP_NAMING_VIOLATION; + if ( ptr2-ptr1 == 1) + return LDAP_NAMING_VIOLATION; + gotindex = 1; + index = atoi(ptr1+1); + if ( index < 0 ) + return LDAP_NAMING_VIOLATION; + } + + /* count related kids */ + for (nsibs=0, ce=parent->ce_kids; ce; ce=ce->ce_sibs) { + if ( ce->ce_type == ce_type ) nsibs++; + } + + if ( index != nsibs ) { + if ( gotindex ) { + if ( index < nsibs ) { + if ( tailindex ) return LDAP_NAMING_VIOLATION; + /* Siblings need to be renumbered */ + renumber = 1; + } + } + if ( !renumber ) { + struct berval ival, newrdn, nnewrdn; + struct berval rtype, rval; + Attribute *a; + AttributeDescription *ad = NULL; + char ibuf[32]; + const char *text; + + rval.bv_val = strchr(rdn.bv_val, '=' ) + 1; + rval.bv_len = rdn.bv_len - (rval.bv_val - rdn.bv_val); + rtype.bv_val = rdn.bv_val; + rtype.bv_len = rval.bv_val - rtype.bv_val - 1; + + /* Find attr */ + slap_bv2ad( &rtype, &ad, &text ); + a = attr_find( e->e_attrs, ad ); + if (!a ) return LDAP_NAMING_VIOLATION; + + ival.bv_val = ibuf; + ival.bv_len = sprintf( ibuf, IFMT, nsibs ); + + newrdn.bv_len = rdn.bv_len + ival.bv_len; + newrdn.bv_val = ch_malloc( newrdn.bv_len+1 ); + + if ( tailindex ) { + ptr1 = lutil_strncopy( newrdn.bv_val, rdn.bv_val, rdn.bv_len ); + ptr1 = lutil_strcopy( ptr1, ival.bv_val ); + } else { + int xlen; + if ( !gotindex ) { + ptr2 = rval.bv_val; + xlen = rval.bv_len; + } else { + xlen = rdn.bv_len - (ptr2 - rdn.bv_val); + } + ptr1 = lutil_strncopy( newrdn.bv_val, rtype.bv_val, + rtype.bv_len ); + *ptr1++ = '='; + ptr1 = lutil_strcopy( ptr1, ival.bv_val ); + ptr1 = lutil_strncopy( ptr1, ptr2, xlen ); + *ptr1 = '\0'; + } + + /* Do the equivalent of ModRDN */ + /* Replace DN / NDN */ + newrdn.bv_len = ptr1 - newrdn.bv_val; + rdnNormalize( 0, NULL, NULL, &newrdn, &nnewrdn, NULL ); + free( e->e_name.bv_val ); + build_new_dn( &e->e_name, &parent->ce_entry->e_name, + &newrdn, NULL ); + free( e->e_nname.bv_val ); + build_new_dn( &e->e_nname, &parent->ce_entry->e_nname, + &nnewrdn, NULL ); + + /* Replace attr */ + free( a->a_vals[0].bv_val ); + ptr1 = strchr( newrdn.bv_val, '=' ) + 1; + a->a_vals[0].bv_len = newrdn.bv_len - (ptr1 - newrdn.bv_val); + a->a_vals[0].bv_val = ch_malloc( a->a_vals[0].bv_len + 1 ); + strcpy( a->a_vals[0].bv_val, ptr1 ); + + if ( a->a_nvals != a->a_vals ) { + free( a->a_nvals[0].bv_val ); + ptr1 = strchr( nnewrdn.bv_val, '=' ) + 1; + a->a_nvals[0].bv_len = nnewrdn.bv_len - (ptr1 - nnewrdn.bv_val); + a->a_nvals[0].bv_val = ch_malloc( a->a_nvals[0].bv_len + 1 ); + strcpy( a->a_nvals[0].bv_val, ptr1 ); + } + free( nnewrdn.bv_val ); + free( newrdn.bv_val ); + } + } + if ( renum ) *renum = renumber; + return 0; +} + /* Parse an LDAP entry into config directives */ static int -config_add_internal( CfBackInfo *cfb, Entry *e, SlapReply *rs ) +config_add_internal( CfBackInfo *cfb, Entry *e, SlapReply *rs, int *renum ) { CfEntryInfo *ce, *last; CfOcInfo co, *coptr, **colst = NULL; @@ -3016,6 +3167,7 @@ config_add_internal( CfBackInfo *cfb, Entry *e, SlapReply *rs ) rc = LDAP_CONSTRAINT_VIOLATION; goto leave; } + break; #ifdef SLAPD_MODULES case Cft_Module: if ( !last || last->ce_type != Cft_Global ) { @@ -3036,7 +3188,7 @@ config_add_internal( CfBackInfo *cfb, Entry *e, SlapReply *rs ) goto ok; /* FALLTHRU */ case Cft_Global: - ca.be = cfb->cb_be; + ca.be = LDAP_STAILQ_FIRST(&backendDB); break; case Cft_Backend: @@ -3058,11 +3210,13 @@ config_add_internal( CfBackInfo *cfb, Entry *e, SlapReply *rs ) case Cft_Overlay: ca.be = last->ce_be; type_ad = cfAd_overlay; + break; case Cft_Include: if ( !rs ) /* ignored */ break; type_ad = cfAd_include; + break; #ifdef SLAPD_MODULES case Cft_Module: { ModPaths *mp; @@ -3085,6 +3239,24 @@ config_add_internal( CfBackInfo *cfb, Entry *e, SlapReply *rs ) break; #endif } + + /* If doing an LDAPadd, check for indexed names and any necessary + * renaming/renumbering. Entries that don't need indexed names are + * ignored. Entries that need an indexed name and arrive without one + * are assigned to the end. Entries that arrive with an index may + * cause the following entries to be renumbered/bumped down. + * + * Note that "pseudo-indexed" entries (cn=Include{xx}, cn=Module{xx}) + * don't allow Adding an entry with an index that's already in use. + * This is flagged as an error (LDAP_ALREADY_EXISTS) up above. + * + * These entries can have auto-assigned indexes (appended to the end) + * but only the other types support auto-renumbering of siblings. + */ + rc = check_name_index( last, colst[0]->co_type, e, rs, renum ); + if ( rc ) + goto leave; + init_config_argv( &ca ); if ( type_ad ) { type_attr = attr_find( e->e_attrs, type_ad ); @@ -3117,9 +3289,14 @@ config_add_internal( CfBackInfo *cfb, Entry *e, SlapReply *rs ) /* Basic syntax checks are OK. Do the actual settings. */ if ( type_ct ) { - ca.line = type_attr->a_nvals[0].bv_val; + ca.line = type_attr->a_vals[0].bv_val; + if ( type_ad->ad_type->sat_flags & SLAP_AT_ORDERED ) + ca.line = strchr( ca.line, '}' ) + 1; rc = config_parse_add( type_ct, &ca, 0 ); - if ( rc ) goto leave; + if ( rc ) { + rc = LDAP_OTHER; + goto leave; + } } for ( a=e->e_attrs; a; a=a->a_next ) { if ( a == type_attr || a == oc_at ) continue; @@ -3129,10 +3306,15 @@ config_add_internal( CfBackInfo *cfb, Entry *e, SlapReply *rs ) 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; + for (i=0; a->a_vals[i].bv_val; i++) { + ca.line = a->a_vals[i].bv_val; + if ( a->a_desc->ad_type->sat_flags & SLAP_AT_ORDERED ) + ca.line = strchr( ca.line, '}' ) + 1; rc = config_parse_add( ct, &ca, i ); - if ( rc ) goto leave; + if ( rc ) { + rc = LDAP_OTHER; + goto leave; + } } } ok: @@ -3147,6 +3329,7 @@ ok: CfEntryInfo *c2; for (c2=last->ce_kids; c2 && c2->ce_sibs; c2 = c2->ce_sibs); + c2->ce_sibs = ce; } else { last->ce_kids = ce; @@ -3166,6 +3349,7 @@ config_back_add( Operation *op, SlapReply *rs ) { CfBackInfo *cfb; CfEntryInfo *ce, *last; + int renumber; if ( !be_isroot( op ) ) { rs->sr_err = LDAP_INSUFFICIENT_ACCESS; @@ -3178,9 +3362,24 @@ config_back_add( Operation *op, SlapReply *rs ) /* Strategy: * 1) check for existence of entry - * 2) perform internal add - * 3) store entry in underlying database + * 2) check for sibling renumbering + * 3) perform internal add + * 4) store entry in underlying database + * 5) perform any necessary renumbering */ + rs->sr_err = config_add_internal( cfb, op->ora_e, rs, &renumber ); + if ( rs->sr_err == LDAP_SUCCESS ) { + BackendDB *be = op->o_bd; + slap_callback sc = { NULL, slap_null_cb, NULL, NULL }; + op->o_bd = &cfb->cb_db; + sc.sc_next = op->o_callback; + op->o_callback = ≻ + op->o_bd->be_add( op, rs ); + op->o_bd = be; + op->o_callback = sc.sc_next; + } + if ( renumber ) { + } ldap_pvt_thread_pool_resume( &connection_pool ); @@ -3189,6 +3388,14 @@ out: return rs->sr_err; } +/* Modify rules: + * for single-valued attributes, should just use REPLACE. + * any received DELETE/ADD on a single-valued attr will + * be checked (if a DEL value is provided) and then + * rewritten as a REPLACE. + * any DELETE received without a corresponding ADD will be + * rejected with LDAP_CONSTRAINT_VIOLATION. + */ static int config_back_modify( Operation *op, SlapReply *rs ) { @@ -3223,6 +3430,42 @@ out: return rs->sr_err; } +static int +config_back_modrdn( 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; + + 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; + } + + /* We don't allow moving objects to new parents. + * Generally we only allow reordering a set of ordered entries. + */ + if ( op->orr_newSup ) { + rs->sr_err = LDAP_UNWILLING_TO_PERFORM; + goto out; + } + ldap_pvt_thread_pool_pause( &connection_pool ); + + ldap_pvt_thread_pool_resume( &connection_pool ); +out: + send_ldap_result( op, rs ); + return rs->sr_err; +} + static int config_back_search( Operation *op, SlapReply *rs ) { @@ -3400,7 +3643,7 @@ config_build_schema_inc( ConfigArgs *c, CfEntryInfo *ceparent, ptr = strchr( bv.bv_val, '.' ); if ( ptr ) bv.bv_len = ptr - bv.bv_val; - c->value_dn.bv_len = sprintf(c->value_dn.bv_val, "cn={%02d}", c->depth); + c->value_dn.bv_len = sprintf(c->value_dn.bv_val, "cn=" IFMT, c->depth); strncpy( c->value_dn.bv_val + c->value_dn.bv_len, bv.bv_val, bv.bv_len ); c->value_dn.bv_len += bv.bv_len; @@ -3444,7 +3687,7 @@ config_build_includes( ConfigArgs *c, CfEntryInfo *ceparent, for (i=0; cf; cf=cf->c_sibs, i++) { c->value_dn.bv_val = c->log; - c->value_dn.bv_len = sprintf(c->value_dn.bv_val, "cn=include{%02d}", i); + c->value_dn.bv_len = sprintf(c->value_dn.bv_val, "cn=include" IFMT, i); e = config_alloc_entry( ceparent, &c->value_dn ); c->private = cf; config_build_entry( c, e, cfOc_include, &c->value_dn, @@ -3488,7 +3731,7 @@ config_build_modules( ConfigArgs *c, CfEntryInfo *ceparent, if ( BER_BVISNULL( &mp->mp_path ) && !mp->mp_loads ) continue; c->value_dn.bv_val = c->log; - c->value_dn.bv_len = sprintf(c->value_dn.bv_val, "cn=module{%02d}", i); + c->value_dn.bv_len = sprintf(c->value_dn.bv_val, "cn=module" IFMT, i); e = config_alloc_entry( ceparent, &c->value_dn ); ce = e->e_private; ce->ce_type = Cft_Include; @@ -3561,7 +3804,7 @@ config_back_db_open( BackendDB *be ) /* Create schema nodes... cn=schema will contain the hardcoded core * schema, read-only. Child objects will contain runtime loaded schema - * files. FIXME + * files. */ rdn = schema_rdn; e = config_alloc_entry( ceparent, &rdn ); @@ -3590,7 +3833,7 @@ config_back_db_open( BackendDB *be ) #ifdef SLAPD_MODULES /* Create Module nodes... */ if ( modpaths.mp_loads ) { - ceprev = config_build_includes( &c, ceparent, op, &rs ); + ceprev = config_build_modules( &c, ceparent, op, &rs ); } #endif @@ -3599,8 +3842,7 @@ config_back_db_open( BackendDB *be ) */ c.line = 0; - bi = backendInfo; - for (i=0; ibi_cf_table) continue; if (!bi->bi_private) continue; @@ -3623,12 +3865,14 @@ config_back_db_open( BackendDB *be ) } /* Create database nodes... */ - for (i=0; ibd_info->bi_private; @@ -3637,7 +3881,7 @@ config_back_db_open( BackendDB *be ) bi = bptr->bd_info; } rdn.bv_val = c.log; - rdn.bv_len = sprintf(rdn.bv_val, "%s={%0x}%s", cfAd_database->ad_cname.bv_val, + rdn.bv_len = sprintf(rdn.bv_val, "%s=" IFMT "%s", cfAd_database->ad_cname.bv_val, i, bi->bi_type); e = config_alloc_entry( ceparent, &rdn ); ce = e->e_private; @@ -3664,7 +3908,7 @@ config_back_db_open( BackendDB *be ) for (j=0,on=oi->oi_list; on; j++,on=on->on_next) { rdn.bv_val = c.log; - rdn.bv_len = sprintf(rdn.bv_val, "%s={%0x}%s", + rdn.bv_len = sprintf(rdn.bv_val, "%s=" IFMT "%s", cfAd_overlay->ad_cname.bv_val, j, on->on_bi.bi_type ); oe = config_alloc_entry( opar, &rdn ); ce = oe->e_private; @@ -3704,7 +3948,6 @@ 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 ); @@ -3728,7 +3971,7 @@ static struct { { "database", &cfAd_database }, { "include", &cfAd_include }, { "overlay", &cfAd_overlay }, - { NULL, NULL, NULL } + { NULL, NULL } }; /* Notes: @@ -3760,6 +4003,12 @@ config_back_initialize( BackendInfo *bi ) ConfigTable *ct = config_back_cf_table; char *argv[4]; int i; + static char *controls[] = { + LDAP_CONTROL_MANAGEDSAIT, + NULL + }; + + bi->bi_controls = controls; bi->bi_open = 0; bi->bi_close = 0; @@ -3777,8 +4026,8 @@ config_back_initialize( BackendInfo *bi ) bi->bi_op_search = config_back_search; bi->bi_op_compare = 0; bi->bi_op_modify = config_back_modify; - bi->bi_op_modrdn = 0; - bi->bi_op_add = 0; + bi->bi_op_modrdn = config_back_modrdn; + bi->bi_op_add = config_back_add; bi->bi_op_delete = 0; bi->bi_op_abandon = 0;