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/08 09:05:32 UTC

svn commit: rev 56911 - in geronimo/trunk/modules: connector/src/java/org/apache/geronimo/connector/outbound/security security/src/java/org/apache/geronimo/security/jaas security/src/java/org/apache/geronimo/security/realm security/src/java/org/apache/geronimo/security/realm/providers security/src/test/org/apache/geronimo/security/bridge

Author: ammulder
Date: Mon Nov  8 00:05:31 2004
New Revision: 56911

Added:
   geronimo/trunk/modules/security/src/java/org/apache/geronimo/security/jaas/LoginModuleConfiguration.java
   geronimo/trunk/modules/security/src/java/org/apache/geronimo/security/jaas/LoginUtils.java
Modified:
   geronimo/trunk/modules/connector/src/java/org/apache/geronimo/connector/outbound/security/PasswordCredentialRealm.java
   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/LoginModuleControlFlag.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/SerializableACE.java
   geronimo/trunk/modules/security/src/java/org/apache/geronimo/security/realm/SecurityRealm.java
   geronimo/trunk/modules/security/src/java/org/apache/geronimo/security/realm/providers/AbstractSecurityRealm.java
   geronimo/trunk/modules/security/src/java/org/apache/geronimo/security/realm/providers/KerberosSecurityRealm.java
   geronimo/trunk/modules/security/src/java/org/apache/geronimo/security/realm/providers/PropertiesFileSecurityRealm.java
   geronimo/trunk/modules/security/src/java/org/apache/geronimo/security/realm/providers/SQLSecurityRealm.java
   geronimo/trunk/modules/security/src/java/org/apache/geronimo/security/realm/providers/SimpleSecurityRealm.java
   geronimo/trunk/modules/security/src/test/org/apache/geronimo/security/bridge/TestRealm.java
Log:
Initial steps toward support for multiple LoginModules per realms
  (GERONIMO-424)


Modified: geronimo/trunk/modules/connector/src/java/org/apache/geronimo/connector/outbound/security/PasswordCredentialRealm.java
==============================================================================
--- geronimo/trunk/modules/connector/src/java/org/apache/geronimo/connector/outbound/security/PasswordCredentialRealm.java	(original)
+++ geronimo/trunk/modules/connector/src/java/org/apache/geronimo/connector/outbound/security/PasswordCredentialRealm.java	Mon Nov  8 00:05:31 2004
@@ -68,7 +68,7 @@
     public void refresh() throws GeronimoSecurityException {
     }
 
-    public AppConfigurationEntry getAppConfigurationEntry() {
+    public AppConfigurationEntry[] getAppConfigurationEntries() {
         Map options = new HashMap();
 
         // TODO: This can be a bad thing, passing a reference to a realm to the login module
@@ -77,7 +77,7 @@
         AppConfigurationEntry appConfigurationEntry = new AppConfigurationEntry(PasswordCredentialLoginModule.class.getName(),
                 AppConfigurationEntry.LoginModuleControlFlag.REQUISITE,
                 options);
-        return appConfigurationEntry;
+        return new AppConfigurationEntry[]{appConfigurationEntry};
     }
 
     public boolean isLoginModuleLocal() {

Modified: geronimo/trunk/modules/security/src/java/org/apache/geronimo/security/jaas/LocalLoginModule.java
==============================================================================
--- geronimo/trunk/modules/security/src/java/org/apache/geronimo/security/jaas/LocalLoginModule.java	(original)
+++ geronimo/trunk/modules/security/src/java/org/apache/geronimo/security/jaas/LocalLoginModule.java	Mon Nov  8 00:05:31 2004
@@ -64,7 +64,7 @@
 
             loginService = (LoginServiceMBean) MBeanProxyFactory.getProxy(LoginServiceMBean.class, kernel.getMBeanServer(), LoginService.LOGIN_SERVICE);
 
-            this.loginModuleId = loginService.allocateLoginModule(realmName);
+            this.loginModuleId = loginService.allocateLoginModules(realmName);
         } catch (Exception e) {
             throw (GeronimoSecurityException) new GeronimoSecurityException("Initialize error: " + e.toString() + "\n").initCause(e);
         }
@@ -77,7 +77,7 @@
             return tryLogin();
         } catch (ExpiredLoginModuleException ele) {
             try {
-                loginModuleId = loginService.allocateLoginModule(realmName);
+                loginModuleId = loginService.allocateLoginModules(realmName);
                 return tryLogin();
             } catch (Exception e) {
                 throw (LoginException) new LoginException().initCause(e);
@@ -143,7 +143,7 @@
         Collection collection = loginService.getCallbacks(loginModuleId);
         Callback[] callbacks = new Callback[0];
 
-        callbacks = (Callback[]) collection.toArray(new Callback[]{});
+        callbacks = (Callback[]) collection.toArray(new Callback[collection.size()]);
 
         try {
             callbackHandler.handle(callbacks);

Modified: geronimo/trunk/modules/security/src/java/org/apache/geronimo/security/jaas/LoginModuleCacheObject.java
==============================================================================
--- geronimo/trunk/modules/security/src/java/org/apache/geronimo/security/jaas/LoginModuleCacheObject.java	(original)
+++ geronimo/trunk/modules/security/src/java/org/apache/geronimo/security/jaas/LoginModuleCacheObject.java	Mon Nov  8 00:05:31 2004
@@ -30,7 +30,7 @@
     private final LoginModuleId loginModuleId;
     private String realmName;
     private Subject subject;
-    private LoginModule loginModule;
+    private LoginModuleConfiguration[] loginModules;
     private CallbackHandler callbackHandler;
     private long created;
     private boolean done;
@@ -73,12 +73,12 @@
         this.subject = subject;
     }
 
-    LoginModule getLoginModule() {
-        return loginModule;
+    LoginModuleConfiguration[] getLoginModules() {
+        return loginModules;
     }
 
-    void setLoginModule(LoginModule loginModule) {
-        this.loginModule = loginModule;
+    void setLoginModules(LoginModuleConfiguration[] loginModules) {
+        this.loginModules = loginModules;
     }
 
     CallbackHandler getCallbackHandler() {

Added: geronimo/trunk/modules/security/src/java/org/apache/geronimo/security/jaas/LoginModuleConfiguration.java
==============================================================================
--- (empty file)
+++ geronimo/trunk/modules/security/src/java/org/apache/geronimo/security/jaas/LoginModuleConfiguration.java	Mon Nov  8 00:05:31 2004
@@ -0,0 +1,26 @@
+package org.apache.geronimo.security.jaas;
+
+import javax.security.auth.spi.LoginModule;
+
+/**
+ * 
+ * 
+ * @version $Revision 1.0 $
+ */
+public class LoginModuleConfiguration {
+    private LoginModule module;
+    private LoginModuleControlFlag controlFlag;
+
+    public LoginModuleConfiguration(LoginModule module, LoginModuleControlFlag controlFlag) {
+        this.module = module;
+        this.controlFlag = controlFlag;
+    }
+
+    public LoginModule getModule() {
+        return module;
+    }
+
+    public LoginModuleControlFlag getControlFlag() {
+        return controlFlag;
+    }
+}

Modified: geronimo/trunk/modules/security/src/java/org/apache/geronimo/security/jaas/LoginModuleControlFlag.java
==============================================================================
--- geronimo/trunk/modules/security/src/java/org/apache/geronimo/security/jaas/LoginModuleControlFlag.java	(original)
+++ geronimo/trunk/modules/security/src/java/org/apache/geronimo/security/jaas/LoginModuleControlFlag.java	Mon Nov  8 00:05:31 2004
@@ -51,4 +51,13 @@
     Object readResolve() throws ObjectStreamException {
         return values[ordinal];
     }
+
+    public static LoginModuleControlFlag getInstance(AppConfigurationEntry.LoginModuleControlFlag flag) {
+        for(int i = 0; i < values.length; i++) {
+            if(values[i].flag == flag) {
+                return values[i];
+            }
+        }
+        return null;
+    }
 }

Modified: geronimo/trunk/modules/security/src/java/org/apache/geronimo/security/jaas/LoginService.java
==============================================================================
--- geronimo/trunk/modules/security/src/java/org/apache/geronimo/security/jaas/LoginService.java	(original)
+++ geronimo/trunk/modules/security/src/java/org/apache/geronimo/security/jaas/LoginService.java	Mon Nov  8 00:05:31 2004
@@ -31,6 +31,8 @@
 import java.util.Iterator;
 import java.util.Map;
 import java.util.Set;
+import java.util.List;
+import java.util.Arrays;
 import javax.crypto.Mac;
 import javax.crypto.SecretKey;
 import javax.crypto.spec.SecretKeySpec;
@@ -144,39 +146,44 @@
         this.password = password;
     }
 
-    public SerializableACE getAppConfigurationEntry(String realmName) {
+    public SerializableACE[] getAppConfigurationEntries(String realmName) {
 
         for (Iterator iter = getRealms().iterator(); iter.hasNext();) {
             SecurityRealm securityRealm = (SecurityRealm) iter.next();
 
             if (realmName.equals(securityRealm.getRealmName())) {
-                javax.security.auth.login.AppConfigurationEntry entry = securityRealm.getAppConfigurationEntry();
-
-                HashMap options = new HashMap();
-
-                options.put(LoginModuleConstants.REALM_NAME, realmName);
-                options.put(LoginModuleConstants.MODULE, entry.getLoginModuleName());
-
-                SerializableACE wrapper;
-
-                if (securityRealm.isLoginModuleLocal()) {
-                    wrapper = new SerializableACE("org.apache.geronimo.security.jaas.RemoteLoginModuleLocalWrapper",
-                            SerializableACE.LoginModuleControlFlag.REQUIRED,
-                            options);
-
-                } else {
-                    options.putAll(entry.getOptions());
-                    wrapper = new SerializableACE("org.apache.geronimo.security.jaas.RemoteLoginModuleRemoteWrapper",
-                            SerializableACE.LoginModuleControlFlag.REQUIRED,
-                            options);
+                javax.security.auth.login.AppConfigurationEntry[] entries = securityRealm.getAppConfigurationEntries();
+                SerializableACE[] results = new SerializableACE[entries.length];
+                for(int i = 0; i < entries.length; i++) {
+                    AppConfigurationEntry entry = entries[i];
+
+                    HashMap options = new HashMap();
+
+                    options.put(LoginModuleConstants.REALM_NAME, realmName);
+                    options.put(LoginModuleConstants.MODULE, entry.getLoginModuleName());
+
+                    SerializableACE wrapper;
+
+                    if (securityRealm.isLoginModuleLocal()) {
+                        wrapper = new SerializableACE("org.apache.geronimo.security.jaas.RemoteLoginModuleLocalWrapper",
+                                LoginModuleControlFlag.REQUIRED,
+                                options);
+
+                    } else {
+                        options.putAll(entry.getOptions());
+                        wrapper = new SerializableACE("org.apache.geronimo.security.jaas.RemoteLoginModuleRemoteWrapper",
+                                LoginModuleControlFlag.REQUIRED,
+                                options);
+                    }
+                    results[i] = wrapper;
                 }
-                return wrapper;
+                return results;
             }
         }
         return null;
     }
 
-    public LoginModuleId allocateLoginModule(String realmName) {
+    public LoginModuleId allocateLoginModules(String realmName) {
         LoginModuleCacheObject lm = null;
 
         synchronized (LoginService.class) {
@@ -185,38 +192,43 @@
                     SecurityRealm securityRealm = (SecurityRealm) iter.next();
 
                     if (realmName.equals(securityRealm.getRealmName())) {
-                        AppConfigurationEntry entry = securityRealm.getAppConfigurationEntry();
-
-                        final String finalClass = entry.getLoginModuleName();
-
-                        LoginModule module = (LoginModule) AccessController.doPrivileged(new java.security.PrivilegedExceptionAction() {
-                            public Object run() throws ClassNotFoundException, InstantiationException, IllegalAccessException {
-                                return Class.forName(finalClass, true, classLoader).newInstance();
-                            }
-                        });
+                        AppConfigurationEntry[] entries = securityRealm.getAppConfigurationEntries();
                         Subject subject = new Subject();
                         CallbackProxy callback = new CallbackProxy();
-                        module.initialize(subject, callback, new HashMap(), entry.getOptions());
+                        LoginModuleConfiguration[] modules = new LoginModuleConfiguration[entries.length];
+                        for(int i = 0; i < entries.length; i++) {
+                            AppConfigurationEntry entry = entries[i];
+
+                            final String finalClass = entry.getLoginModuleName();
+
+                            LoginModule module = (LoginModule) AccessController.doPrivileged(new java.security.PrivilegedExceptionAction() {
+                                public Object run() throws ClassNotFoundException, InstantiationException, IllegalAccessException {
+                                    return Class.forName(finalClass, true, classLoader).newInstance();
+                                }
+                            });
+                            module.initialize(subject, callback, new HashMap(), entry.getOptions());
+                            modules[i] = new LoginModuleConfiguration(module, LoginModuleControlFlag.getInstance(entry.getControlFlag()));
 
+                        }
                         lm = allocateLoginModuleCacheObject(securityRealm.getMaxLoginModuleAge());
                         lm.setRealmName(realmName);
-                        lm.setLoginModule(module);
+                        lm.setLoginModules(modules);
                         lm.setSubject(subject);
                         lm.setCallbackHandler(callback);
-
                         log.trace("LoginModule [" + lm.getLoginModuleId() + "] created for realm " + realmName);
 
                         break;
                     }
                 }
             } catch (Exception e) {
+                e.printStackTrace();
                 return null;
             }
         }
         return lm.getLoginModuleId();
     }
 
-    public void removeLoginModule(LoginModuleId loginModuleId) throws ExpiredLoginModuleException {
+    public void removeLoginModules(LoginModuleId loginModuleId) throws ExpiredLoginModuleException {
         LoginModuleCacheObject lm = (LoginModuleCacheObject) loginCache.get(loginModuleId);
         if (lm == null) throw new ExpiredLoginModuleException();
 
@@ -224,26 +236,27 @@
         log.trace("LoginModule [" + lm.getLoginModuleId() + "] marked done");
     }
 
+    //todo: this is pretty cheesy
     public Collection getCallbacks(LoginModuleId loginModuleId) throws ExpiredLoginModuleException {
         LoginModuleCacheObject lm = (LoginModuleCacheObject) loginCache.get(loginModuleId);
         if (lm == null) throw new ExpiredLoginModuleException();
 
-        LoginModule module = lm.getLoginModule();
-        CallbackProxy callback = (CallbackProxy) lm.getCallbackHandler();
+        LoginModuleConfiguration[] modules = lm.getLoginModules();
 
-        try {
-            module.login();
-        } catch (LoginException e) {
-        }
-        try {
-            module.abort();
-        } catch (LoginException e) {
-        }
-        ArrayList callbacks = new ArrayList();
-        for (int i = 0; i < callback.callbacks.length; i++) {
-            callbacks.add(callback.callbacks[i]);
+        CallbackProxy proxy = (CallbackProxy) lm.getCallbackHandler();
+        proxy.setExploring();
+        for(int i = 0; i < modules.length; i++) {
+            LoginModuleConfiguration module = modules[i];
+            try {
+                module.getModule().login();
+            } catch (LoginException e) {
+            }
+            try {
+                module.getModule().abort();
+            } catch (LoginException e) {
+            }
         }
-        return callbacks;
+        return proxy.finalizeCallbackList();
     }
 
     /**
@@ -251,41 +264,55 @@
      * that a login module will use and to fill in the reply that a remote
      * client has provided.
      */
-    class CallbackProxy implements CallbackHandler {
-        Callback[] callbacks;
+    static class CallbackProxy implements CallbackHandler {
+        private List callbacks = new ArrayList();
+        private boolean exploring = true;
 
         public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {
-            if (this.callbacks == null) {
-                this.callbacks = callbacks;
+            if (exploring) {
+                this.callbacks.addAll(Arrays.asList(callbacks));
                 throw new UnsupportedCallbackException(callbacks[0], "DO NOT PROCEED WITH THIS LOGIN");
             } else {
-                assert this.callbacks.length == callbacks.length : "Callback lengths should not have changed";
+                assert this.callbacks.size() == callbacks.length : "Callback lengths should not have changed";
 
                 for (int i = 0; i < callbacks.length; i++) {
-                    callbacks[i] = this.callbacks[i];
+                    callbacks[i] = (Callback) this.callbacks.get(i);
                 }
             }
         }
+
+        public void setExploring() {
+            exploring = true;
+            callbacks.clear();
+        }
+
+        public List finalizeCallbackList() {
+            exploring = false;
+            return callbacks;
+        }
     }
 
     public boolean login(LoginModuleId loginModuleId, Collection callbacks) throws LoginException {
         LoginModuleCacheObject lm = (LoginModuleCacheObject) loginCache.get(loginModuleId);
         if (lm == null) throw new ExpiredLoginModuleException();
-
-        LoginModule module = lm.getLoginModule();
-
+        LoginModuleConfiguration[] modules = lm.getLoginModules();
+        if(modules.length == 0) {
+            throw new LoginException("No login modules configured for realm "+lm.getRealmName());
+        }
         CallbackProxy callback = (CallbackProxy) lm.getCallbackHandler();
-        callback.callbacks = (Callback[]) callbacks.toArray(new Callback[]{});
-
-        return module.login();
+        callback.callbacks = new ArrayList(callbacks);
+        return LoginUtils.computeLogin(modules);
     }
 
     public boolean commit(LoginModuleId loginModuleId) throws LoginException {
         LoginModuleCacheObject lm = (LoginModuleCacheObject) loginCache.get(loginModuleId);
         if (lm == null) throw new ExpiredLoginModuleException();
 
-        LoginModule module = lm.getLoginModule();
-        if (!module.commit()) return false;
+        LoginModuleConfiguration[] modules = lm.getLoginModules();
+        for(int i = 0; i < modules.length; i++) {
+            LoginModuleConfiguration configuration = modules[i];
+            configuration.getModule().commit();
+        }
 
         Subject subject = lm.getSubject();
         RealmPrincipal principal;
@@ -310,9 +337,13 @@
         LoginModuleCacheObject lm = (LoginModuleCacheObject) loginCache.get(loginModuleId);
         if (lm == null) throw new ExpiredLoginModuleException();
 
-        LoginModule module = lm.getLoginModule();
+        LoginModuleConfiguration[] modules = lm.getLoginModules();
+        for(int i = 0; i < modules.length; i++) {
+            LoginModuleConfiguration configuration = modules[i];
+            configuration.getModule().abort();
+        }
 
-        return module.abort();
+        return true;
     }
 
     public boolean logout(LoginModuleId loginModuleId) throws LoginException {
@@ -320,10 +351,13 @@
         if (lm == null) throw new ExpiredLoginModuleException();
 
         lm.getSubject().getPrincipals(RealmPrincipal.class).clear();
-
-        LoginModule module = lm.getLoginModule();
-
-        return module.logout();
+        lm.getSubject().getPrincipals(IdentificationPrincipal.class).clear();
+        LoginModuleConfiguration[] modules = lm.getLoginModules();
+        for(int i = 0; i < modules.length; i++) {
+            LoginModuleConfiguration configuration = modules[i];
+            configuration.getModule().logout();
+        }
+        return true;
     }
 
     public Subject retrieveSubject(LoginModuleId loginModuleId) throws LoginException {
@@ -439,8 +473,8 @@
     static {
         GBeanInfoBuilder infoFactory = new GBeanInfoBuilder(LoginService.class);
 
-        infoFactory.addOperation("getAppConfigurationEntry", new Class[]{String.class});
-        infoFactory.addOperation("allocateLoginModule", new Class[]{String.class});
+        infoFactory.addOperation("getAppConfigurationEntries", new Class[]{String.class});
+        infoFactory.addOperation("allocateLoginModules", new Class[]{String.class});
         infoFactory.addOperation("getCallbacks", new Class[]{LoginModuleId.class});
         infoFactory.addOperation("login", new Class[]{LoginModuleId.class, Collection.class});
         infoFactory.addOperation("commit", new Class[]{LoginModuleId.class});

Modified: geronimo/trunk/modules/security/src/java/org/apache/geronimo/security/jaas/LoginServiceMBean.java
==============================================================================
--- geronimo/trunk/modules/security/src/java/org/apache/geronimo/security/jaas/LoginServiceMBean.java	(original)
+++ geronimo/trunk/modules/security/src/java/org/apache/geronimo/security/jaas/LoginServiceMBean.java	Mon Nov  8 00:05:31 2004
@@ -29,6 +29,10 @@
 /**
  * An MBean that maintains a list of security realms.
  *
+ * A LoginModuleId represents the configuration of a single security realm,
+ * which may in fact include multiple login modules under the covers, but
+ * that is not really important here.
+ *
  * @version $Rev$ $Date$
  */
 public interface LoginServiceMBean {
@@ -37,11 +41,11 @@
 
     void setRealms(Collection realms);
 
-    SerializableACE getAppConfigurationEntry(String realmName);
+    SerializableACE[] getAppConfigurationEntries(String realmName);
 
-    LoginModuleId allocateLoginModule(String realmName) throws LoginException;
+    LoginModuleId allocateLoginModules(String realmName) throws LoginException;
 
-    void removeLoginModule(LoginModuleId loginModuleId) throws ExpiredLoginModuleException;
+    void removeLoginModules(LoginModuleId loginModuleId) throws ExpiredLoginModuleException;
 
     Collection getCallbacks(LoginModuleId loginModuleId) throws ExpiredLoginModuleException;
 

Added: geronimo/trunk/modules/security/src/java/org/apache/geronimo/security/jaas/LoginUtils.java
==============================================================================
--- (empty file)
+++ geronimo/trunk/modules/security/src/java/org/apache/geronimo/security/jaas/LoginUtils.java	Mon Nov  8 00:05:31 2004
@@ -0,0 +1,49 @@
+package org.apache.geronimo.security.jaas;
+
+import javax.security.auth.login.LoginException;
+
+/**
+ * 
+ * 
+ * @version $Revision 1.0 $
+ */
+public class LoginUtils {
+    public static boolean computeLogin(LoginModuleConfiguration[] modules) throws LoginException {
+        Boolean success = null;
+        Boolean backup = null;
+        // see http://java.sun.com/j2se/1.4.2/docs/api/javax/security/auth/login/Configuration.html
+        for(int i = 0; i < modules.length; i++) {
+            LoginModuleConfiguration module = modules[i];
+            boolean result = module.getModule().login();
+            if(module.getControlFlag() == LoginModuleControlFlag.REQUIRED) {
+                if(success == null || success.booleanValue()) {
+                    success = result ? Boolean.TRUE : Boolean.FALSE;
+                }
+            } else if(module.getControlFlag() == LoginModuleControlFlag.REQUISITE) {
+                if(!result) {
+                    return false;
+                } else if(success == null) {
+                   success = Boolean.TRUE;
+                }
+            } else if(module.getControlFlag() == LoginModuleControlFlag.SUFFICIENT) {
+                if(result && (success == null || success.booleanValue())) {
+                    return true;
+                }
+            } else if(module.getControlFlag() == LoginModuleControlFlag.OPTIONAL) {
+                if(backup == null || backup.booleanValue()) {
+                    backup = result ? Boolean.TRUE : Boolean.FALSE;
+                }
+            }
+        }
+        // all required and requisite modules succeeded, or at least one required module failed
+        if(success != null) {
+            return success.booleanValue();
+        }
+        // no required or requisite modules, no sufficient modules succeeded, fall back to optional modules
+        if(backup != null) {
+            return backup.booleanValue();
+        }
+        // perhaps only a sufficient module, and it failed
+        return false;
+    }
+}

Modified: geronimo/trunk/modules/security/src/java/org/apache/geronimo/security/jaas/RemoteLoginModule.java
==============================================================================
--- geronimo/trunk/modules/security/src/java/org/apache/geronimo/security/jaas/RemoteLoginModule.java	(original)
+++ geronimo/trunk/modules/security/src/java/org/apache/geronimo/security/jaas/RemoteLoginModule.java	Mon Nov  8 00:05:31 2004
@@ -45,7 +45,7 @@
     private boolean debug;
     private URI connectURI;
     private LoginServiceMBean remoteLoginService;
-    private LoginModule wrapper;
+    private LoginModuleConfiguration[] modules;
     private static ClassLoader classLoader;
 
     static {
@@ -68,19 +68,25 @@
             connectURI = new URI(uri);
             remoteLoginService = RemoteLoginServiceFactory.create(connectURI.getHost(), connectURI.getPort());
 
-            SerializableACE entry = remoteLoginService.getAppConfigurationEntry(realm);
+            SerializableACE[] entries = remoteLoginService.getAppConfigurationEntries(realm);
+            modules = new LoginModuleConfiguration[entries.length];
+            for(int i = 0; i < entries.length; i++) {
+                SerializableACE entry = entries[i];
+
+                final String finalClass = entry.getLoginModuleName();
+                LoginModule wrapper;
+                wrapper = (LoginModule) AccessController.doPrivileged(new PrivilegedExceptionAction() {
+                    public Object run() throws ClassNotFoundException, InstantiationException, IllegalAccessException {
+                        return Class.forName(finalClass, true, classLoader).newInstance();
+                    }
+                });
 
-            final String finalClass = entry.getLoginModuleName();
-            wrapper = (LoginModule) AccessController.doPrivileged(new PrivilegedExceptionAction() {
-                public Object run() throws ClassNotFoundException, InstantiationException, IllegalAccessException {
-                    return Class.forName(finalClass, true, classLoader).newInstance();
-                }
-            });
+                HashMap map = new HashMap(entry.getOptions());
+                map.put(LOGIN_SERVICE, remoteLoginService);
 
-            HashMap map = new HashMap(entry.getOptions());
-            map.put(LOGIN_SERVICE, remoteLoginService);
-
-            wrapper.initialize(subject, callbackHandler, sharedState, map);
+                wrapper.initialize(subject, callbackHandler, sharedState, map);
+                modules[i] = new LoginModuleConfiguration(wrapper, entry.getControlFlag());
+            }
 
             if (debug) {
                 System.out.print("[GeronimoLoginModule] Debug is  " + debug + " uri " + uri + " realm " + realm + "\n");
@@ -98,22 +104,34 @@
     }
 
     public boolean login() throws LoginException {
-        if (wrapper == null) throw new LoginException("RemoteLoginModule not properly initialzied");
-        return wrapper.login();
+        if (modules == null || modules.length == 0) throw new LoginException("RemoteLoginModule not properly initialzied");
+        return LoginUtils.computeLogin(modules);
     }
 
     public boolean commit() throws LoginException {
-        if (wrapper == null) throw new LoginException("RemoteLoginModule not properly initialzied");
-        return wrapper.commit();
+        if (modules == null || modules.length == 0) throw new LoginException("RemoteLoginModule not properly initialzied");
+        for(int i = 0; i < modules.length; i++) {
+            LoginModuleConfiguration configuration = modules[i];
+            configuration.getModule().commit();
+        }
+        return true;
     }
 
     public boolean abort() throws LoginException {
-        if (wrapper == null) throw new LoginException("RemoteLoginModule not properly initialzied");
-        return wrapper.abort();
+        if (modules == null || modules.length == 0) throw new LoginException("RemoteLoginModule not properly initialzied");
+        for(int i = 0; i < modules.length; i++) {
+            LoginModuleConfiguration configuration = modules[i];
+            configuration.getModule().abort();
+        }
+        return true;
     }
 
     public boolean logout() throws LoginException {
-        if (wrapper == null) throw new LoginException("RemoteLoginModule not properly initialzied");
-        return wrapper.logout();
+        if (modules == null || modules.length == 0) throw new LoginException("RemoteLoginModule not properly initialzied");
+        for(int i = 0; i < modules.length; i++) {
+            LoginModuleConfiguration configuration = modules[i];
+            configuration.getModule().logout();
+        }
+        return true;
     }
 }

Modified: geronimo/trunk/modules/security/src/java/org/apache/geronimo/security/jaas/RemoteLoginModuleLocalWrapper.java
==============================================================================
--- geronimo/trunk/modules/security/src/java/org/apache/geronimo/security/jaas/RemoteLoginModuleLocalWrapper.java	(original)
+++ geronimo/trunk/modules/security/src/java/org/apache/geronimo/security/jaas/RemoteLoginModuleLocalWrapper.java	Mon Nov  8 00:05:31 2004
@@ -55,7 +55,7 @@
         this.realmName = (String) options.get(LoginModuleConstants.REALM_NAME);
         this.remoteLoginService = (LoginServiceMBean) options.get(RemoteLoginModule.LOGIN_SERVICE);
         try {
-            this.loginModuleId = remoteLoginService.allocateLoginModule(realmName);
+            this.loginModuleId = remoteLoginService.allocateLoginModules(realmName);
         } catch (LoginException e) {
         }
     }
@@ -81,7 +81,7 @@
             return tryLogin();
         } catch (ExpiredLoginModuleException ele) {
             try {
-                loginModuleId = remoteLoginService.allocateLoginModule(realmName);
+                loginModuleId = remoteLoginService.allocateLoginModules(realmName);
                 return tryLogin();
             } catch (Exception e) {
                 throw (LoginException) new LoginException().initCause(e);
@@ -157,7 +157,7 @@
      */
     protected void finalize() throws Throwable {
         if (loginModuleId != null) {
-            remoteLoginService.removeLoginModule(loginModuleId);
+            remoteLoginService.removeLoginModules(loginModuleId);
         }
     }
 }

Modified: geronimo/trunk/modules/security/src/java/org/apache/geronimo/security/jaas/SerializableACE.java
==============================================================================
--- geronimo/trunk/modules/security/src/java/org/apache/geronimo/security/jaas/SerializableACE.java	(original)
+++ geronimo/trunk/modules/security/src/java/org/apache/geronimo/security/jaas/SerializableACE.java	Mon Nov  8 00:05:31 2004
@@ -48,7 +48,7 @@
     Map getOptions() {
         return options;
     }
-
+/*
     public static final class LoginModuleControlFlag implements Serializable {
 
         // Be careful here.  If you change the ordinals, this class must be changed on evey client.
@@ -78,4 +78,5 @@
             return values[ordinal];
         }
     }
+*/
 }

Modified: geronimo/trunk/modules/security/src/java/org/apache/geronimo/security/realm/SecurityRealm.java
==============================================================================
--- geronimo/trunk/modules/security/src/java/org/apache/geronimo/security/realm/SecurityRealm.java	(original)
+++ geronimo/trunk/modules/security/src/java/org/apache/geronimo/security/realm/SecurityRealm.java	Mon Nov  8 00:05:31 2004
@@ -34,19 +34,41 @@
 
     public String getRealmName();
 
+    public long getMaxLoginModuleAge();
+
+    public AppConfigurationEntry[] getAppConfigurationEntries();
+
+    public boolean isLoginModuleLocal();
+
+    /**
+     * @deprecated Will be removed in favor of (some kind of realm editor object) in
+     *             a future milestone release.
+     */
     public Set getGroupPrincipals() throws GeronimoSecurityException;
 
+    /**
+     * @deprecated Will be removed in favor of (some kind of realm editor object) in
+     *             a future milestone release.
+     */
     public Set getGroupPrincipals(RE regexExpression) throws GeronimoSecurityException;
 
+    /**
+     * @deprecated Will be removed in favor of (some kind of realm editor object) in
+     *             a future milestone release.
+     */
     public Set getUserPrincipals() throws GeronimoSecurityException;
 
+    /**
+     * @deprecated Will be removed in favor of (some kind of realm editor object) in
+     *             a future milestone release.
+     */
     public Set getUserPrincipals(RE regexExpression) throws GeronimoSecurityException;
 
+    /**
+     * @deprecated Will be removed a future milestone release.  The refreshing should
+     *             be done by a login module or editor when appropriate to its own
+     *             needs.
+     */
     public void refresh() throws GeronimoSecurityException;
 
-    public AppConfigurationEntry getAppConfigurationEntry();
-
-    public boolean isLoginModuleLocal();
-
-    public long getMaxLoginModuleAge();
 }

Modified: geronimo/trunk/modules/security/src/java/org/apache/geronimo/security/realm/providers/AbstractSecurityRealm.java
==============================================================================
--- geronimo/trunk/modules/security/src/java/org/apache/geronimo/security/realm/providers/AbstractSecurityRealm.java	(original)
+++ geronimo/trunk/modules/security/src/java/org/apache/geronimo/security/realm/providers/AbstractSecurityRealm.java	Mon Nov  8 00:05:31 2004
@@ -80,7 +80,7 @@
         infoFactory.addOperation("getUserPrincipals");
         infoFactory.addOperation("getUserPrincipals", new Class[]{RE.class});
         infoFactory.addOperation("refresh");
-        infoFactory.addOperation("getAppConfigurationEntry");
+        infoFactory.addOperation("getAppConfigurationEntries");
 
         infoFactory.setConstructor(new String[]{"realmName"});
 

Modified: geronimo/trunk/modules/security/src/java/org/apache/geronimo/security/realm/providers/KerberosSecurityRealm.java
==============================================================================
--- geronimo/trunk/modules/security/src/java/org/apache/geronimo/security/realm/providers/KerberosSecurityRealm.java	(original)
+++ geronimo/trunk/modules/security/src/java/org/apache/geronimo/security/realm/providers/KerberosSecurityRealm.java	Mon Nov  8 00:05:31 2004
@@ -207,7 +207,7 @@
         log.info("Kerberos Realm - " + getRealmName() + " - refresh");
     }
 
-    public javax.security.auth.login.AppConfigurationEntry getAppConfigurationEntry() {
+    public javax.security.auth.login.AppConfigurationEntry[] getAppConfigurationEntries() {
         HashMap options = new HashMap();
 
         options.put("debug", (debug ? "true" : "false"));
@@ -228,7 +228,7 @@
                                                                 AppConfigurationEntry.LoginModuleControlFlag.SUFFICIENT,
                                                                 options);
 
-        return entry;
+        return new AppConfigurationEntry[]{entry};
     }
 
     public boolean isLoginModuleLocal() {

Modified: geronimo/trunk/modules/security/src/java/org/apache/geronimo/security/realm/providers/PropertiesFileSecurityRealm.java
==============================================================================
--- geronimo/trunk/modules/security/src/java/org/apache/geronimo/security/realm/providers/PropertiesFileSecurityRealm.java	(original)
+++ geronimo/trunk/modules/security/src/java/org/apache/geronimo/security/realm/providers/PropertiesFileSecurityRealm.java	Mon Nov  8 00:05:31 2004
@@ -179,7 +179,7 @@
         }
     }
 
-    public AppConfigurationEntry getAppConfigurationEntry() {
+    public AppConfigurationEntry[] getAppConfigurationEntries() {
         HashMap options = new HashMap();
 
         options.put(REALM_INSTANCE, this);
@@ -187,7 +187,7 @@
                 AppConfigurationEntry.LoginModuleControlFlag.SUFFICIENT,
                 options);
 
-        return entry;
+        return new AppConfigurationEntry[]{entry};
     }
 
     public boolean isLoginModuleLocal() {

Modified: geronimo/trunk/modules/security/src/java/org/apache/geronimo/security/realm/providers/SQLSecurityRealm.java
==============================================================================
--- geronimo/trunk/modules/security/src/java/org/apache/geronimo/security/realm/providers/SQLSecurityRealm.java	(original)
+++ geronimo/trunk/modules/security/src/java/org/apache/geronimo/security/realm/providers/SQLSecurityRealm.java	Mon Nov  8 00:05:31 2004
@@ -267,7 +267,7 @@
         return password;
     }
 
-    public AppConfigurationEntry getAppConfigurationEntry() {
+    public AppConfigurationEntry[] getAppConfigurationEntries() {
         HashMap options = new HashMap();
 
         options.put(USER_SELECT, userSelect);
@@ -280,7 +280,7 @@
                 AppConfigurationEntry.LoginModuleControlFlag.SUFFICIENT,
                 options);
 
-        return entry;
+        return new AppConfigurationEntry[]{entry};
     }
 
     public boolean isLoginModuleLocal() {

Modified: geronimo/trunk/modules/security/src/java/org/apache/geronimo/security/realm/providers/SimpleSecurityRealm.java
==============================================================================
--- geronimo/trunk/modules/security/src/java/org/apache/geronimo/security/realm/providers/SimpleSecurityRealm.java	(original)
+++ geronimo/trunk/modules/security/src/java/org/apache/geronimo/security/realm/providers/SimpleSecurityRealm.java	Mon Nov  8 00:05:31 2004
@@ -112,13 +112,13 @@
         log.info("Simple Realm - " + getRealmName() + " - refresh");
     }
 
-    public javax.security.auth.login.AppConfigurationEntry getAppConfigurationEntry() {
+    public javax.security.auth.login.AppConfigurationEntry[] getAppConfigurationEntries() {
 
         AppConfigurationEntry entry = new AppConfigurationEntry(loginModuleName,
                                                                 AppConfigurationEntry.LoginModuleControlFlag.SUFFICIENT,
                                                                 options);
 
-        return entry;
+        return new AppConfigurationEntry[]{entry};
     }
 
     public boolean isLoginModuleLocal() {

Modified: geronimo/trunk/modules/security/src/test/org/apache/geronimo/security/bridge/TestRealm.java
==============================================================================
--- geronimo/trunk/modules/security/src/test/org/apache/geronimo/security/bridge/TestRealm.java	(original)
+++ geronimo/trunk/modules/security/src/test/org/apache/geronimo/security/bridge/TestRealm.java	Mon Nov  8 00:05:31 2004
@@ -61,10 +61,10 @@
     public void refresh() throws GeronimoSecurityException {
     }
 
-    public AppConfigurationEntry getAppConfigurationEntry() {
-        return new AppConfigurationEntry(TestLoginModule.class.getName(),
+    public AppConfigurationEntry[] getAppConfigurationEntries() {
+        return new AppConfigurationEntry[]{new AppConfigurationEntry(TestLoginModule.class.getName(),
                 AppConfigurationEntry.LoginModuleControlFlag.REQUISITE,
-                new HashMap());
+                new HashMap())};
     }
 
     public boolean isLoginModuleLocal() {