Source Code Cross Referenced for LoginContext.java in  » 6.0-JDK-Core » security » javax » security » auth » login » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Home
Java Source Code / Java Documentation
1.6.0 JDK Core
2.6.0 JDK Modules
3.6.0 JDK Modules com.sun
4.6.0 JDK Modules com.sun.java
5.6.0 JDK Modules sun
6.6.0 JDK Platform
7.Ajax
8.Apache Harmony Java SE
9.Aspect oriented
10.Authentication Authorization
11.Blogger System
12.Build
13.Byte Code
14.Cache
15.Chart
16.Chat
17.Code Analyzer
18.Collaboration
19.Content Management System
20.Database Client
21.Database DBMS
22.Database JDBC Connection Pool
23.Database ORM
24.Development
25.EJB Server
26.ERP CRM Financial
27.ESB
28.Forum
29.Game
30.GIS
31.Graphic 3D
32.Graphic Library
33.Groupware
34.HTML Parser
35.IDE
36.IDE Eclipse
37.IDE Netbeans
38.Installer
39.Internationalization Localization
40.Inversion of Control
41.Issue Tracking
42.J2EE
43.J2ME
44.JBoss
45.JMS
46.JMX
47.Library
48.Mail Clients
49.Music
50.Net
51.Parser
52.PDF
53.Portal
54.Profiler
55.Project Management
56.Report
57.RSS RDF
58.Rule Engine
59.Science
60.Scripting
61.Search Engine
62.Security
63.Sevlet Container
64.Source Control
65.Swing Library
66.Template Engine
67.Test Coverage
68.Testing
69.UML
70.Web Crawler
71.Web Framework
72.Web Mail
73.Web Server
74.Web Services
75.Web Services apache cxf 2.2.6
76.Web Services AXIS2
77.Wiki Engine
78.Workflow Engines
79.XML
80.XML UI
Java Source Code / Java Documentation » 6.0 JDK Core » security » javax.security.auth.login 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001        /*
0002         * Copyright 1998-2006 Sun Microsystems, Inc.  All Rights Reserved.
0003         * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0004         *
0005         * This code is free software; you can redistribute it and/or modify it
0006         * under the terms of the GNU General Public License version 2 only, as
0007         * published by the Free Software Foundation.  Sun designates this
0008         * particular file as subject to the "Classpath" exception as provided
0009         * by Sun in the LICENSE file that accompanied this code.
0010         *
0011         * This code is distributed in the hope that it will be useful, but WITHOUT
0012         * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0013         * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
0014         * version 2 for more details (a copy is included in the LICENSE file that
0015         * accompanied this code).
0016         *
0017         * You should have received a copy of the GNU General Public License version
0018         * 2 along with this work; if not, write to the Free Software Foundation,
0019         * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0020         *
0021         * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
0022         * CA 95054 USA or visit www.sun.com if you need additional information or
0023         * have any questions.
0024         */
0025
0026        package javax.security.auth.login;
0027
0028        import java.lang.reflect.Constructor;
0029        import java.lang.reflect.Method;
0030        import java.lang.reflect.InvocationTargetException;
0031        import java.util.LinkedList;
0032        import java.util.Map;
0033        import java.util.HashMap;
0034        import java.text.MessageFormat;
0035        import javax.security.auth.Subject;
0036        import javax.security.auth.AuthPermission;
0037        import javax.security.auth.callback.*;
0038        import java.security.AccessController;
0039        import java.security.AccessControlContext;
0040        import sun.security.util.PendingException;
0041        import sun.security.util.ResourcesMgr;
0042
0043        /**
0044         * <p> The <code>LoginContext</code> class describes the basic methods used
0045         * to authenticate Subjects and provides a way to develop an
0046         * application independent of the underlying authentication technology.
0047         * A <code>Configuration</code> specifies the authentication technology, or
0048         * <code>LoginModule</code>, to be used with a particular application.
0049         * Different LoginModules can be plugged in under an application
0050         * without requiring any modifications to the application itself.
0051         *
0052         * <p> In addition to supporting <i>pluggable</i> authentication, this class
0053         * also supports the notion of <i>stacked</i> authentication.
0054         * Applications may be configured to use more than one
0055         * LoginModule.  For example, one could
0056         * configure both a Kerberos LoginModule and a smart card
0057         * LoginModule under an application.
0058         *
0059         * <p> A typical caller instantiates a LoginContext with
0060         * a <i>name</i> and a <code>CallbackHandler</code>.
0061         * LoginContext uses the <i>name</i> as the index into a
0062         * Configuration to determine which LoginModules should be used,
0063         * and which ones must succeed in order for the overall authentication to
0064         * succeed.  The <code>CallbackHandler</code> is passed to the underlying
0065         * LoginModules so they may communicate and interact with users
0066         * (prompting for a username and password via a graphical user interface,
0067         * for example).
0068         *
0069         * <p> Once the caller has instantiated a LoginContext,
0070         * it invokes the <code>login</code> method to authenticate
0071         * a <code>Subject</code>.  The <code>login</code> method invokes
0072         * the configured modules to perform their respective types of authentication
0073         * (username/password, smart card pin verification, etc.).
0074         * Note that the LoginModules will not attempt authentication retries nor
0075         * introduce delays if the authentication fails.
0076         * Such tasks belong to the LoginContext caller.
0077         *
0078         * <p> If the <code>login</code> method returns without
0079         * throwing an exception, then the overall authentication succeeded.
0080         * The caller can then retrieve
0081         * the newly authenticated Subject by invoking the
0082         * <code>getSubject</code> method.  Principals and Credentials associated
0083         * with the Subject may be retrieved by invoking the Subject's
0084         * respective <code>getPrincipals</code>, <code>getPublicCredentials</code>,
0085         * and <code>getPrivateCredentials</code> methods.
0086         *
0087         * <p> To logout the Subject, the caller calls
0088         * the <code>logout</code> method.  As with the <code>login</code>
0089         * method, this <code>logout</code> method invokes the <code>logout</code>
0090         * method for the configured modules.
0091         * 
0092         * <p> A LoginContext should not be used to authenticate
0093         * more than one Subject.  A separate LoginContext
0094         * should be used to authenticate each different Subject.
0095         *
0096         * <p> The following documentation applies to all LoginContext constructors:
0097         * <ol>
0098         *
0099         * <li> <code>Subject</code>
0100         * <ul>
0101         * <li> If the constructor has a Subject
0102         * input parameter, the LoginContext uses the caller-specified
0103         * Subject object.
0104         * <p>
0105         * <li> If the caller specifies a <code>null</code> Subject
0106         * and a <code>null</code> value is permitted,
0107         * the LoginContext instantiates a new Subject.
0108         * <p>
0109         * <li> If the constructor does <b>not</b> have a Subject
0110         * input parameter, the LoginContext instantiates a new Subject.
0111         * <p>
0112         * </ul>
0113         *
0114         * <li> <code>Configuration</code> 
0115         * <ul> 
0116         * <li> If the constructor has a Configuration 
0117         * input parameter and the caller specifies a non-null Configuration, 
0118         * the LoginContext uses the caller-specified Configuration.
0119         * <p>
0120         * If the constructor does <b>not</b> have a Configuration
0121         * input parameter, or if the caller specifies a <code>null</code>
0122         * Configuration object, the constructor uses the following call to
0123         * get the installed Configuration:
0124         * <pre>
0125         *      config = Configuration.getConfiguration();
0126         * </pre>
0127         * For both cases,
0128         * the <i>name</i> argument given to the constructor is passed to the
0129         * <code>Configuration.getAppConfigurationEntry</code> method.
0130         * If the Configuration has no entries for the specified <i>name</i>,
0131         * then the <code>LoginContext</code> calls
0132         * <code>getAppConfigurationEntry</code> with the name, "<i>other</i>"
0133         * (the default entry name).  If there is no entry for "<i>other</i>",
0134         * then a <code>LoginException</code> is thrown.
0135         * <p>
0136         * <li> When LoginContext uses the installed Configuration, the caller
0137         * requires the createLoginContext.<em>name</em> and possibly
0138         * createLoginContext.other AuthPermissions. Furthermore, the
0139         * LoginContext will invoke configured modules from within an
0140         * <code>AccessController.doPrivileged</code> call so that modules that
0141         * perform security-sensitive tasks (such as connecting to remote hosts,
0142         * and updating the Subject) will require the respective permissions, but
0143         * the callers of the LoginContext will not require those permissions.
0144         * <p>
0145         * <li> When LoginContext uses a caller-specified Configuration, the caller
0146         * does not require any createLoginContext AuthPermission.  The LoginContext
0147         * saves the <code>AccessControlContext</code> for the caller,
0148         * and invokes the configured modules from within an
0149         * <tt>AccessController.doPrivileged</tt> call constrained by that context.
0150         * This means the caller context (stored when the LoginContext was created)
0151         * must have sufficient permissions to perform any security-sensitive tasks
0152         * that the modules may perform.
0153         * <p>
0154         * </ul>
0155         *
0156         * <li> <code>CallbackHandler</code>
0157         * <ul>
0158         * <li> If the constructor has a CallbackHandler
0159         * input parameter, the LoginContext uses the caller-specified
0160         * CallbackHandler object.
0161         * <p>
0162         * <li> If the constructor does <b>not</b> have a CallbackHandler
0163         * input parameter, or if the caller specifies a <code>null</code>
0164         * CallbackHandler object (and a <code>null</code> value is permitted),
0165         * the LoginContext queries the
0166         * <i>auth.login.defaultCallbackHandler</i> security property
0167         * for the fully qualified class name of a default handler implementation.
0168         * If the security property is not set,
0169         * then the underlying modules will not have a
0170         * CallbackHandler for use in communicating
0171         * with users.  The caller thus assumes that the configured
0172         * modules have alternative means for authenticating the user.
0173         *
0174         * <p>
0175         * <li> When the LoginContext uses the installed Configuration (instead of
0176         * a caller-specified Configuration, see above),
0177         * then this LoginContext must wrap any
0178         * caller-specified or default CallbackHandler implementation
0179         * in a new CallbackHandler implementation
0180         * whose <code>handle</code> method implementation invokes the
0181         * specified CallbackHandler's <code>handle</code> method in a
0182         * <code>java.security.AccessController.doPrivileged</code> call
0183         * constrained by the caller's current <code>AccessControlContext</code>.
0184         * </ul>
0185         * </ol>
0186         *
0187         * <p> Note that Security Properties
0188         * (such as <code>auth.login.defaultCallbackHandler</code>)
0189         * can be set programmatically via the
0190         * <code>java.security.Security</code> class,
0191         * or statically in the Java security properties file located in the
0192         * file named &lt;JAVA_HOME&gt;/lib/security/java.security.
0193         * &lt;JAVA_HOME&gt; refers to the value of the java.home system property,
0194         * and specifies the directory where the JRE is installed.
0195         * 
0196         * @version 1.107, 05/05/07
0197         * @see java.security.Security
0198         * @see javax.security.auth.AuthPermission
0199         * @see javax.security.auth.Subject
0200         * @see javax.security.auth.callback.CallbackHandler
0201         * @see javax.security.auth.login.Configuration
0202         * @see javax.security.auth.spi.LoginModule
0203         */
0204        public class LoginContext {
0205
0206            private static final String INIT_METHOD = "initialize";
0207            private static final String LOGIN_METHOD = "login";
0208            private static final String COMMIT_METHOD = "commit";
0209            private static final String ABORT_METHOD = "abort";
0210            private static final String LOGOUT_METHOD = "logout";
0211            private static final String OTHER = "other";
0212            private static final String DEFAULT_HANDLER = "auth.login.defaultCallbackHandler";
0213            private Subject subject = null;
0214            private boolean subjectProvided = false;
0215            private boolean loginSucceeded = false;
0216            private CallbackHandler callbackHandler;
0217            private Map state = new HashMap();
0218
0219            private Configuration config;
0220            private boolean configProvided = false;
0221            private AccessControlContext creatorAcc = null;
0222            private ModuleInfo[] moduleStack;
0223            private ClassLoader contextClassLoader = null;
0224            private static final Class[] PARAMS = {};
0225
0226            // state saved in the event a user-specified asynchronous exception
0227            // was specified and thrown
0228
0229            private int moduleIndex = 0;
0230            private LoginException firstError = null;
0231            private LoginException firstRequiredError = null;
0232            private boolean success = false;
0233
0234            private static final sun.security.util.Debug debug = sun.security.util.Debug
0235                    .getInstance("logincontext", "\t[LoginContext]");
0236
0237            private void init(String name) throws LoginException {
0238
0239                SecurityManager sm = System.getSecurityManager();
0240                if (sm != null && !configProvided) {
0241                    sm.checkPermission(new AuthPermission("createLoginContext."
0242                            + name));
0243                }
0244
0245                if (name == null)
0246                    throw new LoginException(ResourcesMgr
0247                            .getString("Invalid null input: name"));
0248
0249                // get the Configuration
0250                if (config == null) {
0251                    config = java.security.AccessController
0252                            .doPrivileged(new java.security.PrivilegedAction<Configuration>() {
0253                                public Configuration run() {
0254                                    return Configuration.getConfiguration();
0255                                }
0256                            });
0257                }
0258
0259                // get the LoginModules configured for this application
0260                AppConfigurationEntry[] entries = config
0261                        .getAppConfigurationEntry(name);
0262                if (entries == null) {
0263
0264                    if (sm != null && !configProvided) {
0265                        sm.checkPermission(new AuthPermission(
0266                                "createLoginContext." + OTHER));
0267                    }
0268
0269                    entries = config.getAppConfigurationEntry(OTHER);
0270                    if (entries == null) {
0271                        MessageFormat form = new MessageFormat(
0272                                ResourcesMgr
0273                                        .getString("No LoginModules configured for name"));
0274                        Object[] source = { name };
0275                        throw new LoginException(form.format(source));
0276                    }
0277                }
0278                moduleStack = new ModuleInfo[entries.length];
0279                for (int i = 0; i < entries.length; i++) {
0280                    // clone returned array
0281                    moduleStack[i] = new ModuleInfo(
0282                            new AppConfigurationEntry(entries[i]
0283                                    .getLoginModuleName(), entries[i]
0284                                    .getControlFlag(), entries[i].getOptions()),
0285                            null);
0286                }
0287
0288                contextClassLoader = java.security.AccessController
0289                        .doPrivileged(new java.security.PrivilegedAction<ClassLoader>() {
0290                            public ClassLoader run() {
0291                                return Thread.currentThread()
0292                                        .getContextClassLoader();
0293                            }
0294                        });
0295            }
0296
0297            private void loadDefaultCallbackHandler() throws LoginException {
0298
0299                // get the default handler class
0300                try {
0301
0302                    final ClassLoader finalLoader = contextClassLoader;
0303
0304                    this .callbackHandler = java.security.AccessController
0305                            .doPrivileged(new java.security.PrivilegedExceptionAction<CallbackHandler>() {
0306                                public CallbackHandler run() throws Exception {
0307                                    String defaultHandler = java.security.Security
0308                                            .getProperty(DEFAULT_HANDLER);
0309                                    if (defaultHandler == null
0310                                            || defaultHandler.length() == 0)
0311                                        return null;
0312                                    Class c = Class.forName(defaultHandler,
0313                                            true, finalLoader);
0314                                    return (CallbackHandler) c.newInstance();
0315                                }
0316                            });
0317                } catch (java.security.PrivilegedActionException pae) {
0318                    throw new LoginException(pae.getException().toString());
0319                }
0320
0321                // secure it with the caller's ACC
0322                if (this .callbackHandler != null && !configProvided) {
0323                    this .callbackHandler = new SecureCallbackHandler(
0324                            java.security.AccessController.getContext(),
0325                            this .callbackHandler);
0326                }
0327            }
0328
0329            /**
0330             * Instantiate a new <code>LoginContext</code> object with a name.
0331             *
0332             * @param name the name used as the index into the
0333             *		<code>Configuration</code>.
0334             *
0335             * @exception LoginException if the caller-specified <code>name</code>
0336             *		does not appear in the <code>Configuration</code>
0337             *		and there is no <code>Configuration</code> entry
0338             *		for "<i>other</i>", or if the
0339             *		<i>auth.login.defaultCallbackHandler</i>
0340             *		security property was set, but the implementation
0341             *		class could not be loaded.
0342             *		<p>
0343             * @exception SecurityException if a SecurityManager is set and
0344             *		the caller does not have
0345             *		AuthPermission("createLoginContext.<i>name</i>"),
0346             *		or if a configuration entry for <i>name</i> does not exist and
0347             *		the caller does not additionally have
0348             *		AuthPermission("createLoginContext.other")
0349             */
0350            public LoginContext(String name) throws LoginException {
0351                init(name);
0352                loadDefaultCallbackHandler();
0353            }
0354
0355            /**
0356             * Instantiate a new <code>LoginContext</code> object with a name
0357             * and a <code>Subject</code> object.
0358             *
0359             * <p>
0360             *
0361             * @param name the name used as the index into the
0362             *		<code>Configuration</code>. <p>
0363             *
0364             * @param subject the <code>Subject</code> to authenticate.
0365             *
0366             * @exception LoginException if the caller-specified <code>name</code>
0367             *		does not appear in the <code>Configuration</code>
0368             *          and there is no <code>Configuration</code> entry
0369             *          for "<i>other</i>", if the caller-specified <code>subject</code>
0370             *		is <code>null</code>, or if the
0371             *		<i>auth.login.defaultCallbackHandler</i>
0372             *		security property was set, but the implementation
0373             *		class could not be loaded.
0374             *		<p>
0375             * @exception SecurityException if a SecurityManager is set and
0376             *		the caller does not have
0377             *		AuthPermission("createLoginContext.<i>name</i>"),
0378             *		or if a configuration entry for <i>name</i> does not exist and
0379             *		the caller does not additionally have
0380             *		AuthPermission("createLoginContext.other")
0381             */
0382            public LoginContext(String name, Subject subject)
0383                    throws LoginException {
0384                init(name);
0385                if (subject == null)
0386                    throw new LoginException(ResourcesMgr
0387                            .getString("invalid null Subject provided"));
0388                this .subject = subject;
0389                subjectProvided = true;
0390                loadDefaultCallbackHandler();
0391            }
0392
0393            /**
0394             * Instantiate a new <code>LoginContext</code> object with a name
0395             * and a <code>CallbackHandler</code> object.
0396             *
0397             * <p>
0398             *
0399             * @param name the name used as the index into the
0400             *		<code>Configuration</code>. <p>
0401             *
0402             * @param callbackHandler the <code>CallbackHandler</code> object used by
0403             *		LoginModules to communicate with the user.
0404             *
0405             * @exception LoginException if the caller-specified <code>name</code>
0406             *          does not appear in the <code>Configuration</code>
0407             *          and there is no <code>Configuration</code> entry
0408             *          for "<i>other</i>", or if the caller-specified
0409             *		<code>callbackHandler</code> is <code>null</code>.
0410             *		<p>
0411             * @exception SecurityException if a SecurityManager is set and
0412             *		the caller does not have
0413             *		AuthPermission("createLoginContext.<i>name</i>"),
0414             *		or if a configuration entry for <i>name</i> does not exist and
0415             *		the caller does not additionally have
0416             *		AuthPermission("createLoginContext.other")
0417             */
0418            public LoginContext(String name, CallbackHandler callbackHandler)
0419                    throws LoginException {
0420                init(name);
0421                if (callbackHandler == null)
0422                    throw new LoginException(ResourcesMgr
0423                            .getString("invalid null CallbackHandler provided"));
0424                this .callbackHandler = new SecureCallbackHandler(
0425                        java.security.AccessController.getContext(),
0426                        callbackHandler);
0427            }
0428
0429            /**
0430             * Instantiate a new <code>LoginContext</code> object with a name,
0431             * a <code>Subject</code> to be authenticated, and a
0432             * <code>CallbackHandler</code> object.
0433             *
0434             * <p>
0435             *
0436             * @param name the name used as the index into the
0437             *		<code>Configuration</code>. <p>
0438             *
0439             * @param subject the <code>Subject</code> to authenticate. <p>
0440             *
0441             * @param callbackHandler the <code>CallbackHandler</code> object used by
0442             *		LoginModules to communicate with the user.
0443             *
0444             * @exception LoginException if the caller-specified <code>name</code>
0445             *          does not appear in the <code>Configuration</code>
0446             *          and there is no <code>Configuration</code> entry
0447             *          for "<i>other</i>", or if the caller-specified
0448             *		<code>subject</code> is <code>null</code>,
0449             *		or if the caller-specified
0450             *		<code>callbackHandler</code> is <code>null</code>.
0451             *		<p>
0452             * @exception SecurityException if a SecurityManager is set and
0453             *		the caller does not have
0454             *		AuthPermission("createLoginContext.<i>name</i>"),
0455             *		or if a configuration entry for <i>name</i> does not exist and
0456             *		the caller does not additionally have
0457             *		AuthPermission("createLoginContext.other")
0458             */
0459            public LoginContext(String name, Subject subject,
0460                    CallbackHandler callbackHandler) throws LoginException {
0461                this (name, subject);
0462                if (callbackHandler == null)
0463                    throw new LoginException(ResourcesMgr
0464                            .getString("invalid null CallbackHandler provided"));
0465                this .callbackHandler = new SecureCallbackHandler(
0466                        java.security.AccessController.getContext(),
0467                        callbackHandler);
0468            }
0469
0470            /**
0471             * Instantiate a new <code>LoginContext</code> object with a name,
0472             * a <code>Subject</code> to be authenticated,
0473             * a <code>CallbackHandler</code> object, and a login
0474             * <code>Configuration</code>.
0475             *
0476             * <p>
0477             *
0478             * @param name the name used as the index into the caller-specified
0479             *          <code>Configuration</code>. <p>
0480             *
0481             * @param subject the <code>Subject</code> to authenticate,
0482             *          or <code>null</code>. <p>
0483             *
0484             * @param callbackHandler the <code>CallbackHandler</code> object used by
0485             *          LoginModules to communicate with the user, or <code>null</code>.
0486             *		<p>
0487             *
0488             * @param config the <code>Configuration</code> that lists the
0489             *          login modules to be called to perform the authentication,
0490             *          or <code>null</code>.
0491             *
0492             * @exception LoginException if the caller-specified <code>name</code>
0493             *          does not appear in the <code>Configuration</code>
0494             *          and there is no <code>Configuration</code> entry
0495             *          for "<i>other</i>".
0496             *		<p>
0497             * @exception SecurityException if a SecurityManager is set,
0498             *		<i>config</i> is <code>null</code>,
0499             *		and either the caller does not have
0500             *		AuthPermission("createLoginContext.<i>name</i>"),
0501             *		or if a configuration entry for <i>name</i> does not exist and
0502             *		the caller does not additionally have
0503             *		AuthPermission("createLoginContext.other")
0504             *
0505             * @since 1.5
0506             */
0507            public LoginContext(String name, Subject subject,
0508                    CallbackHandler callbackHandler, Configuration config)
0509                    throws LoginException {
0510                this .config = config;
0511                configProvided = (config != null) ? true : false;
0512                if (configProvided) {
0513                    creatorAcc = java.security.AccessController.getContext();
0514                }
0515
0516                init(name);
0517                if (subject != null) {
0518                    this .subject = subject;
0519                    subjectProvided = true;
0520                }
0521                if (callbackHandler == null) {
0522                    loadDefaultCallbackHandler();
0523                } else if (!configProvided) {
0524                    this .callbackHandler = new SecureCallbackHandler(
0525                            java.security.AccessController.getContext(),
0526                            callbackHandler);
0527                } else {
0528                    this .callbackHandler = callbackHandler;
0529                }
0530            }
0531
0532            /**
0533             * Perform the authentication.
0534             *
0535             * <p> This method invokes the <code>login</code> method for each
0536             * LoginModule configured for the <i>name</i> specified to the
0537             * <code>LoginContext</code> constructor, as determined by the login
0538             * <code>Configuration</code>.  Each <code>LoginModule</code>
0539             * then performs its respective type of authentication
0540             * (username/password, smart card pin verification, etc.).
0541             *
0542             * <p> This method completes a 2-phase authentication process by
0543             * calling each configured LoginModule's <code>commit</code> method
0544             * if the overall authentication succeeded (the relevant REQUIRED,
0545             * REQUISITE, SUFFICIENT, and OPTIONAL LoginModules succeeded),
0546             * or by calling each configured LoginModule's <code>abort</code> method
0547             * if the overall authentication failed.  If authentication succeeded,
0548             * each successful LoginModule's <code>commit</code> method associates
0549             * the relevant Principals and Credentials with the <code>Subject</code>.
0550             * If authentication failed, each LoginModule's <code>abort</code> method
0551             * removes/destroys any previously stored state.
0552             *
0553             * <p> If the <code>commit</code> phase of the authentication process
0554             * fails, then the overall authentication fails and this method
0555             * invokes the <code>abort</code> method for each configured
0556             * <code>LoginModule</code>.
0557             *
0558             * <p> If the <code>abort</code> phase
0559             * fails for any reason, then this method propagates the
0560             * original exception thrown either during the <code>login</code> phase
0561             * or the <code>commit</code> phase.  In either case, the overall
0562             * authentication fails.
0563             *
0564             * <p> In the case where multiple LoginModules fail,
0565             * this method propagates the exception raised by the first
0566             * <code>LoginModule</code> which failed.
0567             *
0568             * <p> Note that if this method enters the <code>abort</code> phase
0569             * (either the <code>login</code> or <code>commit</code> phase failed),
0570             * this method invokes all LoginModules configured for the
0571             * application regardless of their respective <code>Configuration</code>
0572             * flag parameters.  Essentially this means that <code>Requisite</code>
0573             * and <code>Sufficient</code> semantics are ignored during the
0574             * <code>abort</code> phase.  This guarantees that proper cleanup
0575             * and state restoration can take place.
0576             * 
0577             * <p>
0578             *
0579             * @exception LoginException if the authentication fails.
0580             */
0581            public void login() throws LoginException {
0582
0583                loginSucceeded = false;
0584
0585                if (subject == null) {
0586                    subject = new Subject();
0587                }
0588
0589                try {
0590                    if (configProvided) {
0591                        // module invoked in doPrivileged with creatorAcc
0592                        invokeCreatorPriv(LOGIN_METHOD);
0593                        invokeCreatorPriv(COMMIT_METHOD);
0594                    } else {
0595                        // module invoked in doPrivileged
0596                        invokePriv(LOGIN_METHOD);
0597                        invokePriv(COMMIT_METHOD);
0598                    }
0599                    loginSucceeded = true;
0600                } catch (LoginException le) {
0601                    try {
0602                        if (configProvided) {
0603                            invokeCreatorPriv(ABORT_METHOD);
0604                        } else {
0605                            invokePriv(ABORT_METHOD);
0606                        }
0607                    } catch (LoginException le2) {
0608                        throw le;
0609                    }
0610                    throw le;
0611                }
0612            }
0613
0614            /**
0615             * Logout the <code>Subject</code>.
0616             *
0617             * <p> This method invokes the <code>logout</code> method for each
0618             * <code>LoginModule</code> configured for this <code>LoginContext</code>.
0619             * Each <code>LoginModule</code> performs its respective logout procedure
0620             * which may include removing/destroying
0621             * <code>Principal</code> and <code>Credential</code> information
0622             * from the <code>Subject</code> and state cleanup.
0623             *
0624             * <p> Note that this method invokes all LoginModules configured for the
0625             * application regardless of their respective
0626             * <code>Configuration</code> flag parameters.  Essentially this means
0627             * that <code>Requisite</code> and <code>Sufficient</code> semantics are
0628             * ignored for this method.  This guarantees that proper cleanup
0629             * and state restoration can take place.
0630             * 
0631             * <p>
0632             *
0633             * @exception LoginException if the logout fails.
0634             */
0635            public void logout() throws LoginException {
0636                if (subject == null) {
0637                    throw new LoginException(
0638                            ResourcesMgr
0639                                    .getString("null subject - logout called before login"));
0640                }
0641
0642                if (configProvided) {
0643                    // module invoked in doPrivileged with creatorAcc
0644                    invokeCreatorPriv(LOGOUT_METHOD);
0645                } else {
0646                    // module invoked in doPrivileged
0647                    invokePriv(LOGOUT_METHOD);
0648                }
0649            }
0650
0651            /**
0652             * Return the authenticated Subject.
0653             *
0654             * <p>
0655             *
0656             * @return the authenticated Subject.  If the caller specified a
0657             *		Subject to this LoginContext's constructor,
0658             *		this method returns the caller-specified Subject.
0659             *		If a Subject was not specified and authentication succeeds,
0660             *		this method returns the Subject instantiated and used for
0661             *		authentication by this LoginContext.
0662             *		If a Subject was not specified, and authentication fails or
0663             *		has not been attempted, this method returns null.
0664             */
0665            public Subject getSubject() {
0666                if (!loginSucceeded && !subjectProvided)
0667                    return null;
0668                return subject;
0669            }
0670
0671            private void clearState() {
0672                moduleIndex = 0;
0673                firstError = null;
0674                firstRequiredError = null;
0675                success = false;
0676            }
0677
0678            private void throwException(LoginException originalError,
0679                    LoginException le) throws LoginException {
0680
0681                // first clear state
0682                clearState();
0683
0684                // throw the exception
0685                LoginException error = (originalError != null) ? originalError
0686                        : le;
0687                throw error;
0688            }
0689
0690            /**
0691             * Invokes the login, commit, and logout methods
0692             * from a LoginModule inside a doPrivileged block.
0693             *
0694             * This version is called if the caller did not instantiate
0695             * the LoginContext with a Configuration object.
0696             */
0697            private void invokePriv(final String methodName)
0698                    throws LoginException {
0699                try {
0700                    java.security.AccessController
0701                            .doPrivileged(new java.security.PrivilegedExceptionAction<Void>() {
0702                                public Void run() throws LoginException {
0703                                    invoke(methodName);
0704                                    return null;
0705                                }
0706                            });
0707                } catch (java.security.PrivilegedActionException pae) {
0708                    throw (LoginException) pae.getException();
0709                }
0710            }
0711
0712            /**
0713             * Invokes the login, commit, and logout methods
0714             * from a LoginModule inside a doPrivileged block restricted
0715             * by creatorAcc
0716             *
0717             * This version is called if the caller instantiated
0718             * the LoginContext with a Configuration object.
0719             */
0720            private void invokeCreatorPriv(final String methodName)
0721                    throws LoginException {
0722                try {
0723                    java.security.AccessController
0724                            .doPrivileged(
0725                                    new java.security.PrivilegedExceptionAction<Void>() {
0726                                        public Void run() throws LoginException {
0727                                            invoke(methodName);
0728                                            return null;
0729                                        }
0730                                    }, creatorAcc);
0731                } catch (java.security.PrivilegedActionException pae) {
0732                    throw (LoginException) pae.getException();
0733                }
0734            }
0735
0736            private void invoke(String methodName) throws LoginException {
0737
0738                // start at moduleIndex
0739                // - this can only be non-zero if methodName is LOGIN_METHOD
0740
0741                for (int i = moduleIndex; i < moduleStack.length; i++, moduleIndex++) {
0742                    try {
0743
0744                        int mIndex = 0;
0745                        Method[] methods = null;
0746
0747                        if (moduleStack[i].module != null) {
0748                            methods = moduleStack[i].module.getClass()
0749                                    .getMethods();
0750                        } else {
0751
0752                            // instantiate the LoginModule
0753                            Class c = Class.forName(moduleStack[i].entry
0754                                    .getLoginModuleName(), true,
0755                                    contextClassLoader);
0756
0757                            Constructor constructor = c.getConstructor(PARAMS);
0758                            Object[] args = {};
0759
0760                            // allow any object to be a LoginModule
0761                            // as long as it conforms to the interface
0762                            moduleStack[i].module = constructor
0763                                    .newInstance(args);
0764
0765                            methods = moduleStack[i].module.getClass()
0766                                    .getMethods();
0767
0768                            // call the LoginModule's initialize method
0769                            for (mIndex = 0; mIndex < methods.length; mIndex++) {
0770                                if (methods[mIndex].getName().equals(
0771                                        INIT_METHOD))
0772                                    break;
0773                            }
0774
0775                            Object[] initArgs = { subject, callbackHandler,
0776                                    state, moduleStack[i].entry.getOptions() };
0777                            // invoke the LoginModule initialize method
0778                            methods[mIndex].invoke(moduleStack[i].module,
0779                                    initArgs);
0780                        }
0781
0782                        // find the requested method in the LoginModule
0783                        for (mIndex = 0; mIndex < methods.length; mIndex++) {
0784                            if (methods[mIndex].getName().equals(methodName))
0785                                break;
0786                        }
0787
0788                        // set up the arguments to be passed to the LoginModule method
0789                        Object[] args = {};
0790
0791                        // invoke the LoginModule method
0792                        boolean status = ((Boolean) methods[mIndex].invoke(
0793                                moduleStack[i].module, args)).booleanValue();
0794
0795                        if (status == true) {
0796
0797                            // if SUFFICIENT, return if no prior REQUIRED errors
0798                            if (!methodName.equals(ABORT_METHOD)
0799                                    && !methodName.equals(LOGOUT_METHOD)
0800                                    && moduleStack[i].entry.getControlFlag() == AppConfigurationEntry.LoginModuleControlFlag.SUFFICIENT
0801                                    && firstRequiredError == null) {
0802
0803                                // clear state
0804                                clearState();
0805
0806                                if (debug != null)
0807                                    debug.println(methodName
0808                                            + " SUFFICIENT success");
0809                                return;
0810                            }
0811
0812                            if (debug != null)
0813                                debug.println(methodName + " success");
0814                            success = true;
0815                        } else {
0816                            if (debug != null)
0817                                debug.println(methodName + " ignored");
0818                        }
0819
0820                    } catch (NoSuchMethodException nsme) {
0821                        MessageFormat form = new MessageFormat(
0822                                ResourcesMgr
0823                                        .getString("unable to instantiate LoginModule, module, because "
0824                                                + "it does not provide a no-argument constructor"));
0825                        Object[] source = { moduleStack[i].entry
0826                                .getLoginModuleName() };
0827                        throwException(null, new LoginException(form
0828                                .format(source)));
0829                    } catch (InstantiationException ie) {
0830                        throwException(
0831                                null,
0832                                new LoginException(
0833                                        ResourcesMgr
0834                                                .getString("unable to instantiate LoginModule: ")
0835                                                + ie.getMessage()));
0836                    } catch (ClassNotFoundException cnfe) {
0837                        throwException(
0838                                null,
0839                                new LoginException(
0840                                        ResourcesMgr
0841                                                .getString("unable to find LoginModule class: ")
0842                                                + cnfe.getMessage()));
0843                    } catch (IllegalAccessException iae) {
0844                        throwException(null, new LoginException(ResourcesMgr
0845                                .getString("unable to access LoginModule: ")
0846                                + iae.getMessage()));
0847                    } catch (InvocationTargetException ite) {
0848
0849                        // failure cases
0850
0851                        LoginException le;
0852
0853                        if (ite.getCause() instanceof  PendingException
0854                                && methodName.equals(LOGIN_METHOD)) {
0855
0856                            // XXX
0857                            //
0858                            // if a module's LOGIN_METHOD threw a PendingException
0859                            // then immediately throw it.
0860                            //
0861                            // when LoginContext is called again,
0862                            // the module that threw the exception is invoked first
0863                            // (the module list is not invoked from the start).
0864                            // previously thrown exception state is still present.
0865                            //
0866                            // it is assumed that the module which threw
0867                            // the exception can have its
0868                            // LOGIN_METHOD invoked twice in a row
0869                            // without any commit/abort in between.
0870                            //
0871                            // in all cases when LoginContext returns
0872                            // (either via natural return or by throwing an exception)
0873                            // we need to call clearState before returning.
0874                            // the only time that is not true is in this case -
0875                            // do not call throwException here.
0876
0877                            throw (PendingException) ite.getCause();
0878
0879                        } else if (ite.getCause() instanceof  LoginException) {
0880
0881                            le = (LoginException) ite.getCause();
0882
0883                        } else if (ite.getCause() instanceof  SecurityException) {
0884
0885                            // do not want privacy leak
0886                            // (e.g., sensitive file path in exception msg)
0887
0888                            le = new LoginException("Security Exception");
0889                            le.initCause(new SecurityException());
0890                            if (debug != null) {
0891                                debug
0892                                        .println("original security exception with detail msg "
0893                                                + "replaced by new exception with empty detail msg");
0894                                debug.println("original security exception: "
0895                                        + ite.getCause().toString());
0896                            }
0897                        } else {
0898
0899                            // capture an unexpected LoginModule exception
0900                            java.io.StringWriter sw = new java.io.StringWriter();
0901                            ite.getCause().printStackTrace(
0902                                    new java.io.PrintWriter(sw));
0903                            sw.flush();
0904                            le = new LoginException(sw.toString());
0905                        }
0906
0907                        if (moduleStack[i].entry.getControlFlag() == AppConfigurationEntry.LoginModuleControlFlag.REQUISITE) {
0908
0909                            if (debug != null)
0910                                debug
0911                                        .println(methodName
0912                                                + " REQUISITE failure");
0913
0914                            // if REQUISITE, then immediately throw an exception
0915                            if (methodName.equals(ABORT_METHOD)
0916                                    || methodName.equals(LOGOUT_METHOD)) {
0917                                if (firstRequiredError == null)
0918                                    firstRequiredError = le;
0919                            } else {
0920                                throwException(firstRequiredError, le);
0921                            }
0922
0923                        } else if (moduleStack[i].entry.getControlFlag() == AppConfigurationEntry.LoginModuleControlFlag.REQUIRED) {
0924
0925                            if (debug != null)
0926                                debug.println(methodName + " REQUIRED failure");
0927
0928                            // mark down that a REQUIRED module failed
0929                            if (firstRequiredError == null)
0930                                firstRequiredError = le;
0931
0932                        } else {
0933
0934                            if (debug != null)
0935                                debug.println(methodName + " OPTIONAL failure");
0936
0937                            // mark down that an OPTIONAL module failed
0938                            if (firstError == null)
0939                                firstError = le;
0940                        }
0941                    }
0942                }
0943
0944                // we went thru all the LoginModules.
0945                if (firstRequiredError != null) {
0946                    // a REQUIRED module failed -- return the error
0947                    throwException(firstRequiredError, null);
0948                } else if (success == false && firstError != null) {
0949                    // no module succeeded -- return the first error
0950                    throwException(firstError, null);
0951                } else if (success == false) {
0952                    // no module succeeded -- all modules were IGNORED
0953                    throwException(new LoginException(ResourcesMgr
0954                            .getString("Login Failure: all modules ignored")),
0955                            null);
0956                } else {
0957                    // success
0958
0959                    clearState();
0960                    return;
0961                }
0962            }
0963
0964            /**
0965             * Wrap the caller-specified CallbackHandler in our own
0966             * and invoke it within a privileged block, constrained by
0967             * the caller's AccessControlContext.
0968             */
0969            private static class SecureCallbackHandler implements 
0970                    CallbackHandler {
0971
0972                private final java.security.AccessControlContext acc;
0973                private final CallbackHandler ch;
0974
0975                SecureCallbackHandler(java.security.AccessControlContext acc,
0976                        CallbackHandler ch) {
0977                    this .acc = acc;
0978                    this .ch = ch;
0979                }
0980
0981                public void handle(final Callback[] callbacks)
0982                        throws java.io.IOException,
0983                        UnsupportedCallbackException {
0984                    try {
0985                        java.security.AccessController
0986                                .doPrivileged(
0987                                        new java.security.PrivilegedExceptionAction<Void>() {
0988                                            public Void run()
0989                                                    throws java.io.IOException,
0990                                                    UnsupportedCallbackException {
0991                                                ch.handle(callbacks);
0992                                                return null;
0993                                            }
0994                                        }, acc);
0995                    } catch (java.security.PrivilegedActionException pae) {
0996                        if (pae.getException() instanceof  java.io.IOException) {
0997                            throw (java.io.IOException) pae.getException();
0998                        } else {
0999                            throw (UnsupportedCallbackException) pae
1000                                    .getException();
1001                        }
1002                    }
1003                }
1004            }
1005
1006            /**
1007             * LoginModule information -
1008             *		incapsulates Configuration info and actual module instances
1009             */
1010            private static class ModuleInfo {
1011                AppConfigurationEntry entry;
1012                Object module;
1013
1014                ModuleInfo(AppConfigurationEntry newEntry, Object newModule) {
1015                    this.entry = newEntry;
1016                    this.module = newModule;
1017                }
1018            }
1019        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.