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