001/*
002 * Copyright 2015-2024 Ping Identity Corporation
003 * All Rights Reserved.
004 */
005/*
006 * Copyright 2015-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) 2015-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 com.unboundid.asn1.ASN1Element;
041import com.unboundid.asn1.ASN1OctetString;
042import com.unboundid.asn1.ASN1Null;
043import com.unboundid.asn1.ASN1Sequence;
044import com.unboundid.ldap.sdk.Control;
045import com.unboundid.ldap.sdk.ExtendedRequest;
046import com.unboundid.ldap.sdk.ExtendedResult;
047import com.unboundid.ldap.sdk.LDAPConnection;
048import com.unboundid.ldap.sdk.LDAPException;
049import com.unboundid.ldap.sdk.ResultCode;
050import com.unboundid.util.Debug;
051import com.unboundid.util.NotMutable;
052import com.unboundid.util.NotNull;
053import com.unboundid.util.Nullable;
054import com.unboundid.util.StaticUtils;
055import com.unboundid.util.ThreadSafety;
056import com.unboundid.util.ThreadSafetyLevel;
057
058import static com.unboundid.ldap.sdk.unboundidds.extensions.ExtOpMessages.*;
059
060
061
062/**
063 * This class provides an implementation of an extended request that may be used
064 * to retrieve the set of password quality requirements that the Directory
065 * Server will impose for a specified operation, which may include adding a new
066 * user (including a password), a user changing his/her own password (a self
067 * change), or one user changing the password for another user (an
068 * administrative reset).
069 * <BR>
070 * <BLOCKQUOTE>
071 *   <B>NOTE:</B>  This class, and other classes within the
072 *   {@code com.unboundid.ldap.sdk.unboundidds} package structure, are only
073 *   supported for use against Ping Identity, UnboundID, and
074 *   Nokia/Alcatel-Lucent 8661 server products.  These classes provide support
075 *   for proprietary functionality or for external specifications that are not
076 *   considered stable or mature enough to be guaranteed to work in an
077 *   interoperable way with other types of LDAP servers.
078 * </BLOCKQUOTE>
079 * <BR>
080 * This extended request has an OID of 1.3.6.1.4.1.30221.2.6.43 and a value with
081 * the following encoding:
082 * <PRE>
083 *   GetPasswordQualityRequirementsRequestValue ::= SEQUENCE {
084 *        target     CHOICE {
085 *             addWithDefaultPasswordPolicy           [0] NULL,
086 *             addWithSpecifiedPasswordPolicy         [1] LDAPDN,
087 *             selfChangeForAuthorizationIdentity     [2] NULL,
088 *             selfChangeForSpecifiedUser             [3] LDAPDN,
089 *             administrativeResetForUser             [4] LDAPDN,
090 *             ... },
091 *        ... }
092 * </PRE>
093 */
094@NotMutable()
095@ThreadSafety(level=ThreadSafetyLevel.COMPLETELY_THREADSAFE)
096public final class GetPasswordQualityRequirementsExtendedRequest
097       extends ExtendedRequest
098{
099  /**
100   * The OID (1.3.6.1.4.1.30221.2.6.43) for the get password quality
101   * requirements extended request.
102   */
103  @NotNull public static final String
104       OID_GET_PASSWORD_QUALITY_REQUIREMENTS_REQUEST =
105            "1.3.6.1.4.1.30221.2.6.43";
106
107
108
109  /**
110   * The serial version UID for this serializable class.
111   */
112  private static final long serialVersionUID = -3652010872400265557L;
113
114
115
116  // The target type for this get password quality requirements extended
117  // request.
118  @NotNull private final GetPasswordQualityRequirementsTargetType targetType;
119
120  // The target DN for this get password quality requirements extended request.
121  @Nullable private final String targetDN;
122
123
124
125  /**
126   * Creates a new get password quality requirements extended request with the
127   * provided information.
128   *
129   * @param  targetType  The target type for this request.  It must not be
130   *                     {@code null}.
131   * @param  targetDN    The target DN for this request.  It may be {@code null}
132   *                     if no target DN is required for the specified target
133   *                     type.
134   * @param  controls    The set of controls to include in the request.  It may
135   *                     be {@code null} or empty if no controls should be
136   *                     included.
137   */
138  private GetPasswordQualityRequirementsExtendedRequest(
139       @NotNull final GetPasswordQualityRequirementsTargetType targetType,
140       @Nullable final String targetDN,
141       @Nullable final Control... controls)
142  {
143    super(OID_GET_PASSWORD_QUALITY_REQUIREMENTS_REQUEST,
144         encodeValue(targetType, targetDN), controls);
145
146    this.targetType = targetType;
147    this.targetDN   = targetDN;
148  }
149
150
151
152  /**
153   * Creates a new get password quality requirements extended request decoded
154   * from the provided generic extended request.
155   *
156   * @param  r  The extended request to decode as a get password quality
157   *            requirements request.
158   *
159   * @throws  LDAPException  If a problem is encountered while attempting to
160   *                         decoded the provided extended request as a
161   *                         get password quality requirements request.
162   */
163  public GetPasswordQualityRequirementsExtendedRequest(
164              @NotNull final ExtendedRequest r)
165         throws LDAPException
166  {
167    super(r);
168
169    final ASN1OctetString value = r.getValue();
170    if (value == null)
171    {
172      throw new LDAPException(ResultCode.DECODING_ERROR,
173           ERR_GET_PW_QUALITY_REQS_REQUEST_NO_VALUE.get());
174    }
175
176    try
177    {
178      final ASN1Element[] elements =
179           ASN1Sequence.decodeAsSequence(value.getValue()).elements();
180
181      targetType = GetPasswordQualityRequirementsTargetType.forBERType(
182           elements[0].getType());
183      if (targetType == null)
184      {
185        throw new LDAPException(ResultCode.DECODING_ERROR,
186             ERR_GET_PW_QUALITY_REQS_REQUEST_UNKNOWN_TARGET_TYPE.get(
187                  StaticUtils.toHex(elements[0].getType())));
188      }
189
190      switch (targetType)
191      {
192        case ADD_WITH_SPECIFIED_PASSWORD_POLICY:
193        case SELF_CHANGE_FOR_SPECIFIED_USER:
194        case ADMINISTRATIVE_RESET_FOR_SPECIFIED_USER:
195          targetDN = ASN1OctetString.decodeAsOctetString(
196               elements[0]).stringValue();
197          break;
198
199        case ADD_WITH_DEFAULT_PASSWORD_POLICY:
200        case SELF_CHANGE_FOR_AUTHORIZATION_IDENTITY:
201        default:
202          targetDN = null;
203          break;
204      }
205    }
206    catch (final LDAPException le)
207    {
208      Debug.debugException(le);
209      throw le;
210    }
211    catch (final Exception e)
212    {
213      Debug.debugException(e);
214      throw new LDAPException(ResultCode.DECODING_ERROR,
215           ERR_GET_PW_QUALITY_REQS_REQUEST_CANNOT_DECODE.get(
216                StaticUtils.getExceptionMessage(e)),
217           e);
218    }
219  }
220
221
222
223  /**
224   * Encodes the provided information into an ASN.1 octet string suitable for
225   * use as the value of this extended request.
226   *
227   * @param  targetType  The target type for this request.  It must not be
228   *                     {@code null}.
229   * @param  targetDN    The target DN for this request.  It may be {@code null}
230   *                     if no target DN is required for the specified target
231   *                     type.
232   *
233   * @return  The ASN.1 octet string containing the encoded request value.
234   */
235  @NotNull()
236  private static ASN1OctetString encodeValue(
237       @NotNull final GetPasswordQualityRequirementsTargetType targetType,
238       @Nullable final String targetDN)
239  {
240    final ASN1Element targetElement;
241    switch (targetType)
242    {
243      case ADD_WITH_SPECIFIED_PASSWORD_POLICY:
244      case SELF_CHANGE_FOR_SPECIFIED_USER:
245      case ADMINISTRATIVE_RESET_FOR_SPECIFIED_USER:
246        targetElement = new ASN1OctetString(targetType.getBERType(), targetDN);
247        break;
248
249      case ADD_WITH_DEFAULT_PASSWORD_POLICY:
250      case SELF_CHANGE_FOR_AUTHORIZATION_IDENTITY:
251      default:
252        targetElement = new ASN1Null(targetType.getBERType());
253        break;
254    }
255
256    final ASN1Sequence valueSequence = new ASN1Sequence(
257         targetElement);
258
259    return new ASN1OctetString(valueSequence.encode());
260  }
261
262
263
264  /**
265   * Creates a new get password quality requirements extended request that will
266   * retrieve the password requirements for an add operation governed by the
267   * server's default password policy.
268   *
269   * @param  controls  The set of controls to include in the request.  It may be
270   *                   {@code null} or empty if no controls should be included
271   *                   in the request.
272   *
273   * @return  A new get password quality requirements extended request that will
274   *          retrieve the password requirements for an add operation governed
275   *          by the server's default password policy.
276   */
277  @NotNull()
278  public static GetPasswordQualityRequirementsExtendedRequest
279                     createAddWithDefaultPasswordPolicyRequest(
280                          @Nullable final Control... controls)
281  {
282    return new GetPasswordQualityRequirementsExtendedRequest(
283         GetPasswordQualityRequirementsTargetType.
284              ADD_WITH_DEFAULT_PASSWORD_POLICY,
285         null, controls);
286  }
287
288
289
290  /**
291   * Creates a new get password quality requirements extended request that will
292   * retrieve the password requirements for an add operation governed by the
293   * specified password policy.
294   *
295   * @param  policyDN  The DN of the entry that defines the password policy from
296   *                   which to determine the password quality requirements.
297   * @param  controls  The set of controls to include in the request.  It may be
298   *                   {@code null} or empty if no controls should be included
299   *                   in the request.
300   *
301   * @return  A new get password quality requirements extended request that will
302   *          retrieve the password requirements for an add operation governed
303   *          by the specified password policy.
304   */
305  @NotNull()
306  public static GetPasswordQualityRequirementsExtendedRequest
307                     createAddWithSpecifiedPasswordPolicyRequest(
308                          @NotNull final String policyDN,
309                          @Nullable final Control... controls)
310  {
311    return new GetPasswordQualityRequirementsExtendedRequest(
312         GetPasswordQualityRequirementsTargetType.
313              ADD_WITH_SPECIFIED_PASSWORD_POLICY,
314         policyDN, controls);
315  }
316
317
318
319  /**
320   * Creates a new get password quality requirements extended request that will
321   * retrieve the password requirements for a self change requested with the
322   * same authorization identity as this extended request.
323   *
324   * @param  controls  The set of controls to include in the request.  It may be
325   *                   {@code null} or empty if no controls should be included
326   *                   in the request.
327   *
328   * @return  A new get password quality requirements extended request that will
329   *          retrieve the password requirements for a self change requested
330   *          with the same authorization identity as this extended request.
331   */
332  @NotNull()
333  public static GetPasswordQualityRequirementsExtendedRequest
334                     createSelfChangeWithSameAuthorizationIdentityRequest(
335                          @Nullable final Control... controls)
336  {
337    return new GetPasswordQualityRequirementsExtendedRequest(
338         GetPasswordQualityRequirementsTargetType.
339              SELF_CHANGE_FOR_AUTHORIZATION_IDENTITY,
340         null, controls);
341  }
342
343
344
345  /**
346   * Creates a new get password quality requirements extended request that will
347   * retrieve the password requirements for a self change requested by the
348   * specified user.
349   *
350   * @param  userDN    The DN of the user for whom to retrieve the self change
351   *                   password requirements.
352   * @param  controls  The set of controls to include in the request.  It may be
353   *                   {@code null} or empty if no controls should be included
354   *                   in the request.
355   *
356   * @return  A new get password quality requirements extended request that will
357   *          retrieve the password requirements for a self change requested by
358   *          the specified user.
359   */
360  @NotNull()
361  public static GetPasswordQualityRequirementsExtendedRequest
362                     createSelfChangeForSpecifiedUserRequest(
363                          @NotNull final String userDN,
364                          @Nullable final Control... controls)
365  {
366    return new GetPasswordQualityRequirementsExtendedRequest(
367         GetPasswordQualityRequirementsTargetType.
368              SELF_CHANGE_FOR_SPECIFIED_USER,
369         userDN, controls);
370  }
371
372
373
374  /**
375   * Creates a new get password quality requirements extended request that will
376   * retrieve the password requirements for an administrative reset targeting
377   * the specified user.
378   *
379   * @param  userDN    The DN of the user for whom to retrieve the
380   *                   administrative reset password requirements.
381   * @param  controls  The set of controls to include in the request.  It may be
382   *                   {@code null} or empty if no controls should be included
383   *                   in the request.
384   *
385   * @return  A new get password quality requirements extended request that will
386   *          retrieve the password requirements for an administrative reset
387   *          targeting the specified user.
388   */
389  @NotNull()
390  public static GetPasswordQualityRequirementsExtendedRequest
391                     createAdministrativeResetForSpecifiedUserRequest(
392                          @NotNull final String userDN,
393                          @Nullable final Control... controls)
394  {
395    return new GetPasswordQualityRequirementsExtendedRequest(
396         GetPasswordQualityRequirementsTargetType.
397              ADMINISTRATIVE_RESET_FOR_SPECIFIED_USER,
398         userDN, controls);
399  }
400
401
402
403  /**
404   * Retrieves the target type for this get password quality requirements
405   * request.
406   *
407   * @return  The target type for this get password quality requirements
408   *          request.
409   */
410  @NotNull()
411  public GetPasswordQualityRequirementsTargetType getTargetType()
412  {
413    return targetType;
414  }
415
416
417
418  /**
419   * Retrieves the target DN for this get password quality requirements request.
420   * For a request with a target type of
421   * {@code ADD_WITH_SPECIFIED_PASSWORD_POLICY}, this will be the DN of the
422   * password policy from which to obtain the password quality requirements.
423   * For a request with a target type of either
424   * {@code SELF_CHANGE_FOR_SPECIFIED_USER} or
425   * {@code ADMINISTRATIVE_RESET_FOR_SPECIFIED_USER}, this will be the DN of the
426   * user for which to obtain the password quality requirements.  For a request
427   * with a target type of either {@code ADD_WITH_DEFAULT_PASSWORD_POLICY} or
428   * {@code SELF_CHANGE_FOR_AUTHORIZATION_IDENTITY}, no target DN is required
429   * and the value returned will be {@code null}.
430   *
431   * @return  The target DN for this get password quality requirements request.
432   */
433  @Nullable()
434  public String getTargetDN()
435  {
436    return targetDN;
437  }
438
439
440
441  /**
442   * {@inheritDoc}
443   */
444  @Override()
445  @NotNull()
446  public GetPasswordQualityRequirementsExtendedResult process(
447              @NotNull final LDAPConnection connection, final int depth)
448         throws LDAPException
449  {
450    final ExtendedResult result = super.process(connection, depth);
451    return new GetPasswordQualityRequirementsExtendedResult(result);
452  }
453
454
455
456  /**
457   * {@inheritDoc}
458   */
459  @Override()
460  @NotNull()
461  public GetPasswordQualityRequirementsExtendedRequest duplicate()
462  {
463    return duplicate(getControls());
464  }
465
466
467
468  /**
469   * {@inheritDoc}
470   */
471  @Override()
472  @NotNull()
473  public GetPasswordQualityRequirementsExtendedRequest duplicate(
474              @Nullable final Control[] controls)
475  {
476    final GetPasswordQualityRequirementsExtendedRequest r =
477         new GetPasswordQualityRequirementsExtendedRequest(targetType,
478              targetDN, controls);
479    r.setResponseTimeoutMillis(getResponseTimeoutMillis(null));
480    r.setIntermediateResponseListener(getIntermediateResponseListener());
481    r.setReferralDepth(getReferralDepth());
482    r.setReferralConnector(getReferralConnectorInternal());
483    return r;
484  }
485
486
487
488  /**
489   * {@inheritDoc}
490   */
491  @Override()
492  @NotNull()
493  public String getExtendedRequestName()
494  {
495    return INFO_EXTENDED_REQUEST_NAME_GET_PW_QUALITY_REQS.get();
496  }
497
498
499
500  /**
501   * {@inheritDoc}
502   */
503  @Override()
504  public void toString(@NotNull final StringBuilder buffer)
505  {
506    buffer.append("GetPasswordQualityRequirementsExtendedRequest(targetType=");
507    buffer.append(targetType.name());
508
509    if (targetDN != null)
510    {
511      buffer.append(", targetDN='");
512      buffer.append(targetDN);
513      buffer.append('\'');
514    }
515
516    final Control[] controls = getControls();
517    if (controls.length > 0)
518    {
519      buffer.append(", controls={");
520      for (int i=0; i < controls.length; i++)
521      {
522        if (i > 0)
523        {
524          buffer.append(", ");
525        }
526
527        buffer.append(controls[i]);
528      }
529      buffer.append('}');
530    }
531
532    buffer.append(')');
533  }
534}