001/* 002 * Copyright 2015-2024 Ping Identity Corporation 003 * All Rights Reserved. 004 */ 005/* 006 * Copyright 2015-2024 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-2024 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 java.io.Serializable; 041import java.util.StringTokenizer; 042 043import com.unboundid.ldap.sdk.LDAPException; 044import com.unboundid.ldap.sdk.ResultCode; 045import com.unboundid.util.Debug; 046import com.unboundid.util.NotMutable; 047import com.unboundid.util.NotNull; 048import com.unboundid.util.Nullable; 049import com.unboundid.util.StaticUtils; 050import com.unboundid.util.ThreadSafety; 051import com.unboundid.util.ThreadSafetyLevel; 052import com.unboundid.util.Validator; 053 054import static com.unboundid.ldap.sdk.unboundidds.extensions.ExtOpMessages.*; 055 056 057 058/** 059 * This class defines a data structure that will provide information about 060 * notices pertaining to a user's password policy state (items that might be 061 * of interest, but do not necessarily represent a current or imminent problem 062 * with the account). It includes a number of predefined notice types, but also 063 * allows for the possibility of additional notice types that have not been 064 * defined. 065 * <BR> 066 * <BLOCKQUOTE> 067 * <B>NOTE:</B> This class, and other classes within the 068 * {@code com.unboundid.ldap.sdk.unboundidds} package structure, are only 069 * supported for use against Ping Identity, UnboundID, and 070 * Nokia/Alcatel-Lucent 8661 server products. These classes provide support 071 * for proprietary functionality or for external specifications that are not 072 * considered stable or mature enough to be guaranteed to work in an 073 * interoperable way with other types of LDAP servers. 074 * </BLOCKQUOTE> 075 */ 076@NotMutable() 077@ThreadSafety(level=ThreadSafetyLevel.COMPLETELY_THREADSAFE) 078public final class PasswordPolicyStateAccountUsabilityNotice 079 implements Serializable 080{ 081 /** 082 * The numeric value for the notice type that indicates the user has a valid 083 * outstanding retired password. 084 */ 085 public static final int NOTICE_TYPE_OUTSTANDING_RETIRED_PASSWORD = 1; 086 087 088 089 /** 090 * The name for the notice type that indicates the user user has a valid 091 * outstanding retired password. 092 */ 093 @NotNull public static final String NOTICE_NAME_OUTSTANDING_RETIRED_PASSWORD = 094 "outstanding-retired-password"; 095 096 097 098 /** 099 * The numeric value for the notice type that indicates the user has a valid 100 * outstanding one-time password. 101 */ 102 public static final int NOTICE_TYPE_OUTSTANDING_ONE_TIME_PASSWORD = 2; 103 104 105 106 /** 107 * The name for the notice type that indicates the user has a valid 108 * outstanding one-time password. 109 */ 110 @NotNull public static final String 111 NOTICE_NAME_OUTSTANDING_ONE_TIME_PASSWORD = 112 "outstanding-one-time-password"; 113 114 115 116 /** 117 * The numeric value for the notice type that indicates the user has a valid 118 * outstanding password reset token. 119 */ 120 public static final int NOTICE_TYPE_OUTSTANDING_PASSWORD_RESET_TOKEN = 3; 121 122 123 124 /** 125 * The name for the notice type that indicates the user has a valid 126 * outstanding password reset token that will expire in the near future. 127 */ 128 @NotNull public static final String 129 NOTICE_NAME_OUTSTANDING_PASSWORD_RESET_TOKEN = 130 "outstanding-password-reset-token"; 131 132 133 134 /** 135 * The numeric value for the notice type that indicates the user is not 136 * currently allowed to change his/her password because they are within the 137 * minimum password age. 138 */ 139 public static final int NOTICE_TYPE_IN_MINIMUM_PASSWORD_AGE = 4; 140 141 142 143 /** 144 * The name for the notice type that indicates the user is not currently 145 * allowed to change his/her password because they are within the minimum 146 * password age. 147 */ 148 @NotNull public static final String NOTICE_NAME_IN_MINIMUM_PASSWORD_AGE = 149 "in-minimum-password-age"; 150 151 152 153 /** 154 * The numeric value for the notice type that indicates that the user does not 155 * have a static password. 156 */ 157 public static final int NOTICE_TYPE_NO_STATIC_PASSWORD = 5; 158 159 160 161 /** 162 * The name for the notice type that indicates that the user does not have a 163 * static password. 164 */ 165 @NotNull public static final String NOTICE_NAME_NO_STATIC_PASSWORD = 166 "no-static-password"; 167 168 169 170 /** 171 * The numeric value for the notice type that indicates that although the 172 * user's account should be locked as a result of too many outstanding 173 * failed authentication attempts, their password policy is configured with a 174 * failure lockout action that will not prevent them from authenticating, and 175 * should not otherwise have an effect on the usability of their account. 176 */ 177 public static final int NOTICE_TYPE_TOO_MANY_OUTSTANDING_BIND_FAILURES = 6; 178 179 180 181 /** 182 * The name for the warning type that indicates that although the user's 183 * account should be locked as a result of too many outstanding failed 184 * authentication attempts, their password policy is configured with a failure 185 * lockout action that will not prevent them from authenticating, and should 186 * not otherwise have an effect on the usability of their account. 187 */ 188 @NotNull public static final String 189 NOTICE_NAME_TOO_MANY_OUTSTANDING_BIND_FAILURES = 190 "too-many-outstanding-bind-failures"; 191 192 193 194 /** 195 * The serial version UID for this serializable class. 196 */ 197 private static final long serialVersionUID = 6147730018701385799L; 198 199 200 201 // The integer value for this account usability notice. 202 private final int intValue; 203 204 // A human-readable message that provides specific details about this account 205 // usability notice. 206 @Nullable private final String message; 207 208 // The name for this account usability notice. 209 @NotNull private final String name; 210 211 // The encoded string representation for this account usability notice. 212 @NotNull private final String stringRepresentation; 213 214 215 216 /** 217 * Creates a new account usability notice with the provided information. 218 * 219 * @param intValue The integer value for this account usability notice. 220 * @param name The name for this account usability notice. It must not 221 * be {@code null}. 222 * @param message A human-readable message that provides specific details 223 * about this account usability notice. It may be 224 * {@code null} if no message is available. 225 */ 226 public PasswordPolicyStateAccountUsabilityNotice(final int intValue, 227 @NotNull final String name, 228 @Nullable final String message) 229 { 230 Validator.ensureNotNull(name); 231 232 this.intValue = intValue; 233 this.name = name; 234 this.message = message; 235 236 final StringBuilder buffer = new StringBuilder(); 237 buffer.append("code="); 238 buffer.append(intValue); 239 buffer.append("\tname="); 240 buffer.append(name); 241 242 if (message != null) 243 { 244 buffer.append("\tmessage="); 245 buffer.append(message); 246 } 247 248 stringRepresentation = buffer.toString(); 249 } 250 251 252 253 /** 254 * Creates a new account usability notice that is decoded from the provided 255 * string representation. 256 * 257 * @param stringRepresentation The string representation of the account 258 * usability notice to decode. It must not be 259 * {@code null}. 260 * 261 * @throws LDAPException If the provided string cannot be decoded as a valid 262 * account usability notice. 263 */ 264 public PasswordPolicyStateAccountUsabilityNotice( 265 @NotNull final String stringRepresentation) 266 throws LDAPException 267 { 268 this.stringRepresentation = stringRepresentation; 269 270 try 271 { 272 Integer i = null; 273 String n = null; 274 String m = null; 275 276 final StringTokenizer tokenizer = 277 new StringTokenizer(stringRepresentation, "\t"); 278 while (tokenizer.hasMoreTokens()) 279 { 280 final String token = tokenizer.nextToken(); 281 final int equalPos = token.indexOf('='); 282 final String fieldName = token.substring(0, equalPos); 283 final String fieldValue = token.substring(equalPos+1); 284 if (fieldName.equals("code")) 285 { 286 i = Integer.valueOf(fieldValue); 287 } 288 else if (fieldName.equals("name")) 289 { 290 n = fieldValue; 291 } 292 else if (fieldName.equals("message")) 293 { 294 m = fieldValue; 295 } 296 } 297 298 if (i == null) 299 { 300 throw new LDAPException(ResultCode.DECODING_ERROR, 301 ERR_PWP_STATE_ACCOUNT_USABILITY_NOTICE_CANNOT_DECODE.get( 302 stringRepresentation, 303 ERR_PWP_STATE_ACCOUNT_USABILITY_NOTICE_NO_CODE.get())); 304 } 305 306 if (n == null) 307 { 308 throw new LDAPException(ResultCode.DECODING_ERROR, 309 ERR_PWP_STATE_ACCOUNT_USABILITY_NOTICE_CANNOT_DECODE.get( 310 stringRepresentation, 311 ERR_PWP_STATE_ACCOUNT_USABILITY_NOTICE_NO_NAME.get())); 312 } 313 314 intValue = i; 315 name = n; 316 message = m; 317 } 318 catch (final LDAPException le) 319 { 320 Debug.debugException(le); 321 322 throw le; 323 } 324 catch (final Exception e) 325 { 326 Debug.debugException(e); 327 328 throw new LDAPException(ResultCode.DECODING_ERROR, 329 ERR_PWP_STATE_ACCOUNT_USABILITY_NOTICE_CANNOT_DECODE.get( 330 stringRepresentation, StaticUtils.getExceptionMessage(e)), 331 e); 332 } 333 } 334 335 336 337 /** 338 * Retrieves the integer value for this account usability notice. 339 * 340 * @return The integer value for this account usability notice. 341 */ 342 public int getIntValue() 343 { 344 return intValue; 345 } 346 347 348 349 /** 350 * Retrieves the name for this account usability notice. 351 * 352 * @return The name for this account usability notice. 353 */ 354 @NotNull() 355 public String getName() 356 { 357 return name; 358 } 359 360 361 362 /** 363 * Retrieves a human-readable message that provides specific details about 364 * this account usability notice. 365 * 366 * @return A human-readable message that provides specific details about this 367 * account usability notice, or {@code null} if no message is 368 * available. 369 */ 370 @Nullable() 371 public String getMessage() 372 { 373 return message; 374 } 375 376 377 378 /** 379 * Retrieves a string representation of this account usability notice. 380 * 381 * @return A string representation of this account usability notice. 382 */ 383 @Override() 384 @NotNull() 385 public String toString() 386 { 387 return stringRepresentation; 388 } 389}