title: SSLHandshakeException while connection to LDAPS(Active Directory)
body: <p>We are using LDAP(Active Directory) to authenticate users. The ldap server is a secured one so we have generated the certificate and added to our keystore. To generate and import the cert we followed:</p>
  
  <pre><code>1.  Retrieve the public CA certificate from the server
  echo | openssl s_client -connect &lt;host&gt;:&lt;port&gt; 2&gt;&amp;1 | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' &gt; ca-cert.cer
  
  2.  Import the certificate into the keystore.
  sudo keytool -keystore &lt;path-tojre&gt;/jre/lib/security/cacerts -import -alias &lt;name&gt; -file ca-cert.crt
  </code></pre>
  
  <p>We tried to authenticate user with below Java prog, it fails with SSL Handshake exception. If we try to authenticate our LDAP serviceAccount/master user, it works fine. Below is the code we are using.</p>
  
  <pre><code>import java.util.Hashtable;
  
  import javax.naming.AuthenticationException;
  import javax.naming.Context;
  import javax.naming.NamingException;
  import javax.naming.directory.DirContext;
  import javax.naming.directory.InitialDirContext;
  
  public class LdapAuthenticationTest {
  
  private final static String mstrUsersearchBase = ",OU=ServiceAccounts,DC=org,DC=com";
  private final static String userSearchBase = ",ou=Staff,DC=org,DC=com";
  private static final String MASTER_USER = "MASTER_ID"+mstrUsersearchBase;
  private static final String MASTER_PASSWORD = "MASTER_PASSWORD";
  private final static String ldapUrl = "ldaps://server:636";
  
  static String appUser = "userId";
  static String appUserpassword = "password";
  
  public static void main(String[] args) {
      String keystorePath = "/usr/lib/jvm/java-1.8.0-openjdk-1.8/jre/lib/security/cacerts";
      System.setProperty("javax.net.ssl.trustStore", keystorePath);
      // Password of your java keystore. Default value is : changeit
      System.setProperty("javax.net.ssl.trustStorePassword", "changeit");
  
      DirContext ctx = null;
      try {
  //          1. Authenticate using master user.
          ctx = authenticate();
          System.out.println("--------&gt;&gt;&gt;  FOUND MASTER ACCOUNT!    &lt;&lt;&lt;--------- ");
  
  
  //          2. Authenticate using app user.
          ctx = authenticate(appUser, appUserpassword);
          System.out.println("--------&gt;&gt;&gt;  FOUND USER ACCOUNT!    &lt;&lt;&lt;--------");
          ctx.close();
      } catch (AuthenticationException ae) {
          System.out.println(" Authentication failed - exception: " + ae);
      } catch (Exception ie) {
          System.err.println("Unable to get LDAP connection -----&gt;&gt;&gt;&gt;&gt; " + ie);
      }
  }
  
  private static DirContext authenticate() throws NamingException {
      return authenticate(null, null);
  }
  
  private static DirContext authenticate(String username, String password) throws NamingException {
      String userType = username != null ? "App user" : "Master user";
      System.out.println("INSIDE Authenticate method:  authenticating-&gt; "+ userType);
  
      String user = username != null ? username+userSearchBase : MASTER_USER;
      String initialContextFactory = "com.sun.jndi.ldap.LdapCtxFactory"; 
      String securityAuthentication = "simple";
  
      Hashtable&lt;String, String&gt; env = new Hashtable&lt;&gt;();
      env.put(Context.INITIAL_CONTEXT_FACTORY, initialContextFactory);
      env.put(Context.SECURITY_AUTHENTICATION, securityAuthentication);
      env.put(Context.PROVIDER_URL, ldapUrl);
      String principal = "CN=" + user;
      System.out.println("principal-&gt; "+principal);
      env.put(Context.SECURITY_PRINCIPAL, principal);
      env.put(Context.SECURITY_CREDENTIALS, password != null ? password : MASTER_PASSWORD);
      // Specify SSL
      env.put(Context.SECURITY_PROTOCOL, "ssl");
      DirContext ctx = new InitialDirContext(env);
  
      return ctx;
  }
  
  }
  </code></pre>
  
  <p>I get the log in console as:</p>
  
  <pre><code>--------&gt;&gt;&gt;  FOUND MASTER ACCOUNT!    &lt;&lt;&lt;---------
  </code></pre>
  
  <p>followed by below Exception:</p>
  
  <pre><code>javax.naming.CommunicationException: simple bind failed: server: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]
  </code></pre>
  
  <p>The Java application and LDAP server are both in different machines (Linux Environment)</p>