001    /*
002     * Copyright 2012-2015 UnboundID Corp.
003     * All Rights Reserved.
004     */
005    /*
006     * Copyright (C) 2015 UnboundID Corp.
007     *
008     * This program is free software; you can redistribute it and/or modify
009     * it under the terms of the GNU General Public License (GPLv2 only)
010     * or the terms of the GNU Lesser General Public License (LGPLv2.1 only)
011     * as published by the Free Software Foundation.
012     *
013     * This program is distributed in the hope that it will be useful,
014     * but WITHOUT ANY WARRANTY; without even the implied warranty of
015     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
016     * GNU General Public License for more details.
017     *
018     * You should have received a copy of the GNU General Public License
019     * along with this program; if not, see <http://www.gnu.org/licenses>.
020     */
021    package com.unboundid.ldap.sdk.unboundidds;
022    
023    
024    
025    import com.unboundid.asn1.ASN1OctetString;
026    import com.unboundid.ldap.sdk.Control;
027    import com.unboundid.ldap.sdk.LDAPException;
028    import com.unboundid.util.NotMutable;
029    import com.unboundid.util.ThreadSafety;
030    import com.unboundid.util.ThreadSafetyLevel;
031    import com.unboundid.util.Validator;
032    
033    
034    
035    /**
036     * <BLOCKQUOTE>
037     *   <B>NOTE:</B>  This class is part of the Commercial Edition of the UnboundID
038     *   LDAP SDK for Java.  It is not available for use in applications that
039     *   include only the Standard Edition of the LDAP SDK, and is not supported for
040     *   use in conjunction with non-UnboundID products.
041     * </BLOCKQUOTE>
042     * This class provides an implementation of the UNBOUNDID-TOTP SASL bind request
043     * that may be used to repeatedly generate one-time password values.  Because it
044     * is configured with the shared secret rather than a point-in-time version of
045     * the password, it can be used for cases in which the authentication process
046     * may need to be repeated (e.g., for use in a connection pool, following
047     * referrals, or if the auto-reconnect feature is enabled).  If the shared
048     * secret is not known and the one-time password will be provided from an
049     * external source (e.g., entered by a user), then the
050     * {@link SingleUseTOTPBindRequest} variant should be used instead.
051      */
052    @NotMutable()
053    @ThreadSafety(level=ThreadSafetyLevel.NOT_THREADSAFE)
054    public final class ReusableTOTPBindRequest
055           extends UnboundIDTOTPBindRequest
056    {
057      /**
058       * The serial version UID for this serializable class.
059       */
060      private static final long serialVersionUID = -8283436883838802510L;
061    
062    
063    
064      // The shared secret key to use when generating the TOTP password.
065      private final byte[] sharedSecret;
066    
067      // The duration (in seconds) of the time interval to use when generating the
068      // TOTP password.
069      private final int totpIntervalDurationSeconds;
070    
071      // The number of digits to include in the generated TOTP password.
072      private final int totpNumDigits;
073    
074    
075    
076      /**
077       * Creates a new SASL TOTP bind request with the provided information.
078       *
079       * @param  authenticationID  The authentication identity for the bind request.
080       *                           It must not be {@code null}, and must be in the
081       *                           form "u:" followed by a username, or "dn:"
082       *                           followed by a DN.
083       * @param  authorizationID   The authorization identity for the bind request.
084       *                           It may be {@code null} if the authorization
085       *                           identity should be the same as the authentication
086       *                           identity.  If an authorization identity is
087       *                           specified, it must be in the form "u:" followed
088       *                           by a username, or "dn:" followed by a DN.  The
089       *                           value "dn:" may indicate an authorization
090       *                           identity of the anonymous user.
091       * @param  sharedSecret      The shared secret key to use when generating the
092       *                           TOTP password.
093       * @param  staticPassword    The static password for the target user.  It may
094       *                           be {@code null} if only the one-time password is
095       *                           to be used for authentication (which may or may
096       *                           not be allowed by the server).
097       * @param  controls          The set of controls to include in the bind
098       *                           request.
099       */
100      public ReusableTOTPBindRequest(final String authenticationID,
101                                     final String authorizationID,
102                                     final byte[] sharedSecret,
103                                     final String staticPassword,
104                                     final Control... controls)
105      {
106        this(authenticationID, authorizationID, sharedSecret, staticPassword,
107             OneTimePassword.DEFAULT_TOTP_INTERVAL_DURATION_SECONDS,
108             OneTimePassword.DEFAULT_TOTP_NUM_DIGITS);
109      }
110    
111    
112    
113      /**
114       * Creates a new SASL TOTP bind request with the provided information.
115       *
116       * @param  authenticationID  The authentication identity for the bind request.
117       *                           It must not be {@code null}, and must be in the
118       *                           form "u:" followed by a username, or "dn:"
119       *                           followed by a DN.
120       * @param  authorizationID   The authorization identity for the bind request.
121       *                           It may be {@code null} if the authorization
122       *                           identity should be the same as the authentication
123       *                           identity.  If an authorization identity is
124       *                           specified, it must be in the form "u:" followed
125       *                           by a username, or "dn:" followed by a DN.  The
126       *                           value "dn:" may indicate an authorization
127       *                           identity of the anonymous user.
128       * @param  sharedSecret      The shared secret key to use when generating the
129       *                           TOTP password.
130       * @param  staticPassword    The static password for the target user.  It may
131       *                           be {@code null} if only the one-time password is
132       *                           to be used for authentication (which may or may
133       *                           not be allowed by the server).
134       * @param  controls          The set of controls to include in the bind
135       *                           request.
136       */
137      public ReusableTOTPBindRequest(final String authenticationID,
138                                     final String authorizationID,
139                                     final byte[] sharedSecret,
140                                     final byte[] staticPassword,
141                                     final Control... controls)
142      {
143        this(authenticationID, authorizationID, sharedSecret, staticPassword,
144             OneTimePassword.DEFAULT_TOTP_INTERVAL_DURATION_SECONDS,
145             OneTimePassword.DEFAULT_TOTP_NUM_DIGITS, controls);
146      }
147    
148    
149    
150      /**
151       * Creates a new SASL TOTP bind request with the provided information.
152       *
153       * @param  authenticationID             The authentication identity for the
154       *                                      bind request.  It must not be
155       *                                      {@code null}, and must be in the form
156       *                                      "u:" followed by a username, or "dn:"
157       *                                      followed by a DN.
158       * @param  authorizationID              The authorization identity for the
159       *                                      bind request.  It may be {@code null}
160       *                                      if the authorization identity should
161       *                                      be the same as the authentication
162       *                                      identity.  If an authorization
163       *                                      identity is specified, it must be in
164       *                                      the form "u:" followed by a username,
165       *                                      or "dn:" followed by a DN.  The value
166       *                                      "dn:" may indicate an authorization
167       *                                      identity of the anonymous user.
168       * @param  sharedSecret                 The shared secret key to use when
169       *                                      generating the TOTP password.
170       * @param  staticPassword               The static password for the target
171       *                                      user.  It may be {@code null} if only
172       *                                      the one-time password is to be used
173       *                                      for authentication (which may or may
174       *                                      not be allowed by the server).
175       * @param  totpIntervalDurationSeconds  The duration (in seconds) of the time
176       *                                      interval to use for TOTP processing.
177       *                                      It must be greater than zero.
178       * @param  totpNumDigits                The number of digits to include in the
179       *                                      generated TOTP password.  It must be
180       *                                      greater than or equal to six and less
181       *                                      than or equal to eight.
182       * @param  controls                     The set of controls to include in the
183       *                                      bind request.
184       */
185      public ReusableTOTPBindRequest(final String authenticationID,
186                                     final String authorizationID,
187                                     final byte[] sharedSecret,
188                                     final String staticPassword,
189                                     final int totpIntervalDurationSeconds,
190                                     final int totpNumDigits,
191                                     final Control... controls)
192      {
193        super(authenticationID, authorizationID, staticPassword, controls);
194    
195        Validator.ensureTrue(totpIntervalDurationSeconds > 0);
196        Validator.ensureTrue((totpNumDigits >= 6) && (totpNumDigits <= 8));
197    
198        this.sharedSecret                = sharedSecret;
199        this.totpIntervalDurationSeconds = totpIntervalDurationSeconds;
200        this.totpNumDigits               = totpNumDigits;
201      }
202    
203    
204    
205      /**
206       * Creates a new SASL TOTP bind request with the provided information.
207       *
208       * @param  authenticationID             The authentication identity for the
209       *                                      bind request.  It must not be
210       *                                      {@code null}, and must be in the form
211       *                                      "u:" followed by a username, or "dn:"
212       *                                      followed by a DN.
213       * @param  authorizationID              The authorization identity for the
214       *                                      bind request.  It may be {@code null}
215       *                                      if the authorization identity should
216       *                                      be the same as the authentication
217       *                                      identity.  If an authorization
218       *                                      identity is specified, it must be in
219       *                                      the form "u:" followed by a username,
220       *                                      or "dn:" followed by a DN.  The value
221       *                                      "dn:" may indicate an authorization
222       *                                      identity of the anonymous user.
223       * @param  sharedSecret                 The shared secret key to use when
224       *                                      generating the TOTP password.
225       * @param  staticPassword               The static password for the target
226       *                                      user.  It may be {@code null} if only
227       *                                      the one-time password is to be used
228       *                                      for authentication (which may or may
229       *                                      not be allowed by the server).
230       * @param  totpIntervalDurationSeconds  The duration (in seconds) of the time
231       *                                      interval to use for TOTP processing.
232       *                                      It must be greater than zero.
233       * @param  totpNumDigits                The number of digits to include in the
234       *                                      generated TOTP password.  It must be
235       *                                      greater than or equal to six and less
236       *                                      than or equal to eight.
237       * @param  controls                     The set of controls to include in the
238       *                                      bind request.
239       */
240      public ReusableTOTPBindRequest(final String authenticationID,
241                                     final String authorizationID,
242                                     final byte[] sharedSecret,
243                                     final byte[] staticPassword,
244                                     final int totpIntervalDurationSeconds,
245                                     final int totpNumDigits,
246                                     final Control... controls)
247      {
248        super(authenticationID, authorizationID, staticPassword, controls);
249    
250        Validator.ensureTrue(totpIntervalDurationSeconds > 0);
251        Validator.ensureTrue((totpNumDigits >= 6) && (totpNumDigits <= 8));
252    
253        this.sharedSecret                = sharedSecret;
254        this.totpIntervalDurationSeconds = totpIntervalDurationSeconds;
255        this.totpNumDigits               = totpNumDigits;
256      }
257    
258    
259    
260      /**
261       * Creates a new SASL TOTP bind request with the provided information.
262       *
263       * @param  authenticationID             The authentication identity for the
264       *                                      bind request.  It must not be
265       *                                      {@code null}, and must be in the form
266       *                                      "u:" followed by a username, or "dn:"
267       *                                      followed by a DN.
268       * @param  authorizationID              The authorization identity for the
269       *                                      bind request.  It may be {@code null}
270       *                                      if the authorization identity should
271       *                                      be the same as the authentication
272       *                                      identity.  If an authorization
273       *                                      identity is specified, it must be in
274       *                                      the form "u:" followed by a username,
275       *                                      or "dn:" followed by a DN.  The value
276       *                                      "dn:" may indicate an authorization
277       *                                      identity of the anonymous user.
278       * @param  sharedSecret                 The shared secret key to use when
279       *                                      generating the TOTP password.
280       * @param  staticPassword               The static password for the target
281       *                                      user.  It may be {@code null} if only
282       *                                      the one-time password is to be used
283       *                                      for authentication (which may or may
284       *                                      not be allowed by the server).
285       * @param  totpIntervalDurationSeconds  The duration (in seconds) of the time
286       *                                      interval to use when generating the
287       *                                      TOTP password.  It must be greater
288       *                                      than zero.
289       * @param  totpNumDigits                The number of digits to include in the
290       *                                      generated TOTP password.  It must be
291       *                                      greater than or equal to six and less
292       *                                      than or equal to eight.
293       * @param  controls                     The set of controls to include in the
294       *                                      bind request.
295       */
296      private ReusableTOTPBindRequest(final String authenticationID,
297                                      final String authorizationID,
298                                      final byte[] sharedSecret,
299                                      final ASN1OctetString staticPassword,
300                                      final int totpIntervalDurationSeconds,
301                                      final int totpNumDigits,
302                                      final Control... controls)
303      {
304        super(authenticationID, authorizationID, staticPassword, controls);
305    
306        this.sharedSecret                = sharedSecret;
307        this.totpIntervalDurationSeconds = totpIntervalDurationSeconds;
308        this.totpNumDigits               = totpNumDigits;
309      }
310    
311    
312    
313      /**
314       * Retrieves the shared secret key to use when generating the TOTP password.
315       *
316       * @return  The shared secret key to use when generating the TOTP password.
317       */
318      public byte[] getSharedSecret()
319      {
320        return sharedSecret;
321      }
322    
323    
324    
325      /**
326       * Retrieves the duration (in seconds) of the time interval to use when
327       * generating the TOTP password.
328       *
329       * @return  The duration (in seconds) of the time interval to use when
330       *          generating the TOTP password.
331       */
332      public int getTOTPIntervalDurationSeconds()
333      {
334        return totpIntervalDurationSeconds;
335      }
336    
337    
338    
339      /**
340       * Retrieves the number of digits to include in the generated TOTP password.
341       *
342       * @return  The number of digits to include in the generated TOTP password.
343       */
344      public int getTOTPNumDigits()
345      {
346        return totpNumDigits;
347      }
348    
349    
350    
351      /**
352       * {@inheritDoc}
353       */
354      @Override()
355      protected ASN1OctetString getSASLCredentials()
356                throws LDAPException
357      {
358        // Generate the TOTP password.
359        final String totpPassword = OneTimePassword.totp(sharedSecret,
360             System.currentTimeMillis(), totpIntervalDurationSeconds,
361             totpNumDigits);
362    
363        return encodeCredentials(getAuthenticationID(), getAuthorizationID(),
364             totpPassword, getStaticPassword());
365      }
366    
367    
368    
369      /**
370       * {@inheritDoc}
371       */
372      @Override()
373      public ReusableTOTPBindRequest getRebindRequest(final String host,
374                                                      final int port)
375      {
376        return duplicate();
377      }
378    
379    
380    
381      /**
382       * {@inheritDoc}
383       */
384      @Override()
385      public ReusableTOTPBindRequest duplicate()
386      {
387        return duplicate(getControls());
388      }
389    
390    
391    
392      /**
393       * {@inheritDoc}
394       */
395      @Override()
396      public ReusableTOTPBindRequest duplicate(final Control[] controls)
397      {
398        final ReusableTOTPBindRequest bindRequest =
399             new ReusableTOTPBindRequest(getAuthenticationID(),
400                  getAuthorizationID(), sharedSecret, getStaticPassword(),
401                  totpIntervalDurationSeconds, totpNumDigits, controls);
402        bindRequest.setResponseTimeoutMillis(getResponseTimeoutMillis(null));
403        return bindRequest;
404      }
405    }