From ed39262fa647434d4a0e31f07754a263ce2b16e3 Mon Sep 17 00:00:00 2001
From: neil_a_wilson <neil_a_wilson@localhost>
Date: Fri, 09 Feb 2007 21:51:09 +0000
Subject: [PATCH] Add an initial set of privilege support to OpenDS. The current privileges are currently defined and implemented: * config-read (allow reading the configuration) * config-write (allow updating the configuration) * ldif-import (allow invoking LDIF import tasks) * ldif-export (allow invoking LDIF export tasks) * backend-backup (allow invoking backup tasks) * backend-restore (allow invoking restore tasks) * server-shutdown (allow invoking server shutdown tasks) * server-restart (allow invoking server restart tasks) * server-restart (allow invoking server restart tasks) * password-reset (allow resetting user passwords) * update-schema (allow updating the server schema) * privilege-change (allow changing the set of privileges for a user)
---
opends/src/server/org/opends/server/core/RootDNConfigManager.java | 312 +++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 307 insertions(+), 5 deletions(-)
diff --git a/opends/src/server/org/opends/server/core/RootDNConfigManager.java b/opends/src/server/org/opends/server/core/RootDNConfigManager.java
index d4c9d95..0affa1e 100644
--- a/opends/src/server/org/opends/server/core/RootDNConfigManager.java
+++ b/opends/src/server/org/opends/server/core/RootDNConfigManager.java
@@ -22,7 +22,7 @@
* CDDL HEADER END
*
*
- * Portions Copyright 2006 Sun Microsystems, Inc.
+ * Portions Copyright 2006-2007 Sun Microsystems, Inc.
*/
package org.opends.server.core;
@@ -30,22 +30,29 @@
import java.util.ArrayList;
import java.util.Iterator;
+import java.util.LinkedHashSet;
+import java.util.LinkedList;
import java.util.List;
+import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import org.opends.server.api.ConfigAddListener;
import org.opends.server.api.ConfigChangeListener;
import org.opends.server.api.ConfigDeleteListener;
import org.opends.server.api.ConfigHandler;
+import org.opends.server.api.ConfigurableComponent;
+import org.opends.server.config.ConfigAttribute;
import org.opends.server.config.ConfigEntry;
import org.opends.server.config.ConfigException;
import org.opends.server.config.DNConfigAttribute;
+import org.opends.server.config.MultiChoiceConfigAttribute;
import org.opends.server.types.ConfigChangeResult;
import org.opends.server.types.DirectoryException;
import org.opends.server.types.DN;
import org.opends.server.types.ErrorLogCategory;
import org.opends.server.types.ErrorLogSeverity;
import org.opends.server.types.InitializationException;
+import org.opends.server.types.Privilege;
import org.opends.server.types.ResultCode;
import static org.opends.server.config.ConfigConstants.*;
@@ -66,7 +73,8 @@
* DN for use when binding to the server.
*/
public class RootDNConfigManager
- implements ConfigChangeListener, ConfigAddListener, ConfigDeleteListener
+ implements ConfigChangeListener, ConfigAddListener, ConfigDeleteListener,
+ ConfigurableComponent
{
/**
* The fully-qualified name of this class for debugging purposes.
@@ -80,6 +88,13 @@
// bind DNs for that user.
private ConcurrentHashMap<DN,List<DN>> bindMappings;
+ // The DN of the entry that serves as the base for the root DN
+ // configuration entries.
+ private DN rootDNConfigBaseDN;
+
+ // The set of privileges that will be automatically inherited by root users.
+ private LinkedHashSet<Privilege> rootPrivileges;
+
/**
@@ -116,8 +131,8 @@
ConfigEntry baseEntry;
try
{
- DN configBase = DN.decode(DN_ROOT_DN_CONFIG_BASE);
- baseEntry = configHandler.getConfigEntry(configBase);
+ rootDNConfigBaseDN = DN.decode(DN_ROOT_DN_CONFIG_BASE);
+ baseEntry = configHandler.getConfigEntry(rootDNConfigBaseDN);
}
catch (Exception e)
{
@@ -136,11 +151,62 @@
}
+ // Get the set of privileges that root users should have by default.
+ rootPrivileges = new LinkedHashSet<Privilege>(
+ Privilege.getDefaultRootPrivileges());
+
+ int msgID = MSGID_CONFIG_ROOTDN_DESCRIPTION_ROOT_PRIVILEGE;
+ MultiChoiceConfigAttribute rootPrivStub =
+ new MultiChoiceConfigAttribute(ATTR_DEFAULT_ROOT_PRIVILEGE_NAME,
+ getMessage(msgID), false, true, false,
+ Privilege.getPrivilegeNames());
+ try
+ {
+ MultiChoiceConfigAttribute rootPrivAttr =
+ (MultiChoiceConfigAttribute)
+ baseEntry.getConfigAttribute(rootPrivStub);
+ if (rootPrivAttr != null)
+ {
+ ArrayList<Privilege> privList = new ArrayList<Privilege>();
+ for (String value : rootPrivAttr.activeValues())
+ {
+ String privName = toLowerCase(value);
+ Privilege p = Privilege.privilegeForName(privName);
+ if (p == null)
+ {
+ msgID = MSGID_CONFIG_ROOTDN_UNRECOGNIZED_PRIVILEGE;
+ String message = getMessage(msgID, ATTR_DEFAULT_ROOT_PRIVILEGE_NAME,
+ String.valueOf(rootDNConfigBaseDN),
+ String.valueOf(value));
+ logError(ErrorLogCategory.CONFIGURATION,
+ ErrorLogSeverity.SEVERE_WARNING, message, msgID);
+ }
+ else
+ {
+ privList.add(p);
+ }
+ }
+
+ rootPrivileges = new LinkedHashSet<Privilege>(privList);
+ }
+ }
+ catch (Exception e)
+ {
+ assert debugException(CLASS_NAME, "initializeRootDNs", e);
+
+ msgID = MSGID_CONFIG_ROOTDN_ERROR_DETERMINING_ROOT_PRIVILEGES;
+ String message = getMessage(msgID, stackTraceToSingleLineString(e));
+ throw new InitializationException(msgID, message, e);
+ }
+
+
// Register with the configuration base entry as an add and delete listener.
// So that we will be notified of attempts to create or remove root DN
- // entries.
+ // entries. Also, register with the server as a configurable component so
+ // that we can detect and apply any changes to the root
baseEntry.registerAddListener(this);
baseEntry.registerDeleteListener(this);
+ DirectoryServer.registerConfigurableComponent(this);
// See if the base entry has any children. If not, then we don't need to
@@ -206,6 +272,22 @@
/**
+ * Retrieves the set of privileges that should automatically be granted to
+ * root users when they authenticate.
+ *
+ * @return The set of privileges that should automatically be granted to root
+ * users when they authenticate.
+ */
+ public Set<Privilege> getRootPrivileges()
+ {
+ assert debugEnter(CLASS_NAME, "getRootPrivileges");
+
+ return rootPrivileges;
+ }
+
+
+
+ /**
* Indicates whether the configuration entry that will result from a proposed
* modification is acceptable to this change listener.
*
@@ -638,5 +720,225 @@
return new ConfigChangeResult(resultCode, adminActionRequired);
}
+
+
+
+ /**
+ * Retrieves the DN of the configuration entry with which this
+ * component is associated.
+ *
+ * @return The DN of the configuration entry with which this
+ * component is associated.
+ */
+ public DN getConfigurableComponentEntryDN()
+ {
+ assert debugEnter(CLASS_NAME, "getConfigurableComponentEntryDN");
+
+ return rootDNConfigBaseDN;
+ }
+
+
+
+ /**
+ * Retrieves the set of configuration attributes that are associated
+ * with this configurable component.
+ *
+ * @return The set of configuration attributes that are associated
+ * with this configurable component.
+ */
+ public List<ConfigAttribute> getConfigurationAttributes()
+ {
+ assert debugEnter(CLASS_NAME, "getConfigurationAttributes");
+
+ LinkedList<ConfigAttribute> attrList = new LinkedList<ConfigAttribute>();
+
+ LinkedList<String> currentValues = new LinkedList<String>();
+ for (Privilege p : rootPrivileges)
+ {
+ currentValues.add(p.getName());
+ }
+
+ int msgID = MSGID_CONFIG_ROOTDN_DESCRIPTION_ROOT_PRIVILEGE;
+ attrList.add(new MultiChoiceConfigAttribute(
+ ATTR_DEFAULT_ROOT_PRIVILEGE_NAME, getMessage(msgID),
+ false, true, false, Privilege.getPrivilegeNames(),
+ currentValues));
+
+ return attrList;
+ }
+
+
+
+ /**
+ * Indicates whether the provided configuration entry has an
+ * acceptable configuration for this component. If it does not,
+ * then detailed information about the problem(s) should be added to
+ * the provided list.
+ *
+ * @param configEntry The configuration entry for which to
+ * make the determination.
+ * @param unacceptableReasons A list that can be used to hold
+ * messages about why the provided
+ * entry does not have an acceptable
+ * configuration.
+ *
+ * @return <CODE>true</CODE> if the provided entry has an
+ * acceptable configuration for this component, or
+ * <CODE>false</CODE> if not.
+ */
+ public boolean hasAcceptableConfiguration(ConfigEntry configEntry,
+ List<String> unacceptableReasons)
+ {
+ assert debugEnter(CLASS_NAME, "hasAcceptableConfiguration",
+ String.valueOf(configEntry), "List<String>");
+
+
+ int msgID = MSGID_CONFIG_ROOTDN_DESCRIPTION_ROOT_PRIVILEGE;
+ MultiChoiceConfigAttribute rootPrivStub =
+ new MultiChoiceConfigAttribute(ATTR_DEFAULT_ROOT_PRIVILEGE_NAME,
+ getMessage(msgID), false, true, false,
+ Privilege.getPrivilegeNames());
+ try
+ {
+ MultiChoiceConfigAttribute rootPrivAttr =
+ (MultiChoiceConfigAttribute)
+ configEntry.getConfigAttribute(rootPrivStub);
+ if (rootPrivAttr != null)
+ {
+ for (String value : rootPrivAttr.activeValues())
+ {
+ String privName = toLowerCase(value);
+ Privilege p = Privilege.privilegeForName(privName);
+ if (p == null)
+ {
+ msgID = MSGID_CONFIG_ROOTDN_UNRECOGNIZED_PRIVILEGE;
+ String message = getMessage(msgID, ATTR_DEFAULT_ROOT_PRIVILEGE_NAME,
+ String.valueOf(rootDNConfigBaseDN),
+ String.valueOf(value));
+ unacceptableReasons.add(message);
+ return false;
+ }
+ }
+ }
+ }
+ catch (Exception e)
+ {
+ assert debugException(CLASS_NAME, "initializeRootDNs", e);
+
+ msgID = MSGID_CONFIG_ROOTDN_ERROR_DETERMINING_ROOT_PRIVILEGES;
+ String message = getMessage(msgID, stackTraceToSingleLineString(e));
+ unacceptableReasons.add(message);
+ return false;
+ }
+
+
+ // If we've gotten here, then everything looks OK.
+ return true;
+ }
+
+
+
+ /**
+ * Makes a best-effort attempt to apply the configuration contained
+ * in the provided entry. Information about the result of this
+ * processing should be added to the provided message list.
+ * Information should always be added to this list if a
+ * configuration change could not be applied. If detailed results
+ * are requested, then information about the changes applied
+ * successfully (and optionally about parameters that were not
+ * changed) should also be included.
+ *
+ * @param configEntry The entry containing the new
+ * configuration to apply for this
+ * component.
+ * @param detailedResults Indicates whether detailed information
+ * about the processing should be added to
+ * the list.
+ *
+ * @return Information about the result of the configuration
+ * update.
+ */
+ public ConfigChangeResult applyNewConfiguration(ConfigEntry configEntry,
+ boolean detailedResults)
+ {
+ assert debugEnter(CLASS_NAME, "applyNewConfiguration",
+ String.valueOf(configEntry),
+ String.valueOf(detailedResults));
+
+
+ ResultCode resultCode = ResultCode.SUCCESS;
+ ArrayList<String> messages = new ArrayList<String>();
+ boolean adminActionRequired = false;
+
+
+ LinkedHashSet<Privilege> newRootPrivileges =
+ new LinkedHashSet<Privilege>(Privilege.getDefaultRootPrivileges());
+
+ int msgID = MSGID_CONFIG_ROOTDN_DESCRIPTION_ROOT_PRIVILEGE;
+ MultiChoiceConfigAttribute rootPrivStub =
+ new MultiChoiceConfigAttribute(ATTR_DEFAULT_ROOT_PRIVILEGE_NAME,
+ getMessage(msgID), false, true, false,
+ Privilege.getPrivilegeNames());
+ try
+ {
+ MultiChoiceConfigAttribute rootPrivAttr =
+ (MultiChoiceConfigAttribute)
+ configEntry.getConfigAttribute(rootPrivStub);
+ if (rootPrivAttr != null)
+ {
+ ArrayList<Privilege> privList = new ArrayList<Privilege>();
+ for (String value : rootPrivAttr.activeValues())
+ {
+ String privName = toLowerCase(value);
+ Privilege p = Privilege.privilegeForName(privName);
+ if (p == null)
+ {
+ if (resultCode == ResultCode.SUCCESS)
+ {
+ resultCode = ResultCode.INVALID_ATTRIBUTE_SYNTAX;
+ }
+
+ msgID = MSGID_CONFIG_ROOTDN_UNRECOGNIZED_PRIVILEGE;
+ messages.add(getMessage(msgID, ATTR_DEFAULT_ROOT_PRIVILEGE_NAME,
+ String.valueOf(rootDNConfigBaseDN),
+ String.valueOf(value)));
+ }
+ else
+ {
+ privList.add(p);
+ }
+ }
+
+ newRootPrivileges = new LinkedHashSet<Privilege>(privList);
+ }
+ }
+ catch (Exception e)
+ {
+ assert debugException(CLASS_NAME, "initializeRootDNs", e);
+
+ if (resultCode == ResultCode.SUCCESS)
+ {
+ resultCode = ResultCode.INVALID_ATTRIBUTE_SYNTAX;
+ }
+
+ msgID = MSGID_CONFIG_ROOTDN_ERROR_DETERMINING_ROOT_PRIVILEGES;
+ messages.add(getMessage(msgID, stackTraceToSingleLineString(e)));
+ }
+
+
+ if (resultCode == ResultCode.SUCCESS)
+ {
+ rootPrivileges = newRootPrivileges;
+
+ if (detailedResults)
+ {
+ msgID = MSGID_CONFIG_ROOTDN_UPDATED_PRIVILEGES;
+ messages.add(getMessage(msgID));
+ }
+ }
+
+
+ return new ConfigChangeResult(resultCode, adminActionRequired, messages);
+ }
}
--
Gitblit v1.10.0