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 *
026 * Copyright 2006-2008 Sun Microsystems, Inc.
027 */
028 package org.opends.server.tools;
029 import org.opends.messages.Message;
030
031
032
033 import java.io.OutputStream;
034 import java.io.PrintStream;
035 import java.util.ArrayList;
036 import java.util.LinkedList;
037 import java.util.HashSet;
038 import java.util.concurrent.atomic.AtomicInteger;
039
040 import org.opends.server.protocols.asn1.ASN1Element;
041 import org.opends.server.protocols.asn1.ASN1OctetString;
042 import org.opends.server.protocols.asn1.ASN1Sequence;
043 import org.opends.server.protocols.ldap.ExtendedRequestProtocolOp;
044 import org.opends.server.protocols.ldap.ExtendedResponseProtocolOp;
045 import org.opends.server.protocols.ldap.LDAPMessage;
046 import org.opends.server.protocols.ldap.LDAPResultCode;
047 import org.opends.server.types.NullOutputStream;
048 import org.opends.server.util.args.Argument;
049 import org.opends.server.util.args.ArgumentException;
050 import org.opends.server.util.args.BooleanArgument;
051 import org.opends.server.util.args.FileBasedArgument;
052 import org.opends.server.util.args.IntegerArgument;
053 import org.opends.server.util.args.LDAPConnectionArgumentParser;
054 import org.opends.server.util.args.MultiChoiceArgument;
055 import org.opends.server.util.args.StringArgument;
056 import org.opends.server.util.args.SubCommand;
057 import org.opends.server.util.args.SubCommandArgumentParser;
058
059 import static org.opends.server.extensions.
060 PasswordPolicyStateExtendedOperation.*;
061 import static org.opends.messages.ToolMessages.*;
062 import static org.opends.server.tools.ToolConstants.*;
063 import static org.opends.server.util.ServerConstants.*;
064 import static org.opends.server.util.StaticUtils.*;
065
066
067
068 /**
069 * This class provides a tool that can be used to perform various kinds of
070 * account management using the password policy state extended operation.
071 */
072 public class ManageAccount
073 {
074 /**
075 * The fully-qualified name of this class.
076 */
077 private static final String CLASS_NAME =
078 "org.opends.server.tools.ManageAccount";
079
080
081
082 /**
083 * The name of the subcommand that will be used to get all password policy
084 * state information for the user.
085 */
086 private static final String SC_GET_ALL = "get-all";
087
088
089
090 /**
091 * The name of the subcommand that will be used to get the DN of the password
092 * policy for a given user.
093 */
094 private static final String SC_GET_PASSWORD_POLICY_DN =
095 "get-password-policy-dn";
096
097
098
099 /**
100 * The name of the subcommand that will be used to get the disabled state for
101 * a user.
102 */
103 private static final String SC_GET_ACCOUNT_DISABLED_STATE =
104 "get-account-is-disabled";
105
106
107
108 /**
109 * The name of the subcommand that will be used to set the disabled state for
110 * a user.
111 */
112 private static final String SC_SET_ACCOUNT_DISABLED_STATE =
113 "set-account-is-disabled";
114
115
116
117 /**
118 * The name of the subcommand that will be used to clear the disabled state
119 * for a user.
120 */
121 private static final String SC_CLEAR_ACCOUNT_DISABLED_STATE =
122 "clear-account-is-disabled";
123
124
125
126 /**
127 * The name of the subcommand that will be used to get the account expiration
128 * time.
129 */
130 private static final String SC_GET_ACCOUNT_EXPIRATION_TIME =
131 "get-account-expiration-time";
132
133
134
135 /**
136 * The name of the subcommand that will be used to set the account expiration
137 * time.
138 */
139 private static final String SC_SET_ACCOUNT_EXPIRATION_TIME =
140 "set-account-expiration-time";
141
142
143
144 /**
145 * The name of the subcommand that will be used to clear the account
146 * expiration time.
147 */
148 private static final String SC_CLEAR_ACCOUNT_EXPIRATION_TIME =
149 "clear-account-expiration-time";
150
151
152
153 /**
154 * The name of the subcommand that will be used to get the length of time
155 * before the account expires.
156 */
157 private static final String SC_GET_SECONDS_UNTIL_ACCOUNT_EXPIRATION =
158 "get-seconds-until-account-expiration";
159
160
161
162 /**
163 * The name of the subcommand that will be used to get the time the password
164 * was last changed.
165 */
166 private static final String SC_GET_PASSWORD_CHANGED_TIME =
167 "get-password-changed-time";
168
169
170
171 /**
172 * The name of the subcommand that will be used to set the time the password
173 * was last changed.
174 */
175 private static final String SC_SET_PASSWORD_CHANGED_TIME =
176 "set-password-changed-time";
177
178
179
180 /**
181 * The name of the subcommand that will be used to clear the time the password
182 * was last changed.
183 */
184 private static final String SC_CLEAR_PASSWORD_CHANGED_TIME =
185 "clear-password-changed-time";
186
187
188
189 /**
190 * The name of the subcommand that will be used to get the time the user was
191 * first warned about an upcoming password expiration.
192 */
193 private static final String SC_GET_PASSWORD_EXP_WARNED_TIME =
194 "get-password-expiration-warned-time";
195
196
197
198 /**
199 * The name of the subcommand that will be used to set the time the user was
200 * first warned about an upcoming password expiration.
201 */
202 private static final String SC_SET_PASSWORD_EXP_WARNED_TIME =
203 "set-password-expiration-warned-time";
204
205
206
207 /**
208 * The name of the subcommand that will be used to clear the time the user was
209 * first warned about an upcoming password expiration.
210 */
211 private static final String SC_CLEAR_PASSWORD_EXP_WARNED_TIME =
212 "clear-password-expiration-warned-time";
213
214
215
216 /**
217 * The name of the subcommand that will be used to get the length of time
218 * before the password expires.
219 */
220 private static final String SC_GET_SECONDS_UNTIL_PASSWORD_EXPIRATION =
221 "get-seconds-until-password-expiration";
222
223
224
225 /**
226 * The name of the subcommand that will be used to get the length of time
227 * before the user is first warned about an upcoming password expiration.
228 */
229 private static final String SC_GET_SECONDS_UNTIL_PASSWORD_EXPIRATION_WARNING =
230 "get-seconds-until-password-expiration-warning";
231
232
233
234 /**
235 * The name of the subcommand that will be used to get the authentication
236 * failure times for the user.
237 */
238 private static final String SC_GET_AUTHENTICATION_FAILURE_TIMES =
239 "get-authentication-failure-times";
240
241
242
243 /**
244 * The name of the subcommand that will be used to add an authentication
245 * failure time for the user.
246 */
247 private static final String SC_ADD_AUTHENTICATION_FAILURE_TIME =
248 "add-authentication-failure-time";
249
250
251
252 /**
253 * The name of the subcommand that will be used to set the authentication
254 * failure times for the user.
255 */
256 private static final String SC_SET_AUTHENTICATION_FAILURE_TIMES =
257 "set-authentication-failure-times";
258
259
260
261 /**
262 * The name of the subcommand that will be used to clear the authentication
263 * failure times for the user.
264 */
265 private static final String SC_CLEAR_AUTHENTICATION_FAILURE_TIMES =
266 "clear-authentication-failure-times";
267
268
269
270 /**
271 * The name of the subcommand that will be used to get the length of time
272 * before the user's account is unlocked.
273 */
274 private static final String
275 SC_GET_SECONDS_UNTIL_AUTHENTICATION_FAILURE_UNLOCK =
276 "get-seconds-until-authentication-failure-unlock";
277
278
279
280 /**
281 * The name of the subcommand that will be used to get the number of remaining
282 * authentication failures for the user.
283 */
284 private static final String SC_GET_REMAINING_AUTHENTICATION_FAILURE_COUNT =
285 "get-remaining-authentication-failure-count";
286
287
288
289 /**
290 * The name of the subcommand that will be used to get the last login time for
291 * the user.
292 */
293 private static final String SC_GET_LAST_LOGIN_TIME =
294 "get-last-login-time";
295
296
297
298 /**
299 * The name of the subcommand that will be used to set the last login time for
300 * the user.
301 */
302 private static final String SC_SET_LAST_LOGIN_TIME =
303 "set-last-login-time";
304
305
306
307 /**
308 * The name of the subcommand that will be used to clear the last login time
309 * for the user.
310 */
311 private static final String SC_CLEAR_LAST_LOGIN_TIME =
312 "clear-last-login-time";
313
314
315
316 /**
317 * The name of the subcommand that will be used to get the length of time
318 * before the account is idle locked.
319 */
320 private static final String SC_GET_SECONDS_UNTIL_IDLE_LOCKOUT =
321 "get-seconds-until-idle-lockout";
322
323
324
325 /**
326 * The name of the subcommand that will be used to get the password reset
327 * state for a user.
328 */
329 private static final String SC_GET_PASSWORD_RESET_STATE =
330 "get-password-is-reset";
331
332
333
334 /**
335 * The name of the subcommand that will be used to set the password reset
336 * state for a user.
337 */
338 private static final String SC_SET_PASSWORD_RESET_STATE =
339 "set-password-is-reset";
340
341
342
343 /**
344 * The name of the subcommand that will be used to clear the password reset
345 * state for a user.
346 */
347 private static final String SC_CLEAR_PASSWORD_RESET_STATE =
348 "clear-password-is-reset";
349
350
351
352 /**
353 * The name of the subcommand that will be used to get the length of time
354 * before the password reset lockout occurs.
355 */
356 private static final String SC_GET_SECONDS_UNTIL_PASSWORD_RESET_LOCKOUT =
357 "get-seconds-until-password-reset-lockout";
358
359
360
361 /**
362 * The name of the subcommand that will be used to get the grace login use
363 * times for the user.
364 */
365 private static final String SC_GET_GRACE_LOGIN_USE_TIMES =
366 "get-grace-login-use-times";
367
368
369
370 /**
371 * The name of the subcommand that will be used to add a grace login use time
372 * for the user.
373 */
374 private static final String SC_ADD_GRACE_LOGIN_USE_TIME =
375 "add-grace-login-use-time";
376
377
378
379 /**
380 * The name of the subcommand that will be used to set the grace login use
381 * times for the user.
382 */
383 private static final String SC_SET_GRACE_LOGIN_USE_TIMES =
384 "set-grace-login-use-times";
385
386
387
388 /**
389 * The name of the subcommand that will be used to clear the grace login use
390 * times for the user.
391 */
392 private static final String SC_CLEAR_GRACE_LOGIN_USE_TIMES =
393 "clear-grace-login-use-times";
394
395
396
397 /**
398 * The name of the subcommand that will be used to get number of remaining
399 * grace logins for the user.
400 */
401 private static final String SC_GET_REMAINING_GRACE_LOGIN_COUNT =
402 "get-remaining-grace-login-count";
403
404
405
406 /**
407 * The name of the subcommand that will be used to get the password changed by
408 * required time for the user.
409 */
410 private static final String SC_GET_PASSWORD_CHANGED_BY_REQUIRED_TIME =
411 "get-password-changed-by-required-time";
412
413
414
415 /**
416 * The name of the subcommand that will be used to set the password changed by
417 * required time for the user.
418 */
419 private static final String SC_SET_PASSWORD_CHANGED_BY_REQUIRED_TIME =
420 "set-password-changed-by-required-time";
421
422
423
424 /**
425 * The name of the subcommand that will be used to clear the password changed
426 * by required time for the user.
427 */
428 private static final String SC_CLEAR_PASSWORD_CHANGED_BY_REQUIRED_TIME =
429 "clear-password-changed-by-required-time";
430
431
432
433 /**
434 * The name of the subcommand that will be used to get the length of time
435 * before the user is required to change his/her password due to the required
436 * change time.
437 */
438 private static final String SC_GET_SECONDS_UNTIL_REQUIRED_CHANGE_TIME =
439 "get-seconds-until-required-change-time";
440
441
442
443 /**
444 * The name of the subcommand that will be used to get the password history
445 * state values.
446 */
447 private static final String SC_GET_PASSWORD_HISTORY = "get-password-history";
448
449
450
451 /**
452 * The name of the subcommand that will be used to clear the password history
453 * state values.
454 */
455 private static final String SC_CLEAR_PASSWORD_HISTORY =
456 "clear-password-history";
457
458
459
460 /**
461 * The name of the argument that will be used for holding the value(s) to use
462 * for the target operation.
463 */
464 private static final String ARG_OP_VALUE = "opvalue";
465
466
467
468 /**
469 * The value that will be used when encoding a password policy state operation
470 * that should not have any values.
471 */
472 private static final String NO_VALUE = null;
473
474
475
476 // The LDAP reader used to read responses from the server.
477 private static LDAPReader ldapReader;
478
479 // The LDAP writer used to send requests to the server.
480 private static LDAPWriter ldapWriter;
481
482 // The counter that will be used for LDAP message IDs.
483 private static AtomicInteger nextMessageID;
484
485 // The connection to the server.
486 private static LDAPConnection connection;
487
488 // The print stream to use when writing messages to standard error.
489 private static PrintStream err;
490
491 // The print stream to use when writing messages to standard output.
492 private static PrintStream out;
493
494 // The DN of the user to target with the operation.
495 private static String targetDNString;
496
497 // The argument parser for this tool.
498 private static SubCommandArgumentParser argParser;
499
500
501
502 /**
503 * Parses the command-line arguments, connects to the server, and performs the
504 * appropriate processing.
505 *
506 * @param args The command-line arguments provided to this program.
507 */
508 public static void main(String[] args)
509 {
510 int returnCode = main(args, System.out, System.err);
511 if (returnCode != 0)
512 {
513 System.exit(filterExitCode(returnCode));
514 }
515 }
516
517
518
519 /**
520 * Parses the command-line arguments, connects to the server, and performs the
521 * appropriate processing.
522 *
523 * @param args The command-line arguments provided to this program.
524 * @param outStream The output stream to use for standard output, or
525 * {@code null} if standard output is not needed.
526 * @param errStream The output stream to use for standard error, or
527 * {@code null} if standard error is not needed.
528 *
529 * @return A result code indicating whether the processing was successful.
530 */
531 public static int main(String[] args, OutputStream outStream,
532 OutputStream errStream)
533 {
534 if (outStream == null)
535 {
536 out = NullOutputStream.printStream();
537 }
538 else
539 {
540 out = new PrintStream(outStream);
541 }
542
543 if (errStream == null)
544 {
545 err = NullOutputStream.printStream();
546 }
547 else
548 {
549 err = new PrintStream(errStream);
550 }
551
552
553
554
555 // Parse the command-line arguments provided to the program.
556 int result = parseArgsAndConnect(args);
557 if (result < 0)
558 {
559 // This should only happen if we're only displaying usage information or
560 // doing something else other than actually running the tool.
561 return LDAPResultCode.SUCCESS;
562 }
563 else if (result != LDAPResultCode.SUCCESS)
564 {
565 return result;
566 }
567
568
569 try
570 {
571 // Use the subcommand provided to figure out how to encode the request.
572 ArrayList<ASN1Element> opElements = new ArrayList<ASN1Element>(1);
573 result = processSubcommand(opElements);
574 if (result != LDAPResultCode.SUCCESS)
575 {
576 return result;
577 }
578
579
580 // Generate the extended request and send it to the server.
581 ArrayList<ASN1Element> valueElements = new ArrayList<ASN1Element>(2);
582 valueElements.add(new ASN1OctetString(targetDNString));
583 if (! opElements.isEmpty())
584 {
585 valueElements.add(new ASN1Sequence(opElements));
586 }
587 ASN1OctetString requestValue =
588 new ASN1OctetString(new ASN1Sequence(valueElements).encode());
589
590 ExtendedRequestProtocolOp extendedRequest =
591 new ExtendedRequestProtocolOp(OID_PASSWORD_POLICY_STATE_EXTOP,
592 requestValue);
593
594 LDAPMessage requestMessage =
595 new LDAPMessage(nextMessageID.getAndIncrement(), extendedRequest);
596
597 try
598 {
599 ldapWriter.writeMessage(requestMessage);
600 }
601 catch (Exception e)
602 {
603 Message message = ERR_PWPSTATE_CANNOT_SEND_REQUEST_EXTOP.get(
604 getExceptionMessage(e));
605 err.println(wrapText(message, MAX_LINE_WIDTH));
606 return LDAPResultCode.CLIENT_SIDE_SERVER_DOWN;
607 }
608
609
610 // Read the response from the server.
611 ArrayList<ASN1Element> responseOpElements;
612 try
613 {
614 LDAPMessage responseMessage = ldapReader.readMessage();
615 if (responseMessage == null)
616 {
617 Message message =
618 ERR_PWPSTATE_CONNECTION_CLOSED_READING_RESPONSE.get();
619 err.println(wrapText(message, MAX_LINE_WIDTH));
620 return LDAPResultCode.CLIENT_SIDE_SERVER_DOWN;
621 }
622
623 ExtendedResponseProtocolOp extendedResponse =
624 responseMessage.getExtendedResponseProtocolOp();
625
626 int resultCode = extendedResponse.getResultCode();
627 if (resultCode != LDAPResultCode.SUCCESS)
628 {
629 Message message =
630 ERR_PWPSTATE_REQUEST_FAILED.get(resultCode,
631 LDAPResultCode.toString(resultCode),
632 String.valueOf(extendedResponse.getErrorMessage()));
633 err.println(wrapText(message, MAX_LINE_WIDTH));
634 return resultCode;
635 }
636
637 ASN1Sequence valueSequence =
638 ASN1Sequence.decodeAsSequence(extendedResponse.getValue().value());
639 responseOpElements =
640 valueSequence.elements().get(1).decodeAsSequence().elements();
641 }
642 catch (Exception e)
643 {
644 Message message = ERR_PWPSTATE_CANNOT_DECODE_RESPONSE_MESSAGE.get(
645 getExceptionMessage(e));
646 err.println(wrapText(message, MAX_LINE_WIDTH));
647 return LDAPResultCode.CLIENT_SIDE_SERVER_DOWN;
648 }
649
650
651 // Get the response value and parse its individual elements.
652 for (ASN1Element opElement : responseOpElements)
653 {
654 int opType;
655 ArrayList<String> opValues;
656
657 try
658 {
659 ASN1Sequence opSequence = opElement.decodeAsSequence();
660 ArrayList<ASN1Element> elements = opSequence.elements();
661 opType = elements.get(0).decodeAsEnumerated().intValue();
662 opValues = new ArrayList<String>();
663 if (elements.size() == 2)
664 {
665 for (ASN1Element e : elements.get(1).decodeAsSequence().elements())
666 {
667 opValues.add(e.decodeAsOctetString().stringValue());
668 }
669 }
670 }
671 catch (Exception e)
672 {
673 Message message = ERR_PWPSTATE_CANNOT_DECODE_RESPONSE_OP.get(
674 getExceptionMessage(e));
675 err.println(wrapText(message, MAX_LINE_WIDTH));
676 continue;
677 }
678
679 switch (opType)
680 {
681 case OP_GET_PASSWORD_POLICY_DN:
682 Message message = INFO_PWPSTATE_LABEL_PASSWORD_POLICY_DN.get();
683 printLabelAndValues(message, opValues);
684 break;
685
686 case OP_GET_ACCOUNT_DISABLED_STATE:
687 message = INFO_PWPSTATE_LABEL_ACCOUNT_DISABLED_STATE.get();
688 printLabelAndValues(message, opValues);
689 break;
690
691 case OP_GET_ACCOUNT_EXPIRATION_TIME:
692 message = INFO_PWPSTATE_LABEL_ACCOUNT_EXPIRATION_TIME.get();
693 printLabelAndValues(message, opValues);
694 break;
695
696 case OP_GET_SECONDS_UNTIL_ACCOUNT_EXPIRATION:
697 message =
698 INFO_PWPSTATE_LABEL_SECONDS_UNTIL_ACCOUNT_EXPIRATION.get();
699 printLabelAndValues(message, opValues);
700 break;
701
702 case OP_GET_PASSWORD_CHANGED_TIME:
703 message = INFO_PWPSTATE_LABEL_PASSWORD_CHANGED_TIME.get();
704 printLabelAndValues(message, opValues);
705 break;
706
707 case OP_GET_PASSWORD_EXPIRATION_WARNED_TIME:
708 message = INFO_PWPSTATE_LABEL_PASSWORD_EXPIRATION_WARNED_TIME.get();
709 printLabelAndValues(message, opValues);
710 break;
711
712 case OP_GET_SECONDS_UNTIL_PASSWORD_EXPIRATION:
713 message =
714 INFO_PWPSTATE_LABEL_SECONDS_UNTIL_PASSWORD_EXPIRATION.get();
715 printLabelAndValues(message, opValues);
716 break;
717
718 case OP_GET_SECONDS_UNTIL_PASSWORD_EXPIRATION_WARNING:
719 message =
720 INFO_PWPSTATE_LABEL_SECONDS_UNTIL_PASSWORD_EXPIRATION_WARNING
721 .get();
722 printLabelAndValues(message, opValues);
723 break;
724
725 case OP_GET_AUTHENTICATION_FAILURE_TIMES:
726 message = INFO_PWPSTATE_LABEL_AUTH_FAILURE_TIMES.get();
727 printLabelAndValues(message, opValues);
728 break;
729
730 case OP_GET_SECONDS_UNTIL_AUTHENTICATION_FAILURE_UNLOCK:
731 message =
732 INFO_PWPSTATE_LABEL_SECONDS_UNTIL_AUTH_FAILURE_UNLOCK.get();
733 printLabelAndValues(message, opValues);
734 break;
735
736 case OP_GET_REMAINING_AUTHENTICATION_FAILURE_COUNT:
737 message = INFO_PWPSTATE_LABEL_REMAINING_AUTH_FAILURE_COUNT.get();
738 printLabelAndValues(message, opValues);
739 break;
740
741 case OP_GET_LAST_LOGIN_TIME:
742 message = INFO_PWPSTATE_LABEL_LAST_LOGIN_TIME.get();
743 printLabelAndValues(message, opValues);
744 break;
745
746 case OP_GET_SECONDS_UNTIL_IDLE_LOCKOUT:
747 message = INFO_PWPSTATE_LABEL_SECONDS_UNTIL_IDLE_LOCKOUT.get();
748 printLabelAndValues(message, opValues);
749 break;
750
751 case OP_GET_PASSWORD_RESET_STATE:
752 message = INFO_PWPSTATE_LABEL_PASSWORD_RESET_STATE.get();
753 printLabelAndValues(message, opValues);
754 break;
755
756 case OP_GET_SECONDS_UNTIL_PASSWORD_RESET_LOCKOUT:
757 message =
758 INFO_PWPSTATE_LABEL_SECONDS_UNTIL_PASSWORD_RESET_LOCKOUT
759 .get();
760 printLabelAndValues(message, opValues);
761 break;
762
763 case OP_GET_GRACE_LOGIN_USE_TIMES:
764 message = INFO_PWPSTATE_LABEL_GRACE_LOGIN_USE_TIMES.get();
765 printLabelAndValues(message, opValues);
766 break;
767
768 case OP_GET_REMAINING_GRACE_LOGIN_COUNT:
769 message = INFO_PWPSTATE_LABEL_REMAINING_GRACE_LOGIN_COUNT.get();
770 printLabelAndValues(message, opValues);
771 break;
772
773 case OP_GET_PASSWORD_CHANGED_BY_REQUIRED_TIME:
774 message =
775 INFO_PWPSTATE_LABEL_PASSWORD_CHANGED_BY_REQUIRED_TIME.get();
776 printLabelAndValues(message, opValues);
777 break;
778
779 case OP_GET_SECONDS_UNTIL_REQUIRED_CHANGE_TIME:
780 message =
781 INFO_PWPSTATE_LABEL_SECONDS_UNTIL_REQUIRED_CHANGE_TIME
782 .get();
783 printLabelAndValues(message, opValues);
784 break;
785
786 case OP_GET_PASSWORD_HISTORY:
787 message = INFO_PWPSTATE_LABEL_PASSWORD_HISTORY.get();
788 printLabelAndValues(message, opValues);
789 break;
790
791 default:
792 message = ERR_PWPSTATE_INVALID_RESPONSE_OP_TYPE.get(
793 String.valueOf(opType));
794 err.println(wrapText(message, MAX_LINE_WIDTH));
795 break;
796 }
797 }
798
799
800 // If we've gotten here, then everything completed successfully.
801 return 0;
802 }
803 finally
804 {
805 // Close the connection to the server if it's active.
806 if (connection != null)
807 {
808 connection.close(nextMessageID);
809 }
810 }
811 }
812
813
814
815 /**
816 * Initializes the argument parser for this tool, parses the provided
817 * arguments, and establishes a connection to the server.
818 *
819 * @return A result code that indicates the result of the processing. A
820 * value of zero indicates that all processing completed
821 * successfully. A value of -1 indicates that only the usage
822 * information was displayed and no further action is required.
823 */
824 private static int parseArgsAndConnect(String[] args)
825 {
826 argParser = new SubCommandArgumentParser(
827 CLASS_NAME, INFO_PWPSTATE_TOOL_DESCRIPTION.get(),
828 false);
829
830 BooleanArgument showUsage;
831 BooleanArgument trustAll;
832 BooleanArgument useSSL;
833 BooleanArgument useStartTLS;
834 FileBasedArgument bindPWFile;
835 FileBasedArgument keyStorePWFile;
836 FileBasedArgument trustStorePWFile;
837 IntegerArgument port;
838 StringArgument bindDN;
839 StringArgument bindPW;
840 StringArgument certNickname;
841 StringArgument host;
842 StringArgument keyStoreFile;
843 StringArgument keyStorePW;
844 StringArgument saslOption;
845 StringArgument targetDN;
846 StringArgument trustStoreFile;
847 StringArgument trustStorePW;
848
849 try
850 {
851 host = new StringArgument("host", OPTION_SHORT_HOST,
852 OPTION_LONG_HOST, false, false, true,
853 INFO_HOST_PLACEHOLDER.get(), "127.0.0.1", null,
854 INFO_PWPSTATE_DESCRIPTION_HOST.get());
855 argParser.addGlobalArgument(host);
856
857 port = new IntegerArgument(
858 "port", OPTION_SHORT_PORT,
859 OPTION_LONG_PORT, false, false, true,
860 INFO_PORT_PLACEHOLDER.get(), 389, null, true, 1,
861 true, 65535, INFO_PWPSTATE_DESCRIPTION_PORT.get());
862 argParser.addGlobalArgument(port);
863
864 useSSL = new BooleanArgument("usessl", OPTION_SHORT_USE_SSL,
865 OPTION_LONG_USE_SSL,
866 INFO_PWPSTATE_DESCRIPTION_USESSL.get());
867 argParser.addGlobalArgument(useSSL);
868
869 useStartTLS = new BooleanArgument(
870 "usestarttls", OPTION_SHORT_START_TLS,
871 OPTION_LONG_START_TLS,
872 INFO_PWPSTATE_DESCRIPTION_USESTARTTLS.get());
873 argParser.addGlobalArgument(useStartTLS);
874
875 bindDN = new StringArgument("binddn", OPTION_SHORT_BINDDN,
876 OPTION_LONG_BINDDN, false, false, true,
877 INFO_BINDDN_PLACEHOLDER.get(), null, null,
878 INFO_PWPSTATE_DESCRIPTION_BINDDN.get());
879 argParser.addGlobalArgument(bindDN);
880
881 bindPW = new StringArgument("bindpw", OPTION_SHORT_BINDPWD,
882 OPTION_LONG_BINDPWD, false, false,
883 true,
884 INFO_BINDPWD_PLACEHOLDER.get(), null, null,
885 INFO_PWPSTATE_DESCRIPTION_BINDPW.get());
886 argParser.addGlobalArgument(bindPW);
887
888 bindPWFile = new FileBasedArgument(
889 "bindpwfile",
890 OPTION_SHORT_BINDPWD_FILE,
891 OPTION_LONG_BINDPWD_FILE,
892 false, false,
893 INFO_BINDPWD_FILE_PLACEHOLDER.get(),
894 null, null,
895 INFO_PWPSTATE_DESCRIPTION_BINDPWFILE.get());
896 argParser.addGlobalArgument(bindPWFile);
897
898 targetDN = new StringArgument("targetdn", 'b', "targetDN", true, false,
899 true, INFO_TARGETDN_PLACEHOLDER.get(), null,
900 null,
901 INFO_PWPSTATE_DESCRIPTION_TARGETDN.get());
902 argParser.addGlobalArgument(targetDN);
903
904 saslOption = new StringArgument(
905 "sasloption", OPTION_SHORT_SASLOPTION,
906 OPTION_LONG_SASLOPTION, false,
907 true, true,
908 INFO_SASL_OPTION_PLACEHOLDER.get(), null, null,
909 INFO_PWPSTATE_DESCRIPTION_SASLOPTIONS.get());
910 argParser.addGlobalArgument(saslOption);
911
912 trustAll = new BooleanArgument("trustall", 'X', "trustAll",
913 INFO_PWPSTATE_DESCRIPTION_TRUST_ALL.get());
914 argParser.addGlobalArgument(trustAll);
915
916 keyStoreFile = new StringArgument("keystorefile",
917 OPTION_SHORT_KEYSTOREPATH,
918 OPTION_LONG_KEYSTOREPATH,
919 false, false, true,
920 INFO_KEYSTOREPATH_PLACEHOLDER.get(),
921 null, null,
922 INFO_PWPSTATE_DESCRIPTION_KSFILE.get());
923 argParser.addGlobalArgument(keyStoreFile);
924
925 keyStorePW = new StringArgument("keystorepw", OPTION_SHORT_KEYSTORE_PWD,
926 OPTION_LONG_KEYSTORE_PWD,
927 false, false, true,
928 INFO_KEYSTORE_PWD_PLACEHOLDER.get(),
929 null, null,
930 INFO_PWPSTATE_DESCRIPTION_KSPW.get());
931 argParser.addGlobalArgument(keyStorePW);
932
933 keyStorePWFile = new FileBasedArgument("keystorepwfile",
934 OPTION_SHORT_KEYSTORE_PWD_FILE,
935 OPTION_LONG_KEYSTORE_PWD_FILE, false, false,
936 INFO_KEYSTORE_PWD_FILE_PLACEHOLDER.get(), null,
937 null,
938 INFO_PWPSTATE_DESCRIPTION_KSPWFILE.get());
939 argParser.addGlobalArgument(keyStorePWFile);
940
941 certNickname = new StringArgument(
942 "certnickname", 'N', "certNickname",
943 false, false, true, INFO_NICKNAME_PLACEHOLDER.get(), null,
944 null, INFO_DESCRIPTION_CERT_NICKNAME.get());
945 argParser.addGlobalArgument(certNickname);
946
947 trustStoreFile = new StringArgument(
948 "truststorefile",
949 OPTION_SHORT_TRUSTSTOREPATH,
950 OPTION_LONG_TRUSTSTOREPATH,
951 false, false, true,
952 INFO_TRUSTSTOREPATH_PLACEHOLDER.get(),
953 null, null,
954 INFO_PWPSTATE_DESCRIPTION_TSFILE.get());
955 argParser.addGlobalArgument(trustStoreFile);
956
957 trustStorePW = new StringArgument(
958 "truststorepw", 'T',
959 OPTION_LONG_TRUSTSTORE_PWD,
960 false, false,
961 true, INFO_TRUSTSTORE_PWD_PLACEHOLDER.get(), null,
962 null, INFO_PWPSTATE_DESCRIPTION_TSPW.get());
963 argParser.addGlobalArgument(trustStorePW);
964
965 trustStorePWFile = new FileBasedArgument("truststorepwfile",
966 OPTION_SHORT_TRUSTSTORE_PWD_FILE,
967 OPTION_LONG_TRUSTSTORE_PWD_FILE,
968 false, false,
969 INFO_TRUSTSTORE_PWD_FILE_PLACEHOLDER.get(),
970 null, null,
971 INFO_PWPSTATE_DESCRIPTION_TSPWFILE.get());
972 argParser.addGlobalArgument(trustStorePWFile);
973
974 showUsage = new BooleanArgument(
975 "showusage", OPTION_SHORT_HELP,
976 OPTION_LONG_HELP,
977 INFO_PWPSTATE_DESCRIPTION_SHOWUSAGE.get());
978 argParser.addGlobalArgument(showUsage);
979 argParser.setUsageArgument(showUsage, out);
980
981
982 HashSet<String> booleanValues = new HashSet<String>(2);
983 booleanValues.add(INFO_MULTICHOICE_TRUE_VALUE.get().toString());
984 booleanValues.add(INFO_MULTICHOICE_FALSE_VALUE.get().toString());
985
986
987 Message msg = INFO_DESCRIPTION_PWPSTATE_GET_ALL.get();
988 new SubCommand(argParser, SC_GET_ALL, msg);
989
990 msg = INFO_DESCRIPTION_PWPSTATE_GET_PASSWORD_POLICY_DN.get();
991 new SubCommand(argParser, SC_GET_PASSWORD_POLICY_DN, msg);
992
993 msg = INFO_DESCRIPTION_PWPSTATE_GET_ACCOUNT_DISABLED_STATE.get();
994 new SubCommand(argParser, SC_GET_ACCOUNT_DISABLED_STATE, msg);
995
996 msg = INFO_DESCRIPTION_PWPSTATE_SET_ACCOUNT_DISABLED_STATE.get();
997 SubCommand sc = new SubCommand(argParser, SC_SET_ACCOUNT_DISABLED_STATE,
998 msg);
999 sc.addArgument(new MultiChoiceArgument(ARG_OP_VALUE, 'O',
1000 "operationValue", true, false, true,
1001 INFO_TRUE_FALSE_PLACEHOLDER.get(), null, null,
1002 booleanValues, false,
1003 INFO_DESCRIPTION_OPERATION_BOOLEAN_VALUE.get()));
1004
1005 msg = INFO_DESCRIPTION_PWPSTATE_CLEAR_ACCOUNT_DISABLED_STATE.get();
1006 new SubCommand(argParser, SC_CLEAR_ACCOUNT_DISABLED_STATE, msg);
1007
1008 msg = INFO_DESCRIPTION_PWPSTATE_GET_ACCOUNT_EXPIRATION_TIME.get();
1009 new SubCommand(argParser, SC_GET_ACCOUNT_EXPIRATION_TIME, msg);
1010
1011 msg = INFO_DESCRIPTION_PWPSTATE_SET_ACCOUNT_EXPIRATION_TIME.get();
1012 sc = new SubCommand(argParser, SC_SET_ACCOUNT_EXPIRATION_TIME, msg);
1013 sc.addArgument(new StringArgument(ARG_OP_VALUE, 'O', "operationValue",
1014 false, false, true, INFO_TIME_PLACEHOLDER.get(),
1015 null, null,
1016 INFO_DESCRIPTION_OPERATION_TIME_VALUE.get()));
1017 sc.setHidden(true);
1018
1019 msg = INFO_DESCRIPTION_PWPSTATE_CLEAR_ACCOUNT_EXPIRATION_TIME.get();
1020 sc = new SubCommand(argParser, SC_CLEAR_ACCOUNT_EXPIRATION_TIME, msg);
1021 sc.setHidden(true);
1022
1023 msg =
1024 INFO_DESCRIPTION_PWPSTATE_GET_SECONDS_UNTIL_ACCOUNT_EXPIRATION
1025 .get();
1026 new SubCommand(argParser,
1027 SC_GET_SECONDS_UNTIL_ACCOUNT_EXPIRATION,
1028 msg);
1029
1030 msg = INFO_DESCRIPTION_PWPSTATE_GET_PASSWORD_CHANGED_TIME.get();
1031 new SubCommand(argParser, SC_GET_PASSWORD_CHANGED_TIME, msg);
1032
1033 msg = INFO_DESCRIPTION_PWPSTATE_SET_PASSWORD_CHANGED_TIME.get();
1034 sc = new SubCommand(argParser, SC_SET_PASSWORD_CHANGED_TIME, msg);
1035 sc.addArgument(new StringArgument(ARG_OP_VALUE, 'O', "operationValue",
1036 false, false, true, INFO_TIME_PLACEHOLDER.get(),
1037 null, null,
1038 INFO_DESCRIPTION_OPERATION_TIME_VALUE.get()));
1039 sc.setHidden(true);
1040
1041 msg = INFO_DESCRIPTION_PWPSTATE_CLEAR_PASSWORD_CHANGED_TIME.get();
1042 sc = new SubCommand(argParser, SC_CLEAR_PASSWORD_CHANGED_TIME, msg);
1043 sc.setHidden(true);
1044
1045 msg = INFO_DESCRIPTION_PWPSTATE_GET_PASSWORD_EXPIRATION_WARNED_TIME
1046 .get();
1047 new SubCommand(argParser, SC_GET_PASSWORD_EXP_WARNED_TIME, msg);
1048
1049 msg = INFO_DESCRIPTION_PWPSTATE_SET_PASSWORD_EXPIRATION_WARNED_TIME
1050 .get();
1051 sc = new SubCommand(argParser, SC_SET_PASSWORD_EXP_WARNED_TIME, msg);
1052 sc.addArgument(new StringArgument(ARG_OP_VALUE, 'O', "operationValue",
1053 false, false, true, INFO_TIME_PLACEHOLDER.get(),
1054 null, null,
1055 INFO_DESCRIPTION_OPERATION_TIME_VALUE.get()));
1056 sc.setHidden(true);
1057
1058 msg = INFO_DESCRIPTION_PWPSTATE_CLEAR_PASSWORD_EXPIRATION_WARNED_TIME
1059 .get();
1060 sc = new SubCommand(argParser, SC_CLEAR_PASSWORD_EXP_WARNED_TIME, msg);
1061 sc.setHidden(true);
1062
1063 msg = INFO_DESCRIPTION_PWPSTATE_GET_SECONDS_UNTIL_PASSWORD_EXP.get();
1064 new SubCommand(argParser, SC_GET_SECONDS_UNTIL_PASSWORD_EXPIRATION,
1065 msg);
1066
1067 msg = INFO_DESCRIPTION_PWPSTATE_GET_SECONDS_UNTIL_PASSWORD_EXP_WARNING
1068 .get();
1069 new SubCommand(argParser,
1070 SC_GET_SECONDS_UNTIL_PASSWORD_EXPIRATION_WARNING, msg);
1071
1072 msg = INFO_DESCRIPTION_PWPSTATE_GET_AUTH_FAILURE_TIMES.get();
1073 new SubCommand(argParser, SC_GET_AUTHENTICATION_FAILURE_TIMES, msg);
1074
1075 msg = INFO_DESCRIPTION_PWPSTATE_ADD_AUTH_FAILURE_TIME.get();
1076 sc = new SubCommand(argParser, SC_ADD_AUTHENTICATION_FAILURE_TIME,
1077 msg);
1078 sc.addArgument(new StringArgument(ARG_OP_VALUE, 'O', "operationValue",
1079 false, true, true, INFO_TIME_PLACEHOLDER.get(),
1080 null, null,
1081 INFO_DESCRIPTION_OPERATION_TIME_VALUE.get()));
1082 sc.setHidden(true);
1083
1084 msg = INFO_DESCRIPTION_PWPSTATE_SET_AUTH_FAILURE_TIMES.get();
1085 sc = new SubCommand(argParser, SC_SET_AUTHENTICATION_FAILURE_TIMES,
1086 msg);
1087 sc.addArgument(new StringArgument(ARG_OP_VALUE, 'O', "operationValue",
1088 false, true, true, INFO_TIME_PLACEHOLDER.get(),
1089 null, null,
1090 INFO_DESCRIPTION_OPERATION_TIME_VALUES.get()));
1091 sc.setHidden(true);
1092
1093 msg = INFO_DESCRIPTION_PWPSTATE_CLEAR_AUTH_FAILURE_TIMES.get();
1094 sc = new SubCommand(argParser, SC_CLEAR_AUTHENTICATION_FAILURE_TIMES,
1095 msg);
1096 sc.setHidden(true);
1097
1098 msg = INFO_DESCRIPTION_PWPSTATE_GET_SECONDS_UNTIL_AUTH_FAILURE_UNLOCK
1099 .get();
1100 new SubCommand(argParser,
1101 SC_GET_SECONDS_UNTIL_AUTHENTICATION_FAILURE_UNLOCK,
1102 msg);
1103
1104 msg =
1105 INFO_DESCRIPTION_PWPSTATE_GET_REMAINING_AUTH_FAILURE_COUNT.get();
1106 new SubCommand(argParser, SC_GET_REMAINING_AUTHENTICATION_FAILURE_COUNT,
1107 msg);
1108
1109 msg = INFO_DESCRIPTION_PWPSTATE_GET_LAST_LOGIN_TIME.get();
1110 new SubCommand(argParser, SC_GET_LAST_LOGIN_TIME, msg);
1111
1112 msg = INFO_DESCRIPTION_PWPSTATE_SET_LAST_LOGIN_TIME.get();
1113 sc = new SubCommand(argParser, SC_SET_LAST_LOGIN_TIME, msg);
1114 sc.addArgument(new StringArgument(ARG_OP_VALUE, 'O', "operationValue",
1115 false, false, true, INFO_TIME_PLACEHOLDER.get(),
1116 null, null,
1117 INFO_DESCRIPTION_OPERATION_TIME_VALUE.get()));
1118 sc.setHidden(true);
1119
1120 msg = INFO_DESCRIPTION_PWPSTATE_CLEAR_LAST_LOGIN_TIME.get();
1121 sc = new SubCommand(argParser, SC_CLEAR_LAST_LOGIN_TIME, msg);
1122 sc.setHidden(true);
1123
1124 msg = INFO_DESCRIPTION_PWPSTATE_GET_SECONDS_UNTIL_IDLE_LOCKOUT.get();
1125 new SubCommand(argParser, SC_GET_SECONDS_UNTIL_IDLE_LOCKOUT, msg);
1126
1127 msg = INFO_DESCRIPTION_PWPSTATE_GET_PASSWORD_RESET_STATE.get();
1128 new SubCommand(argParser, SC_GET_PASSWORD_RESET_STATE, msg);
1129
1130 msg = INFO_DESCRIPTION_PWPSTATE_SET_PASSWORD_RESET_STATE.get();
1131 sc = new SubCommand(argParser, SC_SET_PASSWORD_RESET_STATE, msg);
1132 sc.addArgument(new MultiChoiceArgument(ARG_OP_VALUE, 'O',
1133 "operationValue", true, false, true,
1134 INFO_TRUE_FALSE_PLACEHOLDER.get(), null, null,
1135 booleanValues, false,
1136 INFO_DESCRIPTION_OPERATION_BOOLEAN_VALUE.get()));
1137 sc.setHidden(true);
1138
1139 msg = INFO_DESCRIPTION_PWPSTATE_CLEAR_PASSWORD_RESET_STATE.get();
1140 sc = new SubCommand(argParser, SC_CLEAR_PASSWORD_RESET_STATE, msg);
1141 sc.setHidden(true);
1142
1143 msg = INFO_DESCRIPTION_PWPSTATE_GET_SECONDS_UNTIL_RESET_LOCKOUT.get();
1144 new SubCommand(argParser, SC_GET_SECONDS_UNTIL_PASSWORD_RESET_LOCKOUT,
1145 msg);
1146
1147 msg = INFO_DESCRIPTION_PWPSTATE_GET_GRACE_LOGIN_USE_TIMES.get();
1148 new SubCommand(argParser, SC_GET_GRACE_LOGIN_USE_TIMES, msg);
1149
1150 msg = INFO_DESCRIPTION_PWPSTATE_ADD_GRACE_LOGIN_USE_TIME.get();
1151 sc = new SubCommand(argParser, SC_ADD_GRACE_LOGIN_USE_TIME, msg);
1152 sc.addArgument(new StringArgument(ARG_OP_VALUE, 'O', "operationValue",
1153 false, true, true, INFO_TIME_PLACEHOLDER.get(),
1154 null, null,
1155 INFO_DESCRIPTION_OPERATION_TIME_VALUE.get()));
1156 sc.setHidden(true);
1157
1158 msg = INFO_DESCRIPTION_PWPSTATE_SET_GRACE_LOGIN_USE_TIMES.get();
1159 sc = new SubCommand(argParser, SC_SET_GRACE_LOGIN_USE_TIMES, msg);
1160 sc.addArgument(new StringArgument(ARG_OP_VALUE, 'O', "operationValue",
1161 false, true, true, INFO_TIME_PLACEHOLDER.get(),
1162 null, null,
1163 INFO_DESCRIPTION_OPERATION_TIME_VALUES.get()));
1164 sc.setHidden(true);
1165
1166 msg = INFO_DESCRIPTION_PWPSTATE_CLEAR_GRACE_LOGIN_USE_TIMES.get();
1167 sc = new SubCommand(argParser, SC_CLEAR_GRACE_LOGIN_USE_TIMES, msg);
1168 sc.setHidden(true);
1169
1170 msg = INFO_DESCRIPTION_PWPSTATE_GET_REMAINING_GRACE_LOGIN_COUNT.get();
1171 new SubCommand(argParser, SC_GET_REMAINING_GRACE_LOGIN_COUNT,
1172 msg);
1173
1174 msg = INFO_DESCRIPTION_PWPSTATE_GET_PW_CHANGED_BY_REQUIRED_TIME.get();
1175 new SubCommand(argParser, SC_GET_PASSWORD_CHANGED_BY_REQUIRED_TIME,
1176 msg);
1177
1178 msg = INFO_DESCRIPTION_PWPSTATE_SET_PW_CHANGED_BY_REQUIRED_TIME.get();
1179 sc = new SubCommand(argParser, SC_SET_PASSWORD_CHANGED_BY_REQUIRED_TIME,
1180 msg);
1181 sc.addArgument(new StringArgument(ARG_OP_VALUE, 'O', "operationValue",
1182 false, false, true, INFO_TIME_PLACEHOLDER.get(),
1183 null, null,
1184 INFO_DESCRIPTION_OPERATION_TIME_VALUE.get()));
1185 sc.setHidden(true);
1186
1187 msg =
1188 INFO_DESCRIPTION_PWPSTATE_CLEAR_PW_CHANGED_BY_REQUIRED_TIME.get();
1189 sc = new SubCommand(argParser, SC_CLEAR_PASSWORD_CHANGED_BY_REQUIRED_TIME,
1190 msg);
1191 sc.setHidden(true);
1192
1193 msg =
1194 INFO_DESCRIPTION_PWPSTATE_GET_SECONDS_UNTIL_REQUIRED_CHANGE_TIME
1195 .get();
1196 new SubCommand(argParser, SC_GET_SECONDS_UNTIL_REQUIRED_CHANGE_TIME,
1197 msg);
1198
1199 msg = INFO_DESCRIPTION_PWPSTATE_GET_PASSWORD_HISTORY.get();
1200 new SubCommand(argParser, SC_GET_PASSWORD_HISTORY, msg);
1201
1202 msg = INFO_DESCRIPTION_PWPSTATE_CLEAR_PASSWORD_HISTORY.get();
1203 sc = new SubCommand(argParser, SC_CLEAR_PASSWORD_HISTORY, msg);
1204 sc.setHidden(true);
1205 }
1206 catch (ArgumentException ae)
1207 {
1208 Message message = ERR_CANNOT_INITIALIZE_ARGS.get(ae.getMessage());
1209
1210 err.println(wrapText(message, MAX_LINE_WIDTH));
1211 return LDAPResultCode.CLIENT_SIDE_LOCAL_ERROR;
1212 }
1213
1214 try
1215 {
1216 argParser.parseArguments(args);
1217 }
1218 catch (ArgumentException ae)
1219 {
1220 Message message = ERR_ERROR_PARSING_ARGS.get(ae.getMessage());
1221
1222 err.println(wrapText(message, MAX_LINE_WIDTH));
1223 err.println(argParser.getUsage());
1224 return LDAPResultCode.CLIENT_SIDE_PARAM_ERROR;
1225 }
1226
1227
1228 // If we should just display usage or version information,
1229 // then exit because it will have already been done.
1230 if (argParser.usageOrVersionDisplayed())
1231 {
1232 return -1;
1233 }
1234
1235
1236 // Get the target DN as a string for later use.
1237 targetDNString = targetDN.getValue();
1238
1239
1240 // Create the LDAP connection options object, which will be used to
1241 // customize the way that we connect to the server and specify a set of
1242 // basic defaults.
1243 LDAPConnectionOptions connectionOptions = new LDAPConnectionOptions();
1244 connectionOptions.setVersionNumber(3);
1245
1246
1247 // If both a bind password and bind password file were provided, then
1248 // return an error.
1249 if (bindPW.isPresent() && bindPWFile.isPresent())
1250 {
1251 Message message = ERR_PWPSTATE_MUTUALLY_EXCLUSIVE_ARGUMENTS.get(
1252 bindPW.getLongIdentifier(),
1253 bindPWFile.getLongIdentifier());
1254 err.println(wrapText(message, MAX_LINE_WIDTH));
1255 return LDAPResultCode.CLIENT_SIDE_PARAM_ERROR;
1256 }
1257
1258 // If both a key store password and key store password file were provided,
1259 // then return an error.
1260 if (keyStorePW.isPresent() && keyStorePWFile.isPresent())
1261 {
1262 Message message = ERR_PWPSTATE_MUTUALLY_EXCLUSIVE_ARGUMENTS.get(
1263 keyStorePW.getLongIdentifier(),
1264 keyStorePWFile.getLongIdentifier());
1265 err.println(wrapText(message, MAX_LINE_WIDTH));
1266 return LDAPResultCode.CLIENT_SIDE_PARAM_ERROR;
1267 }
1268
1269
1270 // If both a trust store password and trust store password file were
1271 // provided, then return an error.
1272 if (trustStorePW.isPresent() && trustStorePWFile.isPresent())
1273 {
1274 Message message = ERR_PWPSTATE_MUTUALLY_EXCLUSIVE_ARGUMENTS.get(
1275 trustStorePW.getLongIdentifier(),
1276 trustStorePWFile.getLongIdentifier());
1277 err.println(wrapText(message, MAX_LINE_WIDTH));
1278 return LDAPResultCode.CLIENT_SIDE_PARAM_ERROR;
1279 }
1280
1281 // See if we should use SSL or StartTLS when establishing the connection.
1282 // If so, then make sure only one of them was specified.
1283 if (useSSL.isPresent())
1284 {
1285 if (useStartTLS.isPresent())
1286 {
1287 Message message = ERR_PWPSTATE_MUTUALLY_EXCLUSIVE_ARGUMENTS.get(
1288 useSSL.getLongIdentifier(),
1289 useStartTLS.getLongIdentifier());
1290 err.println(wrapText(message, MAX_LINE_WIDTH));
1291 return LDAPResultCode.CLIENT_SIDE_PARAM_ERROR;
1292 }
1293 else
1294 {
1295 connectionOptions.setUseSSL(true);
1296 }
1297 }
1298 else if (useStartTLS.isPresent())
1299 {
1300 connectionOptions.setStartTLS(true);
1301 }
1302
1303
1304 // If we should blindly trust any certificate, then install the appropriate
1305 // SSL connection factory.
1306 if (useSSL.isPresent() || useStartTLS.isPresent())
1307 {
1308 try
1309 {
1310 String clientAlias;
1311 if (certNickname.isPresent())
1312 {
1313 clientAlias = certNickname.getValue();
1314 }
1315 else
1316 {
1317 clientAlias = null;
1318 }
1319
1320 SSLConnectionFactory sslConnectionFactory = new SSLConnectionFactory();
1321 sslConnectionFactory.init(trustAll.isPresent(), keyStoreFile.getValue(),
1322 keyStorePW.getValue(), clientAlias,
1323 trustStoreFile.getValue(),
1324 trustStorePW.getValue());
1325
1326 connectionOptions.setSSLConnectionFactory(sslConnectionFactory);
1327 }
1328 catch (SSLConnectionException sce)
1329 {
1330 Message message = ERR_PWPSTATE_CANNOT_INITIALIZE_SSL.get(
1331 sce.getMessage());
1332 err.println(wrapText(message, MAX_LINE_WIDTH));
1333 return LDAPResultCode.CLIENT_SIDE_LOCAL_ERROR;
1334 }
1335 }
1336
1337
1338 // If one or more SASL options were provided, then make sure that one of
1339 // them was "mech" and specified a valid SASL mechanism.
1340 if (saslOption.isPresent())
1341 {
1342 String mechanism = null;
1343 LinkedList<String> options = new LinkedList<String>();
1344
1345 for (String s : saslOption.getValues())
1346 {
1347 int equalPos = s.indexOf('=');
1348 if (equalPos <= 0)
1349 {
1350 Message message = ERR_PWPSTATE_CANNOT_PARSE_SASL_OPTION.get(s);
1351 err.println(wrapText(message, MAX_LINE_WIDTH));
1352 return LDAPResultCode.CLIENT_SIDE_PARAM_ERROR;
1353 }
1354 else
1355 {
1356 String name = s.substring(0, equalPos);
1357
1358 if (name.equalsIgnoreCase("mech"))
1359 {
1360 mechanism = s;
1361 }
1362 else
1363 {
1364 options.add(s);
1365 }
1366 }
1367 }
1368
1369 if (mechanism == null)
1370 {
1371 Message message = ERR_PWPSTATE_NO_SASL_MECHANISM.get();
1372 err.println(wrapText(message, MAX_LINE_WIDTH));
1373 return LDAPResultCode.CLIENT_SIDE_PARAM_ERROR;
1374 }
1375
1376 connectionOptions.setSASLMechanism(mechanism);
1377
1378 for (String option : options)
1379 {
1380 connectionOptions.addSASLProperty(option);
1381 }
1382 }
1383
1384
1385 // Attempt to connect and authenticate to the Directory Server.
1386 nextMessageID = new AtomicInteger(1);
1387 try
1388 {
1389 connection = new LDAPConnection(host.getValue(), port.getIntValue(),
1390 connectionOptions, out, err);
1391 connection.connectToHost(bindDN.getValue(),
1392 LDAPConnectionArgumentParser.getPasswordValue(bindPW, bindPWFile),
1393 nextMessageID);
1394 }
1395 catch (ArgumentException ae)
1396 {
1397 Message message = ERR_PWPSTATE_CANNOT_DETERMINE_PORT.get(
1398 port.getLongIdentifier(),
1399 ae.getMessage());
1400 err.println(wrapText(message, MAX_LINE_WIDTH));
1401 return LDAPResultCode.CLIENT_SIDE_PARAM_ERROR;
1402 }
1403 catch (LDAPConnectionException lce)
1404 {
1405 Message message = ERR_PWPSTATE_CANNOT_CONNECT.get(lce.getMessage());
1406 err.println(wrapText(message, MAX_LINE_WIDTH));
1407 return LDAPResultCode.CLIENT_SIDE_CONNECT_ERROR;
1408 }
1409
1410 ldapReader = connection.getLDAPReader();
1411 ldapWriter = connection.getLDAPWriter();
1412
1413 return LDAPResultCode.SUCCESS;
1414 }
1415
1416
1417
1418 /**
1419 * Processes the subcommand from the provided argument parser and appends the
1420 * appropriate operation elements to the given list.
1421 *
1422 * @param opElements A list into which the operation elements shouold be
1423 * placed.
1424 *
1425 * @return A result code indicating the results of the processing.
1426 */
1427 private static int processSubcommand(ArrayList<ASN1Element> opElements)
1428 {
1429 SubCommand subCommand = argParser.getSubCommand();
1430 if (subCommand == null)
1431 {
1432 Message message = ERR_PWPSTATE_NO_SUBCOMMAND.get();
1433 err.println(wrapText(message, MAX_LINE_WIDTH));
1434 err.println(argParser.getUsage());
1435 return LDAPResultCode.CLIENT_SIDE_PARAM_ERROR;
1436 }
1437
1438 String subCommandName = subCommand.getName();
1439 if (subCommandName.equals(SC_GET_ALL))
1440 {
1441 // The list should stay empty for this one.
1442 }
1443 else if (subCommandName.equals(SC_GET_PASSWORD_POLICY_DN))
1444 {
1445 opElements.add(encode(OP_GET_PASSWORD_POLICY_DN, NO_VALUE));
1446 }
1447 else if (subCommandName.equals(SC_GET_ACCOUNT_DISABLED_STATE))
1448 {
1449 opElements.add(encode(OP_GET_ACCOUNT_DISABLED_STATE, NO_VALUE));
1450 }
1451 else if (subCommandName.equals(SC_SET_ACCOUNT_DISABLED_STATE))
1452 {
1453 Argument a = subCommand.getArgumentForName(ARG_OP_VALUE);
1454 if ((a != null) && a.isPresent())
1455 {
1456 String valueStr = a.getValue();
1457 if (isTrueValue(valueStr))
1458 {
1459 opElements.add(encode(OP_SET_ACCOUNT_DISABLED_STATE, "true"));
1460 }
1461 else if (isFalseValue(valueStr))
1462 {
1463 opElements.add(encode(OP_SET_ACCOUNT_DISABLED_STATE, "false"));
1464 }
1465 else
1466 {
1467 Message message = ERR_PWPSTATE_INVALID_BOOLEAN_VALUE.get(valueStr);
1468 err.println(wrapText(message, MAX_LINE_WIDTH));
1469 return LDAPResultCode.CLIENT_SIDE_PARAM_ERROR;
1470 }
1471 }
1472 else
1473 {
1474 Message message = ERR_PWPSTATE_NO_BOOLEAN_VALUE.get();
1475 err.println(wrapText(message, MAX_LINE_WIDTH));
1476 return LDAPResultCode.CLIENT_SIDE_PARAM_ERROR;
1477 }
1478 }
1479 else if (subCommandName.equals(SC_CLEAR_ACCOUNT_DISABLED_STATE))
1480 {
1481 opElements.add(encode(OP_CLEAR_ACCOUNT_DISABLED_STATE, NO_VALUE));
1482 }
1483 else if (subCommandName.equals(SC_GET_ACCOUNT_EXPIRATION_TIME))
1484 {
1485 opElements.add(encode(OP_GET_ACCOUNT_EXPIRATION_TIME, NO_VALUE));
1486 }
1487 else if (subCommandName.equals(SC_SET_ACCOUNT_EXPIRATION_TIME))
1488 {
1489 Argument a = subCommand.getArgumentForName(ARG_OP_VALUE);
1490 if ((a != null) && a.isPresent())
1491 {
1492 opElements.add(encode(OP_SET_ACCOUNT_EXPIRATION_TIME, a.getValue()));
1493 }
1494 else
1495 {
1496 opElements.add(encode(OP_SET_ACCOUNT_EXPIRATION_TIME, NO_VALUE));
1497 }
1498 }
1499 else if (subCommandName.equals(SC_CLEAR_ACCOUNT_EXPIRATION_TIME))
1500 {
1501 opElements.add(encode(OP_CLEAR_ACCOUNT_EXPIRATION_TIME, NO_VALUE));
1502 }
1503 else if (subCommandName.equals(SC_GET_SECONDS_UNTIL_ACCOUNT_EXPIRATION))
1504 {
1505 opElements.add(encode(OP_GET_SECONDS_UNTIL_ACCOUNT_EXPIRATION, NO_VALUE));
1506 }
1507 else if (subCommandName.equals(SC_GET_PASSWORD_CHANGED_TIME))
1508 {
1509 opElements.add(encode(OP_GET_PASSWORD_CHANGED_TIME, NO_VALUE));
1510 }
1511 else if (subCommandName.equals(SC_SET_PASSWORD_CHANGED_TIME))
1512 {
1513 Argument a = subCommand.getArgumentForName(ARG_OP_VALUE);
1514 if ((a != null) && a.isPresent())
1515 {
1516 opElements.add(encode(OP_SET_PASSWORD_CHANGED_TIME, a.getValue()));
1517 }
1518 else
1519 {
1520 opElements.add(encode(OP_SET_PASSWORD_CHANGED_TIME, NO_VALUE));
1521 }
1522 }
1523 else if (subCommandName.equals(SC_CLEAR_PASSWORD_CHANGED_TIME))
1524 {
1525 opElements.add(encode(OP_CLEAR_PASSWORD_CHANGED_TIME, NO_VALUE));
1526 }
1527 else if(subCommandName.equals(SC_GET_PASSWORD_EXP_WARNED_TIME))
1528 {
1529 opElements.add(encode(OP_GET_PASSWORD_EXPIRATION_WARNED_TIME, NO_VALUE));
1530 }
1531 else if(subCommandName.equals(SC_SET_PASSWORD_EXP_WARNED_TIME))
1532 {
1533 Argument a = subCommand.getArgumentForName(ARG_OP_VALUE);
1534 if ((a != null) && a.isPresent())
1535 {
1536 opElements.add(encode(OP_SET_PASSWORD_EXPIRATION_WARNED_TIME,
1537 a.getValue()));
1538 }
1539 else
1540 {
1541 opElements.add(encode(OP_SET_PASSWORD_EXPIRATION_WARNED_TIME,
1542 NO_VALUE));
1543 }
1544 }
1545 else if(subCommandName.equals(SC_CLEAR_PASSWORD_EXP_WARNED_TIME))
1546 {
1547 opElements.add(encode(OP_CLEAR_PASSWORD_EXPIRATION_WARNED_TIME,
1548 NO_VALUE));
1549 }
1550 else if(subCommandName.equals(SC_GET_SECONDS_UNTIL_PASSWORD_EXPIRATION))
1551 {
1552 opElements.add(encode(OP_GET_SECONDS_UNTIL_PASSWORD_EXPIRATION,
1553 NO_VALUE));
1554 }
1555 else if(subCommandName.equals(
1556 SC_GET_SECONDS_UNTIL_PASSWORD_EXPIRATION_WARNING))
1557 {
1558 opElements.add(encode(OP_GET_SECONDS_UNTIL_PASSWORD_EXPIRATION_WARNING,
1559 NO_VALUE));
1560 }
1561 else if(subCommandName.equals(SC_GET_AUTHENTICATION_FAILURE_TIMES))
1562 {
1563 opElements.add(encode(OP_GET_AUTHENTICATION_FAILURE_TIMES, NO_VALUE));
1564 }
1565 else if(subCommandName.equals(SC_ADD_AUTHENTICATION_FAILURE_TIME))
1566 {
1567 Argument a = subCommand.getArgumentForName(ARG_OP_VALUE);
1568 if ((a != null) && a.isPresent())
1569 {
1570 opElements.add(encode(OP_ADD_AUTHENTICATION_FAILURE_TIME,
1571 a.getValue()));
1572 }
1573 else
1574 {
1575 opElements.add(encode(OP_ADD_AUTHENTICATION_FAILURE_TIME, NO_VALUE));
1576 }
1577 }
1578 else if(subCommandName.equals(SC_SET_AUTHENTICATION_FAILURE_TIMES))
1579 {
1580 Argument a = subCommand.getArgumentForName(ARG_OP_VALUE);
1581 if ((a != null) && a.isPresent())
1582 {
1583 ArrayList<String> valueList = new ArrayList<String>(a.getValues());
1584 String[] values = new String[valueList.size()];
1585 valueList.toArray(values);
1586
1587 opElements.add(encode(OP_SET_AUTHENTICATION_FAILURE_TIMES, values));
1588 }
1589 else
1590 {
1591 opElements.add(encode(OP_SET_AUTHENTICATION_FAILURE_TIMES, NO_VALUE));
1592 }
1593 }
1594 else if(subCommandName.equals(SC_CLEAR_AUTHENTICATION_FAILURE_TIMES))
1595 {
1596 opElements.add(encode(OP_CLEAR_AUTHENTICATION_FAILURE_TIMES, NO_VALUE));
1597 }
1598 else if(subCommandName.equals(
1599 SC_GET_SECONDS_UNTIL_AUTHENTICATION_FAILURE_UNLOCK))
1600 {
1601 opElements.add(encode(OP_GET_SECONDS_UNTIL_AUTHENTICATION_FAILURE_UNLOCK,
1602 NO_VALUE));
1603 }
1604 else if(subCommandName.equals(
1605 SC_GET_REMAINING_AUTHENTICATION_FAILURE_COUNT))
1606 {
1607 opElements.add(encode(OP_GET_REMAINING_AUTHENTICATION_FAILURE_COUNT,
1608 NO_VALUE));
1609 }
1610 else if(subCommandName.equals(SC_GET_LAST_LOGIN_TIME))
1611 {
1612 opElements.add(encode(OP_GET_LAST_LOGIN_TIME, NO_VALUE));
1613 }
1614 else if(subCommandName.equals(SC_SET_LAST_LOGIN_TIME))
1615 {
1616 Argument a = subCommand.getArgumentForName(ARG_OP_VALUE);
1617 if ((a != null) && a.isPresent())
1618 {
1619 opElements.add(encode(OP_SET_LAST_LOGIN_TIME, a.getValue()));
1620 }
1621 else
1622 {
1623 opElements.add(encode(OP_SET_LAST_LOGIN_TIME, NO_VALUE));
1624 }
1625 }
1626 else if(subCommandName.equals(SC_CLEAR_LAST_LOGIN_TIME))
1627 {
1628 opElements.add(encode(OP_CLEAR_LAST_LOGIN_TIME, NO_VALUE));
1629 }
1630 else if(subCommandName.equals(SC_GET_SECONDS_UNTIL_IDLE_LOCKOUT))
1631 {
1632 opElements.add(encode(OP_GET_SECONDS_UNTIL_IDLE_LOCKOUT, NO_VALUE));
1633 }
1634 else if(subCommandName.equals(SC_GET_PASSWORD_RESET_STATE))
1635 {
1636 opElements.add(encode(OP_GET_PASSWORD_RESET_STATE, NO_VALUE));
1637 }
1638 else if(subCommandName.equals(SC_SET_PASSWORD_RESET_STATE))
1639 {
1640 Argument a = subCommand.getArgumentForName(ARG_OP_VALUE);
1641 if ((a != null) && a.isPresent())
1642 {
1643 String valueStr = a.getValue();
1644 if (isTrueValue(valueStr))
1645 {
1646 opElements.add(encode(OP_SET_PASSWORD_RESET_STATE, "true"));
1647 }
1648 else if (isFalseValue(valueStr))
1649 {
1650 opElements.add(encode(OP_SET_PASSWORD_RESET_STATE, "false"));
1651 }
1652 else
1653 {
1654 Message message = ERR_PWPSTATE_INVALID_BOOLEAN_VALUE.get(valueStr);
1655 err.println(wrapText(message, MAX_LINE_WIDTH));
1656 return LDAPResultCode.CLIENT_SIDE_PARAM_ERROR;
1657 }
1658 }
1659 else
1660 {
1661 Message message = ERR_PWPSTATE_NO_BOOLEAN_VALUE.get();
1662 err.println(wrapText(message, MAX_LINE_WIDTH));
1663 return LDAPResultCode.CLIENT_SIDE_PARAM_ERROR;
1664 }
1665 }
1666 else if(subCommandName.equals(SC_CLEAR_PASSWORD_RESET_STATE))
1667 {
1668 opElements.add(encode(OP_GET_PASSWORD_RESET_STATE, NO_VALUE));
1669 }
1670 else if(subCommandName.equals(SC_GET_SECONDS_UNTIL_PASSWORD_RESET_LOCKOUT))
1671 {
1672 opElements.add(encode(OP_GET_SECONDS_UNTIL_PASSWORD_RESET_LOCKOUT,
1673 NO_VALUE));
1674 }
1675 else if(subCommandName.equals(SC_GET_GRACE_LOGIN_USE_TIMES))
1676 {
1677 opElements.add(encode(OP_GET_GRACE_LOGIN_USE_TIMES, NO_VALUE));
1678 }
1679 else if(subCommandName.equals(SC_ADD_GRACE_LOGIN_USE_TIME))
1680 {
1681 Argument a = subCommand.getArgumentForName(ARG_OP_VALUE);
1682 if ((a != null) && a.isPresent())
1683 {
1684 opElements.add(encode(OP_ADD_GRACE_LOGIN_USE_TIME, a.getValue()));
1685 }
1686 else
1687 {
1688 opElements.add(encode(OP_ADD_GRACE_LOGIN_USE_TIME, NO_VALUE));
1689 }
1690 }
1691 else if(subCommandName.equals(SC_SET_GRACE_LOGIN_USE_TIMES))
1692 {
1693 Argument a = subCommand.getArgumentForName(ARG_OP_VALUE);
1694 if ((a != null) && a.isPresent())
1695 {
1696 ArrayList<String> valueList = new ArrayList<String>(a.getValues());
1697 String[] values = new String[valueList.size()];
1698 valueList.toArray(values);
1699
1700 opElements.add(encode(OP_SET_GRACE_LOGIN_USE_TIMES, values));
1701 }
1702 else
1703 {
1704 opElements.add(encode(OP_SET_GRACE_LOGIN_USE_TIMES, NO_VALUE));
1705 }
1706 }
1707 else if(subCommandName.equals(SC_CLEAR_GRACE_LOGIN_USE_TIMES))
1708 {
1709 opElements.add(encode(OP_CLEAR_GRACE_LOGIN_USE_TIMES, NO_VALUE));
1710 }
1711 else if(subCommandName.equals(SC_GET_REMAINING_GRACE_LOGIN_COUNT))
1712 {
1713 opElements.add(encode(OP_GET_REMAINING_GRACE_LOGIN_COUNT, NO_VALUE));
1714 }
1715 else if(subCommandName.equals(SC_GET_PASSWORD_CHANGED_BY_REQUIRED_TIME))
1716 {
1717 opElements.add(encode(OP_GET_PASSWORD_CHANGED_BY_REQUIRED_TIME,
1718 NO_VALUE));
1719 }
1720 else if(subCommandName.equals(SC_SET_PASSWORD_CHANGED_BY_REQUIRED_TIME))
1721 {
1722 Argument a = subCommand.getArgumentForName(ARG_OP_VALUE);
1723 if ((a != null) && a.isPresent())
1724 {
1725 opElements.add(encode(OP_SET_PASSWORD_CHANGED_BY_REQUIRED_TIME,
1726 a.getValue()));
1727 }
1728 else
1729 {
1730 opElements.add(encode(OP_SET_PASSWORD_CHANGED_BY_REQUIRED_TIME,
1731 NO_VALUE));
1732 }
1733 }
1734 else if(subCommandName.equals(SC_CLEAR_PASSWORD_CHANGED_BY_REQUIRED_TIME))
1735 {
1736 opElements.add(encode(OP_CLEAR_PASSWORD_CHANGED_BY_REQUIRED_TIME,
1737 NO_VALUE));
1738 }
1739 else if(subCommandName.equals(SC_GET_SECONDS_UNTIL_REQUIRED_CHANGE_TIME))
1740 {
1741 opElements.add(encode(OP_GET_SECONDS_UNTIL_REQUIRED_CHANGE_TIME,
1742 NO_VALUE));
1743 }
1744 else if (subCommandName.equals(SC_GET_PASSWORD_HISTORY))
1745 {
1746 opElements.add(encode(OP_GET_PASSWORD_HISTORY, NO_VALUE));
1747 }
1748 else if (subCommandName.equals(SC_CLEAR_PASSWORD_HISTORY))
1749 {
1750 opElements.add(encode(OP_CLEAR_PASSWORD_HISTORY, NO_VALUE));
1751 }
1752 else
1753 {
1754 Message message = ERR_PWPSTATE_INVALID_SUBCOMMAND.get(subCommandName);
1755 err.println(wrapText(message, MAX_LINE_WIDTH));
1756 err.println(argParser.getUsage());
1757 return LDAPResultCode.CLIENT_SIDE_PARAM_ERROR;
1758 }
1759
1760 return LDAPResultCode.SUCCESS;
1761 }
1762
1763
1764
1765 /**
1766 * Prints information about a password policy state variable to standard
1767 * output.
1768 *
1769 * @param msg The message ID for the message to use as the label.
1770 * @param values The set of values for the associated state variable.
1771 */
1772 private static void printLabelAndValues(Message msg, ArrayList<String> values)
1773 {
1774 String label = String.valueOf(msg);
1775 if ((values == null) || values.isEmpty())
1776 {
1777 out.print(label);
1778 out.println(":");
1779 }
1780 else
1781 {
1782 for (String value : values)
1783 {
1784 out.print(label);
1785 out.print(": ");
1786 out.println(value);
1787 }
1788 }
1789 }
1790
1791 private static boolean isTrueValue(String value)
1792 {
1793 return INFO_MULTICHOICE_TRUE_VALUE.get().toString().equalsIgnoreCase(value);
1794 }
1795
1796 private static boolean isFalseValue(String value)
1797 {
1798 return INFO_MULTICHOICE_FALSE_VALUE.get().toString().equalsIgnoreCase(
1799 value);
1800 }
1801 }
1802