Index: javax/security/auth/login/LoginContext.java
===================================================================
RCS file: /cvsroot/classpath/classpath/javax/security/auth/login/LoginContext.java,v
retrieving revision 1.1
diff -u -b -B -r1.1 LoginContext.java
--- javax/security/auth/login/LoginContext.java 14 Aug 2004 18:21:35 -0000 1.1
+++ javax/security/auth/login/LoginContext.java 25 Oct 2004 03:14:20 -0000
@@ -38,7 +38,216 @@
package javax.security.auth.login;
+import gnu.java.security.action.GetSecurityPropertyAction;
+
+import java.security.AccessController;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.security.auth.Subject;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.spi.LoginModule;
+
public class LoginContext
{
+ private static final String OTHER = "other";
+
+ private final String name;
+ private final CallbackHandler cbHandler;
+ private final Subject subject;
+ private final AppConfigurationEntry[] entries;
+ private final LoginModule[] modules;
+ private final Map sharedState;
+
+ public LoginContext (final String name) throws LoginException
+ {
+ this (name, new Subject(), defaultHandler());
+ }
+
+ public LoginContext (final String name, final CallbackHandler cbHandler)
+ throws LoginException
+ {
+ this (name, new Subject(), cbHandler);
+ }
+
+ public LoginContext (final String name, final Subject subject)
+ throws LoginException
+ {
+ this (name, subject, defaultHandler());
+ }
+
+ public LoginContext (final String name, final Subject subject,
+ final CallbackHandler cbHandler)
+ throws LoginException
+ {
+ Configuration config = Configuration.getConfig();
+ AppConfigurationEntry[] entries = config.getAppConfigurationEntry (name);
+ if (entries == null)
+ entries = config.getAppConfigurationEntry (OTHER);
+ if (entries == null)
+ throw new LoginException ("no configured modules for application "
+ + name);
+ this.entries = entries;
+ modules = new LoginModule[entries.length];
+ sharedState = new HashMap();
+ for (int i = 0; i < entries.length; i++)
+ modules[i] = lookupModule (entries[i], subject, sharedState);
+ this.name = name;
+ this.subject = subject;
+ this.cbHandler = cbHandler;
+ }
+
+ /**
+ * Returns the authenticated subject, or the parameter passed to one
+ * of the constructors. null
is returned if the previous
+ * login attempt failed and there was no subject provided.
+ *
+ * @return The subject, or null.
+ */
+ public Subject getSubject()
+ {
+ return subject;
+ }
+
+ /**
+ * Logs a subject in, using all login modules configured for this
+ * application. This method will call the address@hidden LoginModule#login()}
+ * method of each module configured for this application, stopping
+ * if a REQUISITE module fails or if a SUFFICIENT module succeeds. If
+ * the overall login attempt fails, a address@hidden LoginException} will be
+ * thrown.
+ *
+ * @throws LoginException If logging in fails.
+ */
+ public void login() throws LoginException
+ {
+ boolean failure = false;
+ for (int i = 0; i < modules.length; i++)
+ {
+ try
+ {
+ boolean result = modules[i].login();
+ if (!result)
+ {
+ if (entries[i].getControlFlag() ==
+ AppConfigurationEntry.LoginModuleControlFlag.REQUISITE)
+ throw new LoginException ("REQUISITE module " + entries[i].getLoginModuleName()
+ + " failed");
+ else if (entries[i].getControlFlag() ==
+ AppConfigurationEntry.LoginModuleControlFlag.REQUIRED)
+ failure = true;
+ }
+ else
+ {
+ if (entries[i].getControlFlag() ==
+ AppConfigurationEntry.LoginModuleControlFlag.SUFFICIENT)
+ break;
+ }
+ }
+ catch (LoginException le)
+ {
+ if (entries[i].getControlFlag() !=
+ AppConfigurationEntry.LoginModuleControlFlag.REQUISITE)
+ continue;
+ for (int j = 0; j < modules.length; j++)
+ modules[i].abort();
+ throw le;
+ }
+ }
+ if (failure)
+ throw new LoginException ("not all REQUIRED modules succeeded");
+
+ for (int i = 0; i < modules.length; i++)
+ modules[i].commit();
+ }
+
+ /**
+ * Logs a subject out, cleaning up any state that may be in memory.
+ *
+ * @throws LoginException If logging out fails.
+ */
+ public void logout() throws LoginException
+ {
+ for (int i = 0; i < modules.length; i++)
+ modules[i].logout();
+ }
+
+ // Own methods.
+
+ /**
+ * Fetch the default callback handler, based on the
+ * auth.login.defaultCallbackHandler property, or null if it is not
+ * set.
+ */
+ private static CallbackHandler defaultHandler()
+ {
+ GetSecurityPropertyAction act =
+ new GetSecurityPropertyAction ("auth.login.defaultCallbackHandler");
+ String classname = (String) AccessController.doPrivileged (act);
+ if (classname != null)
+ {
+ try
+ {
+ return (CallbackHandler) Class.forName (classname).newInstance();
+ }
+ catch (ClassNotFoundException cnfe)
+ {
+ return null;
+ }
+ catch (ClassCastException cce)
+ {
+ return null;
+ }
+ catch (IllegalAccessException iae)
+ {
+ return null;
+ }
+ catch (InstantiationException ie)
+ {
+ return null;
+ }
+ }
+ return null;
+ }
+
+ private LoginModule lookupModule (AppConfigurationEntry entry,
+ Subject subject, Map sharedState)
+ throws LoginException
+ {
+ LoginModule module = null;
+ Exception cause = null;
+ try
+ {
+ module = (LoginModule) Class.forName (entry.getLoginModuleName()).newInstance();
+ }
+ catch (ClassNotFoundException cnfe)
+ {
+ cause = cnfe;
+ }
+ catch (ClassCastException cce)
+ {
+ cause = cce;
+ }
+ catch (IllegalAccessException iae)
+ {
+ cause = iae;
+ }
+ catch (InstantiationException ie)
+ {
+ cause = ie;
+ }
+
+ if (cause != null)
+ {
+ LoginException le = new LoginException ("could not load module "
+ + entry.getLoginModuleName());
+ le.initCause (cause);
+ throw le;
+ }
+
+ module.initialize (subject, cbHandler, sharedState, entry.getOptions());
+ return module;
+ }
}
--- /dev/null 1969-12-31 16:00:00.000000000 -0800
+++ javax/security/auth/spi/LoginModule.java 2004-10-10 22:26:58.000000000 -0700
@@ -0,0 +1,122 @@
+/* LoginModule.java -- interface for login implementations.
+ Copyright (C) 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+02111-1307 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package javax.security.auth.spi;
+
+import java.util.Map;
+
+import javax.security.auth.Subject;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.login.LoginException;
+
+/**
+ * The base interface for login methods in the Java Authentication and
+ * Authorization Service (JAAS).
+ *
+ *
This interface is used by service providers that implement login + * services, and is used internally by the JAAS system. It is not useful + * to application programmers, who should use the address@hidden + * javax.security.auth.login.LoginContext} instead. + * + * @author Casey Marshall (address@hidden) + */ +public interface LoginModule +{ + /** + * Abort the current login attempt. This is called after address@hidden #login()} + * if the overall login attempt fails (that is, if one of the other login + * modules that is REQUIRED or REQUISITE fails). This method should clean + * up this module's saved state, if any. + * + * @return True if the abort succeeded, or false if this module should + * be ignored. + * @throws LoginException If the abort fails. + */ + boolean abort() throws LoginException; + + /** + * Commit the current login attempt. This is called after address@hidden + * #login()} if the overall login attempt succeeds (that is, all + * methods have satisfied all REQUIRED, REQUISITE, SUFFICIENT and + * OPTIONAL module requirements). + * + * @return True if the commit succeeded, or false if this module + * should be ignored. + * @throws LoginException If the commit fails. + */ + boolean commit() throws LoginException; + + /** + * Initializes this login module. This method is called when the + * instance implementing this interface is instantiated, and should + * perform any initialization based on the given parameters. + * Implementations should ignore state variables and options they do + * not recognize. + * + * @param subject The subject being authenticated. + * @param handler The callback handler for user input. + * @param sharedState A mapping that is shared between all login + * modules. + * @param options A mapping of options given to this module. + */ + void initialize(Subject subject, CallbackHandler handler, + Map sharedState, Map options); + + /** + * Authenticates a subject to the system. This is the primary + * mechanism by which subjects are authenticated, and typically + * implementations will ask for credentials (for example, a user + * name and password) which will then be verified. + * + * @return True if the subject was authenticated, or false if this + * module should be ignored. + * @throws LoginException If this method fails. + */ + boolean login() throws LoginException; + + /** + * Logs a subject out. This is primarily used for modules that must + * destroy or remove the authentication state associated with a + * logged-in subject. + * + * @return True if the logout succeeds, or false if this module + * should be ignored. + * @throws LoginException If this method fails. + */ + boolean logout() throws LoginException; +}