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