From 37ba26b0345a53bf318a434e0a871019b27fa004 Mon Sep 17 00:00:00 2001 From: Shibi Date: Sat, 11 Feb 2017 19:37:45 -0800 Subject: [PATCH 1/2] SSLContext changes --- .../org/apache/qpid/proton/engine/SslDomain.java | 8 ++++++++ .../qpid/proton/engine/impl/ssl/SslDomainImpl.java | 13 +++++++++++++ .../engine/impl/ssl/SslEngineFacadeFactory.java | 3 +++ .../apache/qpid/proton/reactor/impl/IOHandler.java | 3 ++- 4 files changed, 26 insertions(+), 1 deletion(-) diff --git a/proton-j/src/main/java/org/apache/qpid/proton/engine/SslDomain.java b/proton-j/src/main/java/org/apache/qpid/proton/engine/SslDomain.java index 24b101c5e..0078144eb 100644 --- a/proton-j/src/main/java/org/apache/qpid/proton/engine/SslDomain.java +++ b/proton-j/src/main/java/org/apache/qpid/proton/engine/SslDomain.java @@ -18,6 +18,7 @@ */ package org.apache.qpid.proton.engine; +import javax.net.ssl.SSLContext; import org.apache.qpid.proton.engine.impl.ssl.SslDomainImpl; /** @@ -142,4 +143,11 @@ public enum VerifyMode void allowUnsecuredClient(boolean allowUnsecured); boolean allowUnsecuredClient(); + + /** + * set SSLContext + */ + void setSslcontext(SSLContext sslcontext); + + SSLContext getSslcontext(); } diff --git a/proton-j/src/main/java/org/apache/qpid/proton/engine/impl/ssl/SslDomainImpl.java b/proton-j/src/main/java/org/apache/qpid/proton/engine/impl/ssl/SslDomainImpl.java index 583e3cae9..73674fc1e 100644 --- a/proton-j/src/main/java/org/apache/qpid/proton/engine/impl/ssl/SslDomainImpl.java +++ b/proton-j/src/main/java/org/apache/qpid/proton/engine/impl/ssl/SslDomainImpl.java @@ -18,6 +18,8 @@ */ package org.apache.qpid.proton.engine.impl.ssl; +import javax.net.ssl.SSLContext; + import org.apache.qpid.proton.ProtonUnsupportedOperationException; import org.apache.qpid.proton.engine.ProtonJSslDomain; import org.apache.qpid.proton.engine.SslDomain; @@ -32,6 +34,7 @@ public class SslDomainImpl implements SslDomain, ProtonSslEngineProvider, Proton private String _privateKeyPassword; private String _trustedCaDb; private boolean _allowUnsecuredClient; + private SSLContext _sslcontext; private final SslEngineFacadeFactory _sslEngineFacadeFactory = new SslEngineFacadeFactory(); @@ -77,6 +80,16 @@ public String getTrustedCaDb() { return _trustedCaDb; } + + @Override + public void setSslcontext(SSLContext sslcontext){ + _sslcontext = sslcontext; + } + + @Override + public SSLContext getSslcontext(){ + return _sslcontext; + } @Override public void setPeerAuthentication(VerifyMode verifyMode) diff --git a/proton-j/src/main/java/org/apache/qpid/proton/engine/impl/ssl/SslEngineFacadeFactory.java b/proton-j/src/main/java/org/apache/qpid/proton/engine/impl/ssl/SslEngineFacadeFactory.java index f6346aa20..afd33a6e4 100644 --- a/proton-j/src/main/java/org/apache/qpid/proton/engine/impl/ssl/SslEngineFacadeFactory.java +++ b/proton-j/src/main/java/org/apache/qpid/proton/engine/impl/ssl/SslEngineFacadeFactory.java @@ -265,6 +265,9 @@ private SSLEngine createSslEngine(SSLContext sslContext, SslPeerDetails sslPeerD private SSLContext getOrCreateSslContext(SslDomain sslDomain) { + if(sslDomain.getSslcontext()!=null){ + _sslContext = sslDomain.getSslcontext(); + } if(_sslContext == null) { if(_logger.isLoggable(Level.FINE)) diff --git a/proton-j/src/main/java/org/apache/qpid/proton/reactor/impl/IOHandler.java b/proton-j/src/main/java/org/apache/qpid/proton/reactor/impl/IOHandler.java index 1282083de..b637bacdb 100644 --- a/proton-j/src/main/java/org/apache/qpid/proton/reactor/impl/IOHandler.java +++ b/proton-j/src/main/java/org/apache/qpid/proton/reactor/impl/IOHandler.java @@ -103,7 +103,8 @@ private void handleOpen(Reactor reactor, Event event) { Transport transport = Proton.transport(); Sasl sasl = transport.sasl(); sasl.client(); - sasl.setMechanisms("ANONYMOUS"); + //sasl.setMechanisms("ANONYMOUS"); + sasl.setMechanisms("EXTERNAL"); transport.bind(connection); } From 685d304836c628775728b1edd5119fb5916cb32c Mon Sep 17 00:00:00 2001 From: Shibi Date: Wed, 15 Feb 2017 11:44:57 -0800 Subject: [PATCH 2/2] SSLContext changes. --- .../apache/qpid/proton/engine/SslDomain.java | 8 +- .../proton/engine/impl/ssl/SslDomainImpl.java | 11 +- .../qpid/proton/reactor/impl/IOHandler.java | 3 +- .../impl/ssl/DummySslContextFactory.java | 450 ++++++++++++++++++ .../impl/ssl/SslEngineFacadeFactoryTest.java | 28 +- 5 files changed, 491 insertions(+), 9 deletions(-) create mode 100644 proton-j/src/test/java/org/apache/qpid/proton/engine/impl/ssl/DummySslContextFactory.java diff --git a/proton-j/src/main/java/org/apache/qpid/proton/engine/SslDomain.java b/proton-j/src/main/java/org/apache/qpid/proton/engine/SslDomain.java index 0078144eb..7fafae1a3 100644 --- a/proton-j/src/main/java/org/apache/qpid/proton/engine/SslDomain.java +++ b/proton-j/src/main/java/org/apache/qpid/proton/engine/SslDomain.java @@ -145,9 +145,15 @@ public enum VerifyMode boolean allowUnsecuredClient(); /** - * set SSLContext + * The method allows SSLContext to be provided and will override any other configuration that might have otherwise been used to create a context. + * + *@param sslcontext provided to proton-j layer */ void setSslcontext(SSLContext sslcontext); + /** + * Returns the SSLContext set by the setter. + * @return + */ SSLContext getSslcontext(); } diff --git a/proton-j/src/main/java/org/apache/qpid/proton/engine/impl/ssl/SslDomainImpl.java b/proton-j/src/main/java/org/apache/qpid/proton/engine/impl/ssl/SslDomainImpl.java index 73674fc1e..56655fb81 100644 --- a/proton-j/src/main/java/org/apache/qpid/proton/engine/impl/ssl/SslDomainImpl.java +++ b/proton-j/src/main/java/org/apache/qpid/proton/engine/impl/ssl/SslDomainImpl.java @@ -19,7 +19,6 @@ package org.apache.qpid.proton.engine.impl.ssl; import javax.net.ssl.SSLContext; - import org.apache.qpid.proton.ProtonUnsupportedOperationException; import org.apache.qpid.proton.engine.ProtonJSslDomain; import org.apache.qpid.proton.engine.SslDomain; @@ -82,13 +81,15 @@ public String getTrustedCaDb() } @Override - public void setSslcontext(SSLContext sslcontext){ - _sslcontext = sslcontext; + public void setSslcontext(SSLContext sslcontext) + { + _sslcontext = sslcontext; } @Override - public SSLContext getSslcontext(){ - return _sslcontext; + public SSLContext getSslcontext() + { + return _sslcontext; } @Override diff --git a/proton-j/src/main/java/org/apache/qpid/proton/reactor/impl/IOHandler.java b/proton-j/src/main/java/org/apache/qpid/proton/reactor/impl/IOHandler.java index b637bacdb..1282083de 100644 --- a/proton-j/src/main/java/org/apache/qpid/proton/reactor/impl/IOHandler.java +++ b/proton-j/src/main/java/org/apache/qpid/proton/reactor/impl/IOHandler.java @@ -103,8 +103,7 @@ private void handleOpen(Reactor reactor, Event event) { Transport transport = Proton.transport(); Sasl sasl = transport.sasl(); sasl.client(); - //sasl.setMechanisms("ANONYMOUS"); - sasl.setMechanisms("EXTERNAL"); + sasl.setMechanisms("ANONYMOUS"); transport.bind(connection); } diff --git a/proton-j/src/test/java/org/apache/qpid/proton/engine/impl/ssl/DummySslContextFactory.java b/proton-j/src/test/java/org/apache/qpid/proton/engine/impl/ssl/DummySslContextFactory.java new file mode 100644 index 000000000..7e29b7198 --- /dev/null +++ b/proton-j/src/test/java/org/apache/qpid/proton/engine/impl/ssl/DummySslContextFactory.java @@ -0,0 +1,450 @@ +/* + * + * 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.qpid.proton.engine.impl.ssl; + +import java.io.Closeable; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.FileReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.Reader; +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.security.KeyManagementException; +import java.security.KeyPair; +import java.security.KeyStore; +import java.security.KeyStoreException; +import java.security.NoSuchAlgorithmException; +import java.security.PrivateKey; +import java.security.Provider; +import java.security.Security; +import java.security.UnrecoverableKeyException; +import java.security.cert.Certificate; +import java.security.cert.CertificateException; +import java.security.cert.CertificateFactory; +import java.security.cert.X509Certificate; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.logging.Level; +import java.util.logging.Logger; + +import javax.net.ssl.KeyManagerFactory; +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLEngine; +import javax.net.ssl.TrustManager; +import javax.net.ssl.TrustManagerFactory; +import javax.net.ssl.X509TrustManager; + +import org.apache.qpid.proton.engine.SslDomain; +import org.apache.qpid.proton.engine.SslPeerDetails; +import org.apache.qpid.proton.engine.TransportException; + +/** + * Creates dummy SSLContext for unit testing + */ +public class DummySslContextFactory +{ + private static final Logger _logger = Logger.getLogger(DummySslContextFactory.class.getName()); + private static final String TLS_PROTOCOL = "TLS"; + + // BouncyCastle Reflection Helpers + private static final Constructor pemParserCons; + private static final Method pemReadMethod; + + private static final Constructor JcaPEMKeyConverterCons; + private static final Class PEMKeyPairClass; + private static final Method getKeyPairMethod; + private static final Method getPrivateKeyMethod; + + private static final Class PEMEncryptedKeyPairClass; + private static final Method decryptKeyPairMethod; + + private static final Constructor JcePEMDecryptorProviderBuilderCons; + private static final Method builderMethod; + + private static final Class PrivateKeyInfoClass; + private static final Exception bouncyCastleSetupException; + + static + { + // Setup BouncyCastle Reflection artifacts + Constructor pemParserConsResult = null; + Method pemReadMethodResult = null; + Constructor JcaPEMKeyConverterConsResult = null; + Class PEMKeyPairClassResult = null; + Method getKeyPairMethodResult = null; + Method getPrivateKeyMethodResult = null; + Class PEMEncryptedKeyPairClassResult = null; + Method decryptKeyPairMethodResult = null; + Constructor JcePEMDecryptorProviderBuilderConsResult = null; + Method builderMethodResult = null; + Class PrivateKeyInfoClassResult = null; + Exception bouncyCastleSetupExceptionResult = null; + + try + { + final Class pemParserClass = Class.forName("org.bouncycastle.openssl.PEMParser"); + pemParserConsResult = pemParserClass.getConstructor(Reader.class); + pemReadMethodResult = pemParserClass.getMethod("readObject"); + + final Class jcaPEMKeyConverterClass = Class.forName("org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter"); + JcaPEMKeyConverterConsResult = jcaPEMKeyConverterClass.getConstructor(); + PEMKeyPairClassResult = Class.forName("org.bouncycastle.openssl.PEMKeyPair"); + getKeyPairMethodResult = jcaPEMKeyConverterClass.getMethod("getKeyPair", PEMKeyPairClassResult); + + final Class PEMDecrypterProvider = Class.forName("org.bouncycastle.openssl.PEMDecryptorProvider"); + + PEMEncryptedKeyPairClassResult = Class.forName("org.bouncycastle.openssl.PEMEncryptedKeyPair"); + decryptKeyPairMethodResult = PEMEncryptedKeyPairClassResult.getMethod("decryptKeyPair", PEMDecrypterProvider); + + final Class jcePEMDecryptorProviderBuilderClass = Class.forName( + "org.bouncycastle.openssl.jcajce.JcePEMDecryptorProviderBuilder"); + JcePEMDecryptorProviderBuilderConsResult = jcePEMDecryptorProviderBuilderClass.getConstructor(); + builderMethodResult = jcePEMDecryptorProviderBuilderClass.getMethod("build", char[].class); + + PrivateKeyInfoClassResult = Class.forName("org.bouncycastle.asn1.pkcs.PrivateKeyInfo"); + getPrivateKeyMethodResult = jcaPEMKeyConverterClass.getMethod("getPrivateKey", PrivateKeyInfoClassResult); + + // Try loading BC as a provider + Class klass = Class.forName("org.bouncycastle.jce.provider.BouncyCastleProvider"); + Provider provider = (Provider) klass.getConstructor().newInstance(); + Security.addProvider(provider); + } + catch (Exception e) + { + bouncyCastleSetupExceptionResult = e; + } + finally { + pemParserCons = pemParserConsResult; + pemReadMethod = pemReadMethodResult; + JcaPEMKeyConverterCons = JcaPEMKeyConverterConsResult; + PEMKeyPairClass = PEMKeyPairClassResult; + getKeyPairMethod = getKeyPairMethodResult; + getPrivateKeyMethod = getPrivateKeyMethodResult; + PEMEncryptedKeyPairClass = PEMEncryptedKeyPairClassResult; + decryptKeyPairMethod = decryptKeyPairMethodResult; + JcePEMDecryptorProviderBuilderCons = JcePEMDecryptorProviderBuilderConsResult; + builderMethod = builderMethodResult; + PrivateKeyInfoClass = PrivateKeyInfoClassResult; + bouncyCastleSetupException = bouncyCastleSetupExceptionResult; + } + } + + DummySslContextFactory() + { + } + + /** + * This is a list of all anonymous cipher suites supported by Java 6, excluding those that + * use MD5. These are all supported by both Oracle's and IBM's Java 6 implementation. + */ + private static final List ANONYMOUS_CIPHER_SUITES = Arrays.asList( + "TLS_DH_anon_WITH_AES_128_CBC_SHA", + "SSL_DH_anon_WITH_3DES_EDE_CBC_SHA", + "SSL_DH_anon_WITH_DES_CBC_SHA", + "SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA"); + + /** lazily initialized */ + private SSLContext _sslContext; + + + /** + * Guarantees that no cached settings are used in subsequent calls to + * {@link #createProtonSslEngine(SslDomain, SslPeerDetails)}. + */ + public void resetCache() + { + _sslContext = null; + } + + /** + * creates sslcontext + * @param sslDomain + * @return + */ + public SSLContext getOrCreateSslContext(SslDomain sslDomain) + { + if(sslDomain.getSslcontext()!=null){ + _sslContext = sslDomain.getSslcontext(); + } + if(_sslContext == null) + { + if(_logger.isLoggable(Level.FINE)) + { + _logger.fine("lazily creating new SSLContext using domain " + sslDomain); + } + + final char[] dummyPassword = "unused-passphrase".toCharArray(); // Dummy password required by KeyStore and KeyManagerFactory, but never referred to again + + try + { + SSLContext sslContext = SSLContext.getInstance(TLS_PROTOCOL); + KeyStore ksKeys = createKeyStoreFrom(sslDomain, dummyPassword); + + KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); + kmf.init(ksKeys, dummyPassword); + + final TrustManager[] trustManagers; + if (sslDomain.getPeerAuthentication() == SslDomain.VerifyMode.ANONYMOUS_PEER) + { + trustManagers = new TrustManager[] { new AlwaysTrustingTrustManager() }; + } + else + { + TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); + tmf.init(ksKeys); + trustManagers = tmf.getTrustManagers(); + } + + sslContext.init(kmf.getKeyManagers(), trustManagers, null); + _sslContext = sslContext; + } + catch (NoSuchAlgorithmException e) + { + throw new TransportException("Unexpected exception creating SSLContext", e); + } + catch (KeyStoreException e) + { + throw new TransportException("Unexpected exception creating SSLContext", e); + } + catch (UnrecoverableKeyException e) + { + throw new TransportException("Unexpected exception creating SSLContext", e); + } + catch (KeyManagementException e) + { + throw new TransportException("Unexpected exception creating SSLContext", e); + } + } + return _sslContext; + } + + private KeyStore createKeyStoreFrom(SslDomain sslDomain, char[] dummyPassword) + { + try + { + KeyStore keystore = KeyStore.getInstance(KeyStore.getDefaultType()); + keystore.load(null, null); + + if (sslDomain.getTrustedCaDb() != null) + { + String caCertAlias = "cacert"; + + if(_logger.isLoggable(Level.FINE)) + { + _logger.log(Level.FINE, "_sslParams.getTrustedCaDb() : " + sslDomain.getTrustedCaDb()); + } + Certificate trustedCaCert = readCertificate(sslDomain.getTrustedCaDb()); + keystore.setCertificateEntry(caCertAlias, trustedCaCert); + } + + if (sslDomain.getCertificateFile() != null + && sslDomain.getPrivateKeyFile() != null) + { + String clientPrivateKeyAlias = "clientPrivateKey"; + + Certificate clientCertificate = (Certificate) readCertificate(sslDomain.getCertificateFile()); + PrivateKey clientPrivateKey = readPrivateKey(sslDomain.getPrivateKeyFile(), sslDomain.getPrivateKeyPassword()); + + keystore.setKeyEntry(clientPrivateKeyAlias, clientPrivateKey, + dummyPassword, new Certificate[] { clientCertificate }); + } + + return keystore; + } + catch (KeyStoreException e) + { + throw new TransportException("Unexpected exception creating keystore", e); + } + catch (NoSuchAlgorithmException e) + { + throw new TransportException("Unexpected exception creating keystore", e); + } + catch (CertificateException e) + { + throw new TransportException("Unexpected exception creating keystore", e); + } + catch (IOException e) + { + throw new TransportException("Unexpected exception creating keystore", e); + } + } + + + + + Certificate readCertificate(String pemFile) + { + InputStream is = null; + + try + { + CertificateFactory cFactory = CertificateFactory.getInstance("X.509"); + is = new FileInputStream(pemFile); + return cFactory.generateCertificate(is); + } + catch (CertificateException ce) + { + String msg = "Failed to load certificate [" + pemFile + "]"; + _logger.log(Level.SEVERE, msg, ce); + throw new TransportException(msg, ce); + } + catch (FileNotFoundException e) + { + String msg = "Certificate file not found [" + pemFile + "]"; + _logger.log(Level.SEVERE, msg); + throw new TransportException(msg, e); + } + finally + { + closeSafely(is); + } + } + + PrivateKey readPrivateKey(String pemFile, String password) + { + if (bouncyCastleSetupException != null) + { + throw new TransportException("BouncyCastle failed to load", bouncyCastleSetupException); + } + + final Object pemObject = readPemObject(pemFile); + PrivateKey privateKey = null; + + try + { + Object keyConverter = JcaPEMKeyConverterCons.newInstance(); + setProvider(keyConverter, "BC"); + + if (PEMEncryptedKeyPairClass.isInstance(pemObject)) + { + Object decryptorBuilder = JcePEMDecryptorProviderBuilderCons.newInstance(); + + // Build a PEMDecryptProvider + Object decryptProvider = builderMethod.invoke(decryptorBuilder, password.toCharArray()); + + Object decryptedKeyPair = decryptKeyPairMethod.invoke(pemObject, decryptProvider); + KeyPair keyPair = (KeyPair) getKeyPairMethod.invoke(keyConverter, decryptedKeyPair); + + privateKey = keyPair.getPrivate(); + } + else if (PEMKeyPairClass.isInstance(pemObject)) + { + // It's a KeyPair but not encrypted. + KeyPair keyPair = (KeyPair) getKeyPairMethod.invoke(keyConverter, pemObject); + privateKey = keyPair.getPrivate(); + } + else if (PrivateKeyInfoClass.isInstance(pemObject)) + { + // It's an unencrypted private key + privateKey = (PrivateKey) getPrivateKeyMethod.invoke(keyConverter, pemObject); + } + else + { + final String msg = "Unable to load PrivateKey, Unpexected Object [" + pemObject.getClass().getName() + + "]"; + _logger.log(Level.SEVERE, msg); + throw new TransportException(msg); + } + } + catch (InstantiationException | IllegalAccessException | IllegalArgumentException + | InvocationTargetException | NoSuchMethodException | SecurityException e) + { + final String msg = "Failed to process key file [" + pemFile + "] - " + e.getMessage(); + throw new TransportException(msg, e); + } + + return privateKey; + } + + private Object readPemObject(String pemFile) + { + Reader reader = null; + Object pemParser = null; + Object pemObject = null; + + try + { + reader = new FileReader(pemFile); + pemParser = pemParserCons.newInstance(reader); // = new PEMParser(reader); + pemObject = pemReadMethod.invoke(pemParser); // = pemParser.readObject(); + } + catch (IOException | IllegalAccessException | IllegalArgumentException | InvocationTargetException | InstantiationException e) + { + _logger.log(Level.SEVERE, "Unable to read PEM object. Perhaps you need the unlimited strength libraries in /jre/lib/security/ ?", e); + throw new TransportException("Unable to read PEM object from file " + pemFile, e); + } + finally + { + closeSafely(reader); + } + + return pemObject; + } + + private void setProvider(Object obj, String provider) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException + { + final Class aClz = obj.getClass(); + final Method setProvider = aClz.getMethod("setProvider", String.class); + setProvider.invoke(obj, provider); + } + + private void closeSafely(Closeable c) + { + if (c != null) + { + try + { + c.close(); + } + catch (IOException e) + { + // Swallow + } + } + } + + private static final class AlwaysTrustingTrustManager implements X509TrustManager + { + @Override + public X509Certificate[] getAcceptedIssuers() + { + return null; + } + + @Override + public void checkServerTrusted(X509Certificate[] arg0, String arg1) + throws CertificateException + { + // Do not check certificate + } + + @Override + public void checkClientTrusted(X509Certificate[] arg0, String arg1) + throws CertificateException + { + // Do not check certificate + } + } +} diff --git a/proton-j/src/test/java/org/apache/qpid/proton/engine/impl/ssl/SslEngineFacadeFactoryTest.java b/proton-j/src/test/java/org/apache/qpid/proton/engine/impl/ssl/SslEngineFacadeFactoryTest.java index 84ba8cb90..ff9478cc1 100644 --- a/proton-j/src/test/java/org/apache/qpid/proton/engine/impl/ssl/SslEngineFacadeFactoryTest.java +++ b/proton-j/src/test/java/org/apache/qpid/proton/engine/impl/ssl/SslEngineFacadeFactoryTest.java @@ -21,9 +21,14 @@ import static org.junit.Assert.assertNotNull; import java.net.URL; +import java.security.NoSuchAlgorithmException; -import org.junit.Test; +import javax.net.ssl.SSLContext; +import org.apache.qpid.proton.engine.SslDomain; +import org.apache.qpid.proton.engine.SslPeerDetails; +import org.junit.Test; +import static org.mockito.Mockito.mock; public class SslEngineFacadeFactoryTest { private static final String PASSWORD = "unittest"; @@ -59,6 +64,27 @@ public void testLoadUnencryptedPKCS8PrivateKey(){ assertNotNull("Key was NULL", factory.readPrivateKey(keyFile, null)); } + + @Test + public void testSSLContext(){ + String certFile = resolveFilename("cert.pem.txt"); + String keyFile = resolveFilename("private-key-clear.pem.txt"); + //sslDomain object + SslDomain domain=SslDomain.Factory.create(); + domain.setCredentials(certFile, keyFile, null); + //Dummy SSLContext + DummySslContextFactory dummySSLContext = new DummySslContextFactory(); + SSLContext sslContext=dummySSLContext.getOrCreateSslContext(domain); + //set SSLContext in SslDomainObject + domain.setSslcontext(sslContext); + + SslEngineFacadeFactory factory = new SslEngineFacadeFactory(); + //Ensure sslEngine is created with the provided SSLContext + ProtonSslEngine sslEngine= factory.createProtonSslEngine(domain, SslPeerDetails.Factory.create("127.0.0.1",1)); + + //Verify sslEngine is created with provided SSLContext + assertNotNull("Cant create SSLEngine with provided Context", sslEngine); + } private String resolveFilename(String testFilename) { URL resourceUri = this.getClass().getResource(testFilename);