summaryrefslogtreecommitdiffstats
path: root/ldap/servers/slapd/config.c
diff options
context:
space:
mode:
Diffstat (limited to 'ldap/servers/slapd/config.c')
-rw-r--r--ldap/servers/slapd/config.c459
1 files changed, 459 insertions, 0 deletions
diff --git a/ldap/servers/slapd/config.c b/ldap/servers/slapd/config.c
new file mode 100644
index 00000000..2e3170a4
--- /dev/null
+++ b/ldap/servers/slapd/config.c
@@ -0,0 +1,459 @@
+/** BEGIN COPYRIGHT BLOCK
+ * Copyright 2001 Sun Microsystems, Inc.
+ * Portions copyright 1999, 2001-2003 Netscape Communications Corporation.
+ * All rights reserved.
+ * END COPYRIGHT BLOCK **/
+/* config.c - configuration file handling routines */
+
+#include <stdio.h>
+#include <string.h>
+#include <sys/types.h>
+#include <errno.h>
+#include <stdlib.h>
+#ifdef _WIN32
+#include <direct.h> /* for getcwd */
+#else
+#include <sys/socket.h>
+#include <sys/param.h>
+#include <unistd.h>
+#include <pwd.h>
+#endif
+#include "slap.h"
+#include "pw.h"
+#include <sys/stat.h>
+#include <prio.h>
+
+#define MAXARGS 1000
+
+
+extern int should_detach;
+extern Slapi_PBlock *repl_pb;
+
+
+extern char* slapd_SSL3ciphers;
+
+#ifndef _WIN32
+extern char *localuser;
+#endif
+
+char* rel2abspath( char * );
+
+/*
+ See if the given entry has an attribute with the given name and the
+ given value; if value is NULL, just test for the presence of the given
+ attribute; if value is an empty string (i.e. value[0] == 0),
+ the first value in the attribute will be copied into the given buffer
+ and returned
+*/
+static int
+entry_has_attr_and_value(Slapi_Entry *e, const char *attrname,
+ char *value, size_t valuebufsize )
+{
+ int retval = 0;
+ Slapi_Attr *attr = 0;
+ if (!e || !attrname)
+ return retval;
+
+ /* see if the entry has the specified attribute name */
+ if (!slapi_entry_attr_find(e, attrname, &attr) && attr)
+ {
+ /* if value is not null, see if the attribute has that
+ value */
+ if (!value)
+ {
+ retval = 1;
+ }
+ else
+ {
+ Slapi_Value *v = 0;
+ int index = 0;
+ for (index = slapi_attr_first_value(attr, &v);
+ v && (index != -1);
+ index = slapi_attr_next_value(attr, index, &v))
+ {
+ const char *s = slapi_value_get_string(v);
+ if (!s)
+ continue;
+
+ if (!*value)
+ {
+ size_t len = strlen(s);
+
+ if ( len < valuebufsize )
+ {
+ strcpy(value, s);
+ retval = 1;
+ }
+ else
+ {
+ slapi_log_error( SLAPI_LOG_FATAL, "bootstrap config",
+ "Ignoring extremely large value for"
+ " configuration attribute %s"
+ " (length=%d, value=%40.40s...)\n",
+ attrname, len, s );
+ retval = 0; /* value is too large: ignore it */
+ }
+ break;
+ }
+ else if (!strcasecmp(s, value))
+ {
+ retval = 1;
+ break;
+ }
+ }
+ }
+ }
+
+ return retval;
+}
+
+
+/*
+ Extract just the configuration information we need for bootstrapping
+ purposes
+ 1) set up error logging
+ 2) disable syntax checking
+ 3) load the syntax plugins
+ etc.
+*/
+int
+slapd_bootstrap_config(const char *configdir)
+{
+ char configfile[MAXPATHLEN+1];
+ PRFileInfo prfinfo;
+ int rc = 0; /* Fail */
+ int done = 0;
+ PRInt32 nr = 0;
+ PRFileDesc *prfd = 0;
+ char *buf = 0;
+ char *lastp = 0;
+ char *entrystr = 0;
+
+ PR_snprintf(configfile, sizeof(configfile), "%s/%s", configdir,
+ CONFIG_FILENAME);
+ if ( (rc = PR_GetFileInfo( configfile, &prfinfo )) != PR_SUCCESS )
+ {
+ /* the "real" file does not exist; see if there is a tmpfile */
+ char tmpfile[MAXPATHLEN+1];
+ PR_snprintf(tmpfile, sizeof(tmpfile), "%s/%s.tmp", configdir,
+ CONFIG_FILENAME);
+ if ( PR_GetFileInfo( tmpfile, &prfinfo ) == PR_SUCCESS ) {
+ rc = PR_Rename(tmpfile, configfile);
+ if (rc == PR_SUCCESS) {
+ slapi_log_error(SLAPI_LOG_FATAL, "config",
+ "The configuration file %s was restored from backup %s\n",
+ configfile, tmpfile);
+ rc = 1;
+ } else {
+ slapi_log_error(SLAPI_LOG_FATAL, "config",
+ "The configuration file %s was not restored from backup %s, error %d\n",
+ configfile, tmpfile, rc);
+ rc = 0;
+ }
+ } else {
+ rc = 0; /* fail */
+ }
+ }
+ if ( (rc = PR_GetFileInfo( configfile, &prfinfo )) != PR_SUCCESS )
+ {
+ PRErrorCode prerr = PR_GetError();
+ slapi_log_error(SLAPI_LOG_FATAL, "config", "The given config file %s could not be accessed, " SLAPI_COMPONENT_NAME_NSPR " error %d (%s)\n",
+ configfile, prerr, slapd_pr_strerror(prerr));
+ rc = 0; /* Fail */
+ }
+ else if (( prfd = PR_Open( configfile, PR_RDONLY,
+ SLAPD_DEFAULT_FILE_MODE )) == NULL )
+ {
+ PRErrorCode prerr = PR_GetError();
+ slapi_log_error(SLAPI_LOG_FATAL, "config", "The given config file %s could not be opened for reading, " SLAPI_COMPONENT_NAME_NSPR " error %d (%s)\n",
+ configfile, prerr, slapd_pr_strerror(prerr));
+ rc = 0; /* Fail */
+ }
+ else
+ {
+ /* read the entire file into core */
+ buf = slapi_ch_malloc( prfinfo.size + 1 );
+ if (( nr = slapi_read_buffer( prfd, buf, prfinfo.size )) < 0 )
+ {
+ slapi_log_error(SLAPI_LOG_FATAL, "config", "Could only read %d of %d bytes from config file %s\n",
+ nr, prfinfo.size, configfile);
+ rc = 0; /* Fail */
+ done= 1;
+ }
+
+ (void)PR_Close(prfd);
+ buf[ nr ] = '\0';
+
+ if(!done)
+ {
+ char errorlog[MAXPATHLEN+1];
+ char loglevel[BUFSIZ];
+ char maxdescriptors[BUFSIZ];
+ char val[BUFSIZ];
+ char logenabled[BUFSIZ];
+ char schemacheck[BUFSIZ];
+ Slapi_DN plug_dn;
+
+ errorlog[0] = loglevel[0] = maxdescriptors[0] = '\0';
+ val[0] = logenabled[0] = schemacheck[0] = '\0';
+
+ /* Convert LDIF to entry structures */
+ slapi_sdn_init_dn_byref(&plug_dn, PLUGIN_BASE_DN);
+ while ((entrystr = dse_read_next_entry(buf, &lastp)) != NULL)
+ {
+ char errorbuf[BUFSIZ];
+ /*
+ * XXXmcs: it would be better to also pass
+ * SLAPI_STR2ENTRY_REMOVEDUPVALS in the flags, but
+ * duplicate value checking requires that the syntax
+ * and schema subsystems be initialized... and they
+ * are not yet.
+ */
+ Slapi_Entry *e = slapi_str2entry(entrystr,
+ SLAPI_STR2ENTRY_NOT_WELL_FORMED_LDIF);
+ if (e == NULL)
+ {
+ LDAPDebug(LDAP_DEBUG_ANY, "The entry [%s] in the configfile %s was empty or could not be parsed\n",
+ entrystr, configfile, 0);
+ continue;
+ }
+
+ /* increase file descriptors */
+#if !defined(_WIN32) && !defined(AIX)
+ if (!maxdescriptors[0] &&
+ entry_has_attr_and_value(e, CONFIG_MAXDESCRIPTORS_ATTRIBUTE,
+ maxdescriptors, sizeof(maxdescriptors)))
+ {
+ if (config_set_maxdescriptors(
+ CONFIG_MAXDESCRIPTORS_ATTRIBUTE,
+ maxdescriptors, errorbuf, CONFIG_APPLY)
+ != LDAP_SUCCESS)
+ {
+ LDAPDebug(LDAP_DEBUG_ANY, "%s: %s: %s\n", configfile,
+ CONFIG_MAXDESCRIPTORS_ATTRIBUTE, errorbuf);
+ }
+ }
+#endif /* !defined(_WIN32) && !defined(AIX) */
+
+ /* see if we need to enable error logging */
+ if (!logenabled[0] &&
+ entry_has_attr_and_value(e,
+ CONFIG_ERRORLOG_LOGGING_ENABLED_ATTRIBUTE,
+ logenabled, sizeof(logenabled)))
+ {
+ if (log_set_logging(
+ CONFIG_ERRORLOG_LOGGING_ENABLED_ATTRIBUTE,
+ logenabled, SLAPD_ERROR_LOG, errorbuf, CONFIG_APPLY)
+ != LDAP_SUCCESS)
+ {
+ LDAPDebug(LDAP_DEBUG_ANY, "%s: %s: %s\n", configfile,
+ CONFIG_ERRORLOG_LOGGING_ENABLED_ATTRIBUTE, errorbuf);
+ }
+ }
+
+ /* set the log file name */
+ if (!errorlog[0] &&
+ entry_has_attr_and_value(e, CONFIG_ERRORLOG_ATTRIBUTE,
+ errorlog, sizeof(errorlog)))
+ {
+ if (config_set_errorlog(CONFIG_ERRORLOG_ATTRIBUTE,
+ errorlog, errorbuf, CONFIG_APPLY) != LDAP_SUCCESS)
+ {
+ LDAPDebug(LDAP_DEBUG_ANY, "%s: %s: %s. \n", configfile,
+ CONFIG_ERRORLOG_ATTRIBUTE, errorbuf);
+ }
+ }
+
+ /* set the error log level */
+ if (!loglevel[0] &&
+ entry_has_attr_and_value(e, CONFIG_LOGLEVEL_ATTRIBUTE,
+ loglevel, sizeof(loglevel)))
+ {
+ if (should_detach || !config_get_errorlog_level())
+ { /* -d wasn't on command line */
+ if (config_set_errorlog_level(CONFIG_LOGLEVEL_ATTRIBUTE,
+ loglevel, errorbuf, CONFIG_APPLY) != LDAP_SUCCESS)
+ {
+ LDAPDebug(LDAP_DEBUG_ANY, "%s: %s: %s. \n", configfile,
+ CONFIG_LOGLEVEL_ATTRIBUTE, errorbuf);
+ }
+ }
+ else
+ {
+ LDAPDebug(LDAP_DEBUG_ANY,
+ "%s: ignoring %s (since -d %d was given on "
+ "the command line)\n",
+ CONFIG_LOGLEVEL_ATTRIBUTE, loglevel,
+ config_get_errorlog_level());
+ }
+ }
+
+ /* see if the entry is a child of the plugin base dn */
+ if (slapi_sdn_isparent(&plug_dn,
+ slapi_entry_get_sdn_const(e)))
+ {
+ if (entry_has_attr_and_value(e, "objectclass",
+ "nsSlapdPlugin", 0) &&
+ (entry_has_attr_and_value(e, ATTR_PLUGIN_TYPE,
+ "syntax", 0) ||
+ entry_has_attr_and_value(e, ATTR_PLUGIN_TYPE,
+ "matchingrule", 0)))
+ {
+ /* add the syntax/matching scheme rule plugin */
+ if (plugin_setup(e, 0, 0, 1))
+ {
+ LDAPDebug(LDAP_DEBUG_ANY, "The plugin entry [%s] in the configfile %s was invalid\n", slapi_entry_get_dn(e), configfile, 0);
+ rc = 0;
+ goto bail;
+ }
+ }
+ }
+ /* see if the entry is a grand child of the plugin base dn */
+ if (slapi_sdn_isgrandparent(&plug_dn,
+ slapi_entry_get_sdn_const(e)))
+ {
+ if (entry_has_attr_and_value(e, "objectclass",
+ "nsSlapdPlugin", 0) &&
+ ( entry_has_attr_and_value(e, ATTR_PLUGIN_TYPE,
+ "pwdstoragescheme", 0) ||
+ entry_has_attr_and_value(e, ATTR_PLUGIN_TYPE,
+ "reverpwdstoragescheme", 0) ) )
+ {
+ /* add the pwd storage scheme rule plugin */
+ if (plugin_setup(e, 0, 0, 1))
+ {
+ LDAPDebug(LDAP_DEBUG_ANY, "The plugin entry [%s] in the configfile %s was invalid\n", slapi_entry_get_dn(e), configfile, 0);
+ rc = 0;
+ goto bail;
+ }
+ }
+ }
+
+ /* see if we need to disable schema checking */
+ if (!schemacheck[0] &&
+ entry_has_attr_and_value(e, CONFIG_SCHEMACHECK_ATTRIBUTE,
+ schemacheck, sizeof(schemacheck)))
+ {
+ if (config_set_schemacheck(CONFIG_SCHEMACHECK_ATTRIBUTE,
+ schemacheck, errorbuf, CONFIG_APPLY)
+ != LDAP_SUCCESS)
+ {
+ LDAPDebug(LDAP_DEBUG_ANY, "%s: %s: %s\n", configfile,
+ CONFIG_SCHEMACHECK_ATTRIBUTE, errorbuf);
+ }
+ }
+
+ /* see if we need to expect quoted schema values */
+ if (entry_has_attr_and_value(e, CONFIG_ENQUOTE_SUP_OC_ATTRIBUTE,
+ val, sizeof(val)))
+ {
+ if (config_set_enquote_sup_oc(
+ CONFIG_ENQUOTE_SUP_OC_ATTRIBUTE, val, errorbuf,
+ CONFIG_APPLY) != LDAP_SUCCESS)
+ {
+ LDAPDebug(LDAP_DEBUG_ANY, "%s: %s: %s\n", configfile,
+ CONFIG_ENQUOTE_SUP_OC_ATTRIBUTE, errorbuf);
+ }
+ val[0] = 0;
+ }
+
+ /* see if we need to maintain case in AT and OC names */
+ if (entry_has_attr_and_value(e,
+ CONFIG_RETURN_EXACT_CASE_ATTRIBUTE, val, sizeof(val)))
+ {
+ if (config_set_return_exact_case(
+ CONFIG_RETURN_EXACT_CASE_ATTRIBUTE, val,
+ errorbuf, CONFIG_APPLY) != LDAP_SUCCESS)
+ {
+ LDAPDebug(LDAP_DEBUG_ANY, "%s: %s: %s\n", configfile,
+ CONFIG_RETURN_EXACT_CASE_ATTRIBUTE, errorbuf);
+ }
+ val[0] = 0;
+ }
+
+ /* see if we should allow attr. name exceptions, e.g. '_'s */
+ if (entry_has_attr_and_value(e,
+ CONFIG_ATTRIBUTE_NAME_EXCEPTION_ATTRIBUTE,
+ val, sizeof(val)))
+ {
+ if (config_set_attrname_exceptions(
+ CONFIG_ATTRIBUTE_NAME_EXCEPTION_ATTRIBUTE, val,
+ errorbuf, CONFIG_APPLY) != LDAP_SUCCESS)
+ {
+ LDAPDebug(LDAP_DEBUG_ANY, "%s: %s: %s\n", configfile,
+ CONFIG_ATTRIBUTE_NAME_EXCEPTION_ATTRIBUTE,
+ errorbuf);
+ }
+ val[0] = 0;
+ }
+
+ /* see if we need to maintain schema compatibility with 4.x */
+ if (entry_has_attr_and_value(e,
+ CONFIG_DS4_COMPATIBLE_SCHEMA_ATTRIBUTE, val, sizeof(val)))
+ {
+ if (config_set_ds4_compatible_schema(
+ CONFIG_DS4_COMPATIBLE_SCHEMA_ATTRIBUTE, val,
+ errorbuf, CONFIG_APPLY) != LDAP_SUCCESS)
+ {
+ LDAPDebug(LDAP_DEBUG_ANY, "%s: %s: %s\n", configfile,
+ CONFIG_DS4_COMPATIBLE_SCHEMA_ATTRIBUTE,
+ errorbuf);
+ }
+ val[0] = 0;
+ }
+
+ /* see if we need to allow trailing spaces in OC and AT names */
+ if (entry_has_attr_and_value(e,
+ CONFIG_SCHEMA_IGNORE_TRAILING_SPACES, val, sizeof(val)))
+ {
+ if (config_set_schema_ignore_trailing_spaces(
+ CONFIG_SCHEMA_IGNORE_TRAILING_SPACES, val,
+ errorbuf, CONFIG_APPLY) != LDAP_SUCCESS)
+ {
+ LDAPDebug(LDAP_DEBUG_ANY, "%s: %s: %s\n", configfile,
+ CONFIG_SCHEMA_IGNORE_TRAILING_SPACES,
+ errorbuf);
+ }
+ val[0] = 0;
+ }
+
+ /* rfc1274-rewrite */
+ if (entry_has_attr_and_value(e,
+ CONFIG_REWRITE_RFC1274_ATTRIBUTE,
+ val, sizeof(val))) {
+ if (config_set_rewrite_rfc1274(
+ CONFIG_REWRITE_RFC1274_ATTRIBUTE, val,
+ errorbuf, CONFIG_APPLY) != LDAP_SUCCESS) {
+ LDAPDebug(LDAP_DEBUG_ANY, "%s: %s: %s\n",
+ configfile,
+ CONFIG_REWRITE_RFC1274_ATTRIBUTE,
+ errorbuf);
+ }
+ }
+
+ if (e)
+ slapi_entry_free(e);
+ }
+
+ /* kexcoff: initialize rootpwstoragescheme and pw_storagescheme
+ * if not explicilty set in the config file
+ */
+ if ( config_set_storagescheme() ) { /* default scheme plugin not loaded */
+ slapi_log_error(SLAPI_LOG_FATAL, "startup",
+ "The default password storage scheme SSHA could not be read or was not found in the file %s. It is mandatory.\n",
+ configfile);
+ exit (1);
+ }
+ else {
+ slapi_sdn_done(&plug_dn);
+ rc= 1; /* OK */
+ }
+ }
+
+ slapi_ch_free((void **)&buf);
+ }
+
+bail:
+ return rc;
+}
+