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