pingidentity / ldapsdk

UnboundID LDAP SDK for Java
Other
334 stars 81 forks source link

How to connect the ldap server with 636 port. #62

Closed cnzhoutao closed 5 years ago

cnzhoutao commented 5 years ago
      When i use 636 connect to ldap server,i recived a error: 
      LDAPException(resultCode=81 (server down), errorMessage='An error occurred while attempting to send the LDAP message to server 192.168.1.172:636:  SocketException(Broken pipe (Write failed)), ldapSDKVersion=4.0.10, revision=b2272901fd62ad978017ff1aeb049cafc1999b12')!
   I want to modify the user's password without oldPassword。I have the administratos's account and password.
dirmgr commented 5 years ago

If you're going to establish a TLS-based connection, then you need to provide an SSLSocketFactory that will be used to create that connection. That will handle all the negotiation work, including selecting TLS protocol version, cipher suites, deciding whether to trust the certificate that the server presents, and optionally selecting a client certificate to present.

To help make this easier, we offer the com.unboundid.util.ssl.SSLUtil class, which can create the socket factory for you if you provide it with at least an appropriate trust manager. The easiest way to do this is to use the TrustAllTrustManager, which will blindly trust any certificate that the server presents, but this is definitely not a good idea for production use because it leaves you vulnerable for man-in-the-middle attacks, where someone could spoof the legitimate server and intercept all of the communication. However, it's a quick way to make sure that you can establish a secure connection and that the server's working properly. You can do that like:

SSLUtil sslUtil = new SSLUtil(new TrustAllTrustManager());
LDAPConnection conn = new LDAPConnection(
     sslUtil.createSSLSocketFactory(), serverAddress, serverPort);

A better approach, and one that doesn't leave you vulnerable to man-in-the-middle attacks, depends on the nature of the certificate that the server presents for TLS communication. If it's a certificate that youv'e purchased from a commercial authority, then chances are good that its issuer certificate will be found in the JVM's default trust store, and if that's the case then you could replace the first line with the following:

SSLUtil sslUtil = new SSLUtil(JVMDefaultTrustManager.getInstance());
LDAPConnection conn = new LDAPConnection(
     sslUtil.createSSLSocketFactory(), serverAddress, serverPort);

If the certificate is signed by your company's internal certificate authority, or if it's self-signed, then the best option is to provide a JKS or PKCS#12 trust store file that contains the issuer certificate. And in that case, you would use:

SSLUtil sslUtil = new SSLUtil(new TrustStoreTrustManager(trustStorePath,
     trustStorePIN, trustStoreFormat, true));
LDAPConnection conn = new LDAPConnection(
     sslUtil.createSSLSocketFactory(), serverAddress, serverPort);

If you need help in getting the right trust store file then the manage-certificates tool that the LDAP SDK provides can create one for you. Just use a command like:

 $ tools/manage-certificates trust-server-certificate \
     --hostname {serverAddress} \
     --port {serverPort} \
     --keystore {trustStorePath} \
     --keystore-password-file {trustStorePINFile}

This will establish a connection to the server, begin TLS negotiation, capture the certificate that the server presents, and write it to the specified trust store file (after prompting you to determine whether the certificate should actually be trusted, unless you provide the --no-prompt argument). You can then use that trust store file in conjunction with the TrustStoreTrustManager to trust the legitimate server certificate, but if an impostor later spins up their own server and tries to perform a man-in-the-middle attack, they won't have the right certificate and your client won't trust their server, and you'll be protected against potentially disclosing sensitive information (like authentication credentials) or acting on bogus results.

cnzhoutao commented 5 years ago

I just try it. But it not work for me. My active directory is on windows server 2008,and the server is in LAN.I wonder if my environment that cause this.

The code: String host="192.168.1.172"; int port=636; SSLUtil sslUtil = new SSLUtil(new TrustAllTrustManager()); // SSLUtil sslUtil = new SSLUtil(JVMDefaultTrustManager.getInstance()); SSLSocketFactory sslSocketFactory = sslUtil.createSSLSocketFactory(); // JavaToLDAPSocketFactory ldapSocketFactory = new JavaToLDAPSocketFactory(sslSocketFactory); LDAPConnection ldapConnection = new LDAPConnection(sslSocketFactory, host, port, LdapConstans.LDAPS_USERENAME, LdapConstans.LDAPS_PWD);

The Exception:

LDAPException(resultCode=91 (connect error), errorMessage='An error occurred while attempting to connect to server 192.168.1.172:636: SocketException(Socket Closed), ldapSDKVersion=4.0.10, revision=b2272901fd62ad978017ff1aeb049cafc1999b12') at com.unboundid.ldap.sdk.LDAPConnection.connect(LDAPConnection.java:871) at com.unboundid.ldap.sdk.LDAPConnection.connect(LDAPConnection.java:760) at com.unboundid.ldap.sdk.LDAPConnection.connect(LDAPConnection.java:710) at com.unboundid.ldap.sdk.LDAPConnection.<init>(LDAPConnection.java:534) at com.unboundid.ldap.sdk.LDAPConnection.<init>(LDAPConnection.java:666) at com.unboundid.ldap.sdk.LDAPConnection.<init>(LDAPConnection.java:629) at cipher.console.oidc.controller.TestLdap.main(TestLdap.java:86) Caused by: java.net.SocketException: Socket Closed at java.net.AbstractPlainSocketImpl.setOption(AbstractPlainSocketImpl.java:212) at java.net.Socket.setKeepAlive(Socket.java:1310) at sun.security.ssl.BaseSSLSocketImpl.setKeepAlive(BaseSSLSocketImpl.java:497) at com.unboundid.util.ssl.SetEnabledProtocolsSocket.setKeepAlive(SetEnabledProtocolsSocket.java:527) at com.unboundid.ldap.sdk.LDAPConnectionInternals.<init>(LDAPConnectionInternals.java:194) at com.unboundid.ldap.sdk.LDAPConnection.connect(LDAPConnection.java:861) ... 6 more

dirmgr commented 5 years ago

It's not clear what's happening just from what you've provided. The best way to figure out what's going on would be to add the following before creating the socket factory:

System.setProperty("javax.net.debug", "all");

This will cause your program to write lots of debug output to standard error, including lots of detail about the TLS negotiation. That should have the information we need to see what went wrong.

You could also try the LDAP SDK's ldapsearch tool (in the tools directory) to see if it's able to establish a secure connection. To do that, issue the following command:

$ tools/ldapsearch --hostname 192.168.1.172 --port 636 --useSSL --baseDN "" --scope base "(objectClass=*)"

This should establish a TCP connection, start TLS negotiation, and display a prompt about whether you want to trust the server certificate. If that doesn't work, then there's probably something else going on.

cnzhoutao commented 5 years ago
In this morning,i've tried it agin.it works for me. I think that problem com from my internet enviorment.

thanks very much.