001/* 002 * The contents of this file are subject to the terms of the Common Development and 003 * Distribution License (the License). You may not use this file except in compliance with the 004 * License. 005 * 006 * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the 007 * specific language governing permission and limitations under the License. 008 * 009 * When distributing Covered Software, include this CDDL Header Notice in each file and include 010 * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL 011 * Header, with the fields enclosed by brackets [] replaced by your own identifying 012 * information: "Portions Copyright [year] [name of copyright owner]". 013 * 014 * Copyright 2006-2008 Sun Microsystems, Inc. 015 * Portions Copyright 2014-2016 ForgeRock AS. 016 */ 017package org.opends.server.core; 018 019import org.forgerock.i18n.LocalizableMessage; 020import org.forgerock.i18n.slf4j.LocalizedLogger; 021import org.forgerock.util.Utils; 022 023import java.util.ArrayList; 024import java.util.List; 025import java.util.concurrent.ConcurrentHashMap; 026 027import org.forgerock.opendj.config.ClassPropertyDefinition; 028import org.forgerock.opendj.config.server.ConfigurationAddListener; 029import org.forgerock.opendj.config.server.ConfigurationChangeListener; 030import org.forgerock.opendj.config.server.ConfigurationDeleteListener; 031import org.forgerock.opendj.server.config.meta.TrustManagerProviderCfgDefn; 032import org.forgerock.opendj.server.config.server.TrustManagerProviderCfg; 033import org.forgerock.opendj.server.config.server.RootCfg; 034import org.opends.server.api.TrustManagerProvider; 035import org.forgerock.opendj.config.server.ConfigException; 036import org.forgerock.opendj.config.server.ConfigChangeResult; 037import org.forgerock.opendj.ldap.DN; 038import org.opends.server.types.InitializationException; 039import org.forgerock.opendj.ldap.ResultCode; 040 041import static org.opends.messages.ConfigMessages.*; 042import static org.opends.server.util.StaticUtils.*; 043 044/** 045 * This class defines a utility that will be used to manage the set of trust 046 * manager providers defined in the Directory Server. It will initialize the 047 * trust manager providers when the server starts, and then will manage any 048 * additions, removals, or modifications to any trust manager providers while 049 * the server is running. 050 */ 051public class TrustManagerProviderConfigManager 052 implements ConfigurationChangeListener<TrustManagerProviderCfg>, 053 ConfigurationAddListener<TrustManagerProviderCfg>, 054 ConfigurationDeleteListener<TrustManagerProviderCfg> 055{ 056 private static final LocalizedLogger logger = LocalizedLogger.getLoggerForThisClass(); 057 058 /** A mapping between the DNs of the config entries and the associated trust manager providers. */ 059 private final ConcurrentHashMap<DN,TrustManagerProvider> providers; 060 061 private final ServerContext serverContext; 062 063 /** 064 * Creates a new instance of this trust manager provider config manager. 065 * 066 * @param serverContext 067 * The server context. 068 */ 069 public TrustManagerProviderConfigManager(ServerContext serverContext) 070 { 071 this.serverContext = serverContext; 072 providers = new ConcurrentHashMap<>(); 073 } 074 075 /** 076 * Initializes all trust manager providers currently defined in the Directory 077 * Server configuration. This should only be called at Directory Server 078 * startup. 079 * 080 * @throws ConfigException If a configuration problem causes the trust 081 * manager provider initialization process to fail. 082 * 083 * @throws InitializationException If a problem occurs while initializing 084 * the trust manager providers that is not 085 * related to the server configuration. 086 */ 087 public void initializeTrustManagerProviders() 088 throws ConfigException, InitializationException 089 { 090 RootCfg rootConfiguration = serverContext.getRootConfig(); 091 rootConfiguration.addTrustManagerProviderAddListener(this); 092 rootConfiguration.addTrustManagerProviderDeleteListener(this); 093 094 //Initialize the existing trust manager providers. 095 for (String name : rootConfiguration.listTrustManagerProviders()) 096 { 097 TrustManagerProviderCfg providerConfig = 098 rootConfiguration.getTrustManagerProvider(name); 099 providerConfig.addChangeListener(this); 100 101 if (providerConfig.isEnabled()) 102 { 103 String className = providerConfig.getJavaClass(); 104 try 105 { 106 TrustManagerProvider provider = 107 loadProvider(className, providerConfig, true); 108 providers.put(providerConfig.dn(), provider); 109 DirectoryServer.registerTrustManagerProvider(providerConfig.dn(), 110 provider); 111 } 112 catch (InitializationException ie) 113 { 114 logger.error(ie.getMessageObject()); 115 continue; 116 } 117 } 118 } 119 } 120 121 @Override 122 public boolean isConfigurationAddAcceptable( 123 TrustManagerProviderCfg configuration, 124 List<LocalizableMessage> unacceptableReasons) 125 { 126 if (configuration.isEnabled()) 127 { 128 // Get the name of the class and make sure we can instantiate it as a 129 // trust manager provider. 130 String className = configuration.getJavaClass(); 131 try 132 { 133 loadProvider(className, configuration, false); 134 } 135 catch (InitializationException ie) 136 { 137 unacceptableReasons.add(ie.getMessageObject()); 138 return false; 139 } 140 } 141 142 // If we've gotten here, then it's fine. 143 return true; 144 } 145 146 @Override 147 public ConfigChangeResult applyConfigurationAdd( 148 TrustManagerProviderCfg configuration) 149 { 150 final ConfigChangeResult ccr = new ConfigChangeResult(); 151 152 configuration.addChangeListener(this); 153 154 if (! configuration.isEnabled()) 155 { 156 return ccr; 157 } 158 159 TrustManagerProvider provider = null; 160 161 // Get the name of the class and make sure we can instantiate it as a trust 162 // manager provider. 163 String className = configuration.getJavaClass(); 164 try 165 { 166 provider = loadProvider(className, configuration, true); 167 } 168 catch (InitializationException ie) 169 { 170 ccr.setResultCodeIfSuccess(DirectoryServer.getServerErrorResultCode()); 171 ccr.addMessage(ie.getMessageObject()); 172 } 173 174 if (ccr.getResultCode() == ResultCode.SUCCESS) 175 { 176 providers.put(configuration.dn(), provider); 177 DirectoryServer.registerTrustManagerProvider(configuration.dn(), 178 provider); 179 } 180 181 return ccr; 182 } 183 184 @Override 185 public boolean isConfigurationDeleteAcceptable( 186 TrustManagerProviderCfg configuration, 187 List<LocalizableMessage> unacceptableReasons) 188 { 189 // FIXME -- We should try to perform some check to determine whether the 190 // provider is in use. 191 return true; 192 } 193 194 @Override 195 public ConfigChangeResult applyConfigurationDelete( 196 TrustManagerProviderCfg configuration) 197 { 198 final ConfigChangeResult ccr = new ConfigChangeResult(); 199 200 DirectoryServer.deregisterTrustManagerProvider(configuration.dn()); 201 202 TrustManagerProvider provider = providers.remove(configuration.dn()); 203 if (provider != null) 204 { 205 provider.finalizeTrustManagerProvider(); 206 } 207 208 return ccr; 209 } 210 211 @Override 212 public boolean isConfigurationChangeAcceptable( 213 TrustManagerProviderCfg configuration, 214 List<LocalizableMessage> unacceptableReasons) 215 { 216 if (configuration.isEnabled()) 217 { 218 // Get the name of the class and make sure we can instantiate it as a 219 // trust manager provider. 220 String className = configuration.getJavaClass(); 221 try 222 { 223 loadProvider(className, configuration, false); 224 } 225 catch (InitializationException ie) 226 { 227 unacceptableReasons.add(ie.getMessageObject()); 228 return false; 229 } 230 } 231 232 // If we've gotten here, then it's fine. 233 return true; 234 } 235 236 @Override 237 public ConfigChangeResult applyConfigurationChange( 238 TrustManagerProviderCfg configuration) 239 { 240 final ConfigChangeResult ccr = new ConfigChangeResult(); 241 242 // Get the existing provider if it's already enabled. 243 TrustManagerProvider existingProvider = providers.get(configuration.dn()); 244 245 // If the new configuration has the provider disabled, then disable it if it 246 // is enabled, or do nothing if it's already disabled. 247 if (! configuration.isEnabled()) 248 { 249 if (existingProvider != null) 250 { 251 DirectoryServer.deregisterTrustManagerProvider(configuration.dn()); 252 253 TrustManagerProvider provider = providers.remove(configuration.dn()); 254 if (provider != null) 255 { 256 provider.finalizeTrustManagerProvider(); 257 } 258 } 259 260 return ccr; 261 } 262 263 // Get the class for the trust manager provider. If the provider is already 264 // enabled, then we shouldn't do anything with it although if the class has 265 // changed then we'll at least need to indicate that administrative action 266 // is required. If the provider is disabled, then instantiate the class and 267 // initialize and register it as a trust manager provider. 268 String className = configuration.getJavaClass(); 269 if (existingProvider != null) 270 { 271 if (! className.equals(existingProvider.getClass().getName())) 272 { 273 ccr.setAdminActionRequired(true); 274 } 275 276 return ccr; 277 } 278 279 TrustManagerProvider provider = null; 280 try 281 { 282 provider = loadProvider(className, configuration, true); 283 } 284 catch (InitializationException ie) 285 { 286 ccr.setResultCodeIfSuccess(DirectoryServer.getServerErrorResultCode()); 287 ccr.addMessage(ie.getMessageObject()); 288 } 289 290 if (ccr.getResultCode() == ResultCode.SUCCESS) 291 { 292 providers.put(configuration.dn(), provider); 293 DirectoryServer.registerTrustManagerProvider(configuration.dn(), provider); 294 } 295 296 return ccr; 297 } 298 299 /** 300 * Loads the specified class, instantiates it as a trust manager provider, and 301 * optionally initializes that instance. 302 * 303 * @param className The fully-qualified name of the trust manager 304 * provider class to load, instantiate, and initialize. 305 * @param configuration The configuration to use to initialize the trust 306 * manager provider. It must not be {@code null}. 307 * @param initialize Indicates whether the trust manager provider 308 * instance should be initialized. 309 * 310 * @return The possibly initialized trust manager provider. 311 * 312 * @throws InitializationException If a problem occurred while attempting to 313 * initialize the trust manager provider. 314 */ 315 private <T extends TrustManagerProviderCfg> TrustManagerProvider<T> loadProvider( 316 String className, 317 T configuration, 318 boolean initialize) 319 throws InitializationException 320 { 321 try 322 { 323 TrustManagerProviderCfgDefn definition = 324 TrustManagerProviderCfgDefn.getInstance(); 325 ClassPropertyDefinition propertyDefinition = 326 definition.getJavaClassPropertyDefinition(); 327 Class<? extends TrustManagerProvider> providerClass = 328 propertyDefinition.loadClass(className, TrustManagerProvider.class); 329 TrustManagerProvider<T> provider = providerClass.newInstance(); 330 331 if (initialize) 332 { 333 provider.initializeTrustManagerProvider(configuration); 334 } 335 else 336 { 337 List<LocalizableMessage> unacceptableReasons = new ArrayList<>(); 338 if (!provider.isConfigurationAcceptable(configuration, unacceptableReasons)) 339 { 340 String reasons = Utils.joinAsString(". ", unacceptableReasons); 341 throw new InitializationException( 342 ERR_CONFIG_TRUSTMANAGER_CONFIG_NOT_ACCEPTABLE.get(configuration.dn(), reasons)); 343 } 344 } 345 346 return provider; 347 } 348 catch (Exception e) 349 { 350 LocalizableMessage message = ERR_CONFIG_TRUSTMANAGER_INITIALIZATION_FAILED. 351 get(className, configuration.dn(), stackTraceToSingleLineString(e)); 352 throw new InitializationException(message, e); 353 } 354 } 355}