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