| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056 |
- /** BEGIN COPYRIGHT BLOCK
- * This Program is free software; you can redistribute it and/or modify it under
- * the terms of the GNU General Public License as published by the Free Software
- * Foundation; version 2 of the License.
- *
- * This Program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
- * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this Program; if not, write to the Free Software Foundation, Inc., 59 Temple
- * Place, Suite 330, Boston, MA 02111-1307 USA.
- *
- * In addition, as a special exception, Red Hat, Inc. gives You the additional
- * right to link the code of this Program with code not covered under the GNU
- * General Public License ("Non-GPL Code") and to distribute linked combinations
- * including the two, subject to the limitations in this paragraph. Non-GPL Code
- * permitted under this exception must only link to the code of this Program
- * through those well defined interfaces identified in the file named EXCEPTION
- * found in the source code files (the "Approved Interfaces"). The files of
- * Non-GPL Code may instantiate templates or use macros or inline functions from
- * the Approved Interfaces without causing the resulting work to be covered by
- * the GNU General Public License. Only Red Hat, Inc. may make changes or
- * additions to the list of Approved Interfaces. You must obey the GNU General
- * Public License in all respects for all of the Program code and other code used
- * in conjunction with the Program except the Non-GPL Code covered by this
- * exception. If you modify this file, you may extend this exception to your
- * version of the file, but you are not obligated to do so. If you do not wish to
- * provide this exception without modification, you must delete this exception
- * statement from your version and license this file solely under the GPL without
- * exception.
- *
- *
- * Copyright (C) 2001 Sun Microsystems, Inc. Used by permission.
- * Copyright (C) 2005 Red Hat, Inc.
- * All rights reserved.
- * END COPYRIGHT BLOCK **/
- #ifdef HAVE_CONFIG_H
- # include <config.h>
- #endif
- /* This file handles configuration information that is specific
- * to ldbm instances.
- */
- #include "back-ldbm.h"
- #include "dblayer.h"
- /* Forward declarations for the callbacks */
- int ldbm_instance_search_config_entry_callback(Slapi_PBlock *pb, Slapi_Entry *e, Slapi_Entry *entryAfter, int *returncode, char *returntext, void *arg);
- int ldbm_instance_modify_config_entry_callback(Slapi_PBlock *pb, Slapi_Entry* entryBefore, Slapi_Entry* e, int *returncode, char *returntext, void *arg);
- static char *ldbm_instance_attrcrypt_filter = "(objectclass=nsAttributeEncryption)";
- /* dse entries add for a new ldbm instance */
- static char *ldbm_instance_skeleton_entries[] =
- {
- "dn:cn=monitor, cn=%s, cn=%s, cn=plugins, cn=config\n"
- "objectclass:top\n"
- "objectclass:extensibleObject\n"
- "cn:monitor\n",
- "dn:cn=index, cn=%s, cn=%s, cn=plugins, cn=config\n"
- "objectclass:top\n"
- "objectclass:extensibleObject\n"
- "cn:index\n",
-
- "dn:cn=encrypted attributes, cn=%s, cn=%s, cn=plugins, cn=config\n"
- "objectclass:top\n"
- "objectclass:extensibleObject\n"
- "cn:encrypted attributes\n",
-
- "dn:cn=encrypted attribute keys, cn=%s, cn=%s, cn=plugins, cn=config\n"
- "objectclass:top\n"
- "objectclass:extensibleObject\n"
- "cn:encrypted attribute keys\n",
- ""
- };
- /*------------------------------------------------------------------------
- * Get and set functions for ldbm instance variables
- *----------------------------------------------------------------------*/
- static void *
- ldbm_instance_config_cachesize_get(void *arg)
- {
- ldbm_instance *inst = (ldbm_instance *) arg;
-
- return (void *) cache_get_max_entries(&(inst->inst_cache));
- }
- static int
- ldbm_instance_config_cachesize_set(void *arg, void *value, char *errorbuf, int phase, int apply)
- {
- ldbm_instance *inst = (ldbm_instance *) arg;
- int retval = LDAP_SUCCESS;
- long val = (long) value;
- /* Do whatever we can to make sure the data is ok. */
- if (apply) {
- cache_set_max_entries(&(inst->inst_cache), val);
- }
- return retval;
- }
- static void *
- ldbm_instance_config_cachememsize_get(void *arg)
- {
- ldbm_instance *inst = (ldbm_instance *) arg;
-
- return (void *) cache_get_max_size(&(inst->inst_cache));
- }
- static int
- ldbm_instance_config_cachememsize_set(void *arg, void *value, char *errorbuf, int phase, int apply)
- {
- ldbm_instance *inst = (ldbm_instance *) arg;
- int retval = LDAP_SUCCESS;
- size_t val = (size_t) value;
- /* Do whatever we can to make sure the data is ok. */
- if (apply) {
- cache_set_max_size(&(inst->inst_cache), val);
- }
- return retval;
- }
- static void *
- ldbm_instance_config_readonly_get(void *arg)
- {
- ldbm_instance *inst = (ldbm_instance *)arg;
- return (void *)((uintptr_t)inst->inst_be->be_readonly);
- }
- static void *
- ldbm_instance_config_instance_dir_get(void *arg)
- {
- ldbm_instance *inst = (ldbm_instance *)arg;
- if (inst->inst_dir_name == NULL)
- return slapi_ch_strdup("");
- else if (inst->inst_parent_dir_name)
- {
- int len = strlen(inst->inst_parent_dir_name) +
- strlen(inst->inst_dir_name) + 2;
- char *full_inst_dir = (char *)slapi_ch_malloc(len);
- PR_snprintf(full_inst_dir, len, "%s%c%s",
- inst->inst_parent_dir_name, get_sep(inst->inst_parent_dir_name),
- inst->inst_dir_name);
- return full_inst_dir;
- }
- else
- return slapi_ch_strdup(inst->inst_dir_name);
- }
- static void *
- ldbm_instance_config_require_index_get(void *arg)
- {
- ldbm_instance *inst = (ldbm_instance *)arg;
-
- return (void *)((uintptr_t)inst->require_index);
- }
- static int
- ldbm_instance_config_instance_dir_set(void *arg, void *value, char *errorbuf, int phase, int apply)
- {
- ldbm_instance *inst = (ldbm_instance *)arg;
- if (!apply) {
- return LDAP_SUCCESS;
- }
- if ((value == NULL) || (strlen(value) == 0))
- {
- inst->inst_dir_name = NULL;
- inst->inst_parent_dir_name = NULL;
- }
- else
- {
- char *dir = (char *)value;
- if (is_fullpath(dir))
- {
- char sep = get_sep(dir);
- char *p = strrchr(dir, sep);
- if (NULL == p) /* should not happens, tho */
- {
- inst->inst_parent_dir_name = NULL;
- inst->inst_dir_name = rel2abspath(dir); /* normalize dir;
- strdup'ed in
- rel2abspath */
- }
- else
- {
- *p = '\0';
- inst->inst_parent_dir_name = rel2abspath(dir); /* normalize dir;
- strdup'ed in
- rel2abspath */
- inst->inst_dir_name = slapi_ch_strdup(p+1);
- *p = sep;
- }
- }
- else
- {
- inst->inst_parent_dir_name = NULL;
- inst->inst_dir_name = slapi_ch_strdup(dir);
- }
- }
- return LDAP_SUCCESS;
- }
- static int
- ldbm_instance_config_readonly_set(void *arg, void *value, char *errorbuf, int phase, int apply)
- {
- ldbm_instance *inst = (ldbm_instance *)arg;
- uintptr_t pval = (uintptr_t)value;
- if (!apply) {
- return LDAP_SUCCESS;
- }
- if (CONFIG_PHASE_RUNNING == phase) {
- /* if the instance is busy, we'll save the user's readonly settings
- * but won't change them until the instance is un-busy again.
- */
- if (! (inst->inst_flags & INST_FLAG_BUSY)) {
- slapi_mtn_be_set_readonly(inst->inst_be, (int)pval);
- }
- if ((int)pval) {
- inst->inst_flags |= INST_FLAG_READONLY;
- } else {
- inst->inst_flags &= ~INST_FLAG_READONLY;
- }
- } else {
- slapi_be_set_readonly(inst->inst_be, (int)pval);
- }
- return LDAP_SUCCESS;
- }
- static int
- ldbm_instance_config_require_index_set(void *arg, void *value, char *errorbuf, int phase, int apply)
- {
- ldbm_instance *inst = (ldbm_instance *)arg;
- if (!apply) {
- return LDAP_SUCCESS;
- }
- inst->require_index = (int)((uintptr_t)value);
- return LDAP_SUCCESS;
- }
- /*------------------------------------------------------------------------
- * ldbm instance configuration array
- *----------------------------------------------------------------------*/
- static config_info ldbm_instance_config[] = {
- {CONFIG_INSTANCE_CACHESIZE, CONFIG_TYPE_LONG, "-1", &ldbm_instance_config_cachesize_get, &ldbm_instance_config_cachesize_set, CONFIG_FLAG_ALWAYS_SHOW|CONFIG_FLAG_ALLOW_RUNNING_CHANGE},
- {CONFIG_INSTANCE_CACHEMEMSIZE, CONFIG_TYPE_SIZE_T, "10485760", &ldbm_instance_config_cachememsize_get, &ldbm_instance_config_cachememsize_set, CONFIG_FLAG_ALWAYS_SHOW|CONFIG_FLAG_ALLOW_RUNNING_CHANGE},
- {CONFIG_INSTANCE_READONLY, CONFIG_TYPE_ONOFF, "off", &ldbm_instance_config_readonly_get, &ldbm_instance_config_readonly_set, CONFIG_FLAG_ALWAYS_SHOW|CONFIG_FLAG_ALLOW_RUNNING_CHANGE},
- {CONFIG_INSTANCE_REQUIRE_INDEX, CONFIG_TYPE_ONOFF, "off", &ldbm_instance_config_require_index_get, &ldbm_instance_config_require_index_set, CONFIG_FLAG_ALWAYS_SHOW|CONFIG_FLAG_ALLOW_RUNNING_CHANGE},
- {CONFIG_INSTANCE_DIR, CONFIG_TYPE_STRING, NULL, &ldbm_instance_config_instance_dir_get, &ldbm_instance_config_instance_dir_set, CONFIG_FLAG_ALWAYS_SHOW},
- {NULL, 0, NULL, NULL, NULL, 0}
- };
- void
- ldbm_instance_config_setup_default(ldbm_instance *inst)
- {
- config_info *config;
- char err_buf[BUFSIZ];
- for (config = ldbm_instance_config; config->config_name != NULL; config++) {
- ldbm_config_set((void *)inst, config->config_name, ldbm_instance_config, NULL /* use default */, err_buf, CONFIG_PHASE_INITIALIZATION, 1 /* apply */);
- }
- }
- static int
- parse_ldbm_instance_entry(Slapi_Entry *e, char **instance_name)
- {
- Slapi_Attr *attr = NULL;
-
- for (slapi_entry_first_attr(e, &attr); attr;
- slapi_entry_next_attr(e, attr, &attr)) {
- char *attr_name = NULL;
- slapi_attr_get_type(attr, &attr_name);
- if (strcasecmp(attr_name, "cn") == 0) {
- Slapi_Value *sval = NULL;
- struct berval *bval;
- slapi_attr_first_value(attr, &sval);
- bval = (struct berval *) slapi_value_get_berval(sval);
- *instance_name = slapi_ch_strdup((char *)bval->bv_val);
- }
- }
- return 0;
- }
- /* When a new instance is started, we need to read the dse to
- * find out what indexes should be maintained. This function
- * does that. Returns 0 on success. */
- static int
- read_instance_index_entries(ldbm_instance *inst)
- {
- Slapi_PBlock *tmp_pb;
- int scope = LDAP_SCOPE_SUBTREE;
- char basedn[BUFSIZ];
- const char *searchfilter = "(objectclass=nsIndex)";
- /* Construct the base dn of the subtree that holds the index entries
- * for this instance. */
- PR_snprintf(basedn, BUFSIZ, "cn=index, cn=%s, cn=%s, cn=plugins, cn=config",
- inst->inst_name, inst->inst_li->li_plugin->plg_name);
- /* Set up a tmp callback that will handle the init for each index entry */
- slapi_config_register_callback(SLAPI_OPERATION_SEARCH, DSE_FLAG_PREOP,
- basedn, scope, searchfilter, ldbm_index_init_entry_callback,
- (void *) inst);
- /* Do a search of the subtree containing the index entries */
- tmp_pb = slapi_pblock_new();
- slapi_search_internal_set_pb(tmp_pb, basedn, LDAP_SCOPE_SUBTREE,
- searchfilter, NULL, 0, NULL, NULL, inst->inst_li->li_identity, 0);
- slapi_search_internal_pb (tmp_pb);
- /* Remove the tmp callback */
- slapi_config_remove_callback(SLAPI_OPERATION_SEARCH, DSE_FLAG_PREOP,
- basedn, scope, searchfilter, ldbm_index_init_entry_callback);
- slapi_free_search_results_internal(tmp_pb);
- slapi_pblock_destroy(tmp_pb);
- return 0;
- }
- /* When a new instance is started, we need to read the dse to
- * find out what attributes should be encrypted. This function
- * does that. Returns 0 on success. */
- static int
- read_instance_attrcrypt_entries(ldbm_instance *inst)
- {
- Slapi_PBlock *tmp_pb;
- int scope = LDAP_SCOPE_SUBTREE;
- char basedn[BUFSIZ];
- const char *searchfilter = ldbm_instance_attrcrypt_filter;
- /* Construct the base dn of the subtree that holds the index entries
- * for this instance. */
- PR_snprintf(basedn, BUFSIZ, "cn=encrypted attributes, cn=%s, cn=%s, cn=plugins, cn=config",
- inst->inst_name, inst->inst_li->li_plugin->plg_name);
- /* Set up a tmp callback that will handle the init for each index entry */
- slapi_config_register_callback(SLAPI_OPERATION_SEARCH, DSE_FLAG_PREOP,
- basedn, scope, searchfilter, ldbm_attrcrypt_init_entry_callback,
- (void *) inst);
- /* Do a search of the subtree containing the index entries */
- tmp_pb = slapi_pblock_new();
- slapi_search_internal_set_pb(tmp_pb, basedn, LDAP_SCOPE_SUBTREE,
- searchfilter, NULL, 0, NULL, NULL, inst->inst_li->li_identity, 0);
- slapi_search_internal_pb (tmp_pb);
- /* Remove the tmp callback */
- slapi_config_remove_callback(SLAPI_OPERATION_SEARCH, DSE_FLAG_PREOP,
- basedn, scope, searchfilter, ldbm_attrcrypt_init_entry_callback);
- slapi_free_search_results_internal(tmp_pb);
- slapi_pblock_destroy(tmp_pb);
- return 0;
- }
- /* Handles the parsing of the config entry for an ldbm instance. Returns 0
- * on success. */
- static int
- parse_ldbm_instance_config_entry(ldbm_instance *inst, Slapi_Entry *e, config_info *config_array)
- {
- Slapi_Attr *attr = NULL;
-
- for (slapi_entry_first_attr(e, &attr); attr;
- slapi_entry_next_attr(e, attr, &attr)) {
- char *attr_name = NULL;
- Slapi_Value *sval = NULL;
- struct berval *bval;
- char err_buf[BUFSIZ];
-
- slapi_attr_get_type(attr, &attr_name);
- /* There are some attributes that we don't care about,
- * like objectclass. */
- if (ldbm_config_ignored_attr(attr_name)) {
- continue;
- }
- /* We have to handle suffix attributes a little differently */
- if (strcasecmp(attr_name, CONFIG_INSTANCE_SUFFIX) == 0) {
- Slapi_DN suffix;
- slapi_attr_first_value(attr, &sval);
- bval = (struct berval *) slapi_value_get_berval(sval);
- slapi_sdn_init_dn_byref(&suffix, bval->bv_val);
- if (!slapi_be_issuffix(inst->inst_be, &suffix)) {
- be_addsuffix(inst->inst_be, &suffix);
- }
- slapi_sdn_done(&suffix);
- continue;
- }
- /* We are assuming that each of these attributes are to have
- * only one value. If they have more than one value, like
- * the nsslapd-suffix attribute, then they need to be
- * handled differently. */
- slapi_attr_first_value(attr, &sval);
- bval = (struct berval *) slapi_value_get_berval(sval);
- if (ldbm_config_set((void *) inst, attr_name, config_array, bval,
- err_buf, CONFIG_PHASE_STARTUP, 1 /* apply */) != LDAP_SUCCESS) {
- LDAPDebug(LDAP_DEBUG_ANY, "Error with config attribute %s : %s\n",
- attr_name, err_buf, 0);
- return 1;
- }
- }
- /* Read the index entries */
- read_instance_index_entries(inst);
- /* Read the attribute encryption entries */
- read_instance_attrcrypt_entries(inst);
- return 0;
- }
- /* general-purpose callback to deny an operation */
- static int ldbm_instance_deny_config(Slapi_PBlock *pb, Slapi_Entry *e,
- Slapi_Entry *entryAfter, int *returncode, char *returntext, void *arg)
- {
- *returncode = LDAP_UNWILLING_TO_PERFORM;
- return SLAPI_DSE_CALLBACK_ERROR;
- }
- /* Reads in any config information held in the dse for the given
- * entry. Creates dse entries used to configure the given instance
- * if they don't already exist. Registers dse callback functions to
- * maintain those dse entries. Returns 0 on success. */
- int
- ldbm_instance_config_load_dse_info(ldbm_instance *inst)
- {
- struct ldbminfo *li = inst->inst_li;
- Slapi_PBlock *search_pb;
- Slapi_Entry **entries = NULL;
- int res;
- char dn[BUFSIZ];
- /* We try to read the entry
- * cn=instance_name, cn=ldbm database, cn=plugins, cn=config. If the
- * entry is there, then we process the config information it stores.
- */
- PR_snprintf(dn, BUFSIZ, "cn=%s, cn=%s, cn=plugins, cn=config",
- inst->inst_name, li->li_plugin->plg_name);
- search_pb = slapi_pblock_new();
- slapi_search_internal_set_pb(search_pb, dn, LDAP_SCOPE_BASE,
- "objectclass=*", NULL, 0, NULL, NULL,
- li->li_identity, 0);
- slapi_search_internal_pb (search_pb);
- slapi_pblock_get(search_pb, SLAPI_PLUGIN_INTOP_RESULT, &res);
- if (res != LDAP_SUCCESS) {
- LDAPDebug(LDAP_DEBUG_ANY, "Error accessing the config DSE\n", 0, 0, 0);
- return 1;
- } else {
- /* Need to parse the configuration information for the ldbm
- * plugin that is held in the DSE. */
- slapi_pblock_get(search_pb, SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES,
- &entries);
- if ((!entries) || (!entries[0])) {
- LDAPDebug(LDAP_DEBUG_ANY, "Error accessing the config DSE\n",
- 0, 0, 0);
- return 1;
- }
- if (0 != parse_ldbm_instance_config_entry(inst, entries[0],
- ldbm_instance_config)) {
- LDAPDebug(LDAP_DEBUG_ANY, "Error parsing the config DSE\n",
- 0, 0, 0);
- return 1;
- }
- }
- if (search_pb)
- {
- slapi_free_search_results_internal(search_pb);
- slapi_pblock_destroy(search_pb);
- }
- /* Add skeleton dse entries for this instance */
- /* IF they already exist, that's ok */
- ldbm_config_add_dse_entries(li, ldbm_instance_skeleton_entries,
- inst->inst_name, li->li_plugin->plg_name,
- inst->inst_name, 0);
- /* setup the dse callback functions for the ldbm instance config entry */
- PR_snprintf(dn, BUFSIZ, "cn=%s, cn=%s, cn=plugins, cn=config",
- inst->inst_name, li->li_plugin->plg_name);
- slapi_config_register_callback(SLAPI_OPERATION_SEARCH, DSE_FLAG_PREOP, dn,
- LDAP_SCOPE_BASE, "(objectclass=*)",
- ldbm_instance_search_config_entry_callback, (void *) inst);
- slapi_config_register_callback(SLAPI_OPERATION_MODIFY, DSE_FLAG_PREOP, dn,
- LDAP_SCOPE_BASE, "(objectclass=*)",
- ldbm_instance_modify_config_entry_callback, (void *) inst);
- slapi_config_register_callback(DSE_OPERATION_WRITE, DSE_FLAG_PREOP, dn,
- LDAP_SCOPE_BASE, "(objectclass=*)",
- ldbm_instance_search_config_entry_callback, (void *) inst);
- slapi_config_register_callback(SLAPI_OPERATION_ADD, DSE_FLAG_PREOP, dn,
- LDAP_SCOPE_BASE, "(objectclass=*)",
- ldbm_instance_deny_config, (void *)inst);
- /* delete is handled by a callback set in ldbm_config.c */
- /* don't forget the monitor! */
- PR_snprintf(dn, BUFSIZ, "cn=monitor, cn=%s, cn=%s, cn=plugins, cn=config",
- inst->inst_name, li->li_plugin->plg_name);
- /* make callback on search; deny add/modify/delete */
- slapi_config_register_callback(SLAPI_OPERATION_SEARCH, DSE_FLAG_PREOP, dn,
- LDAP_SCOPE_BASE, "(objectclass=*)", ldbm_back_monitor_instance_search,
- (void *)inst);
- slapi_config_register_callback(SLAPI_OPERATION_ADD, DSE_FLAG_PREOP, dn,
- LDAP_SCOPE_SUBTREE, "(objectclass=*)", ldbm_instance_deny_config,
- (void *)inst);
- slapi_config_register_callback(SLAPI_OPERATION_MODIFY, DSE_FLAG_PREOP, dn,
- LDAP_SCOPE_BASE, "(objectclass=*)", ldbm_instance_deny_config,
- (void *)inst);
- /* delete is okay */
- /* Callbacks to handle indexes */
- PR_snprintf(dn, BUFSIZ, "cn=index, cn=%s, cn=%s, cn=plugins, cn=config",
- inst->inst_name, li->li_plugin->plg_name);
- slapi_config_register_callback(SLAPI_OPERATION_ADD, DSE_FLAG_PREOP, dn,
- LDAP_SCOPE_SUBTREE, "(objectclass=nsIndex)",
- ldbm_instance_index_config_add_callback, (void *) inst);
- slapi_config_register_callback(SLAPI_OPERATION_DELETE, DSE_FLAG_PREOP, dn,
- LDAP_SCOPE_SUBTREE, "(objectclass=nsIndex)",
- ldbm_instance_index_config_delete_callback, (void *) inst);
- slapi_config_register_callback(SLAPI_OPERATION_MODIFY, DSE_FLAG_PREOP, dn,
- LDAP_SCOPE_SUBTREE, "(objectclass=nsIndex)",
- ldbm_instance_index_config_modify_callback, (void *) inst);
- /* Callbacks to handle attribute encryption */
- PR_snprintf(dn, BUFSIZ, "cn=encrypted attributes, cn=%s, cn=%s, cn=plugins, cn=config",
- inst->inst_name, li->li_plugin->plg_name);
- slapi_config_register_callback(SLAPI_OPERATION_ADD, DSE_FLAG_PREOP, dn,
- LDAP_SCOPE_SUBTREE, ldbm_instance_attrcrypt_filter,
- ldbm_instance_attrcrypt_config_add_callback, (void *) inst);
- slapi_config_register_callback(SLAPI_OPERATION_DELETE, DSE_FLAG_PREOP, dn,
- LDAP_SCOPE_SUBTREE, ldbm_instance_attrcrypt_filter,
- ldbm_instance_attrcrypt_config_delete_callback, (void *) inst);
- slapi_config_register_callback(SLAPI_OPERATION_MODIFY, DSE_FLAG_PREOP, dn,
- LDAP_SCOPE_SUBTREE, ldbm_instance_attrcrypt_filter,
- ldbm_instance_attrcrypt_config_modify_callback, (void *) inst);
- return 0;
- }
- /*
- * Config. DSE callback for instance entry searches.
- */
- int
- ldbm_instance_search_config_entry_callback(Slapi_PBlock *pb, Slapi_Entry *e, Slapi_Entry *entryAfter, int *returncode, char *returntext, void *arg)
- {
- char buf[BUFSIZ];
- struct berval *vals[2];
- struct berval val;
- ldbm_instance *inst = (ldbm_instance *) arg;
- config_info *config;
- int x;
- const Slapi_DN *suffix;
- vals[0] = &val;
- vals[1] = NULL;
- returntext[0] = '\0';
- /* show the suffixes */
- attrlist_delete(&e->e_attrs, CONFIG_INSTANCE_SUFFIX);
- x = 0;
- do {
- suffix = slapi_be_getsuffix(inst->inst_be, x);
- if (suffix != NULL) {
- val.bv_val = (char *) slapi_sdn_get_dn(suffix);
- val.bv_len = strlen (val.bv_val);
- attrlist_merge( &e->e_attrs, CONFIG_INSTANCE_SUFFIX, vals );
- }
- x++;
- } while(suffix!=NULL);
- PR_Lock(inst->inst_config_mutex);
- for(config = ldbm_instance_config; config->config_name != NULL; config++) {
- /* Go through the ldbm_config table and fill in the entry. */
- if (!(config->config_flags & (CONFIG_FLAG_ALWAYS_SHOW | CONFIG_FLAG_PREVIOUSLY_SET))) {
- /* This config option shouldn't be shown */
- continue;
- }
- ldbm_config_get((void *) inst, config, buf);
- val.bv_val = buf;
- val.bv_len = strlen(buf);
- slapi_entry_attr_replace(e, config->config_name, vals);
- }
-
- PR_Unlock(inst->inst_config_mutex);
- *returncode = LDAP_SUCCESS;
- return SLAPI_DSE_CALLBACK_OK;
- }
- /* This function is used by the instance modify callback to add a new
- * suffix. It return LDAP_SUCCESS on success.
- */
- int
- add_suffix(ldbm_instance *inst, struct berval **bvals, int apply_mod, char *returntext)
- {
- Slapi_DN suffix;
- int x;
- returntext[0] = '\0';
- for (x = 0; bvals[x]; x++) {
- slapi_sdn_init_dn_byref(&suffix, bvals[x]->bv_val);
- if (!slapi_be_issuffix(inst->inst_be, &suffix) && apply_mod) {
- be_addsuffix(inst->inst_be, &suffix);
- }
- slapi_sdn_done(&suffix);
- }
- return LDAP_SUCCESS;
- }
- /*
- * Config. DSE callback for instance entry modifies.
- */
- int
- ldbm_instance_modify_config_entry_callback(Slapi_PBlock *pb, Slapi_Entry* entryBefore, Slapi_Entry* e, int *returncode, char *returntext, void *arg)
- {
- int i;
- char *attr_name;
- LDAPMod **mods;
- int rc = LDAP_SUCCESS;
- int apply_mod = 0;
- ldbm_instance *inst = (ldbm_instance *) arg;
- /* This lock is probably way too conservative, but we don't expect much
- * contention for it. */
- PR_Lock(inst->inst_config_mutex);
- slapi_pblock_get( pb, SLAPI_MODIFY_MODS, &mods );
-
- returntext[0] = '\0';
- /*
- * First pass: set apply mods to 0 so only input validation will be done;
- * 2nd pass: set apply mods to 1 to apply changes to internal storage
- */
- for ( apply_mod = 0; apply_mod <= 1 && LDAP_SUCCESS == rc; apply_mod++ ) {
- for (i = 0; mods[i] && LDAP_SUCCESS == rc; i++) {
- attr_name = mods[i]->mod_type;
- if (strcasecmp(attr_name, CONFIG_INSTANCE_SUFFIX) == 0) {
- /* naughty naughty, we don't allow this */
- rc = LDAP_UNWILLING_TO_PERFORM;
- if (returntext) {
- PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE,
- "Can't change the root suffix of a backend");
- }
- LDAPDebug(LDAP_DEBUG_ANY,
- "ldbm: modify attempted to change the root suffix "
- "of a backend (which is not allowed)\n",
- 0, 0, 0);
- continue;
- }
- /* There are some attributes that we don't care about, like
- * modifiersname. */
- if (ldbm_config_ignored_attr(attr_name)) {
- continue;
- }
- if ((mods[i]->mod_op & LDAP_MOD_DELETE) ||
- (mods[i]->mod_op & LDAP_MOD_ADD)) {
- rc= LDAP_UNWILLING_TO_PERFORM;
- PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE, "%s attributes is not allowed",
- (mods[i]->mod_op & LDAP_MOD_DELETE) ?
- "Deleting" : "Adding");
- } else if (mods[i]->mod_op & LDAP_MOD_REPLACE) {
- /* This assumes there is only one bval for this mod. */
- rc = ldbm_config_set((void *) inst, attr_name,
- ldbm_instance_config, mods[i]->mod_bvalues[0], returntext,
- CONFIG_PHASE_RUNNING, apply_mod);
- }
- }
- }
- PR_Unlock(inst->inst_config_mutex);
- *returncode = rc;
- if (LDAP_SUCCESS == rc) {
- return SLAPI_DSE_CALLBACK_OK;
- } else {
- return SLAPI_DSE_CALLBACK_ERROR;
- }
- }
- /* This function is used to set instance config attributes. It can be used as a
- * shortcut to doing an internal modify operation on the config DSE.
- */
- void
- ldbm_instance_config_internal_set(ldbm_instance *inst, char *attrname, char *value)
- {
- char err_buf[BUFSIZ];
- struct berval bval;
- bval.bv_val = value;
- bval.bv_len = strlen(value);
- if (ldbm_config_set((void *) inst, attrname, ldbm_instance_config, &bval,
- err_buf, CONFIG_PHASE_INTERNAL, 1 /* apply */) != LDAP_SUCCESS) {
- LDAPDebug(LDAP_DEBUG_ANY,
- "Internal Error: Error setting instance config attr %s to %s: %s\n",
- attrname, value, err_buf);
- exit(1);
- }
- }
- static int ldbm_instance_generate(struct ldbminfo *li, char *instance_name,
- Slapi_Backend **ret_be)
- {
- Slapi_Backend *new_be = NULL;
- int rc = 0;
- /* Create a new instance, process config info for it,
- * and then call slapi_be_new and create a new backend here
- */
- new_be = slapi_be_new(LDBM_DATABASE_TYPE_NAME /* type */, instance_name,
- 0 /* public */, 1 /* do log changes */);
- new_be->be_database = li->li_plugin;
- ldbm_instance_create(new_be, instance_name);
- ldbm_instance_config_load_dse_info(new_be->be_instance_info);
- rc = ldbm_instance_create_default_indexes(new_be);
- /* if USN plugin is enabled, set slapi_counter */
- if (plugin_enabled("USN", li->li_identity)) {
- /* slapi_counter_new sets the initial value to 0 */
- new_be->be_usn_counter = slapi_counter_new();
- }
- if (ret_be != NULL) {
- *ret_be = new_be;
- }
- return rc;
- }
- int
- ldbm_instance_postadd_instance_entry_callback(Slapi_PBlock *pb, Slapi_Entry* entryBefore, Slapi_Entry* entryAfter, int *returncode, char *returntext, void *arg)
- {
- backend *be = NULL;
- struct ldbm_instance *inst;
- char *instance_name;
- struct ldbminfo *li = (struct ldbminfo *)arg;
- int rval = 0;
- parse_ldbm_instance_entry(entryBefore, &instance_name);
- ldbm_instance_generate(li, instance_name, &be);
- inst = ldbm_instance_find_by_name(li, instance_name);
- /* Add default indexes */
- ldbm_instance_create_default_user_indexes(inst);
- /* Initialize and register callbacks for VLV indexes */
- vlv_init(inst);
- /* this is an ACTUAL ADD being done while the server is running!
- * start up the appropriate backend...
- */
- rval = ldbm_instance_start(be);
- if (0 != rval)
- {
- LDAPDebug(LDAP_DEBUG_ANY,
- "ldbm_instance_postadd_instance_entry_callback: "
- "ldbm_instnace_start (%s) failed (%d)\n",
- instance_name, rval, 0);
- }
- slapi_ch_free((void **)&instance_name);
- /* instance must be fully ready before we call this */
- slapi_mtn_be_started(be);
- return SLAPI_DSE_CALLBACK_OK;
- }
- int
- ldbm_instance_add_instance_entry_callback(Slapi_PBlock *pb, Slapi_Entry* entryBefore, Slapi_Entry* entryAfter, int *returncode, char *returntext, void *arg)
- {
- char *instance_name;
- struct ldbm_instance *inst= NULL;
- struct ldbminfo *li= (struct ldbminfo *) arg;
- int rc = 0;
- parse_ldbm_instance_entry(entryBefore, &instance_name);
- /* Make sure we don't create two instances with the same name. */
- inst = ldbm_instance_find_by_name(li, instance_name);
- if (inst != NULL) {
- LDAPDebug(LDAP_DEBUG_ANY, "WARNING: ldbm instance %s already exists\n",
- instance_name, 0, 0);
- if (returntext != NULL)
- PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE, "An ldbm instance with the name %s already exists\n",
- instance_name);
- if (returncode != NULL)
- *returncode = LDAP_UNWILLING_TO_PERFORM;
- slapi_ch_free((void **)&instance_name);
- return SLAPI_DSE_CALLBACK_ERROR;
- }
- if (pb == NULL) {
- /* called during startup -- do the rest now */
- rc = ldbm_instance_generate(li, instance_name, NULL);
- if (!rc) {
- inst = ldbm_instance_find_by_name(li, instance_name);
- rc = ldbm_instance_create_default_user_indexes(inst);
- }
- }
- /* if called during a normal ADD operation, the postadd callback
- * will do the rest.
- */
- slapi_ch_free((void **)&instance_name);
- return (rc == 0) ? SLAPI_DSE_CALLBACK_OK : SLAPI_DSE_CALLBACK_ERROR;
- }
- /* unregister the DSE callbacks on a backend -- this needs to be done when
- * deleting a backend, so that adding the same backend later won't cause
- * these expired callbacks to be called.
- */
- static void ldbm_instance_unregister_callbacks(ldbm_instance *inst)
- {
- struct ldbminfo *li = inst->inst_li;
- char dn[BUFSIZ];
- /* tear down callbacks for the instance config entry */
- PR_snprintf(dn, BUFSIZ, "cn=%s, cn=%s, cn=plugins, cn=config",
- inst->inst_name, li->li_plugin->plg_name);
- slapi_config_remove_callback(SLAPI_OPERATION_SEARCH, DSE_FLAG_PREOP, dn,
- LDAP_SCOPE_BASE, "(objectclass=*)",
- ldbm_instance_search_config_entry_callback);
- slapi_config_remove_callback(SLAPI_OPERATION_MODIFY, DSE_FLAG_PREOP, dn,
- LDAP_SCOPE_BASE, "(objectclass=*)",
- ldbm_instance_modify_config_entry_callback);
- slapi_config_remove_callback(DSE_OPERATION_WRITE, DSE_FLAG_PREOP, dn,
- LDAP_SCOPE_BASE, "(objectclass=*)",
- ldbm_instance_search_config_entry_callback);
- slapi_config_remove_callback(SLAPI_OPERATION_ADD, DSE_FLAG_PREOP, dn,
- LDAP_SCOPE_BASE, "(objectclass=*)",
- ldbm_instance_deny_config);
- /* now the cn=monitor entry */
- PR_snprintf(dn, BUFSIZ, "cn=monitor, cn=%s, cn=%s, cn=plugins, cn=config",
- inst->inst_name, li->li_plugin->plg_name);
- slapi_config_remove_callback(SLAPI_OPERATION_SEARCH, DSE_FLAG_PREOP, dn,
- LDAP_SCOPE_BASE, "(objectclass=*)", ldbm_back_monitor_instance_search);
- slapi_config_remove_callback(SLAPI_OPERATION_ADD, DSE_FLAG_PREOP, dn,
- LDAP_SCOPE_SUBTREE, "(objectclass=*)", ldbm_instance_deny_config);
- slapi_config_remove_callback(SLAPI_OPERATION_MODIFY, DSE_FLAG_PREOP, dn,
- LDAP_SCOPE_BASE, "(objectclass=*)", ldbm_instance_deny_config);
- /* now the cn=index entries */
- PR_snprintf(dn, BUFSIZ, "cn=index, cn=%s, cn=%s, cn=plugins, cn=config",
- inst->inst_name, li->li_plugin->plg_name);
- slapi_config_remove_callback(SLAPI_OPERATION_ADD, DSE_FLAG_PREOP, dn,
- LDAP_SCOPE_SUBTREE, "(objectclass=nsIndex)",
- ldbm_instance_index_config_add_callback);
- slapi_config_remove_callback(SLAPI_OPERATION_DELETE, DSE_FLAG_PREOP, dn,
- LDAP_SCOPE_SUBTREE, "(objectclass=nsIndex)",
- ldbm_instance_index_config_delete_callback);
- slapi_config_remove_callback(SLAPI_OPERATION_MODIFY, DSE_FLAG_PREOP, dn,
- LDAP_SCOPE_SUBTREE, "(objectclass=nsIndex)",
- ldbm_instance_index_config_modify_callback);
- /* now the cn=encrypted attributes entries */
- PR_snprintf(dn, BUFSIZ, "cn=encrypted attributes, cn=%s, cn=%s, cn=plugins, cn=config",
- inst->inst_name, li->li_plugin->plg_name);
- slapi_config_remove_callback(SLAPI_OPERATION_ADD, DSE_FLAG_PREOP, dn,
- LDAP_SCOPE_SUBTREE, ldbm_instance_attrcrypt_filter,
- ldbm_instance_attrcrypt_config_add_callback);
- slapi_config_remove_callback(SLAPI_OPERATION_DELETE, DSE_FLAG_PREOP, dn,
- LDAP_SCOPE_SUBTREE, ldbm_instance_attrcrypt_filter,
- ldbm_instance_attrcrypt_config_delete_callback);
- slapi_config_remove_callback(SLAPI_OPERATION_MODIFY, DSE_FLAG_PREOP, dn,
- LDAP_SCOPE_SUBTREE, ldbm_instance_attrcrypt_filter,
- ldbm_instance_attrcrypt_config_modify_callback);
- vlv_remove_callbacks(inst);
- }
- int
- ldbm_instance_post_delete_instance_entry_callback(Slapi_PBlock *pb, Slapi_Entry* entryBefore, Slapi_Entry* entryAfter, int *returncode, char *returntext, void *arg)
- {
- char *instance_name;
- struct ldbminfo *li = (struct ldbminfo *)arg;
- struct ldbm_instance *inst = NULL;
- parse_ldbm_instance_entry(entryBefore, &instance_name);
- inst = ldbm_instance_find_by_name(li, instance_name);
- if (inst == NULL) {
- LDAPDebug(LDAP_DEBUG_ANY, "ldbm: instance '%s' does not exist! (2)\n",
- instance_name, 0, 0);
- if (returntext) {
- PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE, "No ldbm instance exists with the name '%s' (2)\n",
- instance_name);
- }
- if (returncode) {
- *returncode = LDAP_UNWILLING_TO_PERFORM;
- }
- slapi_ch_free((void **)&instance_name);
- return SLAPI_DSE_CALLBACK_ERROR;
- }
- LDAPDebug(LDAP_DEBUG_ANY, "ldbm: removing '%s'.\n", instance_name, 0, 0);
- {
- struct ldbminfo *li = (struct ldbminfo *) inst->inst_be->be_database->plg_private;
- dblayer_private *priv = (dblayer_private*) li->li_dblayer_private;
- struct dblayer_private_env *pEnv = priv->dblayer_env;
- if(pEnv) {
- PRDir *dirhandle = NULL;
- char inst_dir[MAXPATHLEN*2];
- char *inst_dirp = NULL;
- if (inst->inst_dir_name == NULL){
- dblayer_get_instance_data_dir(inst->inst_be);
- }
- inst_dirp = dblayer_get_full_inst_dir(li, inst,
- inst_dir, MAXPATHLEN*2);
- if (NULL != inst_dirp) {
- dirhandle = PR_OpenDir(inst_dirp);
- /* the db dir instance may have been removed already */
- if (dirhandle) {
- PRDirEntry *direntry = NULL;
- char *dbp = NULL;
- char *p = NULL;
- while (NULL != (direntry = PR_ReadDir(dirhandle,
- PR_SKIP_DOT|PR_SKIP_DOT_DOT))) {
- int rc;
- if (!direntry->name)
- break;
- dbp = PR_smprintf("%s/%s", inst_dirp, direntry->name);
- if (NULL == dbp) {
- LDAPDebug (LDAP_DEBUG_ANY,
- "ldbm_instance_post_delete_instance_entry_callback:"
- " failed to generate db path: %s/%s\n",
- inst_dirp, direntry->name, 0);
- break;
- }
- p = strstr(dbp, LDBM_FILENAME_SUFFIX);
- if (NULL != p &&
- strlen(p) == strlen(LDBM_FILENAME_SUFFIX)) {
- rc = dblayer_db_remove(pEnv, dbp, 0);
- } else {
- rc = PR_Delete(dbp);
- }
- PR_ASSERT(rc == 0);
- PR_smprintf_free(dbp);
- }
- PR_CloseDir(dirhandle);
- }
- PR_RmDir(inst_dirp);
- } /* non-null dirhandle */
- if (inst_dirp != inst_dir) {
- slapi_ch_free_string(&inst_dirp);
- }
- } /* non-null pEnv */
- }
- ldbm_instance_unregister_callbacks(inst);
- slapi_be_free(&inst->inst_be);
- ldbm_instance_destroy(inst);
- slapi_ch_free((void **)&instance_name);
- return SLAPI_DSE_CALLBACK_OK;
- }
- int
- ldbm_instance_delete_instance_entry_callback(Slapi_PBlock *pb, Slapi_Entry* entryBefore, Slapi_Entry* entryAfter, int *returncode, char *returntext, void *arg)
- {
- char *instance_name;
- struct ldbminfo *li = (struct ldbminfo *)arg;
- struct ldbm_instance *inst = NULL;
- parse_ldbm_instance_entry(entryBefore, &instance_name);
- inst = ldbm_instance_find_by_name(li, instance_name);
- if (inst == NULL) {
- LDAPDebug(LDAP_DEBUG_ANY, "ldbm: instance '%s' does not exist!\n",
- instance_name, 0, 0);
- if (returntext) {
- PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE, "No ldbm instance exists with the name '%s'\n",
- instance_name);
- }
- if (returncode) {
- *returncode = LDAP_UNWILLING_TO_PERFORM;
- }
- slapi_ch_free((void **)&instance_name);
- return SLAPI_DSE_CALLBACK_ERROR;
- }
- /* check if some online task is happening */
- if (instance_set_busy(inst) != 0) {
- LDAPDebug(LDAP_DEBUG_ANY, "ldbm: '%s' is in the middle of a task. "
- "Cancel the task or wait for it to finish, "
- "then try again.\n", instance_name, 0, 0);
- if (returntext) {
- PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE, "ldbm instance '%s' is in the middle of a "
- "task. Cancel the task or wait for it to finish, "
- "then try again.\n", instance_name);
- }
- if (returncode) {
- *returncode = LDAP_UNWILLING_TO_PERFORM;
- }
- slapi_ch_free((void **)&instance_name);
- return SLAPI_DSE_CALLBACK_ERROR;
- }
- /* okay, we're gonna delete this database instance. take it offline. */
- LDAPDebug(LDAP_DEBUG_ANY, "ldbm: Bringing %s offline...\n",
- instance_name, 0, 0);
- slapi_mtn_be_stopping(inst->inst_be);
- dblayer_instance_close(inst->inst_be);
- cache_destroy_please(&inst->inst_cache);
- slapi_ch_free((void **)&instance_name);
- return SLAPI_DSE_CALLBACK_OK;
- }
|