You are viewing a plain text version of this content. The canonical link for it is here.
Posted to scm@geronimo.apache.org by am...@apache.org on 2004/11/16 23:34:08 UTC
svn commit: rev 76044 - in geronimo/trunk/modules: assembly/src/plan jetty/src/java/org/apache/geronimo/jetty jetty/src/test-resources/data jetty/src/test/org/apache/geronimo/jetty security/src/java/org/apache/geronimo/security security/src/java/org/apache/geronimo/security/jaas security/src/java/org/apache/geronimo/security/remoting security/src/java/org/apache/geronimo/security/remoting/jmx security/src/test-data/data security/src/test/org/apache/geronimo/security security/src/test/org/apache/geronimo/security/bridge security/src/test/org/apache/geronimo/security/jaas security/src/test/org/apache/geronimo/security/remoting/jmx
Author: ammulder
Date: Tue Nov 16 14:34:08 2004
New Revision: 76044
Added:
geronimo/trunk/modules/security/src/java/org/apache/geronimo/security/jaas/DecouplingCallbackHandler.java
geronimo/trunk/modules/security/src/java/org/apache/geronimo/security/jaas/JaasClientId.java
geronimo/trunk/modules/security/src/java/org/apache/geronimo/security/jaas/JaasLoginCoordinator.java
geronimo/trunk/modules/security/src/java/org/apache/geronimo/security/jaas/JaasLoginModuleConfiguration.java
geronimo/trunk/modules/security/src/java/org/apache/geronimo/security/jaas/JaasLoginService.java
geronimo/trunk/modules/security/src/java/org/apache/geronimo/security/jaas/JaasLoginServiceMBean.java
geronimo/trunk/modules/security/src/java/org/apache/geronimo/security/jaas/JaasSecurityContext.java
geronimo/trunk/modules/security/src/java/org/apache/geronimo/security/remoting/jmx/JaasLoginServiceRemotingClient.java
geronimo/trunk/modules/security/src/java/org/apache/geronimo/security/remoting/jmx/JaasLoginServiceRemotingServer.java
geronimo/trunk/modules/security/src/test/org/apache/geronimo/security/jaas/TimeoutTest.java
Removed:
geronimo/trunk/modules/security/src/java/org/apache/geronimo/security/jaas/LocalLoginModule.java
geronimo/trunk/modules/security/src/java/org/apache/geronimo/security/jaas/LoginModuleCacheObject.java
geronimo/trunk/modules/security/src/java/org/apache/geronimo/security/jaas/LoginModuleConstants.java
geronimo/trunk/modules/security/src/java/org/apache/geronimo/security/jaas/LoginModuleId.java
geronimo/trunk/modules/security/src/java/org/apache/geronimo/security/jaas/LoginService.java
geronimo/trunk/modules/security/src/java/org/apache/geronimo/security/jaas/LoginServiceMBean.java
geronimo/trunk/modules/security/src/java/org/apache/geronimo/security/jaas/RemoteLoginModule.java
geronimo/trunk/modules/security/src/java/org/apache/geronimo/security/jaas/RemoteLoginModuleLocalWrapper.java
geronimo/trunk/modules/security/src/java/org/apache/geronimo/security/jaas/RemoteLoginModuleRemoteWrapper.java
geronimo/trunk/modules/security/src/java/org/apache/geronimo/security/jaas/SerializableACE.java
geronimo/trunk/modules/security/src/java/org/apache/geronimo/security/remoting/RemoteLoginServiceFactory.java
geronimo/trunk/modules/security/src/java/org/apache/geronimo/security/remoting/jmx/LoginServiceStub.java
geronimo/trunk/modules/security/src/java/org/apache/geronimo/security/remoting/jmx/RemoteLoginServiceFactory.java
Modified:
geronimo/trunk/modules/assembly/src/plan/j2ee-server-plan.xml
geronimo/trunk/modules/jetty/src/java/org/apache/geronimo/jetty/JAASJettyRealm.java
geronimo/trunk/modules/jetty/src/test-resources/data/login.config
geronimo/trunk/modules/jetty/src/test/org/apache/geronimo/jetty/BaseSecurityTest.java
geronimo/trunk/modules/jetty/src/test/org/apache/geronimo/jetty/SecurityTest.java
geronimo/trunk/modules/security/src/java/org/apache/geronimo/security/ContextManager.java
geronimo/trunk/modules/security/src/java/org/apache/geronimo/security/jaas/ConfigurationEntryRealmLocal.java
geronimo/trunk/modules/security/src/java/org/apache/geronimo/security/jaas/ConfigurationEntryRealmRemote.java
geronimo/trunk/modules/security/src/java/org/apache/geronimo/security/jaas/GeronimoLoginConfiguration.java
geronimo/trunk/modules/security/src/test-data/data/login.config
geronimo/trunk/modules/security/src/test/org/apache/geronimo/security/AbstractTest.java
geronimo/trunk/modules/security/src/test/org/apache/geronimo/security/bridge/CallerIdentityUserPasswordBridgeTest.java
geronimo/trunk/modules/security/src/test/org/apache/geronimo/security/bridge/ConfiguredIdentityUserPasswordBridgeTest.java
geronimo/trunk/modules/security/src/test/org/apache/geronimo/security/bridge/MappingUserPasswordBridgeTest.java
geronimo/trunk/modules/security/src/test/org/apache/geronimo/security/jaas/ConfigurationEntryTest.java
geronimo/trunk/modules/security/src/test/org/apache/geronimo/security/jaas/LoginPropertiesFileTest.java
geronimo/trunk/modules/security/src/test/org/apache/geronimo/security/jaas/LoginSQLTest.java
geronimo/trunk/modules/security/src/test/org/apache/geronimo/security/jaas/LoginSimpleRealmTest.java
geronimo/trunk/modules/security/src/test/org/apache/geronimo/security/remoting/jmx/RemoteLoginTest.java
Log:
Initial work on security. More to come some other time.
Modified: geronimo/trunk/modules/assembly/src/plan/j2ee-server-plan.xml
==============================================================================
--- geronimo/trunk/modules/assembly/src/plan/j2ee-server-plan.xml (original)
+++ geronimo/trunk/modules/assembly/src/plan/j2ee-server-plan.xml Tue Nov 16 14:34:08 2004
@@ -122,9 +122,9 @@
<reference name="Realms">geronimo.security:type=SecurityRealm,*</reference>
</gbean>
- <gbean name="geronimo.security:type=LoginService" class="org.apache.geronimo.security.jaas.LoginService">
+ <gbean name="geronimo.security:type=JaasLoginService" class="org.apache.geronimo.security.jaas.JaasLoginService">
<reference name="Realms">geronimo.security:type=SecurityRealm,*</reference>
- <attribute name="reclaimPeriod" type="long">100000</attribute>
+<!-- <attribute name="reclaimPeriod" type="long">100000</attribute>-->
<attribute name="algorithm" type="java.lang.String">HmacSHA1</attribute>
<attribute name="password" type="java.lang.String">secret</attribute>
</gbean>
Modified: geronimo/trunk/modules/jetty/src/java/org/apache/geronimo/jetty/JAASJettyRealm.java
==============================================================================
--- geronimo/trunk/modules/jetty/src/java/org/apache/geronimo/jetty/JAASJettyRealm.java (original)
+++ geronimo/trunk/modules/jetty/src/java/org/apache/geronimo/jetty/JAASJettyRealm.java Tue Nov 16 14:34:08 2004
@@ -22,6 +22,7 @@
import java.util.HashMap;
import javax.security.auth.login.LoginContext;
import javax.security.auth.login.LoginException;
+import javax.security.auth.Subject;
import javax.security.jacc.WebRoleRefPermission;
import org.apache.commons.logging.Log;
@@ -92,12 +93,12 @@
loginContext.login();
callbackHandler.clear();
- ContextManager.registerSubject(loginContext.getSubject());
- ContextManager.setCurrentCaller(loginContext.getSubject());
+ Subject subject = ContextManager.getServerSideSubject(loginContext.getSubject());
+ ContextManager.setCurrentCaller(subject);
//login success
userPrincipal = new JAASJettyPrincipal(username);
- userPrincipal.setSubject(loginContext.getSubject());
+ userPrincipal.setSubject(subject);
userMap.put(username, userPrincipal);
Modified: geronimo/trunk/modules/jetty/src/test-resources/data/login.config
==============================================================================
--- geronimo/trunk/modules/jetty/src/test-resources/data/login.config (original)
+++ geronimo/trunk/modules/jetty/src/test-resources/data/login.config Tue Nov 16 14:34:08 2004
@@ -1,9 +1,5 @@
-
jaasTest {
- org.apache.geronimo.security.jaas.LocalLoginModule required
- debug=true
+ org.apache.geronimo.security.jaas.JaasLoginCoordinator required
realm="demo-properties-realm"
kernel="geronimo.kernel";
};
-
-
Modified: geronimo/trunk/modules/jetty/src/test/org/apache/geronimo/jetty/BaseSecurityTest.java
==============================================================================
--- geronimo/trunk/modules/jetty/src/test/org/apache/geronimo/jetty/BaseSecurityTest.java (original)
+++ geronimo/trunk/modules/jetty/src/test/org/apache/geronimo/jetty/BaseSecurityTest.java Tue Nov 16 14:34:08 2004
@@ -110,10 +110,10 @@
securityServiceGBean.setReferencePatterns("Realms", Collections.singleton(new ObjectName("geronimo.security:type=SecurityRealm,*")));
securityServiceGBean.setAttribute("policyConfigurationFactory", "org.apache.geronimo.security.jacc.GeronimoPolicyConfigurationFactory");
- loginServiceGBean = new GBeanMBean("org.apache.geronimo.security.jaas.LoginService");
- loginServiceName = new ObjectName("geronimo.security:type=LoginService");
+ loginServiceGBean = new GBeanMBean("org.apache.geronimo.security.jaas.JaasLoginService");
+ loginServiceName = new ObjectName("geronimo.security:type=JaasLoginService");
loginServiceGBean.setReferencePatterns("Realms", Collections.singleton(new ObjectName("geronimo.security:type=SecurityRealm,*")));
- loginServiceGBean.setAttribute("reclaimPeriod", new Long(1000 * 1000));
+// loginServiceGBean.setAttribute("reclaimPeriod", new Long(1000 * 1000));
loginServiceGBean.setAttribute("algorithm", "HmacSHA1");
loginServiceGBean.setAttribute("password", "secret");
Modified: geronimo/trunk/modules/jetty/src/test/org/apache/geronimo/jetty/SecurityTest.java
==============================================================================
--- geronimo/trunk/modules/jetty/src/test/org/apache/geronimo/jetty/SecurityTest.java (original)
+++ geronimo/trunk/modules/jetty/src/test/org/apache/geronimo/jetty/SecurityTest.java Tue Nov 16 14:34:08 2004
@@ -91,6 +91,7 @@
connection.setRequestProperty("Cookie", cookie);
connection.setInstanceFollowRedirects(false);
BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
+ System.out.println("Headers: "+connection.getHeaderFields());
assertEquals(HttpURLConnection.HTTP_OK, connection.getResponseCode());
assertEquals("Hello World", reader.readLine());
Modified: geronimo/trunk/modules/security/src/java/org/apache/geronimo/security/ContextManager.java
==============================================================================
--- geronimo/trunk/modules/security/src/java/org/apache/geronimo/security/ContextManager.java (original)
+++ geronimo/trunk/modules/security/src/java/org/apache/geronimo/security/ContextManager.java Tue Nov 16 14:34:08 2004
@@ -63,6 +63,20 @@
public static final GeronimoSecurityPermission GET_CONTEXT = new GeronimoSecurityPermission("getContext");
public static final GeronimoSecurityPermission SET_CONTEXT = new GeronimoSecurityPermission("setContext");
+ /**
+ * After a login, the client is left with a relatively empty Subject, while
+ * the Subject used by the server has more important contents. This method
+ * lets a server-side component acting as an authentication client (such
+ * as Tocmat/Jetty) access the fully populated server-side Subject.
+ */
+ public static Subject getServerSideSubject(Subject clientSideSubject) {
+ Set set = clientSideSubject.getPrincipals(IdentificationPrincipal.class);
+ if(set == null || set.size() == 0) {
+ return null;
+ }
+ IdentificationPrincipal idp = (IdentificationPrincipal)set.iterator().next();
+ return getRegisteredSubject(idp.getId());
+ }
public static void setCurrentCallerId(Serializable id) {
SecurityManager sm = System.getSecurityManager();
Modified: geronimo/trunk/modules/security/src/java/org/apache/geronimo/security/jaas/ConfigurationEntryRealmLocal.java
==============================================================================
--- geronimo/trunk/modules/security/src/java/org/apache/geronimo/security/jaas/ConfigurationEntryRealmLocal.java (original)
+++ geronimo/trunk/modules/security/src/java/org/apache/geronimo/security/jaas/ConfigurationEntryRealmLocal.java Tue Nov 16 14:34:08 2004
@@ -58,7 +58,7 @@
public AppConfigurationEntry[] getAppConfigurationEntry() {
try {
return new AppConfigurationEntry[]{
- new AppConfigurationEntry("org.apache.geronimo.security.jaas.LocalLoginModule",
+ new AppConfigurationEntry("org.apache.geronimo.security.jaas.JaasLoginCoordinator",
getControlFlag().getFlag(),
getOptions())};
} catch (Exception e) {
Modified: geronimo/trunk/modules/security/src/java/org/apache/geronimo/security/jaas/ConfigurationEntryRealmRemote.java
==============================================================================
--- geronimo/trunk/modules/security/src/java/org/apache/geronimo/security/jaas/ConfigurationEntryRealmRemote.java (original)
+++ geronimo/trunk/modules/security/src/java/org/apache/geronimo/security/jaas/ConfigurationEntryRealmRemote.java Tue Nov 16 14:34:08 2004
@@ -41,24 +41,42 @@
* @see javax.security.auth.login.Configuration
*/
public class ConfigurationEntryRealmRemote extends ConfigurationEntryRealmLocal {
- private String URI;
+ private String realmName;
+ private String host;
+ private int port;
public ConfigurationEntryRealmRemote(Kernel kernel) {
super(kernel);
}
- public String getURI() {
- return URI;
+ public String getHost() {
+ return host;
}
- public void setURI(String URI) {
- this.URI = URI;
+ public void setHost(String host) {
+ this.host = host;
+ }
+
+ public int getPort() {
+ return port;
+ }
+
+ public void setPort(int port) {
+ this.port = port;
+ }
+
+ public String getRealmName() {
+ return realmName;
+ }
+
+ public void setRealmName(String realmName) {
+ this.realmName = realmName;
}
public AppConfigurationEntry[] getAppConfigurationEntry() {
try {
return new AppConfigurationEntry[]{
- new AppConfigurationEntry("org.apache.geronimo.security.jaas.LocalLoginModule",
+ new AppConfigurationEntry("org.apache.geronimo.security.jaas.JaasLoginCoordinator",
getControlFlag().getFlag(),
getOptions())};
} catch (Exception e) {
@@ -69,7 +87,9 @@
public void doStart() throws WaitingException, Exception {
super.doStart();
- options.put("uri", URI);
+ options.put("host", host);
+ options.put("realm", realmName);
+ options.put("port", Integer.toString(port));
}
public void doStop() throws WaitingException, Exception {
@@ -80,7 +100,9 @@
static {
GBeanInfoBuilder infoFactory = new GBeanInfoBuilder(ConfigurationEntryRealmRemote.class, ConfigurationEntryRealmLocal.GBEAN_INFO);
- infoFactory.addAttribute("URI", String.class, true);
+ infoFactory.addAttribute("host", String.class, true);
+ infoFactory.addAttribute("port", int.class, true);
+ infoFactory.addAttribute("realmName", String.class, true);
GBEAN_INFO = infoFactory.getBeanInfo();
}
Added: geronimo/trunk/modules/security/src/java/org/apache/geronimo/security/jaas/DecouplingCallbackHandler.java
==============================================================================
--- (empty file)
+++ geronimo/trunk/modules/security/src/java/org/apache/geronimo/security/jaas/DecouplingCallbackHandler.java Tue Nov 16 14:34:08 2004
@@ -0,0 +1,47 @@
+package org.apache.geronimo.security.jaas;
+
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.UnsupportedCallbackException;
+import java.io.IOException;
+
+/**
+ * This callback handler separates the process of obtaining callbacks from
+ * the user from the process of providing the user's values to the login
+ * module. This means the JaasLoginService can figure out what callbacks
+ * the module wants and prompt the user in advance, and then turn around
+ * and pass those values to the login module, instead of actually prompting
+ * the user at the mercy of the login module.
+ */
+public class DecouplingCallbackHandler implements CallbackHandler {
+ private Callback[] source;
+ private boolean exploring = true;
+
+ public DecouplingCallbackHandler() {
+ }
+
+ public void handle(Callback[] callbacks)
+ throws IOException, UnsupportedCallbackException {
+ if (exploring) {
+ source = callbacks;
+ throw new UnsupportedCallbackException(callbacks.length > 0 ? callbacks[0] : null, "DO NOT PROCEED WITH THIS LOGIN");
+ } else {
+ if(callbacks.length != source.length) {
+ throw new IOException("Mismatched callbacks");
+ }
+ for (int i = 0; i < callbacks.length; i++) {
+ callbacks[i] = source[i];
+ }
+ }
+ }
+
+ public void setExploring() {
+ exploring = true;
+ source = null;
+ }
+
+ public Callback[] finalizeCallbackList() {
+ exploring = false;
+ return source;
+ }
+}
Modified: geronimo/trunk/modules/security/src/java/org/apache/geronimo/security/jaas/GeronimoLoginConfiguration.java
==============================================================================
--- geronimo/trunk/modules/security/src/java/org/apache/geronimo/security/jaas/GeronimoLoginConfiguration.java (original)
+++ geronimo/trunk/modules/security/src/java/org/apache/geronimo/security/jaas/GeronimoLoginConfiguration.java Tue Nov 16 14:34:08 2004
@@ -30,6 +30,12 @@
/**
+ * A JAAS configuration mechanism (associating JAAS configuration names with
+ * specific LoginModule configurations). This is a drop-in replacement for the
+ * normal file-reading JAAS configuration mechanism. Instead of getting
+ * its configuration from its file, it gets its configuration from other
+ * GBeans running in Geronimo.
+ *
* @version $Rev$ $Date$
*/
public class GeronimoLoginConfiguration extends Configuration implements GBeanLifecycle {
Added: geronimo/trunk/modules/security/src/java/org/apache/geronimo/security/jaas/JaasClientId.java
==============================================================================
--- (empty file)
+++ geronimo/trunk/modules/security/src/java/org/apache/geronimo/security/jaas/JaasClientId.java Tue Nov 16 14:34:08 2004
@@ -0,0 +1,91 @@
+/**
+ *
+ * Copyright 2004 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.geronimo.security.jaas;
+
+import java.io.Serializable;
+
+
+/**
+ * @version $Rev: 46019 $ $Date: 2004-09-14 05:56:06 -0400 (Tue, 14 Sep 2004) $
+ */
+public class JaasClientId implements Serializable {
+ private final long clientId;
+ private final byte[] hash;
+ private transient int hashCode;
+ private transient String name;
+
+ public JaasClientId(long clientId, byte[] hash) {
+ this.clientId = clientId;
+ this.hash = hash;
+ }
+
+ public long getClientId() {
+ return clientId;
+ }
+
+ public byte[] getHash() {
+ return hash;
+ }
+
+ public boolean equals(Object obj) {
+ if (!(obj instanceof JaasClientId)) return false;
+
+ JaasClientId another = (JaasClientId) obj;
+ if (another.clientId != clientId) return false;
+ for (int i = 0; i < hash.length; i++) {
+ if (another.hash[i] != hash[i]) return false;
+ }
+ return true;
+ }
+
+ public String toString() {
+ if (name == null) {
+ StringBuffer buffer = new StringBuffer();
+ buffer.append('[');
+ buffer.append(clientId);
+ buffer.append(":0x");
+ for (int i = 0; i < hash.length; i++) {
+ buffer.append(HEXCHAR[(hash[i]>>>4)&0x0F]);
+ buffer.append(HEXCHAR[(hash[i] )&0x0F]);
+ }
+ buffer.append(']');
+ name = buffer.toString();
+ }
+ return name;
+ }
+
+ /**
+ * Returns a hashcode for this LoginModuleId.
+ *
+ * @return a hashcode for this LoginModuleId.
+ */
+ public int hashCode() {
+ if (hashCode == 0) {
+ for (int i = 0; i < hash.length; i++) {
+ hashCode ^= hash[i];
+ }
+ hashCode ^= (int)(clientId ^ (clientId >>> 32));
+ }
+ return hashCode;
+ }
+
+ private static final char[] HEXCHAR = {
+ '0', '1', '2', '3', '4', '5', '6', '7',
+ '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'
+ };
+}
Added: geronimo/trunk/modules/security/src/java/org/apache/geronimo/security/jaas/JaasLoginCoordinator.java
==============================================================================
--- (empty file)
+++ geronimo/trunk/modules/security/src/java/org/apache/geronimo/security/jaas/JaasLoginCoordinator.java Tue Nov 16 14:34:08 2004
@@ -0,0 +1,199 @@
+package org.apache.geronimo.security.jaas;
+
+import org.apache.geronimo.security.remoting.jmx.JaasLoginServiceRemotingClient;
+import org.apache.geronimo.kernel.Kernel;
+import org.apache.geronimo.kernel.jmx.MBeanProxyFactory;
+
+import javax.security.auth.spi.LoginModule;
+import javax.security.auth.Subject;
+import javax.security.auth.login.LoginException;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.Callback;
+import java.util.*;
+import java.security.Principal;
+
+/**
+ * A LoginModule implementation which connects to a Geronimo server under
+ * the covers, and uses Geronimo realms to resolve the login. It handles a
+ * mix of client-side and server-side login modules. It treats any client
+ * side module as something it should manage and execute, while a server side
+ * login module would be managed and executed by the Geronimo server.
+ *
+ * Note that this can actually be run from within a Geronimo server, in which
+ * case the client/server distinction is somewhat less important, and the
+ * communication is optimized by avoiding network traffic.
+ *
+ * @version $Revision: 1.0$
+ */
+public class JaasLoginCoordinator implements LoginModule {
+ public final static String OPTION_HOST = "host";
+ public final static String OPTION_PORT = "port";
+ public final static String OPTION_KERNEL = "kernel";
+ public final static String OPTION_REALM = "realm";
+ private String serverHost;
+ private int serverPort;
+ private String realmName;
+ private String kernelName;
+ private JaasLoginServiceMBean service;
+ private CallbackHandler handler;
+ private Subject subject;
+ private Set processedPrincipals = new HashSet();
+ private JaasLoginModuleConfiguration[] config;
+ private JaasClientId client;
+ LoginModuleConfiguration[] workers;
+
+ public void initialize(Subject subject, CallbackHandler callbackHandler,
+ Map sharedState, Map options) {
+ serverHost = (String) options.get(OPTION_HOST);
+ Object port = options.get(OPTION_PORT);
+ if(port != null) {
+ serverPort = Integer.parseInt((String)port);
+ }
+ realmName = (String) options.get(OPTION_REALM);
+ kernelName = (String) options.get(OPTION_KERNEL);
+ service = connect();
+ handler = callbackHandler;
+ this.subject = subject;
+ }
+
+ public boolean login() throws LoginException {
+ client = service.connectToRealm(realmName);
+ config = service.getLoginConfiguration(client);
+ workers = new LoginModuleConfiguration[config.length];
+ for (int i = 0; i < workers.length; i++) {
+ LoginModule wrapper;
+ if(config[i].isServerSide()) {
+ wrapper = new ServerLoginModule(i);
+ } else {
+ LoginModule source = config[i].getLoginModule(JaasLoginCoordinator.class.getClassLoader());
+ wrapper = new ClientLoginModule(source, i);
+ }
+ workers[i] = new LoginModuleConfiguration(wrapper, config[i].getFlag());
+ workers[i].getModule().initialize(subject, handler, new HashMap(), config[i].getOptions());
+ }
+ return LoginUtils.computeLogin(workers);
+ }
+
+ public boolean commit() throws LoginException {
+ for (int i = 0; i < workers.length; i++) {
+ workers[i].getModule().commit();
+ }
+ subject.getPrincipals().add(service.loginSucceeded(client));
+ return true;
+ }
+
+ public boolean abort() throws LoginException {
+ try {
+ for (int i = 0; i < workers.length; i++) {
+ workers[i].getModule().abort();
+ }
+ } finally {
+ service.loginFailed(client);
+ }
+ return true;
+ }
+
+ public boolean logout() throws LoginException {
+ try {
+ for (int i = 0; i < workers.length; i++) {
+ workers[i].getModule().logout();
+ }
+ } finally {
+ service.logout(client);
+ }
+ return true;
+ }
+
+ private JaasLoginServiceMBean connect() {
+ if(serverHost != null && serverPort > 0) {
+ return JaasLoginServiceRemotingClient.create(serverHost, serverPort);
+ } else {
+ return (JaasLoginServiceMBean) MBeanProxyFactory.getProxy(JaasLoginServiceMBean.class, Kernel.getKernel(kernelName).getMBeanServer(), JaasLoginService.OBJECT_NAME);
+ }
+ }
+
+ private class ClientLoginModule implements LoginModule {
+ private LoginModule source;
+ int index;
+
+ public ClientLoginModule(LoginModule source, int index) {
+ this.source = source;
+ this.index = index;
+ }
+
+ public void initialize(Subject subject, CallbackHandler callbackHandler,
+ Map sharedState, Map options) {
+ source.initialize(subject, callbackHandler, sharedState, options);
+ }
+
+ public boolean login() throws LoginException {
+ return source.login();
+ }
+
+ public boolean commit() throws LoginException {
+ boolean result = source.commit();
+ List list = new ArrayList();
+ for (Iterator it = subject.getPrincipals().iterator(); it.hasNext();) {
+ Principal p = (Principal) it.next();
+ if(!processedPrincipals.contains(p)) {
+ list.add(p);
+ processedPrincipals.add(p);
+ }
+ }
+ service.clientLoginModuleCommit(client, index, (Principal[]) list.toArray(new Principal[list.size()]));
+ return result;
+ }
+
+ public boolean abort() throws LoginException {
+ return source.abort();
+ }
+
+ public boolean logout() throws LoginException {
+ return source.logout();
+ }
+ }
+
+ private class ServerLoginModule implements LoginModule {
+ int index;
+ CallbackHandler handler;
+ Callback[] callbacks;
+
+ public ServerLoginModule(int index) {
+ this.index = index;
+ }
+
+ public void initialize(Subject subject, CallbackHandler handler,
+ Map sharedState, Map options) {
+ this.handler = handler;
+ try {
+ callbacks = service.getServerLoginCallbacks(client, index);
+ } catch (LoginException e) {
+ throw new RuntimeException("Server unable to initialize login module", e);
+ }
+ }
+
+ public boolean login() throws LoginException {
+ try {
+ handler.handle(callbacks);
+ return service.performServerLogin(client, index, callbacks);
+ } catch (LoginException e) {
+ throw e;
+ } catch (Exception e) {
+ e.printStackTrace();
+ throw new LoginException("Unable to log in: "+e.getMessage());
+ }
+ }
+
+ public boolean commit() throws LoginException {
+ return service.serverLoginModuleCommit(client, index);
+ }
+
+ public boolean abort() throws LoginException {
+ return false; // taken care of with a single call to the server
+ }
+
+ public boolean logout() throws LoginException {
+ return false; // taken care of with a single call to the server
+ }
+ }
+}
Added: geronimo/trunk/modules/security/src/java/org/apache/geronimo/security/jaas/JaasLoginModuleConfiguration.java
==============================================================================
--- (empty file)
+++ geronimo/trunk/modules/security/src/java/org/apache/geronimo/security/jaas/JaasLoginModuleConfiguration.java Tue Nov 16 14:34:08 2004
@@ -0,0 +1,52 @@
+package org.apache.geronimo.security.jaas;
+
+import org.apache.geronimo.common.GeronimoSecurityException;
+
+import javax.security.auth.spi.LoginModule;
+import java.io.Serializable;
+import java.util.Map;
+
+/**
+ * Describes the configuration of a LoginModule -- its name, class, control
+ * flag, options, and the Geronimo extension for whether it should run on
+ * the client side or server side.
+ *
+ * @version $Revision: 1.0$
+ */
+public class JaasLoginModuleConfiguration implements Serializable {
+ private boolean serverSide;
+ private LoginModuleControlFlag flag;
+ private String loginModuleName;
+ private Map options;
+ private transient LoginModule loginModule;
+
+ public JaasLoginModuleConfiguration(String loginModuleName, LoginModuleControlFlag flag, Map options, boolean serverSide) {
+ this.serverSide = serverSide;
+ this.flag = flag;
+ this.loginModuleName = loginModuleName;
+ this.options = options;
+ }
+
+ public LoginModule getLoginModule(ClassLoader loader) throws GeronimoSecurityException {
+ if(loginModule == null) {
+ try {
+ loginModule = (LoginModule) loader.loadClass(loginModuleName).newInstance();
+ } catch (Exception e) {
+ throw new GeronimoSecurityException("Unable to instantiate login module", e);
+ }
+ }
+ return loginModule;
+ }
+
+ public boolean isServerSide() {
+ return serverSide;
+ }
+
+ public LoginModuleControlFlag getFlag() {
+ return flag;
+ }
+
+ public Map getOptions() {
+ return options;
+ }
+}
Added: geronimo/trunk/modules/security/src/java/org/apache/geronimo/security/jaas/JaasLoginService.java
==============================================================================
--- (empty file)
+++ geronimo/trunk/modules/security/src/java/org/apache/geronimo/security/jaas/JaasLoginService.java Tue Nov 16 14:34:08 2004
@@ -0,0 +1,394 @@
+package org.apache.geronimo.security.jaas;
+
+import org.apache.geronimo.gbean.*;
+import org.apache.geronimo.security.realm.SecurityRealm;
+import org.apache.geronimo.security.SubjectId;
+import org.apache.geronimo.security.ContextManager;
+import org.apache.geronimo.security.IdentificationPrincipal;
+import org.apache.geronimo.common.GeronimoSecurityException;
+import org.apache.geronimo.kernel.jmx.JMXUtil;
+
+import javax.security.auth.callback.*;
+import javax.security.auth.login.LoginException;
+import javax.security.auth.login.AppConfigurationEntry;
+import javax.security.auth.spi.LoginModule;
+import javax.security.auth.Subject;
+import javax.crypto.SecretKey;
+import javax.crypto.Mac;
+import javax.crypto.spec.SecretKeySpec;
+import javax.management.ObjectName;
+import java.security.Principal;
+import java.security.NoSuchAlgorithmException;
+import java.security.InvalidKeyException;
+import java.util.*;
+
+import EDU.oswego.cs.dl.util.concurrent.ClockDaemon;
+import EDU.oswego.cs.dl.util.concurrent.ThreadFactory;
+
+/**
+ * The single point of contact for Geronimo JAAS realms. Instead of attempting
+ * to interact with JAAS realms directly, a client should either interact with
+ * this service, or use a LoginModule implementation that interacts with this
+ * service.
+ *
+ * @version $Revision: 1.0$
+ */
+public class JaasLoginService implements GBeanLifecycle, JaasLoginServiceMBean {
+ public static final ObjectName OBJECT_NAME = JMXUtil.getObjectName("geronimo.security:type=JaasLoginService");
+ private final static int DEFAULT_EXPIRED_LOGIN_SCAN_INTERVAL = 300000; // 5 mins
+ private final static int DEFAULT_MAX_LOGIN_DURATION = 1000 * 3600 * 24; // 1 day
+ private final static ClockDaemon clockDaemon;
+ private static long nextLoginModuleId = System.currentTimeMillis();
+ private ReferenceCollection realms;
+ private Object expiredLoginScanIdentifier;
+ private final SecretKey key;
+ private final String algorithm;
+ private final ClassLoader classLoader;
+ private final Map activeLogins = new Hashtable();
+ private int expiredLoginScanIntervalMillis = DEFAULT_EXPIRED_LOGIN_SCAN_INTERVAL;
+ private int maxLoginDurationMillis = DEFAULT_MAX_LOGIN_DURATION;
+
+ public JaasLoginService(String algorithm, String password, ClassLoader classLoader) {
+ this.classLoader = classLoader;
+ this.algorithm = algorithm;
+ //todo: password could just be randomly generated??
+ key = new SecretKeySpec(password.getBytes(), algorithm);
+ }
+
+ /**
+ * GBean property
+ */
+ public Collection getRealms() throws GeronimoSecurityException {
+ return realms;
+ }
+
+ /**
+ * GBean property
+ */
+ public void setRealms(Collection realms) {
+ this.realms = (ReferenceCollection) realms;
+ //todo: add listener to drop logins when realm is removed
+ }
+
+ /**
+ * GBean property
+ */
+ public int getMaxLoginDurationMillis() {
+ return maxLoginDurationMillis;
+ }
+
+ /**
+ * GBean property
+ */
+ public void setMaxLoginDurationMillis(int maxLoginDurationMillis) {
+ if(maxLoginDurationMillis == 0) {
+ maxLoginDurationMillis = DEFAULT_MAX_LOGIN_DURATION;
+ }
+ this.maxLoginDurationMillis = maxLoginDurationMillis;
+ }
+
+ /**
+ * GBean property
+ */
+ public int getExpiredLoginScanIntervalMillis() {
+ return expiredLoginScanIntervalMillis;
+ }
+
+ /**
+ * GBean property
+ */
+ public void setExpiredLoginScanIntervalMillis(int expiredLoginScanIntervalMillis) {
+ if(expiredLoginScanIntervalMillis == 0) {
+ expiredLoginScanIntervalMillis = DEFAULT_EXPIRED_LOGIN_SCAN_INTERVAL;
+ }
+ this.expiredLoginScanIntervalMillis = expiredLoginScanIntervalMillis;
+ }
+
+ public void doStart() throws WaitingException, Exception {
+ expiredLoginScanIdentifier = clockDaemon.executePeriodically(expiredLoginScanIntervalMillis, new ExpirationMonitor(), true);
+ }
+
+ public void doStop() throws WaitingException, Exception {
+ ClockDaemon.cancel(expiredLoginScanIdentifier);
+ //todo: shut down all logins
+ }
+
+ public void doFail() {
+ //todo: shut down all logins
+ }
+
+ /**
+ * Starts a new authentication process on behalf of an end user. The
+ * returned ID will identify that user throughout the user's interaction
+ * with the server. On the server side, that means maintaining the
+ * Subject and Principals for the user.
+ *
+ * @return The UserIdentifier used as an argument for the rest of the
+ * methods in this class.
+ */
+ public JaasClientId connectToRealm(String realmName) {
+ for (Iterator it = realms.iterator(); it.hasNext();) {
+ SecurityRealm realm = (SecurityRealm) it.next();
+ if(realm.getRealmName().equals(realmName)) {
+ return initializeClient(realm);
+ }
+ }
+ throw new GeronimoSecurityException("No such realm ("+realmName+")");
+ }
+
+ /**
+ * Gets the login module configuration for the specified realm. The
+ * caller needs that in order to perform the authentication process.
+ */
+ public JaasLoginModuleConfiguration[] getLoginConfiguration(JaasClientId userIdentifier) throws LoginException {
+ JaasSecurityContext context = (JaasSecurityContext) activeLogins.get(userIdentifier);
+ if(context == null) {
+ throw new ExpiredLoginModuleException();
+ }
+ return context.getModules();
+ }
+
+ /**
+ * Retrieves callbacks for a server side login module. When the client
+ * is going through the configured login modules, if a specific login
+ * module is client-side, it will be handled directly. If it is
+ * server-side, the client gets the callbacks (using this method),
+ * populates them, and sends them back to the server.
+ */
+ public Callback[] getServerLoginCallbacks(JaasClientId userIdentifier, int loginModuleIndex) throws LoginException {
+ JaasSecurityContext context = (JaasSecurityContext) activeLogins.get(userIdentifier);
+ if(context == null) {
+ throw new ExpiredLoginModuleException();
+ }
+ if(loginModuleIndex < 0 || loginModuleIndex >= context.getModules().length || !context.getModules()[loginModuleIndex].isServerSide()) {
+ throw new LoginException("Invalid login module specified");
+ }
+ JaasLoginModuleConfiguration config = context.getModules()[loginModuleIndex];
+ LoginModule module = config.getLoginModule(classLoader);
+ //todo: properly handle shared state
+ module.initialize(context.getSubject(), context.getHandler(), new HashMap(), config.getOptions());
+ try {
+ module.login();
+ } catch (LoginException e) {}
+ try {
+ module.abort();
+ } catch(LoginException e) {}
+ return context.getHandler().finalizeCallbackList();
+ }
+
+ /**
+ * Returns populated callbacks for a server side login module. When the
+ * client is going through the configured login modules, if a specific
+ * login module is client-side, it will be handled directly. If it is
+ * server-side, the client gets the callbacks, populates them, and sends
+ * them back to the server (using this method).
+ */
+ public boolean performServerLogin(JaasClientId userIdentifier, int loginModuleIndex, Callback[] results) throws LoginException {
+ JaasSecurityContext context = (JaasSecurityContext) activeLogins.get(userIdentifier);
+ if(context == null) {
+ throw new ExpiredLoginModuleException();
+ }
+ if(loginModuleIndex < 0 || loginModuleIndex >= context.getModules().length || !context.getModules()[loginModuleIndex].isServerSide()) {
+ throw new LoginException("Invalid login module specified");
+ }
+ JaasLoginModuleConfiguration module = context.getModules()[loginModuleIndex];
+ return module.getLoginModule(classLoader).login();
+ }
+
+ /**
+ * Indicates that the overall login succeeded, and some principals were
+ * generated by a client-side login module. This method needs to be called
+ * once for each client-side login module, to specify Principals for each
+ * module.
+ */
+ public void clientLoginModuleCommit(JaasClientId userIdentifier, int loginModuleIndex, Principal[] clientLoginModulePrincipals) throws LoginException {
+ JaasSecurityContext context = (JaasSecurityContext) activeLogins.get(userIdentifier);
+ if(context == null) {
+ throw new ExpiredLoginModuleException();
+ }
+ if(loginModuleIndex < 0 || loginModuleIndex >= context.getModules().length || context.getModules()[loginModuleIndex].isServerSide()) {
+ throw new LoginException("Invalid login module specified");
+ }
+ context.processPrincipals(clientLoginModulePrincipals);
+ }
+
+ /**
+ * Indicates that the overall login succeeded, and a particular server-side
+ * login module should be committed. This method needs to be called
+ * once for each server-side login module that was processed before the
+ * overall authentication succeeded.
+ */
+ public boolean serverLoginModuleCommit(JaasClientId userIdentifier, int loginModuleIndex) throws LoginException {
+ JaasSecurityContext context = (JaasSecurityContext) activeLogins.get(userIdentifier);
+ if(context == null) {
+ throw new ExpiredLoginModuleException();
+ }
+ if(loginModuleIndex < 0 || loginModuleIndex >= context.getModules().length || !context.getModules()[loginModuleIndex].isServerSide()) {
+ throw new LoginException("Invalid login module specified");
+ }
+ JaasLoginModuleConfiguration module = context.getModules()[loginModuleIndex];
+ boolean result = module.getLoginModule(classLoader).commit();
+ context.processPrincipals();
+ return result;
+ }
+
+ /**
+ * Indicates that the overall login succeeded. All login modules that were
+ * touched should have been logged in and committed before calling this.
+ */
+ public IdentificationPrincipal loginSucceeded(JaasClientId userIdentifier) throws LoginException {
+ JaasSecurityContext context = (JaasSecurityContext) activeLogins.get(userIdentifier);
+ if(context == null) {
+ throw new ExpiredLoginModuleException();
+ }
+
+ Subject subject = context.getSubject();
+ ContextManager.registerSubject(subject);
+ SubjectId id = ContextManager.getSubjectId(subject);
+ IdentificationPrincipal principal = new IdentificationPrincipal(id);
+ subject.getPrincipals().add(principal);
+ return principal;
+ }
+
+ /**
+ * Indicates that the overall login failed, and the server should release
+ * any resources associated with the user ID.
+ */
+ public void loginFailed(JaasClientId userIdentifier) {
+ activeLogins.remove(userIdentifier);
+ }
+
+ /**
+ * Indicates that the client has logged out, and the server should release
+ * any resources associated with the user ID.
+ */
+ public void logout(JaasClientId userIdentifier) throws LoginException {
+ JaasSecurityContext context = (JaasSecurityContext) activeLogins.get(userIdentifier);
+ if(context == null) {
+ throw new ExpiredLoginModuleException();
+ }
+ ContextManager.unregisterSubject(context.getSubject());
+ activeLogins.remove(userIdentifier);
+ }
+
+ /**
+ * Prepares a new security context for a new client. Each client uses a
+ * unique security context to sture their authentication progress,
+ * principals, etc.
+ *
+ * @param realm The realm the client is authenticating to
+ */
+ private JaasClientId initializeClient(SecurityRealm realm) {
+ long id;
+ synchronized(JaasLoginService.class) {
+ id = ++nextLoginModuleId;
+ }
+ JaasClientId clientId = new JaasClientId(id, hash(id));
+ AppConfigurationEntry[] entries = realm.getAppConfigurationEntries();
+ JaasLoginModuleConfiguration[] modules = new JaasLoginModuleConfiguration[entries.length];
+ for (int i = 0; i < modules.length; i++) {
+ modules[i] = new JaasLoginModuleConfiguration(entries[i].getLoginModuleName(),
+ LoginModuleControlFlag.getInstance(entries[i].getControlFlag()), entries[i].getOptions(),
+ realm.isLoginModuleLocal()); //todo: calculate local-ness per module
+ }
+ JaasSecurityContext context = new JaasSecurityContext(realm.getRealmName(), modules);
+ activeLogins.put(clientId, context);
+ return clientId;
+ }
+
+ /**
+ * Hashes a unique ID. The client keeps an object around with the ID and
+ * the hash of the ID. That way it's not so easy to forge an ID and steal
+ * someone else's account.
+ */
+ private byte[] hash(long id) {
+ byte[] bytes = new byte[8];
+ for (int i = 7; i >= 0; i--) {
+ bytes[i] = (byte) (id);
+ id >>>= 8;
+ }
+
+ try {
+ Mac mac = Mac.getInstance(algorithm);
+ mac.init(key);
+ mac.update(bytes);
+
+ return mac.doFinal();
+ } catch (NoSuchAlgorithmException e) {
+ } catch (InvalidKeyException e) {
+ }
+ assert false : "Should never have reached here";
+ return null;
+ }
+
+
+
+ // This stuff takes care of whacking old logins
+ static {
+ clockDaemon = new ClockDaemon();
+ clockDaemon.setThreadFactory(new ThreadFactory() {
+ public Thread newThread(Runnable r) {
+ Thread t = new Thread(r, "LoginService login modules monitor");
+ t.setDaemon(true);
+ return t;
+ }
+ });
+ }
+ private class ExpirationMonitor implements Runnable { //todo: different timeouts per realm?
+ public void run() {
+ long now = System.currentTimeMillis();
+ List list = new LinkedList();
+ synchronized(activeLogins) {
+ for (Iterator it = activeLogins.keySet().iterator(); it.hasNext();) {
+ JaasClientId id = (JaasClientId) it.next();
+ JaasSecurityContext context = (JaasSecurityContext) activeLogins.get(id);
+ int age = (int)(now-context.getCreated());
+ if(context.isDone() || age > maxLoginDurationMillis) {
+ list.add(context);
+ context.setDone(true);
+ it.remove();
+ }
+ }
+ }
+ for (Iterator it = list.iterator(); it.hasNext();) {
+ JaasSecurityContext context = (JaasSecurityContext) it.next();
+ ContextManager.unregisterSubject(context.getSubject());
+ }
+ }
+ }
+
+
+
+ // This stuff takes care of making this object into a GBean
+ public static final GBeanInfo GBEAN_INFO;
+
+ static {
+ GBeanInfoBuilder infoFactory = new GBeanInfoBuilder(JaasLoginService.class);
+
+ infoFactory.addAttribute("algorithm", String.class, true);
+ infoFactory.addAttribute("password", String.class, true);
+ infoFactory.addAttribute("classLoader", ClassLoader.class, false);
+ infoFactory.addAttribute("maxLoginDurationMillis", int.class, true);
+ infoFactory.addAttribute("expiredLoginScanIntervalMillis", int.class, true);
+
+ infoFactory.addOperation("connectToRealm", new Class[]{String.class});
+ infoFactory.addOperation("getLoginConfiguration", new Class[]{JaasClientId.class});
+ infoFactory.addOperation("getServerLoginCallbacks", new Class[]{JaasClientId.class, int.class});
+ infoFactory.addOperation("performServerLogin", new Class[]{JaasClientId.class, int.class, Callback[].class});
+ infoFactory.addOperation("clientLoginModuleCommit", new Class[]{JaasClientId.class, int.class, Principal[].class});
+ infoFactory.addOperation("serverLoginModuleCommit", new Class[]{JaasClientId.class, int.class});
+ infoFactory.addOperation("loginSucceeded", new Class[]{JaasClientId.class});
+ infoFactory.addOperation("loginFailed", new Class[]{JaasClientId.class});
+ infoFactory.addOperation("logout", new Class[]{JaasClientId.class});
+
+ infoFactory.addReference("Realms", SecurityRealm.class);
+
+ infoFactory.setConstructor(new String[] {"algorithm", "password", "classLoader"});
+
+ GBEAN_INFO = infoFactory.getBeanInfo();
+ }
+
+ public static GBeanInfo getGBeanInfo() {
+ return GBEAN_INFO;
+ }
+}
Added: geronimo/trunk/modules/security/src/java/org/apache/geronimo/security/jaas/JaasLoginServiceMBean.java
==============================================================================
--- (empty file)
+++ geronimo/trunk/modules/security/src/java/org/apache/geronimo/security/jaas/JaasLoginServiceMBean.java Tue Nov 16 14:34:08 2004
@@ -0,0 +1,115 @@
+package org.apache.geronimo.security.jaas;
+
+import org.apache.geronimo.common.GeronimoSecurityException;
+import org.apache.geronimo.security.IdentificationPrincipal;
+
+import javax.security.auth.login.LoginException;
+import javax.security.auth.callback.Callback;
+import java.security.Principal;
+import java.util.Collection;
+
+/**
+ *
+ *
+ * @version $Revision: 1.0$
+ */
+public interface JaasLoginServiceMBean {
+ /**
+ * GBean property
+ */
+ public Collection getRealms() throws GeronimoSecurityException;
+
+ /**
+ * GBean property
+ */
+ public void setRealms(Collection realms);
+
+ /**
+ * GBean property
+ */
+ public int getMaxLoginDurationMillis();
+
+ /**
+ * GBean property
+ */
+ public void setMaxLoginDurationMillis(int maxLoginDurationMillis);
+
+ /**
+ * GBean property
+ */
+ public int getExpiredLoginScanIntervalMillis();
+
+ /**
+ * GBean property
+ */
+ public void setExpiredLoginScanIntervalMillis(int expiredLoginScanIntervalMillis);
+
+ /**
+ * Starts a new authentication process on behalf of an end user. The
+ * returned ID will identify that user throughout the user's interaction
+ * with the server. On the server side, that means maintaining the
+ * Subject and Principals for the user.
+ *
+ * @return The UserIdentifier used as an argument for the rest of the
+ * methods in this class.
+ */
+ public JaasClientId connectToRealm(String realmName);
+
+ /**
+ * Gets the login module configuration for the specified realm. The
+ * caller needs that in order to perform the authentication process.
+ */
+ public JaasLoginModuleConfiguration[] getLoginConfiguration(JaasClientId userIdentifier) throws LoginException ;
+
+ /**
+ * Retrieves callbacks for a server side login module. When the client
+ * is going through the configured login modules, if a specific login
+ * module is client-side, it will be handled directly. If it is
+ * server-side, the client gets the callbacks (using this method),
+ * populates them, and sends them back to the server.
+ */
+ public Callback[] getServerLoginCallbacks(JaasClientId userIdentifier, int loginModuleIndex) throws LoginException;
+
+ /**
+ * Returns populated callbacks for a server side login module. When the
+ * client is going through the configured login modules, if a specific
+ * login module is client-side, it will be handled directly. If it is
+ * server-side, the client gets the callbacks, populates them, and sends
+ * them back to the server (using this method).
+ */
+ public boolean performServerLogin(JaasClientId userIdentifier, int loginModuleIndex, Callback[] results) throws LoginException;
+
+ /**
+ * Indicates that the overall login succeeded, and some principals were
+ * generated by a client-side login module. This method needs to be called
+ * once for each client-side login module, to specify Principals for each
+ * module.
+ */
+ public void clientLoginModuleCommit(JaasClientId userIdentifier, int loginModuleIndex, Principal[] clientLoginModulePrincipals) throws LoginException;
+
+ /**
+ * Indicates that the overall login succeeded, and a particular server-side
+ * login module should be committed. This method needs to be called
+ * once for each server-side login module that was processed before the
+ * overall authentication succeeded.
+ */
+ public boolean serverLoginModuleCommit(JaasClientId userIdentifier, int loginModuleIndex) throws LoginException;
+
+ /**
+ * Indicates that the overall login succeeded. All login modules that were
+ * touched should have been logged in and committed before calling this.
+ */
+ public IdentificationPrincipal loginSucceeded(JaasClientId userIdentifier) throws LoginException;
+
+ /**
+ * Indicates that the overall login failed, and the server should release
+ * any resources associated with the user ID.
+ */
+ public void loginFailed(JaasClientId userIdentifier);
+
+ /**
+ * Indicates that the client has logged out, and the server should release
+ * any resources associated with the user ID.
+ */
+ public void logout(JaasClientId userIdentifier) throws LoginException;
+}
Added: geronimo/trunk/modules/security/src/java/org/apache/geronimo/security/jaas/JaasSecurityContext.java
==============================================================================
--- (empty file)
+++ geronimo/trunk/modules/security/src/java/org/apache/geronimo/security/jaas/JaasSecurityContext.java Tue Nov 16 14:34:08 2004
@@ -0,0 +1,81 @@
+package org.apache.geronimo.security.jaas;
+
+import org.apache.geronimo.security.RealmPrincipal;
+import org.apache.geronimo.security.ContextManager;
+
+import javax.security.auth.Subject;
+import java.util.*;
+import java.security.Principal;
+
+/**
+ * Tracks security information about a single user. This is used before,
+ * during, and after the login.
+ *
+ * @version $Revision: 1.0$
+ */
+public class JaasSecurityContext {
+ private String realmName;
+ private Subject subject;
+ private long created;
+ private boolean done;
+ private JaasLoginModuleConfiguration[] modules;
+ private DecouplingCallbackHandler handler;
+ private Set processedPrincipals = new HashSet();
+
+ public JaasSecurityContext(String realmName, JaasLoginModuleConfiguration[] modules) {
+ this.realmName = realmName;
+ this.created = System.currentTimeMillis();
+ this.done = false;
+ this.modules = modules;
+ subject = new Subject();
+ }
+
+ public Subject getSubject() {
+ return subject;
+ }
+
+ public long getCreated() {
+ return created;
+ }
+
+ public boolean isDone() {
+ return done;
+ }
+
+ public void setDone(boolean done) {
+ this.done = done;
+ }
+
+ public JaasLoginModuleConfiguration[] getModules() {
+ return modules;
+ }
+
+ public DecouplingCallbackHandler getHandler() {
+ if(handler == null) { //lazy create
+ handler = new DecouplingCallbackHandler();
+ }
+ return handler;
+ }
+
+ public void processPrincipals() {
+ List list = new LinkedList();
+ for (Iterator it = subject.getPrincipals().iterator(); it.hasNext();) {
+ Principal p = (Principal) it.next();
+ if(!processedPrincipals.contains(p)) {
+ list.add(ContextManager.registerPrincipal(new RealmPrincipal(realmName, p)));
+ processedPrincipals.add(p);
+ }
+ }
+ subject.getPrincipals().addAll(list);
+ }
+
+ public void processPrincipals(Principal[] principals) {
+ List list = new LinkedList();
+ for (int i = 0; i < principals.length; i++) {
+ Principal p = principals[i];
+ list.add(p);
+ list.add(ContextManager.registerPrincipal(new RealmPrincipal(realmName, p)));
+ }
+ subject.getPrincipals().addAll(list);
+ }
+}
Added: geronimo/trunk/modules/security/src/java/org/apache/geronimo/security/remoting/jmx/JaasLoginServiceRemotingClient.java
==============================================================================
--- (empty file)
+++ geronimo/trunk/modules/security/src/java/org/apache/geronimo/security/remoting/jmx/JaasLoginServiceRemotingClient.java Tue Nov 16 14:34:08 2004
@@ -0,0 +1,56 @@
+/**
+ *
+ * Copyright 2004 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.geronimo.security.remoting.jmx;
+
+import java.net.URI;
+import java.net.URISyntaxException;
+
+import org.apache.geronimo.core.service.Interceptor;
+import org.apache.geronimo.proxy.ProxyContainer;
+import org.apache.geronimo.remoting.MarshalingInterceptor;
+import org.apache.geronimo.remoting.jmx.NotificationRemoterInterceptor;
+import org.apache.geronimo.remoting.transport.RemoteTransportInterceptor;
+import org.apache.geronimo.security.jaas.JaasLoginServiceMBean;
+
+
+/**
+ * @version $Rev: 46019 $ $Date: 2004-09-14 05:56:06 -0400 (Tue, 14 Sep 2004) $
+ */
+public class JaasLoginServiceRemotingClient {
+ static public JaasLoginServiceMBean create(String host, int port) throws IllegalArgumentException {
+ URI target;
+ try {
+ target = new URI("async", null, host, port, "/JMX", null, "geronimo.remoting:target=JaasLoginServiceRemotingServer");
+ } catch (URISyntaxException e) {
+ throw new IllegalArgumentException("Bad host or port.");
+ }
+ return create(target);
+ }
+
+ static public JaasLoginServiceMBean create(URI target) {
+ // Setup the client side container..
+ RemoteTransportInterceptor remoteInterceptor = new RemoteTransportInterceptor(target);
+ remoteInterceptor.setRemoteURI(target);
+
+ Interceptor firstInterceptor = new MarshalingInterceptor(remoteInterceptor);
+ firstInterceptor = new NotificationRemoterInterceptor(firstInterceptor);
+
+ ProxyContainer clientContainer = new ProxyContainer(firstInterceptor);
+ return (JaasLoginServiceMBean) clientContainer.createProxy(JaasLoginServiceMBean.class.getClassLoader(), new Class[]{JaasLoginServiceMBean.class});
+ }
+}
Added: geronimo/trunk/modules/security/src/java/org/apache/geronimo/security/remoting/jmx/JaasLoginServiceRemotingServer.java
==============================================================================
--- (empty file)
+++ geronimo/trunk/modules/security/src/java/org/apache/geronimo/security/remoting/jmx/JaasLoginServiceRemotingServer.java Tue Nov 16 14:34:08 2004
@@ -0,0 +1,111 @@
+/**
+ *
+ * Copyright 2004 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.geronimo.security.remoting.jmx;
+
+import javax.management.ObjectName;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import org.apache.geronimo.core.service.Interceptor;
+import org.apache.geronimo.gbean.GBeanInfo;
+import org.apache.geronimo.gbean.GBeanInfoBuilder;
+import org.apache.geronimo.gbean.GBeanLifecycle;
+import org.apache.geronimo.kernel.Kernel;
+import org.apache.geronimo.kernel.jmx.JMXUtil;
+import org.apache.geronimo.kernel.jmx.MBeanProxyFactory;
+import org.apache.geronimo.proxy.ProxyContainer;
+import org.apache.geronimo.proxy.ReflexiveInterceptor;
+import org.apache.geronimo.remoting.DeMarshalingInterceptor;
+import org.apache.geronimo.remoting.router.JMXRouter;
+import org.apache.geronimo.remoting.router.JMXTarget;
+import org.apache.geronimo.security.jaas.JaasLoginServiceMBean;
+
+
+/**
+ * @version $Rev: 56022 $ $Date: 2004-10-30 01:16:18 -0400 (Sat, 30 Oct 2004) $
+ */
+public class JaasLoginServiceRemotingServer implements GBeanLifecycle, JMXTarget {
+ private static final Log log = LogFactory.getLog(JaasLoginServiceRemotingServer.class);
+ private final Kernel kernel;
+ private final ObjectName objectName;
+ private ProxyContainer serverContainer;
+ private DeMarshalingInterceptor demarshaller;
+ private JMXRouter router;
+
+ public JaasLoginServiceRemotingServer(Kernel kernel, String objectName) {
+ this.kernel = kernel;
+ this.objectName = JMXUtil.getObjectName(objectName);
+ }
+
+ public Interceptor getRemotingEndpointInterceptor() {
+ return demarshaller;
+ }
+
+ public JMXRouter getRouter() {
+ return router;
+ }
+
+ public void setRouter(JMXRouter router) {
+ this.router = router;
+ }
+
+ public void doStart() throws Exception {
+ router.register(objectName, this);
+
+ // Setup the server side contianer..
+ JaasLoginServiceMBean loginService = (JaasLoginServiceMBean) MBeanProxyFactory.getProxy(JaasLoginServiceMBean.class,
+ kernel.getMBeanServer(),
+ JMXUtil.getObjectName("geronimo.security:type=JaasLoginService"));
+ Interceptor firstInterceptor = new ReflexiveInterceptor(loginService);
+ demarshaller = new DeMarshalingInterceptor(firstInterceptor, getClass().getClassLoader());
+ serverContainer = new ProxyContainer(firstInterceptor);
+
+ log.info("Started login service stub");
+ }
+
+ public void doStop() {
+ router.unregister(objectName);
+
+ serverContainer = null;
+ demarshaller = null;
+ log.info("Stopped login service stub");
+ }
+
+ public void doFail() {
+ serverContainer = null;
+ demarshaller = null;
+ log.info("Failed login service stub");
+ }
+
+ public static final GBeanInfo GBEAN_INFO;
+
+ static {
+ GBeanInfoBuilder infoFactory = new GBeanInfoBuilder(JaasLoginServiceRemotingServer.class);
+ infoFactory.addAttribute("kernel", Kernel.class, false);
+ infoFactory.addAttribute("objectName", String.class, false);
+ infoFactory.addReference("Router", JMXRouter.class);
+ infoFactory.addOperation("getRemotingEndpointInterceptor");
+ infoFactory.setConstructor(new String[]{"kernel", "objectName"});
+ GBEAN_INFO = infoFactory.getBeanInfo();
+ }
+
+ public static GBeanInfo getGBeanInfo() {
+ return GBEAN_INFO;
+ }
+}
Modified: geronimo/trunk/modules/security/src/test-data/data/login.config
==============================================================================
--- geronimo/trunk/modules/security/src/test-data/data/login.config (original)
+++ geronimo/trunk/modules/security/src/test-data/data/login.config Tue Nov 16 14:34:08 2004
@@ -3,48 +3,41 @@
*/
FOO {
- org.apache.geronimo.security.jaas.RemoteLoginModule required
- debug=true
- uri="async://localhost:4242"
- realm="properties-realm"
- kernel="test.kernel";
+ org.apache.geronimo.security.jaas.JaasLoginCoordinator required
+ host="localhost"
+ port="4242"
+ realm="properties-realm";
};
kerberos {
- org.apache.geronimo.security.jaas.RemoteLoginModule required
- debug=true
- uri="async://localhost:4242"
- realm="TOOLAZYDOGS.COM"
- kernel="test.kernel";
+ org.apache.geronimo.security.jaas.JaasLoginCoordinator required
+ host="localhost"
+ port="4242"
+ realm="TOOLAZYDOGS.COM";
};
sql {
- org.apache.geronimo.security.jaas.RemoteLoginModule required
- debug=true
- uri="async://localhost:4242"
- realm="sql-realm"
- kernel="test.kernel";
+ org.apache.geronimo.security.jaas.JaasLoginCoordinator required
+ host="localhost"
+ port="4242"
+ realm="sql-realm";
};
properties {
- org.apache.geronimo.security.jaas.RemoteLoginModule required
- debug=true
- uri="async://localhost:4242"
- realm="properties-realm"
- kernel="test.kernel";
+ org.apache.geronimo.security.jaas.JaasLoginCoordinator required
+ host="localhost"
+ port="4242"
+ realm="properties-realm";
};
kerberos-local {
- org.apache.geronimo.security.jaas.LocalLoginModule required
- debug=true
+ org.apache.geronimo.security.jaas.JaasLoginCoordinator required
realm="TOOLAZYDOGS.COM"
kernel="test.kernel";
};
bridge {
- org.apache.geronimo.security.jaas.LocalLoginModule required
- debug=true
+ org.apache.geronimo.security.jaas.JaasLoginCoordinator required
realm="bridge-realm"
kernel="test.kernel";
};
-
Modified: geronimo/trunk/modules/security/src/test/org/apache/geronimo/security/AbstractTest.java
==============================================================================
--- geronimo/trunk/modules/security/src/test/org/apache/geronimo/security/AbstractTest.java (original)
+++ geronimo/trunk/modules/security/src/test/org/apache/geronimo/security/AbstractTest.java Tue Nov 16 14:34:08 2004
@@ -55,10 +55,10 @@
// Create all the parts
- gbean = new GBeanMBean("org.apache.geronimo.security.jaas.LoginService");
- loginService = new ObjectName("geronimo.security:type=LoginService");
+ gbean = new GBeanMBean("org.apache.geronimo.security.jaas.JaasLoginService");
+ loginService = new ObjectName("geronimo.security:type=JaasLoginService");
gbean.setReferencePatterns("Realms", Collections.singleton(new ObjectName("geronimo.security:type=SecurityRealm,*")));
- gbean.setAttribute("reclaimPeriod", new Long(10 * 1000)); // todo check other tests to see if ok
+// gbean.setAttribute("reclaimPeriod", new Long(10 * 1000)); // todo check other tests to see if ok
gbean.setAttribute("algorithm", "HmacSHA1");
gbean.setAttribute("password", "secret");
kernel.loadGBean(loginService, gbean);
@@ -85,9 +85,9 @@
jmxRouter = new ObjectName("geronimo.remoting:router=JMXRouter");
kernel.loadGBean(jmxRouter, gbean);
- gbean = new GBeanMBean("org.apache.geronimo.security.remoting.jmx.LoginServiceStub");
+ gbean = new GBeanMBean("org.apache.geronimo.security.remoting.jmx.JaasLoginServiceRemotingServer");
gbean.setReferencePatterns("Router", Collections.singleton(jmxRouter));
- serverStub = new ObjectName("geronimo.remoting:target=LoginServiceStub");
+ serverStub = new ObjectName("geronimo.remoting:target=JaasLoginServiceRemotingServer");
kernel.loadGBean(serverStub, gbean);
kernel.startGBean(loginService);
Modified: geronimo/trunk/modules/security/src/test/org/apache/geronimo/security/bridge/CallerIdentityUserPasswordBridgeTest.java
==============================================================================
--- geronimo/trunk/modules/security/src/test/org/apache/geronimo/security/bridge/CallerIdentityUserPasswordBridgeTest.java (original)
+++ geronimo/trunk/modules/security/src/test/org/apache/geronimo/security/bridge/CallerIdentityUserPasswordBridgeTest.java Tue Nov 16 14:34:08 2004
@@ -21,6 +21,10 @@
import javax.security.auth.login.LoginException;
import org.apache.geronimo.security.realm.providers.GeronimoPasswordCredential;
+import org.apache.geronimo.security.IdentificationPrincipal;
+import org.apache.geronimo.security.ContextManager;
+
+import java.util.Set;
/**
@@ -40,6 +44,11 @@
Subject sourceSubject = new Subject();
sourceSubject.getPrivateCredentials().add(new GeronimoPasswordCredential(AbstractBridgeTest.USER, AbstractBridgeTest.PASSWORD.toCharArray()));
Subject targetSubject = bridge.mapSubject(sourceSubject);
+ assertTrue("expected non-null client subject", targetSubject != null);
+ Set set = targetSubject.getPrincipals(IdentificationPrincipal.class);
+ assertEquals("client subject should have one ID principal", set.size(), 1);
+ IdentificationPrincipal idp = (IdentificationPrincipal)set.iterator().next();
+ targetSubject = ContextManager.getRegisteredSubject(idp.getId());
checkValidSubject(targetSubject);
}
Modified: geronimo/trunk/modules/security/src/test/org/apache/geronimo/security/bridge/ConfiguredIdentityUserPasswordBridgeTest.java
==============================================================================
--- geronimo/trunk/modules/security/src/test/org/apache/geronimo/security/bridge/ConfiguredIdentityUserPasswordBridgeTest.java (original)
+++ geronimo/trunk/modules/security/src/test/org/apache/geronimo/security/bridge/ConfiguredIdentityUserPasswordBridgeTest.java Tue Nov 16 14:34:08 2004
@@ -17,7 +17,11 @@
package org.apache.geronimo.security.bridge;
+import org.apache.geronimo.security.IdentificationPrincipal;
+import org.apache.geronimo.security.ContextManager;
+
import javax.security.auth.Subject;
+import java.util.Set;
/**
@@ -35,6 +39,13 @@
public void testConfiguredIdentityBridge() throws Exception {
Subject sourceSubject = new Subject();
Subject targetSubject = bridge.mapSubject(sourceSubject);
+
+ assertTrue("expected non-null client subject", targetSubject != null);
+ Set set = targetSubject.getPrincipals(IdentificationPrincipal.class);
+ assertEquals("client subject should have one ID principal", set.size(), 1);
+ IdentificationPrincipal idp = (IdentificationPrincipal)set.iterator().next();
+ targetSubject = ContextManager.getRegisteredSubject(idp.getId());
+
checkValidSubject(targetSubject);
}
Modified: geronimo/trunk/modules/security/src/test/org/apache/geronimo/security/bridge/MappingUserPasswordBridgeTest.java
==============================================================================
--- geronimo/trunk/modules/security/src/test/org/apache/geronimo/security/bridge/MappingUserPasswordBridgeTest.java (original)
+++ geronimo/trunk/modules/security/src/test/org/apache/geronimo/security/bridge/MappingUserPasswordBridgeTest.java Tue Nov 16 14:34:08 2004
@@ -17,9 +17,13 @@
package org.apache.geronimo.security.bridge;
+import org.apache.geronimo.security.IdentificationPrincipal;
+import org.apache.geronimo.security.ContextManager;
+
import java.security.Principal;
import java.util.HashMap;
import java.util.Map;
+import java.util.Set;
import javax.security.auth.Subject;
@@ -65,6 +69,11 @@
subject.getPrincipals().add(new TestUserNamePrincipal(SOURCE_USER_1));
subject.getPrincipals().add(new TestPasswordPrincipal(SOURCE_PASSWORD_1));
Subject targetSubject = bridge.mapSubject(subject);
+ assertTrue("expected non-null client subject", targetSubject != null);
+ Set set = targetSubject.getPrincipals(IdentificationPrincipal.class);
+ assertEquals("client subject should have one ID principal", set.size(), 1);
+ IdentificationPrincipal idp = (IdentificationPrincipal)set.iterator().next();
+ targetSubject = ContextManager.getRegisteredSubject(idp.getId());
checkValidSubject(targetSubject);
}
@@ -75,7 +84,7 @@
try {
bridge.mapSubject(subject);
fail();
- } catch (Exception e) {
+ } catch (Throwable e) {
}
}
@@ -87,7 +96,7 @@
try {
bridge.mapSubject(subject);
fail();
- } catch (Exception e) {
+ } catch (Throwable e) {
}
}
Modified: geronimo/trunk/modules/security/src/test/org/apache/geronimo/security/jaas/ConfigurationEntryTest.java
==============================================================================
--- geronimo/trunk/modules/security/src/test/org/apache/geronimo/security/jaas/ConfigurationEntryTest.java (original)
+++ geronimo/trunk/modules/security/src/test/org/apache/geronimo/security/jaas/ConfigurationEntryTest.java Tue Nov 16 14:34:08 2004
@@ -24,6 +24,7 @@
import java.net.URI;
import java.util.Collections;
import java.util.Properties;
+import java.util.Set;
import junit.framework.TestCase;
@@ -57,13 +58,18 @@
context.login();
Subject subject = context.getSubject();
+ assertTrue("expected non-null client subject", subject != null);
+ Set set = subject.getPrincipals(IdentificationPrincipal.class);
+ assertEquals("client subject should have one ID principal", set.size(), 1);
+ IdentificationPrincipal idp = (IdentificationPrincipal)set.iterator().next();
+ subject = ContextManager.getRegisteredSubject(idp.getId());
- assertTrue("expected non-null subject", subject != null);
- assertTrue("subject should have one remote principal", subject.getPrincipals(IdentificationPrincipal.class).size() == 1);
+ assertTrue("expected non-null server subject", subject != null);
+ assertTrue("server subject should have one remote principal", subject.getPrincipals(IdentificationPrincipal.class).size() == 1);
IdentificationPrincipal remote = (IdentificationPrincipal) subject.getPrincipals(IdentificationPrincipal.class).iterator().next();
- assertTrue("subject should be associated with remote id", ContextManager.getRegisteredSubject(remote.getId()) != null);
- assertTrue("subject should have five principals", subject.getPrincipals().size() == 5);
- assertTrue("subject should have two realm principal", subject.getPrincipals(RealmPrincipal.class).size() == 2);
+ assertTrue("server subject should be associated with remote id", ContextManager.getRegisteredSubject(remote.getId()) != null);
+ assertTrue("server subject should have two realm principals ("+subject.getPrincipals(RealmPrincipal.class).size()+")", subject.getPrincipals(RealmPrincipal.class).size() == 2);
+ assertTrue("server subject should have five principals ("+subject.getPrincipals().size()+")", subject.getPrincipals().size() == 5);
RealmPrincipal principal = (RealmPrincipal) subject.getPrincipals(RealmPrincipal.class).iterator().next();
assertTrue("id of principal should be non-zero", principal.getId() != 0);
@@ -90,10 +96,10 @@
loginConfiguration = new ObjectName("geronimo.security:type=LoginConfiguration");
kernel.loadGBean(loginConfiguration, gbean);
- gbean = new GBeanMBean("org.apache.geronimo.security.jaas.LoginService");
- loginService = new ObjectName("geronimo.security:type=LoginService");
+ gbean = new GBeanMBean("org.apache.geronimo.security.jaas.JaasLoginService");
+ loginService = new ObjectName("geronimo.security:type=JaasLoginService");
gbean.setReferencePatterns("Realms", Collections.singleton(new ObjectName("geronimo.security:type=SecurityRealm,*")));
- gbean.setAttribute("reclaimPeriod", new Long(100));
+// gbean.setAttribute("reclaimPeriod", new Long(100));
gbean.setAttribute("algorithm", "HmacSHA1");
gbean.setAttribute("password", "secret");
kernel.loadGBean(loginService, gbean);
@@ -130,9 +136,9 @@
jmxRouter = new ObjectName("geronimo.remoting:router=JMXRouter");
kernel.loadGBean(jmxRouter, gbean);
- gbean = new GBeanMBean("org.apache.geronimo.security.remoting.jmx.LoginServiceStub");
+ gbean = new GBeanMBean("org.apache.geronimo.security.remoting.jmx.JaasLoginServiceRemotingServer");
gbean.setReferencePatterns("Router", Collections.singleton(jmxRouter));
- serverStub = new ObjectName("geronimo.remoting:target=LoginServiceStub");
+ serverStub = new ObjectName("geronimo.remoting:target=JaasLoginServiceRemotingServer");
kernel.loadGBean(serverStub, gbean);
kernel.startGBean(loginConfiguration);
Modified: geronimo/trunk/modules/security/src/test/org/apache/geronimo/security/jaas/LoginPropertiesFileTest.java
==============================================================================
--- geronimo/trunk/modules/security/src/test/org/apache/geronimo/security/jaas/LoginPropertiesFileTest.java (original)
+++ geronimo/trunk/modules/security/src/test/org/apache/geronimo/security/jaas/LoginPropertiesFileTest.java Tue Nov 16 14:34:08 2004
@@ -23,6 +23,7 @@
import java.io.File;
import java.util.Collections;
import java.util.Properties;
+import java.util.Set;
import org.apache.geronimo.gbean.jmx.GBeanMBean;
import org.apache.geronimo.security.AbstractTest;
@@ -99,18 +100,23 @@
context.login();
Subject subject = context.getSubject();
+ assertTrue("expected non-null client subject", subject != null);
+ Set set = subject.getPrincipals(IdentificationPrincipal.class);
+ assertEquals("client subject should have one ID principal", set.size(), 1);
+ IdentificationPrincipal idp = (IdentificationPrincipal)set.iterator().next();
+ subject = ContextManager.getRegisteredSubject(idp.getId());
- assertTrue("expected non-null subject", subject != null);
- assertTrue("subject should have one remote principal", subject.getPrincipals(IdentificationPrincipal.class).size() == 1);
+ assertTrue("expected non-null server subject", subject != null);
+ assertTrue("server subject should have one remote principal", subject.getPrincipals(IdentificationPrincipal.class).size() == 1);
IdentificationPrincipal remote = (IdentificationPrincipal) subject.getPrincipals(IdentificationPrincipal.class).iterator().next();
- assertTrue("subject should be associated with remote id", ContextManager.getRegisteredSubject(remote.getId()) != null);
- assertTrue("subject should have five principals", subject.getPrincipals().size() == 5);
- assertTrue("subject should have two realm principal", subject.getPrincipals(RealmPrincipal.class).size() == 2);
+ assertTrue("server subject should be associated with remote id", ContextManager.getRegisteredSubject(remote.getId()) != null);
+ assertTrue("server subject should have five principals", subject.getPrincipals().size() == 5);
+ assertTrue("server subject should have two realm principal", subject.getPrincipals(RealmPrincipal.class).size() == 2);
RealmPrincipal principal = (RealmPrincipal) subject.getPrincipals(RealmPrincipal.class).iterator().next();
assertTrue("id of principal should be non-zero", principal.getId() != 0);
context.logout();
- assertTrue("id of subject should be null", ContextManager.getSubjectId(subject) == null);
+ assertTrue("id of server subject should be null", ContextManager.getSubjectId(subject) == null);
}
}
Modified: geronimo/trunk/modules/security/src/test/org/apache/geronimo/security/jaas/LoginSQLTest.java
==============================================================================
--- geronimo/trunk/modules/security/src/test/org/apache/geronimo/security/jaas/LoginSQLTest.java (original)
+++ geronimo/trunk/modules/security/src/test/org/apache/geronimo/security/jaas/LoginSQLTest.java Tue Nov 16 14:34:08 2004
@@ -112,7 +112,7 @@
public void testNothing() {
}
- public void XtestLogin() throws Exception {
+ public void testLogin() throws Exception {
LoginContext context = new LoginContext("sql", new UsernamePasswordCallback("alan", "starcraft"));
context.login();
@@ -128,7 +128,7 @@
context.logout();
}
- public void XtestLogoutTimeout() throws Exception {
+ public void testLogoutTimeout() throws Exception {
assertEquals(new Integer(State.RUNNING_INDEX), kernel.getAttribute(sqlRealm, "state"));
@@ -171,7 +171,7 @@
}
}
- public void XtestReloginTimeout() throws Exception {
+ public void testReloginTimeout() throws Exception {
LoginContext context = new LoginContext("sql", new UsernamePasswordCallback("alan", "starcraft"));
context.login();
Modified: geronimo/trunk/modules/security/src/test/org/apache/geronimo/security/jaas/LoginSimpleRealmTest.java
==============================================================================
--- geronimo/trunk/modules/security/src/test/org/apache/geronimo/security/jaas/LoginSimpleRealmTest.java (original)
+++ geronimo/trunk/modules/security/src/test/org/apache/geronimo/security/jaas/LoginSimpleRealmTest.java Tue Nov 16 14:34:08 2004
@@ -31,6 +31,7 @@
import java.security.Principal;
import java.util.Map;
import java.util.Properties;
+import java.util.Set;
import org.apache.geronimo.gbean.jmx.GBeanMBean;
import org.apache.geronimo.security.AbstractTest;
@@ -109,13 +110,18 @@
context.login();
Subject subject = context.getSubject();
+ assertTrue("expected non-null client subject", subject != null);
+ Set set = subject.getPrincipals(IdentificationPrincipal.class);
+ assertEquals("client subject should have one ID principal", set.size(), 1);
+ IdentificationPrincipal idp = (IdentificationPrincipal)set.iterator().next();
+ subject = ContextManager.getRegisteredSubject(idp.getId());
- assertTrue("expected non-null subject", subject != null);
- assertTrue("subject should have one remote principal", subject.getPrincipals(IdentificationPrincipal.class).size() == 1);
+ assertTrue("expected non-null server subject", subject != null);
+ assertTrue("server subject should have one remote principal", subject.getPrincipals(IdentificationPrincipal.class).size() == 1);
IdentificationPrincipal remote = (IdentificationPrincipal) subject.getPrincipals(IdentificationPrincipal.class).iterator().next();
- assertTrue("subject should be associated with remote id", ContextManager.getRegisteredSubject(remote.getId()) != null);
- assertTrue("subject should have five principals", subject.getPrincipals().size() == 5);
- assertTrue("subject should have two realm principal", subject.getPrincipals(RealmPrincipal.class).size() == 2);
+ assertTrue("server subject should be associated with remote id", ContextManager.getRegisteredSubject(remote.getId()) != null);
+ assertTrue("server subject should have five principals", subject.getPrincipals().size() == 5);
+ assertTrue("server subject should have two realm principal", subject.getPrincipals(RealmPrincipal.class).size() == 2);
RealmPrincipal principal = (RealmPrincipal) subject.getPrincipals(RealmPrincipal.class).iterator().next();
assertTrue("id of principal should be non-zero", principal.getId() != 0);
Added: geronimo/trunk/modules/security/src/test/org/apache/geronimo/security/jaas/TimeoutTest.java
==============================================================================
--- (empty file)
+++ geronimo/trunk/modules/security/src/test/org/apache/geronimo/security/jaas/TimeoutTest.java Tue Nov 16 14:34:08 2004
@@ -0,0 +1,191 @@
+/**
+ *
+ * Copyright 2003-2004 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.geronimo.security.jaas;
+
+import javax.management.ObjectName;
+import javax.security.auth.Subject;
+import javax.security.auth.login.LoginContext;
+import java.io.File;
+import java.util.Collections;
+import java.util.Properties;
+import java.util.Set;
+import java.net.URI;
+
+import org.apache.geronimo.gbean.jmx.GBeanMBean;
+import org.apache.geronimo.security.AbstractTest;
+import org.apache.geronimo.security.ContextManager;
+import org.apache.geronimo.security.IdentificationPrincipal;
+import org.apache.geronimo.security.RealmPrincipal;
+import org.apache.geronimo.security.bridge.TestRealm;
+import org.apache.geronimo.system.serverinfo.ServerInfo;
+import org.apache.geronimo.kernel.Kernel;
+
+
+/**
+ * @version $Rev: 46019 $ $Date: 2004-09-14 05:56:06 -0400 (Tue, 14 Sep 2004) $
+ */
+public class TimeoutTest extends AbstractTest {
+
+ protected ObjectName serverInfo;
+ protected ObjectName loginConfiguration;
+ protected ObjectName propertiesRealm;
+ protected ObjectName propertiesCE;
+
+ public void setUp() throws Exception {
+ kernel = new Kernel("test.kernel", "simple.geronimo.test");
+ kernel.boot();
+
+ GBeanMBean gbean;
+
+ // Create all the parts
+
+ gbean = new GBeanMBean("org.apache.geronimo.security.jaas.JaasLoginService");
+ loginService = new ObjectName("geronimo.security:type=JaasLoginService");
+ gbean.setReferencePatterns("Realms", Collections.singleton(new ObjectName("geronimo.security:type=SecurityRealm,*")));
+ gbean.setAttribute("expiredLoginScanIntervalMillis", new Integer(50));
+ gbean.setAttribute("maxLoginDurationMillis", new Integer(1000));
+ gbean.setAttribute("algorithm", "HmacSHA1");
+ gbean.setAttribute("password", "secret");
+ kernel.loadGBean(loginService, gbean);
+
+ gbean = new GBeanMBean("org.apache.geronimo.security.bridge.TestRealm");
+ testRealm = new ObjectName("geronimo.security:type=SecurityRealm,realm=testrealm");
+ gbean.setAttribute("realmName", TestRealm.REALM_NAME);
+ gbean.setAttribute("maxLoginModuleAge", new Long(1 * 1000));
+ gbean.setAttribute("debug", new Boolean(true));
+ kernel.loadGBean(testRealm, gbean);
+
+ gbean = new GBeanMBean("org.apache.geronimo.remoting.router.SubsystemRouter");
+ subsystemRouter = new ObjectName("geronimo.remoting:router=SubsystemRouter");
+ kernel.loadGBean(subsystemRouter, gbean);
+
+ gbean = new GBeanMBean("org.apache.geronimo.remoting.transport.TransportLoader");
+ gbean.setAttribute("bindURI", new URI("async://0.0.0.0:4242"));
+ gbean.setReferencePatterns("Router", Collections.singleton(subsystemRouter));
+ asyncTransport = new ObjectName("geronimo.remoting:transport=async");
+ kernel.loadGBean(asyncTransport, gbean);
+
+ gbean = new GBeanMBean("org.apache.geronimo.remoting.router.JMXRouter");
+ gbean.setReferencePatterns("SubsystemRouter", Collections.singleton(subsystemRouter));
+ jmxRouter = new ObjectName("geronimo.remoting:router=JMXRouter");
+ kernel.loadGBean(jmxRouter, gbean);
+
+ gbean = new GBeanMBean("org.apache.geronimo.security.remoting.jmx.JaasLoginServiceRemotingServer");
+ gbean.setReferencePatterns("Router", Collections.singleton(jmxRouter));
+ serverStub = new ObjectName("geronimo.remoting:target=JaasLoginServiceRemotingServer");
+ kernel.loadGBean(serverStub, gbean);
+
+ kernel.startGBean(loginService);
+ kernel.startGBean(testRealm);
+ kernel.startGBean(subsystemRouter);
+ kernel.startGBean(asyncTransport);
+ kernel.startGBean(jmxRouter);
+ kernel.startGBean(serverStub);
+
+ gbean = new GBeanMBean(ServerInfo.GBEAN_INFO);
+ serverInfo = new ObjectName("geronimo.system:role=ServerInfo");
+ gbean.setAttribute("baseDirectory", ".");
+ kernel.loadGBean(serverInfo, gbean);
+ kernel.startGBean(serverInfo);
+
+ gbean = new GBeanMBean("org.apache.geronimo.security.jaas.GeronimoLoginConfiguration");
+ loginConfiguration = new ObjectName("geronimo.security:type=LoginConfiguration");
+ kernel.loadGBean(loginConfiguration, gbean);
+
+ gbean = new GBeanMBean("org.apache.geronimo.security.realm.providers.PropertiesFileSecurityRealm");
+ propertiesRealm = new ObjectName("geronimo.security:type=SecurityRealm,realm=properties-realm");
+ gbean.setAttribute("realmName", "properties-realm");
+ gbean.setAttribute("maxLoginModuleAge", new Long(1 * 1000));
+ gbean.setAttribute("usersURI", (new File(new File("."), "src/test-data/data/users.properties")).toURI());
+ gbean.setAttribute("groupsURI", (new File(new File("."), "src/test-data/data/groups.properties")).toURI());
+ gbean.setReferencePatterns("ServerInfo", Collections.singleton(serverInfo));
+ kernel.loadGBean(propertiesRealm, gbean);
+
+ gbean = new GBeanMBean("org.apache.geronimo.security.jaas.ConfigurationEntryRealmLocal");
+ propertiesCE = new ObjectName("geronimo.security:type=ConfigurationEntry,jaasId=properties");
+ gbean.setAttribute("applicationConfigName", "properties");
+ gbean.setAttribute("realmName", "properties-realm");
+ gbean.setAttribute("controlFlag", LoginModuleControlFlag.REQUIRED);
+ gbean.setAttribute("options", new Properties());
+ kernel.loadGBean(propertiesCE, gbean);
+
+ kernel.startGBean(loginConfiguration);
+ kernel.startGBean(propertiesRealm);
+ kernel.startGBean(propertiesCE);
+ }
+
+ public void tearDown() throws Exception {
+ kernel.stopGBean(propertiesCE);
+ kernel.stopGBean(propertiesRealm);
+ kernel.stopGBean(loginConfiguration);
+ kernel.stopGBean(serverInfo);
+
+ kernel.unloadGBean(propertiesRealm);
+ kernel.unloadGBean(propertiesCE);
+ kernel.unloadGBean(loginConfiguration);
+ kernel.unloadGBean(serverInfo);
+
+ kernel.stopGBean(serverStub);
+ kernel.stopGBean(jmxRouter);
+ kernel.stopGBean(asyncTransport);
+ kernel.stopGBean(subsystemRouter);
+ kernel.stopGBean(testRealm);
+ kernel.stopGBean(loginService);
+
+ kernel.unloadGBean(loginService);
+ kernel.unloadGBean(testRealm);
+ kernel.unloadGBean(subsystemRouter);
+ kernel.unloadGBean(asyncTransport);
+ kernel.unloadGBean(jmxRouter);
+ kernel.unloadGBean(serverStub);
+
+ kernel.shutdown();
+ }
+
+ public void testTimeout() throws Exception {
+
+ LoginContext context = new LoginContext("properties", new AbstractTest.UsernamePasswordCallback("alan", "starcraft"));
+
+ context.login();
+ Subject subject = context.getSubject();
+ assertTrue("expected non-null client subject", subject != null);
+ Set set = subject.getPrincipals(IdentificationPrincipal.class);
+ assertEquals("client subject should have one ID principal", set.size(), 1);
+ IdentificationPrincipal idp = (IdentificationPrincipal) set.iterator().next();
+ subject = ContextManager.getRegisteredSubject(idp.getId());
+
+ assertTrue("expected non-null server subject", subject != null);
+ assertTrue("server subject should have one remote principal", subject.getPrincipals(IdentificationPrincipal.class).size() == 1);
+ IdentificationPrincipal remote = (IdentificationPrincipal) subject.getPrincipals(IdentificationPrincipal.class).iterator().next();
+ assertTrue("server subject should be associated with remote id", ContextManager.getRegisteredSubject(remote.getId()) != null);
+ assertTrue("server subject should have five principals", subject.getPrincipals().size() == 5);
+ assertTrue("server subject should have two realm principal", subject.getPrincipals(RealmPrincipal.class).size() == 2);
+ RealmPrincipal principal = (RealmPrincipal) subject.getPrincipals(RealmPrincipal.class).iterator().next();
+ assertTrue("id of principal should be non-zero", principal.getId() != 0);
+
+ assertTrue("id of server subject should be non-null", ContextManager.getSubjectId(subject) != null);
+
+ Thread.sleep(300); // wait for timeout to kick in
+
+ assertTrue("id of server subject should be non-null", ContextManager.getSubjectId(subject) != null);
+
+ Thread.sleep(1700); // wait for timeout to kick in
+
+ assertTrue("id of server subject should be null", ContextManager.getSubjectId(subject) == null);
+ }
+}
Modified: geronimo/trunk/modules/security/src/test/org/apache/geronimo/security/remoting/jmx/RemoteLoginTest.java
==============================================================================
--- geronimo/trunk/modules/security/src/test/org/apache/geronimo/security/remoting/jmx/RemoteLoginTest.java (original)
+++ geronimo/trunk/modules/security/src/test/org/apache/geronimo/security/remoting/jmx/RemoteLoginTest.java Tue Nov 16 14:34:08 2004
@@ -37,7 +37,7 @@
import org.apache.geronimo.remoting.transport.TransportLoader;
import org.apache.geronimo.security.IdentificationPrincipal;
import org.apache.geronimo.security.RealmPrincipal;
-import org.apache.geronimo.security.jaas.LoginServiceMBean;
+import org.apache.geronimo.security.jaas.JaasLoginServiceMBean;
import org.apache.geronimo.system.serverinfo.ServerInfo;
@@ -57,9 +57,9 @@
ObjectName jmxRouter;
ObjectName secureJmxRouter;
ObjectName serverStub;
- LoginServiceMBean asyncRemoteProxy;
- LoginServiceMBean saslRemoteProxy;
- LoginServiceMBean gssapiRemoteProxy;
+ JaasLoginServiceMBean asyncRemoteProxy;
+ JaasLoginServiceMBean saslRemoteProxy;
+ JaasLoginServiceMBean gssapiRemoteProxy;
public void testNothing() {
}
@@ -100,10 +100,10 @@
kernel.loadGBean(serverInfo, gbean);
kernel.startGBean(serverInfo);
- gbean = new GBeanMBean("org.apache.geronimo.security.jaas.LoginService");
- loginService = new ObjectName("geronimo.security:type=LoginService");
+ gbean = new GBeanMBean("org.apache.geronimo.security.jaas.JaasLoginService");
+ loginService = new ObjectName("geronimo.security:type=JaasLoginService");
gbean.setReferencePatterns("Realms", Collections.singleton(new ObjectName("geronimo.security:type=SecurityRealm,*")));
- gbean.setAttribute("reclaimPeriod", new Long(100));
+// gbean.setAttribute("reclaimPeriod", new Long(100));
gbean.setAttribute("algorithm", "HmacSHA1");
gbean.setAttribute("password", "secret");
kernel.loadGBean(loginService, gbean);
@@ -153,9 +153,9 @@
secureJmxRouter = new ObjectName("geronimo.remoting:router=JMXRouter,type=secure");
kernel.loadGBean(secureJmxRouter, gbean);
- gbean = new GBeanMBean("org.apache.geronimo.security.remoting.jmx.LoginServiceStub");
+ gbean = new GBeanMBean("org.apache.geronimo.security.remoting.jmx.JaasLoginServiceRemotingServer");
gbean.setReferencePatterns("Router", Collections.singleton(secureJmxRouter));
- serverStub = new ObjectName("geronimo.remoting:target=LoginServiceStub");
+ serverStub = new ObjectName("geronimo.remoting:target=JaasLoginServiceRemotingServer");
kernel.loadGBean(serverStub, gbean);
kernel.startGBean(loginService);
@@ -171,15 +171,15 @@
TransportLoader bean = (TransportLoader) MBeanProxyFactory.getProxy(TransportLoader.class, kernel.getMBeanServer(), asyncTransport);
URI connectURI = bean.getClientConnectURI();
- asyncRemoteProxy = RemoteLoginServiceFactory.create(connectURI.getHost(), connectURI.getPort());
+ asyncRemoteProxy = JaasLoginServiceRemotingClient.create(connectURI.getHost(), connectURI.getPort());
bean = (TransportLoader) MBeanProxyFactory.getProxy(TransportLoader.class, kernel.getMBeanServer(), saslTransport);
connectURI = bean.getClientConnectURI();
- saslRemoteProxy = RemoteLoginServiceFactory.create(connectURI.getHost(), connectURI.getPort());
+ saslRemoteProxy = JaasLoginServiceRemotingClient.create(connectURI.getHost(), connectURI.getPort());
bean = (TransportLoader) MBeanProxyFactory.getProxy(TransportLoader.class, kernel.getMBeanServer(), gssapiTransport);
connectURI = bean.getClientConnectURI();
- gssapiRemoteProxy = RemoteLoginServiceFactory.create(connectURI.getHost(), connectURI.getPort());
+ gssapiRemoteProxy = JaasLoginServiceRemotingClient.create(connectURI.getHost(), connectURI.getPort());
}
protected void tearDown() throws Exception {