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 2013-2014 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.
040 OneTimePasswordDeliveryMechanismConfig;
041 import com.unboundid.directory.sdk.ds.internal.DirectoryServerExtension;
042 import com.unboundid.directory.sdk.ds.types.DirectoryServerContext;
043 import com.unboundid.directory.sdk.proxy.internal.DirectoryProxyServerExtension;
044 import com.unboundid.ldap.sdk.LDAPException;
045 import com.unboundid.ldap.sdk.ResultCode;
046 import com.unboundid.util.Extensible;
047 import com.unboundid.util.ThreadSafety;
048 import com.unboundid.util.ThreadSafetyLevel;
049 import com.unboundid.util.args.ArgumentException;
050 import com.unboundid.util.args.ArgumentParser;
051
052
053
054 /**
055 * This class defines an API that must be implemented by extensions which
056 * attempt to deliver one-time passwords (OTPs) to end users through some
057 * out-of-band mechanism. The one-time passwords will have been generated by
058 * the deliver one-time password extended request, and may be used to
059 * authenticate to the server through the UNBOUNDID-DELIVERED-OTP SASL
060 * mechanism.
061 * <BR>
062 * <H2>Configuring One-Time Password Delivery Mechanisms</H2>
063 * In order to configure a one-time password delivery mechanism created using
064 * this API, use a command like:
065 * <PRE>
066 * dsconfig create-otp-delivery-mechanism \
067 * --mechanism-name "<I>{mechanism-name}</I>" \
068 * --type third-party \
069 * --set enabled:true \
070 * --set "extension-class:<I>{class-name}</I>" \
071 * --set "extension-argument:<I>{name=value}</I>"
072 * </PRE>
073 * where "<I>{mechanism-name}</I>" is the name to use for the one-time password
074 * instance, "<I>{class-name}</I>" is the fully-qualified name of the Java class
075 * that extends
076 * {@code com.unboundid.directory.sdk.ds.api.OneTimePasswordDeliveryMechanism},
077 * and "<I>{name=value}</I>" represents name-value pairs for any arguments to
078 * provide to the one-time password delivery mechanism. If multiple arguments
079 * should be provided to the OTP delivery mechanism, then the
080 * "<CODE>--set extension-argument:<I>{name=value}</I></CODE>" option should be
081 * provided multiple times.
082 */
083 @Extensible()
084 @DirectoryServerExtension()
085 @DirectoryProxyServerExtension(appliesToLocalContent=true,
086 appliesToRemoteContent=true)
087 @ThreadSafety(level=ThreadSafetyLevel.INTERFACE_THREADSAFE)
088 public abstract class OneTimePasswordDeliveryMechanism
089 implements UnboundIDExtension,
090 Reconfigurable<OneTimePasswordDeliveryMechanismConfig>,
091 ExampleUsageProvider
092 {
093 /**
094 * Creates a new instance of this one-time password delivery mechanism. All
095 * OTP delivery mechanism implementations must include a default constructor,
096 * but any initialization should generally be done in the
097 * {@code initializeOTPDeliveryMechanism} method.
098 */
099 public OneTimePasswordDeliveryMechanism()
100 {
101 // No implementation is required.
102 }
103
104
105
106 /**
107 * {@inheritDoc}
108 */
109 public abstract String getExtensionName();
110
111
112
113 /**
114 * {@inheritDoc}
115 */
116 public abstract String[] getExtensionDescription();
117
118
119
120 /**
121 * {@inheritDoc}
122 */
123 public void defineConfigArguments(final ArgumentParser parser)
124 throws ArgumentException
125 {
126 // No arguments will be allowed by default.
127 }
128
129
130
131 /**
132 * Initializes this one-time password delivery mechanism.
133 *
134 * @param serverContext A handle to the server context for the server in
135 * which this extension is running.
136 * @param config The general configuration for this OTP delivery
137 * mechanism.
138 * @param parser The argument parser which has been initialized from
139 * the configuration for this OTP delivery mechanism.
140 *
141 * @throws LDAPException If a problem occurs while initializing this OTP
142 * delivery mechanism.
143 */
144 public void initializeOTPDeliveryMechanism(
145 final DirectoryServerContext serverContext,
146 final OneTimePasswordDeliveryMechanismConfig config,
147 final ArgumentParser parser)
148 throws LDAPException
149 {
150 // No initialization will be performed by default.
151 }
152
153
154
155 /**
156 * {@inheritDoc}
157 */
158 public boolean isConfigurationAcceptable(
159 final OneTimePasswordDeliveryMechanismConfig config,
160 final ArgumentParser parser,
161 final List<String> unacceptableReasons)
162 {
163 // No extended validation will be performed by default.
164 return true;
165 }
166
167
168
169 /**
170 * {@inheritDoc}
171 */
172 public ResultCode applyConfiguration(
173 final OneTimePasswordDeliveryMechanismConfig 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 one-time " +
186 "password delivery mechanism is disabled and re-enabled or " +
187 "until the server is restarted.");
188 }
189
190 return ResultCode.SUCCESS;
191 }
192
193
194
195 /**
196 * Performs any cleanup which may be necessary when this one-time password
197 * delivery mechanism is to be taken out of service.
198 */
199 public void finalizeOTPDeliveryMechanism()
200 {
201 // No implementation is required.
202 }
203
204
205
206 /**
207 * Attempts to deliver the provided one-time password to the specified user.
208 *
209 * @param oneTimePassword The one-time password to be delivered.
210 * @param userEntry The entry for the user to whom the one-time
211 * password should be delivered.
212 * @param targetRecipientID The target recipient ID that should be used for
213 * the delivery, if possible. It may be
214 * {@code null} if there is no appropriate
215 * identifier for this delivery mechanism or if
216 * the delivery mechanism may choose which
217 * recipient ID should be used. However, if it is
218 * non-{@code null}, then the delivery mechanism
219 * must verify that the provided recipient ID is
220 * valid for the associated user (e.g., for an
221 * e-mail delivery mechanism, the recipient ID
222 * would probably be an e-mail address, and the
223 * delivery mechanism must verify that the provided
224 * e-mail address is associated with the given
225 * user account).
226 * @param message A buffer to which a message may be appended with
227 * additional information about the password
228 * delivery.
229 *
230 * @return An identifier for the user in a format appropriate to the delivery
231 * mechanism (e.g., an e-mail address for an e-mail delivery
232 * mechanism, a phone number for an SMS or voice call delivery
233 * mechanism, etc.). It may be {@code null} if there is no
234 * appropriate identifier for this delivery mechanism that is needed
235 * beyond the name of the delivery mechanism and the DN of the
236 * recipient.
237 *
238 * @throws LDAPException If a problem is encountered while attempting to
239 * send the one-time password to the user.
240 */
241 public abstract String deliverOneTimePassword(final String oneTimePassword,
242 final Entry userEntry,
243 final String targetRecipientID,
244 final StringBuilder message)
245 throws LDAPException;
246
247
248
249 /**
250 * {@inheritDoc}
251 */
252 public Map<List<String>,String> getExamplesArgumentSets()
253 {
254 return Collections.emptyMap();
255 }
256 }