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 }