title: LDAP over SSL with Java
body: <p>The following code works fine:</p>
  
  <pre><code>public static void main(String[] args) {
      String userName = "admin";
      String password = "s3cret";
      Hashtable env = new Hashtable();
      env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
      env.put(Context.PROVIDER_URL, "ldap://192.168.10.45:389/dc=softwaredev,dc=local");
      //env.put(Context.SECURITY_PROTOCOL, "ssl");
      env.put(Context.SECURITY_AUTHENTICATION, "simple");
      env.put(Context.SECURITY_PRINCIPAL, new String("softwaredev" + "\\" + userName));
      env.put(Context.SECURITY_CREDENTIALS, password);
  
      DirContext ctx = null;
      NamingEnumeration results = null;
      try {
          ctx = new InitialDirContext(env);
          SearchControls controls = new SearchControls();
          controls.setSearchScope(SearchControls.SUBTREE_SCOPE);
          results = ctx.search("", "(objectclass=person)", controls);
          while (results.hasMore()) {
              SearchResult searchResult = (SearchResult) results.next();
              Attributes attributes = searchResult.getAttributes();
              System.out.println(" Person Common Name = " + attributes.get("cn"));
              System.out.println(" Person Display Name = " + attributes.get("displayName"));
              System.out.println(" Person logonhours = " + attributes.get("logonhours"));
              System.out.println(" Person MemberOf = " + attributes.get("memberOf"));
          }
      } catch (Throwable e) {
          e.printStackTrace();
      } finally {
          if (results != null) {
              try {
                  results.close();
              } catch (Exception e) {
              }
          }
          if (ctx != null) {
              try {
                  ctx.close();
              } catch (Exception e) {
              }
          }
      }
  }
  </code></pre>
  
  <p>If I uncomment the following line:
  <code>env.put(Context.SECURITY_PROTOCOL, "ssl");</code> to enable SSL connection and use this URL:</p>
  
  <pre><code>ldaps://192.168.10.45:636
  </code></pre>
  
  <p>then the program fails and the error is about the certificate.</p>
  
  <pre><code>*javax.naming.CommunicationException: simple bind failed: 192.168.10.45:636 [Root exception is 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 com.sun.jndi.ldap.LdapClient.authenticate(Unknown Source)
      at com.sun.jndi.ldap.LdapCtx.connect(Unknown Source)
      at com.sun.jndi.ldap.LdapCtx.&lt;init&gt;(Unknown Source)
      at com.sun.jndi.ldap.LdapCtxFactory.getUsingURL(Unknown Source)
      at com.sun.jndi.ldap.LdapCtxFactory.getUsingURLs(Unknown Source)
      at com.sun.jndi.ldap.LdapCtxFactory.getLdapCtxInstance(Unknown Source)
      at com.sun.jndi.ldap.LdapCtxFactory.getInitialContext(Unknown Source)
      at javax.naming.spi.NamingManager.getInitialContext(Unknown Source)
      at javax.naming.InitialContext.getDefaultInitCtx(Unknown Source)
      at javax.naming.InitialContext.init(Unknown Source)
      at javax.naming.InitialContext.&lt;init&gt;(Unknown Source)
      at javax.naming.directory.InitialDirContext.&lt;init&gt;(Unknown Source)
      at asd.LdapBasicExample.main(LdapBasicExample.java:25)
  Caused by: 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(Unknown Source)
      at sun.security.ssl.SSLSocketImpl.fatal(Unknown Source)
      at sun.security.ssl.Handshaker.fatalSE(Unknown Source)
      at sun.security.ssl.Handshaker.fatalSE(Unknown Source)
      at sun.security.ssl.ClientHandshaker.serverCertificate(Unknown Source)
      at sun.security.ssl.ClientHandshaker.processMessage(Unknown Source)
      at sun.security.ssl.Handshaker.processLoop(Unknown Source)
      at sun.security.ssl.Handshaker.process_record(Unknown Source)
      at sun.security.ssl.SSLSocketImpl.readRecord(Unknown Source)
      at sun.security.ssl.SSLSocketImpl.performInitialHandshake(Unknown Source)
      at sun.security.ssl.SSLSocketImpl.readDataRecord(Unknown Source)
      at sun.security.ssl.AppInputStream.read(Unknown Source)
      at java.io.BufferedInputStream.fill(Unknown Source)
      at java.io.BufferedInputStream.read1(Unknown Source)
      at java.io.BufferedInputStream.read(Unknown Source)
      at com.sun.jndi.ldap.Connection.run(Unknown Source)
      at java.lang.Thread.run(Unknown Source)
  Caused by: 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.validator.PKIXValidator.doBuild(Unknown Source)
      at sun.security.validator.PKIXValidator.engineValidate(Unknown Source)
      at sun.security.validator.Validator.validate(Unknown Source)
      at sun.security.ssl.X509TrustManagerImpl.validate(Unknown Source)
      at sun.security.ssl.X509TrustManagerImpl.checkTrusted(Unknown Source)
      at sun.security.ssl.X509TrustManagerImpl.checkServerTrusted(Unknown Source)
      ... 13 more
  Caused by: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
      at sun.security.provider.certpath.SunCertPathBuilder.engineBuild(Unknown Source)
      at java.security.cert.CertPathBuilder.build(Unknown Source)*
  </code></pre>
  
  <p>So, what can I do to solve this problem?</p>