Search code examples
javaandroidsslxmppsmack

Smack: "Trust anchor for certification path not found"


I'm trying to connect from Android to a Apache Vysper XMPP server in localhost. I'm using Smack framework to perform XMPP operations:

AbstractXMPPConnection connection = new XMPPTCPConnection("bigdestroyer", "", ip);
  try {
      connection.setPacketReplyTimeout(10000);        
      connection.connect();
  } catch (SmackException e) {
      e.printStackTrace();
  } catch (IOException e) {
      e.printStackTrace();
  } catch (XMPPException e) {
      e.printStackTrace();
  }

But I get this error:

javax.net.ssl.SSLHandshakeException: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.

I guess it is related to SSL certificate but I don't know what I have to do. Can you help me?

I have tried to put cert file (the same as the server has) in assets folder and create the connection this way:

  XMPPTCPConnectionConfiguration connectionConfiguration = configuration.setConnectTimeout(10000)
                    .setUsernameAndPassword("admin", "admin")
                    .setHost(ip)
                    .setServiceName(ip)
                    .setKeystorePath("file:///android_asset/bogus_mina_tls.cert")
                    .build();

XMPPTCPConnection connection = new XMPPTCPConnection(connectionConfiguration);

But it still doesn't work. Any suggestion?


Solution

  • The KeystorePath should point to a Keystore, not a simple certificate. Android uses KeystoreType BKS by default, so you should create one and import your certificate into it:

    keytool -importcert -v -trustcacerts \
      -file "[YOUR_PUBLIC_CERTIFICATE_PATH]" \
      -alias [YOUR_ALIAS] -keystore "[BKS_TARGET_PATH]" \
      -provider org.bouncycastle.jce.provider.BouncyCastleProvider \
      -providerpath "[BOUNCY_CASTLE_JAR_PATH]" -storetype BKS \
      -storepass [YOUR_PASSWORD]
    

    You can also do this using Portecle (http://portecle.sourceforge.net/), if you don't want to mess with the command line.

    To get the certificate file, you can use the openssl s_client command:

    openssl s_client -showcerts -connect <SERVER_URL>:<SERVER_PORT>  </dev/null