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