001/* 002 * CDDL HEADER START 003 * 004 * The contents of this file are subject to the terms of the 005 * Common Development and Distribution License, Version 1.0 only 006 * (the "License"). You may not use this file except in compliance 007 * with the License. 008 * 009 * You can obtain a copy of the license at legal-notices/CDDLv1_0.txt 010 * or http://forgerock.org/license/CDDLv1.0.html. 011 * See the License for the specific language governing permissions 012 * and limitations under the License. 013 * 014 * When distributing Covered Code, include this CDDL HEADER in each 015 * file and include the License file at legal-notices/CDDLv1_0.txt. 016 * If applicable, add the following below this CDDL HEADER, with the 017 * fields enclosed by brackets "[]" replaced with your own identifying 018 * information: 019 * Portions Copyright [yyyy] [name of copyright owner] 020 * 021 * CDDL HEADER END 022 * 023 * 024 * Copyright 2006-2009 Sun Microsystems, Inc. 025 * Portions Copyright 2014-2015 ForgeRock AS 026 */ 027package org.opends.server.controls; 028import org.forgerock.i18n.LocalizableMessage; 029 030 031import java.io.IOException; 032 033import org.forgerock.opendj.io.*; 034import org.opends.server.types.*; 035import org.forgerock.opendj.ldap.ResultCode; 036import org.forgerock.opendj.ldap.ByteString; 037import org.forgerock.i18n.slf4j.LocalizedLogger; 038import static org.opends.messages.ProtocolMessages.*; 039import static org.opends.server.util.ServerConstants.*; 040import static org.opends.server.util.StaticUtils.*; 041 042 043 044/** 045 * This class implements the account usable response control. This is a 046 * Sun-defined control with OID 1.3.6.1.4.1.42.2.27.9.5.8. The value of this 047 * control is composed according to the following BNF: 048 * <BR> 049 * <PRE> 050 * ACCOUNT_USABLE_RESPONSE ::= CHOICE { 051 * is_available [0] INTEGER, -- Seconds before expiration -- 052 * is_not_available [1] MORE_INFO } 053 * 054 * MORE_INFO ::= SEQUENCE { 055 * inactive [0] BOOLEAN DEFAULT FALSE, 056 * reset [1] BOOLEAN DEFAULT FALSE, 057 * expired [2] BOOLEAN DEFAULT_FALSE, 058 * remaining_grace [3] INTEGER OPTIONAL, 059 * seconds_before_unlock [4] INTEGER OPTIONAL } 060 * </PRE> 061 */ 062public class AccountUsableResponseControl 063 extends Control 064{ 065 /** 066 * ControlDecoder implementation to decode this control from a ByteString. 067 */ 068 private static final class Decoder 069 implements ControlDecoder<AccountUsableResponseControl> 070 { 071 /** {@inheritDoc} */ 072 public AccountUsableResponseControl decode(boolean isCritical, 073 ByteString value) 074 throws DirectoryException 075 { 076 if (value == null) 077 { 078 // The response control must always have a value. 079 LocalizableMessage message = ERR_ACCTUSABLERES_NO_CONTROL_VALUE.get(); 080 throw new DirectoryException(ResultCode.PROTOCOL_ERROR, message); 081 } 082 083 084 try 085 { 086 ASN1Reader reader = ASN1.getReader(value); 087 switch (reader.peekType()) 088 { 089 case TYPE_SECONDS_BEFORE_EXPIRATION: 090 int secondsBeforeExpiration = (int)reader.readInteger(); 091 return new AccountUsableResponseControl(isCritical, 092 secondsBeforeExpiration); 093 case TYPE_MORE_INFO: 094 boolean isInactive = false; 095 boolean isReset = false; 096 boolean isExpired = false; 097 boolean isLocked = false; 098 int remainingGraceLogins = -1; 099 int secondsBeforeUnlock = 0; 100 101 reader.readStartSequence(); 102 if(reader.hasNextElement() && 103 reader.peekType() == TYPE_INACTIVE) 104 { 105 isInactive = reader.readBoolean(); 106 } 107 if(reader.hasNextElement() && 108 reader.peekType() == TYPE_RESET) 109 { 110 isReset = reader.readBoolean(); 111 } 112 if(reader.hasNextElement() && 113 reader.peekType() == TYPE_EXPIRED) 114 { 115 isExpired = reader.readBoolean(); 116 } 117 if(reader.hasNextElement() && 118 reader.peekType() == TYPE_REMAINING_GRACE_LOGINS) 119 { 120 remainingGraceLogins = (int)reader.readInteger(); 121 } 122 if(reader.hasNextElement() && 123 reader.peekType() == TYPE_SECONDS_BEFORE_UNLOCK) 124 { 125 isLocked = true; 126 secondsBeforeUnlock = (int)reader.readInteger(); 127 } 128 reader.readEndSequence(); 129 130 return new AccountUsableResponseControl(isCritical, 131 isInactive, isReset, 132 isExpired, 133 remainingGraceLogins, 134 isLocked, 135 secondsBeforeUnlock); 136 137 default: 138 LocalizableMessage message = ERR_ACCTUSABLERES_UNKNOWN_VALUE_ELEMENT_TYPE.get( 139 byteToHex(reader.peekType())); 140 throw new DirectoryException(ResultCode.PROTOCOL_ERROR, message); 141 } 142 } 143 catch (DirectoryException de) 144 { 145 throw de; 146 } 147 catch (Exception e) 148 { 149 logger.traceException(e); 150 151 LocalizableMessage message = 152 ERR_ACCTUSABLERES_DECODE_ERROR.get(getExceptionMessage(e)); 153 throw new DirectoryException(ResultCode.PROTOCOL_ERROR, message); 154 } 155 } 156 157 public String getOID() 158 { 159 return OID_ACCOUNT_USABLE_CONTROL; 160 } 161 162 } 163 164 /** 165 * The Control Decoder that can be used to decode this control. 166 */ 167 public static final ControlDecoder<AccountUsableResponseControl> DECODER = 168 new Decoder(); 169 private static final LocalizedLogger logger = LocalizedLogger.getLoggerForThisClass(); 170 171 172 173 174 /** 175 * The BER type to use for the seconds before expiration when the account is 176 * available. 177 */ 178 public static final byte TYPE_SECONDS_BEFORE_EXPIRATION = (byte) 0x80; 179 180 181 182 /** 183 * The BER type to use for the MORE_INFO sequence when the account is not 184 * available. 185 */ 186 public static final byte TYPE_MORE_INFO = (byte) 0xA1; 187 188 189 190 /** 191 * The BER type to use for the MORE_INFO element that indicates that the 192 * account has been inactivated. 193 */ 194 public static final byte TYPE_INACTIVE = (byte) 0x80; 195 196 197 198 /** 199 * The BER type to use for the MORE_INFO element that indicates that the 200 * password has been administratively reset. 201 */ 202 public static final byte TYPE_RESET = (byte) 0x81; 203 204 205 206 /** 207 * The BER type to use for the MORE_INFO element that indicates that the 208 * user's password is expired. 209 */ 210 public static final byte TYPE_EXPIRED = (byte) 0x82; 211 212 213 214 /** 215 * The BER type to use for the MORE_INFO element that provides the number of 216 * remaining grace logins. 217 */ 218 public static final byte TYPE_REMAINING_GRACE_LOGINS = (byte) 0x83; 219 220 221 222 /** 223 * The BER type to use for the MORE_INFO element that indicates that the 224 * password has been administratively reset. 225 */ 226 public static final byte TYPE_SECONDS_BEFORE_UNLOCK = (byte) 0x84; 227 228 229 230 /** Indicates whether the user's account is usable. */ 231 private boolean isUsable; 232 233 /** Indicates whether the user's password is expired. */ 234 private boolean isExpired; 235 236 /** Indicates whether the user's account is inactive. */ 237 private boolean isInactive; 238 239 /** Indicates whether the user's account is currently locked. */ 240 private boolean isLocked; 241 242 /** 243 * Indicates whether the user's password has been reset and must be changed 244 * before anything else can be done. 245 */ 246 private boolean isReset; 247 248 /** The number of remaining grace logins, if available. */ 249 private int remainingGraceLogins; 250 251 /** 252 * The length of time in seconds before the user's password expires, if 253 * available. 254 */ 255 private int secondsBeforeExpiration; 256 257 /** The length of time before the user's account is unlocked, if available. */ 258 private int secondsBeforeUnlock; 259 260 261 262 /** 263 * Creates a new account usability response control that may be used to 264 * indicate that the account is available and provide the number of seconds 265 * until expiration. It will use the default OID and criticality. 266 * 267 * @param secondsBeforeExpiration The length of time in seconds until the 268 * user's password expires, or -1 if the 269 * user's password will not expire or the 270 * expiration time is unknown. 271 */ 272 public AccountUsableResponseControl(int secondsBeforeExpiration) 273 { 274 this(false, secondsBeforeExpiration); 275 } 276 277 /** 278 * Creates a new account usability response control that may be used to 279 * indicate that the account is available and provide the number of seconds 280 * until expiration. It will use the default OID and criticality. 281 * 282 * @param isCritical Indicates whether this control should be 283 * considered critical in processing the 284 * request. 285 * @param secondsBeforeExpiration The length of time in seconds until the 286 * user's password expires, or -1 if the 287 * user's password will not expire or the 288 * expiration time is unknown. 289 */ 290 public AccountUsableResponseControl(boolean isCritical, 291 int secondsBeforeExpiration) 292 { 293 super(OID_ACCOUNT_USABLE_CONTROL, isCritical); 294 295 296 this.secondsBeforeExpiration = secondsBeforeExpiration; 297 298 isUsable = true; 299 isInactive = false; 300 isReset = false; 301 isExpired = false; 302 remainingGraceLogins = -1; 303 isLocked = false; 304 secondsBeforeUnlock = 0; 305 } 306 307 308 309 /** 310 * Creates a new account usability response control that may be used to 311 * indicate that the account is not available and provide information about 312 * the underlying reason. It will use the default OID and criticality. 313 * 314 * @param isCritical Indicates whether this control should be 315 * considered critical in processing the 316 * request. 317 * @param isInactive Indicates whether the user's account has been 318 * inactivated by an administrator. 319 * @param isReset Indicates whether the user's password has 320 * been reset by an administrator. 321 * @param isExpired Indicates whether the user's password is 322 * expired. 323 * @param remainingGraceLogins The number of grace logins remaining. A 324 * value of zero indicates that there are none 325 * remaining. A value of -1 indicates that 326 * grace login functionality is not enabled. 327 * @param isLocked Indicates whether the user's account is 328 * currently locked out. 329 * @param secondsBeforeUnlock The length of time in seconds until the 330 * account is unlocked. A value of -1 indicates 331 * that the account will not be automatically 332 * unlocked and must be reset by an 333 * administrator. 334 */ 335 public AccountUsableResponseControl(boolean isCritical, boolean isInactive, 336 boolean isReset, 337 boolean isExpired, 338 int remainingGraceLogins, 339 boolean isLocked, int secondsBeforeUnlock) 340 { 341 super(OID_ACCOUNT_USABLE_CONTROL, isCritical); 342 343 344 this.isInactive = isInactive; 345 this.isReset = isReset; 346 this.isExpired = isExpired; 347 this.remainingGraceLogins = remainingGraceLogins; 348 this.isLocked = isLocked; 349 this.secondsBeforeUnlock = secondsBeforeUnlock; 350 351 isUsable = false; 352 secondsBeforeExpiration = -1; 353 } 354 355 /** 356 * Creates a new account usability response control that may be used to 357 * indicate that the account is not available and provide information about 358 * the underlying reason. It will use the default OID and criticality. 359 * 360 * @param isInactive Indicates whether the user's account has been 361 * inactivated by an administrator. 362 * @param isReset Indicates whether the user's password has 363 * been reset by an administrator. 364 * @param isExpired Indicates whether the user's password is 365 * expired. 366 * @param remainingGraceLogins The number of grace logins remaining. A 367 * value of zero indicates that there are none 368 * remaining. A value of -1 indicates that 369 * grace login functionality is not enabled. 370 * @param isLocked Indicates whether the user's account is 371 * currently locked out. 372 * @param secondsBeforeUnlock The length of time in seconds until the 373 * account is unlocked. A value of -1 indicates 374 * that the account will not be automatically 375 * unlocked and must be reset by an 376 * administrator. 377 */ 378 public AccountUsableResponseControl(boolean isInactive, boolean isReset, 379 boolean isExpired, 380 int remainingGraceLogins, 381 boolean isLocked, int secondsBeforeUnlock) 382 { 383 this(false, isInactive, isReset, isExpired, remainingGraceLogins, 384 isLocked, secondsBeforeUnlock); 385 } 386 387 /** 388 * Writes this control's value to an ASN.1 writer. The value (if any) must be 389 * written as an ASN1OctetString. 390 * 391 * @param writer The ASN.1 output stream to write to. 392 * @throws IOException If a problem occurs while writing to the stream. 393 */ 394 public void writeValue(ASN1Writer writer) throws IOException { 395 writer.writeStartSequence(ASN1.UNIVERSAL_OCTET_STRING_TYPE); 396 397 if(isUsable) 398 { 399 writer.writeInteger(TYPE_SECONDS_BEFORE_EXPIRATION, 400 secondsBeforeExpiration); 401 } 402 else 403 { 404 writer.writeStartSequence(TYPE_MORE_INFO); 405 if (isInactive) 406 { 407 writer.writeBoolean(TYPE_INACTIVE, true); 408 } 409 410 if (isReset) 411 { 412 writer.writeBoolean(TYPE_RESET, true); 413 } 414 415 if (isExpired) 416 { 417 writer.writeBoolean(TYPE_EXPIRED, true); 418 419 if (remainingGraceLogins >= 0) 420 { 421 writer.writeInteger(TYPE_REMAINING_GRACE_LOGINS, 422 remainingGraceLogins); 423 } 424 } 425 426 if (isLocked) 427 { 428 writer.writeInteger(TYPE_SECONDS_BEFORE_UNLOCK, 429 secondsBeforeUnlock); 430 } 431 writer.writeEndSequence(); 432 } 433 434 writer.writeEndSequence(); 435 } 436 437 438 439 440 /** 441 * Indicates whether the associated user account is available for use. 442 * 443 * @return <CODE>true</CODE> if the associated user account is available, or 444 * <CODE>false</CODE> if not. 445 */ 446 public boolean isUsable() 447 { 448 return isUsable; 449 } 450 451 452 453 /** 454 * Retrieves the length of time in seconds before the user's password expires. 455 * This value is unreliable if the account is not available. 456 * 457 * @return The length of time in seconds before the user's password expires, 458 * or -1 if it is unknown or password expiration is not enabled for 459 * the user. 460 */ 461 public int getSecondsBeforeExpiration() 462 { 463 return secondsBeforeExpiration; 464 } 465 466 467 468 /** 469 * Indicates whether the user's account has been inactivated by an 470 * administrator. 471 * 472 * @return <CODE>true</CODE> if the user's account has been inactivated by 473 * an administrator, or <CODE>false</CODE> if not. 474 */ 475 public boolean isInactive() 476 { 477 return isInactive; 478 } 479 480 481 482 /** 483 * Indicates whether the user's password has been administratively reset and 484 * the user must change that password before any other operations will be 485 * allowed. 486 * 487 * @return <CODE>true</CODE> if the user's password has been administratively 488 * reset, or <CODE>false</CODE> if not. 489 */ 490 public boolean isReset() 491 { 492 return isReset; 493 } 494 495 496 497 /** 498 * Indicates whether the user's password is expired. 499 * 500 * @return <CODE>true</CODE> if the user's password is expired, or 501 * <CODE>false</CODE> if not. 502 */ 503 public boolean isExpired() 504 { 505 return isExpired; 506 } 507 508 509 510 /** 511 * Retrieves the number of remaining grace logins for the user. This value is 512 * unreliable if the user's password is not expired. 513 * 514 * @return The number of remaining grace logins for the user, or -1 if the 515 * grace logins feature is not enabled for the user. 516 */ 517 public int getRemainingGraceLogins() 518 { 519 return remainingGraceLogins; 520 } 521 522 523 524 /** 525 * Indicates whether the user's account is locked for some reason. 526 * 527 * @return <CODE>true</CODE> if the user's account is locked, or 528 * <CODE>false</CODE> if it is not. 529 */ 530 public boolean isLocked() 531 { 532 return isLocked; 533 } 534 535 536 537 /** 538 * Retrieves the length of time in seconds before the user's account is 539 * automatically unlocked. This value is unreliable is the user's account is 540 * not locked. 541 * 542 * @return The length of time in seconds before the user's account is 543 * automatically unlocked, or -1 if it requires administrative action 544 * to unlock the account. 545 */ 546 public int getSecondsBeforeUnlock() 547 { 548 return secondsBeforeUnlock; 549 } 550 551 552 553 /** 554 * Appends a string representation of this password policy response control to 555 * the provided buffer. 556 * 557 * @param buffer The buffer to which the information should be appended. 558 */ 559 public void toString(StringBuilder buffer) 560 { 561 buffer.append("AccountUsableResponseControl(isUsable="); 562 buffer.append(isUsable); 563 564 if (isUsable) 565 { 566 buffer.append(",secondsBeforeExpiration="); 567 buffer.append(secondsBeforeExpiration); 568 } 569 else 570 { 571 buffer.append(",isInactive="); 572 buffer.append(isInactive); 573 buffer.append(",isReset="); 574 buffer.append(isReset); 575 buffer.append(",isExpired="); 576 buffer.append(isExpired); 577 buffer.append(",remainingGraceLogins="); 578 buffer.append(remainingGraceLogins); 579 buffer.append(",isLocked="); 580 buffer.append(isLocked); 581 buffer.append(",secondsBeforeUnlock="); 582 buffer.append(secondsBeforeUnlock); 583 } 584 585 buffer.append(")"); 586 } 587} 588