/* * 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 Sun Microsystems, Inc. */ package org.opends.server.core; import static org.opends.server.config.ConfigConstants.*; import static org.opends.server.loggers.Debug.*; import static org.opends.server.loggers.Error.*; import static org.opends.server.messages.ConfigMessages.*; import static org.opends.server.messages.MessageHandler.*; import static org.opends.server.util.StaticUtils.*; import java.util.ArrayList; import java.util.concurrent.atomic.AtomicReference; import org.opends.server.api.AccessControlHandler; import org.opends.server.api.AccessControlProvider; import org.opends.server.api.ConfigChangeListener; import org.opends.server.config.BooleanConfigAttribute; import org.opends.server.config.ConfigEntry; import org.opends.server.config.ConfigException; import org.opends.server.config.StringConfigAttribute; 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 {
// Fully qualified class name for debugging purposes.
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() {
assert debugEnter(CLASS_NAME, "isEnabled");
return currentConfiguration.isEnabled();
}
/**
* Get the active access control handler.
* null).
*/
public AccessControlHandler getAccessControlHandler() {
assert debugEnter(CLASS_NAME, "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 {
assert debugEnter(CLASS_NAME, "initializeAccessControl");
// Get the access control handler configuration entry.
ConfigEntry configEntry;
try {
DN configEntryDN = DN.decode(DN_AUTHZ_HANDLER_CONFIG);
configEntry = DirectoryServer.getConfigEntry(configEntryDN);
} catch (Exception e) {
assert debugException(CLASS_NAME,
"initializeAccessControlConfigManager", e);
int msgID = MSGID_CONFIG_AUTHZ_CANNOT_GET_ENTRY;
String message = getMessage(msgID,
stackTraceToSingleLineString(e));
throw new ConfigException(msgID, message, e);
}
// The access control handler entry must exist.
if (configEntry == null) {
int msgID = MSGID_CONFIG_AUTHZ_ENTRY_DOES_NOT_EXIST;
String message = getMessage(msgID);
throw new ConfigException(msgID, message);
}
// Parse the configuration entry.
Configuration configuration = Configuration
.readConfiguration(configEntry);
// We have a valid usable entry, so register a change listener in
// order to handle configuration changes.
configEntry.registerChangeListener(new ChangeListener());
// The configuration looks valid, so install it.
updateConfiguration(configuration);
}
/**
* Creates a new instance of this access control configuration
* manager.
*/
private AccessControlConfigManager() {
assert debugConstructor(CLASS_NAME);
this.accessControlProvider = new AtomicReferencetrue if access control is enabled,
* false otherwise.
*/
public boolean isEnabled() {
assert debugEnter(CLASS_NAME, "isEnabled");
return enabled;
}
/**
* Get the access control provider class specified in the
* configuration.
*
* @return Returns the {@link AccessControlProvider} class.
*/
public Class extends AccessControlProvider> getProviderClass() {
assert debugEnter(CLASS_NAME, "getProviderClass");
return providerClass;
}
/**
* Get the configuration entry associated with this configuration
* object.
*
* @return Returns the configuration entry.
*/
public ConfigEntry getConfigEntry() {
assert debugEnter(CLASS_NAME, "getConfigEntry");
return configEntry;
}
/**
* Construct a new configuration object with the specified parsed
* attribute values.
*
* @param configEntry
* The associated access control configuration entry.
* @param enabled
* The value of the enabled attribute.
* @param providerClass
* The access control provider class.
*/
private Configuration(ConfigEntry configEntry, boolean enabled,
Class extends AccessControlProvider> providerClass) {
assert debugConstructor(CLASS_NAME);
this.configEntry = configEntry;
this.enabled = enabled;
this.providerClass = providerClass;
}
/**
* Read the value of the attribute which indicates whether or not
* access control is enabled.
*
* @param configEntry
* The access control configuration entry.
* @return The boolean value of the enabled attribute.
* @throws ConfigException
* If the enabled attribute could not be read or if it
* contains an invalid value.
*/
private static boolean getEnabledAttribute(ConfigEntry configEntry)
throws ConfigException {
assert debugEnter(CLASS_NAME, "getEnabledAttribute");
// See if the entry contains an attribute that indicates whether
// or not access control should be enabled.
try {
BooleanConfigAttribute enabledAttrStub = new BooleanConfigAttribute(
ATTR_AUTHZ_HANDLER_ENABLED,
getMessage(MSGID_CONFIG_AUTHZ_DESCRIPTION_ENABLED), false);
BooleanConfigAttribute enabledAttr = (BooleanConfigAttribute)
configEntry.getConfigAttribute(enabledAttrStub);
if (enabledAttr == null) {
int msgID = MSGID_CONFIG_AUTHZ_NO_ENABLED_ATTR;
String message = getMessage(msgID, configEntry.getDN()
.toString());
throw new ConfigException(msgID, message);
} else {
// We have a valid attribute - return it.
return enabledAttr.activeValue();
}
} catch (ConfigException e) {
int msgID = MSGID_CONFIG_AUTHZ_UNABLE_TO_DETERMINE_ENABLED_STATE;
String message = getMessage(msgID, configEntry.getDN()
.toString(), stackTraceToSingleLineString(e));
throw new ConfigException(msgID, message, e);
}
}
/**
* 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 configEntry
* The access control configuration entry.
* @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(
ConfigEntry configEntry) throws ConfigException {
assert debugEnter(CLASS_NAME, "getClassAttribute");
// If access control is enabled then make sure that the class
// attribute is present.
try {
StringConfigAttribute classAttrStub = new StringConfigAttribute(
ATTR_AUTHZ_HANDLER_CLASS,
getMessage(MSGID_CONFIG_AUTHZ_DESCRIPTION_CLASS), true,
false, false);
StringConfigAttribute classAttr = (StringConfigAttribute) configEntry
.getConfigAttribute(classAttrStub);
if (classAttr == null) {
int msgID = MSGID_CONFIG_AUTHZ_NO_CLASS_ATTR;
String message = getMessage(msgID, configEntry.getDN()
.toString());
throw new ConfigException(msgID, message);
}
// Load the access control implementation class.
String className = classAttr.activeValue();
try {
return Class.forName(className).asSubclass(
AccessControlProvider.class);
} catch (ClassNotFoundException e) {
assert debugException(CLASS_NAME, "updateConfiguration", e);
int msgID = MSGID_CONFIG_AUTHZ_UNABLE_TO_LOAD_CLASS;
String message = getMessage(msgID, className, String
.valueOf(configEntry.getDN().toString()),
stackTraceToSingleLineString(e));
throw new ConfigException(msgID, message, e);
} catch (ClassCastException e) {
assert debugException(CLASS_NAME, "updateConfiguration", e);
int msgID = MSGID_CONFIG_AUTHZ_BAD_CLASS;
String message = getMessage(msgID, className, String
.valueOf(configEntry.getDN().toString()),
AccessControlProvider.class.getName(),
stackTraceToSingleLineString(e));
throw new ConfigException(msgID, message, e);
}
} catch (ConfigException e) {
int msgID = MSGID_CONFIG_AUTHZ_UNABLE_TO_DETERMINE_CLASS;
String message = getMessage(msgID, configEntry.getDN()
.toString(), stackTraceToSingleLineString(e));
throw new ConfigException(msgID, message, e);
}
}
}
}