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 010 * trunk/opends/resource/legal-notices/OpenDS.LICENSE 011 * or https://OpenDS.dev.java.net/OpenDS.LICENSE. 012 * See the License for the specific language governing permissions 013 * and limitations under the License. 014 * 015 * When distributing Covered Code, include this CDDL HEADER in each 016 * file and include the License file at 017 * trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable, 018 * add the following below this CDDL HEADER, with the fields enclosed 019 * by brackets "[]" replaced with your own identifying information: 020 * Portions Copyright [yyyy] [name of copyright owner] 021 * 022 * CDDL HEADER END 023 * 024 * 025 * Copyright 2006-2008 Sun Microsystems, Inc. 026 */ 027 package org.opends.server.core; 028 import org.opends.messages.Message; 029 030 031 032 import java.lang.reflect.Method; 033 import java.util.ArrayList; 034 import java.util.Iterator; 035 import java.util.List; 036 import java.util.concurrent.ConcurrentHashMap; 037 038 import org.opends.server.admin.ClassPropertyDefinition; 039 import org.opends.server.admin.server.ConfigurationAddListener; 040 import org.opends.server.admin.server.ConfigurationChangeListener; 041 import org.opends.server.admin.server.ConfigurationDeleteListener; 042 import org.opends.server.admin.std.meta.KeyManagerProviderCfgDefn; 043 import org.opends.server.admin.std.server.KeyManagerProviderCfg; 044 import org.opends.server.admin.std.server.RootCfg; 045 import org.opends.server.admin.server.ServerManagementContext; 046 import org.opends.server.api.KeyManagerProvider; 047 import org.opends.server.config.ConfigException; 048 import org.opends.server.types.ConfigChangeResult; 049 import org.opends.server.types.DN; 050 import org.opends.server.types.InitializationException; 051 import org.opends.server.types.ResultCode; 052 053 import static org.opends.messages.ConfigMessages.*; 054 055 import static org.opends.server.loggers.ErrorLogger.*; 056 import static org.opends.server.util.StaticUtils.*; 057 058 059 060 /** 061 * This class defines a utility that will be used to manage the set of key 062 * manager providers defined in the Directory Server. It will initialize the 063 * key manager providers when the server starts, and then will manage any 064 * additions, removals, or modifications to any key manager providers while 065 * the server is running. 066 */ 067 public class KeyManagerProviderConfigManager 068 implements ConfigurationChangeListener<KeyManagerProviderCfg>, 069 ConfigurationAddListener<KeyManagerProviderCfg>, 070 ConfigurationDeleteListener<KeyManagerProviderCfg> 071 072 { 073 // A mapping between the DNs of the config entries and the associated key 074 // manager providers. 075 private ConcurrentHashMap<DN,KeyManagerProvider> providers; 076 077 078 079 /** 080 * Creates a new instance of this key manager provider config manager. 081 */ 082 public KeyManagerProviderConfigManager() 083 { 084 providers = new ConcurrentHashMap<DN,KeyManagerProvider>(); 085 } 086 087 088 089 /** 090 * Initializes all key manager providers currently defined in the Directory 091 * Server configuration. This should only be called at Directory Server 092 * startup. 093 * 094 * @throws ConfigException If a configuration problem causes the key 095 * manager provider initialization process to fail. 096 * 097 * @throws InitializationException If a problem occurs while initializing 098 * the key manager providers that is not 099 * related to the server configuration. 100 */ 101 public void initializeKeyManagerProviders() 102 throws ConfigException, InitializationException 103 { 104 // Get the root configuration object. 105 ServerManagementContext managementContext = 106 ServerManagementContext.getInstance(); 107 RootCfg rootConfiguration = 108 managementContext.getRootConfiguration(); 109 110 111 // Register as an add and delete listener with the root configuration so we 112 // can be notified if any key manager provider entries are added or removed. 113 rootConfiguration.addKeyManagerProviderAddListener(this); 114 rootConfiguration.addKeyManagerProviderDeleteListener(this); 115 116 117 //Initialize the existing key manager providers. 118 for (String name : rootConfiguration.listKeyManagerProviders()) 119 { 120 KeyManagerProviderCfg providerConfig = 121 rootConfiguration.getKeyManagerProvider(name); 122 providerConfig.addChangeListener(this); 123 124 if (providerConfig.isEnabled()) 125 { 126 String className = providerConfig.getJavaClass(); 127 try 128 { 129 KeyManagerProvider provider = 130 loadProvider(className, providerConfig, true); 131 providers.put(providerConfig.dn(), provider); 132 DirectoryServer.registerKeyManagerProvider(providerConfig.dn(), 133 provider); 134 } 135 catch (InitializationException ie) 136 { 137 logError(ie.getMessageObject()); 138 continue; 139 } 140 } 141 } 142 } 143 144 145 146 /** 147 * {@inheritDoc} 148 */ 149 public boolean isConfigurationAddAcceptable( 150 KeyManagerProviderCfg configuration, 151 List<Message> unacceptableReasons) 152 { 153 if (configuration.isEnabled()) 154 { 155 // Get the name of the class and make sure we can instantiate it as a 156 // key manager provider. 157 String className = configuration.getJavaClass(); 158 try 159 { 160 loadProvider(className, configuration, false); 161 } 162 catch (InitializationException ie) 163 { 164 unacceptableReasons.add(ie.getMessageObject()); 165 return false; 166 } 167 } 168 169 // If we've gotten here, then it's fine. 170 return true; 171 } 172 173 174 175 /** 176 * {@inheritDoc} 177 */ 178 public ConfigChangeResult applyConfigurationAdd( 179 KeyManagerProviderCfg configuration) 180 { 181 ResultCode resultCode = ResultCode.SUCCESS; 182 boolean adminActionRequired = false; 183 ArrayList<Message> messages = new ArrayList<Message>(); 184 185 configuration.addChangeListener(this); 186 187 if (! configuration.isEnabled()) 188 { 189 return new ConfigChangeResult(resultCode, adminActionRequired, messages); 190 } 191 192 KeyManagerProvider provider = null; 193 194 // Get the name of the class and make sure we can instantiate it as a key 195 // manager provider. 196 String className = configuration.getJavaClass(); 197 try 198 { 199 provider = loadProvider(className, configuration, true); 200 } 201 catch (InitializationException ie) 202 { 203 if (resultCode == ResultCode.SUCCESS) 204 { 205 resultCode = DirectoryServer.getServerErrorResultCode(); 206 } 207 208 messages.add(ie.getMessageObject()); 209 } 210 211 if (resultCode == ResultCode.SUCCESS) 212 { 213 providers.put(configuration.dn(), provider); 214 DirectoryServer.registerKeyManagerProvider(configuration.dn(), provider); 215 } 216 217 return new ConfigChangeResult(resultCode, adminActionRequired, messages); 218 } 219 220 221 222 /** 223 * {@inheritDoc} 224 */ 225 public boolean isConfigurationDeleteAcceptable( 226 KeyManagerProviderCfg configuration, 227 List<Message> unacceptableReasons) 228 { 229 // FIXME -- We should try to perform some check to determine whether the 230 // provider is in use. 231 return true; 232 } 233 234 235 236 /** 237 * {@inheritDoc} 238 */ 239 public ConfigChangeResult applyConfigurationDelete( 240 KeyManagerProviderCfg configuration) 241 { 242 ResultCode resultCode = ResultCode.SUCCESS; 243 boolean adminActionRequired = false; 244 ArrayList<Message> messages = new ArrayList<Message>(); 245 246 DirectoryServer.deregisterKeyManagerProvider(configuration.dn()); 247 248 KeyManagerProvider provider = providers.remove(configuration.dn()); 249 if (provider != null) 250 { 251 provider.finalizeKeyManagerProvider(); 252 } 253 254 return new ConfigChangeResult(resultCode, adminActionRequired, messages); 255 } 256 257 258 259 /** 260 * {@inheritDoc} 261 */ 262 public boolean isConfigurationChangeAcceptable( 263 KeyManagerProviderCfg configuration, 264 List<Message> unacceptableReasons) 265 { 266 if (configuration.isEnabled()) 267 { 268 // Get the name of the class and make sure we can instantiate it as a key 269 // manager provider. 270 String className = configuration.getJavaClass(); 271 try 272 { 273 loadProvider(className, configuration, false); 274 } 275 catch (InitializationException ie) 276 { 277 unacceptableReasons.add(ie.getMessageObject()); 278 return false; 279 } 280 } 281 282 // If we've gotten here, then it's fine. 283 return true; 284 } 285 286 287 288 /** 289 * {@inheritDoc} 290 */ 291 public ConfigChangeResult applyConfigurationChange( 292 KeyManagerProviderCfg configuration) 293 { 294 ResultCode resultCode = ResultCode.SUCCESS; 295 boolean adminActionRequired = false; 296 ArrayList<Message> messages = new ArrayList<Message>(); 297 298 299 // Get the existing provider if it's already enabled. 300 KeyManagerProvider existingProvider = providers.get(configuration.dn()); 301 302 303 // If the new configuration has the provider disabled, then disable it if it 304 // is enabled, or do nothing if it's already disabled. 305 if (! configuration.isEnabled()) 306 { 307 if (existingProvider != null) 308 { 309 DirectoryServer.deregisterKeyManagerProvider(configuration.dn()); 310 311 KeyManagerProvider provider = providers.remove(configuration.dn()); 312 if (provider != null) 313 { 314 provider.finalizeKeyManagerProvider(); 315 } 316 } 317 318 return new ConfigChangeResult(resultCode, adminActionRequired, messages); 319 } 320 321 322 // Get the class for the key manager provider. If the provider is already 323 // enabled, then we shouldn't do anything with it although if the class has 324 // changed then we'll at least need to indicate that administrative action 325 // is required. If the provider is disabled, then instantiate the class and 326 // initialize and register it as a key manager provider. 327 String className = configuration.getJavaClass(); 328 if (existingProvider != null) 329 { 330 if (! className.equals(existingProvider.getClass().getName())) 331 { 332 adminActionRequired = true; 333 } 334 335 return new ConfigChangeResult(resultCode, adminActionRequired, messages); 336 } 337 338 KeyManagerProvider provider = null; 339 try 340 { 341 provider = loadProvider(className, configuration, true); 342 } 343 catch (InitializationException ie) 344 { 345 if (resultCode == ResultCode.SUCCESS) 346 { 347 resultCode = DirectoryServer.getServerErrorResultCode(); 348 } 349 350 messages.add(ie.getMessageObject()); 351 } 352 353 if (resultCode == ResultCode.SUCCESS) 354 { 355 providers.put(configuration.dn(), provider); 356 DirectoryServer.registerKeyManagerProvider(configuration.dn(), provider); 357 } 358 359 return new ConfigChangeResult(resultCode, adminActionRequired, messages); 360 } 361 362 363 364 /** 365 * Loads the specified class, instantiates it as a key manager provider, and 366 * optionally initializes that instance. 367 * 368 * @param className The fully-qualified name of the key manager 369 * provider class to load, instantiate, and initialize. 370 * @param configuration The configuration to use to initialize the key 371 * manager provider. It must not be {@code null}. 372 * @param initialize Indicates whether the key manager provider instance 373 * should be initialized. 374 * 375 * @return The possibly initialized key manager provider. 376 * 377 * @throws InitializationException If the provided configuration is not 378 * acceptable, or if a problem occurred 379 * while attempting to initialize the key 380 * manager provider using that 381 * configuration. 382 */ 383 private KeyManagerProvider loadProvider(String className, 384 KeyManagerProviderCfg configuration, 385 boolean initialize) 386 throws InitializationException 387 { 388 try 389 { 390 KeyManagerProviderCfgDefn definition = 391 KeyManagerProviderCfgDefn.getInstance(); 392 ClassPropertyDefinition propertyDefinition = 393 definition.getJavaClassPropertyDefinition(); 394 Class<? extends KeyManagerProvider> providerClass = 395 propertyDefinition.loadClass(className, KeyManagerProvider.class); 396 KeyManagerProvider provider = providerClass.newInstance(); 397 398 399 if (initialize) 400 { 401 Method method = provider.getClass().getMethod( 402 "initializeKeyManagerProvider", configuration.configurationClass()); 403 method.invoke(provider, configuration); 404 } 405 else 406 { 407 Method method = 408 provider.getClass().getMethod("isConfigurationAcceptable", 409 KeyManagerProviderCfg.class, 410 List.class); 411 412 List<Message> unacceptableReasons = new ArrayList<Message>(); 413 Boolean acceptable = (Boolean) method.invoke(provider, configuration, 414 unacceptableReasons); 415 if (! acceptable) 416 { 417 StringBuilder buffer = new StringBuilder(); 418 if (! unacceptableReasons.isEmpty()) 419 { 420 Iterator<Message> iterator = unacceptableReasons.iterator(); 421 buffer.append(iterator.next()); 422 while (iterator.hasNext()) 423 { 424 buffer.append(". "); 425 buffer.append(iterator.next()); 426 } 427 } 428 429 Message message = ERR_CONFIG_KEYMANAGER_CONFIG_NOT_ACCEPTABLE.get( 430 String.valueOf(configuration.dn()), buffer.toString()); 431 throw new InitializationException(message); 432 } 433 } 434 435 return provider; 436 } 437 catch (InitializationException ie) 438 { 439 throw ie; 440 } 441 catch (Exception e) 442 { 443 Message message = ERR_CONFIG_KEYMANAGER_INITIALIZATION_FAILED. 444 get(className, String.valueOf(configuration.dn()), 445 stackTraceToSingleLineString(e)); 446 throw new InitializationException(message, e); 447 } 448 } 449 } 450