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.util.ArrayList; 033 import java.util.List; 034 035 import org.opends.server.admin.server.ConfigurationAddListener; 036 import org.opends.server.admin.server.ConfigurationDeleteListener; 037 import org.opends.server.admin.server.ServerManagementContext; 038 import org.opends.server.admin.std.server.PasswordPolicyCfg; 039 import org.opends.server.admin.std.server.RootCfg; 040 import org.opends.server.config.ConfigException; 041 import org.opends.server.types.ConfigChangeResult; 042 import org.opends.server.types.DN; 043 import org.opends.server.types.InitializationException; 044 import org.opends.server.types.ResultCode; 045 046 import static org.opends.messages.ConfigMessages.*; 047 048 import static org.opends.server.util.StaticUtils.*; 049 050 051 052 /** 053 * This class defines a utility that will be used to manage the set of password 054 * policies defined in the Directory Server. It will initialize the policies 055 * when the server starts, and then will manage any additions or removals while 056 * the server is running. 057 */ 058 public class PasswordPolicyConfigManager 059 implements ConfigurationAddListener<PasswordPolicyCfg>, 060 ConfigurationDeleteListener<PasswordPolicyCfg> 061 { 062 063 064 065 /** 066 * Creates a new instance of this password policy config manager. 067 */ 068 public PasswordPolicyConfigManager() 069 { 070 } 071 072 073 074 /** 075 * Initializes all password policies currently defined in the Directory 076 * Server configuration. This should only be called at Directory Server 077 * startup. 078 * 079 * @throws ConfigException If a configuration problem causes the password 080 * policy initialization process to fail. 081 * 082 * @throws InitializationException If a problem occurs while initializing 083 * the password policies that is not 084 * related to the server configuration. 085 */ 086 public void initializePasswordPolicies() 087 throws ConfigException, InitializationException 088 { 089 // Get the root configuration object. 090 ServerManagementContext managementContext = 091 ServerManagementContext.getInstance(); 092 RootCfg rootConfiguration = 093 managementContext.getRootConfiguration(); 094 095 // Register as an add and delete listener with the root configuration so we 096 // can be notified if any password policy entries are added or removed. 097 rootConfiguration.addPasswordPolicyAddListener(this); 098 rootConfiguration.addPasswordPolicyDeleteListener(this); 099 100 // First, get the configuration base entry. 101 String[] passwordPoliciesName = rootConfiguration.listPasswordPolicies() ; 102 103 // See if the base entry has any children. If not, then that means that 104 // there are no policies defined, so that's a problem. 105 if (passwordPoliciesName.length == 0) 106 { 107 Message message = ERR_CONFIG_PWPOLICY_NO_POLICIES.get(); 108 throw new ConfigException(message); 109 } 110 111 112 // Get the DN of the default password policy from the core configuration. 113 if( null == DirectoryServer.getDefaultPasswordPolicyDN()) 114 { 115 Message message = ERR_CONFIG_PWPOLICY_NO_DEFAULT_POLICY.get(); 116 throw new ConfigException(message); 117 } 118 119 120 // Iterate through the child entries and process them as password policy 121 // configuration entries. 122 for (String passwordPolicyName : passwordPoliciesName) 123 { 124 PasswordPolicyCfg passwordPolicyConfiguration = 125 rootConfiguration.getPasswordPolicy(passwordPolicyName); 126 127 try 128 { 129 PasswordPolicy policy = new PasswordPolicy(passwordPolicyConfiguration); 130 PasswordPolicyConfig config = new PasswordPolicyConfig(policy); 131 DirectoryServer.registerPasswordPolicy( 132 passwordPolicyConfiguration.dn(), config); 133 passwordPolicyConfiguration.addChangeListener(config); 134 } 135 catch (ConfigException ce) 136 { 137 Message message = ERR_CONFIG_PWPOLICY_INVALID_POLICY_CONFIG.get( 138 String.valueOf(passwordPolicyConfiguration.dn()), ce.getMessage()); 139 throw new ConfigException(message, ce); 140 } 141 catch (InitializationException ie) 142 { 143 Message message = ERR_CONFIG_PWPOLICY_INVALID_POLICY_CONFIG.get( 144 String.valueOf(passwordPolicyConfiguration.dn()), ie.getMessage()); 145 throw new InitializationException(message, ie); 146 } 147 catch (Exception e) 148 { 149 Message message = ERR_CONFIG_PWPOLICY_INVALID_POLICY_CONFIG. 150 get(String.valueOf(passwordPolicyConfiguration.dn()), 151 stackTraceToSingleLineString(e)); 152 throw new InitializationException(message, e); 153 } 154 } 155 156 157 // If the entry specified by the default password policy DN has not been 158 // registered, then fail. 159 if (null == DirectoryServer.getDefaultPasswordPolicy()) 160 { 161 DN defaultPolicyDN = DirectoryServer.getDefaultPasswordPolicyDN(); 162 Message message = ERR_CONFIG_PWPOLICY_MISSING_DEFAULT_POLICY.get( 163 String.valueOf(defaultPolicyDN)); 164 throw new ConfigException(message); 165 } 166 } 167 168 169 170 /** 171 * {@inheritDoc} 172 */ 173 public boolean isConfigurationAddAcceptable(PasswordPolicyCfg configuration, 174 List<Message> unacceptableReason) 175 { 176 // See if we can create a password policy from the provided configuration 177 // entry. If so, then it's acceptable. 178 try 179 { 180 new PasswordPolicy(configuration); 181 } 182 catch (ConfigException ce) 183 { 184 Message message = ERR_CONFIG_PWPOLICY_INVALID_POLICY_CONFIG.get( 185 String.valueOf(configuration.dn()), 186 ce.getMessage()); 187 unacceptableReason.add(message); 188 return false; 189 } 190 catch (InitializationException ie) 191 { 192 Message message = ERR_CONFIG_PWPOLICY_INVALID_POLICY_CONFIG.get( 193 String.valueOf(configuration.dn()), 194 ie.getMessage()); 195 unacceptableReason.add(message); 196 return false; 197 } 198 catch (Exception e) 199 { 200 Message message = ERR_CONFIG_PWPOLICY_INVALID_POLICY_CONFIG.get( 201 String.valueOf(configuration.dn()), 202 stackTraceToSingleLineString(e)); 203 unacceptableReason.add(message); 204 return false; 205 } 206 207 208 // If we've gotten here, then it is acceptable. 209 return true; 210 } 211 212 213 214 /** 215 * {@inheritDoc} 216 */ 217 public ConfigChangeResult applyConfigurationAdd( 218 PasswordPolicyCfg configuration) 219 { 220 DN configEntryDN = configuration.dn(); 221 ArrayList<Message> messages = new ArrayList<Message>(); 222 223 224 // See if we can create a password policy from the provided configuration 225 // entry. If so, then register it with the Directory Server. 226 try 227 { 228 PasswordPolicy policy = new PasswordPolicy(configuration); 229 PasswordPolicyConfig config = new PasswordPolicyConfig(policy); 230 231 DirectoryServer.registerPasswordPolicy(configEntryDN, config); 232 configuration.addChangeListener(config); 233 return new ConfigChangeResult(ResultCode.SUCCESS, false, messages); 234 } 235 catch (ConfigException ce) 236 { 237 messages.add(ERR_CONFIG_PWPOLICY_INVALID_POLICY_CONFIG.get( 238 String.valueOf(configuration.dn()), 239 ce.getMessage())); 240 241 return new ConfigChangeResult(ResultCode.CONSTRAINT_VIOLATION, false, 242 messages); 243 } 244 catch (InitializationException ie) 245 { 246 messages.add(ERR_CONFIG_PWPOLICY_INVALID_POLICY_CONFIG.get( 247 String.valueOf(configuration.dn()), 248 ie.getMessage())); 249 250 return new ConfigChangeResult(DirectoryServer.getServerErrorResultCode(), 251 false, messages); 252 } 253 catch (Exception e) 254 { 255 messages.add(ERR_CONFIG_PWPOLICY_INVALID_POLICY_CONFIG.get( 256 String.valueOf(configuration.dn()), 257 stackTraceToSingleLineString(e))); 258 259 return new ConfigChangeResult(DirectoryServer.getServerErrorResultCode(), 260 false, messages); 261 } 262 } 263 264 265 266 /** 267 * {@inheritDoc} 268 */ 269 public boolean isConfigurationDeleteAcceptable( 270 PasswordPolicyCfg configuration, List<Message> unacceptableReason) 271 { 272 // We'll allow the policy to be removed as long as it isn't the default. 273 // FIXME: something like a referential integrity check is needed to ensure 274 // a policy is not removed when referenced by a user entry (either 275 // directly or via a virtual attribute). 276 DN defaultPolicyDN = DirectoryServer.getDefaultPasswordPolicyDN(); 277 if ((defaultPolicyDN != null) && 278 defaultPolicyDN.equals(configuration.dn())) 279 { 280 Message message = WARN_CONFIG_PWPOLICY_CANNOT_DELETE_DEFAULT_POLICY.get( 281 String.valueOf(defaultPolicyDN)); 282 unacceptableReason.add(message); 283 return false; 284 } 285 else 286 { 287 return true; 288 } 289 } 290 291 292 293 /** 294 * {@inheritDoc} 295 */ 296 public ConfigChangeResult applyConfigurationDelete( 297 PasswordPolicyCfg configuration) 298 { 299 // We'll allow the policy to be removed as long as it isn't the default. 300 // FIXME: something like a referential integrity check is needed to ensure 301 // a policy is not removed when referenced by a user entry (either 302 // directly or via a virtual attribute). 303 ArrayList<Message> messages = new ArrayList<Message>(1); 304 DN policyDN = configuration.dn(); 305 DN defaultPolicyDN = DirectoryServer.getDefaultPasswordPolicyDN(); 306 if ((defaultPolicyDN != null) && defaultPolicyDN.equals(policyDN)) 307 { 308 messages.add(WARN_CONFIG_PWPOLICY_CANNOT_DELETE_DEFAULT_POLICY.get( 309 String.valueOf(defaultPolicyDN))); 310 return new ConfigChangeResult(ResultCode.CONSTRAINT_VIOLATION, false, 311 messages); 312 } 313 DirectoryServer.deregisterPasswordPolicy(policyDN); 314 PasswordPolicyConfig config = 315 DirectoryServer.getPasswordPolicyConfig(policyDN); 316 if (config != null) 317 { 318 configuration.removeChangeListener(config); 319 } 320 321 messages.add(INFO_CONFIG_PWPOLICY_REMOVED_POLICY.get( 322 String.valueOf(policyDN))); 323 324 return new ConfigChangeResult(ResultCode.SUCCESS, false, messages); 325 } 326 }