You are viewing a plain text version of this content. The canonical link for it is here.
Posted to scm@geronimo.apache.org by dj...@apache.org on 2005/05/17 02:28:29 UTC

svn commit: r170494 - in /geronimo/trunk/modules: axis-builder/src/java/org/apache/geronimo/axis/builder/ jetty/src/java/org/apache/geronimo/jetty/ jetty/src/test/org/apache/geronimo/jetty/ security/src/java/org/apache/geronimo/security/realm/providers/ webservices/src/java/org/apache/geronimo/webservices/

Author: djencks
Date: Mon May 16 17:28:28 2005
New Revision: 170494

URL: http://svn.apache.org/viewcvs?rev=170494&view=rev
Log:
GERONIMO-648 add security for ejb web services

Added:
    geronimo/trunk/modules/security/src/java/org/apache/geronimo/security/realm/providers/CertificateCallback.java
    geronimo/trunk/modules/security/src/java/org/apache/geronimo/security/realm/providers/CertificateCallbackHandler.java
    geronimo/trunk/modules/security/src/java/org/apache/geronimo/security/realm/providers/CertificatePropertiesFileLoginModule.java
    geronimo/trunk/modules/security/src/java/org/apache/geronimo/security/realm/providers/ClearableCallbackHandler.java
    geronimo/trunk/modules/security/src/java/org/apache/geronimo/security/realm/providers/PasswordCallbackHandler.java
      - copied, changed from r169699, geronimo/trunk/modules/jetty/src/java/org/apache/geronimo/jetty/PasswordCallbackHandler.java
Removed:
    geronimo/trunk/modules/jetty/src/java/org/apache/geronimo/jetty/PasswordCallbackHandler.java
Modified:
    geronimo/trunk/modules/axis-builder/src/java/org/apache/geronimo/axis/builder/AxisBuilder.java
    geronimo/trunk/modules/jetty/src/java/org/apache/geronimo/jetty/JAASJettyRealm.java
    geronimo/trunk/modules/jetty/src/java/org/apache/geronimo/jetty/JettyContainerImpl.java
    geronimo/trunk/modules/jetty/src/java/org/apache/geronimo/jetty/JettyEJBWebServiceContext.java
    geronimo/trunk/modules/jetty/src/test/org/apache/geronimo/jetty/ContainerTest.java
    geronimo/trunk/modules/webservices/src/java/org/apache/geronimo/webservices/SoapHandler.java

Modified: geronimo/trunk/modules/axis-builder/src/java/org/apache/geronimo/axis/builder/AxisBuilder.java
URL: http://svn.apache.org/viewcvs/geronimo/trunk/modules/axis-builder/src/java/org/apache/geronimo/axis/builder/AxisBuilder.java?rev=170494&r1=170493&r2=170494&view=diff
==============================================================================
--- geronimo/trunk/modules/axis-builder/src/java/org/apache/geronimo/axis/builder/AxisBuilder.java (original)
+++ geronimo/trunk/modules/axis-builder/src/java/org/apache/geronimo/axis/builder/AxisBuilder.java Mon May 16 17:28:28 2005
@@ -112,7 +112,7 @@
         try {
             classLoader.loadClass(seiClassName);
         } catch (ClassNotFoundException e) {
-            throw new DeploymentException("Unable to load servlet class for pojo webservice: "+seiClassName, e);
+            throw new DeploymentException("Unable to load servlet class for pojo webservice: " + seiClassName, e);
         }
 
         targetGBean.setAttribute("pojoClassName", seiClassName);
@@ -165,7 +165,7 @@
         SchemaInfoBuilder schemaInfoBuilder = null;
         JavaWsdlMappingType mapping = null;
         if (wsdlURI != null) {
-            schemaInfoBuilder =  new SchemaInfoBuilder(moduleFile, wsdlURI);
+            schemaInfoBuilder = new SchemaInfoBuilder(moduleFile, wsdlURI);
 
             mapping = WSDescriptorParser.readJaxrpcMapping(moduleFile, jaxrpcMappingURI);
         }
@@ -237,9 +237,6 @@
         }
 
         Map exceptionMap = WSDescriptorParser.getExceptionMap(mapping);
-//        Map schemaTypeKeyToSchemaTypeMap = schemaInfoBuilder.getSchemaTypeKeyToSchemaTypeMap();
-//        Map complexTypeMap = schemaInfoBuilder.getComplexTypesInWsdl();
-//        Map elementMap = schemaInfoBuilder.getElementToTypeMap();
 
         Map wsdlPortMap = service.getPorts();
         for (Iterator iterator = wsdlPortMap.entrySet().iterator(); iterator.hasNext();) {
@@ -257,7 +254,7 @@
 
             ServiceEndpointInterfaceMappingType[] endpointMappings = mapping.getServiceEndpointInterfaceMappingArray();
 
-            String credentialsName = credentialsNameMap == null? null: (String) credentialsNameMap.get(port.getName());
+            String credentialsName = credentialsNameMap == null ? null : (String) credentialsNameMap.get(port.getName());
 
             //port type corresponds to SEI
             List operations = portType.getOperations();
@@ -274,15 +271,20 @@
         javax.wsdl.Service service;
         if (serviceQName != null) {
             service = definition.getService(serviceQName);
+            if (service == null) {
+                throw new DeploymentException("No service wsdl for supplied service qname " + serviceQName);
+            }
         } else {
             Map services = definition.getServices();
-            if (services.size() != 1) {
+            if (services.size() > 1) {
                 throw new DeploymentException("no serviceQName supplied, and there are " + services.size() + " services");
             }
-            service = (javax.wsdl.Service) services.values().iterator().next();
-        }
-        if (service == null) {
-            throw new DeploymentException("No service wsdl for supplied service qname " + serviceQName);
+            if (services.size() == 0) {
+                //partial wsdl
+                service = null;
+            } else {
+                service = (javax.wsdl.Service) services.values().iterator().next();
+            }
         }
         return service;
     }

Modified: geronimo/trunk/modules/jetty/src/java/org/apache/geronimo/jetty/JAASJettyRealm.java
URL: http://svn.apache.org/viewcvs/geronimo/trunk/modules/jetty/src/java/org/apache/geronimo/jetty/JAASJettyRealm.java?rev=170494&r1=170493&r2=170494&view=diff
==============================================================================
--- 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 Mon May 16 17:28:28 2005
@@ -19,6 +19,7 @@
 import java.security.AccessControlContext;
 import java.security.AccessControlException;
 import java.security.Principal;
+import java.security.cert.X509Certificate;
 import java.util.HashMap;
 import javax.security.auth.Subject;
 import javax.security.auth.login.LoginContext;
@@ -27,8 +28,11 @@
 
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
-import org.apache.geronimo.security.ContextManager;
 import org.apache.geronimo.jetty.interceptor.SecurityContextBeforeAfter;
+import org.apache.geronimo.security.ContextManager;
+import org.apache.geronimo.security.realm.providers.CertificateCallbackHandler;
+import org.apache.geronimo.security.realm.providers.ClearableCallbackHandler;
+import org.apache.geronimo.security.realm.providers.PasswordCallbackHandler;
 import org.mortbay.http.HttpRequest;
 import org.mortbay.http.UserRealm;
 
@@ -66,16 +70,22 @@
                 userMap.remove(username);
             }
 
-
-            char[] password;
+            ClearableCallbackHandler callbackHandler;
             if (credentials instanceof char[]) {
-                password = (char[]) credentials;
+                char[] password = (char[]) credentials;
+                callbackHandler = new PasswordCallbackHandler(username, password);
             } else if (credentials instanceof String) {
-                password = ((String) credentials).toCharArray();
+                char[] password = ((String) credentials).toCharArray();
+                callbackHandler = new PasswordCallbackHandler(username, password);
+            } else if (credentials instanceof X509Certificate[]) {
+                X509Certificate[] certs = (X509Certificate[]) credentials;
+                if (certs.length < 1) {
+                    throw new LoginException("no certificates supplied");
+                }
+                callbackHandler = new CertificateCallbackHandler(certs[0]);
             } else {
                 throw new LoginException("Cannot extract credentials from class: " + credentials.getClass().getName());
             }
-            PasswordCallbackHandler callbackHandler = new PasswordCallbackHandler(username, password);
 
             //set up the login context
             LoginContext loginContext = new LoginContext(loginDomainName, callbackHandler);
@@ -93,7 +103,7 @@
 
             return userPrincipal;
         } catch (LoginException e) {
-            log.warn(e);
+            log.info("problem", e);
             return null;
         }
     }

Modified: geronimo/trunk/modules/jetty/src/java/org/apache/geronimo/jetty/JettyContainerImpl.java
URL: http://svn.apache.org/viewcvs/geronimo/trunk/modules/jetty/src/java/org/apache/geronimo/jetty/JettyContainerImpl.java?rev=170494&r1=170493&r2=170494&view=diff
==============================================================================
--- geronimo/trunk/modules/jetty/src/java/org/apache/geronimo/jetty/JettyContainerImpl.java (original)
+++ geronimo/trunk/modules/jetty/src/java/org/apache/geronimo/jetty/JettyContainerImpl.java Mon May 16 17:28:28 2005
@@ -132,8 +132,8 @@
         server.removeRealm(realm.getName());
     }
 
-    public void addWebService(String contextPath, WebServiceContainer webServiceContainer) throws Exception {
-        JettyEJBWebServiceContext webServiceContext = new JettyEJBWebServiceContext(contextPath, webServiceContainer);
+    public void addWebService(String contextPath, WebServiceContainer webServiceContainer, String securityRealmName, String realmName, String transportGuarantee, String authMethod, ClassLoader classLoader) throws Exception {
+        JettyEJBWebServiceContext webServiceContext = new JettyEJBWebServiceContext(contextPath, webServiceContainer, securityRealmName, realmName, transportGuarantee, authMethod, classLoader);
         addContext(webServiceContext);
         webServiceContext.start();
         webServices.put(contextPath, webServiceContext);

Modified: geronimo/trunk/modules/jetty/src/java/org/apache/geronimo/jetty/JettyEJBWebServiceContext.java
URL: http://svn.apache.org/viewcvs/geronimo/trunk/modules/jetty/src/java/org/apache/geronimo/jetty/JettyEJBWebServiceContext.java?rev=170494&r1=170493&r2=170494&view=diff
==============================================================================
--- geronimo/trunk/modules/jetty/src/java/org/apache/geronimo/jetty/JettyEJBWebServiceContext.java (original)
+++ geronimo/trunk/modules/jetty/src/java/org/apache/geronimo/jetty/JettyEJBWebServiceContext.java Mon May 16 17:28:28 2005
@@ -25,31 +25,36 @@
 import java.util.Map;
 
 import org.apache.geronimo.webservices.WebServiceContainer;
+import org.mortbay.http.Authenticator;
+import org.mortbay.http.BasicAuthenticator;
+import org.mortbay.http.ClientCertAuthenticator;
+import org.mortbay.http.DigestAuthenticator;
 import org.mortbay.http.HttpContext;
 import org.mortbay.http.HttpException;
 import org.mortbay.http.HttpHandler;
 import org.mortbay.http.HttpRequest;
 import org.mortbay.http.HttpResponse;
+import org.mortbay.http.UserRealm;
 
 /**
  * Delegates requests to a WebServiceContainer which is presumably for an EJB WebService.
- *
+ * <p/>
  * WebServiceContainer delegates to an EJBContainer that will ultimately provide the JNDI,
  * TX, and Security services for this web service.
- *
+ * <p/>
  * Nothing stopping us from using this for POJOs or other types of webservices if shared
  * Context (JNDI, tx, security) wasn't required to be supplied by the web context.
- *
+ * <p/>
  * From a 10,000 foot view the Jetty architecture has:
  * Container -> Context -> Holder -> Servlet
- *
+ * <p/>
  * A Container has multiple Contexts, typically webapps
  * A Context provides the JNDI, TX, and Security for the webapp and has many Holders
  * A Holder simply wraps each Servlet
- *
+ * <p/>
  * The POJO Web Service architecture on Jetty looks like this:
  * Container -> WebApp Context -> JettyPOJOWebServiceHolder -> POJOWebServiceServlet
- *
+ * <p/>
  * The EJB Web Service architecure, on the other hand, creates one Context for each EJB:
  * Container -> JettyEJBWebServiceContext
  *
@@ -59,12 +64,51 @@
 
     private final String contextPath;
     private final WebServiceContainer webServiceContainer;
+    private final Authenticator authenticator;
+    private final UserRealm realm;
+    private final boolean isConfidentialTransportGuarantee;
+    private final boolean isIntegralTransportGuarantee;
+    private final ClassLoader classLoader;
 
     private HttpContext httpContext;
 
-    public JettyEJBWebServiceContext(String contextPath, WebServiceContainer webServiceContainer) {
+    public JettyEJBWebServiceContext(String contextPath, WebServiceContainer webServiceContainer, String securityRealmName, String realmName, String transportGuarantee, String authMethod, ClassLoader classLoader) {
         this.contextPath = contextPath;
         this.webServiceContainer = webServiceContainer;
+        if (securityRealmName != null) {
+            JAASJettyRealm realm = new JAASJettyRealm(realmName, securityRealmName);
+            setRealm(realm);
+            this.realm = realm;
+            if ("NONE".equals(transportGuarantee)) {
+                isConfidentialTransportGuarantee = false;
+                isIntegralTransportGuarantee = false;
+            } else if ("INTEGRAL".equals(transportGuarantee)) {
+                isConfidentialTransportGuarantee = false;
+                isIntegralTransportGuarantee = true;
+            } else if ("CONFIDENTIAL".equals(transportGuarantee)) {
+                isConfidentialTransportGuarantee = true;
+                isIntegralTransportGuarantee = false;
+            } else {
+                throw new IllegalArgumentException("Invalid transport-guarantee: " + transportGuarantee);
+            }
+            if ("BASIC".equals(authMethod)) {
+                authenticator = new BasicAuthenticator();
+            } else if ("DIGEST".equals(authMethod)) {
+                authenticator = new DigestAuthenticator();
+            } else if ("CLIENT-CERT".equals(authMethod)) {
+                authenticator = new ClientCertAuthenticator();
+            } else if ("NONE".equals(authMethod)) {
+                authenticator = null;
+            } else {
+                throw new IllegalArgumentException("Invalid authMethod: " + authMethod);
+            }
+        } else {
+            realm = null;
+            authenticator = null;
+            isConfidentialTransportGuarantee = false;
+            isIntegralTransportGuarantee = false;
+        }
+        this.classLoader = classLoader;
     }
 
     public String getName() {
@@ -84,26 +128,49 @@
         req.setContentType("text/xml");
         RequestAdapter request = new RequestAdapter(req);
         ResponseAdapter response = new ResponseAdapter(res);
-            
+
         if (req.getParameter("wsdl") != null) {
             try {
-                webServiceContainer.getWsdl(request,response);
+                webServiceContainer.getWsdl(request, response);
+                //WHO IS RESPONSIBLE FOR CLOSING OUT?
             } catch (IOException e) {
                 throw e;
             } catch (Exception e) {
                 throw (HttpException) new HttpException(500, "Could not fetch wsdl!").initCause(e);
             }
         } else {
+            if (isConfidentialTransportGuarantee) {
+                if (!req.isConfidential()) {
+                    throw new HttpException(403);
+                }
+            } else if (isIntegralTransportGuarantee) {
+                if (!req.isIntegral()) {
+                    throw new HttpException(403);
+                }
+            }
+            Thread currentThread = Thread.currentThread();
+            ClassLoader oldClassLoader = currentThread.getContextClassLoader();
+            currentThread.setContextClassLoader(classLoader);
             try {
-                webServiceContainer.invoke(request,response);
-                req.setHandled(true);
-            } catch (IOException e) {
-                throw e;
-            } catch (Exception e) {
-                throw (HttpException) new HttpException(500, "Could not process message!").initCause(e);
+                if (authenticator != null) {
+                    String pathInContext = org.mortbay.util.URI.canonicalPath(req.getPath());
+                    if (authenticator.authenticate(realm, pathInContext, req, res) == null) {
+                        throw new HttpException(403);
+                    }
+                }
+                try {
+                    webServiceContainer.invoke(request, response);
+                    req.setHandled(true);
+                } catch (IOException e) {
+                    throw e;
+                } catch (Exception e) {
+                    throw (HttpException) new HttpException(500, "Could not process message!").initCause(e);
+                }
+            } finally {
+                currentThread.setContextClassLoader(oldClassLoader);
             }
         }
-            
+
     }
 
     public String getContextPath() {
@@ -123,9 +190,9 @@
         }
 
         public java.net.URI getURI() {
-            if( uri==null ) {
+            if (uri == null) {
                 try {
-                    String uriString =  request.getScheme()+"://"+request.getHost()+":"+request.getPort()+request.getURI();
+                    String uriString = request.getScheme() + "://" + request.getHost() + ":" + request.getPort() + request.getURI();
                     //return new java.net.URI(uri.getScheme(),uri.getHost(),uri.getPath(),uri.);
                     uri = new java.net.URI(uriString);
                 } catch (URISyntaxException e) {
@@ -149,7 +216,7 @@
 
         public int getMethod() {
             Integer method = (Integer) methods.get(request.getMethod());
-            return method == null ? UNSUPPORTED: method.intValue();
+            return method == null ? UNSUPPORTED : method.intValue();
         }
 
         public String getParameter(String name) {
@@ -164,7 +231,7 @@
             return request.getAttribute(name);
         }
 
-        public void setAttribute(String name, Object value){
+        public void setAttribute(String name, Object value) {
             request.setAttribute(name, value);
         }
 

Modified: geronimo/trunk/modules/jetty/src/test/org/apache/geronimo/jetty/ContainerTest.java
URL: http://svn.apache.org/viewcvs/geronimo/trunk/modules/jetty/src/test/org/apache/geronimo/jetty/ContainerTest.java?rev=170494&r1=170493&r2=170494&view=diff
==============================================================================
--- geronimo/trunk/modules/jetty/src/test/org/apache/geronimo/jetty/ContainerTest.java (original)
+++ geronimo/trunk/modules/jetty/src/test/org/apache/geronimo/jetty/ContainerTest.java Mon May 16 17:28:28 2005
@@ -79,7 +79,7 @@
 
         String contextPath = "/foo/webservice.ws";
         MockWebServiceContainer webServiceInvoker = new MockWebServiceContainer();
-        kernel.invoke(containerName, "addWebService", new Object[] {contextPath, webServiceInvoker}, new String[] {String.class.getName(), WebServiceContainer.class.getName()});
+        kernel.invoke(containerName, "addWebService", new Object[] {contextPath, webServiceInvoker, null, null, null, null,cl}, new String[] {String.class.getName(), WebServiceContainer.class.getName(), String.class.getName(), String.class.getName(), String.class.getName(), String.class.getName(), ClassLoader.class.getName()});
 
         HttpURLConnection connection = (HttpURLConnection) new URL("http://localhost:5678" + contextPath).openConnection();
         try {

Added: geronimo/trunk/modules/security/src/java/org/apache/geronimo/security/realm/providers/CertificateCallback.java
URL: http://svn.apache.org/viewcvs/geronimo/trunk/modules/security/src/java/org/apache/geronimo/security/realm/providers/CertificateCallback.java?rev=170494&view=auto
==============================================================================
--- geronimo/trunk/modules/security/src/java/org/apache/geronimo/security/realm/providers/CertificateCallback.java (added)
+++ geronimo/trunk/modules/security/src/java/org/apache/geronimo/security/realm/providers/CertificateCallback.java Mon May 16 17:28:28 2005
@@ -0,0 +1,35 @@
+/**
+ *
+ * Copyright 2005 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.realm.providers;
+
+import java.security.cert.X509Certificate;
+import javax.security.auth.callback.Callback;
+
+/**
+ * @version $Rev:  $ $Date:  $
+ */
+public class CertificateCallback implements Callback {
+    X509Certificate certificate;
+
+    public X509Certificate getCertificate() {
+        return certificate;
+    }
+
+    public void setCertificate(X509Certificate certificate) {
+        this.certificate = certificate;
+    }
+}

Added: geronimo/trunk/modules/security/src/java/org/apache/geronimo/security/realm/providers/CertificateCallbackHandler.java
URL: http://svn.apache.org/viewcvs/geronimo/trunk/modules/security/src/java/org/apache/geronimo/security/realm/providers/CertificateCallbackHandler.java?rev=170494&view=auto
==============================================================================
--- geronimo/trunk/modules/security/src/java/org/apache/geronimo/security/realm/providers/CertificateCallbackHandler.java (added)
+++ geronimo/trunk/modules/security/src/java/org/apache/geronimo/security/realm/providers/CertificateCallbackHandler.java Mon May 16 17:28:28 2005
@@ -0,0 +1,48 @@
+/**
+ *
+ * Copyright 2005 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.realm.providers;
+
+import java.io.IOException;
+import java.security.cert.X509Certificate;
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.UnsupportedCallbackException;
+
+/**
+ * @version $Rev:  $ $Date:  $
+ */
+public class CertificateCallbackHandler implements ClearableCallbackHandler {
+    X509Certificate certificate;
+    public CertificateCallbackHandler(X509Certificate certificate) {
+        this.certificate = certificate;
+    }
+
+    public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {
+        for (int i = 0; i < callbacks.length; i++) {
+            Callback callback = callbacks[i];
+            if (callback instanceof CertificateCallback) {
+                CertificateCallback cc = (CertificateCallback) callback;
+                cc.setCertificate(certificate);
+            } else {
+                throw new UnsupportedCallbackException(callback);
+            }
+        }
+    }
+
+    public void clear() {
+        certificate = null;
+    }
+}

Added: geronimo/trunk/modules/security/src/java/org/apache/geronimo/security/realm/providers/CertificatePropertiesFileLoginModule.java
URL: http://svn.apache.org/viewcvs/geronimo/trunk/modules/security/src/java/org/apache/geronimo/security/realm/providers/CertificatePropertiesFileLoginModule.java?rev=170494&view=auto
==============================================================================
--- geronimo/trunk/modules/security/src/java/org/apache/geronimo/security/realm/providers/CertificatePropertiesFileLoginModule.java (added)
+++ geronimo/trunk/modules/security/src/java/org/apache/geronimo/security/realm/providers/CertificatePropertiesFileLoginModule.java Mon May 16 17:28:28 2005
@@ -0,0 +1,216 @@
+/**
+ *
+ * Copyright 2003-2005 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.realm.providers;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URI;
+import java.security.cert.X509Certificate;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Set;
+import java.util.Collection;
+import javax.security.auth.Subject;
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.NameCallback;
+import javax.security.auth.callback.UnsupportedCallbackException;
+import javax.security.auth.login.LoginException;
+import javax.security.auth.spi.LoginModule;
+import javax.security.auth.x500.X500Principal;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.geronimo.common.GeronimoSecurityException;
+import org.apache.geronimo.kernel.Kernel;
+import org.apache.geronimo.kernel.KernelRegistry;
+import org.apache.geronimo.security.jaas.JaasLoginModuleUse;
+import org.apache.geronimo.system.serverinfo.ServerInfo;
+
+
+/**
+ * An example LoginModule that reads a list of users and group from a file on disk.
+ * Authentication is provided by the SSL layer supplying the client certificate.
+ * All we check is that it is present.  The
+ * file should be formatted using standard Java properties syntax.  Expects
+ * to be run by a GenericSecurityRealm (doesn't work on its own).
+ *
+ * The usersURI property file should have lines of the form token=certificatename
+ * where certificate name is X509Certificate.getSubjectX500Principal().getName()
+ *
+ * The groupsURI property file should have lines of the form group=token1,token2,...
+ * where the tokens were associated to the certificate names in the usersURI properties file.
+ *
+ * @version $Rev: 169154 $ $Date: 2005-05-08 12:35:23 -0700 (Sun, 08 May 2005) $
+ */
+public class CertificatePropertiesFileLoginModule implements LoginModule {
+    public final static String USERS_URI = "usersURI";
+    public final static String GROUPS_URI = "groupsURI";
+    private static Log log = LogFactory.getLog(CertificatePropertiesFileLoginModule.class);
+    private final Map users = new HashMap();
+    final Map groups = new HashMap();
+
+    Subject subject;
+    CallbackHandler handler;
+    X500Principal principal;
+
+    public void initialize(Subject subject, CallbackHandler callbackHandler, Map sharedState, Map options) {
+        this.subject = subject;
+        this.handler = callbackHandler;
+        try {
+            Kernel kernel = KernelRegistry.getKernel((String)options.get(JaasLoginModuleUse.KERNEL_LM_OPTION));
+            ServerInfo serverInfo = (ServerInfo) options.get(JaasLoginModuleUse.SERVERINFO_LM_OPTION);
+            URI usersURI = new URI((String)options.get(USERS_URI));
+            URI groupsURI = new URI((String)options.get(GROUPS_URI));
+            loadProperties(kernel, serverInfo, usersURI, groupsURI);
+        } catch (Exception e) {
+            log.error(e);
+            throw new IllegalArgumentException("Unable to configure properties file login module: "+e);
+        }
+    }
+
+    public void loadProperties(Kernel kernel, ServerInfo serverInfo, URI usersURI, URI groupURI) throws GeronimoSecurityException {
+        try {
+            URI userFile = serverInfo.resolve(usersURI);
+            URI groupFile = serverInfo.resolve(groupURI);
+            InputStream stream = userFile.toURL().openStream();
+            Properties tmpUsers = new Properties();
+            tmpUsers.load(stream);
+            stream.close();
+
+            for (Iterator iterator = tmpUsers.entrySet().iterator(); iterator.hasNext();) {
+                Map.Entry entry = (Map.Entry) iterator.next();
+                users.put(entry.getValue(), entry.getKey());
+            }
+
+            Properties temp = new Properties();
+            stream = groupFile.toURL().openStream();
+            temp.load(stream);
+            stream.close();
+
+            Enumeration e = temp.keys();
+            while (e.hasMoreElements()) {
+                String groupName = (String) e.nextElement();
+                String[] userList = ((String) temp.get(groupName)).split(",");
+
+                Set userset = (Set) groups.get(groupName);
+                if (userset == null) {
+                    userset = new HashSet();
+                    groups.put(groupName, userset);
+                }
+
+                for (int i = 0; i < userList.length; i++) {
+                    String userName = userList[i];
+                    userset.add(userName);
+                }
+            }
+
+        } catch (Exception e) {
+            log.error("Properties File Login Module - data load failed", e);
+            throw new GeronimoSecurityException(e);
+        }
+    }
+
+
+    public boolean login() throws LoginException {
+        Callback[] callbacks = new Callback[1];
+
+        callbacks[0] = new CertificateCallback();
+        try {
+            handler.handle(callbacks);
+        } catch (IOException ioe) {
+            throw (LoginException) new LoginException().initCause(ioe);
+        } catch (UnsupportedCallbackException uce) {
+            throw (LoginException) new LoginException().initCause(uce);
+        }
+        assert callbacks.length == 1;
+        X509Certificate certificate = ((CertificateCallback)callbacks[0]).getCertificate();
+        if (certificate == null) {
+            return false;
+        }
+        principal = certificate.getSubjectX500Principal();
+
+        return users.containsKey(principal.getName());
+    }
+
+    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;
+                }
+            }
+        }
+
+        return true;
+    }
+
+    public boolean abort() throws LoginException {
+        principal = null;
+
+        return true;
+    }
+
+    public boolean logout() throws LoginException {
+        principal = null;
+
+        return true;
+    }
+
+    /**
+     * Gets the names of all principal classes that may be populated into
+     * a Subject.
+     */
+    public String[] getPrincipalClassNames() {
+        return new String[]{GeronimoUserPrincipal.class.getName(), GeronimoGroupPrincipal.class.getName()};
+    }
+
+    /**
+     * Gets a list of all the principals of a particular type (identified by
+     * the principal class).  These are available for manual role mapping.
+     */
+    public String[] getPrincipalsOfClass(String className) {
+        Collection s;
+        if(className.equals(GeronimoGroupPrincipal.class.getName())) {
+            s = groups.keySet();
+        } else if(className.equals(GeronimoUserPrincipal.class.getName())) {
+            s = users.values();
+        } else if(className.equals(X500Principal.class.getName())) {
+            s = users.keySet();
+        } else {
+            throw new IllegalArgumentException("No such principal class "+className);
+        }
+        return (String[]) s.toArray(new String[s.size()]);
+    }
+}

Added: geronimo/trunk/modules/security/src/java/org/apache/geronimo/security/realm/providers/ClearableCallbackHandler.java
URL: http://svn.apache.org/viewcvs/geronimo/trunk/modules/security/src/java/org/apache/geronimo/security/realm/providers/ClearableCallbackHandler.java?rev=170494&view=auto
==============================================================================
--- geronimo/trunk/modules/security/src/java/org/apache/geronimo/security/realm/providers/ClearableCallbackHandler.java (added)
+++ geronimo/trunk/modules/security/src/java/org/apache/geronimo/security/realm/providers/ClearableCallbackHandler.java Mon May 16 17:28:28 2005
@@ -0,0 +1,26 @@
+/**
+ *
+ * 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.realm.providers;
+
+import javax.security.auth.callback.CallbackHandler;
+
+/**
+ * @version $Rev:  $ $Date:  $
+ */
+public interface ClearableCallbackHandler extends CallbackHandler {
+    void clear();
+}

Copied: geronimo/trunk/modules/security/src/java/org/apache/geronimo/security/realm/providers/PasswordCallbackHandler.java (from r169699, geronimo/trunk/modules/jetty/src/java/org/apache/geronimo/jetty/PasswordCallbackHandler.java)
URL: http://svn.apache.org/viewcvs/geronimo/trunk/modules/security/src/java/org/apache/geronimo/security/realm/providers/PasswordCallbackHandler.java?p2=geronimo/trunk/modules/security/src/java/org/apache/geronimo/security/realm/providers/PasswordCallbackHandler.java&p1=geronimo/trunk/modules/jetty/src/java/org/apache/geronimo/jetty/PasswordCallbackHandler.java&r1=169699&r2=170494&rev=170494&view=diff
==============================================================================
--- geronimo/trunk/modules/jetty/src/java/org/apache/geronimo/jetty/PasswordCallbackHandler.java (original)
+++ geronimo/trunk/modules/security/src/java/org/apache/geronimo/security/realm/providers/PasswordCallbackHandler.java Mon May 16 17:28:28 2005
@@ -14,7 +14,7 @@
  *  See the License for the specific language governing permissions and
  *  limitations under the License.
  */
-package org.apache.geronimo.jetty;
+package org.apache.geronimo.security.realm.providers;
 
 import java.util.Arrays;
 import javax.security.auth.callback.Callback;
@@ -26,7 +26,7 @@
 /**
  * @version $Revision$ $Date$
  */
-public class PasswordCallbackHandler implements CallbackHandler {
+public class PasswordCallbackHandler implements ClearableCallbackHandler {
     private final String username;
     private final char[] password;
 

Modified: geronimo/trunk/modules/webservices/src/java/org/apache/geronimo/webservices/SoapHandler.java
URL: http://svn.apache.org/viewcvs/geronimo/trunk/modules/webservices/src/java/org/apache/geronimo/webservices/SoapHandler.java?rev=170494&r1=170493&r2=170494&view=diff
==============================================================================
--- geronimo/trunk/modules/webservices/src/java/org/apache/geronimo/webservices/SoapHandler.java (original)
+++ geronimo/trunk/modules/webservices/src/java/org/apache/geronimo/webservices/SoapHandler.java Mon May 16 17:28:28 2005
@@ -21,7 +21,7 @@
  */
 public interface SoapHandler {
 
-    void addWebService(String contextPath, WebServiceContainer webServiceContainer) throws Exception;
+    void addWebService(String contextPath, WebServiceContainer webServiceContainer, String securityRealmName, String realmName, String transportGuarantee, String authMethod, ClassLoader classLoader) throws Exception;
 
     void removeWebService(String contextPath);