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 }