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