Hi everyone
It would be nice if Wildfire could connect to the LDAP-Server using a TLS connection.
This would make it possible to use client-certificates and to check the provided server-certificate using the keystore.
I already started with a patch, but I couldn’‘t test it yet and I’'m not a java programmer…
Greets,
Tiziano
diff -Naurb src/java/org/jivesoftware/wildfire/ldap.orig/LdapGroupProvider.java src/java/org/jivesoftware/wildfire/ldap/LdapGroupProvider.java
— src/java/org/jivesoftware/wildfire/ldap.orig/LdapGroupProvider.java 2006-11-26 18:07:55.000000000 +0100
+++ src/java/org/jivesoftware/wildfire/ldap/LdapGroupProvider.java 2006-11-26 18:05:35.000000000 +0100
@@ -32,6 +32,7 @@
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
+import java.io.IOException;
/**
-
LDAP implementation of the GroupProvider interface. All data in the directory is treated as
@@ -597,7 +598,7 @@ -
@return a collection of groups.
-
@throws javax.naming.NamingException
*/ -
private Collection answer) throws NamingException, IOException {
if (manager.isDebugEnabled()) {
Log.debug(“Starting to populate groups with users.”);
}
diff -Naurb src/java/org/jivesoftware/wildfire/ldap.orig/LdapManager.java src/java/org/jivesoftware/wildfire/ldap/LdapManager.java
— src/java/org/jivesoftware/wildfire/ldap.orig/LdapManager.java 2006-11-26 18:07:55.000000000 +0100
+++ src/java/org/jivesoftware/wildfire/ldap/LdapManager.java 2006-11-26 18:03:57.000000000 +0100
@@ -24,10 +24,13 @@
import javax.naming.directory.SearchResult;
import javax.naming.ldap.InitialLdapContext;
import javax.naming.ldap.LdapContext;
+import javax.naming.ldap.StartTlsResponse;
+import javax.naming.ldap.StartTlsRequest;
import java.net.URLEncoder;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
+import java.io.IOException;
/**
-
Centralized administration of LDAP connections. The {@link #getInstance()} method
@@ -53,6 +56,7 @@ -
<li>ldap.groupSearchFilter</li>
-
<li>ldap.debugEnabled</li>
-
<li>ldap.sslEnabled</li>
-
<li>ldap.autoFollowReferrals</li>
-
<li>ldap.initialContextFactory -- if this value is not specified,
-
"com.sun.jndi.ldap.LdapCtxFactory" will be used.</li>
@@ -137,6 +141,7 @@
private String adminPassword;
private boolean ldapDebugEnabled = false;
private boolean sslEnabled = false;
- private boolean tlsEnabled = false;
private String initialContextFactory;
private boolean followReferrals = false;
private boolean connectionPoolEnabled = true;
@@ -256,6 +261,11 @@
if (sslEnabledStr != null) {
sslEnabled = Boolean.valueOf(sslEnabledStr);
} -
tlsEnabled = false;
-
String tlsEnabledStr = properties.get("ldap.tlsEnabled");
-
if (tlsEnabledStr != null) {
-
tlsEnabled = Boolean.valueOf(tlsEnabledStr);
-
} followReferrals = false; String followReferralsStr = properties.get("ldap.autoFollowReferrals"); if (followReferralsStr != null) {
@@ -299,6 +309,7 @@
buf.append("\t subTreeSearch:").append(subTreeSearch).append("\n");
buf.append("\t ldapDebugEnabled: “).append(ldapDebugEnabled).append(”\n");
buf.append("\t sslEnabled: “).append(sslEnabled).append(”\n");
-
buf.append("\t tlsEnabled: ").append(tlsEnabled).append("\n"); buf.append("\t initialContextFactory: ").append(initialContextFactory).append("\n"); buf.append("\t connectionPoolEnabled: ").append(connectionPoolEnabled).append("\n"); buf.append("\t autoFollowReferrals: ").append(followReferrals).append("\n");
@@ -325,7 +336,7 @@
-
@return a connection to the LDAP server.
-
@throws NamingException if there is an error making the LDAP connection.
*/ -
public LdapContext getContext() throws NamingException {
- public LdapContext getContext() throws NamingException, IOException {
try {
return getContext(baseDN);
}
@@ -347,7 +358,7 @@
-
@return a connection to the LDAP server.
-
@throws NamingException if there is an error making the LDAP connection.
*/ -
public LdapContext getContext(String baseDN) throws NamingException {
-
public LdapContext getContext(String baseDN) throws NamingException, IOException {
boolean debug = Log.isDebugEnabled();
if (debug) {
Log.debug(“Creating a DirContext in LdapManager.getContext()…”);
@@ -364,7 +375,7 @@
}// Use simple authentication to connect as the admin.
-
if (adminDN != null) {
-
if (adminDN != null && !tlsEnabled) { env.put(Context.SECURITY_AUTHENTICATION, "simple"); env.put(Context.SECURITY_PRINCIPAL, adminDN); if (adminPassword != null) {
@@ -389,11 +400,27 @@
if (debug) {
Log.debug(“Created hashtable with context values, attempting to create context…”);
}
+
// Create new initial context
LdapContext context = new InitialLdapContext(env, null);
if (debug) {
-
Log.debug("... context created successfully, returning.");
-
Log.debug("... context created successfully.");
-
}
-
if (tlsEnabled) {
-
StartTlsResponse tls = (StartTlsResponse) context.extendedOperation(new StartTlsRequest());
-
tls.negotiate();
-
Log.debug("... TLS successfully initialized.");
-
if (adminDN != null) {
-
context.addToEnvironment(Context.SECURITY_AUTHENTICATION, "simple");
-
context.addToEnvironment(Context.SECURITY_PRINCIPAL, adminDN);
-
if (adminPassword != null) {
-
context.addToEnvironment(Context.SECURITY_CREDENTIALS, adminPassword);
-
}
-
context.reconnect(context.getConnectControls()); }
-
Log.debug("... and reconnected successfully.");
-
}
-
}return context;
@@ -405,13 +432,13 @@
-
@param password the user’'s password.
-
@return true if the user successfully authenticates.
*/ -
public boolean checkAuthentication(String userDN, String password) {
- public boolean checkAuthentication(String userDN, String password) throws IOException {
boolean debug = Log.isDebugEnabled();
if (debug) {
Log.debug("In LdapManager.checkAuthentication(userDN, password), userDN is: " + userDN + “…”);
}
-
DirContext ctx = null;
-
LdapContext ctx = null; try { // See if the user authenticates. Hashtable<String, Object> env = new Hashtable<String, Object>();
@@ -422,12 +449,14 @@
“org.jivesoftware.util.SimpleSSLSocketFactory”);
env.put(Context.SECURITY_PROTOCOL, “ssl”);
}
-
if (!tlsEnabled) { env.put(Context.SECURITY_AUTHENTICATION, "simple"); env.put(Context.SECURITY_PRINCIPAL, userDN + "," + baseDN); env.put(Context.SECURITY_CREDENTIALS, password);
-
} // Specify timeout to be 10 seconds, only on non SSL since SSL connections // break with a timemout.
-
if (!sslEnabled) {
-
if (!sslEnabled && !tlsEnabled) { env.put("com.sun.jndi.ldap.connect.timeout", "10000"); } if (ldapDebugEnabled) {
@@ -440,9 +469,19 @@
if (debug) {
Log.debug(“Created context values, attempting to create context…”);
}
-
ctx = new InitialDirContext(env);
-
ctx = new InitialLdapContext(env, null); if (debug) {
-
Log.debug("... context created successfully, returning.");
-
Log.debug("... context created successfully.");
-
}
-
if (tlsEnabled) {
-
StartTlsResponse tls = (StartTlsResponse) ctx.extendedOperation(new StartTlsRequest());
-
tls.negotiate();
-
Log.debug("... TLS successfully initialized.");
-
ctx.addToEnvironment(Context.SECURITY_AUTHENTICATION, "simple");
-
ctx.addToEnvironment(Context.SECURITY_PRINCIPAL, userDN + "," + baseDN);
-
ctx.addToEnvironment(Context.SECURITY_CREDENTIALS, password);
-
ctx.reconnect(ctx.getConnectControls());
-
Log.debug("... and reconnected successfully."); } } catch (NamingException ne) {
@@ -466,12 +505,14 @@
env.put(“java.naming.ldap.factory.socket”, “org.jivesoftware.util.SimpleSSLSocketFactory”);
env.put(Context.SECURITY_PROTOCOL, “ssl”);
}
-
if (!tlsEnabled) { env.put(Context.SECURITY_AUTHENTICATION, "simple"); env.put(Context.SECURITY_PRINCIPAL, userDN + "," + alternateBaseDN); env.put(Context.SECURITY_CREDENTIALS, password);
-
} // Specify timeout to be 10 seconds, only on non SSL since SSL connections // break with a timemout.
-
if (!sslEnabled) {
-
if (!sslEnabled && !tlsEnabled) { env.put("com.sun.jndi.ldap.connect.timeout", "10000"); } if (ldapDebugEnabled) {
@@ -483,7 +524,19 @@
if (debug) {
Log.debug(“Created context values, attempting to create context…”);
}
-
ctx = new InitialDirContext(env);
-
ctx = new InitialLdapContext(env, null);
-
Log.debug("... context created successfully.");
-
if (tlsEnabled) {
-
StartTlsResponse tls = (StartTlsResponse) ctx.extendedOperation(new StartTlsRequest());
-
tls.negotiate();
-
Log.debug("... TLS successfully initialized.");
-
ctx.addToEnvironment(Context.SECURITY_AUTHENTICATION, "simple");
-
ctx.addToEnvironment(Context.SECURITY_PRINCIPAL, userDN + "," + baseDN);
-
ctx.addToEnvironment(Context.SECURITY_CREDENTIALS, password);
-
ctx.reconnect(ctx.getConnectControls());
-
Log.debug("... and reconnected successfully.");
-
} } catch (NamingException e) { if (debug) {
@@ -575,7 +628,7 @@
-
@throws Exception if the search for the dn fails.
-
@see #findUserDN(String) to search using the default baseDN and alternateBaseDN.
*/ -
public String findUserDN(String username, String baseDN) throws Exception {
-
public String findUserDN(String username, String baseDN) throws Exception, IOException {
boolean debug = Log.isDebugEnabled();
if (debug) {
Log.debug("Trying to find a user’'s DN based on their username. " + usernameField + ": " + username
@@ -778,6 +831,16 @@
}/**
-
* Returns true if LDAP connection is via TLS or not. TLS is turned off by default.
-
*
-
* @return true if TLS connections are enabled or not.
-
*/
-
public boolean isTlsEnabled() {
-
return tlsEnabled;
-
}
-
/**
-
Sets whether the connection to the LDAP server should be made via ssl or not.
* -
@param sslEnabled true if ssl should be enabled, false otherwise.
@@ -788,6 +851,17 @@
}/**
-
* Sets whether the connection to the LDAP server should be made via tls or not.
-
*
-
* @param tlsEnabled true if tls should be enabled, false otherwise.
-
*/
- public void setTlsEnabled(boolean tlsEnabled) {
-
this.tlsEnabled = tlsEnabled;
-
properties.put("ldap.tlsEnabled", Boolean.toString(tlsEnabled));
- }
- /**
-
Returns the LDAP field name that the username lookup will be performed
-
on. By default this is “uid”.
*