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