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