/* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License, Version 1.0 only * (the "License"). You may not use this file except in compliance * with the License. * * You can obtain a copy of the license at * trunk/opends/resource/legal-notices/OpenDS.LICENSE * or https://OpenDS.dev.java.net/OpenDS.LICENSE. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at * trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable, * add the following below this CDDL HEADER, with the fields enclosed * by brackets "[]" replaced with your own identifying information: * Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END * * * Portions Copyright 2006-2007 Sun Microsystems, Inc. */ package org.opends.server.core; import org.opends.server.types.DebugLogLevel; import static org.opends.server.loggers.ErrorLogger.*; import static org.opends.server.loggers.debug.DebugLogger.*; import org.opends.server.loggers.debug.DebugTracer; import static org.opends.server.messages.ConfigMessages.*; import static org.opends.server.messages.MessageHandler.*; import static org.opends.server.util.ServerConstants.*; import static org.opends.server.util.StaticUtils.*; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.LinkedHashMap; import java.util.List; import java.util.concurrent.atomic.AtomicReference; import org.opends.server.admin.ClassPropertyDefinition; import org.opends.server.admin.server.ConfigurationChangeListener; import org.opends.server.admin.server.ServerManagementContext; import org.opends.server.admin.std.meta.AccessControlHandlerCfgDefn; import org.opends.server.admin.std.server.AccessControlHandlerCfg; import org.opends.server.admin.std.server.RootCfg; import org.opends.server.api.AccessControlHandler; import org.opends.server.api.AccessControlProvider; import org.opends.server.api.AlertGenerator; import org.opends.server.config.ConfigException; import org.opends.server.types.ConfigChangeResult; 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.ResultCode; /** * This class manages the application-wide access-control configuration. *
* When access control is disabled a default "permissive" access control
* implementation is used, which permits all operations regardless of
* the identity of the user.
*/
public final class AccessControlConfigManager
implements AlertGenerator
{
/**
* The tracer object for the debug logger.
*/
private static final DebugTracer TRACER = getTracer();
// Fully qualified class name.
private static final String CLASS_NAME =
"org.opends.server.core.AccessControlConfigManager";
// The single application-wide instance.
private static AccessControlConfigManager instance = null;
// The active access control implementation.
private AtomicReference
* When access control is disabled, this method returns a default
* access control implementation which permits all operations.
*
* @return Returns the active access control handler (never
* true if access control is enabled,
* false otherwise.
*/
public boolean isAccessControlEnabled() {
return currentConfiguration.isEnabled();
}
/**
* Get the active access control handler.
* null).
*/
public AccessControlHandler getAccessControlHandler() {
return accessControlProvider.get().getInstance();
}
/**
* Initializes the access control sub-system. This should only be
* called at Directory Server startup. If an error occurs then an
* exception will be thrown and the Directory Server will fail to
* start (this prevents accidental exposure of user data due to
* misconfiguration).
*
* @throws ConfigException
* If an access control configuration error is detected.
* @throws InitializationException
* If a problem occurs while initializing the access control
* handler that is not related to the Directory Server
* configuration.
*/
void initializeAccessControl() throws ConfigException,
InitializationException {
// Get the root configuration object.
ServerManagementContext managementContext =
ServerManagementContext.getInstance();
RootCfg rootConfiguration =
managementContext.getRootConfiguration();
// Don't register as an add and delete listener with the root configuration
// as we can have only one object at a given time.
// //Initialize the current Access control.
AccessControlHandlerCfg accessControlConfiguration =
rootConfiguration.getAccessControlHandler();
// Parse the configuration entry.
PrivateACLConfiguration configuration = PrivateACLConfiguration
.readConfiguration(accessControlConfiguration);
// We have a valid usable entry, so register a change listener in
// order to handle configuration changes.
accessControlConfiguration.addChangeListener(new ChangeListener());
// The configuration looks valid, so install it.
updateConfiguration(configuration);
}
/**
* Creates a new instance of this access control configuration
* manager.
*/
private AccessControlConfigManager() {
this.accessControlProvider = new AtomicReferencetrue if access control is enabled,
* false otherwise.
*/
public boolean isEnabled() {
return enabled;
}
/**
* Get the access control provider class specified in the
* configuration.
*
* @return Returns the {@link AccessControlProvider} class.
*/
public Class extends AccessControlProvider> getProviderClass() {
return providerClass;
}
/**
* Get the configuration entry associated with this configuration
* object.
*
* @return Returns the configuration entry.
*/
public AccessControlHandlerCfg getConfiguration() {
return configuration;
}
/**
* Construct a new configuration object with the specified parsed
* attribute values.
*
* @param configuration
* The associated access control configuration entry.
* @param enabled
* The value of the enabled attribute.
* @param providerClass
* The access control provider class.
*/
private PrivateACLConfiguration(
AccessControlHandlerCfg configuration, boolean enabled,
Class extends AccessControlProvider> providerClass) {
this.configuration = configuration;
this.enabled = enabled;
this.providerClass = providerClass;
}
/**
* Read the value of the attribute which indicates which access
* control implementation class to use. This method checks the
* validity of the class name.
*
* @param configuration
* The access control configuration.
* @return The access control provider class.
* @throws ConfigException
* If the class attribute could not be read or if it
* contains an invalid class name.
*/
private static Class extends AccessControlProvider> getClassAttribute(
AccessControlHandlerCfg configuration) throws ConfigException {
// If access control is enabled then make sure that the class
// attribute is present.
try {
// Load the access control implementation class.
String className = configuration.getAclHandlerClass();
try {
return DirectoryServer.loadClass(className).asSubclass(
AccessControlProvider.class);
} catch (ClassNotFoundException e) {
if (debugEnabled())
{
TRACER.debugCaught(DebugLogLevel.ERROR, e);
}
int msgID = MSGID_CONFIG_AUTHZ_UNABLE_TO_LOAD_CLASS;
String message = getMessage(msgID, className, String
.valueOf(configuration.dn().toString()),
getExceptionMessage(e));
throw new ConfigException(msgID, message, e);
} catch (ClassCastException e) {
if (debugEnabled())
{
TRACER.debugCaught(DebugLogLevel.ERROR, e);
}
int msgID = MSGID_CONFIG_AUTHZ_BAD_CLASS;
String message = getMessage(msgID, className, String
.valueOf(configuration.dn().toString()),
AccessControlProvider.class.getName(),
getExceptionMessage(e));
throw new ConfigException(msgID, message, e);
}
} catch (ConfigException e) {
int msgID = MSGID_CONFIG_AUTHZ_UNABLE_TO_DETERMINE_CLASS;
String message = getMessage(msgID, configuration.dn()
.toString(), getExceptionMessage(e));
throw new ConfigException(msgID, message, e);
}
}
}
/**
* Retrieves the DN of the configuration entry with which this alert
* generator is associated.
*
* @return The DN of the configuration entry with which this alert
* generator is associated.
*/
public DN getComponentEntryDN()
{
return currentConfiguration.getConfiguration().dn();
}
/**
* Retrieves the fully-qualified name of the Java class for this
* alert generator implementation.
*
* @return The fully-qualified name of the Java class for this
* alert generator implementation.
*/
public String getClassName()
{
return CLASS_NAME;
}
/**
* Retrieves information about the set of alerts that this generator
* may produce. The map returned should be between the notification
* type for a particular notification and the human-readable
* description for that notification. This alert generator must not
* generate any alerts with types that are not contained in this
* list.
*
* @return Information about the set of alerts that this generator
* may produce.
*/
public LinkedHashMap