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