001/*
002 * Copyright 2017-2023 Ping Identity Corporation
003 * All Rights Reserved.
004 */
005/*
006 * Copyright 2017-2023 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) 2017-2023 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.controls;
037
038
039
040import java.io.Serializable;
041
042import com.unboundid.util.Mutable;
043import com.unboundid.util.Nullable;
044import com.unboundid.util.NotNull;
045import com.unboundid.util.ThreadSafety;
046import com.unboundid.util.ThreadSafetyLevel;
047
048
049
050/**
051 * This class provides a set of properties that can be used in conjunction with
052 * the {@link PasswordUpdateBehaviorRequestControl}.
053 * <BR>
054 * <BLOCKQUOTE>
055 *   <B>NOTE:</B>  This class, and other classes within the
056 *   {@code com.unboundid.ldap.sdk.unboundidds} package structure, are only
057 *   supported for use against Ping Identity, UnboundID, and
058 *   Nokia/Alcatel-Lucent 8661 server products.  These classes provide support
059 *   for proprietary functionality or for external specifications that are not
060 *   considered stable or mature enough to be guaranteed to work in an
061 *   interoperable way with other types of LDAP servers.
062 * </BLOCKQUOTE>
063 */
064@Mutable()
065@ThreadSafety(level=ThreadSafetyLevel.NOT_THREADSAFE)
066public final class PasswordUpdateBehaviorRequestControlProperties
067       implements Serializable
068{
069  /**
070   * The serial version UID for this serializable class.
071   */
072  private static final long serialVersionUID = -529840713192839805L;
073
074
075
076  // Indicates whether the requester should be allowed to provide a pre-encoded
077  // password.
078  @Nullable private Boolean allowPreEncodedPassword;
079
080  // Indicates whether to ignore any minimum password age configured in the
081  // password policy.
082  @Nullable private Boolean ignoreMinimumPasswordAge;
083
084  // Indicates whether to skip the process of checking whether the provided
085  // password matches the new current password or is in the password history.
086  @Nullable private Boolean ignorePasswordHistory;
087
088  // Indicates whether to treat the password change as a self change.
089  @Nullable private Boolean isSelfChange;
090
091  // Indicates whether to update the user's account to indicate that they must
092  // change their password the next time they authenticate.
093  @Nullable private Boolean mustChangePassword;
094
095  // Indicates whether to skip password validation for the new password.
096  @Nullable private Boolean skipPasswordValidation;
097
098  // Specifies the password storage scheme to use for the new password.
099  @Nullable private String passwordStorageScheme;
100
101
102
103  /**
104   * Creates a new password update behavior request control properties object
105   * with none of the properties set, which will cause the server to behave as
106   * if the control had not been included in the request.
107   */
108  public PasswordUpdateBehaviorRequestControlProperties()
109  {
110    isSelfChange = null;
111    allowPreEncodedPassword = null;
112    skipPasswordValidation = null;
113    ignorePasswordHistory = null;
114    ignoreMinimumPasswordAge = null;
115    passwordStorageScheme = null;
116    mustChangePassword = null;
117  }
118
119
120
121  /**
122   * Creates a new password update behavior request control properties object
123   * with the settings used for the provided password update behavior request
124   * control.
125   *
126   * @param  control  The control to use to initialize this properties object.
127   */
128  public PasswordUpdateBehaviorRequestControlProperties(
129              @NotNull final PasswordUpdateBehaviorRequestControl control)
130  {
131    isSelfChange = control.getIsSelfChange();
132    allowPreEncodedPassword = control.getAllowPreEncodedPassword();
133    skipPasswordValidation = control.getSkipPasswordValidation();
134    ignorePasswordHistory = control.getIgnorePasswordHistory();
135    ignoreMinimumPasswordAge = control.getIgnoreMinimumPasswordAge();
136    passwordStorageScheme = control.getPasswordStorageScheme();
137    mustChangePassword = control.getMustChangePassword();
138  }
139
140
141
142  /**
143   * Indicates whether the password update behavior request control should
144   * override the server's automatic classification of the password update as a
145   * self change or an administrative reset, and if so, what the overridden
146   * value should be.
147   *
148   * @return  {@code Boolean.TRUE} if the server should treat the password
149   *          update as a self change, {@code Boolean.FALSE} if the server
150   *          should treat the password update as an administrative reset, or
151   *          {@code null} if the server should automatically determine whether
152   *          the password update is a self change or an administrative reset.
153   */
154  @Nullable()
155  public Boolean getIsSelfChange()
156  {
157    return isSelfChange;
158  }
159
160
161
162  /**
163   * Specifies whether the password update behavior request control should
164   * override the server's automatic classification of the password update as a
165   * self change or an administrative reset, and if so, what the overridden
166   * value should be.
167   * <BR><BR>
168   * Normally, the server will consider a password update to be a self change if
169   * it contains the user's current password in addition to the new password, or
170   * if the user entry being updated is the entry for the authorization identity
171   * for the requested operation.  Conversely, if the password change does not
172   * include the target user's current password in addition to the new password,
173   * and the user performing the password change doesn't own the entry being
174   * updated, then it will be considered an administrative reset.  But if this
175   * method is called with a value of {@code Boolean.TRUE}, then the server will
176   * consider the password update to be a self change even if it would have
177   * otherwise been considered an administrative reset, and if this method is
178   * called with a value of {@code Boolean.FALSE}, then the server will consider
179   * the password update to be an administrative reset even if it would have
180   * otherwise been considered a self change.
181   * <BR><BR>
182   * Note that this only applies to modify requests and password modify extended
183   * requests.  It does not apply to add requests, which will always be
184   * considered administrative resets because a user can't change their own
185   * password before their account exists in the server.  However, the password
186   * update behavior request control can still be used to override the server's
187   * default behavior for other properties that do apply to add operations.
188   *
189   * @param  isSelfChange  Specifies whether the control should override the
190   *                       server's automatic classification of the password
191   *                       update as a self change or an administrative reset.
192   *                       If this is {@code Boolean.TRUE}, then it indicates
193   *                       that the server should treat the password update as a
194   *                       self change.  If this is {@code Boolean.FALSE}, then
195   *                       it indicates that the server should treat the
196   *                       password update as an administrative reset.  If this
197   *                       is {@code null}, it indicates that the server should
198   *                       automatically determine whether the password change
199   *                       is a self change or an administrative reset.
200   */
201  public void setIsSelfChange(@Nullable final Boolean isSelfChange)
202  {
203    this.isSelfChange = isSelfChange;
204  }
205
206
207
208  /**
209   * Indicates whether the password update behavior request control should
210   * override the value of the {@code allow-pre-encoded-passwords} configuration
211   * property for the target user's password policy, and if so, what the
212   * overridden value should be.
213   *
214   * @return  {@code Boolean.TRUE} if the server should accept a pre-encoded
215   *          password in the password update even if the server's password
216   *          policy configuration would normally not permit this,
217   *          {@code Boolean.FALSE} if the server should reject a pre-encoded
218   *          password in the password update even if the server's password
219   *          policy configuration would normally accept it, or {@code null} if
220   *          the password policy configuration should be used to determine
221   *          whether to accept pre-encoded passwords.
222   */
223  @Nullable()
224  public Boolean getAllowPreEncodedPassword()
225  {
226    return allowPreEncodedPassword;
227  }
228
229
230
231  /**
232   * Specifies whether the password update behavior request control should
233   * override the value of the {@code allow-pre-encoded-passwords} configuration
234   * property for the target user's password policy, and if so, what the
235   * overridden value should be.
236   * <BR><BR>
237   * Note that certain types of validation cannot be performed for new passwords
238   * that are pre-encoded.  It will not be possible to invoke password
239   * validators on a pre-encoded password, and it will not be possible to
240   * compare the a pre-encoded new password against the current password or one
241   * in the password history.  Allowing end users to provide pre-encoded
242   * passwords could create a loophole in which the user could continue using
243   * the same password longer than they would otherwise be permitted to because
244   * they could keep changing the password to a different encoded representation
245   * of the same password, or to a weaker password than the server would
246   * normally allow.
247   *
248   * @param  allowPreEncodedPassword  Specifies whether the password update
249   *                                  behavior request control should override
250   *                                  the value of the
251   *                                  {@code allow-pre-encoded-passwords}
252   *                                  configuration property for the target
253   *                                  user's password policy, and if so, what
254   *                                  the overridden value should be.  If this
255   *                                  is {@code Boolean.TRUE}, then the server
256   *                                  will permit a pre-encoded password, even
257   *                                  if it would normally reject them.  If this
258   *                                  is {@code Boolean.FALSE}, then the server
259   *                                  will reject a pre-encoded password, even
260   *                                  if it would normally accept it.  If this
261   *                                  is {@code null}, then the server will use
262   *                                  the password policy configuration to
263   *                                  determine whether to accept a pre-encoded
264   *                                  password.
265   */
266  public void setAllowPreEncodedPassword(
267                   @Nullable final Boolean allowPreEncodedPassword)
268  {
269    this.allowPreEncodedPassword = allowPreEncodedPassword;
270  }
271
272
273
274  /**
275   * Indicates whether the password update behavior request control should
276   * override the server's normal behavior with regard to invoking password
277   * validators for any new passwords included in the password update, and if
278   * so, what the overridden behavior should be.
279   *
280   * @return  {@code Boolean.TRUE} if the server should skip invoking the
281   *          password validators configured in the target user's password
282   *          policy validators for any new passwords included in the password
283   *          update even if the server would normally perform password
284   *          validation, {@code Boolean.FALSE} if the server should invoke the
285   *          password validators even if it would normally skip them, or
286   *          {@code null} if the password policy configuration should be used
287   *          to determine whether to skip password validation.
288   */
289  @Nullable()
290  public Boolean getSkipPasswordValidation()
291  {
292    return skipPasswordValidation;
293  }
294
295
296
297  /**
298   * Specifies whether the password update behavior request control should
299   * override the server's normal behavior with regard to invoking password
300   * validators for any new passwords included in the password update, and if
301   * so, what the overridden behavior should be.
302   * <BR><BR>
303   * Note that if password validation is to be performed, it will use the set of
304   * password validators set in the target user's password policy.  It is not
305   * possible to customize which validators will be used on a per-request basis.
306   * <BR><BR>
307   * Also note that password validation can only be performed for new passwords
308   * that are not pre-encoded.  Pre-encoded passwords cannot be checked against
309   * password validators or the password history.
310   *
311   * @param  skipPasswordValidation  Specifies whether the password update
312   *                                 behavior request control should override
313   *                                 the server's normal behavior with regard to
314   *                                 invoking password validators for any new
315   *                                 passwords included in the password update,
316   *                                 and if so, what the overridden behavior
317   *                                 should be.  If this is
318   *                                 {@code Boolean.TRUE}, then the server will
319   *                                 skip new password validation even if it
320   *                                 would normally perform it.  If this is
321   *                                 {@code Boolean.FALSE}, then the server will
322   *                                 perform new password validation even if it
323   *                                 would normally skip it.  If this is
324   *                                 {@code null}, then the server will use the
325   *                                 password policy configuration to determine
326   *                                 whether to perform new password validation.
327   */
328  public void setSkipPasswordValidation(
329                   @Nullable final Boolean skipPasswordValidation)
330  {
331    this.skipPasswordValidation = skipPasswordValidation;
332  }
333
334
335
336  /**
337   * Indicates whether the password update behavior request control should
338   * override the server's normal behavior with regard to checking the password
339   * history for any new passwords included in the password update, and if so,
340   * what the overridden behavior should be.
341   *
342   * @return  {@code Boolean.TRUE} if the server should not check to see whether
343   *          any new password matches the current password or is in the user's
344   *          password history even if it would normally perform that check,
345   *          {@code Boolean.FALSE} if the server should check to see whether
346   *          any new password matches the current or previous password even if
347   *          it would normally not perform such a check, or {@code null} if the
348   *          password policy configuration should be used to determine whether
349   *          to ignore the password history.
350   */
351  @Nullable()
352  public Boolean getIgnorePasswordHistory()
353  {
354    return ignorePasswordHistory;
355  }
356
357
358
359  /**
360   * Specifies whether the password update behavior request control should
361   * override the server's normal behavior with regard to checking the password
362   * history for any new passwords included in the password update, and if so,
363   * what the overridden behavior should be.
364   * <BR><BR>
365   * Note that if the target user's password policy is not configured to
366   * maintain a password history, then there may not be any previous passwords
367   * to check.  In that case, overriding the behavior to check the password
368   * history will only compare the new password against the current password.
369   * <BR><BR>
370   * Also note that this setting only applies to the validation of the new
371   * password.  It will not affect the server's behavior with regard to storing
372   * the new or previous password in the password history.
373   * <BR><BR>
374   * Finally, password history validation can only be performed for new
375   * passwords that are not pre-encoded.  Pre-encoded passwords cannot be
376   * checked against password validators or the password history.
377   *
378   * @param  ignorePasswordHistory  Specifies whether the password update
379   *                                behavior request control should override the
380   *                                server's normal behavior with regard to
381   *                                checking the password history for any new
382   *                                passwords included in the password update,
383   *                                and if so, what the overridden behavior
384   *                                should be.  If this is {@code Boolean.TRUE},
385   *                                then the server will skip password history
386   *                                validation even if it would have normally
387   *                                performed it.  If this is
388   *                                {@code Boolean.FALSE}, then the server will
389   *                                perform password history validation even if
390   *                                it would have normally skipped it.  If this
391   *                                is {@code null}, then the server will use
392   *                                the password policy configuration to
393   *                                determine whether to perform password
394   *                                history validation.
395   */
396  public void setIgnorePasswordHistory(
397                   @Nullable final Boolean ignorePasswordHistory)
398  {
399    this.ignorePasswordHistory = ignorePasswordHistory;
400  }
401
402
403
404  /**
405   * Indicates whether the password update behavior request control should
406   * override the server's normal behavior with regard to checking the
407   * minimum password age, and if so, what the overridden behavior should be.
408   *
409   * @return  {@code Boolean.TRUE} if the server should accept the password
410   *          change even if it has been less than the configured minimum
411   *          password age since the password was last changed,
412   *          {@code Boolean.FALSE} if the server should reject the password
413   *          change if it has been less than teh configured minimum password
414   *          age, or {@code null} if the password policy configuration should
415   *          be used to determine the appropriate behavior.
416   */
417  @Nullable()
418  public Boolean getIgnoreMinimumPasswordAge()
419  {
420    return ignoreMinimumPasswordAge;
421  }
422
423
424
425  /**
426   * Specifies whether the password update behavior request control should
427   * override the server's normal behavior with regard to checking the
428   * minimum password age, and if so, what the overridden behavior should be.
429   * <BR><BR>
430   * Normally, if a minimum password age is configured, then it will apply only
431   * for self password changes but not for administrative resets.  With this
432   * value set to {@code Boolean.TRUE}, then the configured minimum password
433   * age will be ignored even for self changes.  With this value set to
434   * {@code Boolean.FALSE}, then the configured minimum password age will be
435   * enforced even for administrative resets.  In any case, this will only be
436   * used if the target user's password policy is configured with a nonzero
437   * minimum password age.
438   *
439   * @param  ignoreMinimumPasswordAge  Specifies whether the password update
440   *                                   behavior request control should override
441   *                                   the server's normal behavior with regard
442   *                                   to checking the minimum password age, and
443   *                                   if so, what the overridden behavior
444   *                                   should be.  If this is
445   *                                   {@code Boolean.TRUE}, then the minimum
446   *                                   password age will not be enforced, even
447   *                                   for self password changes.  If this is
448   *                                   {@code Boolean.FALSE}, then the minimum
449   *                                   password age will be enforced, even for
450   *                                   administrative resets.  If this is
451   *                                   {@code null}, then the server's default
452   *                                   behavior will be used so that the minimum
453   *                                   password age will be enforced for self
454   *                                   changes but not for administrative
455   *                                   resets.
456   */
457  public void setIgnoreMinimumPasswordAge(
458                   @Nullable final Boolean ignoreMinimumPasswordAge)
459  {
460    this.ignoreMinimumPasswordAge = ignoreMinimumPasswordAge;
461  }
462
463
464
465  /**
466   * Indicates whether the password update behavior request control should
467   * override the server's normal behavior with regard to selecting the password
468   * storage scheme to use to encode new password values, and if so, which
469   * password storage scheme should be used.
470   *
471   * @return  The name of the password storage scheme that should be used to
472   *          encode any new password values, or {@code null} if the target
473   *          user's password policy configuration should determine the
474   *          appropriate schemes for encoding new passwords.
475   */
476  @Nullable()
477  public String getPasswordStorageScheme()
478  {
479    return passwordStorageScheme;
480  }
481
482
483
484  /**
485   * Specifies whether the password update behavior request control should
486   * override the server's normal behavior with regard to selecting the password
487   * storage scheme to use to encode new password values, and if so, which
488   * password storage scheme should be used.
489   * <BR><BR>
490   * If a non-{@code null} password storage scheme name is provided, then it
491   * must be the prefix used in front of passwords encoded with that scheme,
492   * optionally including or omitting the curly braces.  The specified scheme
493   * must be enabled for use in the server but does not otherwise need to be
494   * associated with the target user's password policy.
495   *
496   * @param  passwordStorageScheme  The name of the password storage scheme that
497   *                                should be used to encode any new password
498   *                                values.  It may optionally be enclosed in
499   *                                curly braces.  It may be {@code null} if the
500   *                                password policy configuration should be used
501   *                                to determine which password storage schemes
502   *                                should be used to encode new passwords.
503   */
504  public void setPasswordStorageScheme(
505                   @Nullable final String passwordStorageScheme)
506  {
507    this.passwordStorageScheme = passwordStorageScheme;
508  }
509
510
511
512  /**
513   * Indicates whether the password update behavior request control should
514   * override the server's normal behavior with regard to requiring a password
515   * change, and if so, what that behavior should be.
516   *
517   * @return  {@code Boolean.TRUE} if the user will be required to change their
518   *          password before being allowed to perform any other operation,
519   *          {@code Boolean.FALSE} if the user will not be required to change
520   *          their password before being allowed to perform any other
521   *          operation, or {@code null} if the password policy configuration
522   *          should be used to control this behavior.
523   */
524  @Nullable()
525  public Boolean getMustChangePassword()
526  {
527    return mustChangePassword;
528  }
529
530
531
532  /**
533   * Specifies whether the password update behavior request control should
534   * override the server's normal behavior with regard to requiring a password
535   * change, and if so, what that behavior should be.
536   * <BR><BR>
537   * Note that the "must change password" behavior will only be enforced if the
538   * target user's password policy is configured with either
539   * {@code force-change-on-add} or {@code force-change-on-reset} set to
540   * {@code true}.  If both of those properties are set to {@code false}, then
541   * this method will have no effect.
542   * <BR><BR>
543   * Normally, if {@code force-change-on-reset} is {@code true}, then the server
544   * will put the user's account into a "must change password" state after an
545   * administrative password reset, but not after a self change.  If this
546   * method is called with a value of {@code Boolean.TRUE}, then the "must
547   * change password" flag will be set, even if the password update is a self
548   * change.  It this method is called with a value of {@code Boolean.FALSE},
549   * then the "must change password" flag will not be set even if the password
550   * update is an administrative change.  If this method is called with a value
551   * of {@code null}, then the server's normal logic will be used to determine
552   * whether to set the "must change password" flag.
553   *
554   * @param  mustChangePassword  Specifies whether the password update behavior
555   *                             request control should override the server's
556   *                             normal behavior with regard to requiring a
557   *                             password change, and if so, what that behavior
558   *                             should be.  If this is {@code Boolean.TRUE},
559   *                             then the user entry will be required to change
560   *                             their password after their next login even if
561   *                             this is a self change.  If this is
562   *                             {@code Boolean.FALSE}, then the user will not
563   *                             be required to change their password after the
564   *                             next login even if this is an administrative
565   *                             reset.  If this is {@code null}, then the
566   *                             server's normal logic will be used to make the
567   *                             determination.
568   */
569  public void setMustChangePassword(@Nullable final Boolean mustChangePassword)
570  {
571    this.mustChangePassword = mustChangePassword;
572  }
573
574
575
576  /**
577   * Retrieves a string representation of this password update behavior request
578   * control properties object.
579   *
580   * @return  A string representation of this password update behavior request
581   *          control properties object.
582   */
583  @Override()
584  @NotNull()
585  public String toString()
586  {
587    final StringBuilder buffer = new StringBuilder();
588    toString(buffer);
589    return buffer.toString();
590  }
591
592
593
594  /**
595   * Appends a string representation of this password update behavior request
596   * control properties object to the provided buffer.
597   *
598   * @param  buffer  The buffer to which the information should be appended.
599   */
600  public void toString(@NotNull final StringBuilder buffer)
601  {
602    buffer.append("PasswordUpdateBehaviorRequestControlProperties(");
603
604    boolean appended = appendNameValuePair(buffer, "isSelfChange", isSelfChange,
605         false);
606    appended = appendNameValuePair(buffer, "allowPreEncodedPassword",
607         allowPreEncodedPassword, appended);
608    appended = appendNameValuePair(buffer, "skipPasswordValidation",
609         skipPasswordValidation, appended);
610    appended = appendNameValuePair(buffer, "ignorePasswordHistory",
611         ignorePasswordHistory, appended);
612    appended = appendNameValuePair(buffer, "ignoreMinimumPasswordAge",
613         ignoreMinimumPasswordAge, appended);
614    appended = appendNameValuePair(buffer, "passwordStorageScheme",
615         passwordStorageScheme, appended);
616    appendNameValuePair(buffer, "mustChangePassword",
617         mustChangePassword, appended);
618
619    buffer.append(')');
620  }
621
622
623
624  /**
625   * Appends a name-value pair to the provided buffer, if appropriate.
626   *
627   * @param  buffer                The buffer to which the name-value pair
628   *                               should be appended.  It must not be
629   *                               {@code null}.
630   * @param  propertyName          The name for the property to consider
631   *                               appending.  It must not be {@code null}.
632   * @param  propertyValue         The value for the property to consider
633   *                               appending.  It may be {@code null} if the
634   *                               name-value pair should not be appended.  If
635   *                               it is non-{@code null}, then it must have a
636   *                               type of {@code Boolean} or {@code String}.
637   * @param  appendedPreviousPair  Indicates whether a previous name-value pair
638   *                               has already been appended to the buffer.  If
639   *                               the provided name-value pair should not be
640   *                               appended, then this will be returned.  If the
641   *                               provided name-value pair should be appended,
642   *                               then this will be used to indicate whether it
643   *                               should be preceded by a comma.
644   *
645   * @return  {@code true} if this or a previous name-value pair has been
646   *          appended to the buffer, or {@code false} if no name-value pair has
647   *          yet been appended to the buffer.
648   */
649  private static boolean appendNameValuePair(
650               @NotNull final StringBuilder buffer,
651               @NotNull final String propertyName,
652               @Nullable final Object propertyValue,
653               final boolean appendedPreviousPair)
654  {
655    if (propertyValue == null)
656    {
657      return appendedPreviousPair;
658    }
659
660    if (appendedPreviousPair)
661    {
662      buffer.append(", ");
663    }
664
665    buffer.append(propertyName);
666    buffer.append('=');
667
668    if (propertyValue instanceof Boolean)
669    {
670      buffer.append(((Boolean) propertyValue).booleanValue());
671    }
672    else
673    {
674      buffer.append('"');
675      buffer.append(propertyValue);
676      buffer.append('"');
677    }
678
679    return true;
680  }
681}