Unable to detect failure to connect

I’m trying to set up a TLS-only connection but I’m having trouble detecting the failure case.

Specifically, I’m unable to detect when a connection fails due to the presence of a self-signed certificate on the server.

Using smack 3.2.0

Here’s my test application:

package smacktest; import org.jivesoftware.smack.Connection;
import org.jivesoftware.smack.ConnectionConfiguration;
import org.jivesoftware.smack.XMPPConnection; public class SmackTest {
    public static void main(String[] args) throws Exception {
        ConnectionConfiguration conf = new ConnectionConfiguration("myserver", 5222, "mydomain");
        conf.setSecurityMode(ConnectionConfiguration.SecurityMode.required);
        conf.setSelfSignedCertificateEnabled(false);
        conf.setVerifyChainEnabled(true);
        conf.setVerifyRootCAEnabled(true);         Connection conn = new XMPPConnection(conf);         System.out.println("Connecting...");
        conn.connect();
        if (conn.isConnected()) {
            System.out.println("Connected");             System.out.println("Logging in...");
            conn.login("byron", "foobar12", "smacktest");
            System.out.println("Login successful");             conn.disconnect();
        } else {
            System.out.println("Connection failed");
        }
    }
}

And here’s the output:

Connecting...
javax.net.ssl.SSLHandshakeException: java.security.cert.CertificateException: root certificate not trusted of [lancelot]
    at com.sun.net.ssl.internal.ssl.Alerts.getSSLException(Alerts.java:174)
    at com.sun.net.ssl.internal.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1649)
    at com.sun.net.ssl.internal.ssl.Handshaker.fatalSE(Handshaker.java:241)
    at com.sun.net.ssl.internal.ssl.Handshaker.fatalSE(Handshaker.java:235)
    at com.sun.net.ssl.internal.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1206)
    at com.sun.net.ssl.internal.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:136)
    at com.sun.net.ssl.internal.ssl.Handshaker.processLoop(Handshaker.java:593)
    at com.sun.net.ssl.internal.ssl.Handshaker.process_record(Handshaker.java:529)
    at com.sun.net.ssl.internal.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:893)
    at com.sun.net.ssl.internal.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1138)
    at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1165)
    at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1149)
    at org.jivesoftware.smack.XMPPConnection.proceedTLSReceived(XMPPConnection.java:806)
    at org.jivesoftware.smack.PacketReader.parsePackets(PacketReader.java:267)
    at org.jivesoftware.smack.PacketReader.access$000(PacketReader.java:43)
    at org.jivesoftware.smack.PacketReader$1.run(PacketReader.java:70)
Caused by: java.security.cert.CertificateException: root certificate not trusted of [lancelot]
    at org.jivesoftware.smack.ServerTrustManager.checkServerTrusted(ServerTrustManager.java:144)
    at com.sun.net.ssl.internal.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1198)
    ... 11 more
Connected
Logging in...
Exception in thread "main" No response from the server.:     at org.jivesoftware.smack.NonSASLAuthentication.authenticate(NonSASLAuthentication.java:73)
    at org.jivesoftware.smack.SASLAuthentication.authenticate(SASLAuthentication.java:352)
    at org.jivesoftware.smack.XMPPConnection.login(XMPPConnection.java:203)
    at smacktest.SmackTest.main(SmackTest.java:23)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:120) Process finished with exit code 1

Note that my conn.isConnected() guard is passing, despire the (correct) failure to log in connect.

For reference, “myserver” is a secondary box running Openfire 3.7.0 with a self-signed certificate.

Now I do see a work-around here in that I can catch XMPPException on the login call, but I’d really like to fail right on conn.connect()

Am I doing something wrong or have I found a defect?

Edit: I confused login and connect in my description