001/*
002 * Copyright 2019-2024 Ping Identity Corporation
003 * All Rights Reserved.
004 */
005/*
006 * Copyright 2019-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) 2019-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.List;
042
043import com.unboundid.asn1.ASN1Element;
044import com.unboundid.asn1.ASN1Integer;
045import com.unboundid.asn1.ASN1Null;
046import com.unboundid.asn1.ASN1OctetString;
047import com.unboundid.asn1.ASN1Sequence;
048import com.unboundid.ldap.sdk.Control;
049import com.unboundid.ldap.sdk.ExtendedRequest;
050import com.unboundid.ldap.sdk.LDAPConnection;
051import com.unboundid.ldap.sdk.LDAPException;
052import com.unboundid.ldap.sdk.ResultCode;
053import com.unboundid.util.Debug;
054import com.unboundid.util.NotMutable;
055import com.unboundid.util.NotNull;
056import com.unboundid.util.Nullable;
057import com.unboundid.util.StaticUtils;
058import com.unboundid.util.ThreadSafety;
059import com.unboundid.util.ThreadSafetyLevel;
060import com.unboundid.util.Validator;
061
062import static com.unboundid.ldap.sdk.unboundidds.extensions.ExtOpMessages.*;
063
064
065
066/**
067 * This class provides an implementation of an extended request that may be used
068 * to request that the server suggest one or more passwords that the client may
069 * use in new entries, password changes, or administrative password resets.
070 * <BR>
071 * <BLOCKQUOTE>
072 *   <B>NOTE:</B>  This class, and other classes within the
073 *   {@code com.unboundid.ldap.sdk.unboundidds} package structure, are only
074 *   supported for use against Ping Identity, UnboundID, and
075 *   Nokia/Alcatel-Lucent 8661 server products.  These classes provide support
076 *   for proprietary functionality or for external specifications that are not
077 *   considered stable or mature enough to be guaranteed to work in an
078 *   interoperable way with other types of LDAP servers.
079 * </BLOCKQUOTE>
080 * <BR>
081 * This extended request has an OID of "1.3.6.1.4.1.30221.2.6.62" and a value\
082 * with the following encoding:
083 * <BR><BR>
084 * <PRE>
085 *   GeneratePasswordRequest ::= SEQUENCE {
086 *        passwordPolicySelection     CHOICE {
087 *             defaultPolicy        [0] NULL,
088 *             passwordPolicyDN     [1] LDAPDN,
089 *             targetEntryDN        [2] LDAPDN,
090 *             ... },
091 *        numberOfPasswords      [3] INTEGER DEFAULT 1,
092 *        validationAttempts     [4] INTEGER DEFAULT 5,
093 *        ... }
094 * </PRE>
095 * <BR><BR>
096 * The "passwordPolicySelection" element allows the client to indicate which
097 * password policy (along with its associated password generator and password
098 * validators) should be used in the course of generating the passwords, and
099 * available options include:
100 * <UL>
101 *   <LI>defaultPolicy -- Indicates that the server should use the default
102 *       password policy as defined in the configuration.</LI>
103 *   <LI>passwordPolicyDN -- Specifies the DN of the password policy that should
104 *       be used.</LI>
105 *   <LI>targetEntryDN -- Specifies the DN of the target entry for which the
106 *       passwords are to be generated.  If this entry exists, then the password
107 *       policy that governs it will be used.  If the entry does not exist, then
108 *       the server will generate a stub of an entry with the provided DN and
109 *       compute virtual attributes for that entry to account for the
110 *       possibility that a password policy may be assigned by a virtual
111 *       attribute, but will fall back to using the default password policy as
112 *       defined in the configuration.
113 * </UL>
114 * <BR><BR>
115 * The "numberOfPasswords" element indicates the number of passwords that the
116 * server should generate, since it may be beneficial for the server to suggest
117 * multiple passwords and allow the user to choose one.  If specified, then the
118 * value must be greater than or equal to one.
119 * <BR><BR>
120 * The "validationAttempts" element indicates the number of attempts that the
121 * server should make to generate each password in a way that will satisfy the
122 * set of validators associated with the selected password policy.  A value of
123 * zero indicates that no validation should be performed.  A value of one will
124 * cause the server to invoke password validators on each generated password,
125 * still returning that password but also including information about potential
126 * reasons that generated password may not pass validation.  A value that is
127 * greater than one will cause the server to re-generate each password up to
128 * the specified number of times if the previous attempt resulted in a password
129 * that did not satisfy all of the associated password validators.  In the event
130 * that no acceptable password could be generated after exhausting all attempts,
131 * the server will select the last one generated, but will provide a list of
132 * reasons that the password was not considered acceptable so that they may be
133 * provided to the end user as additional guidance when choosing a password.
134 * <BR><BR>
135 * If the generate password operation is processed successfully, then the server
136 * will return a {@link GeneratePasswordExtendedResult} response with the
137 * passwords that it generated and other relevant information.
138 */
139@NotMutable()
140@ThreadSafety(level=ThreadSafetyLevel.COMPLETELY_THREADSAFE)
141public final class GeneratePasswordExtendedRequest
142       extends ExtendedRequest
143{
144  /**
145   * The OID (1.3.6.1.4.1.30221.2.6.62) for the generate password extended
146   * request.
147   */
148  @NotNull public static final String GENERATE_PASSWORD_REQUEST_OID =
149       "1.3.6.1.4.1.30221.2.6.62";
150
151
152
153  /**
154   * The BER type to use for the element that specifies the number of passwords
155   * to generate.
156   */
157  private static final byte TYPE_NUMBER_OF_PASSWORDS = (byte) 0x83;
158
159
160
161  /**
162   * The default value for the number of passwords to generate.
163   */
164  private static final int DEFAULT_NUMBER_OF_PASSWORDS = 1;
165
166
167
168  /**
169   * The BER type to use for the element that specifies the number of validation
170   * attempts to perform.
171   */
172  private static final byte TYPE_VALIDATION_ATTEMPTS = (byte) 0x84;
173
174
175
176  /**
177   * The default number of validation attempts to perform.
178   */
179  private static final int DEFAULT_VALIDATION_ATTEMPTS = 5;
180
181
182
183  /**
184   * The serial version UID for this serializable class.
185   */
186  private static final long serialVersionUID = -4264500486902843854L;
187
188
189
190  // The number of passwords that should be generated.
191  private final int numberOfPasswords;
192
193  // The number of validation attempts to make for each generated password.
194  private final int numberOfValidationAttempts;
195
196  // The password policy selection type for the request.
197  @NotNull private final GeneratePasswordPolicySelectionType
198       passwordPolicySelectionType;
199
200  // The DN of the password policy that should be used in conjunction with the
201  // PASSWORD_POLICY_DN password policy selection type.
202  @Nullable private final String passwordPolicyDN;
203
204  // The DN of the target entry that should be used in conjunction with the
205  // TARGET_ENTRY_DN password policy selection type.
206  @Nullable private final String targetEntryDN;
207
208
209
210  /**
211   * Creates a new generate password extended request with all the default
212   * settings.
213   *
214   * @param  controls  The set of controls to include in the request.  It may be
215   *                   {@code null} or empty if there should not be any request
216   *                   controls.
217   */
218  public GeneratePasswordExtendedRequest(@Nullable final Control... controls)
219  {
220    this(GeneratePasswordPolicySelectionType.DEFAULT_POLICY, null, null,
221         DEFAULT_NUMBER_OF_PASSWORDS, DEFAULT_VALIDATION_ATTEMPTS, controls);
222  }
223
224
225
226  /**
227   * Creates a new generate password extended request with the provided
228   * settings.
229   *
230   * @param  passwordPolicySelectionType
231   *              The password policy selection type to use.  It must not be
232   *              {@code null}.
233   * @param  passwordPolicyDN
234   *              The password policy DN to use in conjunction with the
235   *              {@link GeneratePasswordPolicySelectionType#PASSWORD_POLICY_DN}
236   *              password policy selection type.  It must be non-{@code null}
237   *              when used in conjunction with that policy selection type, and
238   *              it must be {@code null} for all other selection types.
239   * @param  targetEntryDN
240   *              The target entry DN to use in conjunction with the
241   *              {@link GeneratePasswordPolicySelectionType#TARGET_ENTRY_DN}
242   *              password policy selection type.  It must be non-{@code null}
243   *              when used in conjunction with that policy selection type, and
244   *              it must be {@code null} for all other selection types.
245   * @param  numberOfPasswords
246   *              The number of passwords to generate.  The value must be
247   *              greater than or equal to one.
248   * @param  numberOfValidationAttempts
249   *              The number of attempts that should be made to generate each
250   *              password in an attempt to obtain a password that satisfies the
251   *              associated set of password validators.  The value must be
252   *              greater than or equal to zero.
253   * @param  controls
254   *              The set of controls to include in the request.  It may be
255   *              {@code null} or empty if there should not be any request
256   *              controls.
257   */
258  private GeneratePasswordExtendedRequest(
259       @NotNull final GeneratePasswordPolicySelectionType
260            passwordPolicySelectionType,
261       @Nullable final String passwordPolicyDN,
262       @Nullable final String targetEntryDN,
263       final int numberOfPasswords,
264       final int numberOfValidationAttempts,
265       @Nullable final Control... controls)
266  {
267    super(GENERATE_PASSWORD_REQUEST_OID,
268         encodeValue(passwordPolicySelectionType, passwordPolicyDN,
269              targetEntryDN, numberOfPasswords, numberOfValidationAttempts),
270         controls);
271
272    this.passwordPolicySelectionType = passwordPolicySelectionType;
273    this.passwordPolicyDN = passwordPolicyDN;
274    this.targetEntryDN = targetEntryDN;
275    this.numberOfPasswords = numberOfPasswords;
276    this.numberOfValidationAttempts = numberOfValidationAttempts;
277  }
278
279
280
281  /**
282   * Uses the provided information to generate an ASN.1 octet string that may be
283   * used as the value of a generate password extended request.
284   *
285   * @param  passwordPolicySelectionType
286   *              The password policy selection type to use.  It must not be
287   *              {@code null}.
288   * @param  passwordPolicyDN
289   *              The password policy DN to use in conjunction with the
290   *              {@link GeneratePasswordPolicySelectionType#PASSWORD_POLICY_DN}
291   *              password policy selection type.  It must be non-{@code null}
292   *              when used in conjunction with that policy selection type, and
293   *              it must be {@code null} for all other selection types.
294   * @param  targetEntryDN
295   *              The target entry DN to use in conjunction with the
296   *              {@link GeneratePasswordPolicySelectionType#TARGET_ENTRY_DN}
297   *              password policy selection type.  It must be non-{@code null}
298   *              when used in conjunction with that policy selection type, and
299   *              it must be {@code null} for all other selection types.
300   * @param  numberOfPasswords
301   *              The number of passwords to generate.  The value must be
302   *              greater than or equal to one.
303   * @param  numberOfValidationAttempts
304   *              The number of attempts that should be made to generate each
305   *              password in an attempt to obtain a password that satisfies the
306   *              associated set of password validators.  The value must be
307   *              greater than or equal to zero.
308   *
309   * @return  An ASN.1 octet string that may be used as the value of a generate
310   *          password extended request with the provided information, or
311   *          {@code null} if the request uses all the default settings and no
312   *          value is needed.
313   */
314  @Nullable()
315  private static ASN1OctetString encodeValue(
316       @NotNull final GeneratePasswordPolicySelectionType
317            passwordPolicySelectionType,
318       @Nullable final String passwordPolicyDN,
319       @Nullable final String targetEntryDN,
320       final int numberOfPasswords, final int numberOfValidationAttempts)
321  {
322    Validator.ensureNotNullWithMessage(passwordPolicySelectionType,
323         "GeneratePasswordExtendedRequest.passwordPolicySelectionType must " +
324              "not be null.");
325
326    final List<ASN1Element> elements = new ArrayList<>(3);
327    switch (passwordPolicySelectionType)
328    {
329      case DEFAULT_POLICY:
330        Validator.ensureTrue((passwordPolicyDN == null),
331             "GeneratePasswordExtendedRequest.passwordPolicyDN must be null " +
332                  "when using a password policy selection type of " +
333                  passwordPolicySelectionType + '.');
334        Validator.ensureTrue((targetEntryDN == null),
335             "GeneratePasswordExtendedRequest.targetEntryDN must be null " +
336                  "when using a password policy selection type of " +
337                  passwordPolicySelectionType + '.');
338
339        if ((numberOfPasswords == DEFAULT_NUMBER_OF_PASSWORDS) &&
340             (numberOfValidationAttempts == DEFAULT_VALIDATION_ATTEMPTS))
341        {
342          return null;
343        }
344
345        elements.add(new ASN1Null(passwordPolicySelectionType.getBERType()));
346        break;
347
348      case PASSWORD_POLICY_DN:
349        Validator.ensureNotNullWithMessage(passwordPolicyDN,
350             "GeneratePasswordExtendedRequest.passwordPolicyDN must not be " +
351                  "null when using a password policy selection type of " +
352                  passwordPolicySelectionType + '.');
353        Validator.ensureTrue((targetEntryDN == null),
354             "GeneratePasswordExtendedRequest.targetEntryDN must be null " +
355                  "when using a password policy selection type of " +
356                  passwordPolicySelectionType + '.');
357
358        elements.add(new ASN1OctetString(
359             passwordPolicySelectionType.getBERType(), passwordPolicyDN));
360        break;
361
362      case TARGET_ENTRY_DN:
363        Validator.ensureTrue((passwordPolicyDN == null),
364             "GeneratePasswordExtendedRequest.passwordPolicyDN must be null " +
365                  "when using a password policy selection type of " +
366                  passwordPolicySelectionType + '.');
367        Validator.ensureNotNullWithMessage(targetEntryDN,
368             "GeneratePasswordExtendedRequest.targetEntryDN must not be null " +
369                  "when using a password policy selection type of " +
370                  passwordPolicySelectionType + '.');
371
372        elements.add(new ASN1OctetString(
373             passwordPolicySelectionType.getBERType(), targetEntryDN));
374        break;
375    }
376
377    if (numberOfPasswords != DEFAULT_NUMBER_OF_PASSWORDS)
378    {
379      Validator.ensureTrue((numberOfPasswords >= 1),
380           "GeneratePasswordExtendedRequest.numberOfPasswords must be " +
381                "greater than or equal to one.");
382      elements.add(new ASN1Integer(TYPE_NUMBER_OF_PASSWORDS,
383           numberOfPasswords));
384    }
385
386    if (numberOfValidationAttempts != DEFAULT_VALIDATION_ATTEMPTS)
387    {
388      Validator.ensureTrue((numberOfValidationAttempts >= 0),
389           "GeneratePasswordExtendedRequest.validationAttempts must be " +
390                "greater than or equal to zero.");
391      elements.add(new ASN1Integer(TYPE_VALIDATION_ATTEMPTS,
392           numberOfValidationAttempts));
393    }
394
395    return new ASN1OctetString(new ASN1Sequence(elements).encode());
396  }
397
398
399
400  /**
401   * Creates a new generate password extended request that is decoded from the
402   * provided generic request.
403   *
404   * @param  request  The extended request to be decoded as a generate password
405   *                  extended request.  It must not be {@code null}.
406   *
407   * @throws  LDAPException  If the provided extended request cannot be decoded
408   *                         as a generate password request.
409   */
410  public GeneratePasswordExtendedRequest(@NotNull final ExtendedRequest request)
411         throws LDAPException
412  {
413    super(request);
414
415    final ASN1OctetString value = request.getValue();
416    if (value == null)
417    {
418      passwordPolicySelectionType =
419           GeneratePasswordPolicySelectionType.DEFAULT_POLICY;
420      passwordPolicyDN = null;
421      targetEntryDN = null;
422      numberOfPasswords = DEFAULT_NUMBER_OF_PASSWORDS;
423      numberOfValidationAttempts = DEFAULT_VALIDATION_ATTEMPTS;
424      return;
425    }
426
427    try
428    {
429      final ASN1Element[] elements =
430           ASN1Sequence.decodeAsSequence(value.getValue()).elements();
431
432      passwordPolicySelectionType =
433           GeneratePasswordPolicySelectionType.forType(elements[0].getType());
434      if (passwordPolicySelectionType == null)
435      {
436        throw new LDAPException(ResultCode.DECODING_ERROR,
437             ERR_GENERATE_PASSWORD_REQUEST_UNSUPPORTED_SELECTION_TYPE.get(
438                  StaticUtils.toHex(elements[0].getType())));
439      }
440
441      switch (passwordPolicySelectionType)
442      {
443        case PASSWORD_POLICY_DN:
444          passwordPolicyDN = elements[0].decodeAsOctetString().stringValue();
445          targetEntryDN = null;
446          break;
447
448        case TARGET_ENTRY_DN:
449          targetEntryDN = elements[0].decodeAsOctetString().stringValue();
450          passwordPolicyDN = null;
451          break;
452
453        case DEFAULT_POLICY:
454        default:
455          passwordPolicyDN = null;
456          targetEntryDN = null;
457          break;
458      }
459
460      int numPasswords = DEFAULT_NUMBER_OF_PASSWORDS;
461      int numAttempts = DEFAULT_VALIDATION_ATTEMPTS;
462      for (int i=1; i < elements.length; i++)
463      {
464        switch (elements[i].getType())
465        {
466          case TYPE_NUMBER_OF_PASSWORDS:
467            numPasswords = ASN1Integer.decodeAsInteger(elements[i]).intValue();
468            if (numPasswords < 1)
469            {
470              throw new LDAPException(ResultCode.DECODING_ERROR,
471                   ERR_GENERATE_PASSWORD_REQUEST_INVALID_NUM_PASSWORDS.get(
472                        numPasswords));
473            }
474            break;
475
476          case TYPE_VALIDATION_ATTEMPTS:
477            numAttempts = ASN1Integer.decodeAsInteger(elements[i]).intValue();
478            if (numAttempts < 0)
479            {
480              throw new LDAPException(ResultCode.DECODING_ERROR,
481                   ERR_GENERATE_PASSWORD_REQUEST_INVALID_NUM_ATTEMPTS.get(
482                        numAttempts));
483            }
484            break;
485        }
486      }
487
488      numberOfPasswords = numPasswords;
489      numberOfValidationAttempts = numAttempts;
490    }
491    catch (final LDAPException e)
492    {
493      Debug.debugException(e);
494      throw e;
495    }
496    catch (final Exception e)
497    {
498      Debug.debugException(e);
499      throw new LDAPException(ResultCode.DECODING_ERROR,
500           ERR_GENERATE_PASSWORD_REQUEST_DECODING_ERROR.get(
501                StaticUtils.getExceptionMessage(e)),
502           e);
503    }
504  }
505
506
507
508  /**
509   * Creates a generate password extended request that will use the default
510   * password policy (as defined in the server configuration) to determine which
511   * password generator and validators should be used.
512   *
513   * @param  numberOfPasswords
514   *              The number of passwords to generate.  The value must be
515   *              greater than or equal to one.
516   * @param  numberOfValidationAttempts
517   *              The number of attempts that should be made to generate each
518   *              password in an attempt to obtain a password that satisfies the
519   *              associated set of password validators.  The value must be
520   *              greater than or equal to zero.
521   * @param  controls
522   *              The set of controls to include in the request.  It may be
523   *              {@code null} or empty if there should not be any request
524   *              controls.
525   *
526   * @return  The generate password extended request that was created.
527   */
528  @NotNull()
529  public static GeneratePasswordExtendedRequest createDefaultPolicyRequest(
530                     final int numberOfPasswords,
531                     final int numberOfValidationAttempts,
532                     @Nullable final Control... controls)
533  {
534    return new GeneratePasswordExtendedRequest(
535         GeneratePasswordPolicySelectionType.DEFAULT_POLICY, null, null,
536         numberOfPasswords, numberOfValidationAttempts, controls);
537  }
538
539
540
541  /**
542   * Creates a generate password extended request that will use the password
543   * policy defined in the entry with the specified DN to determine which
544   * password generator and validators should be used.
545   *
546   * @param  passwordPolicyDN
547   *              The DN of the entry that defines the password policy to use to
548   *              determine which password generator and validators should be
549   *              used.  It must not be {@code null}.
550   * @param  numberOfPasswords
551   *              The number of passwords to generate.  The value must be
552   *              greater than or equal to one.
553   * @param  numberOfValidationAttempts
554   *              The number of attempts that should be made to generate each
555   *              password in an attempt to obtain a password that satisfies the
556   *              associated set of password validators.  The value must be
557   *              greater than or equal to zero.
558   * @param  controls
559   *              The set of controls to include in the request.  It may be
560   *              {@code null} or empty if there should not be any request
561   *              controls.
562   *
563   * @return  The generate password extended request that was created.
564   */
565  @NotNull()
566  public static GeneratePasswordExtendedRequest createPasswordPolicyDNRequest(
567                     @NotNull final String passwordPolicyDN,
568                     final int numberOfPasswords,
569                     final int numberOfValidationAttempts,
570                     @Nullable final Control... controls)
571  {
572    return new GeneratePasswordExtendedRequest(
573         GeneratePasswordPolicySelectionType.PASSWORD_POLICY_DN,
574         passwordPolicyDN, null, numberOfPasswords, numberOfValidationAttempts,
575         controls);
576  }
577
578
579
580  /**
581   * Creates a generate password extended request that will use the password
582   * policy that governs the specified entry to determine which
583   * password generator and validators should be used.  If the target entry does
584   * not exist, then the server will generate a stub of an entry and compute
585   * virtual attributes for that entry to account for the possibility that the
586   * password policy may be specified using a virtual attribute.
587   *
588   * @param  targetEntryDN
589   *              The DN of the entry whose governing password policy should be
590   *              used.  It must not be {@code null}.
591   * @param  numberOfPasswords
592   *              The number of passwords to generate.  The value must be
593   *              greater than or equal to one.
594   * @param  numberOfValidationAttempts
595   *              The number of attempts that should be made to generate each
596   *              password in an attempt to obtain a password that satisfies the
597   *              associated set of password validators.  The value must be
598   *              greater than or equal to zero.
599   * @param  controls
600   *              The set of controls to include in the request.  It may be
601   *              {@code null} or empty if there should not be any request
602   *              controls.
603   *
604   * @return  The generate password extended request that was created.
605   */
606  @NotNull()
607  public static GeneratePasswordExtendedRequest createTargetEntryDNRequest(
608                     @NotNull final String targetEntryDN,
609                     final int numberOfPasswords,
610                     final int numberOfValidationAttempts,
611                     @Nullable final Control... controls)
612  {
613    return new GeneratePasswordExtendedRequest(
614         GeneratePasswordPolicySelectionType.TARGET_ENTRY_DN, null,
615         targetEntryDN, numberOfPasswords, numberOfValidationAttempts,
616         controls);
617  }
618
619
620
621  /**
622   * Retrieves the password policy selection type for this request.
623   *
624   * @return  The password policy selection type for this request.
625   */
626  @NotNull()
627  public GeneratePasswordPolicySelectionType getPasswordPolicySelectionType()
628  {
629    return passwordPolicySelectionType;
630  }
631
632
633
634  /**
635   * Retrieves the DN of the entry that defines the password policy that should
636   * be used when generating and validating passwords.  This will only be
637   * available for the
638   * {@link GeneratePasswordPolicySelectionType#PASSWORD_POLICY_DN} password
639   * policy selection type.
640   *
641   * @return  The DN of the entry that defines the password policy that should
642   *          be used when generating and validating the passwords, or
643   *          {@code null} if the password policy selection type is anything
644   *          other than {@code PASSWORD_POLICY_DN}.
645   */
646  @Nullable()
647  public String getPasswordPolicyDN()
648  {
649    return passwordPolicyDN;
650  }
651
652
653
654  /**
655   * Retrieves the DN of the target entry whose governing password policy should
656   * be used when generating and validating passwords.  This will only be
657   * available for the
658   * {@link GeneratePasswordPolicySelectionType#TARGET_ENTRY_DN} password
659   * policy selection type.
660   *
661   * @return  The DN of the target entry whose governing password policy should
662   *          be used when generating and validating the passwords, or
663   *          {@code null} if the password policy selection type is anything
664   *          other than {@code TARGET_ENTRY_DN}.
665   */
666  @Nullable()
667  public String getTargetEntryDN()
668  {
669    return targetEntryDN;
670  }
671
672
673
674  /**
675   * Retrieves the number of passwords that the client wants the server to
676   * generate.  Note that the server may choose to generate fewer passwords than
677   * this, based on its configuration.
678   *
679   * @return  The number of passwords that the client wants the server to
680   *          generate.
681   */
682  public int getNumberOfPasswords()
683  {
684    return numberOfPasswords;
685  }
686
687
688
689  /**
690   * Retrieves the number of maximum number of attempts that the client wants
691   * the server to make when generating each password in the hope that the
692   * generated password will satisfy the validation criteria specified in the
693   * associated password policy.  Note that the server may choose to make fewer
694   * validation attempts than this, based on its configuration.
695   *
696   * @return  The number maximum number of validation attempts that the client
697   *          wants the server to make, or zero if the server should not attempt
698   *          to validate the generated passwords.
699   */
700  public int getNumberOfValidationAttempts()
701  {
702    return numberOfValidationAttempts;
703  }
704
705
706
707  /**
708   * {@inheritDoc}
709   */
710  @Override()
711  @NotNull()
712  protected GeneratePasswordExtendedResult process(
713                 @NotNull final LDAPConnection connection, final int depth)
714            throws LDAPException
715  {
716    return new GeneratePasswordExtendedResult(super.process(connection, depth));
717  }
718
719
720
721  /**
722   * {@inheritDoc}
723   */
724  @Override()
725  @NotNull()
726  public GeneratePasswordExtendedRequest duplicate()
727  {
728    return duplicate(getControls());
729  }
730
731
732
733  /**
734   * {@inheritDoc}
735   */
736  @Override()
737  @NotNull()
738  public GeneratePasswordExtendedRequest duplicate(
739              @Nullable final Control[] controls)
740  {
741    final GeneratePasswordExtendedRequest r =
742         new GeneratePasswordExtendedRequest(passwordPolicySelectionType,
743              passwordPolicyDN, targetEntryDN, numberOfPasswords,
744              numberOfValidationAttempts, controls);
745    r.setResponseTimeoutMillis(getResponseTimeoutMillis(null));
746    r.setIntermediateResponseListener(getIntermediateResponseListener());
747    r.setReferralDepth(getReferralDepth());
748    r.setReferralConnector(getReferralConnectorInternal());
749    return r;
750  }
751
752
753
754  /**
755   * {@inheritDoc}
756   */
757  @Override()
758  @NotNull()
759  public String getExtendedRequestName()
760  {
761    return INFO_GENERATE_PASSWORD_REQUEST_NAME.get();
762  }
763
764
765
766  /**
767   * {@inheritDoc}
768   */
769  @Override()
770  public void toString(@NotNull final StringBuilder buffer)
771  {
772    buffer.append("GeneratePasswordExtendedRequest(" +
773         "passwordPolicySelectionType='");
774    buffer.append(passwordPolicySelectionType.name());
775    buffer.append('\'');
776
777    switch (passwordPolicySelectionType)
778    {
779      case PASSWORD_POLICY_DN:
780        buffer.append(", passwordPolicyDN='");
781        buffer.append(passwordPolicyDN);
782        buffer.append('\'');
783        break;
784      case TARGET_ENTRY_DN:
785        buffer.append(", targetEntryDN='");
786        buffer.append(targetEntryDN);
787        buffer.append('\'');
788        break;
789    }
790
791    buffer.append(", numberOfPasswords=");
792    buffer.append(numberOfPasswords);
793    buffer.append(", numberOfValidationAttempts=");
794    buffer.append(numberOfValidationAttempts);
795
796    final Control[] controls = getControls();
797    if (controls.length > 0)
798    {
799      buffer.append(", controls={");
800      for (int i=0; i < controls.length; i++)
801      {
802        if (i > 0)
803        {
804          buffer.append(", ");
805        }
806
807        buffer.append(controls[i]);
808      }
809      buffer.append('}');
810    }
811
812    buffer.append(')');
813  }
814}