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