/* $OpenLDAP$ */
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
*
- * Copyright 2005-2011 The OpenLDAP Foundation.
+ * Copyright 2005-2012 The OpenLDAP Foundation.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
#ifdef SLAP_AUTH_REWRITE
static BerVarray authz_rewrites;
#endif
+static AccessControl *defacl_parsed = NULL;
static struct berval cfdir;
* OLcfg{Bk|Db}{Oc|At}:3 -> back-ldap
* OLcfg{Bk|Db}{Oc|At}:4 -> back-monitor
* OLcfg{Bk|Db}{Oc|At}:5 -> back-relay
- * OLcfg{Bk|Db}{Oc|At}:6 -> back-sql
+ * OLcfg{Bk|Db}{Oc|At}:6 -> back-sql(/back-ndb)
* OLcfg{Bk|Db}{Oc|At}:7 -> back-sock
* OLcfg{Bk|Db}{Oc|At}:8 -> back-null
+ * OLcfg{Bk|Db}{Oc|At}:9 -> back-passwd
+ * OLcfg{Bk|Db}{Oc|At}:10 -> back-shell
+ * OLcfg{Bk|Db}{Oc|At}:11 -> back-perl
+ * OLcfg{Bk|Db}{Oc|At}:12 -> back-mdb
*/
/*
"NAME 'olcSchemaConfig' "
"DESC 'OpenLDAP schema object' "
"SUP olcConfig STRUCTURAL "
- "MAY ( cn $ olcObjectIdentifier $ olcAttributeTypes $ "
- "olcObjectClasses $ olcDitContentRules $ olcLdapSyntaxes ) )",
+ "MAY ( cn $ olcObjectIdentifier $ olcLdapSyntaxes $ "
+ "olcAttributeTypes $ olcObjectClasses $ olcDitContentRules ) )",
Cft_Schema, NULL, cfAddSchema },
{ "( OLcfgGlOc:3 "
"NAME 'olcBackendConfig' "
break;
case CFG_MIRRORMODE:
if ( SLAP_SHADOW(c->be))
- c->value_int = (SLAP_SINGLE_SHADOW(c->be) == 0);
+ c->value_int = (SLAP_MULTIMASTER(c->be) != 0);
else
rc = 1;
break;
case CFG_AZPOLICY:
case CFG_DEPTH:
case CFG_LASTMOD:
- case CFG_MIRRORMODE:
case CFG_MONITORING:
case CFG_SASLSECP:
case CFG_SSTR_IF_MAX:
snprintf(c->log, sizeof( c->log ), "change requires slapd restart");
break;
+ case CFG_MIRRORMODE:
+ SLAP_DBFLAGS(c->be) &= ~SLAP_DBFLAG_MULTI_SHADOW;
+ if(SLAP_SHADOW(c->be))
+ SLAP_DBFLAGS(c->be) |= SLAP_DBFLAG_SINGLE_SHADOW;
+ break;
+
case CFG_SALT:
ch_free( passwd_salt );
passwd_salt = NULL;
*prev = a->acl_next;
acl_free( a );
}
+ if ( SLAP_CONFIG( c->be ) && !c->be->be_acl ) {
+ Debug( LDAP_DEBUG_CONFIG, "config_generic (CFG_ACL): "
+ "Last explicit ACL for back-config removed. "
+ "Using hardcoded default\n", 0, 0, 0 );
+ c->be->be_acl = defacl_parsed;
+ }
break;
case CFG_OC: {
/* else prev is NULL, append to end of global list */
}
if(parse_oc(c, &oc, prev)) return(1);
- if (!cfn->c_oc_head) cfn->c_oc_head = oc;
+ if (!cfn->c_oc_head || !c->valx) cfn->c_oc_head = oc;
if (cfn->c_oc_tail == prev) cfn->c_oc_tail = oc;
}
break;
/* else prev is NULL, append to end of global list */
}
if(parse_at(c, &at, prev)) return(1);
- if (!cfn->c_at_head) cfn->c_at_head = at;
+ if (!cfn->c_at_head || !c->valx) cfn->c_at_head = at;
if (cfn->c_at_tail == prev) cfn->c_at_tail = at;
}
break;
/* else prev is NULL, append to end of global list */
}
if ( parse_syn( c, &syn, prev ) ) return(1);
- if ( !cfn->c_syn_head ) cfn->c_syn_head = syn;
+ if ( !cfn->c_syn_head || !c->valx ) cfn->c_syn_head = syn;
if ( cfn->c_syn_tail == prev ) cfn->c_syn_tail = syn;
}
break;
break;
case CFG_ACL:
+ if ( SLAP_CONFIG( c->be ) && c->be->be_acl == defacl_parsed) {
+ c->be->be_acl = NULL;
+ }
/* Don't append to the global ACL if we're on a specific DB */
i = c->valx;
if ( c->valx == -1 ) {
i++;
}
if ( parse_acl(c->be, c->fname, c->lineno, c->argc, c->argv, i ) ) {
+ if ( SLAP_CONFIG( c->be ) && !c->be->be_acl) {
+ c->be->be_acl = defacl_parsed;
+ }
return 1;
}
break;
c->log, c->cr_msg, 0 );
return(1);
}
- if(c->value_int)
+ if(c->value_int) {
SLAP_DBFLAGS(c->be) &= ~SLAP_DBFLAG_SINGLE_SHADOW;
- else
+ SLAP_DBFLAGS(c->be) |= SLAP_DBFLAG_MULTI_SHADOW;
+ } else {
SLAP_DBFLAGS(c->be) |= SLAP_DBFLAG_SINGLE_SHADOW;
+ SLAP_DBFLAGS(c->be) &= ~SLAP_DBFLAG_MULTI_SHADOW;
+ }
break;
case CFG_MONITORING:
if ( !c->line ) {
c->be->be_restrictops = 0;
} else {
- restrictops = verb_to_mask( c->line, restrictable_ops );
- c->be->be_restrictops ^= restrictops;
+ i = verb_to_mask( c->line, restrictable_ops );
+ c->be->be_restrictops &= ~restrictable_ops[i].mask;
}
return 0;
}
if ( !c->line ) {
global_allows = 0;
} else {
- allows = verb_to_mask( c->line, allowable_ops );
- global_allows ^= allows;
+ i = verb_to_mask( c->line, allowable_ops );
+ global_allows &= ~allowable_ops[i].mask;
}
return 0;
}
if ( !c->line ) {
global_disallows = 0;
} else {
- disallows = verb_to_mask( c->line, disallowable_ops );
- global_disallows ^= disallows;
+ i = verb_to_mask( c->line, disallowable_ops );
+ global_disallows &= ~disallowable_ops[i].mask;
}
return 0;
}
if ( !c->line ) {
c->be->be_requires = 0;
} else {
- requires = verb_to_mask( c->line, requires_ops );
- c->be->be_requires ^= requires;
+ i = verb_to_mask( c->line, requires_ops );
+ c->be->be_requires &= ~requires_ops[i].mask;
}
return 0;
}
if ( !c->line ) {
config_syslog = 0;
} else {
- int level = verb_to_mask( c->line, loglevel_ops );
- config_syslog ^= level;
+ i = verb_to_mask( c->line, loglevel_ops );
+ config_syslog &= ~loglevel_ops[i].mask;
}
if ( slapMode & SLAP_SERVER_MODE ) {
ldap_syslog = config_syslog;
}
} else {
- SLAP_DBFLAGS(c->be) |= (SLAP_DBFLAG_SHADOW | SLAP_DBFLAG_SINGLE_SHADOW | flag);
+ SLAP_DBFLAGS(c->be) |= (SLAP_DBFLAG_SHADOW | flag);
+ if ( !SLAP_MULTIMASTER( c->be ))
+ SLAP_DBFLAGS(c->be) |= SLAP_DBFLAG_SINGLE_SHADOW;
}
return 0;
/* FALLTHRU: LDAP_MOD_REPLACE && vals */
case LDAP_MOD_ADD:
+ if ( !a )
+ break;
for (i=0; ml->sml_values[i].bv_val; i++) {
ca->line = ml->sml_values[i].bv_val;
ca->valx = -1;
rs->sr_matched = last->ce_entry->e_name.bv_val;
rs->sr_err = LDAP_NO_SUCH_OBJECT;
} else if ( ce->ce_kids ) {
- rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
+ rs->sr_err = LDAP_NOT_ALLOWED_ON_NONLEAF;
} else if ( op->o_abandon ) {
rs->sr_err = SLAPD_ABANDON;
- } else if ( ce->ce_type == Cft_Overlay ){
+ } else if ( ce->ce_type == Cft_Overlay ||
+ ce->ce_type == Cft_Database ||
+ ce->ce_type == Cft_Misc ){
char *iptr;
int count, ixold;
ldap_pvt_thread_pool_pause( &connection_pool );
-
- overlay_remove( ce->ce_be, (slap_overinst *)ce->ce_bi );
+
+ if ( ce->ce_type == Cft_Overlay ){
+ overlay_remove( ce->ce_be, (slap_overinst *)ce->ce_bi, op );
+ } else if ( ce->ce_type == Cft_Misc ) {
+ /*
+ * only Cft_Misc objects that have a co_lddel handler set in
+ * the ConfigOCs struct can be deleted. This code also
+ * assumes that the entry can be only have one objectclass
+ * with co_type == Cft_Misc
+ */
+ ConfigOCs co, *coptr;
+ Attribute *oc_at;
+ int i;
+
+ oc_at = attr_find( ce->ce_entry->e_attrs,
+ slap_schema.si_ad_objectClass );
+ if ( !oc_at ) {
+ rs->sr_err = LDAP_OTHER;
+ rs->sr_text = "objectclass not found";
+ ldap_pvt_thread_pool_resume( &connection_pool );
+ goto out;
+ }
+ for ( i=0; !BER_BVISNULL(&oc_at->a_nvals[i]); i++ ) {
+ co.co_name = &oc_at->a_nvals[i];
+ coptr = avl_find( CfOcTree, &co, CfOc_cmp );
+ if ( coptr == NULL || coptr->co_type != Cft_Misc ) {
+ continue;
+ }
+ if ( ! coptr->co_lddel || coptr->co_lddel( ce, op ) ){
+ rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
+ if ( ! coptr->co_lddel ) {
+ rs->sr_text = "No delete handler found";
+ } else {
+ rs->sr_err = LDAP_OTHER;
+ /* FIXME: We should return a helpful error message
+ * here */
+ }
+ ldap_pvt_thread_pool_resume( &connection_pool );
+ goto out;
+ }
+ break;
+ }
+ } else if (ce->ce_type == Cft_Database ) {
+ if ( ce->ce_be == frontendDB || ce->ce_be == op->o_bd ){
+ rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
+ rs->sr_text = "Cannot delete config or frontend database";
+ ldap_pvt_thread_pool_resume( &connection_pool );
+ goto out;
+ }
+ if ( ce->ce_be->bd_info->bi_db_close ) {
+ ce->ce_be->bd_info->bi_db_close( ce->ce_be, NULL );
+ }
+ backend_destroy_one( ce->ce_be, 1);
+ }
/* remove CfEntryInfo from the siblings list */
if ( ce->ce_parent->ce_kids == ce ) {
} else {
rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
}
+out:
#else
rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
#endif /* SLAP_CONFIG_DELETE */
slap_callback cb = { NULL, slap_null_cb, NULL, NULL };
SlapReply rs = {REP_RESULT};
void *thrctx = NULL;
+ AccessControl *save_access;
Debug( LDAP_DEBUG_TRACE, "config_back_db_open\n", 0, 0, 0);
/* If we have no explicitly configured ACLs, don't just use
* the global ACLs. Explicitly deny access to everything.
*/
- if ( !be->bd_self->be_acl ) {
- parse_acl(be->bd_self, "config_back_db_open", 0, 6, (char **)defacl, 0 );
+ save_access = be->bd_self->be_acl;
+ be->bd_self->be_acl = NULL;
+ parse_acl(be->bd_self, "config_back_db_open", 0, 6, (char **)defacl, 0 );
+ defacl_parsed = be->bd_self->be_acl;
+ if ( save_access ) {
+ be->bd_self->be_acl = save_access;
+ } else {
+ Debug( LDAP_DEBUG_CONFIG, "config_back_db_open: "
+ "No explicit ACL for back-config configured. "
+ "Using hardcoded default\n", 0, 0, 0 );
}
thrctx = ldap_pvt_thread_pool_context();
backend_shutdown( &cfb->cb_db );
}
+ if ( defacl_parsed && be->be_acl != defacl_parsed ) {
+ acl_free( defacl_parsed );
+ defacl_parsed = NULL;
+ }
+
return 0;
}
return 0;
}
-