001/*
002 * Copyright 2013-2024 Ping Identity Corporation
003 * All Rights Reserved.
004 */
005/*
006 * Copyright 2013-2024 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) 2013-2024 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;
041import java.util.Collections;
042import java.util.Iterator;
043import java.util.LinkedHashSet;
044import java.util.List;
045
046import com.unboundid.asn1.ASN1Element;
047import com.unboundid.asn1.ASN1OctetString;
048import com.unboundid.asn1.ASN1Sequence;
049import com.unboundid.ldap.sdk.Control;
050import com.unboundid.ldap.sdk.ExtendedRequest;
051import com.unboundid.ldap.sdk.ExtendedResult;
052import com.unboundid.ldap.sdk.LDAPConnection;
053import com.unboundid.ldap.sdk.LDAPException;
054import com.unboundid.ldap.sdk.ResultCode;
055import com.unboundid.util.Debug;
056import com.unboundid.util.NotMutable;
057import com.unboundid.util.NotNull;
058import com.unboundid.util.Nullable;
059import com.unboundid.util.ObjectPair;
060import com.unboundid.util.StaticUtils;
061import com.unboundid.util.ThreadSafety;
062import com.unboundid.util.ThreadSafetyLevel;
063
064import static com.unboundid.ldap.sdk.unboundidds.extensions.ExtOpMessages.*;
065
066
067
068/**
069 * This class provides an implementation of an extended request that may be used
070 * to request that the Directory Server deliver a one-time password to an end
071 * user that they may use to authenticate via an
072 * {@link com.unboundid.ldap.sdk.unboundidds.UnboundIDDeliveredOTPBindRequest}.
073 * <BR>
074 * <BLOCKQUOTE>
075 *   <B>NOTE:</B>  This class, and other classes within the
076 *   {@code com.unboundid.ldap.sdk.unboundidds} package structure, are only
077 *   supported for use against Ping Identity, UnboundID, and
078 *   Nokia/Alcatel-Lucent 8661 server products.  These classes provide support
079 *   for proprietary functionality or for external specifications that are not
080 *   considered stable or mature enough to be guaranteed to work in an
081 *   interoperable way with other types of LDAP servers.
082 * </BLOCKQUOTE>
083 * <BR>
084 * Notes on the recommended use of this extended request:
085 * <UL>
086 *   <LI>Whenever possible, the user's static password should be provided.
087 *       However, the server will allow the static password to be omitted if the
088 *       authentication ID included in the request matches the authorization
089 *       identity of the extended operation (either because that user is already
090 *       authenticated on the connection, or because the request includes a
091 *       proxied authorization or intermediate client control specifying that
092 *       identity).  In that case, the operation will be able to act as a
093 *       "step-up" mechanism, providing further proof of the identity of an
094 *       already-authenticated client rather than performing the complete
095 *       authentication process.</LI>
096 *   <LI>The request offers two mechanisms for indicating which delivery
097 *       mechanism(s) should be considered:  an option to specify just the
098 *       delivery mechanism names, and an option to specify the names along with
099 *       recipient IDs.  At most one of these elements must be present in the
100 *       request.  If neither is present, the server will attempt to determine
101 *       which delivery mechanisms and recipient IDs should be used.  If the
102 *       set of preferred delivery mechanisms includes multiple items, the
103 *       server will attempt them in the order provided until it is able to
104 *       successfully deliver the message.  The server will not attempt to
105 *       use any other delivery mechanisms that may be configured if the request
106 *       includes a list of preferred delivery mechanisms.</LI>
107 *   <LI>Although the message elements (message subject, and full and compact
108 *       text before and after the OTP) are optional, it is recommended that
109 *       they be supplied by the client.  The server will provide a generic
110 *       message if no message elements are included in the request.</LI>
111 * </UL>
112 * <BR><BR>
113 * The OID for this extended request is 1.3.6.1.4.1.30221.2.6.24.  It must have
114 * a value, and that value should have the following encoding:
115 * <BR><BR>
116 * <PRE>
117 *   DeliverOTPRequest ::= SEQUENCE {
118 *        authenticationID             [0] OCTET STRING,
119 *        staticPassword               [1] OCTET STRING OPTIONAL,
120 *        preferredMechNames           [2] SEQUENCE OF OCTET STRING OPTIONAL,
121 *        preferredMechNamesAndIDs     [3] SEQUENCE OF SEQUENCE,
122 *             mechanismName     OCTET STRING,
123 *             recipientID       OCTET STRING OPTIONAL } OPTIONAL,
124 *        messageSubject               [4] OCTET STRING OPTIONAL,
125 *        fullTextBeforeOTP            [5] OCTET STRING OPTIONAL,
126 *        fullTextAfterOTP             [6] OCTET STRING OPTIONAL,
127 *        compactTextBeforeOTP         [7] OCTET STRING OPTIONAL,
128 *        compactTextAfterOTP          [8] OCTET STRING OPTIONAL,
129 *        ... }
130 * </PRE>
131 *
132 * @see  com.unboundid.ldap.sdk.unboundidds.UnboundIDDeliveredOTPBindRequest
133 * @see  DeliverOneTimePasswordExtendedResult
134 */
135@NotMutable()
136@ThreadSafety(level=ThreadSafetyLevel.COMPLETELY_THREADSAFE)
137public final class DeliverOneTimePasswordExtendedRequest
138       extends ExtendedRequest
139{
140  /**
141   * The OID (1.3.6.1.4.1.30221.2.6.24) for the deliver one-time password
142   * extended request.
143   */
144  @NotNull public static final String DELIVER_OTP_REQUEST_OID =
145       "1.3.6.1.4.1.30221.2.6.24";
146
147
148
149  /**
150   * The BER type for the authentication ID element.
151   */
152  private static final byte TYPE_AUTHN_ID = (byte) 0x80;
153
154
155
156  /**
157   * The BER type for the static password element.
158   */
159  private static final byte TYPE_PASSWORD = (byte) 0x81;
160
161
162
163  /**
164   * The BER type for the preferred delivery mechanism names element.
165   */
166  private static final byte TYPE_PREFERRED_DELIVERY_MECHANISM_NAMES =
167       (byte) 0xA2;
168
169
170
171  /**
172   * The BER type for the preferred delivery mechanism names and IDs element.
173   */
174  private static final byte TYPE_PREFERRED_DELIVERY_MECHANISM_NAMES_AND_IDS =
175       (byte) 0xA3;
176
177
178
179  /**
180   * The BER type for the "message subject" element of the value sequence.
181   */
182  private static final byte MESSAGE_SUBJECT_BER_TYPE = (byte) 0x84;
183
184
185
186  /**
187   * The BER type for the "full text before OTP" element of the value
188   * sequence.
189   */
190  private static final byte FULL_TEXT_BEFORE_OTP_BER_TYPE = (byte) 0x85;
191
192
193
194  /**
195   * The BER type for the "full text after OTP" element of the value
196   * sequence.
197   */
198  private static final byte FULL_TEXT_AFTER_OTP_BER_TYPE = (byte) 0x86;
199
200
201
202  /**
203   * The BER type for the "compact text before OTP" element of the value
204   * sequence.
205   */
206  private static final byte COMPACT_TEXT_BEFORE_OTP_BER_TYPE = (byte) 0x87;
207
208
209
210  /**
211   * The BER type for the "compact text after OTP" element of the value
212   * sequence.
213   */
214  private static final byte COMPACT_TEXT_AFTER_OTP_BER_TYPE = (byte) 0x88;
215
216
217
218  /**
219   * The serial version UID for this serializable class.
220   */
221  private static final long serialVersionUID = 1259250969726758847L;
222
223
224
225  // The static password to include in the request.
226  @Nullable private final ASN1OctetString staticPassword;
227
228  // The list of preferred delivery mechanisms to include in the request.
229  @NotNull private final List<ObjectPair<String, String>>
230       preferredDeliveryMechanisms;
231
232  // The authentication ID to include in the request.
233  @NotNull private final String authenticationID;
234
235  // The text to include after the OTP in a compact message.
236  @Nullable private final String compactTextAfterOTP;
237
238  // The text to include before the OTP in a compact message.
239  @Nullable private final String compactTextBeforeOTP;
240
241  // The text to include after the OTP in a message without size constraints.
242  @Nullable private final String fullTextAfterOTP;
243
244  // The text to include before the OTP in a message without size constraints.
245  @Nullable private final String fullTextBeforeOTP;
246
247  // The text to use as the message subject.
248  @Nullable private final String messageSubject;
249
250
251
252  /**
253   * Creates a new deliver one-time password extended request with the provided
254   * information.
255   *
256   * @param  authenticationID             The authentication ID for the user to
257   *                                      whom the one-time password should be
258   *                                      delivered.  It must not be
259   *                                      {@code null}.
260   * @param  staticPassword               The static password for the user to
261   *                                      whom the one-time password should be
262   *                                      delivered.  It may be {@code null} if
263   *                                      this request is intended to be used
264   *                                      to step-up an existing authentication
265   *                                      rather than perform a new
266   *                                      authentication (in which case the
267   *                                      provided authentication ID must match
268   *                                      the operation's authorization ID).
269   * @param  preferredDeliveryMechanisms  The names of the preferred delivery
270   *                                      mechanisms for the one-time password.
271   *                                      It may be {@code null} or empty if the
272   *                                      server should select an appropriate
273   *                                      delivery mechanism.  If it is
274   *                                      non-{@code null} and non-empty, then
275   *                                      only the listed mechanisms will be
276   *                                      considered for use, even if the server
277   *                                      supports alternate mechanisms not
278   *                                      included in this list.
279   */
280  public DeliverOneTimePasswordExtendedRequest(
281              @NotNull final String authenticationID,
282              @Nullable final String staticPassword,
283              @Nullable final String... preferredDeliveryMechanisms)
284  {
285    this(authenticationID, staticPassword,
286         StaticUtils.toList(preferredDeliveryMechanisms));
287  }
288
289
290
291  /**
292   * Creates a new deliver one-time password extended request with the provided
293   * information.
294   *
295   * @param  authenticationID             The authentication ID for the user to
296   *                                      whom the one-time password should be
297   *                                      delivered.  It must not be
298   *                                      {@code null}.
299   * @param  staticPassword               The static password for the user to
300   *                                      whom the one-time password should be
301   *                                      delivered.  It may be {@code null} if
302   *                                      this request is intended to be used
303   *                                      to step-up an existing authentication
304   *                                      rather than perform a new
305   *                                      authentication (in which case the
306   *                                      provided authentication ID must match
307   *                                      the operation's authorization ID).
308   * @param  preferredDeliveryMechanisms  The names of the preferred delivery
309   *                                      mechanisms for the one-time password.
310   *                                      It may be {@code null} or empty if the
311   *                                      server should select an appropriate
312   *                                      delivery mechanism.  If it is
313   *                                      non-{@code null} and non-empty, then
314   *                                      only the listed mechanisms will be
315   *                                      considered for use, even if the server
316   *                                      supports alternate mechanisms not
317   *                                      included in this list.
318   */
319  public DeliverOneTimePasswordExtendedRequest(
320              @NotNull final String authenticationID,
321              @Nullable final byte[] staticPassword,
322              @Nullable final String... preferredDeliveryMechanisms)
323  {
324    this(authenticationID, staticPassword,
325         StaticUtils.toList(preferredDeliveryMechanisms));
326  }
327
328
329
330  /**
331   * Creates a new deliver one-time password extended request with the provided
332   * information.
333   *
334   * @param  authenticationID             The authentication ID for the user to
335   *                                      whom the one-time password should be
336   *                                      delivered.  It must not be
337   *                                      {@code null}.
338   * @param  staticPassword               The static password for the user to
339   *                                      whom the one-time password should be
340   *                                      delivered.  It may be {@code null} if
341   *                                      this request is intended to be used
342   *                                      to step-up an existing authentication
343   *                                      rather than perform a new
344   *                                      authentication (in which case the
345   *                                      provided authentication ID must match
346   *                                      the operation's authorization ID).
347   * @param  preferredDeliveryMechanisms  The names of the preferred delivery
348   *                                      mechanisms for the one-time password.
349   *                                      It may be {@code null} or empty if the
350   *                                      server should select an appropriate
351   *                                      delivery mechanism.  If it is
352   *                                      non-{@code null} and non-empty, then
353   *                                      only the listed mechanisms will be
354   *                                      considered for use, even if the server
355   *                                      supports alternate mechanisms not
356   *                                      included in this list.
357   * @param  controls                     The set of controls to include in the
358   *                                      request.  It may be {@code null} or
359   *                                      empty if no controls should be
360   *                                      included.
361   */
362  public DeliverOneTimePasswordExtendedRequest(
363              @NotNull final String authenticationID,
364              @Nullable final String staticPassword,
365              @Nullable final List<String> preferredDeliveryMechanisms,
366              @Nullable final Control... controls)
367  {
368    this(authenticationID,
369         (staticPassword == null
370              ? null
371              : new ASN1OctetString(TYPE_PASSWORD, staticPassword)),
372         preferredDeliveryMechanisms, controls);
373  }
374
375
376
377  /**
378   * Creates a new deliver one-time password extended request with the provided
379   * information.
380   *
381   * @param  authenticationID             The authentication ID for the user to
382   *                                      whom the one-time password should be
383   *                                      delivered.  It must not be
384   *                                      {@code null}.
385   * @param  staticPassword               The static password for the user to
386   *                                      whom the one-time password should be
387   *                                      delivered.  It may be {@code null} if
388   *                                      this request is intended to be used
389   *                                      to step-up an existing authentication
390   *                                      rather than perform a new
391   *                                      authentication (in which case the
392   *                                      provided authentication ID must match
393   *                                      the operation's authorization ID).
394   * @param  preferredDeliveryMechanisms  The names of the preferred delivery
395   *                                      mechanisms for the one-time password.
396   *                                      It may be {@code null} or empty if the
397   *                                      server should select an appropriate
398   *                                      delivery mechanism.  If it is
399   *                                      non-{@code null} and non-empty, then
400   *                                      only the listed mechanisms will be
401   *                                      considered for use, even if the server
402   *                                      supports alternate mechanisms not
403   *                                      included in this list.
404   * @param  controls                     The set of controls to include in the
405   *                                      request.  It may be {@code null} or
406   *                                      empty if no controls should be
407   *                                      included.
408   */
409  public DeliverOneTimePasswordExtendedRequest(
410              @NotNull final String authenticationID,
411              @Nullable final byte[] staticPassword,
412              @Nullable final List<String> preferredDeliveryMechanisms,
413              @Nullable final Control... controls)
414  {
415    this(authenticationID,
416         (staticPassword == null
417              ? null
418              : new ASN1OctetString(TYPE_PASSWORD, staticPassword)),
419         preferredDeliveryMechanisms, controls);
420  }
421
422
423
424  /**
425   * Creates a new deliver one-time password extended request with the provided
426   * information.
427   *
428   * @param  authenticationID             The authentication ID for the user to
429   *                                      whom the one-time password should be
430   *                                      delivered.  It must not be
431   *                                      {@code null}.
432   * @param  staticPassword               The static password for the user to
433   *                                      whom the one-time password should be
434   *                                      delivered.  It may be {@code null} if
435   *                                      this request is intended to be used
436   *                                      to step-up an existing authentication
437   *                                      rather than perform a new
438   *                                      authentication (in which case the
439   *                                      provided authentication ID must match
440   *                                      the operation's authorization ID).
441   * @param  preferredDeliveryMechanisms  The names of the preferred delivery
442   *                                      mechanisms for the one-time password.
443   *                                      It may be {@code null} or empty if the
444   *                                      server should select an appropriate
445   *                                      delivery mechanism.  If it is
446   *                                      non-{@code null} and non-empty, then
447   *                                      only the listed mechanisms will be
448   *                                      considered for use, even if the server
449   *                                      supports alternate mechanisms not
450   *                                      included in this list.
451   * @param  controls                     The set of controls to include in the
452   *                                      request.  It may be {@code null} or
453   *                                      empty if no controls should be
454   *                                      included.
455   */
456  private DeliverOneTimePasswordExtendedRequest(
457               @NotNull final String authenticationID,
458               @Nullable final ASN1OctetString staticPassword,
459               @Nullable final List<String> preferredDeliveryMechanisms,
460               @Nullable final Control... controls)
461  {
462    super(DELIVER_OTP_REQUEST_OID,
463         encodeValue(authenticationID, staticPassword,
464              preferredDeliveryMechanisms),
465         controls);
466
467    this.authenticationID = authenticationID;
468    this.staticPassword   = staticPassword;
469
470    if ((preferredDeliveryMechanisms == null) ||
471        preferredDeliveryMechanisms.isEmpty())
472    {
473      this.preferredDeliveryMechanisms = Collections.emptyList();
474    }
475    else
476    {
477      final ArrayList<ObjectPair<String,String>> l =
478           new ArrayList<>(preferredDeliveryMechanisms.size());
479      for (final String s : preferredDeliveryMechanisms)
480      {
481        l.add(new ObjectPair<String,String>(s, null));
482      }
483      this.preferredDeliveryMechanisms = Collections.unmodifiableList(l);
484    }
485
486    messageSubject       = null;
487    fullTextBeforeOTP    = null;
488    fullTextAfterOTP     = null;
489    compactTextBeforeOTP = null;
490    compactTextAfterOTP  = null;
491  }
492
493
494
495  /**
496   * Creates a new deliver one-time password extended request with the provided
497   * information.
498   *
499   * @param  authenticationID             The authentication ID for the user to
500   *                                      whom the one-time password should be
501   *                                      delivered.  It must not be
502   *                                      {@code null}.
503   * @param  staticPassword               The static password for the user to
504   *                                      whom the one-time password should be
505   *                                      delivered.  It may be {@code null} if
506   *                                      this request is intended to be used
507   *                                      to step-up an existing authentication
508   *                                      rather than perform a new
509   *                                      authentication (in which case the
510   *                                      provided authentication ID must match
511   *                                      the operation's authorization ID).
512   * @param  messageSubject               The text (if any) that should be used
513   *                                      as the message subject if the delivery
514   *                                      mechanism accepts a subject.  This may
515   *                                      be {@code null} if no subject is
516   *                                      required or a subject should be
517   *                                      automatically generated.
518   * @param  fullTextBeforeOTP            The text (if any) that should appear
519   *                                      before the generated one-time password
520   *                                      in the message delivered to the user
521   *                                      via a delivery mechanism that does not
522   *                                      impose significant constraints on
523   *                                      message size.  This may be
524   *                                      {@code null} if no text is required
525   *                                      before the one-time password.
526   * @param  fullTextAfterOTP             The text (if any) that should appear
527   *                                      after the one-time password in the
528   *                                      message delivered to the user via a
529   *                                      delivery mechanism that does not
530   *                                      impose significant constraints on
531   *                                      message size.  This may be
532   *                                      {@code null} if no text is required
533   *                                      after the one-time password.
534   * @param  compactTextBeforeOTP         The text (if any) that should appear
535   *                                      before the generated one-time password
536   *                                      in the message delivered to the user
537   *                                      via a delivery mechanism that imposes
538   *                                      significant constraints on message
539   *                                      size.  This may be {@code null} if no
540   *                                      text is required before the one-time
541   *                                      password.
542   * @param  compactTextAfterOTP          The text (if any) that should appear
543   *                                      after the generated one-time password
544   *                                      in the message delivered to the user
545   *                                      via a delivery mechanism that imposes
546   *                                      significant constraints on message
547   *                                      size.  This may be {@code null} if no
548   *                                      text is required after the one-time
549   *                                      password.
550   * @param  preferredDeliveryMechanisms  An optional ordered list of preferred
551   *                                      delivery mechanisms that should be
552   *                                      used to deliver the one-time password
553   *                                      to the user.  It may be {@code null}
554   *                                      or empty to allow the server to select
555   *                                      an appropriate delivery mechanism.  If
556   *                                      it is non-{@code null} and non-empty,
557   *                                      then only the listed mechanisms will
558   *                                      be considered for use, even if the
559   *                                      server supports alternate mechanisms
560   *                                      not included in this list.  Each
561   *                                      {@code ObjectPair} item must have
562   *                                      a non-{@code null} value for the first
563   *                                      element, which is the name of the
564   *                                      target delivery mechanism.  It may
565   *                                      optionally have a non-{@code null}
566   *                                      value for the second element, which is
567   *                                      a recipient ID to use for that
568   *                                      mechanism (e.g., the target  mobile
569   *                                      phone number for SMS delivery, an
570   *                                      email address for email delivery,
571   *                                      etc.).  If no recipient ID is provided
572   *                                      for a mechanism, then the server will
573   *                                      attempt to select a value for the
574   *                                      user.
575   * @param  controls                     The set of controls to include in the
576   *                                      request.  It may be {@code null} or
577   *                                      empty if no controls should be
578   *                                      included.
579   */
580  public DeliverOneTimePasswordExtendedRequest(
581       @NotNull final String authenticationID,
582       @Nullable final String staticPassword,
583       @Nullable final String messageSubject,
584       @Nullable final String fullTextBeforeOTP,
585       @Nullable final String fullTextAfterOTP,
586       @Nullable final String compactTextBeforeOTP,
587       @Nullable final String compactTextAfterOTP,
588       @Nullable final List<ObjectPair<String,String>>
589            preferredDeliveryMechanisms,
590       @Nullable final Control... controls)
591  {
592    this(authenticationID,
593         (staticPassword == null
594              ? null
595              : new ASN1OctetString(TYPE_PASSWORD, staticPassword)),
596         messageSubject, fullTextBeforeOTP, fullTextAfterOTP,
597         compactTextBeforeOTP, compactTextAfterOTP, preferredDeliveryMechanisms,
598         controls);
599  }
600
601
602
603  /**
604   * Creates a new deliver one-time password extended request with the provided
605   * information.
606   *
607   * @param  authenticationID             The authentication ID for the user to
608   *                                      whom the one-time password should be
609   *                                      delivered.  It must not be
610   *                                      {@code null}.
611   * @param  staticPassword               The static password for the user to
612   *                                      whom the one-time password should be
613   *                                      delivered.  It may be {@code null} if
614   *                                      this request is intended to be used
615   *                                      to step-up an existing authentication
616   *                                      rather than perform a new
617   *                                      authentication (in which case the
618   *                                      provided authentication ID must match
619   *                                      the operation's authorization ID).
620   * @param  messageSubject               The text (if any) that should be used
621   *                                      as the message subject if the delivery
622   *                                      mechanism accepts a subject.  This may
623   *                                      be {@code null} if no subject is
624   *                                      required or a subject should be
625   *                                      automatically generated.
626   * @param  fullTextBeforeOTP            The text (if any) that should appear
627   *                                      before the generated one-time password
628   *                                      in the message delivered to the user
629   *                                      via a delivery mechanism that does not
630   *                                      impose significant constraints on
631   *                                      message size.  This may be
632   *                                      {@code null} if no text is required
633   *                                      before the one-time password.
634   * @param  fullTextAfterOTP             The text (if any) that should appear
635   *                                      after the one-time password in the
636   *                                      message delivered to the user via a
637   *                                      delivery mechanism that does not
638   *                                      impose significant constraints on
639   *                                      message size.  This may be
640   *                                      {@code null} if no text is required
641   *                                      after the one-time password.
642   * @param  compactTextBeforeOTP         The text (if any) that should appear
643   *                                      before the generated one-time password
644   *                                      in the message delivered to the user
645   *                                      via a delivery mechanism that imposes
646   *                                      significant constraints on message
647   *                                      size.  This may be {@code null} if no
648   *                                      text is required before the one-time
649   *                                      password.
650   * @param  compactTextAfterOTP          The text (if any) that should appear
651   *                                      after the generated one-time password
652   *                                      in the message delivered to the user
653   *                                      via a delivery mechanism that imposes
654   *                                      significant constraints on message
655   *                                      size.  This may be {@code null} if no
656   *                                      text is required after the one-time
657   *                                      password.
658   * @param  preferredDeliveryMechanisms  An optional ordered list of preferred
659   *                                      delivery mechanisms that should be
660   *                                      used to deliver the one-time password
661   *                                      to the user.  It may be {@code null}
662   *                                      or empty to allow the server to select
663   *                                      an appropriate delivery mechanism.  If
664   *                                      it is non-{@code null} and non-empty,
665   *                                      then only the listed mechanisms will
666   *                                      be considered for use, even if the
667   *                                      server supports alternate mechanisms
668   *                                      not included in this list.  Each
669   *                                      {@code ObjectPair} item must have
670   *                                      a non-{@code null} value for the first
671   *                                      element, which is the name of the
672   *                                      target delivery mechanism.  It may
673   *                                      optionally have a non-{@code null}
674   *                                      value for the second element, which is
675   *                                      a recipient ID to use for that
676   *                                      mechanism (e.g., the target  mobile
677   *                                      phone number for SMS delivery, an
678   *                                      email address for email delivery,
679   *                                      etc.).  If no recipient ID is provided
680   *                                      for a mechanism, then the server will
681   *                                      attempt to select a value for the
682   *                                      user.
683   * @param  controls                     The set of controls to include in the
684   *                                      request.  It may be {@code null} or
685   *                                      empty if no controls should be
686   *                                      included.
687   */
688  public DeliverOneTimePasswordExtendedRequest(
689       @NotNull final String authenticationID,
690       @Nullable final byte[] staticPassword,
691       @Nullable final String messageSubject,
692       @Nullable final String fullTextBeforeOTP,
693       @Nullable final String fullTextAfterOTP,
694       @Nullable final String compactTextBeforeOTP,
695       @Nullable final String compactTextAfterOTP,
696       @Nullable final List<ObjectPair<String,String>>
697            preferredDeliveryMechanisms,
698       @Nullable final Control... controls)
699  {
700    this(authenticationID,
701         (staticPassword == null
702              ? null
703              : new ASN1OctetString(TYPE_PASSWORD, staticPassword)),
704         messageSubject, fullTextBeforeOTP, fullTextAfterOTP,
705         compactTextBeforeOTP, compactTextAfterOTP, preferredDeliveryMechanisms,
706         controls);
707  }
708
709
710
711  /**
712   * Creates a new deliver one-time password extended request with the provided
713   * information.
714   *
715   * @param  authenticationID             The authentication ID for the user to
716   *                                      whom the one-time password should be
717   *                                      delivered.  It must not be
718   *                                      {@code null}.
719   * @param  staticPassword               The static password for the user to
720   *                                      whom the one-time password should be
721   *                                      delivered.  It may be {@code null} if
722   *                                      this request is intended to be used
723   *                                      to step-up an existing authentication
724   *                                      rather than perform a new
725   *                                      authentication (in which case the
726   *                                      provided authentication ID must match
727   *                                      the operation's authorization ID).
728   * @param  messageSubject               The text (if any) that should be used
729   *                                      as the message subject if the delivery
730   *                                      mechanism accepts a subject.  This may
731   *                                      be {@code null} if no subject is
732   *                                      required or a subject should be
733   *                                      automatically generated.
734   * @param  fullTextBeforeOTP            The text (if any) that should appear
735   *                                      before the generated one-time password
736   *                                      in the message delivered to the user
737   *                                      via a delivery mechanism that does not
738   *                                      impose significant constraints on
739   *                                      message size.  This may be
740   *                                      {@code null} if no text is required
741   *                                      before the one-time password.
742   * @param  fullTextAfterOTP             The text (if any) that should appear
743   *                                      after the one-time password in the
744   *                                      message delivered to the user via a
745   *                                      delivery mechanism that does not
746   *                                      impose significant constraints on
747   *                                      message size.  This may be
748   *                                      {@code null} if no text is required
749   *                                      after the one-time password.
750   * @param  compactTextBeforeOTP         The text (if any) that should appear
751   *                                      before the generated one-time password
752   *                                      in the message delivered to the user
753   *                                      via a delivery mechanism that imposes
754   *                                      significant constraints on message
755   *                                      size.  This may be {@code null} if no
756   *                                      text is required before the one-time
757   *                                      password.
758   * @param  compactTextAfterOTP          The text (if any) that should appear
759   *                                      after the generated one-time password
760   *                                      in the message delivered to the user
761   *                                      via a delivery mechanism that imposes
762   *                                      significant constraints on message
763   *                                      size.  This may be {@code null} if no
764   *                                      text is required after the one-time
765   *                                      password.
766   * @param  preferredDeliveryMechanisms  An optional ordered list of preferred
767   *                                      delivery mechanisms that should be
768   *                                      used to deliver the one-time password
769   *                                      to the user.  It may be {@code null}
770   *                                      or empty to allow the server to select
771   *                                      an appropriate delivery mechanism.  If
772   *                                      it is non-{@code null} and non-empty,
773   *                                      then only the listed mechanisms will
774   *                                      be considered for use, even if the
775   *                                      server supports alternate mechanisms
776   *                                      not included in this list.  Each
777   *                                      {@code ObjectPair} item must have
778   *                                      a non-{@code null} value for the first
779   *                                      element, which is the name of the
780   *                                      target delivery mechanism.  It may
781   *                                      optionally have a non-{@code null}
782   *                                      value for the second element, which is
783   *                                      a recipient ID to use for that
784   *                                      mechanism (e.g., the target  mobile
785   *                                      phone number for SMS delivery, an
786   *                                      email address for email delivery,
787   *                                      etc.).  If no recipient ID is provided
788   *                                      for a mechanism, then the server will
789   *                                      attempt to select a value for the
790   *                                      user.
791   * @param  controls                     The set of controls to include in the
792   *                                      request.  It may be {@code null} or
793   *                                      empty if no controls should be
794   *                                      included.
795   */
796  private DeliverOneTimePasswordExtendedRequest(
797       @NotNull final String authenticationID,
798       @Nullable final ASN1OctetString staticPassword,
799       @Nullable final String messageSubject,
800       @Nullable final String fullTextBeforeOTP,
801       @Nullable final String fullTextAfterOTP,
802       @Nullable final String compactTextBeforeOTP,
803       @Nullable final String compactTextAfterOTP,
804       @Nullable final List<ObjectPair<String,String>>
805            preferredDeliveryMechanisms,
806       @Nullable final Control... controls)
807  {
808    super(DELIVER_OTP_REQUEST_OID,
809         encodeValue(authenticationID, staticPassword, messageSubject,
810              fullTextBeforeOTP, fullTextAfterOTP, compactTextBeforeOTP,
811              compactTextAfterOTP, preferredDeliveryMechanisms),
812         controls);
813
814    this.authenticationID     = authenticationID;
815    this.staticPassword       = staticPassword;
816    this.messageSubject       = messageSubject;
817    this.fullTextBeforeOTP    = fullTextBeforeOTP;
818    this.fullTextAfterOTP     = fullTextAfterOTP;
819    this.compactTextBeforeOTP = compactTextBeforeOTP;
820    this.compactTextAfterOTP  = compactTextAfterOTP;
821
822    if ((preferredDeliveryMechanisms == null) ||
823        preferredDeliveryMechanisms.isEmpty())
824    {
825      this.preferredDeliveryMechanisms = Collections.emptyList();
826    }
827    else
828    {
829      this.preferredDeliveryMechanisms =
830           Collections.unmodifiableList(preferredDeliveryMechanisms);
831    }
832  }
833
834
835
836  /**
837   * Creates a new deliver one-time password extended request from the
838   * information contained in the provided generic extended request.
839   *
840   * @param  request  The generic extended request to be decoded as a deliver
841   *                  one-time password extended request.
842   *
843   * @throws  LDAPException  If a problem is encountered while attempting to
844   *                         decode the provided generic extended request as a
845   *                         deliver one-time password extended request.
846   */
847  public DeliverOneTimePasswordExtendedRequest(
848              @NotNull final ExtendedRequest request)
849         throws LDAPException
850  {
851    super(request);
852
853    // The request must have a value.
854    final ASN1OctetString value = request.getValue();
855    if (value == null)
856    {
857      throw new LDAPException(ResultCode.DECODING_ERROR,
858           ERR_DELIVER_OTP_REQ_NO_VALUE.get());
859    }
860
861
862    //  Parse the value.
863    ASN1OctetString password = null;
864    String authnID = null;
865    String subject = null;
866    String fullBefore = null;
867    String fullAfter = null;
868    String compactBefore = null;
869    String compactAfter = null;
870    final ArrayList<ObjectPair<String,String>> pdmList = new ArrayList<>(10);
871    try
872    {
873      for (final ASN1Element e :
874           ASN1Sequence.decodeAsSequence(value.getValue()).elements())
875      {
876        switch (e.getType())
877        {
878          case TYPE_AUTHN_ID:
879            authnID = ASN1OctetString.decodeAsOctetString(e).stringValue();
880            break;
881
882          case TYPE_PASSWORD:
883            password = ASN1OctetString.decodeAsOctetString(e);
884            break;
885
886          case TYPE_PREFERRED_DELIVERY_MECHANISM_NAMES:
887            final ASN1Element[] mechNameElements =
888                 ASN1Sequence.decodeAsSequence(e).elements();
889            for (final ASN1Element mechElement : mechNameElements)
890            {
891              pdmList.add(new ObjectPair<String,String>(
892                   ASN1OctetString.decodeAsOctetString(mechElement).
893                        stringValue(),
894                   null));
895            }
896            break;
897
898          case TYPE_PREFERRED_DELIVERY_MECHANISM_NAMES_AND_IDS:
899            final ASN1Element[] pdmElements =
900                 ASN1Sequence.decodeAsSequence(e).elements();
901            for (final ASN1Element pdmElement : pdmElements)
902            {
903              final ASN1Element[] mechElements =
904                   ASN1Sequence.decodeAsSequence(pdmElement).elements();
905              final String mech = ASN1OctetString.decodeAsOctetString(
906                   mechElements[0]).stringValue();
907
908              final String recipientID;
909              if (mechElements.length > 1)
910              {
911                recipientID = ASN1OctetString.decodeAsOctetString(
912                     mechElements[1]).stringValue();
913              }
914              else
915              {
916                recipientID = null;
917              }
918
919              pdmList.add(new ObjectPair<>(mech, recipientID));
920            }
921            break;
922
923          case MESSAGE_SUBJECT_BER_TYPE:
924            subject =
925                 ASN1OctetString.decodeAsOctetString(e).stringValue();
926            break;
927
928          case FULL_TEXT_BEFORE_OTP_BER_TYPE:
929            fullBefore =
930                 ASN1OctetString.decodeAsOctetString(e).stringValue();
931            break;
932
933          case FULL_TEXT_AFTER_OTP_BER_TYPE:
934            fullAfter =
935                 ASN1OctetString.decodeAsOctetString(e).stringValue();
936            break;
937
938          case COMPACT_TEXT_BEFORE_OTP_BER_TYPE:
939            compactBefore =
940                 ASN1OctetString.decodeAsOctetString(e).stringValue();
941            break;
942
943          case COMPACT_TEXT_AFTER_OTP_BER_TYPE:
944            compactAfter =
945                 ASN1OctetString.decodeAsOctetString(e).stringValue();
946            break;
947
948          default:
949            throw new LDAPException(ResultCode.DECODING_ERROR,
950                 ERR_DELIVER_OTP_REQ_UNEXPECTED_ELEMENT_TYPE.get(
951                      StaticUtils.toHex(e.getType())));
952
953        }
954      }
955    }
956    catch (final LDAPException le)
957    {
958      Debug.debugException(le);
959      throw le;
960    }
961    catch (final Exception e)
962    {
963      Debug.debugException(e);
964      throw new LDAPException(ResultCode.DECODING_ERROR,
965           ERR_DELIVER_OTP_REQ_ERROR_PARSING_VALUE.get(
966                StaticUtils.getExceptionMessage(e)),
967           e);
968    }
969
970    if (authnID == null)
971    {
972      throw new LDAPException(ResultCode.DECODING_ERROR,
973           ERR_DELIVER_OTP_REQ_NO_AUTHN_ID.get());
974    }
975    else
976    {
977      authenticationID = authnID;
978    }
979
980    staticPassword       = password;
981    messageSubject       = subject;
982    fullTextBeforeOTP    = fullBefore;
983    fullTextAfterOTP     = fullAfter;
984    compactTextBeforeOTP = compactBefore;
985    compactTextAfterOTP  = compactAfter;
986
987    if ((pdmList == null) || pdmList.isEmpty())
988    {
989      preferredDeliveryMechanisms = Collections.emptyList();
990    }
991    else
992    {
993      preferredDeliveryMechanisms = Collections.unmodifiableList(pdmList);
994    }
995  }
996
997
998
999  /**
1000   * Encodes the provided information into an ASN.1 octet string suitable for
1001   * use as the value of this extended request.
1002   *
1003   * @param  authenticationID             The authentication ID for the user to
1004   *                                      whom the one-time password should be
1005   *                                      delivered.  It must not be
1006   *                                      {@code null}.
1007   * @param  staticPassword               The static password for the user to
1008   *                                      whom the one-time password should be
1009   *                                      delivered.
1010   * @param  preferredDeliveryMechanisms  The names of the preferred delivery
1011   *                                      mechanisms for the one-time password.
1012   *                                      It may be {@code null} or empty if the
1013   *                                      server should select an appropriate
1014   *                                      delivery mechanism.  If it is
1015   *                                      non-{@code null} and non-empty, then
1016   *                                      only the listed mechanisms will be
1017   *                                      considered for use, even if the server
1018   *                                      supports alternate mechanisms not
1019   *                                      included in this list.
1020   *
1021   * @return  An ASN.1 octet string suitable for use as the value of this
1022   *          extended request.
1023   */
1024  @NotNull()
1025  private static ASN1OctetString encodeValue(
1026               @NotNull final String authenticationID,
1027               @Nullable final ASN1OctetString staticPassword,
1028               @Nullable final List<String> preferredDeliveryMechanisms)
1029  {
1030    final ArrayList<ASN1Element> elements = new ArrayList<>(3);
1031
1032    elements.add(new ASN1OctetString(TYPE_AUTHN_ID, authenticationID));
1033
1034    if (staticPassword != null)
1035    {
1036      elements.add(staticPassword);
1037    }
1038
1039    if ((preferredDeliveryMechanisms != null) &&
1040        (! preferredDeliveryMechanisms.isEmpty()))
1041    {
1042      final ArrayList<ASN1Element> dmElements =
1043           new ArrayList<>(preferredDeliveryMechanisms.size());
1044      for (final String s : preferredDeliveryMechanisms)
1045      {
1046        dmElements.add(new ASN1OctetString(s));
1047      }
1048      elements.add(new ASN1Sequence(TYPE_PREFERRED_DELIVERY_MECHANISM_NAMES,
1049           dmElements));
1050    }
1051
1052    return new ASN1OctetString(new ASN1Sequence(elements).encode());
1053  }
1054
1055
1056
1057  /**
1058   * Encodes the provided information into an ASN.1 octet string suitable for
1059   * use as the value of this extended request.
1060   *
1061   * @param  authenticationID             The authentication ID for the user to
1062   *                                      whom the one-time password should be
1063   *                                      delivered.  It must not be
1064   *                                      {@code null}.
1065   * @param  staticPassword               The static password for the user to
1066   *                                      whom the one-time password should be
1067   *                                      delivered.  It may be {@code null} if
1068   *                                      this request is intended to be used
1069   *                                      to step-up an existing authentication
1070   *                                      rather than perform a new
1071   *                                      authentication (in which case the
1072   *                                      provided authentication ID must match
1073   *                                      the operation's authorization ID).
1074   * @param  messageSubject               The text (if any) that should be used
1075   *                                      as the message subject if the delivery
1076   *                                      mechanism accepts a subject.  This may
1077   *                                      be {@code null} if no subject is
1078   *                                      required or a subject should be
1079   *                                      automatically generated.
1080   * @param  fullTextBeforeOTP            The text (if any) that should appear
1081   *                                      before the generated one-time password
1082   *                                      in the message delivered to the user
1083   *                                      via a delivery mechanism that does not
1084   *                                      impose significant constraints on
1085   *                                      message size.  This may be
1086   *                                      {@code null} if no text is required
1087   *                                      before the one-time password.
1088   * @param  fullTextAfterOTP             The text (if any) that should appear
1089   *                                      after the one-time password in the
1090   *                                      message delivered to the user via a
1091   *                                      delivery mechanism that does not
1092   *                                      impose significant constraints on
1093   *                                      message size.  This may be
1094   *                                      {@code null} if no text is required
1095   *                                      after the one-time password.
1096   * @param  compactTextBeforeOTP         The text (if any) that should appear
1097   *                                      before the generated one-time password
1098   *                                      in the message delivered to the user
1099   *                                      via a delivery mechanism that imposes
1100   *                                      significant constraints on message
1101   *                                      size.  This may be {@code null} if no
1102   *                                      text is required before the one-time
1103   *                                      password.
1104   * @param  compactTextAfterOTP          The text (if any) that should appear
1105   *                                      after the generated one-time password
1106   *                                      in the message delivered to the user
1107   *                                      via a delivery mechanism that imposes
1108   *                                      significant constraints on message
1109   *                                      size.  This may be {@code null} if no
1110   *                                      text is required after the one-time
1111   *                                      password.
1112   * @param  preferredDeliveryMechanisms  An optional ordered list of preferred
1113   *                                      delivery mechanisms that should be
1114   *                                      used to deliver the one-time password
1115   *                                      to the user.  It may be {@code null}
1116   *                                      or empty to allow the server to select
1117   *                                      an appropriate delivery mechanism.  If
1118   *                                      it is non-{@code null} and non-empty,
1119   *                                      then only the listed mechanisms will
1120   *                                      be considered for use, even if the
1121   *                                      server supports alternate mechanisms
1122   *                                      not included in this list.  Each
1123   *                                      {@code ObjectPair} item must have
1124   *                                      a non-{@code null} value for the first
1125   *                                      element, which is the name of the
1126   *                                      target delivery mechanism.  It may
1127   *                                      optionally have a non-{@code null}
1128   *                                      value for the second element, which is
1129   *                                      a recipient ID to use for that
1130   *                                      mechanism (e.g., the target  mobile
1131   *                                      phone number for SMS delivery, an
1132   *                                      email address for email delivery,
1133   *                                      etc.).  If no recipient ID is provided
1134   *                                      for a mechanism, then the server will
1135   *                                      attempt to select a value for the
1136   *                                      user.
1137   *
1138   * @return  An ASN.1 octet string suitable for use as the value of this
1139   *          extended request.
1140   */
1141  @NotNull()
1142  private static ASN1OctetString encodeValue(
1143       @NotNull final String authenticationID,
1144       @Nullable final ASN1OctetString staticPassword,
1145       @Nullable final String messageSubject,
1146       @Nullable final String fullTextBeforeOTP,
1147       @Nullable final String fullTextAfterOTP,
1148       @Nullable final String compactTextBeforeOTP,
1149       @Nullable final String compactTextAfterOTP,
1150       @Nullable final List<ObjectPair<String,String>>
1151            preferredDeliveryMechanisms)
1152  {
1153    final ArrayList<ASN1Element> elements = new ArrayList<>(8);
1154
1155    elements.add(new ASN1OctetString(TYPE_AUTHN_ID, authenticationID));
1156
1157    if (staticPassword != null)
1158    {
1159      elements.add(staticPassword);
1160    }
1161
1162    if (messageSubject != null)
1163    {
1164      elements.add(new ASN1OctetString(MESSAGE_SUBJECT_BER_TYPE,
1165           messageSubject));
1166    }
1167
1168    if (fullTextBeforeOTP != null)
1169    {
1170      elements.add(new ASN1OctetString(FULL_TEXT_BEFORE_OTP_BER_TYPE,
1171           fullTextBeforeOTP));
1172    }
1173
1174    if (fullTextAfterOTP != null)
1175    {
1176      elements.add(new ASN1OctetString(FULL_TEXT_AFTER_OTP_BER_TYPE,
1177           fullTextAfterOTP));
1178    }
1179
1180    if (compactTextBeforeOTP != null)
1181    {
1182      elements.add(new ASN1OctetString(COMPACT_TEXT_BEFORE_OTP_BER_TYPE,
1183           compactTextBeforeOTP));
1184    }
1185
1186    if (compactTextAfterOTP != null)
1187    {
1188      elements.add(new ASN1OctetString(COMPACT_TEXT_AFTER_OTP_BER_TYPE,
1189           compactTextAfterOTP));
1190    }
1191
1192    if ((preferredDeliveryMechanisms != null) &&
1193        (! preferredDeliveryMechanisms.isEmpty()))
1194    {
1195      final ArrayList<ASN1Element> pdmElements =
1196           new ArrayList<>(preferredDeliveryMechanisms.size());
1197      for (final ObjectPair<String,String> p : preferredDeliveryMechanisms)
1198      {
1199        if (p.getSecond() == null)
1200        {
1201          pdmElements.add(new ASN1Sequence(
1202               new ASN1OctetString(p.getFirst())));
1203        }
1204        else
1205        {
1206          pdmElements.add(new ASN1Sequence(
1207               new ASN1OctetString(p.getFirst()),
1208               new ASN1OctetString(p.getSecond())));
1209        }
1210      }
1211
1212      elements.add(new ASN1Sequence(
1213           TYPE_PREFERRED_DELIVERY_MECHANISM_NAMES_AND_IDS, pdmElements));
1214    }
1215
1216    return new ASN1OctetString(new ASN1Sequence(elements).encode());
1217  }
1218
1219
1220
1221  /**
1222   * Retrieves the authentication ID for the user to whom the one-time password
1223   * should be delivered.
1224   *
1225   * @return  The authentication ID for the user to whom the one-time password
1226   *          should be delivered.
1227   */
1228  @NotNull()
1229  public String getAuthenticationID()
1230  {
1231    return authenticationID;
1232  }
1233
1234
1235
1236  /**
1237   * Retrieves the static password for the user to whom the one-time password
1238   * should be delivered.  The returned password may be {@code null} if no
1239   *
1240   *
1241   * @return  The static password for the user to whom the one-time password
1242   *          should be delivered, or {@code null} if no static password should
1243   *          be included in the request.
1244   */
1245  @Nullable()
1246  public ASN1OctetString getStaticPassword()
1247  {
1248    return staticPassword;
1249  }
1250
1251
1252
1253  /**
1254   * Retrieves an ordered list of the names of the preferred delivery mechanisms
1255   * for the one-time password, if provided.
1256   *
1257   * @return  An ordered list of the names of the preferred delivery mechanisms
1258   *          for the one-time password, or {@code null} if this was not
1259   *          provided.
1260   */
1261  @Nullable()
1262  public List<String> getPreferredDeliveryMechanisms()
1263  {
1264    if (preferredDeliveryMechanisms.isEmpty())
1265    {
1266      return null;
1267    }
1268    else
1269    {
1270      final LinkedHashSet<String> s = new LinkedHashSet<>(
1271           StaticUtils.computeMapCapacity(preferredDeliveryMechanisms.size()));
1272      for (final ObjectPair<String,String> p : preferredDeliveryMechanisms)
1273      {
1274        s.add(p.getFirst());
1275      }
1276
1277      return Collections.unmodifiableList(new ArrayList<>(s));
1278    }
1279  }
1280
1281
1282
1283  /**
1284   * Retrieves an ordered list of the preferred delivery mechanisms that should
1285   * be used to provide the one-time password to the user, optionally paired
1286   * with a mechanism-specific recipient ID (e.g., a mobile phone number for SMS
1287   * delivery, or an email address for email delivery) that can be used in the
1288   * delivery.  If this list is non-empty, then the server will use the first
1289   * mechanism in the list that the server supports and is available for the
1290   * target user, and the server will only consider mechanisms in the provided
1291   * list even if the server supports alternate mechanisms that are not
1292   * included.  If this list is empty, then the server will attempt to select an
1293   * appropriate delivery mechanism for the user.
1294   *
1295   * @return  An ordered list of the preferred delivery mechanisms for the
1296   *          one-time password, or an empty list if none were provided.
1297   */
1298  @NotNull()
1299  public List<ObjectPair<String,String>>
1300              getPreferredDeliveryMechanismNamesAndIDs()
1301  {
1302    return preferredDeliveryMechanisms;
1303  }
1304
1305
1306
1307  /**
1308   * Retrieves the text (if any) that should be used as the message subject for
1309   * delivery mechanisms that can make use of a subject.
1310   *
1311   * @return  The text that should be used as the message subject for delivery
1312   *          mechanisms that can make use of a subject, or {@code null} if no
1313   *          subject should be used, or if the delivery mechanism should
1314   *          attempt to automatically determine a subject.
1315   */
1316  @Nullable()
1317  public String getMessageSubject()
1318  {
1319    return messageSubject;
1320  }
1321
1322
1323
1324  /**
1325   * Retrieves the text (if any) that should appear before the one-time password
1326   * in the message delivered to the user via a mechanism that does not impose
1327   * significant constraints on message size.
1328   *
1329   * @return  The text that should appear before the one-time password in the
1330   *          message delivered to the user via a mechanism that does not impose
1331   *          significant constraints on message size, or {@code null} if there
1332   *          should not be any text before the one-time password.
1333   */
1334  @Nullable()
1335  public String getFullTextBeforeOTP()
1336  {
1337    return fullTextBeforeOTP;
1338  }
1339
1340
1341
1342  /**
1343   * Retrieves the text (if any) that should appear after the one-time password
1344   * in the message delivered to the user via a mechanism that does not impose
1345   * significant constraints on message size.
1346   *
1347   * @return  The text that should appear after the one-time password in the
1348   *          message delivered to the user via a mechanism that does not impose
1349   *          significant constraints on message size, or {@code null} if there
1350   *          should not be any text after the one-time password.
1351   */
1352  @Nullable()
1353  public String getFullTextAfterOTP()
1354  {
1355    return fullTextAfterOTP;
1356  }
1357
1358
1359
1360  /**
1361   * Retrieves the text (if any) that should appear before the one-time password
1362   * in the message delivered to the user via a mechanism that imposes
1363   * significant constraints on message size.
1364   *
1365   * @return  The text that should appear before the one-time password in the
1366   *          message delivered to the user via a mechanism that imposes
1367   *          significant constraints on message size, or {@code null} if there
1368   *          should not be any text before the one-time password.
1369   */
1370  @Nullable()
1371  public String getCompactTextBeforeOTP()
1372  {
1373    return compactTextBeforeOTP;
1374  }
1375
1376
1377
1378  /**
1379   * Retrieves the text (if any) that should appear after the one-time password
1380   * in the message delivered to the user via a mechanism that imposes
1381   * significant constraints on message size.
1382   *
1383   * @return  The text that should appear after the one-time password in the
1384   *          message delivered to the user via a mechanism that imposes
1385   *          significant constraints on message size, or {@code null} if there
1386   *          should not be any text after the one-time password.
1387   */
1388  @Nullable()
1389  public String getCompactTextAfterOTP()
1390  {
1391    return compactTextAfterOTP;
1392  }
1393
1394
1395
1396  /**
1397   * {@inheritDoc}
1398   */
1399  @Override()
1400  @NotNull()
1401  public DeliverOneTimePasswordExtendedResult process(
1402              @NotNull final LDAPConnection connection, final int depth)
1403         throws LDAPException
1404  {
1405    final ExtendedResult extendedResponse = super.process(connection, depth);
1406    return new DeliverOneTimePasswordExtendedResult(extendedResponse);
1407  }
1408
1409
1410
1411  /**
1412   * {@inheritDoc}.
1413   */
1414  @Override()
1415  @NotNull()
1416  public DeliverOneTimePasswordExtendedRequest duplicate()
1417  {
1418    return duplicate(getControls());
1419  }
1420
1421
1422
1423  /**
1424   * {@inheritDoc}.
1425   */
1426  @Override()
1427  @NotNull()
1428  public DeliverOneTimePasswordExtendedRequest duplicate(
1429              @Nullable final Control[] controls)
1430  {
1431    final DeliverOneTimePasswordExtendedRequest r =
1432         new DeliverOneTimePasswordExtendedRequest(authenticationID,
1433              staticPassword, messageSubject, fullTextBeforeOTP,
1434              fullTextAfterOTP, compactTextBeforeOTP, compactTextAfterOTP,
1435              preferredDeliveryMechanisms, controls);
1436    r.setResponseTimeoutMillis(getResponseTimeoutMillis(null));
1437    r.setIntermediateResponseListener(getIntermediateResponseListener());
1438    r.setReferralDepth(getReferralDepth());
1439    r.setReferralConnector(getReferralConnectorInternal());
1440    return r;
1441  }
1442
1443
1444
1445  /**
1446   * {@inheritDoc}
1447   */
1448  @Override()
1449  @NotNull()
1450  public String getExtendedRequestName()
1451  {
1452    return INFO_DELIVER_OTP_REQ_NAME.get();
1453  }
1454
1455
1456
1457  /**
1458   * {@inheritDoc}
1459   */
1460  @Override()
1461  public void toString(@NotNull final StringBuilder buffer)
1462  {
1463    buffer.append("DeliverOneTimePasswordExtendedRequest(authenticationID=");
1464    buffer.append(authenticationID);
1465
1466    if (messageSubject != null)
1467    {
1468      buffer.append(", messageSubject='");
1469      buffer.append(messageSubject);
1470      buffer.append('\'');
1471    }
1472
1473    if (fullTextBeforeOTP != null)
1474    {
1475      buffer.append(", fullTextBeforeOTP='");
1476      buffer.append(fullTextBeforeOTP);
1477      buffer.append('\'');
1478    }
1479
1480    if (fullTextAfterOTP != null)
1481    {
1482      buffer.append(", fullTextAfterOTP='");
1483      buffer.append(fullTextAfterOTP);
1484      buffer.append('\'');
1485    }
1486
1487    if (compactTextBeforeOTP != null)
1488    {
1489      buffer.append(", compactTextBeforeOTP='");
1490      buffer.append(compactTextBeforeOTP);
1491      buffer.append('\'');
1492    }
1493
1494    if (compactTextAfterOTP != null)
1495    {
1496      buffer.append(", compactTextAfterOTP='");
1497      buffer.append(compactTextAfterOTP);
1498      buffer.append('\'');
1499    }
1500
1501    if (preferredDeliveryMechanisms != null)
1502    {
1503      buffer.append(", preferredDeliveryMechanisms={");
1504
1505      final Iterator<ObjectPair<String,String>> iterator =
1506           preferredDeliveryMechanisms.iterator();
1507      while (iterator.hasNext())
1508      {
1509        final ObjectPair<String,String> p = iterator.next();
1510        buffer.append('\'');
1511        buffer.append(p.getFirst());
1512        if (p.getSecond() != null)
1513        {
1514          buffer.append('(');
1515          buffer.append(p.getSecond());
1516          buffer.append(')');
1517        }
1518        buffer.append('\'');
1519        if (iterator.hasNext())
1520        {
1521          buffer.append(',');
1522        }
1523      }
1524    }
1525
1526    final Control[] controls = getControls();
1527    if (controls.length > 0)
1528    {
1529      buffer.append(", controls={");
1530      for (int i=0; i < controls.length; i++)
1531      {
1532        if (i > 0)
1533        {
1534          buffer.append(", ");
1535        }
1536
1537        buffer.append(controls[i]);
1538      }
1539      buffer.append('}');
1540    }
1541
1542    buffer.append(')');
1543  }
1544}