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 }