geronimo-scm mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From vamsic...@apache.org
Subject svn commit: r590862 - in /geronimo/server: branches/2.0/modules/geronimo-security/src/main/java/org/apache/geronimo/security/realm/providers/ branches/2.0/modules/geronimo-security/src/test/java/org/apache/geronimo/security/jaas/ trunk/framework/module...
Date Wed, 31 Oct 2007 23:56:41 GMT
Author: vamsic007
Date: Wed Oct 31 16:56:41 2007
New Revision: 590862

URL: http://svn.apache.org/viewvc?rev=590862&view=rev
Log:
**GERONIMO-3575 Review CertificatePropertiesFileLoginModule
 o LoginModule should not add principals when login fails.  Added a test to detect if it does.
 o Other changes to bring CertificatePropertiesFileLoginModule in line with http://java.sun.com/j2se/1.5.0/docs/guide/security/jaas/JAASLMDevGuide.html
**: This fix can use a thorough review.

Added:
    geronimo/server/branches/2.0/modules/geronimo-security/src/test/java/org/apache/geronimo/security/jaas/LoginCertificatePropertiesFileAdvancedTest.java
  (with props)
    geronimo/server/trunk/framework/modules/geronimo-security/src/test/java/org/apache/geronimo/security/jaas/LoginCertificatePropertiesFileAdvancedTest.java
  (with props)
    geronimo/server/trunk/modules/geronimo-security/src/test/java/org/apache/geronimo/security/jaas/LoginCertificatePropertiesFileAdvancedTest.java
  (with props)
Modified:
    geronimo/server/branches/2.0/modules/geronimo-security/src/main/java/org/apache/geronimo/security/realm/providers/CertificatePropertiesFileLoginModule.java
    geronimo/server/trunk/framework/modules/geronimo-security/src/main/java/org/apache/geronimo/security/realm/providers/CertificatePropertiesFileLoginModule.java
    geronimo/server/trunk/modules/geronimo-security/src/main/java/org/apache/geronimo/security/realm/providers/CertificatePropertiesFileLoginModule.java

Modified: geronimo/server/branches/2.0/modules/geronimo-security/src/main/java/org/apache/geronimo/security/realm/providers/CertificatePropertiesFileLoginModule.java
URL: http://svn.apache.org/viewvc/geronimo/server/branches/2.0/modules/geronimo-security/src/main/java/org/apache/geronimo/security/realm/providers/CertificatePropertiesFileLoginModule.java?rev=590862&r1=590861&r2=590862&view=diff
==============================================================================
--- geronimo/server/branches/2.0/modules/geronimo-security/src/main/java/org/apache/geronimo/security/realm/providers/CertificatePropertiesFileLoginModule.java
(original)
+++ geronimo/server/branches/2.0/modules/geronimo-security/src/main/java/org/apache/geronimo/security/realm/providers/CertificatePropertiesFileLoginModule.java
Wed Oct 31 16:56:41 2007
@@ -20,11 +20,15 @@
 import java.io.IOException;
 import java.io.InputStream;
 import java.net.URI;
+import java.security.Principal;
 import java.security.cert.X509Certificate;
+import java.util.Arrays;
+import java.util.Collections;
 import java.util.Enumeration;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Iterator;
+import java.util.List;
 import java.util.Map;
 import java.util.Properties;
 import java.util.Set;
@@ -67,17 +71,25 @@
     private static Log log = LogFactory.getLog(CertificatePropertiesFileLoginModule.class);
     public final static String USERS_URI = "usersURI";
     public final static String GROUPS_URI = "groupsURI";
-
+    public final static List<String> supportedOptions = Arrays.asList(USERS_URI, GROUPS_URI);
+            
     private final Map users = new HashMap();
     final Map groups = new HashMap();
 
     private Subject subject;
     private CallbackHandler handler;
     private X500Principal principal;
+    private boolean loginSucceeded;
+    private final Set<Principal> allPrincipals = new HashSet<Principal>();
 
     public void initialize(Subject subject, CallbackHandler callbackHandler, Map sharedState,
Map options) {
         this.subject = subject;
         this.handler = callbackHandler;
+        for(Object option: options.keySet()) {
+            if(!supportedOptions.contains(option)) {
+                log.warn("Ignoring option: "+option+". Not supported.");
+            }
+        }
         try {
             ServerInfo serverInfo = (ServerInfo) options.get(JaasLoginModuleUse.SERVERINFO_LM_OPTION);
             URI usersURI = new URI((String)options.get(USERS_URI));
@@ -132,7 +144,13 @@
     }
 
 
+    /**
+     * This LoginModule is not to be ignored.  So, this method should never return false.
+     * @return true if authentication succeeds, or throw a LoginException such as FailedLoginException
+     *         if authentication fails
+     */
     public boolean login() throws LoginException {
+        loginSucceeded = false;
         Callback[] callbacks = new Callback[1];
 
         callbacks[0] = new CertificateCallback();
@@ -151,44 +169,65 @@
         principal = certificate.getSubjectX500Principal();
 
         if(!users.containsKey(principal.getName())) {
+            // Clear out the private state
+            principal = null;
             throw new FailedLoginException();
         }
+
+        loginSucceeded = true;
         return true;
     }
 
+    /*
+     * @exception LoginException if login succeeded but commit failed.
+     *
+     * @return true if login succeeded and commit succeeded, or false if login failed but
commit succeeded.
+     */
     public boolean commit() throws LoginException {
-        Set principals = subject.getPrincipals();
-
-        principals.add(principal);
-        String userName = (String) users.get(principal.getName());
-        principals.add(new GeronimoUserPrincipal(userName));
-
-        Iterator e = groups.keySet().iterator();
-        while (e.hasNext()) {
-            String groupName = (String) e.next();
-            Set users = (Set) groups.get(groupName);
-            Iterator iter = users.iterator();
-            while (iter.hasNext()) {
-                String user = (String) iter.next();
-                if (userName.equals(user)) {
-                    principals.add(new GeronimoGroupPrincipal(groupName));
-                    break;
+        if(loginSucceeded) {
+            allPrincipals.add(principal);
+            String userName = (String) users.get(principal.getName());
+            allPrincipals.add(new GeronimoUserPrincipal(userName));
+
+            Iterator e = groups.keySet().iterator();
+            while (e.hasNext()) {
+                String groupName = (String) e.next();
+                Set users = (Set) groups.get(groupName);
+                Iterator iter = users.iterator();
+                while (iter.hasNext()) {
+                    String user = (String) iter.next();
+                    if (userName.equals(user)) {
+                        allPrincipals.add(new GeronimoGroupPrincipal(groupName));
+                        break;
+                    }
                 }
             }
+            subject.getPrincipals().addAll(allPrincipals);
         }
-
-        return true;
+        // Clear out the private state
+        principal = null;
+        
+        return loginSucceeded;
     }
 
     public boolean abort() throws LoginException {
-        principal = null;
-
-        return true;
+        if(loginSucceeded) {
+            // Clear out the private state
+            principal = null;
+            allPrincipals.retainAll(Collections.EMPTY_SET);
+        }
+        return loginSucceeded;
     }
 
     public boolean logout() throws LoginException {
+        // Clear out the private state
+        loginSucceeded = false;
         principal = null;
-        //todo: should remove principals added by commit
+        if(!subject.isReadOnly()) {
+            // Remove principals added by this LoginModule
+            subject.getPrincipals().removeAll(allPrincipals);
+        }
+        allPrincipals.retainAll(Collections.EMPTY_SET);
         return true;
     }
 

Added: geronimo/server/branches/2.0/modules/geronimo-security/src/test/java/org/apache/geronimo/security/jaas/LoginCertificatePropertiesFileAdvancedTest.java
URL: http://svn.apache.org/viewvc/geronimo/server/branches/2.0/modules/geronimo-security/src/test/java/org/apache/geronimo/security/jaas/LoginCertificatePropertiesFileAdvancedTest.java?rev=590862&view=auto
==============================================================================
--- geronimo/server/branches/2.0/modules/geronimo-security/src/test/java/org/apache/geronimo/security/jaas/LoginCertificatePropertiesFileAdvancedTest.java
(added)
+++ geronimo/server/branches/2.0/modules/geronimo-security/src/test/java/org/apache/geronimo/security/jaas/LoginCertificatePropertiesFileAdvancedTest.java
Wed Oct 31 16:56:41 2007
@@ -0,0 +1,142 @@
+/**
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You 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.ByteArrayInputStream;
+import java.io.File;
+import java.security.cert.CertificateFactory;
+import java.security.cert.X509Certificate;
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.security.auth.Subject;
+import javax.security.auth.login.LoginContext;
+
+import org.apache.geronimo.gbean.AbstractName;
+import org.apache.geronimo.gbean.GBeanData;
+import org.apache.geronimo.security.AbstractTest;
+import org.apache.geronimo.security.realm.GenericSecurityRealm;
+
+
+/**
+ * This test makes sure that CertificatePropertiesFileLoginModule does not add any principals
when login failed.
+ * 
+ * @version $Rev$ $Date$
+ */
+public class LoginCertificatePropertiesFileAdvancedTest extends AbstractTest {
+    protected AbstractName clientCE;
+    protected AbstractName testCE;
+    protected AbstractName testRealm;
+    protected AbstractName neverFailModule;
+
+    protected X509Certificate badCert;
+    String badCertText = "-----BEGIN CERTIFICATE-----\n"
+                        +"MIIBqTCCAVMCBgEV+C5ZTjANBgkqhkiG9w0BAQQFADBdMQwwCgYDVQQDEwNCYWQxEDAOBgNVBAsT\n"
+                        +"B015IFVuaXQxDzANBgNVBAoTBk15IE9yZzEQMA4GA1UEBxMHTXkgQ2l0eTELMAkGA1UECBMCQVAx\n"
+                        +"CzAJBgNVBAYTAklOMB4XDTA3MTAzMTIyMjg0OFoXDTE3MTAyODIyMjg0OFowXTEMMAoGA1UEAxMD\n"
+                        +"QmFkMRAwDgYDVQQLEwdNeSBVbml0MQ8wDQYDVQQKEwZNeSBPcmcxEDAOBgNVBAcTB015IENpdHkx\n"
+                        +"CzAJBgNVBAgTAkFQMQswCQYDVQQGEwJJTjBcMA0GCSqGSIb3DQEBAQUAA0sAMEgCQQDBoSkFEEJC\n"
+                        +"/OtI49Cr8rC9pXpniw8lXG6iUUjEC3VzDuHpqKaCGNdilhVPkRsONsmLySoJDFsZR/w4HrXlwUS1\n"
+                        +"AgMBAAEwDQYJKoZIhvcNAQEEBQADQQCe3Xt5J+UoNqpdDN4y6KV4EdQlrMNfqBJnGTE+sdlKV6cN\n"
+                        +"PjUnrEF1laqhX4Rx+2u56VBA2SBnEaeADawaXWkD\n"
+                        +"-----END CERTIFICATE-----";
+
+    public void setUp() throws Exception {
+        needServerInfo = true;
+        needLoginConfiguration = true;
+        super.setUp();
+
+        GBeanData gbean;
+
+        gbean = buildGBeanData("name", "NeverFailLoginModule", LoginModuleGBean.getGBeanInfo());
+        neverFailModule = gbean.getAbstractName();
+        gbean.setAttribute("loginModuleClass", "org.apache.geronimo.security.jaas.NeverFailLoginModule");
+        gbean.setAttribute("options", null);
+        gbean.setAttribute("loginDomainName", "NeverFailDomain");
+        gbean.setAttribute("wrapPrincipals", Boolean.TRUE);
+        kernel.loadGBean(gbean, LoginModuleGBean.class.getClassLoader());
+        kernel.startGBean(neverFailModule);
+
+        gbean = buildGBeanData("name", "CertificatePropertiesLoginModule", LoginModuleGBean.getGBeanInfo());
+        testCE = gbean.getAbstractName();
+        gbean.setAttribute("loginModuleClass", "org.apache.geronimo.security.realm.providers.CertificatePropertiesFileLoginModule");
+        Map<String, Object> props = new HashMap<String, Object>();
+        props.put("usersURI", new File(BASEDIR, "src/test/data/data/cert-users.properties").toURI().toString());
+        props.put("groupsURI", new File(BASEDIR, "src/test/data/data/groups.properties").toURI().toString());
+        gbean.setAttribute("options", props);
+        gbean.setAttribute("loginDomainName", "CertProperties");
+        gbean.setAttribute("wrapPrincipals", Boolean.TRUE);
+        kernel.loadGBean(gbean, LoginModuleGBean.class.getClassLoader());
+        kernel.startGBean(testCE);
+
+        gbean = buildGBeanData("name", "CertificatePropertiesLoginModuleUse", JaasLoginModuleUse.getGBeanInfo());
+        AbstractName propsUseName = gbean.getAbstractName();
+        gbean.setAttribute("controlFlag", LoginModuleControlFlag.OPTIONAL);
+        gbean.setReferencePattern("LoginModule", testCE);
+        kernel.loadGBean(gbean, JaasLoginModuleUse.class.getClassLoader());
+        kernel.startGBean(propsUseName);
+
+        gbean = buildGBeanData("name", "NeverFailLoginModuleUse", JaasLoginModuleUse.getGBeanInfo());
+        AbstractName neverFailUseName = gbean.getAbstractName();
+        gbean.setAttribute("controlFlag", LoginModuleControlFlag.REQUIRED);
+        gbean.setReferencePattern("LoginModule", neverFailModule);
+        gbean.setReferencePattern("Next", propsUseName);
+        kernel.loadGBean(gbean, JaasLoginModuleUse.class.getClassLoader());
+        kernel.startGBean(neverFailUseName);
+
+        gbean = buildGBeanData("name", "CertificatePropertiesSecurityRealm", GenericSecurityRealm.getGBeanInfo());
+        testRealm = gbean.getAbstractName();
+        gbean.setAttribute("realmName", "cert-properties-realm");
+        gbean.setAttribute("wrapPrincipals", Boolean.TRUE);
+        gbean.setReferencePattern("LoginModuleConfiguration", neverFailUseName);
+        gbean.setReferencePattern("ServerInfo", serverInfo);
+        kernel.loadGBean(gbean, GenericSecurityRealm.class.getClassLoader());
+
+        kernel.startGBean(loginConfiguration);
+        kernel.startGBean(testRealm);
+        
+        CertificateFactory certFac = CertificateFactory.getInstance("X.509");
+        badCert = (X509Certificate) certFac.generateCertificate(new ByteArrayInputStream(badCertText.getBytes()));
+    }
+
+    public void tearDown() throws Exception {
+        kernel.stopGBean(testRealm);
+        kernel.stopGBean(loginConfiguration);
+        kernel.stopGBean(testCE);
+        kernel.stopGBean(neverFailModule);
+        kernel.stopGBean(serverInfo);
+
+        kernel.unloadGBean(testRealm);
+        kernel.unloadGBean(loginConfiguration);
+        kernel.unloadGBean(testCE);
+        kernel.unloadGBean(neverFailModule);
+        kernel.unloadGBean(serverInfo);
+
+        super.tearDown();
+    }
+
+    public void testBadCertificate() throws Exception {
+        LoginContext context = new LoginContext("cert-properties-realm", new CertCallback(badCert));
+
+        context.login();
+        Subject subject = context.getSubject();
+        assertTrue("expected non-null subject", subject != null);
+        assertEquals("expected zero principals", 0, subject.getPrincipals().size());
+        context.logout();
+    }
+}

Propchange: geronimo/server/branches/2.0/modules/geronimo-security/src/test/java/org/apache/geronimo/security/jaas/LoginCertificatePropertiesFileAdvancedTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: geronimo/server/branches/2.0/modules/geronimo-security/src/test/java/org/apache/geronimo/security/jaas/LoginCertificatePropertiesFileAdvancedTest.java
------------------------------------------------------------------------------
    svn:keywords = Date Revision

Propchange: geronimo/server/branches/2.0/modules/geronimo-security/src/test/java/org/apache/geronimo/security/jaas/LoginCertificatePropertiesFileAdvancedTest.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: geronimo/server/trunk/framework/modules/geronimo-security/src/main/java/org/apache/geronimo/security/realm/providers/CertificatePropertiesFileLoginModule.java
URL: http://svn.apache.org/viewvc/geronimo/server/trunk/framework/modules/geronimo-security/src/main/java/org/apache/geronimo/security/realm/providers/CertificatePropertiesFileLoginModule.java?rev=590862&r1=590861&r2=590862&view=diff
==============================================================================
--- geronimo/server/trunk/framework/modules/geronimo-security/src/main/java/org/apache/geronimo/security/realm/providers/CertificatePropertiesFileLoginModule.java
(original)
+++ geronimo/server/trunk/framework/modules/geronimo-security/src/main/java/org/apache/geronimo/security/realm/providers/CertificatePropertiesFileLoginModule.java
Wed Oct 31 16:56:41 2007
@@ -20,11 +20,15 @@
 import java.io.IOException;
 import java.io.InputStream;
 import java.net.URI;
+import java.security.Principal;
 import java.security.cert.X509Certificate;
+import java.util.Arrays;
+import java.util.Collections;
 import java.util.Enumeration;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Iterator;
+import java.util.List;
 import java.util.Map;
 import java.util.Properties;
 import java.util.Set;
@@ -67,17 +71,25 @@
     private static Log log = LogFactory.getLog(CertificatePropertiesFileLoginModule.class);
     public final static String USERS_URI = "usersURI";
     public final static String GROUPS_URI = "groupsURI";
-
+    public final static List<String> supportedOptions = Arrays.asList(USERS_URI, GROUPS_URI);
+            
     private final Map users = new HashMap();
     final Map groups = new HashMap();
 
     private Subject subject;
     private CallbackHandler handler;
     private X500Principal principal;
+    private boolean loginSucceeded;
+    private final Set<Principal> allPrincipals = new HashSet<Principal>();
 
     public void initialize(Subject subject, CallbackHandler callbackHandler, Map sharedState,
Map options) {
         this.subject = subject;
         this.handler = callbackHandler;
+        for(Object option: options.keySet()) {
+            if(!supportedOptions.contains(option)) {
+                log.warn("Ignoring option: "+option+". Not supported.");
+            }
+        }
         try {
             ServerInfo serverInfo = (ServerInfo) options.get(JaasLoginModuleUse.SERVERINFO_LM_OPTION);
             URI usersURI = new URI((String)options.get(USERS_URI));
@@ -132,7 +144,13 @@
     }
 
 
+    /**
+     * This LoginModule is not to be ignored.  So, this method should never return false.
+     * @return true if authentication succeeds, or throw a LoginException such as FailedLoginException
+     *         if authentication fails
+     */
     public boolean login() throws LoginException {
+        loginSucceeded = false;
         Callback[] callbacks = new Callback[1];
 
         callbacks[0] = new CertificateCallback();
@@ -151,44 +169,65 @@
         principal = certificate.getSubjectX500Principal();
 
         if(!users.containsKey(principal.getName())) {
+            // Clear out the private state
+            principal = null;
             throw new FailedLoginException();
         }
+
+        loginSucceeded = true;
         return true;
     }
 
+    /*
+     * @exception LoginException if login succeeded but commit failed.
+     *
+     * @return true if login succeeded and commit succeeded, or false if login failed but
commit succeeded.
+     */
     public boolean commit() throws LoginException {
-        Set principals = subject.getPrincipals();
-
-        principals.add(principal);
-        String userName = (String) users.get(principal.getName());
-        principals.add(new GeronimoUserPrincipal(userName));
-
-        Iterator e = groups.keySet().iterator();
-        while (e.hasNext()) {
-            String groupName = (String) e.next();
-            Set users = (Set) groups.get(groupName);
-            Iterator iter = users.iterator();
-            while (iter.hasNext()) {
-                String user = (String) iter.next();
-                if (userName.equals(user)) {
-                    principals.add(new GeronimoGroupPrincipal(groupName));
-                    break;
+        if(loginSucceeded) {
+            allPrincipals.add(principal);
+            String userName = (String) users.get(principal.getName());
+            allPrincipals.add(new GeronimoUserPrincipal(userName));
+
+            Iterator e = groups.keySet().iterator();
+            while (e.hasNext()) {
+                String groupName = (String) e.next();
+                Set users = (Set) groups.get(groupName);
+                Iterator iter = users.iterator();
+                while (iter.hasNext()) {
+                    String user = (String) iter.next();
+                    if (userName.equals(user)) {
+                        allPrincipals.add(new GeronimoGroupPrincipal(groupName));
+                        break;
+                    }
                 }
             }
+            subject.getPrincipals().addAll(allPrincipals);
         }
-
-        return true;
+        // Clear out the private state
+        principal = null;
+        
+        return loginSucceeded;
     }
 
     public boolean abort() throws LoginException {
-        principal = null;
-
-        return true;
+        if(loginSucceeded) {
+            // Clear out the private state
+            principal = null;
+            allPrincipals.retainAll(Collections.EMPTY_SET);
+        }
+        return loginSucceeded;
     }
 
     public boolean logout() throws LoginException {
+        // Clear out the private state
+        loginSucceeded = false;
         principal = null;
-        //todo: should remove principals added by commit
+        if(!subject.isReadOnly()) {
+            // Remove principals added by this LoginModule
+            subject.getPrincipals().removeAll(allPrincipals);
+        }
+        allPrincipals.retainAll(Collections.EMPTY_SET);
         return true;
     }
 

Added: geronimo/server/trunk/framework/modules/geronimo-security/src/test/java/org/apache/geronimo/security/jaas/LoginCertificatePropertiesFileAdvancedTest.java
URL: http://svn.apache.org/viewvc/geronimo/server/trunk/framework/modules/geronimo-security/src/test/java/org/apache/geronimo/security/jaas/LoginCertificatePropertiesFileAdvancedTest.java?rev=590862&view=auto
==============================================================================
--- geronimo/server/trunk/framework/modules/geronimo-security/src/test/java/org/apache/geronimo/security/jaas/LoginCertificatePropertiesFileAdvancedTest.java
(added)
+++ geronimo/server/trunk/framework/modules/geronimo-security/src/test/java/org/apache/geronimo/security/jaas/LoginCertificatePropertiesFileAdvancedTest.java
Wed Oct 31 16:56:41 2007
@@ -0,0 +1,142 @@
+/**
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You 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.ByteArrayInputStream;
+import java.io.File;
+import java.security.cert.CertificateFactory;
+import java.security.cert.X509Certificate;
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.security.auth.Subject;
+import javax.security.auth.login.LoginContext;
+
+import org.apache.geronimo.gbean.AbstractName;
+import org.apache.geronimo.gbean.GBeanData;
+import org.apache.geronimo.security.AbstractTest;
+import org.apache.geronimo.security.realm.GenericSecurityRealm;
+
+
+/**
+ * This test makes sure that CertificatePropertiesFileLoginModule does not add any principals
when login failed.
+ * 
+ * @version $Rev$ $Date$
+ */
+public class LoginCertificatePropertiesFileAdvancedTest extends AbstractTest {
+    protected AbstractName clientCE;
+    protected AbstractName testCE;
+    protected AbstractName testRealm;
+    protected AbstractName neverFailModule;
+
+    protected X509Certificate badCert;
+    String badCertText = "-----BEGIN CERTIFICATE-----\n"
+                        +"MIIBqTCCAVMCBgEV+C5ZTjANBgkqhkiG9w0BAQQFADBdMQwwCgYDVQQDEwNCYWQxEDAOBgNVBAsT\n"
+                        +"B015IFVuaXQxDzANBgNVBAoTBk15IE9yZzEQMA4GA1UEBxMHTXkgQ2l0eTELMAkGA1UECBMCQVAx\n"
+                        +"CzAJBgNVBAYTAklOMB4XDTA3MTAzMTIyMjg0OFoXDTE3MTAyODIyMjg0OFowXTEMMAoGA1UEAxMD\n"
+                        +"QmFkMRAwDgYDVQQLEwdNeSBVbml0MQ8wDQYDVQQKEwZNeSBPcmcxEDAOBgNVBAcTB015IENpdHkx\n"
+                        +"CzAJBgNVBAgTAkFQMQswCQYDVQQGEwJJTjBcMA0GCSqGSIb3DQEBAQUAA0sAMEgCQQDBoSkFEEJC\n"
+                        +"/OtI49Cr8rC9pXpniw8lXG6iUUjEC3VzDuHpqKaCGNdilhVPkRsONsmLySoJDFsZR/w4HrXlwUS1\n"
+                        +"AgMBAAEwDQYJKoZIhvcNAQEEBQADQQCe3Xt5J+UoNqpdDN4y6KV4EdQlrMNfqBJnGTE+sdlKV6cN\n"
+                        +"PjUnrEF1laqhX4Rx+2u56VBA2SBnEaeADawaXWkD\n"
+                        +"-----END CERTIFICATE-----";
+
+    public void setUp() throws Exception {
+        needServerInfo = true;
+        needLoginConfiguration = true;
+        super.setUp();
+
+        GBeanData gbean;
+
+        gbean = buildGBeanData("name", "NeverFailLoginModule", LoginModuleGBean.getGBeanInfo());
+        neverFailModule = gbean.getAbstractName();
+        gbean.setAttribute("loginModuleClass", "org.apache.geronimo.security.jaas.NeverFailLoginModule");
+        gbean.setAttribute("options", null);
+        gbean.setAttribute("loginDomainName", "NeverFailDomain");
+        gbean.setAttribute("wrapPrincipals", Boolean.TRUE);
+        kernel.loadGBean(gbean, LoginModuleGBean.class.getClassLoader());
+        kernel.startGBean(neverFailModule);
+
+        gbean = buildGBeanData("name", "CertificatePropertiesLoginModule", LoginModuleGBean.getGBeanInfo());
+        testCE = gbean.getAbstractName();
+        gbean.setAttribute("loginModuleClass", "org.apache.geronimo.security.realm.providers.CertificatePropertiesFileLoginModule");
+        Map<String, Object> props = new HashMap<String, Object>();
+        props.put("usersURI", new File(BASEDIR, "src/test/data/data/cert-users.properties").toURI().toString());
+        props.put("groupsURI", new File(BASEDIR, "src/test/data/data/groups.properties").toURI().toString());
+        gbean.setAttribute("options", props);
+        gbean.setAttribute("loginDomainName", "CertProperties");
+        gbean.setAttribute("wrapPrincipals", Boolean.TRUE);
+        kernel.loadGBean(gbean, LoginModuleGBean.class.getClassLoader());
+        kernel.startGBean(testCE);
+
+        gbean = buildGBeanData("name", "CertificatePropertiesLoginModuleUse", JaasLoginModuleUse.getGBeanInfo());
+        AbstractName propsUseName = gbean.getAbstractName();
+        gbean.setAttribute("controlFlag", LoginModuleControlFlag.OPTIONAL);
+        gbean.setReferencePattern("LoginModule", testCE);
+        kernel.loadGBean(gbean, JaasLoginModuleUse.class.getClassLoader());
+        kernel.startGBean(propsUseName);
+
+        gbean = buildGBeanData("name", "NeverFailLoginModuleUse", JaasLoginModuleUse.getGBeanInfo());
+        AbstractName neverFailUseName = gbean.getAbstractName();
+        gbean.setAttribute("controlFlag", LoginModuleControlFlag.REQUIRED);
+        gbean.setReferencePattern("LoginModule", neverFailModule);
+        gbean.setReferencePattern("Next", propsUseName);
+        kernel.loadGBean(gbean, JaasLoginModuleUse.class.getClassLoader());
+        kernel.startGBean(neverFailUseName);
+
+        gbean = buildGBeanData("name", "CertificatePropertiesSecurityRealm", GenericSecurityRealm.getGBeanInfo());
+        testRealm = gbean.getAbstractName();
+        gbean.setAttribute("realmName", "cert-properties-realm");
+        gbean.setAttribute("wrapPrincipals", Boolean.TRUE);
+        gbean.setReferencePattern("LoginModuleConfiguration", neverFailUseName);
+        gbean.setReferencePattern("ServerInfo", serverInfo);
+        kernel.loadGBean(gbean, GenericSecurityRealm.class.getClassLoader());
+
+        kernel.startGBean(loginConfiguration);
+        kernel.startGBean(testRealm);
+        
+        CertificateFactory certFac = CertificateFactory.getInstance("X.509");
+        badCert = (X509Certificate) certFac.generateCertificate(new ByteArrayInputStream(badCertText.getBytes()));
+    }
+
+    public void tearDown() throws Exception {
+        kernel.stopGBean(testRealm);
+        kernel.stopGBean(loginConfiguration);
+        kernel.stopGBean(testCE);
+        kernel.stopGBean(neverFailModule);
+        kernel.stopGBean(serverInfo);
+
+        kernel.unloadGBean(testRealm);
+        kernel.unloadGBean(loginConfiguration);
+        kernel.unloadGBean(testCE);
+        kernel.unloadGBean(neverFailModule);
+        kernel.unloadGBean(serverInfo);
+
+        super.tearDown();
+    }
+
+    public void testBadCertificate() throws Exception {
+        LoginContext context = new LoginContext("cert-properties-realm", new CertCallback(badCert));
+
+        context.login();
+        Subject subject = context.getSubject();
+        assertTrue("expected non-null subject", subject != null);
+        assertEquals("expected zero principals", 0, subject.getPrincipals().size());
+        context.logout();
+    }
+}

Propchange: geronimo/server/trunk/framework/modules/geronimo-security/src/test/java/org/apache/geronimo/security/jaas/LoginCertificatePropertiesFileAdvancedTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: geronimo/server/trunk/framework/modules/geronimo-security/src/test/java/org/apache/geronimo/security/jaas/LoginCertificatePropertiesFileAdvancedTest.java
------------------------------------------------------------------------------
    svn:keywords = Date Revision

Propchange: geronimo/server/trunk/framework/modules/geronimo-security/src/test/java/org/apache/geronimo/security/jaas/LoginCertificatePropertiesFileAdvancedTest.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: geronimo/server/trunk/modules/geronimo-security/src/main/java/org/apache/geronimo/security/realm/providers/CertificatePropertiesFileLoginModule.java
URL: http://svn.apache.org/viewvc/geronimo/server/trunk/modules/geronimo-security/src/main/java/org/apache/geronimo/security/realm/providers/CertificatePropertiesFileLoginModule.java?rev=590862&r1=590861&r2=590862&view=diff
==============================================================================
--- geronimo/server/trunk/modules/geronimo-security/src/main/java/org/apache/geronimo/security/realm/providers/CertificatePropertiesFileLoginModule.java
(original)
+++ geronimo/server/trunk/modules/geronimo-security/src/main/java/org/apache/geronimo/security/realm/providers/CertificatePropertiesFileLoginModule.java
Wed Oct 31 16:56:41 2007
@@ -20,11 +20,15 @@
 import java.io.IOException;
 import java.io.InputStream;
 import java.net.URI;
+import java.security.Principal;
 import java.security.cert.X509Certificate;
+import java.util.Arrays;
+import java.util.Collections;
 import java.util.Enumeration;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Iterator;
+import java.util.List;
 import java.util.Map;
 import java.util.Properties;
 import java.util.Set;
@@ -67,17 +71,25 @@
     private static Log log = LogFactory.getLog(CertificatePropertiesFileLoginModule.class);
     public final static String USERS_URI = "usersURI";
     public final static String GROUPS_URI = "groupsURI";
-
+    public final static List<String> supportedOptions = Arrays.asList(USERS_URI, GROUPS_URI);
+            
     private final Map users = new HashMap();
     final Map groups = new HashMap();
 
     private Subject subject;
     private CallbackHandler handler;
     private X500Principal principal;
+    private boolean loginSucceeded;
+    private final Set<Principal> allPrincipals = new HashSet<Principal>();
 
     public void initialize(Subject subject, CallbackHandler callbackHandler, Map sharedState,
Map options) {
         this.subject = subject;
         this.handler = callbackHandler;
+        for(Object option: options.keySet()) {
+            if(!supportedOptions.contains(option)) {
+                log.warn("Ignoring option: "+option+". Not supported.");
+            }
+        }
         try {
             ServerInfo serverInfo = (ServerInfo) options.get(JaasLoginModuleUse.SERVERINFO_LM_OPTION);
             URI usersURI = new URI((String)options.get(USERS_URI));
@@ -132,7 +144,13 @@
     }
 
 
+    /**
+     * This LoginModule is not to be ignored.  So, this method should never return false.
+     * @return true if authentication succeeds, or throw a LoginException such as FailedLoginException
+     *         if authentication fails
+     */
     public boolean login() throws LoginException {
+        loginSucceeded = false;
         Callback[] callbacks = new Callback[1];
 
         callbacks[0] = new CertificateCallback();
@@ -151,44 +169,65 @@
         principal = certificate.getSubjectX500Principal();
 
         if(!users.containsKey(principal.getName())) {
+            // Clear out the private state
+            principal = null;
             throw new FailedLoginException();
         }
+
+        loginSucceeded = true;
         return true;
     }
 
+    /*
+     * @exception LoginException if login succeeded but commit failed.
+     *
+     * @return true if login succeeded and commit succeeded, or false if login failed but
commit succeeded.
+     */
     public boolean commit() throws LoginException {
-        Set principals = subject.getPrincipals();
-
-        principals.add(principal);
-        String userName = (String) users.get(principal.getName());
-        principals.add(new GeronimoUserPrincipal(userName));
-
-        Iterator e = groups.keySet().iterator();
-        while (e.hasNext()) {
-            String groupName = (String) e.next();
-            Set users = (Set) groups.get(groupName);
-            Iterator iter = users.iterator();
-            while (iter.hasNext()) {
-                String user = (String) iter.next();
-                if (userName.equals(user)) {
-                    principals.add(new GeronimoGroupPrincipal(groupName));
-                    break;
+        if(loginSucceeded) {
+            allPrincipals.add(principal);
+            String userName = (String) users.get(principal.getName());
+            allPrincipals.add(new GeronimoUserPrincipal(userName));
+
+            Iterator e = groups.keySet().iterator();
+            while (e.hasNext()) {
+                String groupName = (String) e.next();
+                Set users = (Set) groups.get(groupName);
+                Iterator iter = users.iterator();
+                while (iter.hasNext()) {
+                    String user = (String) iter.next();
+                    if (userName.equals(user)) {
+                        allPrincipals.add(new GeronimoGroupPrincipal(groupName));
+                        break;
+                    }
                 }
             }
+            subject.getPrincipals().addAll(allPrincipals);
         }
-
-        return true;
+        // Clear out the private state
+        principal = null;
+        
+        return loginSucceeded;
     }
 
     public boolean abort() throws LoginException {
-        principal = null;
-
-        return true;
+        if(loginSucceeded) {
+            // Clear out the private state
+            principal = null;
+            allPrincipals.retainAll(Collections.EMPTY_SET);
+        }
+        return loginSucceeded;
     }
 
     public boolean logout() throws LoginException {
+        // Clear out the private state
+        loginSucceeded = false;
         principal = null;
-        //todo: should remove principals added by commit
+        if(!subject.isReadOnly()) {
+            // Remove principals added by this LoginModule
+            subject.getPrincipals().removeAll(allPrincipals);
+        }
+        allPrincipals.retainAll(Collections.EMPTY_SET);
         return true;
     }
 

Added: geronimo/server/trunk/modules/geronimo-security/src/test/java/org/apache/geronimo/security/jaas/LoginCertificatePropertiesFileAdvancedTest.java
URL: http://svn.apache.org/viewvc/geronimo/server/trunk/modules/geronimo-security/src/test/java/org/apache/geronimo/security/jaas/LoginCertificatePropertiesFileAdvancedTest.java?rev=590862&view=auto
==============================================================================
--- geronimo/server/trunk/modules/geronimo-security/src/test/java/org/apache/geronimo/security/jaas/LoginCertificatePropertiesFileAdvancedTest.java
(added)
+++ geronimo/server/trunk/modules/geronimo-security/src/test/java/org/apache/geronimo/security/jaas/LoginCertificatePropertiesFileAdvancedTest.java
Wed Oct 31 16:56:41 2007
@@ -0,0 +1,142 @@
+/**
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You 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.ByteArrayInputStream;
+import java.io.File;
+import java.security.cert.CertificateFactory;
+import java.security.cert.X509Certificate;
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.security.auth.Subject;
+import javax.security.auth.login.LoginContext;
+
+import org.apache.geronimo.gbean.AbstractName;
+import org.apache.geronimo.gbean.GBeanData;
+import org.apache.geronimo.security.AbstractTest;
+import org.apache.geronimo.security.realm.GenericSecurityRealm;
+
+
+/**
+ * This test makes sure that CertificatePropertiesFileLoginModule does not add any principals
when login failed.
+ * 
+ * @version $Rev$ $Date$
+ */
+public class LoginCertificatePropertiesFileAdvancedTest extends AbstractTest {
+    protected AbstractName clientCE;
+    protected AbstractName testCE;
+    protected AbstractName testRealm;
+    protected AbstractName neverFailModule;
+
+    protected X509Certificate badCert;
+    String badCertText = "-----BEGIN CERTIFICATE-----\n"
+                        +"MIIBqTCCAVMCBgEV+C5ZTjANBgkqhkiG9w0BAQQFADBdMQwwCgYDVQQDEwNCYWQxEDAOBgNVBAsT\n"
+                        +"B015IFVuaXQxDzANBgNVBAoTBk15IE9yZzEQMA4GA1UEBxMHTXkgQ2l0eTELMAkGA1UECBMCQVAx\n"
+                        +"CzAJBgNVBAYTAklOMB4XDTA3MTAzMTIyMjg0OFoXDTE3MTAyODIyMjg0OFowXTEMMAoGA1UEAxMD\n"
+                        +"QmFkMRAwDgYDVQQLEwdNeSBVbml0MQ8wDQYDVQQKEwZNeSBPcmcxEDAOBgNVBAcTB015IENpdHkx\n"
+                        +"CzAJBgNVBAgTAkFQMQswCQYDVQQGEwJJTjBcMA0GCSqGSIb3DQEBAQUAA0sAMEgCQQDBoSkFEEJC\n"
+                        +"/OtI49Cr8rC9pXpniw8lXG6iUUjEC3VzDuHpqKaCGNdilhVPkRsONsmLySoJDFsZR/w4HrXlwUS1\n"
+                        +"AgMBAAEwDQYJKoZIhvcNAQEEBQADQQCe3Xt5J+UoNqpdDN4y6KV4EdQlrMNfqBJnGTE+sdlKV6cN\n"
+                        +"PjUnrEF1laqhX4Rx+2u56VBA2SBnEaeADawaXWkD\n"
+                        +"-----END CERTIFICATE-----";
+
+    public void setUp() throws Exception {
+        needServerInfo = true;
+        needLoginConfiguration = true;
+        super.setUp();
+
+        GBeanData gbean;
+
+        gbean = buildGBeanData("name", "NeverFailLoginModule", LoginModuleGBean.getGBeanInfo());
+        neverFailModule = gbean.getAbstractName();
+        gbean.setAttribute("loginModuleClass", "org.apache.geronimo.security.jaas.NeverFailLoginModule");
+        gbean.setAttribute("options", null);
+        gbean.setAttribute("loginDomainName", "NeverFailDomain");
+        gbean.setAttribute("wrapPrincipals", Boolean.TRUE);
+        kernel.loadGBean(gbean, LoginModuleGBean.class.getClassLoader());
+        kernel.startGBean(neverFailModule);
+
+        gbean = buildGBeanData("name", "CertificatePropertiesLoginModule", LoginModuleGBean.getGBeanInfo());
+        testCE = gbean.getAbstractName();
+        gbean.setAttribute("loginModuleClass", "org.apache.geronimo.security.realm.providers.CertificatePropertiesFileLoginModule");
+        Map<String, Object> props = new HashMap<String, Object>();
+        props.put("usersURI", new File(BASEDIR, "src/test/data/data/cert-users.properties").toURI().toString());
+        props.put("groupsURI", new File(BASEDIR, "src/test/data/data/groups.properties").toURI().toString());
+        gbean.setAttribute("options", props);
+        gbean.setAttribute("loginDomainName", "CertProperties");
+        gbean.setAttribute("wrapPrincipals", Boolean.TRUE);
+        kernel.loadGBean(gbean, LoginModuleGBean.class.getClassLoader());
+        kernel.startGBean(testCE);
+
+        gbean = buildGBeanData("name", "CertificatePropertiesLoginModuleUse", JaasLoginModuleUse.getGBeanInfo());
+        AbstractName propsUseName = gbean.getAbstractName();
+        gbean.setAttribute("controlFlag", LoginModuleControlFlag.OPTIONAL);
+        gbean.setReferencePattern("LoginModule", testCE);
+        kernel.loadGBean(gbean, JaasLoginModuleUse.class.getClassLoader());
+        kernel.startGBean(propsUseName);
+
+        gbean = buildGBeanData("name", "NeverFailLoginModuleUse", JaasLoginModuleUse.getGBeanInfo());
+        AbstractName neverFailUseName = gbean.getAbstractName();
+        gbean.setAttribute("controlFlag", LoginModuleControlFlag.REQUIRED);
+        gbean.setReferencePattern("LoginModule", neverFailModule);
+        gbean.setReferencePattern("Next", propsUseName);
+        kernel.loadGBean(gbean, JaasLoginModuleUse.class.getClassLoader());
+        kernel.startGBean(neverFailUseName);
+
+        gbean = buildGBeanData("name", "CertificatePropertiesSecurityRealm", GenericSecurityRealm.getGBeanInfo());
+        testRealm = gbean.getAbstractName();
+        gbean.setAttribute("realmName", "cert-properties-realm");
+        gbean.setAttribute("wrapPrincipals", Boolean.TRUE);
+        gbean.setReferencePattern("LoginModuleConfiguration", neverFailUseName);
+        gbean.setReferencePattern("ServerInfo", serverInfo);
+        kernel.loadGBean(gbean, GenericSecurityRealm.class.getClassLoader());
+
+        kernel.startGBean(loginConfiguration);
+        kernel.startGBean(testRealm);
+        
+        CertificateFactory certFac = CertificateFactory.getInstance("X.509");
+        badCert = (X509Certificate) certFac.generateCertificate(new ByteArrayInputStream(badCertText.getBytes()));
+    }
+
+    public void tearDown() throws Exception {
+        kernel.stopGBean(testRealm);
+        kernel.stopGBean(loginConfiguration);
+        kernel.stopGBean(testCE);
+        kernel.stopGBean(neverFailModule);
+        kernel.stopGBean(serverInfo);
+
+        kernel.unloadGBean(testRealm);
+        kernel.unloadGBean(loginConfiguration);
+        kernel.unloadGBean(testCE);
+        kernel.unloadGBean(neverFailModule);
+        kernel.unloadGBean(serverInfo);
+
+        super.tearDown();
+    }
+
+    public void testBadCertificate() throws Exception {
+        LoginContext context = new LoginContext("cert-properties-realm", new CertCallback(badCert));
+
+        context.login();
+        Subject subject = context.getSubject();
+        assertTrue("expected non-null subject", subject != null);
+        assertEquals("expected zero principals", 0, subject.getPrincipals().size());
+        context.logout();
+    }
+}

Propchange: geronimo/server/trunk/modules/geronimo-security/src/test/java/org/apache/geronimo/security/jaas/LoginCertificatePropertiesFileAdvancedTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: geronimo/server/trunk/modules/geronimo-security/src/test/java/org/apache/geronimo/security/jaas/LoginCertificatePropertiesFileAdvancedTest.java
------------------------------------------------------------------------------
    svn:keywords = Date Revision

Propchange: geronimo/server/trunk/modules/geronimo-security/src/test/java/org/apache/geronimo/security/jaas/LoginCertificatePropertiesFileAdvancedTest.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain



Mime
View raw message