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-2015 UnboundID Corp.
026 */
027package com.unboundid.directory.sdk.ds.api;
028
029
030
031import java.util.Collections;
032import java.util.List;
033import java.util.Map;
034
035import com.unboundid.directory.sdk.common.internal.ExampleUsageProvider;
036import com.unboundid.directory.sdk.common.internal.Reconfigurable;
037import com.unboundid.directory.sdk.common.internal.UnboundIDExtension;
038import com.unboundid.directory.sdk.common.types.Entry;
039import com.unboundid.directory.sdk.ds.config.
040            OneTimePasswordDeliveryMechanismConfig;
041import com.unboundid.directory.sdk.ds.internal.DirectoryServerExtension;
042import com.unboundid.directory.sdk.ds.types.DirectoryServerContext;
043import com.unboundid.directory.sdk.proxy.internal.DirectoryProxyServerExtension;
044import com.unboundid.ldap.sdk.LDAPException;
045import com.unboundid.ldap.sdk.ResultCode;
046import com.unboundid.util.Extensible;
047import com.unboundid.util.ThreadSafety;
048import com.unboundid.util.ThreadSafetyLevel;
049import com.unboundid.util.args.ArgumentException;
050import 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)
088public 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}