001/* 002 * Copyright 2016-2018 Ping Identity Corporation 003 * All Rights Reserved. 004 */ 005/* 006 * Copyright (C) 2016-2018 Ping Identity Corporation 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 */ 021package com.unboundid.ldap.sdk.unboundidds.extensions; 022 023 024 025import java.util.ArrayList; 026 027import com.unboundid.asn1.ASN1Element; 028import com.unboundid.asn1.ASN1OctetString; 029import com.unboundid.asn1.ASN1Sequence; 030import com.unboundid.ldap.sdk.Control; 031import com.unboundid.ldap.sdk.ExtendedRequest; 032import com.unboundid.ldap.sdk.LDAPException; 033import com.unboundid.ldap.sdk.ResultCode; 034import com.unboundid.util.Debug; 035import com.unboundid.util.NotMutable; 036import com.unboundid.util.StaticUtils; 037import com.unboundid.util.ThreadSafety; 038import com.unboundid.util.ThreadSafetyLevel; 039 040import static com.unboundid.ldap.sdk.unboundidds.extensions.ExtOpMessages.*; 041 042 043 044/** 045 * This class provides an implementation of an extended request that may be used 046 * to deregister a YubiKey OTP device with the Directory Server so that it may 047 * no longer used to authenticate using the UNBOUNDID-YUBIKEY-OTP SASL 048 * mechanism. 049 * <BR> 050 * <BLOCKQUOTE> 051 * <B>NOTE:</B> This class, and other classes within the 052 * {@code com.unboundid.ldap.sdk.unboundidds} package structure, are only 053 * supported for use against Ping Identity, UnboundID, and Alcatel-Lucent 8661 054 * server products. These classes provide support for proprietary 055 * functionality or for external specifications that are not considered stable 056 * or mature enough to be guaranteed to work in an interoperable way with 057 * other types of LDAP servers. 058 * </BLOCKQUOTE> 059 * <BR> 060 * This extended request has an OID of 1.3.6.1.4.1.30221.2.6.55, and it must 061 * include a request value with the following encoding: 062 * <BR><BR> 063 * <PRE> 064 * DeregisterYubiKeyOTPDeviceRequest ::= SEQUENCE { 065 * authenticationID [0] OCTET STRING OPTIONAL, 066 * staticPassword [1] OCTET STRING OPTIONAL, 067 * yubiKeyOTP [2] OCTET STRING OPTIONAL, 068 * ... } 069 * </PRE> 070 * 071 * 072 * @see RegisterYubiKeyOTPDeviceExtendedRequest 073 * @see com.unboundid.ldap.sdk.unboundidds.UnboundIDYubiKeyOTPBindRequest 074 * @see com.unboundid.ldap.sdk.unboundidds.RegisterYubiKeyOTPDevice 075 */ 076@NotMutable() 077@ThreadSafety(level=ThreadSafetyLevel.COMPLETELY_THREADSAFE) 078public final class DeregisterYubiKeyOTPDeviceExtendedRequest 079 extends ExtendedRequest 080{ 081 /** 082 * The OID (1.3.6.1.4.1.30221.2.6.55) for the deregister YubiKey OTP device 083 * extended request. 084 */ 085 public static final String DEREGISTER_YUBIKEY_OTP_DEVICE_REQUEST_OID = 086 "1.3.6.1.4.1.30221.2.6.55"; 087 088 089 090 /** 091 * The BER type for the authentication ID element of the request value 092 * sequence. 093 */ 094 private static final byte TYPE_AUTHENTICATION_ID = (byte) 0x80; 095 096 097 098 /** 099 * The BER type for the static password element of the request value sequence. 100 */ 101 private static final byte TYPE_STATIC_PASSWORD = (byte) 0x81; 102 103 104 105 /** 106 * The BER type for the YubiKey OTP element of the request value sequence. 107 */ 108 private static final byte TYPE_YUBIKEY_OTP = (byte) 0x82; 109 110 111 112 /** 113 * The serial version UID for this serializable class. 114 */ 115 private static final long serialVersionUID = -4029230013825076585L; 116 117 118 119 // The static password for the request. 120 private final ASN1OctetString staticPassword; 121 122 // The authentication ID for the request. 123 private final String authenticationID; 124 125 // The YubiKey OTP for the request. 126 private final String yubiKeyOTP; 127 128 129 130 /** 131 * Creates a new deregister YubiKey OTP device extended request with the 132 * provided information. 133 * 134 * @param authenticationID The authentication ID that identifies the user 135 * for whom the YubiKey OTP device is to be 136 * deregistered. It may be {@code null} if the 137 * device is to be deregistered for the user as whom 138 * the underlying connection is authenticated. 139 * @param yubiKeyOTP An optional one-time password generated by the 140 * YubiKey device to be deregistered. If this is 141 * {@code null}, then all YubiKey OTP devices 142 * associated with the target user will be 143 * deregistered. If it is non-{@code null}, then 144 * only the YubiKey device used to generate the OTP 145 * will be deregistered. 146 * @param controls The set of controls to include in the request. 147 * It may be {@code null} or empty if there should 148 * not be any request controls. 149 */ 150 public DeregisterYubiKeyOTPDeviceExtendedRequest( 151 final String authenticationID, final String yubiKeyOTP, 152 final Control... controls) 153 { 154 this(authenticationID, (ASN1OctetString) null, yubiKeyOTP, controls); 155 } 156 157 158 159 /** 160 * Creates a new deregister YubiKey OTP device extended request with the 161 * provided information. 162 * 163 * @param authenticationID The authentication ID that identifies the user 164 * for whom the YubiKey OTP device is to be 165 * deregistered. It may be {@code null} if the 166 * device is to be deregistered for the user as whom 167 * the underlying connection is authenticated. 168 * @param staticPassword The static password of the user for whom the 169 * device is to be deregistered. It may be 170 * {@code null} if the server is configured to not 171 * require a static password when deregistering one 172 * or more devices. 173 * @param yubiKeyOTP An optional one-time password generated by the 174 * YubiKey device to be deregistered. If this is 175 * {@code null}, then all YubiKey OTP devices 176 * associated with the target user will be 177 * deregistered. If it is non-{@code null}, then 178 * only the YubiKey device used to generate the OTP 179 * will be deregistered. 180 * @param controls The set of controls to include in the request. 181 * It may be {@code null} or empty if there should 182 * not be any request controls. 183 */ 184 public DeregisterYubiKeyOTPDeviceExtendedRequest( 185 final String authenticationID, final String staticPassword, 186 final String yubiKeyOTP, final Control... controls) 187 { 188 this(authenticationID, 189 RegisterYubiKeyOTPDeviceExtendedRequest.encodePassword(staticPassword), 190 yubiKeyOTP, controls); 191 } 192 193 194 195 /** 196 * Creates a new deregister YubiKey OTP device extended request with the 197 * provided information. 198 * 199 * @param authenticationID The authentication ID that identifies the user 200 * for whom the YubiKey OTP device is to be 201 * deregistered. It may be {@code null} if the 202 * device is to be deregistered for the user as whom 203 * the underlying connection is authenticated. 204 * @param staticPassword The static password of the user for whom the 205 * device is to be deregistered. It may be 206 * {@code null} if the server is configured to not 207 * require a static password when deregistering one 208 * or more devices. 209 * @param yubiKeyOTP An optional one-time password generated by the 210 * YubiKey device to be deregistered. If this is 211 * {@code null}, then all YubiKey OTP devices 212 * associated with the target user will be 213 * deregistered. If it is non-{@code null}, then 214 * only the YubiKey device used to generate the OTP 215 * will be deregistered. 216 * @param controls The set of controls to include in the request. 217 * It may be {@code null} or empty if there should 218 * not be any request controls. 219 */ 220 public DeregisterYubiKeyOTPDeviceExtendedRequest( 221 final String authenticationID, final byte[] staticPassword, 222 final String yubiKeyOTP, final Control... controls) 223 { 224 this(authenticationID, 225 RegisterYubiKeyOTPDeviceExtendedRequest.encodePassword(staticPassword), 226 yubiKeyOTP, controls); 227 } 228 229 230 231 /** 232 * Creates a new deregister YubiKey OTP device extended request with the 233 * provided information. 234 * 235 * @param authenticationID The authentication ID that identifies the user 236 * for whom the YubiKey OTP device is to be 237 * deregistered. It may be {@code null} if the 238 * device is to be deregistered for the user as whom 239 * the underlying connection is authenticated. 240 * @param staticPassword The static password of the user for whom the 241 * device is to be deregistered. It may be 242 * {@code null} if the server is configured to not 243 * require a static password when deregistering one 244 * or more devices. 245 * @param yubiKeyOTP An optional one-time password generated by the 246 * YubiKey device to be deregistered. If this is 247 * {@code null}, then all YubiKey OTP devices 248 * associated with the target user will be 249 * deregistered. If it is non-{@code null}, then 250 * only the YubiKey device used to generate the OTP 251 * will be deregistered. 252 * @param controls The set of controls to include in the request. 253 * It may be {@code null} or empty if there should 254 * not be any request controls. 255 */ 256 private DeregisterYubiKeyOTPDeviceExtendedRequest( 257 final String authenticationID, 258 final ASN1OctetString staticPassword, final String yubiKeyOTP, 259 final Control... controls) 260 { 261 super(DEREGISTER_YUBIKEY_OTP_DEVICE_REQUEST_OID, 262 encodeValue(authenticationID, staticPassword, yubiKeyOTP), controls); 263 264 this.authenticationID = authenticationID; 265 this.staticPassword = staticPassword; 266 this.yubiKeyOTP = yubiKeyOTP; 267 } 268 269 270 271 /** 272 * Creates a new deregister YubiKey OTP device extended request that is 273 * decoded from the provided generic extended request. 274 * 275 * @param request The generic extended request to decode as a deregister 276 * YubiKey OTP device request. 277 * 278 * @throws LDAPException If a problem is encountered while attempting to 279 * decode the provided request. 280 */ 281 public DeregisterYubiKeyOTPDeviceExtendedRequest( 282 final ExtendedRequest request) 283 throws LDAPException 284 { 285 super(request); 286 287 final ASN1OctetString value = request.getValue(); 288 if (value == null) 289 { 290 throw new LDAPException(ResultCode.DECODING_ERROR, 291 ERR_DEREGISTER_YUBIKEY_OTP_REQUEST_NO_VALUE.get()); 292 } 293 294 try 295 { 296 String authID = null; 297 ASN1OctetString staticPW = null; 298 String otp = null; 299 for (final ASN1Element e : 300 ASN1Sequence.decodeAsSequence(value.getValue()).elements()) 301 { 302 switch (e.getType()) 303 { 304 case TYPE_AUTHENTICATION_ID: 305 authID = ASN1OctetString.decodeAsOctetString(e).stringValue(); 306 break; 307 case TYPE_STATIC_PASSWORD: 308 staticPW = ASN1OctetString.decodeAsOctetString(e); 309 break; 310 case TYPE_YUBIKEY_OTP: 311 otp = ASN1OctetString.decodeAsOctetString(e).stringValue(); 312 break; 313 default: 314 throw new LDAPException(ResultCode.DECODING_ERROR, 315 ERR_DEREGISTER_YUBIKEY_OTP_REQUEST_UNRECOGNIZED_TYPE.get( 316 StaticUtils.toHex(e.getType()))); 317 } 318 } 319 320 authenticationID = authID; 321 staticPassword = staticPW; 322 yubiKeyOTP = otp; 323 } 324 catch (final LDAPException le) 325 { 326 Debug.debugException(le); 327 throw le; 328 } 329 catch (final Exception e) 330 { 331 Debug.debugException(e); 332 throw new LDAPException(ResultCode.DECODING_ERROR, 333 ERR_DEREGISTER_YUBIKEY_OTP_REQUEST_ERROR_DECODING_VALUE.get( 334 StaticUtils.getExceptionMessage(e)), 335 e); 336 } 337 } 338 339 340 341 /** 342 * Encodes the provided information into an ASN.1 octet string suitable for 343 * use as the value of this extended request. 344 * 345 * @param authenticationID The authentication ID that identifies the user 346 * for whom the YubiKey OTP device is to be 347 * deregistered. It may be {@code null} if the 348 * device is to be deregistered for the user as whom 349 * the underlying connection is authenticated. 350 * @param staticPassword The static password of the user for whom the 351 * device is to be deregistered. It may be 352 * {@code null} if the server is configured to not 353 * require a static password when deregistering one 354 * or more devices. 355 * @param yubiKeyOTP An optional one-time password generated by the 356 * YubiKey device to be deregistered. If this is 357 * {@code null}, then all YubiKey OTP devices 358 * associated with the target user will be 359 * deregistered. If it is non-{@code null}, then 360 * only the YubiKey device used to generate the OTP 361 * will be deregistered. 362 * 363 * @return The ASN.1 octet string containing the encoded request value. 364 */ 365 private static ASN1OctetString encodeValue(final String authenticationID, 366 final ASN1OctetString staticPassword, 367 final String yubiKeyOTP) 368 { 369 final ArrayList<ASN1Element> elements = new ArrayList<ASN1Element>(3); 370 371 if (authenticationID != null) 372 { 373 elements.add( 374 new ASN1OctetString(TYPE_AUTHENTICATION_ID, authenticationID)); 375 } 376 377 if (staticPassword != null) 378 { 379 elements.add(staticPassword); 380 } 381 382 if (yubiKeyOTP != null) 383 { 384 elements.add(new ASN1OctetString(TYPE_YUBIKEY_OTP, yubiKeyOTP)); 385 } 386 387 return new ASN1OctetString(new ASN1Sequence(elements).encode()); 388 } 389 390 391 392 /** 393 * Retrieves the authentication ID that identifies the user from whom the 394 * YubiKey OTP device is to be deregistered, if provided. 395 * 396 * @return The authentication ID that identifies the target user, or 397 * {@code null} if the device is to be deregistered for the user as 398 * whom the underlying connection is authenticated. 399 */ 400 public String getAuthenticationID() 401 { 402 return authenticationID; 403 } 404 405 406 407 /** 408 * Retrieves the string representation of the static password for the target 409 * user, if provided. 410 * 411 * @return The string representation of the static password for the target 412 * user, or {@code null} if no static password was provided. 413 */ 414 public String getStaticPasswordString() 415 { 416 if (staticPassword == null) 417 { 418 return null; 419 } 420 else 421 { 422 return staticPassword.stringValue(); 423 } 424 } 425 426 427 428 /** 429 * Retrieves the bytes that comprise the static password for the target user, 430 * if provided. 431 * 432 * @return The bytes that comprise the static password for the target user, 433 * or {@code null} if no static password was provided. 434 */ 435 public byte[] getStaticPasswordBytes() 436 { 437 if (staticPassword == null) 438 { 439 return null; 440 } 441 else 442 { 443 return staticPassword.getValue(); 444 } 445 } 446 447 448 449 /** 450 * Retrieves a one-time password generated by the YubiKey device to be 451 * deregistered, if provided. 452 * 453 * @return A one-time password generated by the YubiKey device to be 454 * deregistered, or {@code null} if all devices associated with the 455 * target user should be deregistered. 456 */ 457 public String getYubiKeyOTP() 458 { 459 return yubiKeyOTP; 460 } 461 462 463 464 /** 465 * {@inheritDoc} 466 */ 467 @Override() 468 public DeregisterYubiKeyOTPDeviceExtendedRequest duplicate() 469 { 470 return duplicate(getControls()); 471 } 472 473 474 475 /** 476 * {@inheritDoc} 477 */ 478 @Override() 479 public DeregisterYubiKeyOTPDeviceExtendedRequest 480 duplicate(final Control[] controls) 481 { 482 final DeregisterYubiKeyOTPDeviceExtendedRequest r = 483 new DeregisterYubiKeyOTPDeviceExtendedRequest(authenticationID, 484 staticPassword, yubiKeyOTP, controls); 485 r.setResponseTimeoutMillis(getResponseTimeoutMillis(null)); 486 return r; 487 } 488 489 490 491 /** 492 * {@inheritDoc} 493 */ 494 @Override() 495 public String getExtendedRequestName() 496 { 497 return INFO_DEREGISTER_YUBIKEY_OTP_REQUEST_NAME.get(); 498 } 499 500 501 502 /** 503 * {@inheritDoc} 504 */ 505 @Override() 506 public void toString(final StringBuilder buffer) 507 { 508 buffer.append("DeregisterYubiKeyOTPDeviceExtendedRequest("); 509 510 if (authenticationID != null) 511 { 512 buffer.append("authenticationID='"); 513 buffer.append(authenticationID); 514 buffer.append("', "); 515 } 516 517 buffer.append("staticPasswordProvided="); 518 buffer.append(staticPassword != null); 519 buffer.append(", otpProvided="); 520 buffer.append(yubiKeyOTP != null); 521 522 final Control[] controls = getControls(); 523 if (controls.length > 0) 524 { 525 buffer.append(", controls={"); 526 for (int i=0; i < controls.length; i++) 527 { 528 if (i > 0) 529 { 530 buffer.append(", "); 531 } 532 533 buffer.append(controls[i]); 534 } 535 buffer.append('}'); 536 } 537 538 buffer.append(')'); 539 } 540}