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