1 7 8 package javax.security.auth.login; 9 10 import java.lang.reflect.Constructor ; 11 import java.lang.reflect.Method ; 12 import java.lang.reflect.InvocationTargetException ; 13 import java.util.LinkedList ; 14 import java.util.Map ; 15 import java.util.HashMap ; 16 import java.text.MessageFormat ; 17 import javax.security.auth.Subject ; 18 import javax.security.auth.AuthPermission ; 19 import javax.security.auth.callback.*; 20 import java.security.AccessController ; 21 import java.security.AccessControlContext ; 22 import sun.security.util.PendingException; 23 import sun.security.util.ResourcesMgr; 24 25 186 public class LoginContext { 187 188 private static final String INIT_METHOD = "initialize"; 189 private static final String LOGIN_METHOD = "login"; 190 private static final String COMMIT_METHOD = "commit"; 191 private static final String ABORT_METHOD = "abort"; 192 private static final String LOGOUT_METHOD = "logout"; 193 private static final String OTHER = "other"; 194 private static final String DEFAULT_HANDLER = 195 "auth.login.defaultCallbackHandler"; 196 private Subject subject = null; 197 private boolean subjectProvided = false; 198 private boolean loginSucceeded = false; 199 private CallbackHandler callbackHandler; 200 private Map state = new HashMap (); 201 202 private Configuration config; 203 private boolean configProvided = false; 204 private AccessControlContext creatorAcc = null; 205 private ModuleInfo[] moduleStack; 206 private ClassLoader contextClassLoader = null; 207 private static final Class [] PARAMS = { }; 208 209 212 private int moduleIndex = 0; 213 private LoginException firstError = null; 214 private LoginException firstRequiredError = null; 215 private boolean success = false; 216 217 private static final sun.security.util.Debug debug = 218 sun.security.util.Debug.getInstance("logincontext", "\t[LoginContext]"); 219 220 private void init(String name) throws LoginException { 221 222 SecurityManager sm = System.getSecurityManager(); 223 if (sm != null && !configProvided) { 224 sm.checkPermission(new AuthPermission 225 ("createLoginContext." + name)); 226 } 227 228 if (name == null) 229 throw new LoginException 230 (ResourcesMgr.getString("Invalid null input: name")); 231 232 if (config == null) { 234 config = (Configuration )java.security.AccessController.doPrivileged 235 (new java.security.PrivilegedAction () { 236 public Object run() { 237 return Configuration.getConfiguration(); 238 } 239 }); 240 } 241 242 AppConfigurationEntry [] entries = config.getAppConfigurationEntry(name); 244 if (entries == null) { 245 246 if (sm != null && !configProvided) { 247 sm.checkPermission(new AuthPermission 248 ("createLoginContext." + OTHER)); 249 } 250 251 entries = config.getAppConfigurationEntry(OTHER); 252 if (entries == null) { 253 MessageFormat form = new MessageFormat (ResourcesMgr.getString 254 ("No LoginModules configured for name")); 255 Object [] source = {name}; 256 throw new LoginException (form.format(source)); 257 } 258 } 259 moduleStack = new ModuleInfo[entries.length]; 260 for (int i = 0; i < entries.length; i++) { 261 moduleStack[i] = new ModuleInfo 263 (new AppConfigurationEntry 264 (entries[i].getLoginModuleName(), 265 entries[i].getControlFlag(), 266 entries[i].getOptions()), 267 null); 268 } 269 270 contextClassLoader = 271 (ClassLoader )java.security.AccessController.doPrivileged 272 (new java.security.PrivilegedAction () { 273 public Object run() { 274 return Thread.currentThread().getContextClassLoader(); 275 } 276 }); 277 } 278 279 private void loadDefaultCallbackHandler() throws LoginException { 280 281 try { 283 284 final ClassLoader finalLoader = contextClassLoader; 285 286 this.callbackHandler = (CallbackHandler) 287 java.security.AccessController.doPrivileged 288 (new java.security.PrivilegedExceptionAction () { 289 public Object run() throws Exception { 290 String defaultHandler = java.security.Security.getProperty 291 (DEFAULT_HANDLER); 292 if (defaultHandler == null || defaultHandler.length() == 0) 293 return null; 294 Class c = Class.forName(defaultHandler, 295 true, 296 finalLoader); 297 return c.newInstance(); 298 } 299 }); 300 } catch (java.security.PrivilegedActionException pae) { 301 throw new LoginException (pae.getException().toString()); 302 } 303 304 if (this.callbackHandler != null && !configProvided) { 306 this.callbackHandler = new SecureCallbackHandler 307 (java.security.AccessController.getContext(), 308 this.callbackHandler); 309 } 310 } 311 312 333 public LoginContext(String name) throws LoginException { 334 init(name); 335 loadDefaultCallbackHandler(); 336 } 337 338 365 public LoginContext(String name, Subject subject) 366 throws LoginException { 367 init(name); 368 if (subject == null) 369 throw new LoginException 370 (ResourcesMgr.getString("invalid null Subject provided")); 371 this.subject = subject; 372 subjectProvided = true; 373 loadDefaultCallbackHandler(); 374 } 375 376 401 public LoginContext(String name, CallbackHandler callbackHandler) 402 throws LoginException { 403 init(name); 404 if (callbackHandler == null) 405 throw new LoginException (ResourcesMgr.getString 406 ("invalid null CallbackHandler provided")); 407 this.callbackHandler = new SecureCallbackHandler 408 (java.security.AccessController.getContext(), 409 callbackHandler); 410 } 411 412 442 public LoginContext(String name, Subject subject, 443 CallbackHandler callbackHandler) throws LoginException { 444 this(name, subject); 445 if (callbackHandler == null) 446 throw new LoginException (ResourcesMgr.getString 447 ("invalid null CallbackHandler provided")); 448 this.callbackHandler = new SecureCallbackHandler 449 (java.security.AccessController.getContext(), 450 callbackHandler); 451 } 452 453 490 public LoginContext(String name, Subject subject, 491 CallbackHandler callbackHandler, 492 Configuration config) throws LoginException { 493 this.config = config; 494 configProvided = (config != null) ? true : false; 495 if (configProvided) { 496 creatorAcc = java.security.AccessController.getContext(); 497 } 498 499 init(name); 500 if (subject != null) { 501 this.subject = subject; 502 subjectProvided = true; 503 } 504 if (callbackHandler == null) { 505 loadDefaultCallbackHandler(); 506 } else if (!configProvided) { 507 this.callbackHandler = new SecureCallbackHandler 508 (java.security.AccessController.getContext(), 509 callbackHandler); 510 } else { 511 this.callbackHandler = callbackHandler; 512 } 513 } 514 515 564 public void login() throws LoginException { 565 566 loginSucceeded = false; 567 568 if (subject == null) { 569 subject = new Subject (); 570 } 571 572 try { 573 if (configProvided) { 574 invokeCreatorPriv(LOGIN_METHOD); 576 invokeCreatorPriv(COMMIT_METHOD); 577 } else { 578 invokePriv(LOGIN_METHOD); 580 invokePriv(COMMIT_METHOD); 581 } 582 loginSucceeded = true; 583 } catch (LoginException le) { 584 try { 585 if (configProvided) { 586 invokeCreatorPriv(ABORT_METHOD); 587 } else { 588 invokePriv(ABORT_METHOD); 589 } 590 } catch (LoginException le2) { 591 throw le; 592 } 593 throw le; 594 } 595 } 596 597 618 public void logout() throws LoginException { 619 if (subject == null) { 620 throw new LoginException (ResourcesMgr.getString 621 ("null subject - logout called before login")); 622 } 623 624 if (configProvided) { 625 invokeCreatorPriv(LOGOUT_METHOD); 627 } else { 628 invokePriv(LOGOUT_METHOD); 630 } 631 } 632 633 647 public Subject getSubject() { 648 if (!loginSucceeded && !subjectProvided) 649 return null; 650 return subject; 651 } 652 653 private void clearState() { 654 moduleIndex = 0; 655 firstError = null; 656 firstRequiredError = null; 657 success = false; 658 } 659 660 private void throwException(LoginException originalError, LoginException le) 661 throws LoginException { 662 663 clearState(); 665 666 LoginException error = (originalError != null) ? originalError : le; 668 throw error; 669 } 670 671 678 private void invokePriv(final String methodName) throws LoginException { 679 try { 680 java.security.AccessController.doPrivileged 681 (new java.security.PrivilegedExceptionAction () { 682 public Object run() throws LoginException { 683 invoke(methodName); 684 return null; 685 } 686 }); 687 } catch (java.security.PrivilegedActionException pae) { 688 throw (LoginException )pae.getException(); 689 } 690 } 691 692 700 private void invokeCreatorPriv(final String methodName) 701 throws LoginException { 702 try { 703 java.security.AccessController.doPrivileged 704 (new java.security.PrivilegedExceptionAction () { 705 public Object run() throws LoginException { 706 invoke(methodName); 707 return null; 708 } 709 }, creatorAcc); 710 } catch (java.security.PrivilegedActionException pae) { 711 throw (LoginException )pae.getException(); 712 } 713 } 714 715 private void invoke(String methodName) throws LoginException { 716 717 720 for (int i = moduleIndex; i < moduleStack.length; i++, moduleIndex++) { 721 try { 722 723 int mIndex = 0; 724 Method [] methods = null; 725 726 if (moduleStack[i].module != null) { 727 methods = moduleStack[i].module.getClass().getMethods(); 728 } else { 729 730 Class c = Class.forName 732 (moduleStack[i].entry.getLoginModuleName(), 733 true, 734 contextClassLoader); 735 736 Constructor constructor = c.getConstructor(PARAMS); 737 Object [] args = { }; 738 739 moduleStack[i].module = constructor.newInstance(args); 742 743 methods = moduleStack[i].module.getClass().getMethods(); 744 745 for (mIndex = 0; mIndex < methods.length; mIndex++) { 747 if (methods[mIndex].getName().equals(INIT_METHOD)) 748 break; 749 } 750 751 Object [] initArgs = {subject, 752 callbackHandler, 753 state, 754 moduleStack[i].entry.getOptions() }; 755 methods[mIndex].invoke(moduleStack[i].module, initArgs); 757 } 758 759 for (mIndex = 0; mIndex < methods.length; mIndex++) { 761 if (methods[mIndex].getName().equals(methodName)) 762 break; 763 } 764 765 Object [] args = { }; 767 768 boolean status = ((Boolean )methods[mIndex].invoke 770 (moduleStack[i].module, args)).booleanValue(); 771 772 if (status == true) { 773 774 if (!methodName.equals(ABORT_METHOD) && 776 !methodName.equals(LOGOUT_METHOD) && 777 moduleStack[i].entry.getControlFlag() == 778 AppConfigurationEntry.LoginModuleControlFlag.SUFFICIENT && 779 firstRequiredError == null) { 780 781 clearState(); 783 784 if (debug != null) 785 debug.println(methodName + " SUFFICIENT success"); 786 return; 787 } 788 789 if (debug != null) 790 debug.println(methodName + " success"); 791 success = true; 792 } else { 793 if (debug != null) 794 debug.println(methodName + " ignored"); 795 } 796 797 } catch (NoSuchMethodException nsme) { 798 MessageFormat form = new MessageFormat (ResourcesMgr.getString 799 ("unable to instantiate LoginModule, module, because " + 800 "it does not provide a no-argument constructor")); 801 Object [] source = {moduleStack[i].entry.getLoginModuleName()}; 802 throwException(null, new LoginException (form.format(source))); 803 } catch (InstantiationException ie) { 804 throwException(null, new LoginException (ResourcesMgr.getString 805 ("unable to instantiate LoginModule: ") + 806 ie.getMessage())); 807 } catch (ClassNotFoundException cnfe) { 808 throwException(null, new LoginException (ResourcesMgr.getString 809 ("unable to find LoginModule class: ") + 810 cnfe.getMessage())); 811 } catch (IllegalAccessException iae) { 812 throwException(null, new LoginException (ResourcesMgr.getString 813 ("unable to access LoginModule: ") + 814 iae.getMessage())); 815 } catch (InvocationTargetException ite) { 816 817 819 LoginException le; 820 821 if (ite.getCause() instanceof PendingException && 822 methodName.equals(LOGIN_METHOD)) { 823 824 845 throw (PendingException)ite.getCause(); 846 847 } else if (ite.getCause() instanceof LoginException ) { 848 849 le = (LoginException )ite.getCause(); 850 851 } else if (ite.getCause() instanceof SecurityException ) { 852 853 856 le = new LoginException ("Security Exception"); 857 le.initCause(new SecurityException ()); 858 if (debug != null) { 859 debug.println 860 ("original security exception with detail msg " + 861 "replaced by new exception with empty detail msg"); 862 debug.println("original security exception: " + 863 ite.getCause().toString()); 864 } 865 } else { 866 867 java.io.StringWriter sw = new java.io.StringWriter (); 869 ite.getCause().printStackTrace 870 (new java.io.PrintWriter (sw)); 871 sw.flush(); 872 le = new LoginException (sw.toString()); 873 } 874 875 if (moduleStack[i].entry.getControlFlag() == 876 AppConfigurationEntry.LoginModuleControlFlag.REQUISITE) { 877 878 if (debug != null) 879 debug.println(methodName + " REQUISITE failure"); 880 881 if (methodName.equals(ABORT_METHOD) || 883 methodName.equals(LOGOUT_METHOD)) { 884 if (firstRequiredError == null) 885 firstRequiredError = le; 886 } else { 887 throwException(firstRequiredError, le); 888 } 889 890 } else if (moduleStack[i].entry.getControlFlag() == 891 AppConfigurationEntry.LoginModuleControlFlag.REQUIRED) { 892 893 if (debug != null) 894 debug.println(methodName + " REQUIRED failure"); 895 896 if (firstRequiredError == null) 898 firstRequiredError = le; 899 900 } else { 901 902 if (debug != null) 903 debug.println(methodName + " OPTIONAL failure"); 904 905 if (firstError == null) 907 firstError = le; 908 } 909 } 910 } 911 912 if (firstRequiredError != null) { 914 throwException(firstRequiredError, null); 916 } else if (success == false && firstError != null) { 917 throwException(firstError, null); 919 } else if (success == false) { 920 throwException(new LoginException 922 (ResourcesMgr.getString("Login Failure: all modules ignored")), 923 null); 924 } else { 925 927 clearState(); 928 return; 929 } 930 } 931 932 937 private static class SecureCallbackHandler implements CallbackHandler { 938 939 private final java.security.AccessControlContext acc; 940 private final CallbackHandler ch; 941 942 SecureCallbackHandler(java.security.AccessControlContext acc, 943 CallbackHandler ch) { 944 this.acc = acc; 945 this.ch = ch; 946 } 947 948 public void handle(final Callback[] callbacks) 949 throws java.io.IOException , UnsupportedCallbackException { 950 try { 951 java.security.AccessController.doPrivileged 952 (new java.security.PrivilegedExceptionAction () { 953 public Object run() throws java.io.IOException , 954 UnsupportedCallbackException { 955 ch.handle(callbacks); 956 return null; 957 } 958 }, acc); 959 } catch (java.security.PrivilegedActionException pae) { 960 if (pae.getException() instanceof java.io.IOException ) { 961 throw (java.io.IOException )pae.getException(); 962 } else { 963 throw (UnsupportedCallbackException)pae.getException(); 964 } 965 } 966 } 967 } 968 969 973 private static class ModuleInfo { 974 AppConfigurationEntry entry; 975 Object module; 976 977 ModuleInfo(AppConfigurationEntry newEntry, Object newModule) { 978 this.entry = newEntry; 979 this.module = newModule; 980 } 981 } 982 } 983 | Popular Tags |