From da1987a98b49c447e5e0f8e94f74228b87f485ca Mon Sep 17 00:00:00 2001 From: Florian Schmaus Date: Tue, 26 Feb 2013 08:44:17 +0000 Subject: [PATCH] SMACK-376 Allow supplying a custom SSLContext for encrypted connections. The provided TrustManager / SSLContext implementation is very flexible, but it does not allow to query the user about accepting possibly invalid SSL certificates. By supplying a custom SSLContext with a TrustManager implementing such a query mechanism it is possible to implement this behaviour. The patch adds ConnectionConfiguration.customSSLContext with appropriate getter/setter methods and uses the custom context in XMPPConnection. Signed-Off-By: Georg Lukas git-svn-id: http://svn.igniterealtime.org/svn/repos/smack/trunk@13520 b35dd754-fafc-0310-a699-88a17e54d16e --- .../smack/ConnectionConfiguration.java | 21 +++++++++++++++++++ .../jivesoftware/smack/XMPPConnection.java | 12 ++++++----- 2 files changed, 28 insertions(+), 5 deletions(-) diff --git a/source/org/jivesoftware/smack/ConnectionConfiguration.java b/source/org/jivesoftware/smack/ConnectionConfiguration.java index bc5dbabde..24389ac6f 100644 --- a/source/org/jivesoftware/smack/ConnectionConfiguration.java +++ b/source/org/jivesoftware/smack/ConnectionConfiguration.java @@ -24,6 +24,7 @@ import org.jivesoftware.smack.proxy.ProxyInfo; import org.jivesoftware.smack.util.DNSUtil; import javax.net.SocketFactory; +import javax.net.ssl.SSLContext; import javax.security.auth.callback.CallbackHandler; import java.io.File; @@ -59,6 +60,7 @@ public class ConnectionConfiguration implements Cloneable { private boolean selfSignedCertificateEnabled = false; private boolean expiredCertificatesCheckEnabled = false; private boolean notMatchingDomainCheckEnabled = false; + private SSLContext customSSLContext; private boolean compressionEnabled = false; @@ -486,6 +488,25 @@ public class ConnectionConfiguration implements Cloneable { this.notMatchingDomainCheckEnabled = notMatchingDomainCheckEnabled; } + /** + * Gets the custom SSLContext for SSL sockets. This is null by default. + * + * @return the SSLContext previously set with setCustomSSLContext() or null. + */ + public SSLContext getCustomSSLContext() { + return this.customSSLContext; + } + + /** + * Sets a custom SSLContext for creating SSL sockets. A custom Context causes all other + * SSL/TLS realted settings to be ignored. + * + * @param context the custom SSLContext for new sockets; null to reset default behavior. + */ + public void setCustomSSLContext(SSLContext context) { + this.customSSLContext = context; + } + /** * Returns true if the connection is going to use stream compression. Stream compression * will be requested after TLS was established (if TLS was enabled) and only if the server diff --git a/source/org/jivesoftware/smack/XMPPConnection.java b/source/org/jivesoftware/smack/XMPPConnection.java index b91aba3da..86aa5ad74 100644 --- a/source/org/jivesoftware/smack/XMPPConnection.java +++ b/source/org/jivesoftware/smack/XMPPConnection.java @@ -763,14 +763,14 @@ public class XMPPConnection extends Connection { * @throws Exception if an exception occurs. */ void proceedTLSReceived() throws Exception { - SSLContext context = SSLContext.getInstance("TLS"); + SSLContext context = this.config.getCustomSSLContext(); KeyStore ks = null; KeyManager[] kms = null; PasswordCallback pcb = null; if(config.getCallbackHandler() == null) { ks = null; - } else { + } else if (context == null) { //System.out.println("Keystore type: "+configuration.getKeystoreType()); if(config.getKeystoreType().equals("NONE")) { ks = null; @@ -826,9 +826,11 @@ public class XMPPConnection extends Connection { } // Verify certificate presented by the server - context.init(kms, - new javax.net.ssl.TrustManager[]{new ServerTrustManager(getServiceName(), config)}, - new java.security.SecureRandom()); + if (context == null) { + context = SSLContext.getInstance("TLS"); + context.init(kms, new javax.net.ssl.TrustManager[] { new ServerTrustManager(getServiceName(), config) }, + new java.security.SecureRandom()); + } Socket plain = socket; // Secure the plain connection socket = context.getSocketFactory().createSocket(plain,