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