View Javadoc
1 /* 2 * LoginModuleManager.java 3 * 4 * Created on May 20, 2003, 10:15 PM 5 */ 6 7 package com.sun.xml.registry.ebxml.jaas; 8 9 import java.net.*; 10 import java.io.*; 11 import java.util.*; 12 import java.lang.reflect.Constructor; 13 import java.lang.reflect.InvocationTargetException; 14 import java.util.jar.*; 15 import java.awt.Frame; 16 17 import javax.security.auth.callback.CallbackHandler; 18 import javax.xml.registry.JAXRException; 19 20 import com.sun.xml.registry.ebxml.util.KeystoreUtil; 21 22 import com.sun.security.auth.callback.DialogCallbackHandler; 23 import com.sun.security.auth.login.ConfigFile; 24 import javax.security.auth.login.AppConfigurationEntry; 25 import javax.security.auth.login.Configuration; 26 27 import org.apache.commons.logging.Log; 28 import org.apache.commons.logging.LogFactory; 29 30 /*** 31 * 32 * @author psterk 33 */ 34 public class LoginModuleManager 35 { 36 private static final int MAX_FIXED_ATTRIBUTES = 25; 37 private static final int MAX_BACKUP_LOGIN_FILES = 10; 38 private static final String LINE_SEPARATOR = 39 System.getProperty("line.separator"); 40 private static final String FILE_SEPARATOR = 41 System.getProperty("file.separator"); 42 // Default application name. This is used if a bundled authentication 43 // application config file does not exist, or if the 44 // LoginModuleManager(String applicationName) was not called 45 private static final String DEFAULT_APPLICATION_NAME = 46 "jaxr-ebxml-provider"; 47 private static final String DEFAULT_LOGIN_MODULE_CLASSNAME = 48 "com.sun.security.auth.module.KeyStoreLoginModule"; 49 private static final String DEFAULT_KEYSTORE_FILENAME = 50 "${user.home}${/}jaxr-ebxml${/}security${/}keystore.jks"; 51 private static boolean _createLoginFile = false; 52 private static boolean _createDefaultLoginFile = false; 53 private static boolean _getCallbackHandler = false; 54 55 56 // cached objects 57 private String _applicationName; 58 private CallbackHandler _callbackHandler; 59 private CallbackHandler _defaultCallbackHandler; 60 private String _propertiesName = "jaxr-ebxml"; 61 private Properties _bundledProperties; 62 private String _bundledCfgFileContents; 63 private Properties _securityProps; 64 65 private static final Log log = LogFactory.getLog(LoginModuleManager.class); 66 67 private Frame _parentFrame; 68 private Log _parentLog = log; 69 70 /*** 71 * Default constructor<br> 72 * Uses jaxr-ebxml-provider as the default login config application name 73 */ 74 public LoginModuleManager() 75 { 76 77 } 78 79 /*** 80 * Alternative constructor<br> 81 * The application name is configurable 82 * 83 * @param applicationName 84 * A String that contains the application name for the login config file 85 */ 86 public LoginModuleManager(String applicationName) 87 { 88 if (_applicationName == null) 89 { 90 _applicationName = DEFAULT_APPLICATION_NAME; 91 } 92 else 93 { 94 _applicationName = applicationName; 95 } 96 } 97 98 /*** 99 * This method is used to set the parent frame of this class. The 100 * reference will be passed to the CallbackHandler implementation to 101 * improve the GUI behavior. 102 * 103 * @param frame 104 * The parent frame used by the CallbackHandler implementation 105 */ 106 public void setParentFrame(Frame frame) 107 { 108 _parentFrame = frame; 109 } 110 111 /*** 112 * This method is used to get the parent frame of this class. 113 * 114 * @retrun 115 * The parent frame used by the CallbackHandler implementation 116 */ 117 public Frame getParentFrame() 118 { 119 if (_parentFrame == null) 120 { 121 _parentFrame = new Frame(); 122 } 123 return _parentFrame; 124 } 125 126 /*** 127 * This method is used to set the parent Log of this class. This reference 128 * will be passed to the CallbackHandler implementation to provide more 129 * consistent logging. 130 * 131 * @param log 132 * The parent log used by the CallbackHandler implementation 133 */ 134 public void setParentLog(Log log) 135 { 136 _parentLog = log; 137 } 138 139 /*** 140 * This method is used to write the login configuration file required 141 * by the LoginContext. It searches for the java.login.config file in 142 * the classpath and writes it to the filesystem. The LoginContext class 143 * will read this file, and instantiate and configure the correct 144 * JAAS LoginModules. If the java.login.config file cannot be found, it 145 * defaults to the current KeystoreLoginModule. 146 * 147 * @throws JAXRException 148 * This exception is thrown if the bundled config file is different from 149 * the user config file, and cannot be written to the filesystem. If there 150 * is no bundled config file, this exception is thrown if there is a 151 * problem writing the default config file to the filesystem 152 */ 153 public void createLoginConfigFile() throws JAXRException 154 { 155 log.debug("start creating login config file"); 156 // first look for java.login.config in the classpath 157 String bundledCfgFileContents = getBundledCfgFileContents(); 158 159 // if java.login.config does not exist, 160 // call createDefaultLoginConfigFile() 161 if (bundledCfgFileContents == null) 162 { 163 createDefaultLoginConfigFile(); 164 } 165 else 166 { 167 createLoginConfigFileInternal(bundledCfgFileContents); 168 } 169 log.debug("finish creating login config file"); 170 } 171 172 /*** 173 * This method is used to get the application name from the bundled config 174 * file. If this file does not exist, it defaults to 'jaxr-ebxml-provider' 175 * 176 * @return 177 * A String containing the application name 178 */ 179 public String getApplicationName() 180 { 181 log.debug("start getting application name"); 182 if (_applicationName == null) 183 { 184 try 185 { // try to get application from bundled config file 186 String bundledCfgFileContents = getBundledCfgFileContents(); 187 if (bundledCfgFileContents != null) 188 { 189 _applicationName = getLoginName(bundledCfgFileContents); 190 } 191 log.info("authentication application name: "+_applicationName); 192 } 193 catch (Throwable t) 194 { 195 log.warn("problem reading bundled login config file. "+ 196 "Use default "+DEFAULT_APPLICATION_NAME, t); 197 } 198 // if bundled config does not exist or there is a problem loading it 199 // use default 200 if (_applicationName == null) 201 { 202 log.warn("problem reading bundled login config file. "+ 203 "Use default "+DEFAULT_APPLICATION_NAME); 204 _applicationName = DEFAULT_APPLICATION_NAME; 205 } 206 } 207 log.debug("finish getting application name"); 208 return _applicationName; 209 } 210 211 /*** 212 * This method is used to set the default CallbackHandler. If the 213 * jaxr-ebxml.security.jaas.callbackHandlerClassName property is not set, 214 * this default CallbackHandler will be used. 215 * 216 * @param handler 217 * A javax.security.auth.callback.CallbackHandler implementation 218 * provided by the user 219 */ 220 public void setDefaultCallbackHandler(CallbackHandler handler) 221 { 222 _defaultCallbackHandler = handler; 223 } 224 225 /*** 226 * This method is used to get the CallbackHandler from the bundled 227 * properties file. It reads the 228 * jaxr-ebxml.security.jaas.callbackHandlerClassName property. 229 * If this file or property does not exist, it defaults to 230 * com.sun.xml.registry.client.jaas.DialogAuthenticationCallbackHandler. 231 * 232 * @return 233 * An instance of the CallbackHandler interface 234 */ 235 public CallbackHandler getCallbackHandler() throws JAXRException 236 { 237 log.debug("start getting CallbackHandler name"); 238 if (_callbackHandler == null) 239 { 240 241 Properties properties = getBundledProperties(); 242 String callbackHandlerClassName = properties.getProperty( 243 _propertiesName+".security.jaas.callbackHandlerClassName"); 244 if (callbackHandlerClassName != null) 245 { 246 Class clazz = null; 247 try 248 { 249 clazz = Class.forName(callbackHandlerClassName); 250 } 251 catch (ClassNotFoundException ex) 252 { 253 throw new JAXRException("Could not instantiate "+ 254 "CallbackHandler "+callbackHandlerClassName+ 255 " Is this class in the classpath?", ex); 256 } 257 Class[] clazzes = new Class[2]; 258 clazzes[0] = java.awt.Frame.class; 259 clazzes[1] = org.apache.commons.logging.Log.class; 260 Constructor constructor = null; 261 try 262 { 263 constructor = clazz.getDeclaredConstructor(clazzes); 264 Object[] objs = new Object[2]; 265 objs[0] = getParentFrame(); 266 objs[1] = _parentLog; 267 _callbackHandler = 268 (CallbackHandler)constructor.newInstance(objs); 269 } 270 catch (NoSuchMethodException ex) 271 { 272 log.debug("Could not find constructor that takes a Frame "+ 273 "and Log as parameters. Trying default constructor"); 274 // use default constructor instead 275 try 276 { 277 _callbackHandler = (CallbackHandler)Class. 278 forName(callbackHandlerClassName).newInstance(); 279 } 280 catch (Throwable t) 281 { 282 throw new JAXRException("Could not instantiate "+ 283 "CallbackHandler "+callbackHandlerClassName+ 284 " reason", t); 285 } 286 } 287 catch (Throwable t) 288 { 289 throw new JAXRException("Could not instantiate "+ 290 "CallbackHandler "+callbackHandlerClassName+" Details:"+ 291 t.getMessage()); 292 } 293 } 294 if (_callbackHandler == null) 295 { 296 log.info("Using default CallbackHandler"); 297 // If set, user default CallbackHandler provided by user 298 if (_defaultCallbackHandler != null) 299 { 300 _callbackHandler = _defaultCallbackHandler; 301 } 302 else // user our internal default CallbackHandler 303 { 304 _callbackHandler = new DialogAuthenticationCallbackHandler( 305 getParentFrame(), log); 306 } 307 } 308 log.info("CallbackHandler name: "+ _callbackHandler.getClass().getName()); 309 } 310 log.debug("finish getting CallbackHandler name"); 311 return _callbackHandler; 312 } 313 314 /*** 315 * This method is used to create the default login configuration file. 316 * Currently, the default file is for the 317 * com.sun.security.auth.module.KeystoreLoginModule 318 * 319 * @throws JAXRException 320 * This is thrown if there is a problem writing the default login config 321 * file to the filesystem 322 */ 323 public void createDefaultLoginConfigFile() throws JAXRException 324 { 325 log.debug("start creation of default login config file"); 326 File keystoreFile = KeystoreUtil.getKeystoreFile(); 327 KeystoreUtil.canReadKeystoreFile(keystoreFile); 328 // This property should always be set by java 329 String userHomeFileName = System.getProperty("user.home"); 330 if ((userHomeFileName == null) 331 || (userHomeFileName.length() == 0)) 332 { 333 throw new JAXRException("Could not get system property user.home"); 334 } 335 File configFile = new File(userHomeFileName, ".java.login.config"); 336 if (configFile.exists()) 337 { 338 if (configFile.canRead()) 339 { 340 Configuration config = ConfigFile.getConfiguration(); 341 String appName = getApplicationName(); 342 AppConfigurationEntry[] defaultAppConfigEntries = 343 getReloadedAppConfigurationEntries( 344 ConfigFile.getConfiguration(), 345 configFile.getPath()+".tmp", 346 getDefaultConfigFileContents(DEFAULT_APPLICATION_NAME+ 347 ".tmp"), 348 appName+".tmp"); 349 AppConfigurationEntry[] userAppConfigEntries = 350 config.getAppConfigurationEntry(appName); 351 boolean isCorrect = checkLoginModules(userAppConfigEntries, 352 defaultAppConfigEntries); 353 354 // if the user has a login config file with the same app name 355 // as the default, but the login modules are different, rename 356 // the existing user login config file and write the default 357 // config file in place of the existing 358 if (isCorrect == false) 359 { 360 String userCfgFileName = configFile.getName(); 361 log.warn("User login config file does not have the same "+ 362 "login modules as the default"); 363 renameCfgFile(userCfgFileName, userCfgFileName+".bak"); 364 writeCfgFile(configFile, getDefaultConfigFileContents()); 365 config.refresh(); 366 log.info("created new login config file: "+configFile.getName()); 367 } 368 else 369 { 370 log.info("using existing config file: "+ 371 configFile.getName()); 372 return; 373 } 374 } 375 else 376 { 377 throw new JAXRException("File " 378 + configFile.getAbsolutePath() 379 + " exists but is not readable."); 380 } 381 } 382 else 383 { 384 writeCfgFile(configFile, getDefaultConfigFileContents()); 385 log.info("created new login config file: "+configFile.getName()); 386 } 387 log.debug("finish creation of default login config file"); 388 } 389 390 /************************************************************************** 391 * private methods 392 *************************************************************************/ 393 private boolean getDebugSetting() 394 { 395 boolean debug = false; 396 Configuration config = ConfigFile.getConfiguration(); 397 AppConfigurationEntry[] userAppConfigEntries = 398 config.getAppConfigurationEntry(getApplicationName()); 399 for (int i = 0; i < userAppConfigEntries.length; i++) 400 { 401 Map options = userAppConfigEntries[i].getOptions(); 402 String debugStr = (String)options.get("debug"); 403 if (debugStr != null) 404 { 405 if (debugStr.equalsIgnoreCase("true")) 406 { 407 debug = true; 408 } 409 break; 410 } 411 } 412 return debug; 413 } 414 415 private String getBundledCfgFilename() 416 { 417 URL url = this.getClass().getClassLoader(). 418 getResource("java.login.config"); 419 String fileName = url.getFile(); 420 return fileName; 421 } 422 423 private Properties getBundledProperties() 424 { 425 if (_bundledProperties == null) 426 { 427 _bundledProperties = new Properties(); 428 BufferedReader in = null; 429 try 430 { 431 InputStream propInputStream = this.getClass(). 432 getClassLoader().getResourceAsStream( 433 "com/sun/xml/registry/ebxml/util/jaxr-ebxml-defaults.properties"); 434 if (propInputStream != null) 435 { 436 _bundledProperties.load(propInputStream); 437 } 438 } 439 catch (Throwable t) 440 { 441 log.warn("Problem reading bundled jaxr-ebxml.properties file"); 442 } 443 finally 444 { 445 if (in != null) 446 { 447 try 448 { 449 in.close(); 450 } 451 catch (IOException ex) 452 { 453 log.warn("could not close input stream", ex); 454 } 455 } 456 } 457 } 458 return _bundledProperties; 459 } 460 461 private String getBundledCfgFileContents() 462 { 463 if (_bundledCfgFileContents == null) 464 { 465 BufferedReader in = null; 466 try 467 { 468 InputStream cfgFileInputStream = this.getClass(). 469 getClassLoader().getResourceAsStream( 470 "com/sun/xml/registry/ebxml/util/jaxr.java.login.config"); 471 if (cfgFileInputStream != null) 472 { 473 log.info("found com/sun/xml/registry/ebxml/util/jaxr.java.login.config file"); 474 StringBuffer sb = new StringBuffer(); 475 String line = null; 476 in = new BufferedReader(new InputStreamReader( 477 cfgFileInputStream)); 478 while ((line = in.readLine()) != null) 479 { 480 sb.append(line).append(LINE_SEPARATOR); 481 } 482 _bundledCfgFileContents = sb.toString(); 483 checkKeystoreOption(); 484 } 485 486 } 487 catch (IOException ex) 488 { 489 log.warn("problem reading bundled login config file. "+ 490 "Use default", ex); 491 _bundledCfgFileContents = null; 492 } 493 finally 494 { 495 try 496 { 497 if (in != null) 498 in.close(); 499 } 500 catch (IOException ex) 501 { 502 // ignore 503 } 504 } 505 } 506 return _bundledCfgFileContents; 507 } 508 509 private void createLoginConfigFileInternal(String bundledFileContents) 510 throws JAXRException 511 { 512 log.debug("start creating login config file - internal"); 513 try 514 { 515 String userCfgFileName = getUserCfgFileName(); 516 log.info("User's config file name: "+ userCfgFileName); 517 String userCfgContents = getUserCfgFileContents(userCfgFileName); 518 // if the user doesn't have an existing login cfg file, write the 519 // bundled one 520 if (userCfgContents == null) 521 { 522 writeCfgFile(userCfgFileName, bundledFileContents); 523 } 524 else 525 { 526 // the user has an existing login cfg file. Use this method 527 // to compare both files and take appropriate actions 528 checkUserCfgFile(userCfgFileName, userCfgContents, 529 bundledFileContents); 530 } 531 } 532 catch (Throwable t) 533 { 534 log.warn("problem reading config file. using default", t); 535 // problem reading config file. Use default 536 createDefaultLoginConfigFile(); 537 } 538 log.debug("finish creating login config file - internal"); 539 } 540 541 private void checkUserCfgFile(String userCfgFileName, 542 String userCfgContents, 543 String bundledFileContents) 544 throws JAXRException 545 { 546 String userLoginName = getLoginName(userCfgContents); 547 String bundledLoginName = getLoginName(bundledFileContents); 548 // if the login names are the same, check attributes 549 if (userLoginName.equalsIgnoreCase(bundledLoginName)) 550 { 551 // this method checks that any required attributes are present and 552 // that fixed attributes are set according to the settings in the 553 // bundled jaxr-ebxml.properties file. 554 Configuration config = ConfigFile.getConfiguration(); 555 String appName = getApplicationName(); 556 String tmpAppName = appName+".tmp"; 557 AppConfigurationEntry[] bundledAppConfigEntries = 558 getReloadedAppConfigurationEntries(config, userCfgFileName+".tmp", 559 bundledFileContents, appName); 560 AppConfigurationEntry[] userAppConfigEntries = 561 config.getAppConfigurationEntry(appName); 562 boolean isCorrect = 563 areUserCfgFileAttributesCorrect(userAppConfigEntries, 564 bundledAppConfigEntries); 565 // if the user cfg content has changed, write it to the user cfg 566 // file 567 if (isCorrect == false) 568 { 569 log.warn("User login config file is not correct. Using "+ 570 "bundled config file instead"); 571 renameCfgFile(userCfgFileName, userCfgFileName+".bak"); 572 log.info("Renamed "+userCfgFileName+" to .bak file"); 573 writeCfgFile(userCfgFileName, bundledFileContents); 574 ConfigFile.getConfiguration().refresh(); 575 log.info("created new login file: "+userCfgFileName); 576 } 577 else 578 { 579 // if the user has a different keystore file in the 580 // jaxr-ebxml.properties file, update the user's config file 581 // automatically 582 updateUserCfgContents(userAppConfigEntries, userCfgContents, 583 userCfgFileName); 584 } 585 } 586 else 587 { 588 // the existing login name in different than the bundled. So, move 589 // the existing user cfg file to a backup file 590 renameCfgFile(userCfgFileName, userCfgFileName+".bak"); 591 writeCfgFile(userCfgFileName, bundledFileContents); 592 } 593 } 594 595 private void renameCfgFile(String fileName, String renamedFileName) 596 throws JAXRException 597 { 598 try 599 { 600 File file = new File(fileName); 601 File renamedFile = new File(renamedFileName); 602 if (renamedFile.exists()) 603 { 604 for (int i = 2; i <= MAX_BACKUP_LOGIN_FILES; i++) 605 { 606 String tempFileName = renamedFileName + i; 607 File tempFile = new File(tempFileName); 608 if (! tempFile.exists()) 609 { 610 file.renameTo(tempFile); 611 log.debug("renaming config file "+fileName+" to "+ 612 renamedFileName); 613 break; 614 } 615 } 616 } 617 else 618 { 619 file.renameTo(renamedFile); 620 } 621 } 622 catch (SecurityException ex) 623 { 624 throw new JAXRException(ex); 625 } 626 } 627 628 private boolean areUserCfgFileAttributesCorrect( 629 AppConfigurationEntry[] userAppConfigEntries, 630 AppConfigurationEntry[] bundledAppConfigEntries) 631 throws JAXRException 632 { 633 boolean isCorrect = false; 634 isCorrect = checkLoginModules(userAppConfigEntries, 635 bundledAppConfigEntries); 636 if (isCorrect == false) 637 return isCorrect; 638 isCorrect = checkControlFlag(userAppConfigEntries, 639 bundledAppConfigEntries); 640 if (isCorrect == false) 641 return isCorrect; 642 isCorrect = checkLoginModuleOptions(userAppConfigEntries, 643 bundledAppConfigEntries); 644 return isCorrect; 645 } 646 647 private AppConfigurationEntry[] getReloadedAppConfigurationEntries( 648 Configuration config, String cfgFileName, String cfgFileContents, 649 String appConfigName) 650 throws JAXRException 651 { 652 AppConfigurationEntry[] appConfigEntries = null; 653 // if there is an IOException, we do not have permission to write 654 // to the local filesystem. Without this permission, we cannot 655 // control the authentication. In this case, throw new 656 // JAXRException to notify the user to give us permission 657 try 658 { 659 File file = new File(cfgFileName); 660 writeCfgFile(file, cfgFileContents); 661 } 662 catch (Throwable t) 663 { 664 throw new JAXRException("This application does not have "+ 665 "permission to write to the local filesystem. Please "+ 666 "provide this permission in your java.policy file. Go to "+ 667 "http://java.sun.com and search for 'java.policy' for "+ 668 "details on setting permissions", t); 669 } 670 String javaSecLoginCfg = 671 System.getProperty("java.security.auth.login.config"); 672 String userCfgFileName = getUserCfgFileName(); 673 System.setProperty("java.security.auth.login.config", cfgFileName); 674 config.refresh(); 675 appConfigEntries = config.getAppConfigurationEntry(appConfigName); 676 try 677 { 678 deleteCfgFile(cfgFileName); 679 } 680 catch (Throwable t) 681 { 682 log.warn("problem deleting config file: ", t); 683 } 684 finally 685 { 686 if (javaSecLoginCfg != null) 687 { 688 System.setProperty("java.security.auth.login.config", javaSecLoginCfg); 689 } 690 else 691 { 692 System.setProperty("java.security.auth.login.config", userCfgFileName); 693 } 694 config.refresh(); 695 } 696 return appConfigEntries; 697 } 698 699 /* 700 * The login module names in the user's config file must appear in the 701 * same order as the bundled config file 702 */ 703 private boolean checkLoginModules( 704 AppConfigurationEntry[] userAppConfigEntries, 705 AppConfigurationEntry[] bundledAppConfigEntries) 706 { 707 boolean isCorrect = false; 708 for (int i = 0; i < bundledAppConfigEntries.length; i++) 709 { 710 isCorrect = true; 711 try 712 { // user login modules must appear in the same order as the 713 // bundled ones 714 String bundledLoginModuleName = 715 bundledAppConfigEntries[i].getLoginModuleName(); 716 String userLoginModuleName = 717 userAppConfigEntries[i].getLoginModuleName(); 718 if (! bundledLoginModuleName.equals(userLoginModuleName)) 719 { 720 721 isCorrect = false; 722 break; 723 } 724 } 725 catch (Throwable t) 726 { 727 // If the user config file has missing login module, it will 728 // be caught here 729 isCorrect = false; 730 break; 731 } 732 } 733 if (isCorrect) 734 { 735 log.debug("login module(s) in the existing login config file are ok"); 736 } 737 else 738 { 739 log.warn("The login module(s) contained in the existing "+ 740 "login config file do not appear in the "+ 741 "same order as the modules in the bundled config file"); 742 } 743 return isCorrect; 744 } 745 746 private boolean checkControlFlag( 747 AppConfigurationEntry[] userAppConfigEntries, 748 AppConfigurationEntry[] bundledAppConfigEntries) 749 { 750 boolean isCorrect = true; 751 for (int i = 0; i < bundledAppConfigEntries.length; i++) 752 { 753 try 754 { 755 AppConfigurationEntry.LoginModuleControlFlag bundledFlag = 756 bundledAppConfigEntries[i].getControlFlag(); 757 String bundledFlagStr = bundledFlag.toString(); 758 AppConfigurationEntry.LoginModuleControlFlag userFlag = 759 userAppConfigEntries[i].getControlFlag(); 760 String userFlagStr = userFlag.toString(); 761 if (! bundledFlagStr.equals(userFlagStr)) 762 { 763 isCorrect = false; 764 break; 765 } 766 767 } 768 catch (Throwable t) 769 { 770 isCorrect = false; 771 break; 772 } 773 } 774 if (isCorrect) 775 { 776 log.debug("control flag(s) in the existing login config file are ok"); 777 } 778 else 779 { 780 log.warn("The control flags contained in the existing "+ 781 "login config file do not match those in the "+ 782 "bundled config file"); 783 } 784 return isCorrect; 785 } 786 787 private boolean checkLoginModuleOptions( 788 AppConfigurationEntry[] userAppConfigEntries, 789 AppConfigurationEntry[] bundledAppConfigEntries) 790 { 791 boolean isCorrect = true; 792 for (int i = 0; i < bundledAppConfigEntries.length; i++) 793 { 794 Map userOptions = userAppConfigEntries[i].getOptions(); 795 Map bundledOptions = bundledAppConfigEntries[i].getOptions(); 796 isCorrect = doAllUserOptionExist(userOptions, bundledOptions); 797 if (isCorrect == false) 798 { 799 break; // problem with options; stop checking 800 } 801 String loginModuleName = 802 bundledAppConfigEntries[i].getLoginModuleName(); 803 isCorrect = areAllUserOptionsSetToCorrectValues(userOptions, 804 loginModuleName); 805 if (isCorrect == false) 806 { 807 break; // problem with options; stop checking 808 } 809 } 810 return isCorrect; 811 } 812 813 private boolean doAllUserOptionExist(Map userOptions, Map bundledOptions) 814 { 815 boolean isCorrect = true; 816 Iterator bundledOptionsIter = bundledOptions.keySet().iterator(); 817 while (bundledOptionsIter.hasNext()) 818 { 819 String bundledOption = (String)bundledOptionsIter.next(); 820 String userOption = (String)userOptions.get(bundledOption); 821 if (userOption == null) 822 { 823 log.warn("The following option is missing "+ 824 "in the existing login config file: "+userOption); 825 isCorrect = false; 826 break; 827 } 828 } 829 if (isCorrect) 830 { 831 log.debug("All options exist in the existing login config file"); 832 } 833 return isCorrect; 834 } 835 836 private boolean areAllUserOptionsSetToCorrectValues(Map userOptions, 837 String loginModuleFullName) 838 { 839 boolean isCorrect = true; 840 int lastPeriodIndex = loginModuleFullName.lastIndexOf('.'); 841 String loginModuleName = loginModuleFullName. 842 substring(lastPeriodIndex+1, loginModuleFullName.length()); 843 Properties properties = getBundledProperties(); 844 if (properties == null) 845 return isCorrect; 846 String partialAttributeKey = _propertiesName+".security.jaas."+ 847 loginModuleName+".attribute."; 848 String partialFixedKey = _propertiesName+".security.jaas."+ 849 loginModuleName+".fixedValue."; 850 for (int j = 1; j <= MAX_FIXED_ATTRIBUTES; j++) 851 { 852 String attributeKey = partialAttributeKey + j; 853 String attributeValue = null; 854 try 855 { 856 attributeValue = properties.getProperty(attributeKey); 857 } 858 catch (MissingResourceException ex) 859 { 860 // ignore - try to load attribute.1 through 861 // attribute.MAX_FIXED_ATTRIBUTES 862 } 863 if (attributeValue != null) 864 { 865 String fixedKey = partialFixedKey + j; 866 String fixedValue = null; 867 try 868 { 869 fixedValue = properties.getProperty(fixedKey); 870 } 871 catch (MissingResourceException ex) 872 { 873 // ignore - try to load fixedValue.1 through 874 // fixedValue.MAX_FIXED_ATTRIBUTES 875 } 876 if (fixedValue != null) 877 { 878 String optionValue = 879 (String)userOptions.get(attributeValue); 880 if (optionValue == null || 881 ! optionValue.equalsIgnoreCase(fixedValue)) 882 { 883 // integrity check has failed 884 // break and return 'false' 885 log.warn("The following option is not set properly: "+ 886 attributeValue); 887 log.warn("It is set to: "+optionValue); 888 log.warn("It should be set to: "+fixedValue); 889 isCorrect = false; 890 break; 891 } 892 } 893 } 894 } 895 if (isCorrect == true) 896 { 897 log.debug("all user config file options are set properly"); 898 } 899 return isCorrect; 900 } 901 902 private Properties getSecurityProperties() 903 { 904 if (_securityProps == null) 905 { 906 _securityProps = new Properties(); 907 BufferedInputStream bis = null; 908 String fileName = null; 909 try 910 { 911 String javaHome = System.getProperty("java.home"); 912 String dirSep = System.getProperty("file.separator"); 913 StringBuffer sb = new StringBuffer(javaHome); 914 sb.append(dirSep).append("lib").append(dirSep); 915 sb.append("security").append(dirSep); 916 sb.append("java.security"); 917 fileName = sb.toString(); 918 log.info("Found java.security properties: "+fileName); 919 File file = new File(fileName); 920 bis = new BufferedInputStream(new FileInputStream(file)); 921 _securityProps.load(bis); 922 } 923 catch (IOException ex) 924 { 925 log.warn("could not open java.security properties file. Ignore.", 926 ex); 927 } 928 finally 929 { 930 try 931 { 932 if (bis != null) 933 { 934 bis.close(); 935 } 936 } 937 catch (IOException ex) 938 { 939 // ignore 940 } 941 } 942 } 943 return _securityProps; 944 } 945 946 private String getLoginName(String cfgFileContents) 947 { 948 int firstSpaceIndex = cfgFileContents.indexOf(' '); 949 return (cfgFileContents.substring(0, firstSpaceIndex)); 950 } 951 952 private void deleteCfgFile(String cfgFile) throws JAXRException 953 { 954 try 955 { 956 File file = new File(cfgFile); 957 boolean isDeleted = file.delete(); 958 if (isDeleted == false) 959 { 960 System.out.println("warning: could not delete tmp file"); 961 } 962 } 963 catch (Throwable t) 964 { 965 throw new JAXRException(t); 966 } 967 } 968 969 private void writeCfgFile(File configFile, String cfgFileContents) 970 throws JAXRException 971 { 972 BufferedWriter writer = null; 973 try 974 { 975 writer = new BufferedWriter(new FileWriter(configFile)); 976 writer.write(cfgFileContents, 0, cfgFileContents.length()); 977 writer.flush(); 978 } 979 catch (IOException ex) 980 { 981 throw new JAXRException(ex); 982 } 983 finally 984 { 985 if (writer != null) 986 { 987 try 988 { 989 writer.close(); 990 } 991 catch (IOException ex) 992 { 993 // ignore 994 } 995 } 996 } 997 } 998 999 private void writeCfgFile(String userCfgFileName, String fileContents) 1000 throws JAXRException 1001 { 1002 BufferedWriter writer = null; 1003 try 1004 { 1005 File file = new File(userCfgFileName); 1006 writer = new BufferedWriter(new FileWriter(file)); 1007 writer.write(fileContents, 0, fileContents.length()); 1008 writer.flush(); 1009 } 1010 catch (IOException ex) 1011 { 1012 throw new JAXRException(ex); 1013 } 1014 finally 1015 { 1016 if (writer != null) 1017 { 1018 try 1019 { 1020 writer.close(); 1021 } 1022 catch (IOException ex) 1023 { 1024 // ignore 1025 } 1026 } 1027 } 1028 } 1029 1030 private String getUserCfgFileName() 1031 { 1032 String userCfgFileName = null; 1033 try 1034 { 1035 Properties securityProps = getSecurityProperties(); 1036 // Ignore the login.configuration.provider property in this 1037 // release. Alternative provider implementations can be supported 1038 // in subsequent releases. 1039 // We do not support login.config.url.1 in this release 1040 userCfgFileName = 1041 System.getProperty("java.security.auth.login.config"); 1042 if (userCfgFileName == null || userCfgFileName.equals("")) 1043 { 1044 userCfgFileName = getDefaultUserCfgFileName(); 1045 } 1046 } 1047 catch (Throwable t) 1048 { 1049 log.warn("problem getting user config file: ", t); 1050 userCfgFileName = getDefaultUserCfgFileName(); 1051 } 1052 return userCfgFileName; 1053 } 1054 1055 private String getDefaultUserCfgFileName() 1056 { 1057 StringBuffer sb = new StringBuffer(System.getProperty("user.home")); 1058 sb.append(System.getProperty("file.separator")); 1059 sb.append(".java.login.config"); 1060 return (sb.toString()); 1061 } 1062 1063 private String getUserCfgFileContents(String userHomeFileName) 1064 throws JAXRException 1065 { 1066 String fileContents = null; 1067 BufferedReader in = null; 1068 try 1069 { 1070 File configFile = new File(userHomeFileName); 1071 if (configFile.exists() == true) 1072 { 1073 StringBuffer sb2 = new StringBuffer(); 1074 String line = null; 1075 in = new BufferedReader(new FileReader(configFile)); 1076 while ((line = in.readLine()) != null) 1077 { 1078 sb2.append(line).append(LINE_SEPARATOR); 1079 } 1080 fileContents = sb2.toString(); 1081 } 1082 log.debug("user config file contents: "+fileContents); 1083 return fileContents; 1084 } 1085 catch (IOException ex) 1086 { 1087 throw new JAXRException(ex); 1088 } 1089 finally 1090 { 1091 try 1092 { 1093 if (in != null) 1094 in.close(); 1095 } 1096 catch (IOException ex) 1097 { 1098 // ignore 1099 } 1100 } 1101 } 1102 1103 private String getDefaultConfigFileContents() 1104 { 1105 return getDefaultConfigFileContents(DEFAULT_APPLICATION_NAME); 1106 } 1107 1108 private String getDefaultConfigFileContents(String appName) 1109 { 1110 String defaultConfigFileContents = null; 1111 1112 if (appName == null) 1113 { 1114 appName = DEFAULT_APPLICATION_NAME; 1115 } 1116 String keystoreFileName = DEFAULT_KEYSTORE_FILENAME; 1117 try 1118 { 1119 File keystoreFile = KeystoreUtil.getKeystoreFile(); 1120 KeystoreUtil.canReadKeystoreFile(keystoreFile); 1121 keystoreFileName = keystoreFile.toURL().getFile(); 1122 } 1123 catch (Throwable ex) 1124 { 1125 // Since keystoreFileName is already set to default, ignore 1126 } 1127 1128 StringBuffer sb = new StringBuffer(appName); 1129 sb.append(" { "+LINE_SEPARATOR); 1130 sb.append(" com.sun.security.auth.module.KeyStoreLoginModule "); 1131 sb.append("required ").append(LINE_SEPARATOR); 1132 sb.append(" debug=true keyStoreURL=\"file:"); 1133 sb.append(keystoreFileName).append("\";"); 1134 sb.append(LINE_SEPARATOR).append("};").append(LINE_SEPARATOR); 1135 defaultConfigFileContents = sb.toString(); 1136 log.debug("Default config file contents: "+defaultConfigFileContents); 1137 return defaultConfigFileContents; 1138 } 1139 1140 /*** 1141 * @param args the command line arguments 1142 */ 1143 public static void main(String[] args) 1144 { 1145 for (int i = 0; i < args.length; i++) 1146 { 1147 try 1148 { 1149 String argFlag = args[i]; 1150 if (argFlag.equals("-d")) 1151 { 1152 _createDefaultLoginFile = true; 1153 } 1154 else if (argFlag.equals("-l")) 1155 { 1156 _createLoginFile = true; 1157 } 1158 else if (argFlag.equals("-c")) 1159 { 1160 _getCallbackHandler = true; 1161 } 1162 else 1163 { // if no flags execute all methods 1164 _createDefaultLoginFile = true; 1165 _createLoginFile = true; 1166 _getCallbackHandler = true; 1167 } 1168 } 1169 catch (RuntimeException ex) 1170 { 1171 // use defaults 1172 } 1173 } 1174 if (args.length == 0) 1175 { 1176 _createLoginFile = true; 1177 } 1178 LoginModuleManager loginModuleMgr = new LoginModuleManager(); 1179 try 1180 { 1181 if (_createDefaultLoginFile) 1182 { 1183 log.info("starting createDefaultLoginConfigFile"); 1184 loginModuleMgr.createDefaultLoginConfigFile(); 1185 } 1186 if (_createLoginFile) 1187 { 1188 log.info("starting createLoginConfigFile"); 1189 loginModuleMgr.createLoginConfigFile(); 1190 } 1191 if (_getCallbackHandler) 1192 { 1193 log.info("starting getCallbackHandler"); 1194 loginModuleMgr.getCallbackHandler(); 1195 } 1196 } 1197 catch (Throwable t) 1198 { 1199 t.printStackTrace(); 1200 } 1201 } 1202 1203 private void updateUserCfgContents( 1204 AppConfigurationEntry[] userAppConfigEntries, String userCfgContents, 1205 String cfgFileName) 1206 { 1207 for (int i = 0; i < userAppConfigEntries.length; i++) 1208 { 1209 Map userOptions = userAppConfigEntries[i].getOptions(); 1210 String userKeystoreFile = (String)userOptions.get("keyStoreURL"); 1211 if (userKeystoreFile != null) 1212 { 1213 try 1214 { 1215 File keystoreFile = KeystoreUtil.getKeystoreFile(); 1216 KeystoreUtil.canReadKeystoreFile(keystoreFile); 1217 String keystoreFileInPropFile = 1218 keystoreFile.toURL().getFile(); 1219 if (keystoreFileInPropFile != null) 1220 { 1221 if (! userKeystoreFile.equals(keystoreFileInPropFile)) 1222 { 1223 String keyStoreURL = new String("keyStoreURL=\"file:"); 1224 int keyStartIndex = 1225 userCfgContents.indexOf(keyStoreURL); 1226 keyStartIndex += keyStoreURL.length(); 1227 int keyEndIndex = 1228 userCfgContents.indexOf("\";", keyStartIndex); 1229 1230 String firstPart = userCfgContents.substring(0, 1231 keyStartIndex); 1232 String lastPart = 1233 userCfgContents.substring(keyEndIndex); 1234 // combine all parts 1235 StringBuffer sb = new StringBuffer(firstPart); 1236 sb.append(keystoreFileInPropFile).append(lastPart); 1237 userCfgContents = sb.toString(); 1238 writeCfgFile(cfgFileName, userCfgContents); 1239 } 1240 } 1241 } 1242 catch (Throwable t) 1243 { 1244 // ignore 1245 } 1246 } 1247 } 1248 } 1249 1250 private void checkKeystoreOption() 1251 { 1252 String keyStoreURL = new String("keyStoreURL=\"file:"); 1253 int keyStartIndex = 1254 _bundledCfgFileContents.indexOf(keyStoreURL); 1255 keyStartIndex += keyStoreURL.length(); 1256 int keyEndIndex = 1257 _bundledCfgFileContents.indexOf("\";", keyStartIndex); 1258 try 1259 { 1260 File keystoreFile = KeystoreUtil.getKeystoreFile(); 1261 KeystoreUtil.canReadKeystoreFile(keystoreFile); 1262 String firstPart = _bundledCfgFileContents.substring(0, keyStartIndex); 1263 String keystoreFileName = keystoreFile.toURL().getFile(); 1264 String lastPart = _bundledCfgFileContents.substring(keyEndIndex); 1265 // combine all parts 1266 StringBuffer sb = new StringBuffer(firstPart); 1267 sb.append(keystoreFileName).append(lastPart); 1268 _bundledCfgFileContents = sb.toString(); 1269 } 1270 catch (Throwable ex) 1271 { 1272 // ignore - use existing _bundledCfgFileContents 1273 } 1274 } 1275 }

This page was automatically generated by Maven