001/* 002 * Copyright 2013-2018 Ping Identity Corporation 003 * All Rights Reserved. 004 */ 005/* 006 * Copyright (C) 2015-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.ExtendedResult; 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; 039import com.unboundid.util.Validator; 040 041import static com.unboundid.ldap.sdk.unboundidds.extensions.ExtOpMessages.*; 042 043 044 045/** 046 * This class provides an implementation of an extended result that may be used 047 * to provide information about the result of processing for a deliver one-time 048 * password extended request. If the one-time password was delivered 049 * successfully, then this result will include information about the mechanism 050 * through which that message was delivered. 051 * <BR> 052 * <BLOCKQUOTE> 053 * <B>NOTE:</B> This class, and other classes within the 054 * {@code com.unboundid.ldap.sdk.unboundidds} package structure, are only 055 * supported for use against Ping Identity, UnboundID, and Alcatel-Lucent 8661 056 * server products. These classes provide support for proprietary 057 * functionality or for external specifications that are not considered stable 058 * or mature enough to be guaranteed to work in an interoperable way with 059 * other types of LDAP servers. 060 * </BLOCKQUOTE> 061 * <BR> 062 * If the request was processed successfully, then the extended result will have 063 * an OID of 1.3.6.1.4.1.30221.2.6.25 and a value with the following encoding: 064 * <BR><BR> 065 * <PRE> 066 * DeliverOTPResult ::= SEQUENCE { 067 * deliveryMechanism [0] OCTET STRING, 068 * recipientDN [1] LDAPDN, 069 * recipientID [2] OCTET STRING OPTIONAL, 070 * message [3] OCTET STRING OPTIONAL, 071 * ... } 072 * </PRE> 073 * 074 * @see com.unboundid.ldap.sdk.unboundidds.UnboundIDDeliveredOTPBindRequest 075 * @see DeliverOneTimePasswordExtendedRequest 076 */ 077@NotMutable() 078@ThreadSafety(level=ThreadSafetyLevel.COMPLETELY_THREADSAFE) 079public final class DeliverOneTimePasswordExtendedResult 080 extends ExtendedResult 081{ 082 /** 083 * The OID (1.3.6.1.4.1.30221.2.6.25) for the deliver one-time password 084 * extended result. 085 */ 086 public static final String DELIVER_OTP_RESULT_OID = 087 "1.3.6.1.4.1.30221.2.6.25"; 088 089 090 091 /** 092 * The BER type for the delivery mechanism element. 093 */ 094 private static final byte TYPE_MECH = (byte) 0x80; 095 096 097 098 /** 099 * The BER type for the recipient DN element. 100 */ 101 private static final byte TYPE_RECIPIENT_DN = (byte) 0x81; 102 103 104 105 /** 106 * The BER type for the recipient ID element. 107 */ 108 private static final byte TYPE_RECIPIENT_ID = (byte) 0x82; 109 110 111 112 /** 113 * The BER type for the delivery message element. 114 */ 115 private static final byte TYPE_MESSAGE = (byte) 0x83; 116 117 118 119 /** 120 * The serial version UID for this serializable class. 121 */ 122 private static final long serialVersionUID = 5077693879184160485L; 123 124 125 126 // The name of the mechanism by which the one-time password was delivered. 127 private final String deliveryMechanism; 128 129 // An message providing additional information about the delivery of the 130 // one-time password. 131 private final String deliveryMessage; 132 133 // An the DN of the user to whom the one-time password was sent. 134 private final String recipientDN; 135 136 // An identifier for the recipient of the one-time password. 137 private final String recipientID; 138 139 140 141 /** 142 * Creates a new deliver one-time password extended result from the provided 143 * generic extended result. 144 * 145 * @param extendedResult The generic extended result to be parsed as a 146 * deliver one-time password result. 147 * 148 * @throws LDAPException If the provided extended result cannot be parsed as 149 * a deliver one-time password result. 150 */ 151 public DeliverOneTimePasswordExtendedResult( 152 final ExtendedResult extendedResult) 153 throws LDAPException 154 { 155 super(extendedResult); 156 157 final ASN1OctetString value = extendedResult.getValue(); 158 if (value == null) 159 { 160 deliveryMechanism = null; 161 recipientDN = null; 162 recipientID = null; 163 deliveryMessage = null; 164 return; 165 } 166 167 String mech = null; 168 String dn = null; 169 String id = null; 170 String message = null; 171 try 172 { 173 for (final ASN1Element e : 174 ASN1Sequence.decodeAsSequence(value.getValue()).elements()) 175 { 176 switch (e.getType()) 177 { 178 case TYPE_MECH: 179 mech = ASN1OctetString.decodeAsOctetString(e).stringValue(); 180 break; 181 case TYPE_RECIPIENT_DN: 182 dn = ASN1OctetString.decodeAsOctetString(e).stringValue(); 183 break; 184 case TYPE_RECIPIENT_ID: 185 id = ASN1OctetString.decodeAsOctetString(e).stringValue(); 186 break; 187 case TYPE_MESSAGE: 188 message = ASN1OctetString.decodeAsOctetString(e).stringValue(); 189 break; 190 default: 191 throw new LDAPException(ResultCode.DECODING_ERROR, 192 ERR_DELIVER_OTP_RES_UNEXPECTED_ELEMENT_TYPE.get( 193 StaticUtils.toHex(e.getType()))); 194 } 195 } 196 } 197 catch (final LDAPException le) 198 { 199 Debug.debugException(le); 200 throw le; 201 } 202 catch (final Exception e) 203 { 204 Debug.debugException(e); 205 throw new LDAPException(ResultCode.DECODING_ERROR, 206 ERR_DELIVER_OTP_RES_ERROR_PARSING_VALUE.get( 207 StaticUtils.getExceptionMessage(e)), 208 e); 209 } 210 211 212 if (mech == null) 213 { 214 throw new LDAPException(ResultCode.DECODING_ERROR, 215 ERR_DELIVER_OTP_RES_NO_MECH.get()); 216 } 217 else 218 { 219 deliveryMechanism = mech; 220 } 221 222 if (dn == null) 223 { 224 throw new LDAPException(ResultCode.DECODING_ERROR, 225 ERR_DELIVER_OTP_RES_NO_RECIPIENT_DN.get()); 226 } 227 else 228 { 229 recipientDN = dn; 230 } 231 232 recipientID = id; 233 deliveryMessage = message; 234 } 235 236 237 238 /** 239 * Creates a new deliver one-time password extended result with the provided 240 * information. 241 * 242 * @param messageID The message ID for the LDAP message that is 243 * associated with this LDAP result. 244 * @param resultCode The result code from the response. 245 * @param diagnosticMessage The diagnostic message from the response, if 246 * available. 247 * @param matchedDN The matched DN from the response, if available. 248 * @param referralURLs The set of referral URLs from the response, if 249 * available. 250 * @param deliveryMechanism The name of the mechanism by which the one-time 251 * password was delivered, if available. This 252 * should be non-{@code null} for a success result. 253 * @param recipientDN The DN of the user to whom the one-time password 254 * was sent. This should be non-{@code null} for a 255 * success result. 256 * @param recipientID An identifier for the user to whom the one-time 257 * password was delivered. It may be {@code null} 258 * if no password was delivered or there is no 259 * appropriate identifier, but if a value is 260 * provided then it should appropriate for the 261 * delivery mechanism (e.g., the user's e-mail 262 * address if delivered via e-mail, a phone number 263 * if delivered via SMS or voice call, etc.). 264 * @param deliveryMessage A message providing additional information about 265 * the one-time password delivery, if available. 266 * If this is non-{@code null}, then the delivery 267 * mechanism must also be non-null. 268 * @param responseControls The set of controls from the response, if 269 * available. 270 */ 271 public DeliverOneTimePasswordExtendedResult(final int messageID, 272 final ResultCode resultCode, final String diagnosticMessage, 273 final String matchedDN, final String[] referralURLs, 274 final String deliveryMechanism, final String recipientDN, 275 final String recipientID, final String deliveryMessage, 276 final Control... responseControls) 277 { 278 super(messageID, resultCode, diagnosticMessage, matchedDN, referralURLs, 279 ((deliveryMechanism == null) ? null : DELIVER_OTP_RESULT_OID), 280 encodeValue(deliveryMechanism, recipientDN, recipientID, 281 deliveryMessage), 282 responseControls); 283 284 this.deliveryMechanism = deliveryMechanism; 285 this.recipientDN = recipientDN; 286 this.recipientID = recipientID; 287 this.deliveryMessage = deliveryMessage; 288 } 289 290 291 292 /** 293 * Encodes the provided information into an ASN.1 octet string suitable for 294 * use as the value of this extended result. 295 * 296 * @param deliveryMechanism The name of the mechanism by which the one-time 297 * password was delivered, if available. This 298 * should be non-{@code null} for a success result. 299 * @param recipientDN The DN of the user to whom the one-time password 300 * was sent. This should be non-{@code null} for a 301 * success result. 302 * @param recipientID An identifier for the user to whom the one-time 303 * password was delivered. It may be {@code null} 304 * if no password was delivered or there is no 305 * appropriate identifier, but if a value is 306 * provided then it should appropriate for the 307 * delivery mechanism (e.g., the user's e-mail 308 * address if delivered via e-mail, a phone number 309 * if delivered via SMS or voice call, etc.). 310 * @param deliveryMessage A message providing additional information about 311 * the one-time password delivery, if available. 312 * If this is non-{@code null}, then the delivery 313 * mechanism must also be non-null. 314 * 315 * @return An ASN.1 octet string containing the encoded value, or 316 * {@code null} if the extended result should not have a value. 317 */ 318 private static ASN1OctetString encodeValue(final String deliveryMechanism, 319 final String recipientDN, 320 final String recipientID, 321 final String deliveryMessage) 322 { 323 if (deliveryMechanism == null) 324 { 325 Validator.ensureTrue((recipientID == null), 326 "The delivery mechanism must be non-null if the recipient ID " + 327 "is non-null."); 328 Validator.ensureTrue((deliveryMessage == null), 329 "The delivery mechanism must be non-null if the delivery message " + 330 "is non-null."); 331 return null; 332 } 333 334 Validator.ensureTrue((recipientDN != null), 335 "If a delivery mechanism is provided, then a recipient DN must also " + 336 "be provided."); 337 338 final ArrayList<ASN1Element> elements = new ArrayList<ASN1Element>(4); 339 elements.add(new ASN1OctetString(TYPE_MECH, deliveryMechanism)); 340 elements.add(new ASN1OctetString(TYPE_RECIPIENT_DN, recipientDN)); 341 342 if (recipientID != null) 343 { 344 elements.add(new ASN1OctetString(TYPE_RECIPIENT_ID, recipientID)); 345 } 346 347 if (deliveryMessage != null) 348 { 349 elements.add(new ASN1OctetString(TYPE_MESSAGE, deliveryMessage)); 350 } 351 352 return new ASN1OctetString(new ASN1Sequence(elements).encode()); 353 } 354 355 356 357 /** 358 * Retrieves the name of the mechanism by which the one-time password was 359 * delivered to the end user, if available. 360 * 361 * @return The name of the mechanism by which the one-time password was 362 * delivered to the end user, or {@code null} if this is not 363 * available. 364 */ 365 public String getDeliveryMechanism() 366 { 367 return deliveryMechanism; 368 } 369 370 371 372 /** 373 * Retrieves the DN of the user to whom the one-time password was delivered, 374 * if available. 375 * 376 * @return The DN of the user to whom the one-time password was delivered, or 377 * {@code null} if this is not available. 378 */ 379 public String getRecipientDN() 380 { 381 return recipientDN; 382 } 383 384 385 386 /** 387 * Retrieves an identifier for the user to whom the one-time password was 388 * delivered, if available. If a recipient ID is provided, then it should be 389 * in a form appropriate to the delivery mechanism (e.g., an e-mail address 390 * if the password was delivered by e-mail, a phone number if it was delivered 391 * by SMS or a voice call, etc.). 392 * 393 * @return An identifier for the user to whom the one-time password was 394 * delivered, or {@code null} if this is not available. 395 */ 396 public String getRecipientID() 397 { 398 return recipientID; 399 } 400 401 402 403 /** 404 * Retrieves a message providing additional information about the one-time 405 * password delivery, if available. 406 * 407 * @return A message providing additional information about the one-time 408 * password delivery, or {@code null} if this is not available. 409 */ 410 public String getDeliveryMessage() 411 { 412 return deliveryMessage; 413 } 414 415 416 417 /** 418 * {@inheritDoc} 419 */ 420 @Override() 421 public String getExtendedResultName() 422 { 423 return INFO_DELIVER_OTP_RES_NAME.get(); 424 } 425 426 427 428 /** 429 * Appends a string representation of this extended result to the provided 430 * buffer. 431 * 432 * @param buffer The buffer to which a string representation of this 433 * extended result will be appended. 434 */ 435 @Override() 436 public void toString(final StringBuilder buffer) 437 { 438 buffer.append("DeliverOneTimePasswordExtendedResult(resultCode="); 439 buffer.append(getResultCode()); 440 441 final int messageID = getMessageID(); 442 if (messageID >= 0) 443 { 444 buffer.append(", messageID="); 445 buffer.append(messageID); 446 } 447 448 if (deliveryMechanism != null) 449 { 450 buffer.append(", deliveryMechanism='"); 451 buffer.append(deliveryMechanism); 452 buffer.append('\''); 453 } 454 455 if (recipientDN != null) 456 { 457 buffer.append(", recipientDN='"); 458 buffer.append(recipientDN); 459 buffer.append('\''); 460 } 461 462 if (recipientID != null) 463 { 464 buffer.append(", recipientID='"); 465 buffer.append(recipientID); 466 buffer.append('\''); 467 } 468 469 if (deliveryMessage != null) 470 { 471 buffer.append(", deliveryMessage='"); 472 buffer.append(deliveryMessage); 473 buffer.append('\''); 474 } 475 476 final String diagnosticMessage = getDiagnosticMessage(); 477 if (diagnosticMessage != null) 478 { 479 buffer.append(", diagnosticMessage='"); 480 buffer.append(diagnosticMessage); 481 buffer.append('\''); 482 } 483 484 final String matchedDN = getMatchedDN(); 485 if (matchedDN != null) 486 { 487 buffer.append(", matchedDN='"); 488 buffer.append(matchedDN); 489 buffer.append('\''); 490 } 491 492 final String[] referralURLs = getReferralURLs(); 493 if (referralURLs.length > 0) 494 { 495 buffer.append(", referralURLs={"); 496 for (int i=0; i < referralURLs.length; i++) 497 { 498 if (i > 0) 499 { 500 buffer.append(", "); 501 } 502 503 buffer.append('\''); 504 buffer.append(referralURLs[i]); 505 buffer.append('\''); 506 } 507 buffer.append('}'); 508 } 509 510 final Control[] responseControls = getResponseControls(); 511 if (responseControls.length > 0) 512 { 513 buffer.append(", responseControls={"); 514 for (int i=0; i < responseControls.length; i++) 515 { 516 if (i > 0) 517 { 518 buffer.append(", "); 519 } 520 521 buffer.append(responseControls[i]); 522 } 523 buffer.append('}'); 524 } 525 526 buffer.append(')'); 527 } 528}