/* * 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 legal-notices/CDDLv1_0.txt * or http://forgerock.org/license/CDDLv1.0.html. * 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 legal-notices/CDDLv1_0.txt. * 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 * * * Copyright 2006-2008 Sun Microsystems, Inc. * Portions Copyright 2014-2015 ForgeRock AS */ package org.opends.server.core; import static org.opends.messages.ConfigMessages.*; import static org.opends.server.util.ServerConstants.*; import static org.opends.server.util.StaticUtils.*; import java.util.ArrayList; import java.util.LinkedHashMap; import java.util.List; import java.util.concurrent.atomic.AtomicReference; import org.forgerock.i18n.LocalizableMessage; import org.forgerock.i18n.slf4j.LocalizedLogger; import org.forgerock.opendj.config.server.ConfigException; import org.forgerock.opendj.ldap.ResultCode; import org.forgerock.util.Utils; 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.AlertGenerator; import org.forgerock.opendj.config.server.ConfigChangeResult; import org.opends.server.types.DN; import org.opends.server.types.InitializationException; /** * 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 ,
ConfigurationChangeListener
* When access control is disabled, this method returns a default access
* control implementation which permits all operations.
*
* @return The active access control handler (never {@code null}).
*/
public AccessControlHandler> getAccessControlHandler()
{
return accessControlHandler.get();
}
/**
* 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).
*
* @param serverContext
* The server context.
* @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.
*/
public void initializeAccessControl(ServerContext serverContext)
throws ConfigException, InitializationException
{
this.serverContext = serverContext;
// 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();
// We have a valid usable entry, so register a change listener in
// order to handle configuration changes.
accessControlConfiguration.addChangeListener(this);
//This makes TestCaseUtils.reStartServer happy.
currentConfiguration=null;
// The configuration looks valid, so install it.
updateConfiguration(accessControlConfiguration);
}
/**
* Updates the access control configuration based on the contents of a
* valid configuration entry.
*
* @param newConfiguration The new configuration object.
*
* @throws ConfigException If the access control configuration is invalid.
*
* @throws InitializationException If the access control handler provider
* could not be instantiated.
*/
private void updateConfiguration(AccessControlHandlerCfg newConfiguration)
throws ConfigException, InitializationException
{
String newHandlerClass = null;
boolean enabledOld = false, enabledNew = newConfiguration.isEnabled();
if (currentConfiguration == null)
{
// Initialization phase.
if (enabledNew)
{
newHandlerClass = newConfiguration.getJavaClass();
}
else
{
newHandlerClass = DefaultAccessControlHandler.class.getName();
}
//Get a new handler, initialize it and make it the current handler.
accessControlHandler.getAndSet(getHandler(newHandlerClass,
newConfiguration, true, false));
} else {
enabledOld = currentConfiguration.isEnabled();
if(enabledNew) {
//Access control is either being enabled or a attribute in the
//configuration has changed such as class name or a global ACI.
newHandlerClass = newConfiguration.getJavaClass();
String oldHandlerClass = currentConfiguration.getJavaClass();
//Check if moving from not enabled to enabled state.
if(!enabledOld) {
AccessControlHandler oldHandler =
accessControlHandler.getAndSet(getHandler(newHandlerClass,
newConfiguration, true,
true));
oldHandler.finalizeAccessControlHandler();
} else {
//Check if the class name is being changed.
if(!newHandlerClass.equals(oldHandlerClass)) {
AccessControlHandler oldHandler =
accessControlHandler.getAndSet(getHandler(newHandlerClass,
newConfiguration, true, true));
oldHandler.finalizeAccessControlHandler();
} else {
//Some other attribute has changed, try to get a new non-initialized
//handler, but keep the old handler.
getHandler(newHandlerClass,newConfiguration, false, false);
}
}
} else if (enabledOld && !enabledNew) {
//Access control has been disabled, switch to the default handler and
//finalize the old handler.
newHandlerClass = DefaultAccessControlHandler.class.getName();
AccessControlHandler oldHandler =
accessControlHandler.getAndSet(getHandler(newHandlerClass,
newConfiguration, false, true));
oldHandler.finalizeAccessControlHandler();
}
}
// Switch in the local configuration.
currentConfiguration = newConfiguration;
}
/**
* Instantiates a new Access Control Handler using the specified class name,
* configuration.
*
* @param handlerClassName The name of the handler to instantiate.
* @param config The configuration to use when instantiating a new handler.
* @param initHandler True
if the new handler should be
* initialized.
* @param logMessage True
if an error message should be logged
* and an alert should be sent.
* @return The newly instantiated handler.
*
* @throws InitializationException If an error occurs instantiating the
* the new handler.
*/
AccessControlHandler extends AccessControlHandlerCfg>
getHandler(String handlerClassName, AccessControlHandlerCfg config,
boolean initHandler, boolean logMessage)
throws InitializationException {
AccessControlHandler extends AccessControlHandlerCfg> newHandler;
try {
if(handlerClassName.equals(DefaultAccessControlHandler.class.getName())) {
newHandler = new DefaultAccessControlHandler();
newHandler.initializeAccessControlHandler(null);
if(logMessage) {
LocalizableMessage message = WARN_CONFIG_AUTHZ_DISABLED.get();
logger.warn(message);
if (currentConfiguration != null) {
DirectoryServer.sendAlertNotification(this,
ALERT_TYPE_ACCESS_CONTROL_DISABLED, message);
}
}
} else {
newHandler = loadHandler(handlerClassName, config, initHandler);
if(logMessage) {
LocalizableMessage message = NOTE_CONFIG_AUTHZ_ENABLED.get(handlerClassName);
logger.info(message);
if (currentConfiguration != null) {
DirectoryServer.sendAlertNotification(this,
ALERT_TYPE_ACCESS_CONTROL_ENABLED, message);
}
}
}
} catch (Exception e) {
logger.traceException(e);
LocalizableMessage message = ERR_CONFIG_AUTHZ_UNABLE_TO_INSTANTIATE_HANDLER.
get(handlerClassName, config.dn(), stackTraceToSingleLineString(e));
throw new InitializationException(message, e);
}
return newHandler;
}
/** {@inheritDoc} */
@Override
public boolean isConfigurationChangeAcceptable(
AccessControlHandlerCfg configuration,
List