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 * docs/licenses/cddl.txt
011 * or http://www.opensource.org/licenses/cddl1.php.
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 * docs/licenses/cddl.txt. 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 2010-2013 UnboundID Corp.
026 */
027 package com.unboundid.directory.sdk.ds.api;
028
029
030
031 import java.util.Collections;
032 import java.util.List;
033 import java.util.Map;
034
035 import com.unboundid.directory.sdk.common.internal.ExampleUsageProvider;
036 import com.unboundid.directory.sdk.common.internal.Reconfigurable;
037 import com.unboundid.directory.sdk.common.internal.UnboundIDExtension;
038 import com.unboundid.directory.sdk.common.types.Entry;
039 import com.unboundid.directory.sdk.ds.config.PasswordGeneratorConfig;
040 import com.unboundid.directory.sdk.ds.internal.DirectoryServerExtension;
041 import com.unboundid.directory.sdk.ds.types.DirectoryServerContext;
042 import com.unboundid.directory.sdk.proxy.internal.DirectoryProxyServerExtension;
043 import com.unboundid.directory.sdk.sync.internal.SynchronizationServerExtension;
044 import com.unboundid.ldap.sdk.LDAPException;
045 import com.unboundid.ldap.sdk.ResultCode;
046 import com.unboundid.util.ByteString;
047 import com.unboundid.util.Extensible;
048 import com.unboundid.util.ThreadSafety;
049 import com.unboundid.util.ThreadSafetyLevel;
050 import com.unboundid.util.args.ArgumentException;
051 import com.unboundid.util.args.ArgumentParser;
052
053
054
055 /**
056 * This class defines an API that must be implemented by extensions which
057 * generate user passwords. This is primarily used when processing a password
058 * modify extended operation in order to generate a new password for the target
059 * user if the request did not explicitly provide the new password that should
060 * be used. The generated password will not be subject to the constraints of
061 * any defined password validators.
062 * <BR>
063 * <H2>Configuring Password Generators</H2>
064 * In order to configure a password generator created using this API, use a
065 * command like:
066 * <PRE>
067 * dsconfig create-password-generator \
068 * --generator-name "<I>{generator-name}</I>" \
069 * --type third-party \
070 * --set enabled:true \
071 * --set "extension-class:<I>{class-name}</I>" \
072 * --set "extension-argument:<I>{name=value}</I>"
073 * </PRE>
074 * where "<I>{generator-name}</I>" is the name to use for the password generator
075 * instance, "<I>{class-name}</I>" is the fully-qualified name of the Java class
076 * that extends {@code com.unboundid.directory.sdk.ds.api.PasswordGenerator},
077 * and "<I>{name=value}</I>" represents name-value pairs for any arguments to
078 * provide to the password generator. If multiple arguments should be provided
079 * to the password generator, then the
080 * "<CODE>--set extension-argument:<I>{name=value}</I></CODE>" option should be
081 * provided multiple times.
082 *
083 * @see com.unboundid.directory.sdk.ds.scripting.ScriptedPasswordGenerator
084 */
085 @Extensible()
086 @DirectoryServerExtension()
087 @DirectoryProxyServerExtension(appliesToLocalContent=true,
088 appliesToRemoteContent=false)
089 @SynchronizationServerExtension(appliesToLocalContent=true,
090 appliesToSynchronizedContent=false)
091 @ThreadSafety(level=ThreadSafetyLevel.INTERFACE_THREADSAFE)
092 public abstract class PasswordGenerator
093 implements UnboundIDExtension, Reconfigurable<PasswordGeneratorConfig>,
094 ExampleUsageProvider
095 {
096 /**
097 * Creates a new instance of this password generator. All password generator
098 * implementations must include a default constructor, but any initialization
099 * should generally be done in the {@code initializePasswordGenerator} method.
100 */
101 public PasswordGenerator()
102 {
103 // No implementation is required.
104 }
105
106
107
108 /**
109 * {@inheritDoc}
110 */
111 public abstract String getExtensionName();
112
113
114
115 /**
116 * {@inheritDoc}
117 */
118 public abstract String[] getExtensionDescription();
119
120
121
122 /**
123 * {@inheritDoc}
124 */
125 public void defineConfigArguments(final ArgumentParser parser)
126 throws ArgumentException
127 {
128 // No arguments will be allowed by default.
129 }
130
131
132
133 /**
134 * Initializes this password generator.
135 *
136 * @param serverContext A handle to the server context for the server in
137 * which this extension is running.
138 * @param config The general configuration for this password
139 * generator.
140 * @param parser The argument parser which has been initialized from
141 * the configuration for this password generator.
142 *
143 * @throws LDAPException If a problem occurs while initializing this
144 * password generator.
145 */
146 public void initializePasswordGenerator(
147 final DirectoryServerContext serverContext,
148 final PasswordGeneratorConfig config,
149 final ArgumentParser parser)
150 throws LDAPException
151 {
152 // No initialization will be performed by default.
153 }
154
155
156
157 /**
158 * {@inheritDoc}
159 */
160 public boolean isConfigurationAcceptable(final PasswordGeneratorConfig config,
161 final ArgumentParser parser,
162 final List<String> unacceptableReasons)
163 {
164 // No extended validation will be performed by default.
165 return true;
166 }
167
168
169
170 /**
171 * {@inheritDoc}
172 */
173 public ResultCode applyConfiguration(final PasswordGeneratorConfig config,
174 final ArgumentParser parser,
175 final List<String> adminActionsRequired,
176 final List<String> messages)
177 {
178 // By default, no configuration changes will be applied. If there are any
179 // arguments, then add an admin action message indicating that the extension
180 // needs to be restarted for any changes to take effect.
181 if (! parser.getNamedArguments().isEmpty())
182 {
183 adminActionsRequired.add(
184 "No configuration change has actually been applied. The new " +
185 "configuration will not take effect until this password " +
186 "generator is disabled and re-enabled or until the server " +
187 "is restarted.");
188 }
189
190 return ResultCode.SUCCESS;
191 }
192
193
194
195 /**
196 * Performs any cleanup which may be necessary when this password generator is
197 * to be taken out of service.
198 */
199 public void finalizePasswordGenerator()
200 {
201 // No implementation is required.
202 }
203
204
205
206 /**
207 * Performs any processing which may be necessary to generate a user
208 * password.
209 *
210 * @param userEntry The entry of the user for whom to generate the password.
211 *
212 * @return The generated password.
213 *
214 * @throws LDAPException If a problem occurs while attempting to generate a
215 * password for the user.
216 */
217 public abstract ByteString generatePassword(final Entry userEntry)
218 throws LDAPException;
219
220
221
222 /**
223 * {@inheritDoc}
224 */
225 public Map<List<String>,String> getExamplesArgumentSets()
226 {
227 return Collections.emptyMap();
228 }
229 }