You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@qpid.apache.org by ra...@apache.org on 2010/03/22 23:38:31 UTC

svn commit: r926380 - in /qpid/trunk/qpid/java: client/src/main/java/org/apache/qpid/client/ common/src/main/java/org/apache/qpid/ssl/ common/src/main/java/org/apache/qpid/transport/network/security/ssl/ systests/src/main/java/org/apache/qpid/client/ssl/

Author: rajith
Date: Mon Mar 22 22:38:31 2010
New Revision: 926380

URL: http://svn.apache.org/viewvc?rev=926380&view=rev
Log:
This is related to QPID-2447
Added QpidClientX509KeyManager (a customer KeyManager) which will return the ssl_client_alias specified in the Connection URL.
Note the alias here is actually the certificate name and not the alias used in the keytool.

I also fixed a minor bug in SSLUtil to retrive the identitiy of the local certificate instead of the peer's certificate.
Added a test for the above JIRA.
Added AMQTestConnection_0_10 which allows the SecurityLayer to be exposed for testing purposes.

Added:
    qpid/trunk/qpid/java/client/src/main/java/org/apache/qpid/client/AMQTestConnection_0_10.java
    qpid/trunk/qpid/java/common/src/main/java/org/apache/qpid/transport/network/security/ssl/QpidClientX509KeyManager.java
Modified:
    qpid/trunk/qpid/java/client/src/main/java/org/apache/qpid/client/AMQConnectionDelegate_0_10.java
    qpid/trunk/qpid/java/common/src/main/java/org/apache/qpid/ssl/SSLContextFactory.java
    qpid/trunk/qpid/java/common/src/main/java/org/apache/qpid/transport/network/security/ssl/SSLUtil.java
    qpid/trunk/qpid/java/systests/src/main/java/org/apache/qpid/client/ssl/SSLTest.java

Modified: qpid/trunk/qpid/java/client/src/main/java/org/apache/qpid/client/AMQConnectionDelegate_0_10.java
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/java/client/src/main/java/org/apache/qpid/client/AMQConnectionDelegate_0_10.java?rev=926380&r1=926379&r2=926380&view=diff
==============================================================================
--- qpid/trunk/qpid/java/client/src/main/java/org/apache/qpid/client/AMQConnectionDelegate_0_10.java (original)
+++ qpid/trunk/qpid/java/client/src/main/java/org/apache/qpid/client/AMQConnectionDelegate_0_10.java Mon Mar 22 22:38:31 2010
@@ -398,4 +398,9 @@ public class AMQConnectionDelegate_0_10 
         } 
         return 0;
     }
+    
+    protected org.apache.qpid.transport.Connection getQpidConnection()
+    {
+        return _qpidConnection;
+    }
 }

Added: qpid/trunk/qpid/java/client/src/main/java/org/apache/qpid/client/AMQTestConnection_0_10.java
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/java/client/src/main/java/org/apache/qpid/client/AMQTestConnection_0_10.java?rev=926380&view=auto
==============================================================================
--- qpid/trunk/qpid/java/client/src/main/java/org/apache/qpid/client/AMQTestConnection_0_10.java (added)
+++ qpid/trunk/qpid/java/client/src/main/java/org/apache/qpid/client/AMQTestConnection_0_10.java Mon Mar 22 22:38:31 2010
@@ -0,0 +1,16 @@
+package org.apache.qpid.client;
+
+import org.apache.qpid.transport.Connection;
+
+public class AMQTestConnection_0_10 extends AMQConnection
+{
+    public AMQTestConnection_0_10(String url) throws Exception
+    {
+        super(url);
+    }
+    
+    public Connection getConnection()
+    {
+        return((AMQConnectionDelegate_0_10)_delegate).getQpidConnection();
+    }    
+}

Modified: qpid/trunk/qpid/java/common/src/main/java/org/apache/qpid/ssl/SSLContextFactory.java
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/java/common/src/main/java/org/apache/qpid/ssl/SSLContextFactory.java?rev=926380&r1=926379&r2=926380&view=diff
==============================================================================
--- qpid/trunk/qpid/java/common/src/main/java/org/apache/qpid/ssl/SSLContextFactory.java (original)
+++ qpid/trunk/qpid/java/common/src/main/java/org/apache/qpid/ssl/SSLContextFactory.java Mon Mar 22 22:38:31 2010
@@ -27,10 +27,13 @@ import java.io.InputStream;
 import java.security.GeneralSecurityException;
 import java.security.KeyStore;
 
+import javax.net.ssl.KeyManager;
 import javax.net.ssl.KeyManagerFactory;
 import javax.net.ssl.SSLContext;
 import javax.net.ssl.TrustManagerFactory;
 
+import org.apache.qpid.transport.network.security.ssl.SSLUtil;
+
 /**
  * Factory used to create SSLContexts. SSL needs to be configured
  * before this will work.
@@ -68,7 +71,7 @@ public class SSLContextFactory {
      */
     private String _trustStoreCertType;
     
-	
+	private KeyManager customKeyManager;
     
     public SSLContextFactory(String trustStorePath, String trustStorePassword,
             String trustStoreCertType) 
@@ -90,7 +93,7 @@ public class SSLContextFactory {
 	    _trustStorePath = trustStorePath;
         _trustStorePassword = trustStorePassword;
                 
-        if (_trustStorePassword.equals("none"))
+        if (_trustStorePassword != null && _trustStorePassword.equals("none"))
         {
             _trustStorePassword = null;
         }
@@ -99,7 +102,7 @@ public class SSLContextFactory {
 	    _keyStorePath = keyStorePath;
 		_keyStorePassword = keyStorePassword;
 				
-		if (_keyStorePassword.equals("none"))
+		if (_keyStorePassword != null && _keyStorePassword.equals("none"))
 		{
 			_keyStorePassword = null;
 		}
@@ -113,29 +116,63 @@ public class SSLContextFactory {
 		}
 	}
 	
+	public SSLContextFactory(String trustStorePath, String trustStorePassword, String trustStoreCertType,
+	                         KeyManager customKeyManager) 
+    {
+
+        _trustStorePath = trustStorePath;
+        _trustStorePassword = trustStorePassword;
+                
+        if (_trustStorePassword != null && _trustStorePassword.equals("none"))
+        {
+            _trustStorePassword = null;
+        }
+        _trustStoreCertType = trustStoreCertType;
+        
+        if (_trustStorePath == null) {
+            throw new IllegalArgumentException("A TrustStore path or KeyStore path must be specified");
+        }
+        if (_trustStoreCertType == null) {
+            throw new IllegalArgumentException("Cert type must be specified");
+        }
+        
+        this.customKeyManager = customKeyManager;
+    }
+	
+	
 	/**
 	 * Builds a SSLContext appropriate for use with a server
 	 * @return SSLContext
 	 * @throws GeneralSecurityException
 	 * @throws IOException
 	 */
+
 	public SSLContext buildServerContext() throws GeneralSecurityException, IOException
 	{
-        // Create keystore
-		KeyStore ks = getInitializedKeyStore(_keyStorePath,_keyStorePassword);
-
-        // Set up key manager factory to use our key store
-        KeyManagerFactory kmf = KeyManagerFactory.getInstance(_keyStoreCertType);
-        kmf.init(ks, _keyStorePassword.toCharArray());
-
-        KeyStore ts = getInitializedKeyStore(_trustStorePath,_trustStorePassword);
+        KeyStore ts = SSLUtil.getInitializedKeyStore(_trustStorePath,_trustStorePassword);
         TrustManagerFactory tmf = TrustManagerFactory.getInstance(_trustStoreCertType);
         tmf.init(ts);
         
         // Initialize the SSLContext to work with our key managers.
-        SSLContext sslContext = SSLContext.getInstance("TLS");        
-        sslContext.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
+        SSLContext sslContext = SSLContext.getInstance("TLS");
+        
+        if (customKeyManager != null)
+        {
+            sslContext.init(new KeyManager[]{customKeyManager},
+                            tmf.getTrustManagers(), null);
+            
+        }
+        else
+        {
+            // Create keystore
+            KeyStore ks = SSLUtil.getInitializedKeyStore(_keyStorePath,_keyStorePassword);
+            // Set up key manager factory to use our key store
+            KeyManagerFactory kmf = KeyManagerFactory.getInstance(_keyStoreCertType);
+            kmf.init(ks, _keyStorePassword.toCharArray());
 
+            sslContext.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);    
+        }
+        
         return sslContext;		
 	}
 	
@@ -147,7 +184,7 @@ public class SSLContextFactory {
 	 */
 	public SSLContext buildClientContext() throws GeneralSecurityException, IOException
 	{
-		KeyStore ks = getInitializedKeyStore(_trustStorePath,_trustStorePassword);
+		KeyStore ks = SSLUtil.getInitializedKeyStore(_trustStorePath,_trustStorePassword);
         TrustManagerFactory tmf = TrustManagerFactory.getInstance(_trustStoreCertType);
         tmf.init(ks);
         SSLContext context = SSLContext.getInstance("TLS");
@@ -155,41 +192,4 @@ public class SSLContextFactory {
         return context;		
 	}
 	
-	private KeyStore getInitializedKeyStore(String storePath, String storePassword) throws GeneralSecurityException, IOException
-	{
-        KeyStore ks = KeyStore.getInstance("JKS");
-        InputStream in = null;
-        try
-        {
-        	File f = new File(storePath);
-        	if (f.exists())
-        	{
-        		in = new FileInputStream(f);
-        	}
-        	else 
-        	{
-        		in = Thread.currentThread().getContextClassLoader().getResourceAsStream(storePath);
-        	}
-            if (in == null)
-            {
-                throw new IOException("Unable to load keystore resource: " + storePath);
-            }
-            ks.load(in, storePassword.toCharArray());
-        }
-        finally
-        {
-            if (in != null)
-            {
-                //noinspection EmptyCatchBlock
-                try
-                {
-                    in.close();
-                }
-                catch (IOException ignored)
-                {
-                }
-            }
-        }
-        return ks;
-	}
 }

Added: qpid/trunk/qpid/java/common/src/main/java/org/apache/qpid/transport/network/security/ssl/QpidClientX509KeyManager.java
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/java/common/src/main/java/org/apache/qpid/transport/network/security/ssl/QpidClientX509KeyManager.java?rev=926380&view=auto
==============================================================================
--- qpid/trunk/qpid/java/common/src/main/java/org/apache/qpid/transport/network/security/ssl/QpidClientX509KeyManager.java (added)
+++ qpid/trunk/qpid/java/common/src/main/java/org/apache/qpid/transport/network/security/ssl/QpidClientX509KeyManager.java Mon Mar 22 22:38:31 2010
@@ -0,0 +1,80 @@
+package org.apache.qpid.transport.network.security.ssl;
+
+import java.net.Socket;
+import java.security.KeyStore;
+import java.security.Principal;
+import java.security.PrivateKey;
+import java.security.cert.X509Certificate;
+
+import javax.net.ssl.KeyManagerFactory;
+import javax.net.ssl.SSLEngine;
+import javax.net.ssl.X509ExtendedKeyManager;
+
+import org.apache.qpid.transport.util.Logger;
+
+public class QpidClientX509KeyManager extends X509ExtendedKeyManager
+{
+    private static final Logger log = Logger.get(QpidClientX509KeyManager.class);
+    
+    X509ExtendedKeyManager delegate;
+    String alias;
+    
+    public QpidClientX509KeyManager(String alias, String keyStorePath,
+                           String keyStorePassword,String keyStoreCertType) throws Exception
+    {
+        this.alias = alias;    
+        KeyStore ks = SSLUtil.getInitializedKeyStore(keyStorePath,keyStorePassword);
+        KeyManagerFactory kmf = KeyManagerFactory.getInstance(keyStoreCertType);
+        kmf.init(ks, keyStorePassword.toCharArray());
+        this.delegate = (X509ExtendedKeyManager)kmf.getKeyManagers()[0];
+    }
+        
+    @Override
+    public String chooseClientAlias(String[] keyType, Principal[] issuers, Socket socket)
+    {
+        log.debug("chooseClientAlias:Returning alias " + alias);
+        return alias;
+    }
+
+    @Override
+    public String chooseServerAlias(String keyType, Principal[] issuers, Socket socket)
+    {
+        return delegate.chooseServerAlias(keyType, issuers, socket);
+    }
+
+    @Override
+    public X509Certificate[] getCertificateChain(String alias)
+    {
+        return delegate.getCertificateChain(alias);
+    }
+
+    @Override
+    public String[] getClientAliases(String keyType, Principal[] issuers)
+    {
+        log.debug("getClientAliases:Returning alias " + alias);
+        return new String[]{alias};
+    }
+
+    @Override
+    public PrivateKey getPrivateKey(String alias)
+    {
+        return delegate.getPrivateKey(alias);
+    }
+
+    @Override
+    public String[] getServerAliases(String keyType, Principal[] issuers)
+    {
+        return delegate.getServerAliases(keyType, issuers);
+    }
+    
+    public String chooseEngineClientAlias(String[] keyType, Principal[] issuers, SSLEngine engine)
+    {
+        log.debug("chooseEngineClientAlias:Returning alias " + alias);
+        return alias;
+    }
+    
+    public String chooseEngineServerAlias(String keyType, Principal[] issuers, SSLEngine engine) 
+    {
+        return delegate.chooseEngineServerAlias(keyType, issuers, engine);
+    }
+}

Modified: qpid/trunk/qpid/java/common/src/main/java/org/apache/qpid/transport/network/security/ssl/SSLUtil.java
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/java/common/src/main/java/org/apache/qpid/transport/network/security/ssl/SSLUtil.java?rev=926380&r1=926379&r2=926380&view=diff
==============================================================================
--- qpid/trunk/qpid/java/common/src/main/java/org/apache/qpid/transport/network/security/ssl/SSLUtil.java (original)
+++ qpid/trunk/qpid/java/common/src/main/java/org/apache/qpid/transport/network/security/ssl/SSLUtil.java Mon Mar 22 22:38:31 2010
@@ -1,5 +1,11 @@
 package org.apache.qpid.transport.network.security.ssl;
 
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.security.GeneralSecurityException;
+import java.security.KeyStore;
 import java.security.Principal;
 import java.security.cert.Certificate;
 import java.security.cert.X509Certificate;
@@ -63,7 +69,7 @@ public class SSLUtil
         StringBuffer id = new StringBuffer(); 
         try
         {
-          Certificate cert = engine.getSession().getPeerCertificates()[0];
+          Certificate cert = engine.getSession().getLocalCertificates()[0];
           Principal p = ((X509Certificate)cert).getSubjectDN();
           String dn = p.getName();
                     
@@ -101,15 +107,71 @@ public class SSLUtil
     
     public static SSLContext createSSLContext(ConnectionSettings settings) throws Exception
     {
+        SSLContextFactory sslContextFactory;
         
-        SSLContextFactory sslContextFactory = new SSLContextFactory(settings.getTrustStorePath(),
-                                                                    settings.getTrustStorePassword(),
-                                                                    settings.getTrustStoreCertType(),
-                                                                    settings.getKeyStorePath(),
-                                                                    settings.getKeyStorePassword(),
-                                                                    settings.getKeyStoreCertType());
-        
+        if (settings.getCertAlias() == null)
+        {
+            sslContextFactory = 
+                new SSLContextFactory(settings.getTrustStorePath(),
+                                      settings.getTrustStorePassword(),
+                                      settings.getTrustStoreCertType(),
+                                      settings.getKeyStorePath(),
+                                      settings.getKeyStorePassword(),
+                                      settings.getKeyStoreCertType());
+
+        } else
+        {
+            sslContextFactory = 
+                new SSLContextFactory(settings.getTrustStorePath(),
+                                      settings.getTrustStorePassword(),
+                                      settings.getTrustStoreCertType(),
+                    new QpidClientX509KeyManager(settings.getCertAlias(),
+                                                     settings.getKeyStorePath(),
+                                                     settings.getKeyStorePassword(),
+                                                     settings.getKeyStoreCertType()));
+            
+            log.debug("Using custom key manager");
+        }
+
         return sslContextFactory.buildServerContext();
         
     }
+    
+    public static KeyStore getInitializedKeyStore(String storePath, String storePassword) throws GeneralSecurityException, IOException
+    {
+        KeyStore ks = KeyStore.getInstance("JKS");
+        InputStream in = null;
+        try
+        {
+            File f = new File(storePath);
+            if (f.exists())
+            {
+                in = new FileInputStream(f);
+            }
+            else 
+            {
+                in = Thread.currentThread().getContextClassLoader().getResourceAsStream(storePath);
+            }
+            if (in == null)
+            {
+                throw new IOException("Unable to load keystore resource: " + storePath);
+            }
+            ks.load(in, storePassword.toCharArray());
+        }
+        finally
+        {
+            if (in != null)
+            {
+                //noinspection EmptyCatchBlock
+                try
+                {
+                    in.close();
+                }
+                catch (IOException ignored)
+                {
+                }
+            }
+        }
+        return ks;
+    }
 }

Modified: qpid/trunk/qpid/java/systests/src/main/java/org/apache/qpid/client/ssl/SSLTest.java
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/java/systests/src/main/java/org/apache/qpid/client/ssl/SSLTest.java?rev=926380&r1=926379&r2=926380&view=diff
==============================================================================
--- qpid/trunk/qpid/java/systests/src/main/java/org/apache/qpid/client/ssl/SSLTest.java (original)
+++ qpid/trunk/qpid/java/systests/src/main/java/org/apache/qpid/client/ssl/SSLTest.java Mon Mar 22 22:38:31 2010
@@ -6,10 +6,27 @@ import java.io.PrintStream;
 import javax.jms.Session;
 
 import org.apache.qpid.client.AMQConnection;
+import org.apache.qpid.client.AMQTestConnection_0_10;
 import org.apache.qpid.test.utils.QpidTestCase;
+import org.apache.qpid.transport.Connection;
 
 public class SSLTest extends QpidTestCase
 {      
+    
+    @Override
+    protected void setUp() throws Exception
+    {
+        System.setProperty("javax.net.debug", "ssl");
+        super.setUp();
+    }
+
+    @Override
+    protected void tearDown() throws Exception
+    {
+        System.setProperty("javax.net.debug", "");
+        super.tearDown();
+    }
+        
     public void testCreateSSLContextFromConnectionURLParams()
     {
         if (Boolean.getBoolean("profile.use_ssl"))
@@ -52,6 +69,32 @@ public class SSLTest extends QpidTestCas
             }
         }        
     }
+
+    public void testMultipleCertsInSingleStore() throws Exception
+    {
+        if (Boolean.getBoolean("profile.use_ssl"))
+        {
+            String url = "amqp://guest:guest@test/?brokerlist='tcp://localhost:" + 
+            System.getProperty("test.port.ssl") + 
+            "?ssl='true'&ssl_cert_alias='app1''";
+            
+            AMQTestConnection_0_10 con = new AMQTestConnection_0_10(url);      
+            Connection transportCon = con.getConnection();
+            String userID = transportCon.getSecurityLayer().getUserID();
+            assertEquals("The correct certificate was not choosen","app1@acme.org",userID);
+            con.close();
+            
+            url = "amqp://guest:guest@test/?brokerlist='tcp://localhost:" + 
+            System.getProperty("test.port.ssl") + 
+            "?ssl='true'&ssl_cert_alias='app2''";
+            
+            con = new AMQTestConnection_0_10(url);      
+            transportCon = con.getConnection();
+            userID = transportCon.getSecurityLayer().getUserID();
+            assertEquals("The correct certificate was not choosen","app2@acme.org",userID);
+            con.close();
+        }        
+    }
     
     public void testVerifyHostName()
     {



---------------------------------------------------------------------
Apache Qpid - AMQP Messaging Implementation
Project:      http://qpid.apache.org
Use/Interact: mailto:commits-subscribe@qpid.apache.org