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 }