I've been working on an Android client using Smack 4.1.0-rc1 (4.0.6-518-g8a32d22 2015-02-15) that would connect to our private XMPP server (running OpenFire 3.9.3) using a self-signed certificate. I've followed instructions here for reading our certificate file as a raw file and adding it to a KeyStore and then creating a TrustManager and SSLContext based on it:
SSLContext sslContext = null; try { // Load CAs from an InputStream. CertificateFactory cf = CertificateFactory.getInstance("X.509"); InputStream inputStream = context.getResources().openRawResource(R.raw.xmpp); BufferedInputStream caInput = new BufferedInputStream(inputStream); Certificate ca; try { ca = cf.generateCertificate(caInput); System.out.println("ca=" + ((X509Certificate) ca).getSubjectDN()); } finally { caInput.close(); } // Create a KeyStore containing our trusted CAs. String keyStoreType = KeyStore.getDefaultType(); KeyStore keyStore = KeyStore.getInstance(keyStoreType); keyStore.load(null, null); keyStore.setCertificateEntry("ca", ca); // Create a TrustManager that trusts the CAs in our KeyStore. String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm(); TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlgorithm); tmf.init(keyStore); // Create an SSLContext that uses our TrustManager. sslContext = SSLContext.getInstance("TLS"); sslContext.init(null, tmf.getTrustManagers(), new SecureRandom()); } catch (CertificateException e) { Log.e("XmppManager", e.getMessage()); } catch (IOException e) { Log.e("XmppManager", e.getMessage()); } catch (KeyStoreException e) { Log.e("XmppManager", e.getMessage()); } catch (NoSuchAlgorithmException e) { Log.e("XmppManager", e.getMessage()); } catch (KeyManagementException e) { Log.e("XmppManager", e.getMessage()); }
Then using the new SSLContext object, I set the SocketFactory in my ConnectionConfiguration and attempt connect to our private XMPP server:
XMPPTCPConnectionConfiguration configuration = XMPPTCPConnectionConfiguration.builder() .setUsernameAndPassword(username, password) .setServiceName(serviceName) .setSocketFactory(sslContext.getSocketFactory()) .build(); connection = new XMPPTCPConnection(configuration); try { Log.d("XmppManager", "Connecting to XMPP server..."); connection.connect(); Log.d("XmppManager", "Connected to XMPP server!"); if (!connection.isAuthenticated()) { Log.d("XmppManager", "Authenticating with XMPP server..."); connection.login(); Log.d("XmppManager", "Authenticated with XMPP server!"); } } catch (XMPPException e) { e.printStackTrace(); } catch (SmackException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); }
I get the following error message and stack trace:
02-25 14:57:48.079 9499-9513/com.drg.ageon D/XmppManager﹕ Connecting to XMPP server... 02-25 14:57:48.179 9499-9513/com.drg.ageon W/System.err﹕ javax.net.ssl.SSLHandshakeException: javax.net.ssl.SSLProtocolException: SSL handshake aborted: ssl=0x5c3d3f90: Failure in SSL library, usually a protocol error 02-25 14:57:48.179 9499-9513/com.drg.ageon W/System.err﹕ error:140770FC:SSL routines:SSL23_GET_SERVER_HELLO:unknown protocol (external/openssl/ssl/s23_clnt.c:766 0x59307b5a:0x00000000) 02-25 14:57:48.179 9499-9513/com.drg.ageon W/System.err﹕ at org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:420) 02-25 14:57:48.179 9499-9513/com.drg.ageon W/System.err﹕ at org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl$SSLInputStream.<init>(OpenSSLSocketImpl.java:636) 02-25 14:57:48.179 9499-9513/com.drg.ageon W/System.err﹕ at org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl.getInputStream(OpenSSLSocketImpl.java:607) 02-25 14:57:48.179 9499-9513/com.drg.ageon W/System.err﹕ at org.jivesoftware.smack.tcp.XMPPTCPConnection.initReaderAndWriter(XMPPTCPConnection.java:620) 02-25 14:57:48.179 9499-9513/com.drg.ageon W/System.err﹕ at org.jivesoftware.smack.tcp.XMPPTCPConnection.initConnection(XMPPTCPConnection.java:590) 02-25 14:57:48.179 9499-9513/com.drg.ageon W/System.err﹕ at org.jivesoftware.smack.tcp.XMPPTCPConnection.connectInternal(XMPPTCPConnection.java:812) 02-25 14:57:48.179 9499-9513/com.drg.ageon W/System.err﹕ at org.jivesoftware.smack.AbstractXMPPConnection.connect(AbstractXMPPConnection.java:397) 02-25 14:57:48.179 9499-9513/com.drg.ageon W/System.err﹕ at com.drg.ageon.xmpp.XmppManager.connect(XmppManager.java:110) 02-25 14:57:48.179 9499-9513/com.drg.ageon W/System.err﹕ at com.drg.ageon.app.MainActivity$XmppConnectTask.doInBackground(MainActivity.java:276) 02-25 14:57:48.179 9499-9513/com.drg.ageon W/System.err﹕ at com.drg.ageon.app.MainActivity$XmppConnectTask.doInBackground(MainActivity.java:263) 02-25 14:57:48.179 9499-9513/com.drg.ageon W/System.err﹕ at android.os.AsyncTask$2.call(AsyncTask.java:287) 02-25 14:57:48.179 9499-9513/com.drg.ageon W/System.err﹕ at java.util.concurrent.FutureTask.run(FutureTask.java:234) 02-25 14:57:48.184 9499-9513/com.drg.ageon W/System.err﹕ at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:230) 02-25 14:57:48.184 9499-9513/com.drg.ageon W/System.err﹕ at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1080) 02-25 14:57:48.184 9499-9513/com.drg.ageon W/System.err﹕ at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:573) 02-25 14:57:48.184 9499-9513/com.drg.ageon W/System.err﹕ at java.lang.Thread.run(Thread.java:856) 02-25 14:57:48.184 9499-9513/com.drg.ageon W/System.err﹕ Caused by: javax.net.ssl.SSLProtocolException: SSL handshake aborted: ssl=0x5c3d3f90: Failure in SSL library, usually a protocol error 02-25 14:57:48.184 9499-9513/com.drg.ageon W/System.err﹕ error:140770FC:SSL routines:SSL23_GET_SERVER_HELLO:unknown protocol (external/openssl/ssl/s23_clnt.c:766 0x59307b5a:0x00000000) 02-25 14:57:48.184 9499-9513/com.drg.ageon W/System.err﹕ at org.apache.harmony.xnet.provider.jsse.NativeCrypto.SSL_do_handshake(Native Method) 02-25 14:57:48.189 9499-9513/com.drg.ageon W/System.err﹕ at org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:378) 02-25 14:57:48.189 9499-9513/com.drg.ageon W/System.err﹕ ... 15 more
Anybody have any insight on what could possibly be wrong? I have been able to connect to our private XMPP server via other clients such as Pidgin and Spark. This leads me to believe that there may be something faulty in our self-signed certificate, or my self-certificate implementation on the Android client, or both.
Any help would be greatly appreciated!