1 16 package com.sun.slamd.example; 17 18 19 20 import java.io.*; 21 import java.security.*; 22 import java.util.*; 23 import netscape.ldap.*; 24 import netscape.ldap.factory.*; 25 import com.sun.slamd.job.*; 26 import com.sun.slamd.parameter.*; 27 import com.sun.slamd.stat.*; 28 29 30 31 41 public class DigestMD5AuthRateJobClass 42 extends JobClass 43 { 44 47 public static final int MEMBERSHIP_TYPE_NONE = 0; 48 49 50 51 55 public static final int MEMBERSHIP_TYPE_STATIC = 1; 56 57 58 59 63 public static final int MEMBERSHIP_TYPE_DYNAMIC = 2; 64 65 66 67 71 public static final int MEMBERSHIP_TYPE_ROLE = 3; 72 73 74 75 78 public static final String DEFAULT_LOG_ID_ATTR = "uid"; 79 80 81 82 86 public static final String ROLE_ATTR = "nsRole"; 87 88 89 90 93 public static final String SSL_KEY_STORE_PROPERTY = 94 "javax.net.ssl.keyStore"; 95 96 97 98 101 public static final String SSL_KEY_PASSWORD_PROPERTY = 102 "javax.net.ssl.keyStorePassword"; 103 104 105 106 109 public static final String SSL_TRUST_STORE_PROPERTY = 110 "javax.net.ssl.trustStore"; 111 112 113 114 117 public static final String SSL_TRUST_PASSWORD_PROPERTY = 118 "javax.net.ssl.trustStorePassword"; 119 120 121 122 126 public static final String STAT_TRACKER_AUTHENTICATION_ATTEMPTS = 127 "Authentication Attempts"; 128 129 130 131 132 136 public static final String STAT_TRACKER_AUTHENTICATION_TIME = 137 "Authentication Time"; 138 139 140 141 142 146 public static final String STAT_TRACKER_FAILED_AUTHENTICATIONS = 147 "Failed Authentications"; 148 149 150 151 155 public static final String STAT_TRACKER_SUCCESSFUL_AUTHENTICATIONS = 156 "Successful Authentications"; 157 158 159 160 164 public static final String [] NO_ATTRS = new String [] { "1.1" }; 165 166 167 168 static boolean blindTrust; 170 171 static boolean ignoreInvalidCredentials; 174 175 static boolean useDataFile; 178 179 static boolean useLoginIDRange; 181 182 static boolean useSequential; 184 185 static boolean useSSL; 187 188 static boolean useSharedConnections; 191 192 static int coolDownTime; 194 195 static int directoryPort; 197 198 static int loginIDMax; 200 201 static int loginIDMin; 203 204 static int loginIDSpan; 206 207 static int membershipType; 209 210 static int sequentialCounter; 212 213 static int timeLimit; 216 217 static int warmUpTime; 219 220 static long delay; 222 223 static LDAPConnection sharedAuthConnection; 225 226 static Random parentRandom; 229 230 static String bindDN; 233 234 static String bindPW; 236 237 static String directoryHost; 239 240 static String loginIDAttr; 243 244 static String loginIDFinal; 246 247 static String loginIDInitial; 249 250 static String loginPassword; 252 253 static String membershipDN; 255 256 static String membershipURLBase; 258 259 static String membershipURLFilter; 261 262 static String searchBase; 265 266 static String sslKeyStore; 268 269 static String sslKeyPassword; 271 272 static String sslTrustStore; 274 275 static String sslTrustPassword; 277 278 static String [] loginIDs; 280 281 static String [] loginPasswords; 283 284 285 286 BooleanParameter blindTrustParameter = 288 new BooleanParameter("blind_trust", "Blindly Trust Any Certificate", 289 "Indicates whether the client should blindly trust " + 290 "any certificate presented by the server, or " + 291 "whether the key and trust stores should be used.", 292 true); 293 294 BooleanParameter ignoreInvCredParameter = 297 new BooleanParameter("ignore_49", "Ignore Invalid Credentials Errors", 298 "Indicates whether bind failures because of " + 299 "invalid credentials (err=49). This makes it " + 300 "possible to use this job without actually " + 301 "know user passwords.", false); 302 303 BooleanParameter shareConnsParameter = 305 new BooleanParameter("share_conns", "Share Connections between Threads", 306 "Indicates whether the connections to the " + 307 "directory server will be shared between threads " + 308 "or if each client thread will have its own " + 309 "connections.", true); 310 311 BooleanParameter useSSLParameter = 313 new BooleanParameter("usessl", "Use SSL", 314 "Indicates whether SSL should be used for all " + 315 "communication with the directory server", false); 316 317 FileURLParameter loginDataFileParameter = 319 new FileURLParameter("login_data_file", "Login Data File URL", 320 "The URL (FILE or HTTP) of the file containing " + 321 "the login IDs and passwords to use for the " + 322 "authentication.", null, false); 323 324 IntegerParameter coolDownParameter = 326 new IntegerParameter("cool_down", "Cool Down Time", 327 "The time in seconds that the job should " + 328 "continue searching after ending statistics " + 329 "collection.", true, 0, true, 0, false, 0); 330 331 IntegerParameter delayParameter = 334 new IntegerParameter("delay", "Time Between Authentications (ms)", 335 "Specifies the length of time in milliseconds " + 336 "each thread should wait between authentication " + 337 "attempts. Note that this delay will be " + 338 "between the starts of consecutive attempts and " + 339 "not between the end of one attempt and the " + 340 "beginning of the next. If an authentication " + 341 "takes longer than this length of time, then " + 342 "there will be no delay.", true, 0, true, 0, false, 343 0); 344 345 IntegerParameter portParameter = 347 new IntegerParameter("ldap_port", "Directory Server Port", 348 "The port number for the directory server.", true, 349 389, true, 1, true, 65535); 350 351 IntegerParameter timeLimitParameter = 354 new IntegerParameter("time_limit", "Operation Time Limit", 355 "The maximum length of time in seconds that any " + 356 "single LDAP operation will be allowed to take " + 357 "before it is cancelled.", true, 0, true, 0, false, 358 0); 359 360 IntegerParameter warmUpParameter = 362 new IntegerParameter("warm_up", "Warm Up Time", 363 "The time in seconds that the job should " + 364 "search before beginning statistics collection.", 365 true, 0, true, 0, false, 0); 366 367 PasswordParameter bindPWParameter = 369 new PasswordParameter("bindpw", "Directory Bind Password", 370 "The password to use when binding to the " + 371 "directory server to perform search and modify " + 372 "operations.", false, ""); 373 374 PasswordParameter loginPasswordParameter = 377 new PasswordParameter("login_id_pw", "Login Password", 378 "The password to use when authenticating to the " + 379 "directory for user authentications.", false, ""); 380 381 PasswordParameter keyPWParameter = 383 new PasswordParameter("sslkeypw", "SSL Key Store Password", 384 "The password for the JSSE key store", false, ""); 385 386 PasswordParameter trustPWParameter = 388 new PasswordParameter("ssltrustpw", "SSL Trust Store Password", 389 "The password for the JSSE trust store", false, ""); 390 391 PlaceholderParameter placeholder = new PlaceholderParameter(); 393 394 StringParameter bindDNParameter = 396 new StringParameter("binddn", "Directory Bind DN", 397 "The DN to use when binding to the directory " + 398 "server to perform search and modify operations.", 399 false, ""); 400 401 StringParameter hostParameter = 403 new StringParameter("ldap_host", "Directory Server Address", 404 "The address for the directory server.", true, ""); 405 406 StringParameter keyStoreParameter = 408 new StringParameter("sslkeystore", "SSL Key Store", 409 "The path to the JSSE key store to use for an " + 410 "SSL-based connection", false, ""); 411 412 StringParameter loginIDParameter = 414 new StringParameter("login_id_attr", "Login ID Attribute", 415 "The attribute to use as the login ID to find the " + 416 "user's entry.", true, DEFAULT_LOG_ID_ATTR); 417 418 StringParameter loginIDValueParameter = 420 new StringParameter("login_id_value", "Login ID Value", 421 "The text to use as the value of the login ID " + 422 "attribute in search filters. The value may " + 423 "contain a range of numbers in square brackets.", 424 false, ""); 425 426 StringParameter membershipDNParameter = 429 new StringParameter("membership_dn", "Membership DN", 430 "The DN of a static group, dynamic group, or role " + 431 "for which to determine whether the user is a " + 432 "member.", false, ""); 433 434 StringParameter searchBaseParameter = 436 new StringParameter("search_base", "User Search Base", 437 "The DN in the directory server under which user " + 438 "entries may be found.", true, ""); 439 440 StringParameter trustStoreParameter = 442 new StringParameter("ssltruststore", "SSL Trust Store", 443 "The path to the JSSE trust store to use for an " + 444 "SSL-based connection", false, ""); 445 446 IncrementalTracker attemptCounter; 448 449 IncrementalTracker failureCounter; 451 452 IncrementalTracker successCounter; 454 455 LDAPConnection authConnection; 458 459 LDAPConnection bindConnection; 461 462 LDAPConstraints authConstraints; 464 465 LDAPDigestMD5SocketFactory socketFactory; 467 468 LDAPSearchConstraints authSearchConstraints; 470 471 Random random; 473 474 TimeTracker authTimer; 476 477 478 479 483 public DigestMD5AuthRateJobClass() 484 { 485 super(); 486 } 487 488 489 490 496 public String getJobName() 497 { 498 return "LDAP DIGEST-MD5 Auth Rate"; 499 } 500 501 502 503 509 public String getJobDescription() 510 { 511 return "This job performs repeated DIGEST-MD5 authentications against an " + 512 "LDAP directory server, optionally including a lookup to verify that " + 513 "the user is a member of an indicated group or role."; 514 } 515 516 517 518 524 public String getJobCategoryName() 525 { 526 return "LDAP"; 527 } 528 529 530 531 536 public ParameterList getParameterStubs() 537 { 538 Parameter[] parameterArray = new Parameter[] 539 { 540 placeholder, 541 hostParameter, 542 portParameter, 543 bindDNParameter, 544 bindPWParameter, 545 placeholder, 546 searchBaseParameter, 547 loginDataFileParameter, 548 loginIDValueParameter, 549 loginPasswordParameter, 550 loginIDParameter, 551 membershipDNParameter, 552 placeholder, 553 warmUpParameter, 554 coolDownParameter, 555 timeLimitParameter, 556 delayParameter, 557 placeholder, 558 useSSLParameter, 559 blindTrustParameter, 560 keyStoreParameter, 561 keyPWParameter, 562 trustStoreParameter, 563 trustPWParameter, 564 ignoreInvCredParameter, 565 shareConnsParameter 566 }; 567 568 return new ParameterList(parameterArray); 569 } 570 571 572 573 595 public StatTracker[] getStatTrackerStubs(String clientID, String threadID, 596 int collectionInterval) 597 { 598 return new StatTracker[] 599 { 600 new IncrementalTracker(clientID, threadID, 601 STAT_TRACKER_AUTHENTICATION_ATTEMPTS, 602 collectionInterval), 603 new IncrementalTracker(clientID, threadID, 604 STAT_TRACKER_SUCCESSFUL_AUTHENTICATIONS, 605 collectionInterval), 606 new IncrementalTracker(clientID, threadID, 607 STAT_TRACKER_FAILED_AUTHENTICATIONS, 608 collectionInterval), 609 new TimeTracker(clientID, threadID, STAT_TRACKER_AUTHENTICATION_TIME, 610 collectionInterval) 611 }; 612 } 613 614 615 616 621 public StatTracker[] getStatTrackers() 622 { 623 return new StatTracker[] 624 { 625 attemptCounter, 626 successCounter, 627 failureCounter, 628 authTimer 629 }; 630 } 631 632 633 634 656 public void validateJobInfo(int numClients, int threadsPerClient, 657 int threadStartupDelay, Date startTime, 658 Date stopTime, int duration, 659 int collectionInterval, ParameterList parameters) 660 throws InvalidValueException 661 { 662 FileURLParameter loginDataURLParameter = 663 parameters.getFileURLParameter(loginDataFileParameter.getName()); 664 if ((loginDataURLParameter == null) || 665 (! loginDataURLParameter.hasValue())) 666 { 667 StringParameter loginValueParameter = 668 parameters.getStringParameter(loginIDValueParameter.getName()); 669 PasswordParameter loginPWParameter = 670 parameters.getPasswordParameter(loginPasswordParameter.getName()); 671 672 if ((loginValueParameter == null) || 673 (! loginValueParameter.hasValue()) || 674 (loginPWParameter == null) || 675 (! loginPWParameter.hasValue())) 676 { 677 throw new InvalidValueException("You must specify either a login " + 678 "data file URL or a login ID value " + 679 "and password"); 680 } 681 } 682 } 683 684 685 686 694 public boolean providesParameterTest() 695 { 696 return true; 697 } 698 699 700 701 728 public boolean testJobParameters(ParameterList parameters, 729 ArrayList outputMessages) 730 { 731 StringParameter hostParam = 733 parameters.getStringParameter(hostParameter.getName()); 734 if ((hostParam == null) || (! hostParam.hasValue())) 735 { 736 outputMessages.add("ERROR: No directory server address was provided."); 737 return false; 738 } 739 String host = hostParam.getStringValue(); 740 741 742 IntegerParameter portParam = 743 parameters.getIntegerParameter(portParameter.getName()); 744 if ((portParam == null) || (! hostParam.hasValue())) 745 { 746 outputMessages.add("ERROR: No directory server port was provided."); 747 return false; 748 } 749 int port = portParam.getIntValue(); 750 751 752 boolean useSSL = false; 753 BooleanParameter useSSLParam = 754 parameters.getBooleanParameter(useSSLParameter.getName()); 755 if (useSSLParam != null) 756 { 757 useSSL = useSSLParam.getBooleanValue(); 758 } 759 760 761 boolean blindTrust = true; 762 BooleanParameter blindTrustParam = 763 parameters.getBooleanParameter(blindTrustParameter.getName()); 764 if (blindTrustParam != null) 765 { 766 blindTrust = blindTrustParam.getBooleanValue(); 767 } 768 769 770 String keyStore = null; 771 StringParameter keyStoreParam = 772 parameters.getStringParameter(keyStoreParameter.getName()); 773 if ((keyStoreParam != null) && keyStoreParam.hasValue()) 774 { 775 keyStore = keyStoreParam.getStringValue(); 776 File keyStoreFile = new File(keyStore); 777 if (useSSL && (! blindTrust) && (! keyStoreFile.exists())) 778 { 779 outputMessages.add("WARNING: Key store file \"" + keyStore + 780 "\" not found on SLAMD server system. This test " + 781 "will blindly trust any SSL certificate " + 782 "presented by the directory server."); 783 outputMessages.add(""); 784 blindTrust = true; 785 } 786 else 787 { 788 System.setProperty(SSL_KEY_STORE_PROPERTY, keyStore); 789 } 790 } 791 792 793 String keyStorePassword = ""; 794 StringParameter keyPassParam = 795 parameters.getStringParameter(keyPWParameter.getName()); 796 if ((keyPassParam != null) && keyPassParam.hasValue()) 797 { 798 keyStorePassword = keyPassParam.getStringValue(); 799 System.setProperty(SSL_KEY_PASSWORD_PROPERTY, keyStorePassword); 800 } 801 802 803 String trustStore = null; 804 StringParameter trustStoreParam = 805 parameters.getStringParameter(trustStoreParameter.getName()); 806 if ((trustStoreParam != null) && trustStoreParam.hasValue()) 807 { 808 trustStore = trustStoreParam.getStringValue(); 809 File trustStoreFile = new File(trustStore); 810 if (useSSL && (! blindTrust) && (! trustStoreFile.exists())) 811 { 812 outputMessages.add("WARNING: trust store file \"" + trustStore + 813 "\" not found on SLAMD server system. This test " + 814 "will blindly trust any SSL certificate " + 815 "presented by the directory server."); 816 outputMessages.add(""); 817 blindTrust = true; 818 } 819 else 820 { 821 System.setProperty(SSL_TRUST_STORE_PROPERTY, trustStore); 822 } 823 } 824 825 826 String trustStorePassword = ""; 827 StringParameter trustPassParam = 828 parameters.getStringParameter(trustPWParameter.getName()); 829 if ((trustPassParam != null) && trustPassParam.hasValue()) 830 { 831 trustStorePassword = trustPassParam.getStringValue(); 832 System.setProperty(SSL_TRUST_PASSWORD_PROPERTY, trustStorePassword); 833 } 834 835 836 String bindDN = ""; 837 StringParameter bindDNParam = 838 parameters.getStringParameter(bindDNParameter.getName()); 839 if ((bindDNParam != null) && bindDNParam.hasValue()) 840 { 841 bindDN = bindDNParam.getStringValue(); 842 } 843 844 845 String bindPassword = ""; 846 PasswordParameter bindPWParam = 847 parameters.getPasswordParameter(bindPWParameter.getName()); 848 if ((bindPWParam != null) && bindPWParam.hasValue()) 849 { 850 bindPassword = bindPWParam.getStringValue(); 851 } 852 853 854 StringParameter baseDNParam = 855 parameters.getStringParameter(searchBaseParameter.getName()); 856 if ((baseDNParam == null) || (! baseDNParam.hasValue())) 857 { 858 outputMessages.add("ERROR: No base DN was provided."); 859 return false; 860 } 861 String baseDN = baseDNParam.getStringValue(); 862 863 864 LDAPConnection conn; 867 if (useSSL) 868 { 869 if (blindTrust) 870 { 871 try 872 { 873 conn = new LDAPConnection(new JSSEBlindTrustSocketFactory()); 874 } 875 catch (Exception e) 876 { 877 outputMessages.add("ERROR: Unable to instantiate the blind trust " + 878 "socket factory for use in creating the SSL " + 879 "connection: " + stackTraceToString(e)); 880 return false; 881 } 882 } 883 else 884 { 885 conn = new LDAPConnection(new JSSESocketFactory(null)); 886 } 887 } 888 else 889 { 890 conn = new LDAPConnection(); 891 } 892 893 894 try 896 { 897 if (useSSL) 898 { 899 outputMessages.add("Attempting to establish an SSL-based connection " + 900 "to " + host + ":" + port + "...."); 901 } 902 else 903 { 904 outputMessages.add("Attempting to establish a connection to " + host + 905 ":" + port + "...."); 906 } 907 conn.connect(host, port); 908 outputMessages.add("Connected successfully."); 909 outputMessages.add(""); 910 } 911 catch (Exception e) 912 { 913 outputMessages.add("ERROR: Unable to connect to the directory " + 914 "server: " + stackTraceToString(e)); 915 return false; 916 } 917 918 919 try 921 { 922 outputMessages.add("Attempting to perform an LDAPv3 bind to the " + 923 "directory server with a DN of '" + bindDN + "'...."); 924 conn.bind(3, bindDN, bindPassword); 925 outputMessages.add("Bound successfully."); 926 outputMessages.add(""); 927 } 928 catch (Exception e) 929 { 930 try 931 { 932 conn.disconnect(); 933 } catch (Exception e2) {} 934 935 outputMessages.add("ERROR: Unable to bind to the directory server: " + 936 stackTraceToString(e)); 937 return false; 938 } 939 940 941 try 943 { 944 outputMessages.add("Checking to make sure that the base DN entry '" + 945 baseDN + "' exists in the directory...."); 946 LDAPEntry baseDNEntry = conn.read(baseDN, new String [] { "1.1" }); 947 if (baseDNEntry == null) 948 { 949 try 950 { 951 conn.disconnect(); 952 } catch (Exception e2) {} 953 954 outputMessages.add("ERROR: Unable to retrieve the base DN entry."); 955 return false; 956 } 957 else 958 { 959 outputMessages.add("Successfully read the base DN entry."); 960 outputMessages.add(""); 961 } 962 } 963 catch (Exception e) 964 { 965 try 966 { 967 conn.disconnect(); 968 } catch (Exception e2) {} 969 970 outputMessages.add("ERROR: Unable to retrieve the base DN entry: " + 971 stackTraceToString(e)); 972 return false; 973 } 974 975 976 try 979 { 980 conn.disconnect(); 981 } catch (Exception e) {} 982 983 outputMessages.add("All tests completed successfully."); 984 return true; 985 } 986 987 988 989 1001 public void initializeClient(String clientID, ParameterList parameters) 1002 throws UnableToRunException 1003 { 1004 hostParameter = parameters.getStringParameter(hostParameter.getName()); 1006 if (hostParameter == null) 1007 { 1008 throw new UnableToRunException("No directory server host provided."); 1009 } 1010 else 1011 { 1012 directoryHost = hostParameter.getStringValue(); 1013 } 1014 1015 1016 portParameter = parameters.getIntegerParameter(portParameter.getName()); 1018 if (portParameter != null) 1019 { 1020 directoryPort = portParameter.getIntValue(); 1021 } 1022 1023 bindDNParameter = parameters.getStringParameter(bindDNParameter.getName()); 1025 if (bindDNParameter == null) 1026 { 1027 bindDN = ""; 1028 } 1029 else 1030 { 1031 bindDN = bindDNParameter.getStringValue(); 1032 } 1033 1034 bindPWParameter = 1036 parameters.getPasswordParameter(bindPWParameter.getName()); 1037 if (bindPWParameter == null) 1038 { 1039 bindPW = ""; 1040 } 1041 else 1042 { 1043 bindPW = bindPWParameter.getStringValue(); 1044 } 1045 1046 searchBaseParameter = 1048 parameters.getStringParameter(searchBaseParameter.getName()); 1049 if (searchBaseParameter != null) 1050 { 1051 searchBase = searchBaseParameter.getStringValue(); 1052 } 1053 1054 1055 useDataFile = false; 1057 loginDataFileParameter = 1058 parameters.getFileURLParameter(loginDataFileParameter.getName()); 1059 if ((loginDataFileParameter != null) && (loginDataFileParameter.hasValue())) 1060 { 1061 String [] fileLines; 1062 try 1063 { 1064 fileLines = loginDataFileParameter.getNonBlankFileLines(); 1065 } 1066 catch (Exception e) 1067 { 1068 throw new UnableToRunException("Unable to retrieve the login data " + 1069 "from the file: " + e, e); 1070 } 1071 1072 ArrayList loginIDList = new ArrayList(fileLines.length); 1074 ArrayList passwordList = new ArrayList(fileLines.length); 1075 for (int i=0; i < fileLines.length; i++) 1076 { 1077 try 1078 { 1079 StringTokenizer tokenizer = new StringTokenizer(fileLines[i], "\t"); 1080 String loginID = tokenizer.nextToken(); 1081 String password = tokenizer.nextToken(); 1082 loginIDList.add(loginID); 1083 passwordList.add(password); 1084 } catch (Exception e) {} 1085 } 1086 1087 loginIDs = new String [loginIDList.size()]; 1090 loginPasswords = new String [passwordList.size()]; 1091 loginIDList.toArray(loginIDs); 1092 passwordList.toArray(loginPasswords); 1093 if (loginIDs.length == 0) 1094 { 1095 throw new UnableToRunException("No login IDs/passwords extracted from " + 1096 "the login data file."); 1097 } 1098 1099 useDataFile = true; 1100 } 1101 else 1102 { 1103 loginPasswordParameter = 1104 parameters.getPasswordParameter(loginPasswordParameter.getName()); 1105 if ((loginPasswordParameter != null) && 1106 (loginPasswordParameter.hasValue())) 1107 { 1108 loginPassword = loginPasswordParameter.getStringValue(); 1109 } 1110 1111 loginIDValueParameter = 1112 parameters.getStringParameter(loginIDValueParameter.getName()); 1113 useLoginIDRange = true; 1114 useSequential = false; 1115 String loginIDValue = loginIDValueParameter.getStringValue(); 1116 try 1117 { 1118 int openPos = loginIDValue.indexOf('['); 1119 int closePos = loginIDValue.indexOf(']', openPos); 1120 loginIDInitial = loginIDValue.substring(0, openPos); 1121 loginIDFinal = loginIDValue.substring(closePos+1); 1122 1123 int dashPos = loginIDValue.indexOf('-', openPos); 1124 if (dashPos < 0) 1125 { 1126 dashPos = loginIDValue.indexOf(':', openPos); 1127 useSequential = true; 1128 } 1129 loginIDMin = Integer.parseInt(loginIDValue.substring(openPos+1, 1130 dashPos)); 1131 loginIDMax = Integer.parseInt(loginIDValue.substring(dashPos+1, 1132 closePos)); 1133 loginIDSpan = loginIDMax - loginIDMin + 1; 1134 sequentialCounter = loginIDMin; 1135 } 1136 catch (Exception e) 1137 { 1138 useLoginIDRange = false; 1139 loginIDInitial = loginIDValue; 1140 } 1141 } 1142 1143 1144 loginIDParameter = 1146 parameters.getStringParameter(loginIDParameter.getName()); 1147 if (loginIDParameter != null) 1148 { 1149 loginIDAttr = loginIDParameter.getStringValue(); 1150 } 1151 1152 membershipDNParameter = 1154 parameters.getStringParameter(membershipDNParameter.getName()); 1155 if ((membershipDNParameter != null) && (membershipDNParameter.hasValue())) 1156 { 1157 membershipDN = membershipDNParameter.getStringValue(); 1158 } 1159 else 1160 { 1161 membershipDN = null; 1162 } 1163 1164 warmUpTime = 0; 1166 warmUpParameter = parameters.getIntegerParameter(warmUpParameter.getName()); 1167 if (warmUpParameter != null) 1168 { 1169 warmUpTime = warmUpParameter.getIntValue(); 1170 } 1171 1172 coolDownTime = 0; 1174 coolDownParameter = 1175 parameters.getIntegerParameter(coolDownParameter.getName()); 1176 if (coolDownParameter != null) 1177 { 1178 coolDownTime = coolDownParameter.getIntValue(); 1179 } 1180 1181 timeLimitParameter = 1183 parameters.getIntegerParameter(timeLimitParameter.getName()); 1184 if (timeLimitParameter != null) 1185 { 1186 timeLimit = timeLimitParameter.getIntValue(); 1187 } 1188 1189 delay = 0; 1191 delayParameter = parameters.getIntegerParameter(delayParameter.getName()); 1192 if (delayParameter != null) 1193 { 1194 delay = delayParameter.getIntValue(); 1195 } 1196 1197 useSSL = false; 1199 useSSLParameter = parameters.getBooleanParameter(useSSLParameter.getName()); 1200 if (useSSLParameter != null) 1201 { 1202 useSSL = useSSLParameter.getBooleanValue(); 1203 } 1204 1205 if (useSSL) 1207 { 1208 blindTrustParameter = 1210 parameters.getBooleanParameter(blindTrustParameter.getName()); 1211 if (blindTrustParameter != null) 1212 { 1213 blindTrust = blindTrustParameter.getBooleanValue(); 1214 } 1215 1216 sslKeyStore = null; 1218 keyStoreParameter = 1219 parameters.getStringParameter(keyStoreParameter.getName()); 1220 if ((keyStoreParameter != null) && (keyStoreParameter.hasValue())) 1221 { 1222 sslKeyStore = keyStoreParameter.getStringValue(); 1223 System.setProperty(SSL_KEY_STORE_PROPERTY, sslKeyStore); 1224 } 1225 1226 sslKeyPassword = null; 1228 keyPWParameter = 1229 parameters.getPasswordParameter(keyPWParameter.getName()); 1230 if ((keyPWParameter != null) && (keyPWParameter.hasValue())) 1231 { 1232 sslKeyPassword = keyPWParameter.getStringValue(); 1233 System.setProperty(SSL_KEY_PASSWORD_PROPERTY, sslKeyPassword); 1234 } 1235 1236 sslTrustStore = null; 1238 trustStoreParameter = 1239 parameters.getStringParameter(trustStoreParameter.getName()); 1240 if ((trustStoreParameter != null) && (trustStoreParameter.hasValue())) 1241 { 1242 sslTrustStore = trustStoreParameter.getStringValue(); 1243 System.setProperty(SSL_TRUST_STORE_PROPERTY, sslTrustStore); 1244 } 1245 1246 sslTrustPassword = null; 1248 trustPWParameter = 1249 parameters.getPasswordParameter(trustPWParameter.getName()); 1250 if ((trustPWParameter != null) && (trustPWParameter.hasValue())) 1251 { 1252 sslTrustPassword = trustPWParameter.getStringValue(); 1253 System.setProperty(SSL_TRUST_PASSWORD_PROPERTY, sslTrustPassword); 1254 } 1255 } 1256 1257 1258 ignoreInvCredParameter = 1261 parameters.getBooleanParameter(ignoreInvCredParameter.getName()); 1262 if (ignoreInvCredParameter != null) 1263 { 1264 ignoreInvalidCredentials = ignoreInvCredParameter.getBooleanValue(); 1265 } 1266 1267 shareConnsParameter = 1269 parameters.getBooleanParameter(shareConnsParameter.getName()); 1270 if (shareConnsParameter != null) 1271 { 1272 useSharedConnections = shareConnsParameter.getBooleanValue(); 1273 } 1274 1275 1276 if (useSharedConnections) 1278 { 1279 if (useSSL) 1280 { 1281 if (blindTrust) 1282 { 1283 try 1284 { 1285 sharedAuthConnection = 1286 new LDAPConnection(new JSSEBlindTrustSocketFactory()); 1287 } 1288 catch (LDAPException le) 1289 { 1290 throw new UnableToRunException(le.getMessage(), le); 1291 } 1292 } 1293 else 1294 { 1295 sharedAuthConnection = new LDAPConnection(new JSSESocketFactory(null)); 1296 } 1297 } 1298 else 1299 { 1300 sharedAuthConnection = new LDAPConnection(); 1301 } 1302 1303 try 1304 { 1305 sharedAuthConnection.connect(3, directoryHost, directoryPort, bindDN, 1306 bindPW); 1307 } 1308 catch (Exception e) 1309 { 1310 throw new UnableToRunException("Could not establish shared " + 1311 "connections to the directory: " + e, 1312 e); 1313 } 1314 } 1315 1316 1317 membershipType = MEMBERSHIP_TYPE_NONE; 1320 if (membershipDN != null) 1321 { 1322 LDAPConnection conn = null; 1324 if (useSharedConnections) 1325 { 1326 conn = sharedAuthConnection; 1327 } 1328 else 1329 { 1330 try 1331 { 1332 if (useSSL) 1333 { 1334 if (blindTrust) 1335 { 1336 conn = new LDAPConnection(new JSSEBlindTrustSocketFactory()); 1337 } 1338 else 1339 { 1340 conn = new LDAPConnection(new JSSESocketFactory(null)); 1341 } 1342 } 1343 else 1344 { 1345 conn = new LDAPConnection(); 1346 } 1347 conn.connect(3, directoryHost, directoryPort, bindDN, bindPW); 1348 } 1349 catch (Exception e) 1350 { 1351 throw new UnableToRunException("Could not connect to directory " + 1352 "server " + directoryHost + ":" + 1353 directoryPort + 1354 " to retrieve membership entry.", e); 1355 } 1356 } 1357 1358 String [] attrsToReturn = new String [] { "objectClass", "memberURL" }; 1360 LDAPEntry entry = null; 1361 try 1362 { 1363 entry = conn.read(membershipDN); 1364 } 1365 catch (Exception e) {} 1366 1367 if (entry == null) 1368 { 1369 try 1370 { 1371 conn.disconnect(); 1372 } catch (Exception e) {} 1373 throw new UnableToRunException("Could not retrieve the membership " + 1374 "entry '" + membershipDN + "' from " + 1375 "directory " + directoryHost + ":" + 1376 directoryPort + "."); 1377 } 1378 1379 LDAPAttribute ocAttr = entry.getAttribute("objectClass"); 1381 String [] ocValues = null; 1382 if ((ocAttr == null) || 1383 ((ocValues = ocAttr.getStringValueArray()) == null) || 1384 (ocValues.length == 0)) 1385 { 1386 try 1387 { 1388 conn.disconnect(); 1389 } catch (Exception e) {} 1390 throw new UnableToRunException("Could not retrieve objectclass " + 1391 "values from '" + membershipDN + "'"); 1392 } 1393 1394 for (int i=0; i < ocValues.length; i++) 1395 { 1396 if (ocValues[i].equalsIgnoreCase("groupOfNames") || 1397 ocValues[i].equalsIgnoreCase("groupOfUniqueNames")) 1398 { 1399 membershipType = MEMBERSHIP_TYPE_STATIC; 1400 break; 1401 } 1402 else if (ocValues[i].equalsIgnoreCase("groupOfURLs")) 1403 { 1404 LDAPAttribute urlAttr = entry.getAttribute("memberURL"); 1405 String [] urlValues = null; 1406 if ((urlAttr == null) || 1407 ((urlValues = urlAttr.getStringValueArray()) == null) || 1408 (urlValues.length == 0)) 1409 { 1410 try 1411 { 1412 conn.disconnect(); 1413 } catch (Exception e) {} 1414 1415 throw new UnableToRunException("Could not retrieve memberURL " + 1416 "from dynamic group entry " + 1417 membershipDN); 1418 } 1419 1420 try 1421 { 1422 LDAPUrl url = new LDAPUrl(urlValues[0]); 1423 membershipURLBase = LDAPDN.normalize(url.getDN()); 1424 membershipURLFilter = url.getFilter(); 1425 } 1426 catch (Exception e) 1427 { 1428 try 1429 { 1430 conn.disconnect(); 1431 } catch (Exception e2) {} 1432 1433 throw new UnableToRunException("Could not interpret " + 1434 urlValues[0] + " as an LDAP URL", e); 1435 } 1436 1437 membershipType = MEMBERSHIP_TYPE_DYNAMIC; 1438 break; 1439 } 1440 else if (ocValues[i].toLowerCase().indexOf("role") >= 0) 1441 { 1442 membershipType = MEMBERSHIP_TYPE_ROLE; 1443 membershipDN = LDAPDN.normalize(membershipDN); 1444 break; 1445 } 1446 } 1447 1448 if (membershipType == MEMBERSHIP_TYPE_NONE) 1449 { 1450 throw new UnableToRunException("Could not determine the membership " + 1451 "type to check for entry " + 1452 membershipDN); 1453 } 1454 1455 if (! useSharedConnections) 1456 { 1457 try 1458 { 1459 conn.disconnect(); 1460 } catch (Exception e) {} 1461 } 1462 } 1463 1464 parentRandom = new Random(); 1466 } 1467 1468 1469 1470 1486 public void initializeThread(String clientID, String threadID, 1487 int collectionInterval, ParameterList parameters) 1488 throws UnableToRunException 1489 { 1490 random = new Random(parentRandom.nextLong()); 1492 1493 if (useSharedConnections) 1497 { 1498 authConnection = sharedAuthConnection; 1499 } 1500 else 1501 { 1502 if (useSSL) 1503 { 1504 if (blindTrust) 1505 { 1506 try 1507 { 1508 authConnection = 1509 new LDAPConnection(new JSSEBlindTrustSocketFactory()); 1510 } 1511 catch (LDAPException le) 1512 { 1513 throw new UnableToRunException(le.getMessage(), le); 1514 } 1515 } 1516 else 1517 { 1518 authConnection = new LDAPConnection(new JSSESocketFactory(null)); 1519 } 1520 } 1521 else 1522 { 1523 authConnection = new LDAPConnection(); 1524 } 1525 1526 try 1527 { 1528 authConnection.connect(3, directoryHost, directoryPort, bindDN, bindPW); 1529 } 1530 catch (Exception e) 1531 { 1532 throw new UnableToRunException("Unable to establish the connections " + 1533 "to the directory server: " + e, e); 1534 } 1535 } 1536 1537 try 1538 { 1539 socketFactory = new LDAPDigestMD5SocketFactory(); 1540 } 1541 catch (Exception e) 1542 { 1543 throw new UnableToRunException("Could not create DIGEST-MD5 socket " + 1544 "factory -- " + e, e); 1545 } 1546 1547 if (useSSL) 1548 { 1549 if (blindTrust) 1550 { 1551 try 1552 { 1553 socketFactory.setAdditionalSocketFactory( 1554 new JSSEBlindTrustSocketFactory()); 1555 } 1556 catch (LDAPException le) 1557 { 1558 throw new UnableToRunException(le.getMessage(), le); 1559 } 1560 } 1561 else 1562 { 1563 socketFactory.setAdditionalSocketFactory(new JSSESocketFactory(null)); 1564 } 1565 } 1566 1567 authConstraints = authConnection.getConstraints(); 1569 authSearchConstraints = authConnection.getSearchConstraints(); 1570 authConstraints.setTimeLimit(1000*timeLimit); 1571 authSearchConstraints.setTimeLimit(1000*timeLimit); 1572 authSearchConstraints.setServerTimeLimit(timeLimit); 1573 1574 1575 attemptCounter = 1577 new IncrementalTracker(clientID, threadID, 1578 STAT_TRACKER_AUTHENTICATION_ATTEMPTS, 1579 collectionInterval); 1580 successCounter = 1581 new IncrementalTracker(clientID, threadID, 1582 STAT_TRACKER_SUCCESSFUL_AUTHENTICATIONS, 1583 collectionInterval); 1584 failureCounter = 1585 new IncrementalTracker(clientID, threadID, 1586 STAT_TRACKER_FAILED_AUTHENTICATIONS, 1587 collectionInterval); 1588 authTimer = new TimeTracker(clientID, threadID, 1589 STAT_TRACKER_AUTHENTICATION_TIME, 1590 collectionInterval); 1591 1592 1593 RealTimeStatReporter statReporter = getStatReporter(); 1595 if (statReporter != null) 1596 { 1597 String jobID = getJobID(); 1598 attemptCounter.enableRealTimeStats(statReporter, jobID); 1599 successCounter.enableRealTimeStats(statReporter, jobID); 1600 failureCounter.enableRealTimeStats(statReporter, jobID); 1601 authTimer.enableRealTimeStats(statReporter, jobID); 1602 } 1603 } 1604 1605 1606 1607 1611 public void runJob() 1612 { 1613 long currentTime = System.currentTimeMillis(); 1615 boolean collectingStats = false; 1616 long startCollectingTime = currentTime + (1000 * warmUpTime); 1617 long stopCollectingTime = Long.MAX_VALUE; 1618 if ((coolDownTime > 0) && (getShouldStopTime() > 0)) 1619 { 1620 stopCollectingTime = getShouldStopTime() - (1000 * coolDownTime); 1621 } 1622 1623 long authStartTime = 0; 1626 1627 1628 while (! shouldStop()) 1630 { 1631 currentTime = System.currentTimeMillis(); 1632 if ((! collectingStats) && (currentTime >= startCollectingTime) && 1633 (currentTime < stopCollectingTime)) 1634 { 1635 attemptCounter.startTracker(); 1637 successCounter.startTracker(); 1638 failureCounter.startTracker(); 1639 authTimer.startTracker(); 1640 collectingStats = true; 1641 } 1642 else if ((collectingStats) && (currentTime >= stopCollectingTime)) 1643 { 1644 attemptCounter.stopTracker(); 1645 successCounter.stopTracker(); 1646 failureCounter.stopTracker(); 1647 authTimer.stopTracker(); 1648 collectingStats = false; 1649 } 1650 1651 if ((delay > 0) && (authStartTime > 0)) 1653 { 1654 long now = System.currentTimeMillis(); 1655 long sleepTime = delay - (now - authStartTime); 1656 if (sleepTime > 0) 1657 { 1658 try 1659 { 1660 Thread.sleep(sleepTime); 1661 } catch (InterruptedException ie) {} 1662 1663 if (shouldStop()) 1664 { 1665 break; 1666 } 1667 } 1668 } 1669 1670 String [] loginInfo = getLoginInfo(); 1672 String loginID = loginInfo[0]; 1673 String password = loginInfo[1]; 1674 1675 1676 if (delay > 0) 1678 { 1679 authStartTime = System.currentTimeMillis(); 1680 } 1681 1682 1683 if (collectingStats) 1685 { 1686 attemptCounter.increment(); 1687 authTimer.startTimer(); 1688 } 1689 1690 String [] attrsToReturn; 1692 if ((membershipDN == null) || (membershipType != MEMBERSHIP_TYPE_ROLE)) 1693 { 1694 attrsToReturn = NO_ATTRS; 1695 } 1696 else 1697 { 1698 attrsToReturn = new String [] { ROLE_ATTR }; 1699 } 1700 1701 String filter = "(" + loginIDAttr + "=" + loginID + ")"; 1702 LDAPSearchResults results; 1703 LDAPEntry userEntry = null; 1704 try 1705 { 1706 results = authConnection.search(searchBase, LDAPConnection.SCOPE_SUB, 1707 filter, attrsToReturn, false, 1708 authSearchConstraints); 1709 while (results.hasMoreElements()) 1710 { 1711 Object element = results.nextElement(); 1712 if (element instanceof LDAPEntry) 1713 { 1714 userEntry = (LDAPEntry) element; 1715 } 1716 } 1717 } 1718 catch (LDAPException le) 1719 { 1720 if (collectingStats) 1722 { 1723 failureCounter.increment(); 1724 authTimer.stopTimer(); 1725 } 1726 continue; 1727 } 1728 1729 1730 if (userEntry == null) 1732 { 1733 if (collectingStats) 1734 { 1735 failureCounter.increment(); 1736 authTimer.stopTimer(); 1737 } 1738 continue; 1739 } 1740 1741 1742 try 1745 { 1746 socketFactory.setAuthenticationInfo("dn:" + userEntry.getDN(), 1747 password); 1748 bindConnection = new LDAPConnection(socketFactory); 1749 bindConnection.connect(directoryHost, directoryPort); 1750 bindConnection.disconnect(); 1751 } 1752 catch (LDAPException le) 1753 { 1754 if (! (ignoreInvalidCredentials && 1755 (le.getLDAPResultCode() == LDAPException.INVALID_CREDENTIALS))) 1756 { 1757 if (collectingStats) 1758 { 1759 failureCounter.increment(); 1760 authTimer.stopTimer(); 1761 } 1762 continue; 1763 } 1764 } 1765 1766 1767 if (membershipDN != null) 1769 { 1770 if (isMember(userEntry)) 1771 { 1772 if (collectingStats) 1773 { 1774 successCounter.increment(); 1775 authTimer.stopTimer(); 1776 } 1777 } 1778 else 1779 { 1780 if (collectingStats) 1781 { 1782 failureCounter.increment(); 1783 authTimer.stopTimer(); 1784 } 1785 } 1786 } 1787 else 1788 { 1789 if (collectingStats) 1790 { 1791 successCounter.increment(); 1792 authTimer.stopTimer(); 1793 } 1794 } 1795 } 1796 1797 1798 1799 if (collectingStats) 1801 { 1802 attemptCounter.stopTracker(); 1803 successCounter.stopTracker(); 1804 failureCounter.stopTracker(); 1805 authTimer.stopTracker(); 1806 } 1807 1808 1809 if (! useSharedConnections) 1811 { 1812 try 1813 { 1814 authConnection.disconnect(); 1815 } catch (Exception e) {} 1816 1817 try 1818 { 1819 bindConnection.disconnect(); 1820 } catch (Exception e) {} 1821 } 1822 } 1823 1824 1825 1826 1830 public void destroy() 1831 { 1832 if (authConnection != null) 1833 { 1834 try 1835 { 1836 authConnection.disconnect(); 1837 } catch (Exception e) {} 1838 1839 authConnection = null; 1840 } 1841 1842 if (bindConnection != null) 1843 { 1844 try 1845 { 1846 bindConnection.disconnect(); 1847 } catch (Exception e) {} 1848 1849 bindConnection = null; 1850 } 1851 } 1852 1853 1854 1855 1860 public void finalizeClient() 1861 { 1862 if (useSharedConnections) 1864 { 1865 try 1866 { 1867 sharedAuthConnection.disconnect(); 1868 } catch (Exception e) {} 1869 } 1870 } 1871 1872 1873 1874 1882 public boolean isMember(LDAPEntry userEntry) 1883 { 1884 switch (membershipType) 1885 { 1886 case MEMBERSHIP_TYPE_STATIC: 1887 String userDN = userEntry.getDN(); 1888 String filter = "(|(&(objectclass=groupOfNames)(member=" + userDN + 1889 "))(&(objectClass=groupOfUniqueNames)(uniqueMember=" + 1890 userDN + ")))"; 1891 try 1892 { 1893 LDAPSearchResults results = 1894 authConnection.search(membershipDN, LDAPConnection.SCOPE_BASE, 1895 filter, NO_ATTRS, false); 1896 while (results.hasMoreElements()) 1897 { 1898 Object element = results.nextElement(); 1899 if (element instanceof LDAPEntry) 1900 { 1901 return true; 1902 } 1903 } 1904 1905 return false; 1906 } 1907 catch (Exception e) 1908 { 1909 return false; 1910 } 1911 case MEMBERSHIP_TYPE_DYNAMIC: 1912 userDN = LDAPDN.normalize(userEntry.getDN()); 1913 if (! userDN.endsWith(membershipURLBase)) 1914 { 1915 return false; 1916 } 1917 1918 try 1919 { 1920 LDAPSearchResults results = 1921 authConnection.search(userDN, LDAPConnection.SCOPE_BASE, 1922 membershipURLFilter, NO_ATTRS, false); 1923 while (results.hasMoreElements()) 1924 { 1925 Object element = results.nextElement(); 1926 if (element instanceof LDAPEntry) 1927 { 1928 return true; 1929 } 1930 } 1931 1932 return false; 1933 } 1934 catch (Exception e) 1935 { 1936 return false; 1937 } 1938 case MEMBERSHIP_TYPE_ROLE: 1939 LDAPAttribute roleAttr = userEntry.getAttribute(ROLE_ATTR); 1940 String [] roleValues = null; 1941 if ((roleAttr == null) || 1942 ((roleValues = roleAttr.getStringValueArray()) == null) || 1943 (roleValues.length == 0)) 1944 { 1945 return false; 1946 } 1947 1948 for (int i=0; i < roleValues.length; i++) 1949 { 1950 String roleDN = LDAPDN.normalize(roleValues[i]); 1951 if (roleDN.equals(membershipDN)) 1952 { 1953 return true; 1954 } 1955 } 1956 1957 return false; 1958 } 1959 1960 1961 return false; 1962 } 1963 1964 1965 1966 1972 public String [] getLoginInfo() 1973 { 1974 String [] loginInfo = new String [2]; 1975 1976 if (useDataFile) 1977 { 1978 int slot = (random.nextInt() & 0x7FFFFFFF) % loginIDs.length; 1979 loginInfo[0] = loginIDs[slot]; 1980 loginInfo[1] = loginPasswords[slot]; 1981 } 1982 else 1983 { 1984 if (useLoginIDRange) 1985 { 1986 int value; 1987 if (useSequential) 1988 { 1989 value = sequentialCounter++; 1990 if (sequentialCounter > loginIDMax) 1991 { 1992 sequentialCounter = loginIDMin; 1993 } 1994 } 1995 else 1996 { 1997 value = ((random.nextInt() & 0x7FFFFFFF) % loginIDSpan) + loginIDMin; 1998 } 1999 loginInfo[0] = loginIDInitial + value + loginIDFinal; 2000 loginInfo[1] = loginPassword; 2001 } 2002 else 2003 { 2004 loginInfo[0] = loginIDInitial; 2005 loginInfo[1] = loginPassword; 2006 } 2007 } 2008 2009 return loginInfo; 2010 } 2011} 2012 2013 | Popular Tags |