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 010 * trunk/opends/resource/legal-notices/OpenDS.LICENSE 011 * or https://OpenDS.dev.java.net/OpenDS.LICENSE. 012 * See the License for the specific language governing permissions 013 * and limitations under the License. 014 * 015 * When distributing Covered Code, include this CDDL HEADER in each 016 * file and include the License file at 017 * trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable, 018 * add the following below this CDDL HEADER, with the fields enclosed 019 * by brackets "[]" replaced with your own identifying information: 020 * Portions Copyright [yyyy] [name of copyright owner] 021 * 022 * CDDL HEADER END 023 * 024 * 025 * Copyright 2006-2008 Sun Microsystems, Inc. 026 */ 027 package org.opends.server.extensions; 028 029 030 031 import java.util.ArrayList; 032 import java.util.LinkedHashSet; 033 import java.util.List; 034 035 import org.opends.messages.Message; 036 import org.opends.server.admin.std.server. 037 PasswordPolicyStateExtendedOperationHandlerCfg; 038 import org.opends.server.api.ClientConnection; 039 import org.opends.server.api.ExtendedOperationHandler; 040 import org.opends.server.config.ConfigException; 041 import org.opends.server.core.DirectoryServer; 042 import org.opends.server.core.ExtendedOperation; 043 import org.opends.server.core.ModifyOperation; 044 import org.opends.server.core.PasswordPolicy; 045 import org.opends.server.core.PasswordPolicyState; 046 import org.opends.server.loggers.debug.DebugTracer; 047 import org.opends.server.protocols.asn1.ASN1Element; 048 import org.opends.server.protocols.asn1.ASN1Enumerated; 049 import org.opends.server.protocols.asn1.ASN1OctetString; 050 import org.opends.server.protocols.asn1.ASN1Sequence; 051 import org.opends.server.protocols.internal.InternalClientConnection; 052 import org.opends.server.protocols.internal.InternalSearchOperation; 053 import org.opends.server.schema.GeneralizedTimeSyntax; 054 import org.opends.server.types.DebugLogLevel; 055 import org.opends.server.types.DereferencePolicy; 056 import org.opends.server.types.DirectoryException; 057 import org.opends.server.types.DN; 058 import org.opends.server.types.Entry; 059 import org.opends.server.types.InitializationException; 060 import org.opends.server.types.Modification; 061 import org.opends.server.types.Privilege; 062 import org.opends.server.types.ResultCode; 063 import org.opends.server.types.SearchFilter; 064 import org.opends.server.types.SearchResultEntry; 065 import org.opends.server.types.SearchScope; 066 067 import static org.opends.messages.ExtensionMessages.*; 068 import static org.opends.server.loggers.debug.DebugLogger.*; 069 import static org.opends.server.util.ServerConstants.*; 070 import static org.opends.server.util.StaticUtils.*; 071 072 073 074 /** 075 * This class implements an LDAP extended operation that can be used to query 076 * and update elements of the Directory Server password policy state for a given 077 * user. The ASN.1 definition for the value of the extended request is: 078 * <BR> 079 * <PRE> 080 * PasswordPolicyStateValue ::= SEQUENCE { 081 * targetUser LDAPDN 082 * operations SEQUENCE OF PasswordPolicyStateOperation OPTIONAL } 083 * 084 * PasswordPolicyStateOperation ::= SEQUENCE { 085 * opType ENUMERATED { 086 * getPasswordPolicyDN (0), 087 * getAccountDisabledState (1), 088 * setAccountDisabledState (2), 089 * clearAccountDisabledState (3), 090 * getAccountExpirationTime (4), 091 * setAccountExpirationTime (5), 092 * clearAccountExpirationTime (6), 093 * getSecondsUntilAccountExpiration (7), 094 * getPasswordChangedTime (8), 095 * setPasswordChangedTime (9), 096 * clearPasswordChangedTime (10), 097 * getPasswordExpirationWarnedTime (11), 098 * setPasswordExpirationWarnedTime (12), 099 * clearPasswordExpirationWarnedTime (13), 100 * getSecondsUntilPasswordExpiration (14), 101 * getSecondsUntilPasswordExpirationWarning (15), 102 * getAuthenticationFailureTimes (16), 103 * addAuthenticationFailureTime (17), 104 * setAuthenticationFailureTimes (18), 105 * clearAuthenticationFailureTimes (19), 106 * getSecondsUntilAuthenticationFailureUnlock (20), 107 * getRemainingAuthenticationFailureCount (21), 108 * getLastLoginTime (22), 109 * setLastLoginTime (23), 110 * clearLastLoginTime (24), 111 * getSecondsUntilIdleLockout (25), 112 * getPasswordResetState (26), 113 * setPasswordResetState (27), 114 * clearPasswordResetState (28), 115 * getSecondsUntilPasswordResetLockout (29), 116 * getGraceLoginUseTimes (30), 117 * addGraceLoginUseTime (31), 118 * setGraceLoginUseTimes (32), 119 * clearGraceLoginUseTimes (33), 120 * getRemainingGraceLoginCount (34), 121 * getPasswordChangedByRequiredTime (35), 122 * setPasswordChangedByRequiredTime (36), 123 * clearPasswordChangedByRequiredTime (37), 124 * getSecondsUntilRequiredChangeTime (38), 125 * getPasswordHistory (39), 126 * clearPasswordHistory (40), 127 * ... }, 128 * opValues SEQUENCE OF OCTET STRING OPTIONAL } 129 * </PRE> 130 * <BR> 131 * Both the request and response values use the same encoded form, and they both 132 * use the same OID of "1.3.6.1.4.1.26027.1.6.1". The response value will only 133 * include get* elements. If the request did not include any operations, then 134 * the response will include all get* elements; otherwise, the response will 135 * only include the get* elements that correspond to the state fields referenced 136 * in the request (regardless of whether that operation was included in a get*, 137 * set*, add*, remove*, or clear* operation). 138 */ 139 public class PasswordPolicyStateExtendedOperation 140 extends ExtendedOperationHandler< 141 PasswordPolicyStateExtendedOperationHandlerCfg> 142 { 143 /** 144 * The tracer object for the debug logger. 145 */ 146 private static final DebugTracer TRACER = getTracer(); 147 148 149 150 /** 151 * The enumerated value for the getPasswordPolicyDN operation. 152 */ 153 public static final int OP_GET_PASSWORD_POLICY_DN = 0; 154 155 156 157 /** 158 * The enumerated value for the getAccountDisabledState operation. 159 */ 160 public static final int OP_GET_ACCOUNT_DISABLED_STATE = 1; 161 162 163 164 /** 165 * The enumerated value for the setAccountDisabledState operation. 166 */ 167 public static final int OP_SET_ACCOUNT_DISABLED_STATE = 2; 168 169 170 171 /** 172 * The enumerated value for the clearAccountDisabledState operation. 173 */ 174 public static final int OP_CLEAR_ACCOUNT_DISABLED_STATE = 3; 175 176 177 178 /** 179 * The enumerated value for the getAccountExpirationTime operation. 180 */ 181 public static final int OP_GET_ACCOUNT_EXPIRATION_TIME = 4; 182 183 184 185 /** 186 * The enumerated value for the setAccountExpirationTime operation. 187 */ 188 public static final int OP_SET_ACCOUNT_EXPIRATION_TIME = 5; 189 190 191 192 /** 193 * The enumerated value for the clearAccountExpirationTime operation. 194 */ 195 public static final int OP_CLEAR_ACCOUNT_EXPIRATION_TIME = 6; 196 197 198 199 /** 200 * The enumerated value for the getSecondsUntilAccountExpiration operation. 201 */ 202 public static final int OP_GET_SECONDS_UNTIL_ACCOUNT_EXPIRATION = 7; 203 204 205 206 /** 207 * The enumerated value for the getPasswordChangedTime operation. 208 */ 209 public static final int OP_GET_PASSWORD_CHANGED_TIME = 8; 210 211 212 213 /** 214 * The enumerated value for the setPasswordChangedTime operation. 215 */ 216 public static final int OP_SET_PASSWORD_CHANGED_TIME = 9; 217 218 219 220 /** 221 * The enumerated value for the clearPasswordChangedTime operation. 222 */ 223 public static final int OP_CLEAR_PASSWORD_CHANGED_TIME = 10; 224 225 226 227 /** 228 * The enumerated value for the getPasswordExpirationWarnedTime operation. 229 */ 230 public static final int OP_GET_PASSWORD_EXPIRATION_WARNED_TIME = 11; 231 232 233 234 /** 235 * The enumerated value for the setPasswordExpirationWarnedTime operation. 236 */ 237 public static final int OP_SET_PASSWORD_EXPIRATION_WARNED_TIME = 12; 238 239 240 241 /** 242 * The enumerated value for the clearPasswordExpirationWarnedTime operation. 243 */ 244 public static final int OP_CLEAR_PASSWORD_EXPIRATION_WARNED_TIME = 13; 245 246 247 248 /** 249 * The enumerated value for the getSecondsUntilPasswordExpiration operation. 250 */ 251 public static final int OP_GET_SECONDS_UNTIL_PASSWORD_EXPIRATION = 14; 252 253 254 255 /** 256 * The enumerated value for the getSecondsUntilPasswordExpirationWarning 257 * operation. 258 */ 259 public static final int OP_GET_SECONDS_UNTIL_PASSWORD_EXPIRATION_WARNING = 15; 260 261 262 263 /** 264 * The enumerated value for the getAuthenticationFailureTimes operation. 265 */ 266 public static final int OP_GET_AUTHENTICATION_FAILURE_TIMES = 16; 267 268 269 270 /** 271 * The enumerated value for the addAuthenticationFailureTime operation. 272 */ 273 public static final int OP_ADD_AUTHENTICATION_FAILURE_TIME = 17; 274 275 276 277 /** 278 * The enumerated value for the setAuthenticationFailureTimes operation. 279 */ 280 public static final int OP_SET_AUTHENTICATION_FAILURE_TIMES = 18; 281 282 283 284 /** 285 * The enumerated value for the clearAuthenticationFailureTimes operation. 286 */ 287 public static final int OP_CLEAR_AUTHENTICATION_FAILURE_TIMES = 19; 288 289 290 291 /** 292 * The enumerated value for the getSecondsUntilAuthenticationFailureUnlock 293 * operation. 294 */ 295 public static final int OP_GET_SECONDS_UNTIL_AUTHENTICATION_FAILURE_UNLOCK = 296 20; 297 298 299 300 /** 301 * The enumerated value for the getRemainingAuthenticationFailureCount 302 * operation. 303 */ 304 public static final int OP_GET_REMAINING_AUTHENTICATION_FAILURE_COUNT = 21; 305 306 307 308 /** 309 * The enumerated value for the getLastLoginTime operation. 310 */ 311 public static final int OP_GET_LAST_LOGIN_TIME = 22; 312 313 314 315 /** 316 * The enumerated value for the setLastLoginTime operation. 317 */ 318 public static final int OP_SET_LAST_LOGIN_TIME = 23; 319 320 321 322 /** 323 * The enumerated value for the clearLastLoginTime operation. 324 */ 325 public static final int OP_CLEAR_LAST_LOGIN_TIME = 24; 326 327 328 329 /** 330 * The enumerated value for the getSecondsUntilIdleLockout operation. 331 */ 332 public static final int OP_GET_SECONDS_UNTIL_IDLE_LOCKOUT = 25; 333 334 335 336 /** 337 * The enumerated value for the getPasswordResetState operation. 338 */ 339 public static final int OP_GET_PASSWORD_RESET_STATE = 26; 340 341 342 343 /** 344 * The enumerated value for the setPasswordResetState operation. 345 */ 346 public static final int OP_SET_PASSWORD_RESET_STATE = 27; 347 348 349 350 /** 351 * The enumerated value for the clearPasswordResetState operation. 352 */ 353 public static final int OP_CLEAR_PASSWORD_RESET_STATE = 28; 354 355 356 357 /** 358 * The enumerated value for the getSecondsUntilPasswordResetLockout operation. 359 */ 360 public static final int OP_GET_SECONDS_UNTIL_PASSWORD_RESET_LOCKOUT = 29; 361 362 363 364 /** 365 * The enumerated value for the getGraceLoginUseTimes operation. 366 */ 367 public static final int OP_GET_GRACE_LOGIN_USE_TIMES = 30; 368 369 370 371 /** 372 * The enumerated value for the addGraceLoginUseTime operation. 373 */ 374 public static final int OP_ADD_GRACE_LOGIN_USE_TIME = 31; 375 376 377 378 /** 379 * The enumerated value for the setGraceLoginUseTimes operation. 380 */ 381 public static final int OP_SET_GRACE_LOGIN_USE_TIMES = 32; 382 383 384 385 /** 386 * The enumerated value for the clearGraceLoginUseTimes operation. 387 */ 388 public static final int OP_CLEAR_GRACE_LOGIN_USE_TIMES = 33; 389 390 391 392 /** 393 * The enumerated value for the getRemainingGraceLoginCount operation. 394 */ 395 public static final int OP_GET_REMAINING_GRACE_LOGIN_COUNT = 34; 396 397 398 399 /** 400 * The enumerated value for the getPasswordChangedByRequiredTime operation. 401 */ 402 public static final int OP_GET_PASSWORD_CHANGED_BY_REQUIRED_TIME = 35; 403 404 405 406 /** 407 * The enumerated value for the setPasswordChangedByRequiredTime operation. 408 */ 409 public static final int OP_SET_PASSWORD_CHANGED_BY_REQUIRED_TIME = 36; 410 411 412 413 /** 414 * The enumerated value for the clearPasswordChangedByRequiredTime operation. 415 */ 416 public static final int OP_CLEAR_PASSWORD_CHANGED_BY_REQUIRED_TIME = 37; 417 418 419 420 /** 421 * The enumerated value for the getSecondsUntilRequiredChangeTime operation. 422 */ 423 public static final int OP_GET_SECONDS_UNTIL_REQUIRED_CHANGE_TIME = 38; 424 425 426 427 /** 428 * The enumerated value for the getPasswordHistory operation. 429 */ 430 public static final int OP_GET_PASSWORD_HISTORY = 39; 431 432 433 434 /** 435 * The enumerated value for the clearPasswordHistory operation. 436 */ 437 public static final int OP_CLEAR_PASSWORD_HISTORY = 40; 438 439 440 441 // The set of attributes to request when retrieving a user's entry. 442 private LinkedHashSet<String> requestAttributes; 443 444 // The search filter that will be used to retrieve user entries. 445 private SearchFilter userFilter; 446 447 448 449 /** 450 * Create an instance of this password policy state extended operation. All 451 * initialization should be performed in the 452 * {@code initializeExtendedOperationHandler} method. 453 */ 454 public PasswordPolicyStateExtendedOperation() 455 { 456 super(); 457 } 458 459 460 /** 461 * Initializes this extended operation handler based on the information in the 462 * provided configuration entry. It should also register itself with the 463 * Directory Server for the particular kinds of extended operations that it 464 * will process. 465 * 466 * @param config The configuration that contains the information 467 * to use to initialize this extended operation handler. 468 * 469 * @throws ConfigException If an unrecoverable problem arises in the 470 * process of performing the initialization. 471 * 472 * @throws InitializationException If a problem occurs during initialization 473 * that is not related to the server 474 * configuration. 475 */ 476 public void initializeExtendedOperationHandler( 477 PasswordPolicyStateExtendedOperationHandlerCfg config) 478 throws ConfigException, InitializationException 479 { 480 // Construct the filter that will be used to retrieve user entries. 481 try 482 { 483 userFilter = SearchFilter.createFilterFromString("(objectClass=*)"); 484 } 485 catch (Exception e) 486 { 487 // This should never happen. 488 if (debugEnabled()) 489 { 490 TRACER.debugCaught(DebugLogLevel.ERROR, e); 491 } 492 } 493 494 495 // Construct the set of request attributes. 496 requestAttributes = new LinkedHashSet<String>(2); 497 requestAttributes.add("*"); 498 requestAttributes.add("+"); 499 500 501 DirectoryServer.registerSupportedExtension(OID_PASSWORD_POLICY_STATE_EXTOP, 502 this); 503 } 504 505 506 507 /** 508 * Performs any finalization that may be necessary for this extended 509 * operation handler. By default, no finalization is performed. 510 */ 511 public void finalizeExtendedOperationHandler() 512 { 513 DirectoryServer.deregisterSupportedExtension(OID_CANCEL_REQUEST); 514 } 515 516 517 518 /** 519 * Processes the provided extended operation. 520 * 521 * @param operation The extended operation to be processed. 522 */ 523 public void processExtendedOperation(ExtendedOperation operation) 524 { 525 operation.setResultCode(ResultCode.UNDEFINED); 526 527 528 // The user must have the password-reset privilege in order to be able to do 529 // anything with this extended operation. 530 ClientConnection clientConnection = operation.getClientConnection(); 531 if (! clientConnection.hasPrivilege(Privilege.PASSWORD_RESET, operation)) 532 { 533 Message message = ERR_PWPSTATE_EXTOP_NO_PRIVILEGE.get(); 534 operation.appendErrorMessage(message); 535 operation.setResultCode(ResultCode.INSUFFICIENT_ACCESS_RIGHTS); 536 return; 537 } 538 539 540 // There must be a request value, and it must be a sequence. Decode it 541 // into its components. 542 ASN1OctetString requestValue = operation.getRequestValue(); 543 if (requestValue == null) 544 { 545 Message message = ERR_PWPSTATE_EXTOP_NO_REQUEST_VALUE.get(); 546 operation.appendErrorMessage(message); 547 operation.setResultCode(ResultCode.PROTOCOL_ERROR); 548 return; 549 } 550 551 ASN1OctetString dnString; 552 ASN1Sequence opSequence; 553 try 554 { 555 ASN1Sequence valueSequence = 556 ASN1Sequence.decodeAsSequence(requestValue.value()); 557 List<ASN1Element> elements = valueSequence.elements(); 558 dnString = elements.get(0).decodeAsOctetString(); 559 560 if (elements.size() == 2) 561 { 562 opSequence = elements.get(1).decodeAsSequence(); 563 } 564 else 565 { 566 opSequence = null; 567 } 568 } 569 catch (Exception e) 570 { 571 if (debugEnabled()) 572 { 573 TRACER.debugCaught(DebugLogLevel.ERROR, e); 574 } 575 576 Message message = 577 ERR_PWPSTATE_EXTOP_DECODE_FAILURE.get(getExceptionMessage(e)); 578 operation.appendErrorMessage(message); 579 operation.setResultCode(ResultCode.PROTOCOL_ERROR); 580 return; 581 } 582 583 584 // Decode the DN and get the corresponding user entry. 585 DN targetDN; 586 try 587 { 588 targetDN = DN.decode(dnString); 589 } 590 catch (DirectoryException de) 591 { 592 if (debugEnabled()) 593 { 594 TRACER.debugCaught(DebugLogLevel.ERROR, de); 595 } 596 597 operation.setResponseData(de); 598 return; 599 } 600 601 DN rootDN = DirectoryServer.getActualRootBindDN(targetDN); 602 if (rootDN != null) 603 { 604 targetDN = rootDN; 605 } 606 607 Entry userEntry; 608 InternalClientConnection conn = 609 new InternalClientConnection(clientConnection.getAuthenticationInfo()); 610 InternalSearchOperation internalSearch = 611 conn.processSearch(targetDN, SearchScope.BASE_OBJECT, 612 DereferencePolicy.NEVER_DEREF_ALIASES, 1, 0, 613 false, userFilter, requestAttributes, null); 614 if (internalSearch.getResultCode() != ResultCode.SUCCESS) 615 { 616 operation.setResultCode(internalSearch.getResultCode()); 617 operation.setErrorMessage(internalSearch.getErrorMessage()); 618 operation.setMatchedDN(internalSearch.getMatchedDN()); 619 operation.setReferralURLs(internalSearch.getReferralURLs()); 620 return; 621 } 622 623 List<SearchResultEntry> matchingEntries = internalSearch.getSearchEntries(); 624 if (matchingEntries.isEmpty()) 625 { 626 operation.setResultCode(ResultCode.INSUFFICIENT_ACCESS_RIGHTS); 627 return; 628 } 629 else if (matchingEntries.size() > 1) 630 { 631 Message message = ERR_PWPSTATE_EXTOP_MULTIPLE_ENTRIES.get( 632 String.valueOf(targetDN)); 633 operation.appendErrorMessage(message); 634 operation.setResultCode(ResultCode.CONSTRAINT_VIOLATION); 635 return; 636 } 637 else 638 { 639 userEntry = matchingEntries.get(0); 640 } 641 642 643 // Get the password policy state for the user entry. 644 PasswordPolicyState pwpState; 645 PasswordPolicy policy; 646 try 647 { 648 pwpState = new PasswordPolicyState(userEntry, false); 649 policy = pwpState.getPolicy(); 650 } 651 catch (DirectoryException de) 652 { 653 if (debugEnabled()) 654 { 655 TRACER.debugCaught(DebugLogLevel.ERROR, de); 656 } 657 658 operation.setResponseData(de); 659 return; 660 } 661 662 663 // Create a hash set that will be used to hold the types of the return 664 // types that should be included in the response. 665 boolean returnAll; 666 LinkedHashSet<Integer> returnTypes = new LinkedHashSet<Integer>(); 667 if ((opSequence == null) || opSequence.elements().isEmpty()) 668 { 669 returnAll = true; 670 } 671 else 672 { 673 returnAll = false; 674 for (ASN1Element element : opSequence.elements()) 675 { 676 int opType; 677 ArrayList<String> opValues; 678 try 679 { 680 List<ASN1Element> opElements = element.decodeAsSequence().elements(); 681 opType = opElements.get(0).decodeAsEnumerated().intValue(); 682 683 if (opElements.size() == 1) 684 { 685 opValues = null; 686 } 687 else 688 { 689 List<ASN1Element> valueElements = 690 opElements.get(1).decodeAsSequence().elements(); 691 if (valueElements.isEmpty()) 692 { 693 opValues = null; 694 } 695 else 696 { 697 opValues = new ArrayList<String>(valueElements.size()); 698 for (ASN1Element e : valueElements) 699 { 700 opValues.add(e.decodeAsOctetString().stringValue()); 701 } 702 } 703 } 704 } 705 catch (Exception e) 706 { 707 if (debugEnabled()) 708 { 709 TRACER.debugCaught(DebugLogLevel.ERROR, e); 710 } 711 712 Message message = ERR_PWPSTATE_EXTOP_INVALID_OP_ENCODING.get( 713 e.getLocalizedMessage()); 714 operation.appendErrorMessage(message); 715 operation.setResultCode(ResultCode.PROTOCOL_ERROR); 716 return; 717 } 718 719 switch (opType) 720 { 721 case OP_GET_PASSWORD_POLICY_DN: 722 returnTypes.add(OP_GET_PASSWORD_POLICY_DN); 723 break; 724 725 case OP_GET_ACCOUNT_DISABLED_STATE: 726 returnTypes.add(OP_GET_ACCOUNT_DISABLED_STATE); 727 break; 728 729 case OP_SET_ACCOUNT_DISABLED_STATE: 730 if (opValues == null) 731 { 732 operation.appendErrorMessage( 733 ERR_PWPSTATE_EXTOP_NO_DISABLED_VALUE.get()); 734 operation.setResultCode(ResultCode.CONSTRAINT_VIOLATION); 735 return; 736 } 737 else if (opValues.size() != 1) 738 { 739 operation.appendErrorMessage( 740 ERR_PWPSTATE_EXTOP_BAD_DISABLED_VALUE_COUNT.get()); 741 operation.setResultCode(ResultCode.CONSTRAINT_VIOLATION); 742 return; 743 } 744 else 745 { 746 String value = opValues.get(0); 747 if (value.equalsIgnoreCase("true")) 748 { 749 pwpState.setDisabled(true); 750 } 751 else if (value.equalsIgnoreCase("false")) 752 { 753 pwpState.setDisabled(false); 754 } 755 else 756 { 757 operation.appendErrorMessage( 758 ERR_PWPSTATE_EXTOP_BAD_DISABLED_VALUE.get()); 759 operation.setResultCode(ResultCode.CONSTRAINT_VIOLATION); 760 return; 761 } 762 } 763 764 returnTypes.add(OP_GET_ACCOUNT_DISABLED_STATE); 765 break; 766 767 case OP_CLEAR_ACCOUNT_DISABLED_STATE: 768 pwpState.setDisabled(false); 769 returnTypes.add(OP_GET_ACCOUNT_DISABLED_STATE); 770 break; 771 772 case OP_GET_ACCOUNT_EXPIRATION_TIME: 773 returnTypes.add(OP_GET_ACCOUNT_EXPIRATION_TIME); 774 break; 775 776 case OP_SET_ACCOUNT_EXPIRATION_TIME: 777 if (opValues == null) 778 { 779 pwpState.setAccountExpirationTime(pwpState.getCurrentTime()); 780 } 781 else if (opValues.size() != 1) 782 { 783 operation.appendErrorMessage( 784 ERR_PWPSTATE_EXTOP_BAD_ACCT_EXP_VALUE_COUNT.get()); 785 operation.setResultCode(ResultCode.CONSTRAINT_VIOLATION); 786 return; 787 } 788 else 789 { 790 try 791 { 792 ASN1OctetString valueString = 793 new ASN1OctetString(opValues.get(0)); 794 long time = GeneralizedTimeSyntax.decodeGeneralizedTimeValue( 795 valueString); 796 pwpState.setAccountExpirationTime(time); 797 } 798 catch (DirectoryException de) 799 { 800 operation.appendErrorMessage( 801 ERR_PWPSTATE_EXTOP_BAD_ACCT_EXP_VALUE.get( 802 opValues.get(0), 803 de.getMessageObject())); 804 operation.setResultCode(ResultCode.CONSTRAINT_VIOLATION); 805 return; 806 } 807 } 808 809 returnTypes.add(OP_GET_ACCOUNT_EXPIRATION_TIME); 810 break; 811 812 case OP_CLEAR_ACCOUNT_EXPIRATION_TIME: 813 pwpState.clearAccountExpirationTime(); 814 returnTypes.add(OP_GET_ACCOUNT_EXPIRATION_TIME); 815 break; 816 817 case OP_GET_SECONDS_UNTIL_ACCOUNT_EXPIRATION: 818 returnTypes.add(OP_GET_SECONDS_UNTIL_ACCOUNT_EXPIRATION); 819 break; 820 821 case OP_GET_PASSWORD_CHANGED_TIME: 822 returnTypes.add(OP_GET_PASSWORD_CHANGED_TIME); 823 break; 824 825 case OP_SET_PASSWORD_CHANGED_TIME: 826 if (opValues == null) 827 { 828 pwpState.setPasswordChangedTime(); 829 } 830 else if (opValues.size() != 1) 831 { 832 operation.appendErrorMessage( 833 ERR_PWPSTATE_EXTOP_BAD_PWCHANGETIME_VALUE_COUNT.get()); 834 operation.setResultCode(ResultCode.CONSTRAINT_VIOLATION); 835 return; 836 } 837 else 838 { 839 try 840 { 841 ASN1OctetString valueString = 842 new ASN1OctetString(opValues.get(0)); 843 long time = GeneralizedTimeSyntax.decodeGeneralizedTimeValue( 844 valueString); 845 pwpState.setPasswordChangedTime(time); 846 } 847 catch (DirectoryException de) 848 { 849 operation.appendErrorMessage( 850 ERR_PWPSTATE_EXTOP_BAD_PWCHANGETIME_VALUE.get( 851 opValues.get(0), 852 de.getMessageObject())); 853 operation.setResultCode(ResultCode.CONSTRAINT_VIOLATION); 854 return; 855 } 856 } 857 858 returnTypes.add(OP_GET_PASSWORD_CHANGED_TIME); 859 break; 860 861 case OP_CLEAR_PASSWORD_CHANGED_TIME: 862 pwpState.clearPasswordChangedTime(); 863 returnTypes.add(OP_GET_PASSWORD_CHANGED_TIME); 864 break; 865 866 case OP_GET_PASSWORD_EXPIRATION_WARNED_TIME: 867 returnTypes.add(OP_GET_PASSWORD_EXPIRATION_WARNED_TIME); 868 break; 869 870 case OP_SET_PASSWORD_EXPIRATION_WARNED_TIME: 871 if (opValues == null) 872 { 873 pwpState.setWarnedTime(); 874 } 875 else if (opValues.size() != 1) 876 { 877 operation.appendErrorMessage( 878 ERR_PWPSTATE_EXTOP_BAD_PWWARNEDTIME_VALUE_COUNT.get()); 879 operation.setResultCode(ResultCode.CONSTRAINT_VIOLATION); 880 return; 881 } 882 else 883 { 884 try 885 { 886 ASN1OctetString valueString = 887 new ASN1OctetString(opValues.get(0)); 888 long time = GeneralizedTimeSyntax.decodeGeneralizedTimeValue( 889 valueString); 890 pwpState.setWarnedTime(time); 891 } 892 catch (DirectoryException de) 893 { 894 operation.appendErrorMessage( 895 ERR_PWPSTATE_EXTOP_BAD_PWWARNEDTIME_VALUE.get( 896 opValues.get(0), 897 de.getMessageObject())); 898 operation.setResultCode(ResultCode.CONSTRAINT_VIOLATION); 899 return; 900 } 901 } 902 903 returnTypes.add(OP_GET_PASSWORD_EXPIRATION_WARNED_TIME); 904 break; 905 906 case OP_CLEAR_PASSWORD_EXPIRATION_WARNED_TIME: 907 pwpState.clearWarnedTime(); 908 returnTypes.add(OP_GET_PASSWORD_EXPIRATION_WARNED_TIME); 909 break; 910 911 case OP_GET_SECONDS_UNTIL_PASSWORD_EXPIRATION: 912 returnTypes.add(OP_GET_SECONDS_UNTIL_PASSWORD_EXPIRATION); 913 break; 914 915 case OP_GET_SECONDS_UNTIL_PASSWORD_EXPIRATION_WARNING: 916 returnTypes.add(OP_GET_SECONDS_UNTIL_PASSWORD_EXPIRATION_WARNING); 917 break; 918 919 case OP_GET_AUTHENTICATION_FAILURE_TIMES: 920 returnTypes.add(OP_GET_AUTHENTICATION_FAILURE_TIMES); 921 break; 922 923 case OP_ADD_AUTHENTICATION_FAILURE_TIME: 924 if (opValues == null) 925 { 926 if (policy.getLockoutFailureCount() == 0) 927 { 928 returnTypes.add(OP_GET_AUTHENTICATION_FAILURE_TIMES); 929 break; 930 } 931 932 pwpState.updateAuthFailureTimes(); 933 } 934 else if (opValues.size() != 1) 935 { 936 operation.appendErrorMessage( 937 ERR_PWPSTATE_EXTOP_BAD_ADD_FAILURE_TIME_COUNT.get()); 938 operation.setResultCode(ResultCode.CONSTRAINT_VIOLATION); 939 return; 940 } 941 else 942 { 943 try 944 { 945 ASN1OctetString valueString = 946 new ASN1OctetString(opValues.get(0)); 947 long time = GeneralizedTimeSyntax.decodeGeneralizedTimeValue( 948 valueString); 949 List<Long> authFailureTimes = pwpState.getAuthFailureTimes(); 950 ArrayList<Long> newFailureTimes = 951 new ArrayList<Long>(authFailureTimes.size()+1); 952 newFailureTimes.addAll(authFailureTimes); 953 newFailureTimes.add(time); 954 pwpState.setAuthFailureTimes(newFailureTimes); 955 } 956 catch (DirectoryException de) 957 { 958 Message message = ERR_PWPSTATE_EXTOP_BAD_AUTH_FAILURE_TIME.get( 959 opValues.get(0), 960 de.getMessageObject()); 961 operation.setResultCode(de.getResultCode()); 962 operation.appendErrorMessage(message); 963 return; 964 } 965 } 966 967 returnTypes.add(OP_GET_AUTHENTICATION_FAILURE_TIMES); 968 break; 969 970 case OP_SET_AUTHENTICATION_FAILURE_TIMES: 971 if (opValues == null) 972 { 973 ArrayList<Long> valueList = new ArrayList<Long>(1); 974 valueList.add(pwpState.getCurrentTime()); 975 pwpState.setAuthFailureTimes(valueList); 976 } 977 else 978 { 979 ArrayList<Long> valueList = new ArrayList<Long>(opValues.size()); 980 for (String s : opValues) 981 { 982 try 983 { 984 valueList.add( 985 GeneralizedTimeSyntax.decodeGeneralizedTimeValue( 986 new ASN1OctetString(s))); 987 } 988 catch (DirectoryException de) 989 { 990 Message message = 991 ERR_PWPSTATE_EXTOP_BAD_AUTH_FAILURE_TIME.get( 992 s, 993 de.getMessageObject()); 994 operation.setResultCode(de.getResultCode()); 995 operation.appendErrorMessage(message); 996 return; 997 } 998 } 999 pwpState.setAuthFailureTimes(valueList); 1000 } 1001 1002 returnTypes.add(OP_GET_AUTHENTICATION_FAILURE_TIMES); 1003 break; 1004 1005 case OP_CLEAR_AUTHENTICATION_FAILURE_TIMES: 1006 pwpState.clearFailureLockout(); 1007 returnTypes.add(OP_GET_AUTHENTICATION_FAILURE_TIMES); 1008 break; 1009 1010 case OP_GET_SECONDS_UNTIL_AUTHENTICATION_FAILURE_UNLOCK: 1011 returnTypes.add(OP_GET_SECONDS_UNTIL_AUTHENTICATION_FAILURE_UNLOCK); 1012 break; 1013 1014 case OP_GET_REMAINING_AUTHENTICATION_FAILURE_COUNT: 1015 returnTypes.add(OP_GET_REMAINING_AUTHENTICATION_FAILURE_COUNT); 1016 break; 1017 1018 case OP_GET_LAST_LOGIN_TIME: 1019 returnTypes.add(OP_GET_LAST_LOGIN_TIME); 1020 break; 1021 1022 case OP_SET_LAST_LOGIN_TIME: 1023 if (opValues == null) 1024 { 1025 pwpState.setLastLoginTime(); 1026 } 1027 else if (opValues.size() != 1) 1028 { 1029 operation.appendErrorMessage( 1030 ERR_PWPSTATE_EXTOP_BAD_LAST_LOGIN_TIME_COUNT.get()); 1031 operation.setResultCode(ResultCode.CONSTRAINT_VIOLATION); 1032 return; 1033 } 1034 else 1035 { 1036 try 1037 { 1038 ASN1OctetString valueString = 1039 new ASN1OctetString(opValues.get(0)); 1040 long time = GeneralizedTimeSyntax.decodeGeneralizedTimeValue( 1041 valueString); 1042 pwpState.setLastLoginTime(time); 1043 } 1044 catch (DirectoryException de) 1045 { 1046 operation.appendErrorMessage( 1047 ERR_PWPSTATE_EXTOP_BAD_LAST_LOGIN_TIME.get( 1048 opValues.get(0), 1049 de.getMessageObject())); 1050 operation.setResultCode(ResultCode.CONSTRAINT_VIOLATION); 1051 return; 1052 } 1053 } 1054 1055 returnTypes.add(OP_GET_LAST_LOGIN_TIME); 1056 break; 1057 1058 case OP_CLEAR_LAST_LOGIN_TIME: 1059 pwpState.clearLastLoginTime(); 1060 returnTypes.add(OP_GET_LAST_LOGIN_TIME); 1061 break; 1062 1063 case OP_GET_SECONDS_UNTIL_IDLE_LOCKOUT: 1064 returnTypes.add(OP_GET_SECONDS_UNTIL_IDLE_LOCKOUT); 1065 break; 1066 1067 case OP_GET_PASSWORD_RESET_STATE: 1068 returnTypes.add(OP_GET_PASSWORD_RESET_STATE); 1069 break; 1070 1071 case OP_SET_PASSWORD_RESET_STATE: 1072 if (opValues == null) 1073 { 1074 operation.appendErrorMessage( 1075 ERR_PWPSTATE_EXTOP_NO_RESET_STATE_VALUE.get()); 1076 operation.setResultCode(ResultCode.CONSTRAINT_VIOLATION); 1077 return; 1078 } 1079 else if (opValues.size() != 1) 1080 { 1081 operation.appendErrorMessage( 1082 ERR_PWPSTATE_EXTOP_BAD_RESET_STATE_VALUE_COUNT.get()); 1083 operation.setResultCode(ResultCode.CONSTRAINT_VIOLATION); 1084 return; 1085 } 1086 else 1087 { 1088 String value = opValues.get(0); 1089 if (value.equalsIgnoreCase("true")) 1090 { 1091 pwpState.setMustChangePassword(true); 1092 } 1093 else if (value.equalsIgnoreCase("false")) 1094 { 1095 pwpState.setMustChangePassword(false); 1096 } 1097 else 1098 { 1099 operation.appendErrorMessage( 1100 ERR_PWPSTATE_EXTOP_BAD_RESET_STATE_VALUE.get()); 1101 operation.setResultCode(ResultCode.CONSTRAINT_VIOLATION); 1102 return; 1103 } 1104 } 1105 1106 returnTypes.add(OP_GET_PASSWORD_RESET_STATE); 1107 break; 1108 1109 case OP_CLEAR_PASSWORD_RESET_STATE: 1110 pwpState.setMustChangePassword(false); 1111 returnTypes.add(OP_GET_PASSWORD_RESET_STATE); 1112 break; 1113 1114 case OP_GET_SECONDS_UNTIL_PASSWORD_RESET_LOCKOUT: 1115 returnTypes.add(OP_GET_SECONDS_UNTIL_PASSWORD_RESET_LOCKOUT); 1116 break; 1117 1118 case OP_GET_GRACE_LOGIN_USE_TIMES: 1119 returnTypes.add(OP_GET_GRACE_LOGIN_USE_TIMES); 1120 break; 1121 1122 case OP_ADD_GRACE_LOGIN_USE_TIME: 1123 if (opValues == null) 1124 { 1125 pwpState.updateGraceLoginTimes(); 1126 } 1127 else if (opValues.size() != 1) 1128 { 1129 operation.appendErrorMessage( 1130 ERR_PWPSTATE_EXTOP_BAD_ADD_GRACE_LOGIN_TIME_COUNT.get()); 1131 operation.setResultCode(ResultCode.CONSTRAINT_VIOLATION); 1132 return; 1133 } 1134 else 1135 { 1136 try 1137 { 1138 ASN1OctetString valueString = 1139 new ASN1OctetString(opValues.get(0)); 1140 long time = GeneralizedTimeSyntax.decodeGeneralizedTimeValue( 1141 valueString); 1142 List<Long> authFailureTimes = pwpState.getGraceLoginTimes(); 1143 ArrayList<Long> newGraceTimes = 1144 new ArrayList<Long>(authFailureTimes.size()+1); 1145 newGraceTimes.addAll(authFailureTimes); 1146 newGraceTimes.add(time); 1147 pwpState.setGraceLoginTimes(newGraceTimes); 1148 } 1149 catch (DirectoryException de) 1150 { 1151 Message message = ERR_PWPSTATE_EXTOP_BAD_GRACE_LOGIN_TIME.get( 1152 opValues.get(0), 1153 de.getMessageObject()); 1154 operation.setResultCode(de.getResultCode()); 1155 operation.appendErrorMessage(message); 1156 return; 1157 } 1158 } 1159 1160 returnTypes.add(OP_GET_GRACE_LOGIN_USE_TIMES); 1161 break; 1162 1163 case OP_SET_GRACE_LOGIN_USE_TIMES: 1164 if (opValues == null) 1165 { 1166 ArrayList<Long> valueList = new ArrayList<Long>(1); 1167 valueList.add(pwpState.getCurrentTime()); 1168 pwpState.setGraceLoginTimes(valueList); 1169 } 1170 else 1171 { 1172 ArrayList<Long> valueList = new ArrayList<Long>(opValues.size()); 1173 for (String s : opValues) 1174 { 1175 try 1176 { 1177 valueList.add( 1178 GeneralizedTimeSyntax.decodeGeneralizedTimeValue( 1179 new ASN1OctetString(s))); 1180 } 1181 catch (DirectoryException de) 1182 { 1183 Message message = ERR_PWPSTATE_EXTOP_BAD_GRACE_LOGIN_TIME.get( 1184 s, de.getMessageObject()); 1185 operation.setResultCode(de.getResultCode()); 1186 operation.appendErrorMessage(message); 1187 return; 1188 } 1189 } 1190 pwpState.setGraceLoginTimes(valueList); 1191 } 1192 1193 returnTypes.add(OP_GET_GRACE_LOGIN_USE_TIMES); 1194 break; 1195 1196 case OP_CLEAR_GRACE_LOGIN_USE_TIMES: 1197 pwpState.clearGraceLoginTimes(); 1198 returnTypes.add(OP_GET_GRACE_LOGIN_USE_TIMES); 1199 break; 1200 1201 case OP_GET_REMAINING_GRACE_LOGIN_COUNT: 1202 returnTypes.add(OP_GET_REMAINING_GRACE_LOGIN_COUNT); 1203 break; 1204 1205 case OP_GET_PASSWORD_CHANGED_BY_REQUIRED_TIME: 1206 returnTypes.add(OP_GET_PASSWORD_CHANGED_BY_REQUIRED_TIME); 1207 break; 1208 1209 case OP_SET_PASSWORD_CHANGED_BY_REQUIRED_TIME: 1210 if (opValues == null) 1211 { 1212 pwpState.setRequiredChangeTime(); 1213 } 1214 else if (opValues.size() != 1) 1215 { 1216 operation.appendErrorMessage( 1217 ERR_PWPSTATE_EXTOP_BAD_REQUIRED_CHANGE_TIME_COUNT.get()); 1218 operation.setResultCode(ResultCode.CONSTRAINT_VIOLATION); 1219 return; 1220 } 1221 else 1222 { 1223 try 1224 { 1225 ASN1OctetString valueString = 1226 new ASN1OctetString(opValues.get(0)); 1227 long time = GeneralizedTimeSyntax.decodeGeneralizedTimeValue( 1228 valueString); 1229 pwpState.setRequiredChangeTime(time); 1230 } 1231 catch (DirectoryException de) 1232 { 1233 operation.appendErrorMessage( 1234 ERR_PWPSTATE_EXTOP_BAD_REQUIRED_CHANGE_TIME.get( 1235 opValues.get(0), 1236 de.getMessageObject())); 1237 operation.setResultCode(ResultCode.CONSTRAINT_VIOLATION); 1238 return; 1239 } 1240 } 1241 1242 returnTypes.add(OP_GET_PASSWORD_CHANGED_BY_REQUIRED_TIME); 1243 break; 1244 1245 case OP_CLEAR_PASSWORD_CHANGED_BY_REQUIRED_TIME: 1246 pwpState.clearRequiredChangeTime(); 1247 returnTypes.add(OP_GET_PASSWORD_CHANGED_BY_REQUIRED_TIME); 1248 break; 1249 1250 case OP_GET_SECONDS_UNTIL_REQUIRED_CHANGE_TIME: 1251 returnTypes.add(OP_GET_SECONDS_UNTIL_REQUIRED_CHANGE_TIME); 1252 break; 1253 1254 case OP_GET_PASSWORD_HISTORY: 1255 returnTypes.add(OP_GET_PASSWORD_HISTORY); 1256 break; 1257 1258 case OP_CLEAR_PASSWORD_HISTORY: 1259 pwpState.clearPasswordHistory(); 1260 returnTypes.add(OP_GET_PASSWORD_HISTORY); 1261 break; 1262 1263 default: 1264 1265 operation.appendErrorMessage(ERR_PWPSTATE_EXTOP_UNKNOWN_OP_TYPE.get( 1266 String.valueOf(opType))); 1267 operation.setResultCode(ResultCode.CONSTRAINT_VIOLATION); 1268 return; 1269 } 1270 } 1271 1272 1273 // If there are any modifications that need to be made to the password 1274 // policy state, then apply them now. 1275 List<Modification> stateMods = pwpState.getModifications(); 1276 if ((stateMods != null) && (! stateMods.isEmpty())) 1277 { 1278 ModifyOperation modifyOperation = 1279 conn.processModify(targetDN, stateMods); 1280 if (modifyOperation.getResultCode() != ResultCode.SUCCESS) 1281 { 1282 operation.setResultCode(modifyOperation.getResultCode()); 1283 operation.setErrorMessage(modifyOperation.getErrorMessage()); 1284 operation.setMatchedDN(modifyOperation.getMatchedDN()); 1285 operation.setReferralURLs(modifyOperation.getReferralURLs()); 1286 return; 1287 } 1288 } 1289 } 1290 1291 1292 // Construct the sequence of values to return. 1293 ArrayList<ASN1Element> opElements = new ArrayList<ASN1Element>(); 1294 if (returnAll || returnTypes.contains(OP_GET_PASSWORD_POLICY_DN)) 1295 { 1296 opElements.add(encode(OP_GET_PASSWORD_POLICY_DN, 1297 policy.getConfigEntryDN().toString())); 1298 } 1299 1300 if (returnAll || returnTypes.contains(OP_GET_ACCOUNT_DISABLED_STATE)) 1301 { 1302 opElements.add(encode(OP_GET_ACCOUNT_DISABLED_STATE, 1303 String.valueOf(pwpState.isDisabled()))); 1304 } 1305 1306 if (returnAll || returnTypes.contains(OP_GET_ACCOUNT_EXPIRATION_TIME)) 1307 { 1308 String expTimeStr; 1309 long expTime = pwpState.getAccountExpirationTime(); 1310 if (expTime < 0) 1311 { 1312 expTimeStr = null; 1313 } 1314 else 1315 { 1316 expTimeStr = GeneralizedTimeSyntax.format(expTime); 1317 } 1318 1319 opElements.add(encode(OP_GET_ACCOUNT_EXPIRATION_TIME, expTimeStr)); 1320 } 1321 1322 if (returnAll || 1323 returnTypes.contains(OP_GET_SECONDS_UNTIL_ACCOUNT_EXPIRATION)) 1324 { 1325 String secondsStr; 1326 long expTime = pwpState.getAccountExpirationTime(); 1327 if (expTime < 0) 1328 { 1329 secondsStr = null; 1330 } 1331 else 1332 { 1333 secondsStr = 1334 String.valueOf((expTime - pwpState.getCurrentTime()) / 1000); 1335 } 1336 1337 opElements.add(encode(OP_GET_SECONDS_UNTIL_ACCOUNT_EXPIRATION, 1338 secondsStr)); 1339 } 1340 1341 if (returnAll || returnTypes.contains(OP_GET_PASSWORD_CHANGED_TIME)) 1342 { 1343 String timeStr; 1344 long changedTime = pwpState.getPasswordChangedTime(); 1345 if (changedTime < 0) 1346 { 1347 timeStr = null; 1348 } 1349 else 1350 { 1351 timeStr = GeneralizedTimeSyntax.format(changedTime); 1352 } 1353 1354 opElements.add(encode(OP_GET_PASSWORD_CHANGED_TIME, timeStr)); 1355 } 1356 1357 if (returnAll || 1358 returnTypes.contains(OP_GET_PASSWORD_EXPIRATION_WARNED_TIME)) 1359 { 1360 String timeStr; 1361 long warnedTime = pwpState.getWarnedTime(); 1362 if (warnedTime < 0) 1363 { 1364 timeStr = null; 1365 } 1366 else 1367 { 1368 timeStr = GeneralizedTimeSyntax.format(warnedTime); 1369 } 1370 1371 opElements.add(encode(OP_GET_PASSWORD_EXPIRATION_WARNED_TIME, timeStr)); 1372 } 1373 1374 if (returnAll || 1375 returnTypes.contains(OP_GET_SECONDS_UNTIL_PASSWORD_EXPIRATION)) 1376 { 1377 String secondsStr; 1378 int secondsUntilExp = pwpState.getSecondsUntilExpiration(); 1379 if (secondsUntilExp < 0) 1380 { 1381 secondsStr = null; 1382 } 1383 else 1384 { 1385 secondsStr = String.valueOf(secondsUntilExp); 1386 } 1387 1388 opElements.add(encode(OP_GET_SECONDS_UNTIL_PASSWORD_EXPIRATION, 1389 secondsStr)); 1390 } 1391 1392 if (returnAll || 1393 returnTypes.contains(OP_GET_SECONDS_UNTIL_PASSWORD_EXPIRATION_WARNING)) 1394 { 1395 String secondsStr; 1396 int secondsUntilExp = pwpState.getSecondsUntilExpiration(); 1397 if (secondsUntilExp < 0) 1398 { 1399 secondsStr = null; 1400 } 1401 else 1402 { 1403 int secondsUntilWarning = secondsUntilExp - policy.getWarningInterval(); 1404 if (secondsUntilWarning <= 0) 1405 { 1406 secondsStr = "0"; 1407 } 1408 else 1409 { 1410 secondsStr = String.valueOf(secondsUntilWarning); 1411 } 1412 } 1413 1414 opElements.add(encode(OP_GET_SECONDS_UNTIL_PASSWORD_EXPIRATION_WARNING, 1415 secondsStr)); 1416 } 1417 1418 if (returnAll || returnTypes.contains(OP_GET_AUTHENTICATION_FAILURE_TIMES)) 1419 { 1420 opElements.add(encode(OP_GET_AUTHENTICATION_FAILURE_TIMES, 1421 pwpState.getAuthFailureTimes())); 1422 } 1423 1424 if (returnAll || returnTypes.contains( 1425 OP_GET_SECONDS_UNTIL_AUTHENTICATION_FAILURE_UNLOCK)) 1426 { 1427 // We have to check whether the account is locked due to failures before 1428 // we can get the length of time until the account is unlocked. 1429 String secondsStr; 1430 if (pwpState.lockedDueToFailures()) 1431 { 1432 int seconds = pwpState.getSecondsUntilUnlock(); 1433 if (seconds <= 0) 1434 { 1435 secondsStr = null; 1436 } 1437 else 1438 { 1439 secondsStr = String.valueOf(seconds); 1440 } 1441 } 1442 else 1443 { 1444 secondsStr = null; 1445 } 1446 1447 opElements.add(encode(OP_GET_SECONDS_UNTIL_AUTHENTICATION_FAILURE_UNLOCK, 1448 secondsStr)); 1449 } 1450 1451 if (returnAll || 1452 returnTypes.contains(OP_GET_REMAINING_AUTHENTICATION_FAILURE_COUNT)) 1453 { 1454 String remainingFailuresStr; 1455 int allowedFailureCount = policy.getLockoutFailureCount(); 1456 if (allowedFailureCount > 0) 1457 { 1458 int remainingFailures = 1459 allowedFailureCount - pwpState.getAuthFailureTimes().size(); 1460 if (remainingFailures < 0) 1461 { 1462 remainingFailures = 0; 1463 } 1464 1465 remainingFailuresStr = String.valueOf(remainingFailures); 1466 } 1467 else 1468 { 1469 remainingFailuresStr = null; 1470 } 1471 1472 opElements.add(encode(OP_GET_REMAINING_AUTHENTICATION_FAILURE_COUNT, 1473 remainingFailuresStr)); 1474 } 1475 1476 if (returnAll || returnTypes.contains(OP_GET_LAST_LOGIN_TIME)) 1477 { 1478 String timeStr; 1479 long lastLoginTime = pwpState.getLastLoginTime(); 1480 if (lastLoginTime < 0) 1481 { 1482 timeStr = null; 1483 } 1484 else 1485 { 1486 timeStr = GeneralizedTimeSyntax.format(lastLoginTime); 1487 } 1488 1489 opElements.add(encode(OP_GET_LAST_LOGIN_TIME, timeStr)); 1490 } 1491 1492 if (returnAll || returnTypes.contains(OP_GET_SECONDS_UNTIL_IDLE_LOCKOUT)) 1493 { 1494 String secondsStr; 1495 int lockoutInterval = policy.getIdleLockoutInterval(); 1496 if (lockoutInterval > 0) 1497 { 1498 long lastLoginTime = pwpState.getLastLoginTime(); 1499 if (lastLoginTime < 0) 1500 { 1501 secondsStr = "0"; 1502 } 1503 else 1504 { 1505 long lockoutTime = lastLoginTime + (lockoutInterval*1000); 1506 long currentTime = pwpState.getCurrentTime(); 1507 int secondsUntilLockout = (int) ((lockoutTime - currentTime) / 1000); 1508 if (secondsUntilLockout <= 0) 1509 { 1510 secondsStr = "0"; 1511 } 1512 else 1513 { 1514 secondsStr = String.valueOf(secondsUntilLockout); 1515 } 1516 } 1517 } 1518 else 1519 { 1520 secondsStr = null; 1521 } 1522 1523 opElements.add(encode(OP_GET_SECONDS_UNTIL_IDLE_LOCKOUT, secondsStr)); 1524 } 1525 1526 if (returnAll || returnTypes.contains(OP_GET_PASSWORD_RESET_STATE)) 1527 { 1528 opElements.add(encode(OP_GET_PASSWORD_RESET_STATE, 1529 String.valueOf(pwpState.mustChangePassword()))); 1530 } 1531 1532 if (returnAll || 1533 returnTypes.contains(OP_GET_SECONDS_UNTIL_PASSWORD_RESET_LOCKOUT)) 1534 { 1535 String secondsStr; 1536 if (pwpState.mustChangePassword()) 1537 { 1538 int maxAge = policy.getMaximumPasswordResetAge(); 1539 if (maxAge > 0) 1540 { 1541 long currentTime = pwpState.getCurrentTime(); 1542 long changedTime = pwpState.getPasswordChangedTime(); 1543 int changeAge = (int) ((currentTime - changedTime) / 1000); 1544 int timeToLockout = maxAge - changeAge; 1545 if (timeToLockout <= 0) 1546 { 1547 secondsStr = "0"; 1548 } 1549 else 1550 { 1551 secondsStr = String.valueOf(timeToLockout); 1552 } 1553 } 1554 else 1555 { 1556 secondsStr = null; 1557 } 1558 } 1559 else 1560 { 1561 secondsStr = null; 1562 } 1563 1564 opElements.add(encode(OP_GET_SECONDS_UNTIL_PASSWORD_RESET_LOCKOUT, 1565 secondsStr)); 1566 } 1567 1568 if (returnAll || returnTypes.contains(OP_GET_GRACE_LOGIN_USE_TIMES)) 1569 { 1570 opElements.add(encode(OP_GET_GRACE_LOGIN_USE_TIMES, 1571 pwpState.getGraceLoginTimes())); 1572 } 1573 1574 if (returnAll || returnTypes.contains(OP_GET_REMAINING_GRACE_LOGIN_COUNT)) 1575 { 1576 String remainingStr; 1577 int remainingGraceLogins = pwpState.getGraceLoginsRemaining(); 1578 if (remainingGraceLogins <= 0) 1579 { 1580 remainingStr = "0"; 1581 } 1582 else 1583 { 1584 remainingStr = String.valueOf(remainingGraceLogins); 1585 } 1586 1587 opElements.add(encode(OP_GET_REMAINING_GRACE_LOGIN_COUNT, remainingStr)); 1588 } 1589 1590 if (returnAll || 1591 returnTypes.contains(OP_GET_PASSWORD_CHANGED_BY_REQUIRED_TIME)) 1592 { 1593 String timeStr; 1594 long requiredChangeTime = pwpState.getRequiredChangeTime(); 1595 if (requiredChangeTime < 0) 1596 { 1597 timeStr = null; 1598 } 1599 else 1600 { 1601 timeStr = GeneralizedTimeSyntax.format(requiredChangeTime); 1602 } 1603 1604 opElements.add(encode(OP_GET_PASSWORD_CHANGED_BY_REQUIRED_TIME, timeStr)); 1605 } 1606 1607 if (returnAll || 1608 returnTypes.contains(OP_GET_SECONDS_UNTIL_REQUIRED_CHANGE_TIME)) 1609 { 1610 String secondsStr; 1611 long policyRequiredChangeTime = policy.getRequireChangeByTime(); 1612 if (policyRequiredChangeTime > 0) 1613 { 1614 long accountRequiredChangeTime = pwpState.getRequiredChangeTime(); 1615 if (accountRequiredChangeTime >= policyRequiredChangeTime) 1616 { 1617 secondsStr = null; 1618 } 1619 else 1620 { 1621 long currentTime = pwpState.getCurrentTime(); 1622 if (currentTime >= policyRequiredChangeTime) 1623 { 1624 secondsStr = "0"; 1625 } 1626 else 1627 { 1628 secondsStr = 1629 String.valueOf((policyRequiredChangeTime-currentTime) / 1000); 1630 1631 } 1632 } 1633 } 1634 else 1635 { 1636 secondsStr = null; 1637 } 1638 1639 opElements.add(encode(OP_GET_SECONDS_UNTIL_REQUIRED_CHANGE_TIME, 1640 secondsStr)); 1641 } 1642 1643 if (returnAll || returnTypes.contains(OP_GET_PASSWORD_HISTORY)) 1644 { 1645 opElements.add(encode(OP_GET_PASSWORD_HISTORY, 1646 pwpState.getPasswordHistoryValues())); 1647 } 1648 1649 ArrayList<ASN1Element> responseValueElements = 1650 new ArrayList<ASN1Element>(2); 1651 responseValueElements.add(dnString); 1652 responseValueElements.add(new ASN1Sequence(opElements)); 1653 1654 ASN1OctetString responseValue = 1655 new ASN1OctetString(new ASN1Sequence(responseValueElements).encode()); 1656 1657 operation.setResponseOID(OID_PASSWORD_POLICY_STATE_EXTOP); 1658 operation.setResponseValue(responseValue); 1659 operation.setResultCode(ResultCode.SUCCESS); 1660 } 1661 1662 1663 1664 /** 1665 * Encodes the provided information in a form suitable for including in the 1666 * response value. 1667 * 1668 * @param opType The operation type to use for the value. 1669 * @param value The single value to include in the response. 1670 * 1671 * @return The encoded ASN.1 element. 1672 */ 1673 public static ASN1Element encode(int opType, String value) 1674 { 1675 ArrayList<ASN1Element> elements = new ArrayList<ASN1Element>(2); 1676 elements.add(new ASN1Enumerated(opType)); 1677 1678 if (value != null) 1679 { 1680 ArrayList<ASN1Element> valueElements = new ArrayList<ASN1Element>(1); 1681 valueElements.add(new ASN1OctetString(value)); 1682 elements.add(new ASN1Sequence(valueElements)); 1683 } 1684 1685 return new ASN1Sequence(elements); 1686 } 1687 1688 1689 1690 /** 1691 * Encodes the provided information in a form suitable for including in the 1692 * response value. 1693 * 1694 * @param opType The operation type to use for the value. 1695 * @param values The set of string values to include in the response. 1696 * 1697 * @return The encoded ASN.1 element. 1698 */ 1699 public static ASN1Element encode(int opType, String[] values) 1700 { 1701 ArrayList<ASN1Element> elements = new ArrayList<ASN1Element>(2); 1702 elements.add(new ASN1Enumerated(opType)); 1703 1704 if ((values != null) && (values.length > 0)) 1705 { 1706 ArrayList<ASN1Element> valueElements = 1707 new ArrayList<ASN1Element>(values.length); 1708 for (int i=0; i < values.length; i++) 1709 { 1710 valueElements.add(new ASN1OctetString(values[i])); 1711 } 1712 elements.add(new ASN1Sequence(valueElements)); 1713 } 1714 1715 return new ASN1Sequence(elements); 1716 } 1717 1718 1719 1720 /** 1721 * Encodes the provided information in a form suitable for including in the 1722 * response value. 1723 * 1724 * @param opType The operation type to use for the value. 1725 * @param values The set of timestamp values to include in the response. 1726 * 1727 * @return The encoded ASN.1 element. 1728 */ 1729 public static ASN1Element encode(int opType, List<Long> values) 1730 { 1731 ArrayList<ASN1Element> elements = new ArrayList<ASN1Element>(2); 1732 elements.add(new ASN1Enumerated(opType)); 1733 1734 ArrayList<ASN1Element> valueElements = 1735 new ArrayList<ASN1Element>(values.size()); 1736 for (long l : values) 1737 { 1738 valueElements.add(new ASN1OctetString(GeneralizedTimeSyntax.format(l))); 1739 } 1740 elements.add(new ASN1Sequence(valueElements)); 1741 1742 return new ASN1Sequence(elements); 1743 } 1744 } 1745