title: Simple example TLS client connection with Smack 4.0.*
body: <p>I'm trying to use the Smack 4.0.5 Api to connect to the Vines XMPP as part of the Growing Object Oriented Software Guided by Tests worked example. I've struggled to find any documentation that describes how to connect using TLS. Several threads have presented samples like below, but this (as I believe insecure) option fails due to:</p>
  
  <pre><code>    ConnectionConfiguration connectionConfig = new ConnectionConfiguration(XMPP_HOSTNAME, 5222);
      connectionConfig.setDebuggerEnabled(true);
  
      SSLContext sslContext = null;
      try {
          sslContext = SSLContext.getInstance("TLS");
          TrustManager tm = new X509TrustManager() {
              @Override
              public void checkClientTrusted(X509Certificate[] x509Certificates, String s)
                  throws CertificateException {
              }
  
              @Override
              public void checkServerTrusted(X509Certificate[] x509Certificates, String s)
                  throws CertificateException {
              }
  
              @Override
              public X509Certificate[] getAcceptedIssuers() {
                  return new X509Certificate[0];
              }
          };
          sslContext.init(null, new TrustManager[] {tm}, null);
          connectionConfig.setCustomSSLContext(sslContext);
  
          this.connection = new XMPPTCPConnection(connectionConfig);
          this.connection.connect();
          this.connection.login(format(ITEM_ID_AS_LOGIN, itemId), AUCTION_PASSWORD, AUCTION_RESOURCE);
  
      } catch (Exception e) {
          e.printStackTrace();
          throw new RuntimeException("connecting failed", e);
      }
  </code></pre>
  
  <p>with    </p>
  
  <pre><code>org.jivesoftware.smack.sasl.SASLErrorException: SASLError using PLAIN: not-authorized
          at org.jivesoftware.smack.SASLAuthentication.authenticate(SASLAuthentication.java:348)
          at org.jivesoftware.smack.tcp.XMPPTCPConnection.login(XMPPTCPConnection.java:244)
          at uk.me.paulswilliams.auction.fakes.FakeAuctionServer.&lt;init&gt;(FakeAuctionServer.java:60)
          at uk.me.paulswilliams.auction.AuctionSniperEndToEndTest.&lt;init&gt;(AuctionSniperEndToEndTest.java:10)
          at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
          at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:57)
          at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
          at java.lang.reflect.Constructor.newInstance(Constructor.java:526)
          at org.junit.runners.BlockJUnit4ClassRunner.createTest(BlockJUnit4ClassRunner.java:195)
          at org.junit.runners.BlockJUnit4ClassRunner$1.runReflectiveCall(BlockJUnit4ClassRunner.java:244)
          at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
          at org.junit.runners.BlockJUnit4ClassRunner.methodBlock(BlockJUnit4ClassRunner.java:241)
          at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:70)
          at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)
          at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238)
          at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63)
          at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236)
          at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53)
          at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229)
          at org.junit.runners.ParentRunner.run(ParentRunner.java:309)
          at org.junit.runner.JUnitCore.run(JUnitCore.java:160)
          at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:74)
          at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:211)
          at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:67)
          at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
          at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
          at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
          at java.lang.reflect.Method.invoke(Method.java:606)
          at com.intellij.rt.execution.application.AppMain.main(AppMain.java:134)
  </code></pre>
  
  <p>Vines presents a self signed certificate, and I've tried to implement the 'secure' way by copying the public certificate to the client, registering it using the Java Control Panel on OS X, and use it with following code:</p>
  
  <pre><code>        try {
              ConnectionConfiguration connectionConfig = new ConnectionConfiguration(XMPP_HOSTNAME, 5222);
              connectionConfig.setSecurityMode(ConnectionConfiguration.SecurityMode.required);
              this.connection = new XMPPTCPConnection(connectionConfig);
              this.connection.connect();
              this.connection.login(format(ITEM_ID_AS_LOGIN, itemId), AUCTION_PASSWORD, AUCTION_RESOURCE);
          }
          catch (Exception e) {
              e.printStackTrace();
              throw new RuntimeException("connection failed");
          }
  </code></pre>
  
  <p>However, in this situation, I continue to receive a:</p>
  
  <pre><code>Nov 13, 2014 8:49:11 PM org.jivesoftware.smack.XMPPConnection callConnectionClosedOnErrorListener
  WARNING: Connection closed with error
  javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
      at sun.security.ssl.Alerts.getSSLException(Alerts.java:192)
  </code></pre>
  
  <p>I suspect both are close to working, and, due the nature of this work, security really isn't a consideration.</p>
  
  <p>Edit:</p>
  
  <p>I've now tried to import Vines certificate into my JVM keystone using:</p>
  
  <pre><code>sudo /Library/Java/Home/bin/keytool --import --alias "localhost" -file localhost.crt -keystore  /Library/Java/Home/lib/security/cacerts
  </code></pre>
  
  <p>I've specified the alias to match the server name 'localhost' although the server is also known as 'rails-dev-box' but I'm not using that name in the java client. Do I need to import the ca-bundle.crt CA as well? Should Java pick up this certificate based on server name, or do I need to explicitly instruct Java to do so?</p>