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    }