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