You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@activemq.apache.org by ch...@apache.org on 2006/09/19 00:43:25 UTC

svn commit: r447608 [2/2] - in /incubator/activemq/trunk: activemq-core/src/main/java/org/apache/activemq/ activemq-core/src/main/java/org/apache/activemq/broker/ activemq-core/src/main/java/org/apache/activemq/security/ activemq-core/src/main/java/org...

Added: incubator/activemq/trunk/activemq-core/src/test/java/org/apache/activemq/transport/tcp/StubSSLSocketFactory.java
URL: http://svn.apache.org/viewvc/incubator/activemq/trunk/activemq-core/src/test/java/org/apache/activemq/transport/tcp/StubSSLSocketFactory.java?view=auto&rev=447608
==============================================================================
--- incubator/activemq/trunk/activemq-core/src/test/java/org/apache/activemq/transport/tcp/StubSSLSocketFactory.java (added)
+++ incubator/activemq/trunk/activemq-core/src/test/java/org/apache/activemq/transport/tcp/StubSSLSocketFactory.java Mon Sep 18 15:43:24 2006
@@ -0,0 +1,59 @@
+/**
+ *
+ * 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.activemq.transport.tcp;
+
+import java.io.IOException;
+import java.net.InetAddress;
+import java.net.ServerSocket;
+import java.net.Socket;
+
+import javax.net.ssl.SSLServerSocketFactory;
+
+public class StubSSLSocketFactory extends SSLServerSocketFactory {
+    
+    private final ServerSocket retServerSocket;
+    
+    public StubSSLSocketFactory(ServerSocket returnServerSocket) {
+        retServerSocket = returnServerSocket;
+    }
+    
+    public ServerSocket createServerSocket(int arg0) throws IOException {
+        return retServerSocket;
+    }
+
+    public ServerSocket createServerSocket(int arg0, int arg1)
+            throws IOException {
+        return retServerSocket;
+    }
+    
+    public ServerSocket createServerSocket(int arg0, int arg1, InetAddress arg2)
+    throws IOException {
+        return retServerSocket;
+    }
+    
+    // --- Stubbed Methods --- 
+
+    public String[] getDefaultCipherSuites() {
+        return null;
+    }
+
+    public String[] getSupportedCipherSuites() {
+        return null;
+    }
+}

Added: incubator/activemq/trunk/activemq-core/src/test/java/org/apache/activemq/transport/tcp/StubSslTransport.java
URL: http://svn.apache.org/viewvc/incubator/activemq/trunk/activemq-core/src/test/java/org/apache/activemq/transport/tcp/StubSslTransport.java?view=auto&rev=447608
==============================================================================
--- incubator/activemq/trunk/activemq-core/src/test/java/org/apache/activemq/transport/tcp/StubSslTransport.java (added)
+++ incubator/activemq/trunk/activemq-core/src/test/java/org/apache/activemq/transport/tcp/StubSslTransport.java Mon Sep 18 15:43:24 2006
@@ -0,0 +1,52 @@
+/**
+ *
+ * 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.activemq.transport.tcp;
+
+import javax.net.ssl.SSLSocket;
+
+import org.apache.activemq.wireformat.WireFormat;
+
+public class StubSslTransport extends SslTransport {
+    public static final int UNTOUCHED = -1;
+    public static final int FALSE = 0;
+    public static final int TRUE = 1;
+    
+    private int wantClientAuthStatus = UNTOUCHED;
+    private int needClientAuthStatus = UNTOUCHED;
+    
+    public StubSslTransport(WireFormat wireFormat, SSLSocket socket) throws Exception {
+        super(wireFormat, socket);
+    }
+    
+    public void setWantClientAuth(boolean arg0) {
+        this.wantClientAuthStatus = (arg0 ? TRUE : FALSE);
+    }
+    
+    public void setNeedClientAuth(boolean arg0) {
+        this.needClientAuthStatus = (arg0 ? TRUE : FALSE);
+    }
+    
+    public int getWantClientAuthStatus() {
+        return wantClientAuthStatus;
+    }
+    
+    public int getNeedClientAuthStatus() {
+        return needClientAuthStatus;
+    }
+}

Added: incubator/activemq/trunk/activemq-core/src/test/java/org/apache/activemq/transport/tcp/StubX509Certificate.java
URL: http://svn.apache.org/viewvc/incubator/activemq/trunk/activemq-core/src/test/java/org/apache/activemq/transport/tcp/StubX509Certificate.java?view=auto&rev=447608
==============================================================================
--- incubator/activemq/trunk/activemq-core/src/test/java/org/apache/activemq/transport/tcp/StubX509Certificate.java (added)
+++ incubator/activemq/trunk/activemq-core/src/test/java/org/apache/activemq/transport/tcp/StubX509Certificate.java Mon Sep 18 15:43:24 2006
@@ -0,0 +1,166 @@
+/**
+ *
+ * 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.activemq.transport.tcp;
+
+import java.math.BigInteger;
+import java.security.Principal;
+import java.security.PublicKey;
+import java.util.Date;
+import java.util.Set;
+
+import java.security.cert.X509Certificate;
+
+public class StubX509Certificate extends X509Certificate {
+    public StubX509Certificate(Principal id) {
+        this.id = id;
+    }
+    
+    public Principal getSubjectDN() {
+        return this.id;
+    }
+    
+    private final Principal id;
+    
+    // --- Stubbed Methods ---
+    public void checkValidity() {
+    // TODO Auto-generated method stub
+    
+    }
+    
+    public void checkValidity(Date arg0) {
+    // TODO Auto-generated method stub
+    
+    }
+    
+    public int getVersion() {
+    // TODO Auto-generated method stub
+    return 0;
+    }
+    
+    public BigInteger getSerialNumber() {
+    // TODO Auto-generated method stub
+    return null;
+    }
+    
+    public Principal getIssuerDN() {
+    // TODO Auto-generated method stub
+    return null;
+    }
+    
+    public Date getNotBefore() {
+    // TODO Auto-generated method stub
+    return null;
+    }
+    
+    public Date getNotAfter() {
+    // TODO Auto-generated method stub
+    return null;
+    }
+    
+    public byte[] getTBSCertificate() {
+    // TODO Auto-generated method stub
+    return null;
+    }
+    
+    public byte[] getSignature() {
+    // TODO Auto-generated method stub
+    return null;
+    }
+    
+    public String getSigAlgName() {
+    // TODO Auto-generated method stub
+    return null;
+    }
+    
+    public String getSigAlgOID() {
+    // TODO Auto-generated method stub
+    return null;
+    }
+    
+    public byte[] getSigAlgParams() {
+    // TODO Auto-generated method stub
+    return null;
+    }
+    
+    public boolean[] getIssuerUniqueID() {
+    // TODO Auto-generated method stub
+    return null;
+    }
+    
+    public boolean[] getSubjectUniqueID() {
+    // TODO Auto-generated method stub
+    return null;
+    }
+    
+    public boolean[] getKeyUsage() {
+    // TODO Auto-generated method stub
+    return null;
+    }
+    
+    public int getBasicConstraints() {
+    // TODO Auto-generated method stub
+    return 0;
+    }
+    
+    public byte[] getEncoded() {
+    // TODO Auto-generated method stub
+    return null;
+    }
+    
+    public void verify(PublicKey arg0) {
+    // TODO Auto-generated method stub
+    
+    }
+    
+    public void verify(PublicKey arg0, String arg1) {
+    // TODO Auto-generated method stub
+    
+    }
+    
+    public String toString() {
+    // TODO Auto-generated method stub
+    return null;
+    }
+    
+    public PublicKey getPublicKey() {
+    // TODO Auto-generated method stub
+    return null;
+    }
+    
+    public boolean hasUnsupportedCriticalExtension() {
+    // TODO Auto-generated method stub
+    return false;
+    }
+    
+    public Set getCriticalExtensionOIDs() {
+    // TODO Auto-generated method stub
+    return null;
+    }
+    
+    public Set getNonCriticalExtensionOIDs() {
+    // TODO Auto-generated method stub
+    return null;
+    }
+    
+    public byte[] getExtensionValue(String arg0) {
+    // TODO Auto-generated method stub
+    return null;
+    }
+
+}
\ No newline at end of file

Added: incubator/activemq/trunk/activemq-jaas/src/main/java/org/apache/activemq/jaas/CertificateCallback.java
URL: http://svn.apache.org/viewvc/incubator/activemq/trunk/activemq-jaas/src/main/java/org/apache/activemq/jaas/CertificateCallback.java?view=auto&rev=447608
==============================================================================
--- incubator/activemq/trunk/activemq-jaas/src/main/java/org/apache/activemq/jaas/CertificateCallback.java (added)
+++ incubator/activemq/trunk/activemq-jaas/src/main/java/org/apache/activemq/jaas/CertificateCallback.java Mon Sep 18 15:43:24 2006
@@ -0,0 +1,52 @@
+/**
+ *
+ * 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.activemq.jaas;
+
+import javax.security.auth.callback.Callback;
+import java.security.cert.X509Certificate;
+
+/**
+ * A Callback for SSL certificates.
+ * 
+ * Will return a certificate chain to its client.
+ * 
+ * @author sepandm@gmail.com (Sepand)
+ *
+ */
+public class CertificateCallback implements Callback {
+    X509Certificate certificates[] = null;
+    
+    /**
+     * Setter for certificate chain.
+     * 
+     * @param certs The certificates to be returned.
+     */
+    public void setCertificates(X509Certificate certs[]) {
+        certificates = certs;
+    }
+    
+    /**
+     * Getter for certificate chain.
+     * 
+     * @return The certificates being carried.
+     */
+    public X509Certificate[] getCertificates() {
+        return certificates;
+    }
+}

Added: incubator/activemq/trunk/activemq-jaas/src/main/java/org/apache/activemq/jaas/CertificateLoginModule.java
URL: http://svn.apache.org/viewvc/incubator/activemq/trunk/activemq-jaas/src/main/java/org/apache/activemq/jaas/CertificateLoginModule.java?view=auto&rev=447608
==============================================================================
--- incubator/activemq/trunk/activemq-jaas/src/main/java/org/apache/activemq/jaas/CertificateLoginModule.java (added)
+++ incubator/activemq/trunk/activemq-jaas/src/main/java/org/apache/activemq/jaas/CertificateLoginModule.java Mon Sep 18 15:43:24 2006
@@ -0,0 +1,191 @@
+/**
+ *
+ * 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.activemq.jaas;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Enumeration;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+import java.security.cert.X509Certificate;
+
+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.PasswordCallback;
+import javax.security.auth.callback.UnsupportedCallbackException;
+import javax.security.auth.login.FailedLoginException;
+import javax.security.auth.login.LoginException;
+import javax.security.auth.spi.LoginModule;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+/**
+ * A LoginModule that allows for authentication based on SSL certificates.
+ * 
+ * Allows for subclasses to define methods used to verify user certificates and find user groups. 
+ * Uses CertificateCallbacks to retrieve certificates.
+ *  
+ * @author sepandm@gmail.com (Sepand)
+ *
+ */
+public abstract class CertificateLoginModule implements LoginModule {
+    
+    private CallbackHandler callbackHandler;
+    private Subject subject;
+    
+    private X509Certificate certificates[];
+    private String username = null;
+    private Set groups = null;
+    
+    private Set principals = new HashSet();
+    
+    private static final Log log = LogFactory.getLog(CertificateLoginModule.class);
+    private boolean debug;
+
+    /**
+     * Overriding to allow for proper initialization.
+     * 
+     * Standard JAAS.
+     */
+    public void initialize(Subject subject, CallbackHandler callbackHandler, Map sharedState, Map options) {
+        this.subject = subject;
+        this.callbackHandler = callbackHandler;
+        
+        debug = "true".equalsIgnoreCase((String) options.get("debug"));
+        
+        if (debug) {
+            log.debug("Initialized debug");
+        }
+    }
+
+    /**
+     * Overriding to allow for certificate-based login.
+     * 
+     * Standard JAAS.
+     */
+    public boolean login() throws LoginException {
+        Callback[] callbacks = new Callback[1];
+
+        callbacks[0] = new CertificateCallback();
+        try {
+            callbackHandler.handle(callbacks);
+        } catch (IOException ioe) {
+            throw new LoginException(ioe.getMessage());
+        } catch (UnsupportedCallbackException uce) {
+            throw new LoginException(uce.getMessage() + " Unable to obtain client certificates.");
+        }
+        certificates = ((CertificateCallback) callbacks[0]).getCertificates();
+        
+        username = getUserNameForCertificates(certificates);
+        if ( username == null )
+            throw new FailedLoginException("Unable to verify client certificates.");
+
+        groups = getUserGroups(username);
+        
+        if (debug) {
+            log.debug("Certificate for user: " + username);
+        }
+        return true;
+    }
+
+    /**
+     * Overriding to complete login process.
+     * 
+     * Standard JAAS.
+     */
+    public boolean commit() throws LoginException {
+        principals.add(new UserPrincipal(username));
+
+        String currentGroup = null;
+        for (Iterator iter = groups.iterator(); iter.hasNext(); ) {
+            currentGroup = (String)iter.next();
+            principals.add(new GroupPrincipal(currentGroup));
+        }
+
+        subject.getPrincipals().addAll(principals);
+
+        clear();
+
+        if (debug) {
+            log.debug("commit");
+        }
+        return true;
+    }
+
+    /**
+     * Standard JAAS override.
+     */
+    public boolean abort() throws LoginException {
+        clear();
+
+        if (debug) {
+            log.debug("abort");
+        }
+        return true;
+    }
+
+    /**
+     * Standard JAAS override.
+     */
+    public boolean logout() {
+        subject.getPrincipals().removeAll(principals);
+        principals.clear();
+
+        if (debug) {
+            log.debug("logout");
+        }
+        return true;
+    }
+    
+    /**
+     * Helper method.
+     */
+    private void clear() {
+        groups.clear();
+        certificates = null;
+    }
+    
+    /**
+     * Should return a unique name corresponding to the certificates given.
+     * 
+     * The name returned will be used to look up access levels as well as
+     *      group associations.
+     *      
+     * @param dn The distinguished name.
+     * @return The unique name if the certificate is recognized, null otherwise.
+     */
+    protected abstract String getUserNameForCertificates(final X509Certificate[] certs) throws LoginException;
+    
+    /**
+     * Should return a set of the groups this user belongs to.
+     * 
+     * The groups returned will be added to the user's credentials.
+     * 
+     * @param username The username of the client. This is the same name that
+     *      getUserNameForDn returned for the user's DN.
+     * @return A Set of the names of the groups this user belongs to.
+     */
+    protected abstract Set getUserGroups(final String username) throws LoginException;
+
+}

Added: incubator/activemq/trunk/activemq-jaas/src/main/java/org/apache/activemq/jaas/JaasCertificateCallbackHandler.java
URL: http://svn.apache.org/viewvc/incubator/activemq/trunk/activemq-jaas/src/main/java/org/apache/activemq/jaas/JaasCertificateCallbackHandler.java?view=auto&rev=447608
==============================================================================
--- incubator/activemq/trunk/activemq-jaas/src/main/java/org/apache/activemq/jaas/JaasCertificateCallbackHandler.java (added)
+++ incubator/activemq/trunk/activemq-jaas/src/main/java/org/apache/activemq/jaas/JaasCertificateCallbackHandler.java Mon Sep 18 15:43:24 2006
@@ -0,0 +1,71 @@
+/**
+ *
+ * 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.activemq.jaas;
+
+
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.NameCallback;
+import javax.security.auth.callback.PasswordCallback;
+import javax.security.auth.callback.UnsupportedCallbackException;
+
+import java.io.IOException;
+import java.security.cert.X509Certificate;
+
+/**
+ * A Standard JAAS callback handler for SSL certificate requests.
+ * 
+ * Will only handle callbacks of type CertificateCallback.
+ * 
+ * @author sepandm@gmail.com (Sepand)
+ *
+ */
+public class JaasCertificateCallbackHandler implements CallbackHandler {
+    final X509Certificate certificates[];
+    
+    /**
+     * Basic constructor.
+     * 
+     * @param cert The certificate returned when calling back.
+     */
+    public JaasCertificateCallbackHandler(X509Certificate certs[]) {
+        certificates = certs;
+    }
+    
+    /**
+     * Overriding handle method to handle certificates.
+     * 
+     * @param callbacks The callbacks requested.
+     * @throws IOException
+     * @throws UnsupportedCallbackException Thrown if an unkown Callback type is encountered.
+     */
+    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 certCallback = (CertificateCallback) callback;
+                
+                certCallback.setCertificates(certificates);
+                
+            } else {
+                throw new UnsupportedCallbackException(callback);
+            }
+        }
+    }
+}

Added: incubator/activemq/trunk/activemq-jaas/src/main/java/org/apache/activemq/jaas/JassCredentialCallback.java
URL: http://svn.apache.org/viewvc/incubator/activemq/trunk/activemq-jaas/src/main/java/org/apache/activemq/jaas/JassCredentialCallback.java?view=auto&rev=447608
==============================================================================
--- incubator/activemq/trunk/activemq-jaas/src/main/java/org/apache/activemq/jaas/JassCredentialCallback.java (added)
+++ incubator/activemq/trunk/activemq-jaas/src/main/java/org/apache/activemq/jaas/JassCredentialCallback.java Mon Sep 18 15:43:24 2006
@@ -0,0 +1,63 @@
+/**
+ *
+ * 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.activemq.jaas;
+
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.NameCallback;
+import javax.security.auth.callback.PasswordCallback;
+import javax.security.auth.callback.UnsupportedCallbackException;
+import java.io.IOException;
+
+
+/**
+ * A JASS username password CallbackHandler.
+ */
+public class JassCredentialCallback implements CallbackHandler {
+
+    private final String username;
+    private final String password;
+
+    public JassCredentialCallback(String username, String password) {
+        this.username = username;
+        this.password = password;
+    }
+
+    public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {
+        for (int i = 0; i < callbacks.length; i++) {
+            Callback callback = callbacks[i];
+            if (callback instanceof PasswordCallback) {
+                PasswordCallback passwordCallback = (PasswordCallback) callback;
+                if (password == null) {
+                    passwordCallback.setPassword(null);
+                }
+                else {
+                    passwordCallback.setPassword(password.toCharArray());
+                }
+            } else if (callback instanceof NameCallback) {
+                NameCallback nameCallback = (NameCallback) callback;
+                if (username == null) {
+                    nameCallback.setName(null);
+                }
+                else {
+                    nameCallback.setName(username);
+                }
+            }
+        }
+    }
+}

Added: incubator/activemq/trunk/activemq-jaas/src/main/java/org/apache/activemq/jaas/TextFileCertificateLoginModule.java
URL: http://svn.apache.org/viewvc/incubator/activemq/trunk/activemq-jaas/src/main/java/org/apache/activemq/jaas/TextFileCertificateLoginModule.java?view=auto&rev=447608
==============================================================================
--- incubator/activemq/trunk/activemq-jaas/src/main/java/org/apache/activemq/jaas/TextFileCertificateLoginModule.java (added)
+++ incubator/activemq/trunk/activemq-jaas/src/main/java/org/apache/activemq/jaas/TextFileCertificateLoginModule.java Mon Sep 18 15:43:24 2006
@@ -0,0 +1,140 @@
+/**
+ *
+ * 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.activemq.jaas;
+
+import java.io.File;
+import java.io.IOException;
+import java.security.cert.X509Certificate;
+import java.util.Enumeration;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Set;
+
+import javax.security.auth.Subject;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.login.LoginException;
+
+/**
+ * A LoginModule allowing for SSL certificate based authentication based on Distinguished Names (DN) stored in text
+ *      files.
+ *      
+ * The DNs are parsed using a Properties class where each line is <user_name>=<user_DN>.
+ * This class also uses a group definition file where each line is <group_name>=<user_name_1>,<user_name_2>,etc.
+ * The user and group files' locations must be specified in the org.apache.activemq.jaas.textfiledn.user and
+ *      org.apache.activemq.jaas.textfiledn.user properties respectively.
+ * 
+ * NOTE: This class will re-read user and group files for every authentication (i.e it does live updates of allowed
+ *      groups and users).
+ * 
+ * @author sepandm@gmail.com (Sepand)
+ */
+public class TextFileCertificateLoginModule extends CertificateLoginModule {
+    
+    private final String USER_FILE = "org.apache.activemq.jaas.textfiledn.user";
+    private final String GROUP_FILE = "org.apache.activemq.jaas.textfiledn.group";
+    
+    private File baseDir;
+    private String usersFilePathname;
+    private String groupsFilePathname;
+    
+    /**
+     * Performs initialization of file paths.
+     * 
+     * A standard JAAS override.
+     */
+    public void initialize(Subject subject, CallbackHandler callbackHandler, Map sharedState, Map options) {
+        super.initialize(subject, callbackHandler, sharedState, options);       
+        if (System.getProperty("java.security.auth.login.config") != null) {
+            baseDir = new File(System.getProperty("java.security.auth.login.config")).getParentFile();
+        } else {
+            baseDir = new File(".");
+        }
+        
+        usersFilePathname = (String) options.get(USER_FILE)+"";
+        groupsFilePathname = (String) options.get(GROUP_FILE)+"";
+    }
+    
+    /**
+     * Overriding to allow DN authorization based on DNs specified in text files.
+     *  
+     * @param certs The certificate the incoming connection provided.
+     * @return The user's authenticated name or null if unable to authenticate the user.
+     * @throws LoginException Thrown if unable to find user file or connection certificate. 
+     */
+    protected String getUserNameForCertificates(final X509Certificate[] certs) throws LoginException {
+        if (certs == null) {
+            throw new LoginException("Client certificates not found. Cannot authenticate.");
+        }
+        
+        File usersFile = new File(baseDir,usersFilePathname);
+        
+        Properties users = new Properties();
+        
+        try {
+            users.load(new java.io.FileInputStream(usersFile));
+        } catch (IOException ioe) {
+            throw new LoginException("Unable to load user properties file " + usersFile);
+        }
+        
+        String dn = certs[0].getSubjectDN().getName();
+        
+        for(Enumeration vals = users.elements(), keys = users.keys(); vals.hasMoreElements(); ) {
+            if ( ((String)vals.nextElement()).equals(dn) ) {
+                return (String)keys.nextElement();
+            } else {
+                keys.nextElement();
+            }
+        }
+        
+        return null;
+    }
+    
+    /**
+     * Overriding to allow for group discovery based on text files.
+     * 
+     * @param username The name of the user being examined. This is the same name returned by
+     *      getUserNameForCertificates.
+     * @return A Set of name Strings for groups this user belongs to.
+     * @throws LoginException Thrown if unable to find group definition file.
+     */
+    protected Set getUserGroups(String username) throws LoginException {
+        File groupsFile = new File(baseDir, groupsFilePathname);
+        
+        Properties groups = new Properties();
+        try {
+            groups.load(new java.io.FileInputStream(groupsFile));
+        } catch (IOException ioe) {
+            throw new LoginException("Unable to load group properties file " + groupsFile);
+        }
+        Set userGroups = new HashSet();
+        for (Enumeration enumeration = groups.keys(); enumeration.hasMoreElements();) {
+            String groupName = (String) enumeration.nextElement();
+            String[] userList = (groups.getProperty(groupName) + "").split(",");
+            for (int i = 0; i < userList.length; i++) {
+                if (username.equals(userList[i])) {
+                    userGroups.add(groupName);
+                    break;
+                }
+            }
+        }
+        
+        return userGroups;
+    }
+}

Added: incubator/activemq/trunk/activemq-jaas/src/test/java/org/apache/activemq/jaas/CertificateLoginModuleTest.java
URL: http://svn.apache.org/viewvc/incubator/activemq/trunk/activemq-jaas/src/test/java/org/apache/activemq/jaas/CertificateLoginModuleTest.java?view=auto&rev=447608
==============================================================================
--- incubator/activemq/trunk/activemq-jaas/src/test/java/org/apache/activemq/jaas/CertificateLoginModuleTest.java (added)
+++ incubator/activemq/trunk/activemq-jaas/src/test/java/org/apache/activemq/jaas/CertificateLoginModuleTest.java Mon Sep 18 15:43:24 2006
@@ -0,0 +1,144 @@
+/**
+ *
+ * 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.activemq.jaas;
+
+import junit.framework.TestCase;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.security.Principal;
+import java.security.cert.X509Certificate;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+import java.util.Vector;
+
+import javax.security.auth.Subject;
+import javax.security.auth.login.LoginException;
+
+public class CertificateLoginModuleTest extends TestCase {
+    private final String userName = "testUser";
+    private final List groupNames = new Vector();
+    private StubCertificateLoginModule loginModule;
+    
+    private Subject subject;
+    
+    public CertificateLoginModuleTest() {
+        groupNames.add("testGroup1");
+        groupNames.add("testGroup2");
+        groupNames.add("testGroup3");
+        groupNames.add("testGroup4");
+    }
+    
+    protected void setUp() throws Exception {
+        subject = new Subject();
+    }
+
+    protected void tearDown() throws Exception {
+    }
+    
+    private void loginWithCredentials(String userName, Set groupNames) throws LoginException {
+        loginModule = new StubCertificateLoginModule(userName, new HashSet(groupNames));
+        JaasCertificateCallbackHandler callbackHandler = new JaasCertificateCallbackHandler(null); 
+        
+        loginModule.initialize(subject, callbackHandler, null, new HashMap());
+
+        loginModule.login();
+        loginModule.commit();
+    }
+    
+    private void checkPrincipalsMatch(Subject subject) {
+        boolean nameFound = false;
+        boolean groupsFound[] = new boolean[groupNames.size()];
+        for (int i = 0; i < groupsFound.length; ++i) {
+            groupsFound[i] = false;
+        }
+        
+        for (Iterator iter = subject.getPrincipals().iterator(); iter.hasNext(); ) {
+            Principal currentPrincipal = (Principal) iter.next();
+            
+            if (currentPrincipal instanceof UserPrincipal) {
+                if (((UserPrincipal)currentPrincipal).getName().equals(userName)) {
+                    if (nameFound == false) {
+                        nameFound = true;
+                    } else {
+                        fail("UserPrincipal found twice.");
+                    }
+                        
+                } else {
+                    fail("Unknown UserPrincipal found.");
+                }
+                    
+            } else if (currentPrincipal instanceof GroupPrincipal) {
+                int principalIdx = groupNames.indexOf(((GroupPrincipal)currentPrincipal).getName());
+                
+                if (principalIdx < 0) {
+                    fail("Unknown GroupPrincipal found.");
+                }
+                
+                if (groupsFound[principalIdx] == false) {
+                    groupsFound[principalIdx] = true;
+                } else {
+                    fail("GroupPrincipal found twice.");
+                }
+            } else {
+                fail("Unknown Principal type found.");
+            }
+        }
+    }
+    
+    public void testLoginSuccess() throws IOException {
+        try {
+            loginWithCredentials(userName, new HashSet(groupNames));
+        } catch (Exception e) {
+            fail("Unable to login: " + e.getMessage());
+        }
+        
+        checkPrincipalsMatch(subject);
+    }
+    
+    public void testLoginFailure() throws IOException {
+        boolean loginFailed = false;
+        
+        try {
+            loginWithCredentials(null, new HashSet());
+        } catch (LoginException e) {
+            loginFailed = true;
+        }
+        
+        if (!loginFailed) {
+            fail("Logged in with unknown certificate.");
+        }
+    }
+    
+    public void testLogOut() throws IOException {
+        try {
+            loginWithCredentials(userName, new HashSet(groupNames));
+        } catch (Exception e) {
+            fail("Unable to login: " + e.getMessage());
+        }
+        
+        loginModule.logout();
+        
+        assertEquals("logout should have cleared Subject principals.", 0, subject.getPrincipals().size());
+    }
+}
+

Added: incubator/activemq/trunk/activemq-jaas/src/test/java/org/apache/activemq/jaas/StubCertificateLoginModule.java
URL: http://svn.apache.org/viewvc/incubator/activemq/trunk/activemq-jaas/src/test/java/org/apache/activemq/jaas/StubCertificateLoginModule.java?view=auto&rev=447608
==============================================================================
--- incubator/activemq/trunk/activemq-jaas/src/test/java/org/apache/activemq/jaas/StubCertificateLoginModule.java (added)
+++ incubator/activemq/trunk/activemq-jaas/src/test/java/org/apache/activemq/jaas/StubCertificateLoginModule.java Mon Sep 18 15:43:24 2006
@@ -0,0 +1,48 @@
+/**
+ *
+ * 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.activemq.jaas;
+
+import java.security.cert.X509Certificate;
+import java.util.Set;
+
+import javax.security.auth.login.LoginException;
+
+public class StubCertificateLoginModule extends CertificateLoginModule {
+    final String userName;
+    final Set groupNames;
+    
+    String lastUserName = null;
+    X509Certificate[] lastCertChain = null;
+    
+    public StubCertificateLoginModule(String userName, Set groupNames) {
+        this.userName = userName;
+        this.groupNames = groupNames;
+    }
+
+    protected String getUserNameForCertificates(X509Certificate[] certs)
+            throws LoginException {
+        lastCertChain = certs;
+        return userName;
+    }
+    
+    protected Set getUserGroups(String username) throws LoginException {
+        lastUserName = username;
+        return this.groupNames;
+    }
+}