Commit 0cf31aa2 authored by Matt Tucker's avatar Matt Tucker Committed by matt

Added the ability to do flat LDAP searches (JM-719).

git-svn-id: http://svn.igniterealtime.org/svn/repos/wildfire/trunk@4018 b35dd754-fafc-0310-a699-88a17e54d16e
parent 9b4f6d67
...@@ -130,6 +130,10 @@ ...@@ -130,6 +130,10 @@
<li>ldap.searchFilter -- the search filter that should be used when loading users. If this <li>ldap.searchFilter -- the search filter that should be used when loading users. If this
property is not set, the default search will be for users that have the attribute specified by property is not set, the default search will be for users that have the attribute specified by
ldap.usernameField. ldap.usernameField.
<li>ldap.subTreeSearch -- the value "true" if the entire sub-tree under the base DN should
be included when executing searches (recursive search). If the value "false" is set, only
the first level under the base DN will be searched. The default value is "true", which is the better
option for the majority of directory layouts. Only set the value to "false" if necessary.</li>
<br><br> <br><br>
<b>Group Settings</b><br><br> <b>Group Settings</b><br><br>
......
...@@ -352,6 +352,35 @@ public class JiveGlobals { ...@@ -352,6 +352,35 @@ public class JiveGlobals {
return defaultValue; return defaultValue;
} }
/**
* Returns a boolean value local property. Local properties are stored in the
* file defined in <tt>JIVE_CONFIG_FILENAME</tt> that exists in the <tt>home</tt>
* directory. Properties are always specified as "foo.bar.prop", which would map to
* the following entry in the XML file:
* <pre>
* &lt;foo&gt;
* &lt;bar&gt;
* &lt;prop&gt;some value&lt;/prop&gt;
* &lt;/bar&gt;
* &lt;/foo&gt;
* </pre>
*
* If the specified property can't be found, the <tt>defaultValue</tt> will be returned.
* If the property is found, it will be parsed using {@link Boolean#valueOf(String)}.
*
* @param name the name of the property to return.
* @param defaultValue value returned if the property could not be loaded or was not
* a number.
* @return the property value specified by name or <tt>defaultValue</tt>.
*/
public static boolean getXMLProperty(String name, boolean defaultValue) {
String value = getXMLProperty(name);
if (value != null) {
return Boolean.valueOf(value);
}
return defaultValue;
}
/** /**
* Sets a local property. If the property doesn't already exists, a new * Sets a local property. If the property doesn't already exists, a new
* one will be created. Local properties are stored in the file defined in * one will be created. Local properties are stored in the file defined in
......
...@@ -353,7 +353,13 @@ public class LdapGroupProvider implements GroupProvider { ...@@ -353,7 +353,13 @@ public class LdapGroupProvider implements GroupProvider {
// Search for the dn based on the groupname. // Search for the dn based on the groupname.
SearchControls searchControls = new SearchControls(); SearchControls searchControls = new SearchControls();
searchControls.setReturningAttributes(returningAttributes); searchControls.setReturningAttributes(returningAttributes);
searchControls.setSearchScope(SearchControls.SUBTREE_SCOPE); // See if recursive searching is enabled. Otherwise, only search one level.
if (manager.isSubTreeSearch()) {
searchControls.setSearchScope(SearchControls.SUBTREE_SCOPE);
}
else {
searchControls.setSearchScope(SearchControls.ONELEVEL_SCOPE);
}
answer = ctx.search("", searchFilter, searchControls); answer = ctx.search("", searchFilter, searchControls);
if (manager.isDebugEnabled()) { if (manager.isDebugEnabled()) {
...@@ -388,9 +394,15 @@ public class LdapGroupProvider implements GroupProvider { ...@@ -388,9 +394,15 @@ public class LdapGroupProvider implements GroupProvider {
ctx = manager.getContext(); ctx = manager.getContext();
SearchControls ctrls = new SearchControls(); SearchControls searchControls = new SearchControls();
ctrls.setReturningAttributes(new String[]{manager.getUsernameField()}); searchControls.setReturningAttributes(new String[]{manager.getUsernameField()});
ctrls.setSearchScope(SearchControls.SUBTREE_SCOPE); // See if recursive searching is enabled. Otherwise, only search one level.
if (manager.isSubTreeSearch()) {
searchControls.setSearchScope(SearchControls.SUBTREE_SCOPE);
}
else {
searchControls.setSearchScope(SearchControls.ONELEVEL_SCOPE);
}
String userSearchFilter = MessageFormat.format(manager.getSearchFilter(), "*"); String userSearchFilter = MessageFormat.format(manager.getSearchFilter(), "*");
XMPPServer server = XMPPServer.getInstance(); XMPPServer server = XMPPServer.getInstance();
...@@ -438,7 +450,7 @@ public class LdapGroupProvider implements GroupProvider { ...@@ -438,7 +450,7 @@ public class LdapGroupProvider implements GroupProvider {
String combinedFilter = String combinedFilter =
"(&(" + ldapcn + ")" + userSearchFilter + ")"; "(&(" + ldapcn + ")" + userSearchFilter + ")";
NamingEnumeration usrAnswer = NamingEnumeration usrAnswer =
ctx.search("", combinedFilter, ctrls); ctx.search("", combinedFilter, searchControls);
if (usrAnswer.hasMoreElements()) { if (usrAnswer.hasMoreElements()) {
username = (String) ((SearchResult) usrAnswer.next()) username = (String) ((SearchResult) usrAnswer.next())
.getAttributes().get( .getAttributes().get(
......
...@@ -78,6 +78,7 @@ public class LdapManager { ...@@ -78,6 +78,7 @@ public class LdapManager {
private boolean followReferrals = false; private boolean followReferrals = false;
private boolean connectionPoolEnabled = true; private boolean connectionPoolEnabled = true;
private String searchFilter = null; private String searchFilter = null;
private boolean subTreeSearch;
private String groupNameField = "cn"; private String groupNameField = "cn";
private String groupMemberField = "member"; private String groupMemberField = "member";
...@@ -144,6 +145,7 @@ public class LdapManager { ...@@ -144,6 +145,7 @@ public class LdapManager {
filter.append("(").append(usernameField).append("={0})"); filter.append("(").append(usernameField).append("={0})");
this.searchFilter = filter.toString(); this.searchFilter = filter.toString();
} }
this.subTreeSearch = JiveGlobals.getXMLProperty("ldap.subTreeSearch", true);
if (JiveGlobals.getXMLProperty("ldap.groupNameField") != null) { if (JiveGlobals.getXMLProperty("ldap.groupNameField") != null) {
this.groupNameField = JiveGlobals.getXMLProperty("ldap.groupNameField"); this.groupNameField = JiveGlobals.getXMLProperty("ldap.groupNameField");
} }
...@@ -202,6 +204,7 @@ public class LdapManager { ...@@ -202,6 +204,7 @@ public class LdapManager {
Log.debug("\t adminDN: " + adminDN); Log.debug("\t adminDN: " + adminDN);
Log.debug("\t adminPassword: " + adminPassword); Log.debug("\t adminPassword: " + adminPassword);
Log.debug("\t searchFilter: " + searchFilter); Log.debug("\t searchFilter: " + searchFilter);
Log.debug("\t subTreeSearch:" + subTreeSearch);
Log.debug("\t ldapDebugEnabled: " + ldapDebugEnabled); Log.debug("\t ldapDebugEnabled: " + ldapDebugEnabled);
Log.debug("\t sslEnabled: " + sslEnabled); Log.debug("\t sslEnabled: " + sslEnabled);
Log.debug("\t initialContextFactory: " + initialContextFactory); Log.debug("\t initialContextFactory: " + initialContextFactory);
...@@ -476,7 +479,14 @@ public class LdapManager { ...@@ -476,7 +479,14 @@ public class LdapManager {
} }
// Search for the dn based on the username. // Search for the dn based on the username.
SearchControls constraints = new SearchControls(); SearchControls constraints = new SearchControls();
constraints.setSearchScope(SearchControls.SUBTREE_SCOPE); // If sub-tree searching is enabled (default is true) then search the entire tree.
if (subTreeSearch) {
constraints.setSearchScope(SearchControls.SUBTREE_SCOPE);
}
// Otherwise, only search a single level.
else {
constraints.setSearchScope(SearchControls.ONELEVEL_SCOPE);
}
constraints.setReturningAttributes(new String[] { usernameField }); constraints.setReturningAttributes(new String[] { usernameField });
NamingEnumeration answer = ctx.search("", searchFilter, new String[] {username}, NamingEnumeration answer = ctx.search("", searchFilter, new String[] {username},
...@@ -860,6 +870,33 @@ public class LdapManager { ...@@ -860,6 +870,33 @@ public class LdapManager {
} }
} }
/**
* Returns true if the entire tree under the base DN will be searched (recursive search)
* when doing LDAP queries (finding users, groups, etc). When false, only a single level
* under the base DN will be searched. The default is <tt>true</tt> which is the best
* option for most LDAP setups. In only a few cases will the directory be setup in such
* a way that it's better to do single level searching.
*
* @return true if the entire tree under the base DN will be searched.
*/
public boolean isSubTreeSearch() {
return subTreeSearch;
}
/**
* Sets whether the entire tree under the base DN will be searched (recursive search)
* when doing LDAP queries (finding users, groups, etc). When false, only a single level
* under the base DN will be searched. The default is <tt>true</tt> which is the best
* option for most LDAP setups. In only a few cases will the directory be setup in such
* a way that it's better to do single level searching.
*
* @param subTreeSearch true if the entire tree under the base DN will be searched.
*/
public void setSubTreeSearch(boolean subTreeSearch) {
this.subTreeSearch = subTreeSearch;
JiveGlobals.setXMLProperty("ldap.subTreeSearch", String.valueOf(subTreeSearch));
}
/** /**
* Returns the field name used for groups. * Returns the field name used for groups.
* Value of groupNameField defaults to "cn". * Value of groupNameField defaults to "cn".
......
...@@ -123,11 +123,17 @@ public class LdapUserProvider implements UserProvider { ...@@ -123,11 +123,17 @@ public class LdapUserProvider implements UserProvider {
try { try {
ctx = manager.getContext(); ctx = manager.getContext();
// Search for the dn based on the username. // Search for the dn based on the username.
SearchControls constraints = new SearchControls(); SearchControls searchControls = new SearchControls();
constraints.setSearchScope(SearchControls.SUBTREE_SCOPE); // See if recursive searching is enabled. Otherwise, only search one level.
constraints.setReturningAttributes(new String[] { manager.getUsernameField() }); if (manager.isSubTreeSearch()) {
searchControls.setSearchScope(SearchControls.SUBTREE_SCOPE);
}
else {
searchControls.setSearchScope(SearchControls.ONELEVEL_SCOPE);
}
searchControls.setReturningAttributes(new String[] { manager.getUsernameField() });
String filter = MessageFormat.format(manager.getSearchFilter(), "*"); String filter = MessageFormat.format(manager.getSearchFilter(), "*");
NamingEnumeration answer = ctx.search("", filter, constraints); NamingEnumeration answer = ctx.search("", filter, searchControls);
while (answer.hasMoreElements()) { while (answer.hasMoreElements()) {
count++; count++;
answer.nextElement(); answer.nextElement();
...@@ -168,11 +174,17 @@ public class LdapUserProvider implements UserProvider { ...@@ -168,11 +174,17 @@ public class LdapUserProvider implements UserProvider {
ctx.setRequestControls(searchControl); ctx.setRequestControls(searchControl);
// Search for the dn based on the username. // Search for the dn based on the username.
SearchControls constraints = new SearchControls(); SearchControls searchControls = new SearchControls();
constraints.setSearchScope(SearchControls.SUBTREE_SCOPE); // See if recursive searching is enabled. Otherwise, only search one level.
constraints.setReturningAttributes(new String[] { manager.getUsernameField() }); if (manager.isSubTreeSearch()) {
searchControls.setSearchScope(SearchControls.SUBTREE_SCOPE);
}
else {
searchControls.setSearchScope(SearchControls.ONELEVEL_SCOPE);
}
searchControls.setReturningAttributes(new String[] { manager.getUsernameField() });
String filter = MessageFormat.format(manager.getSearchFilter(), "*"); String filter = MessageFormat.format(manager.getSearchFilter(), "*");
NamingEnumeration answer = ctx.search("", filter, constraints); NamingEnumeration answer = ctx.search("", filter, searchControls);
while (answer.hasMoreElements()) { while (answer.hasMoreElements()) {
// Get the next userID. // Get the next userID.
String username = (String)((SearchResult)answer.next()).getAttributes().get( String username = (String)((SearchResult)answer.next()).getAttributes().get(
...@@ -214,16 +226,22 @@ public class LdapUserProvider implements UserProvider { ...@@ -214,16 +226,22 @@ public class LdapUserProvider implements UserProvider {
ctx.setRequestControls(searchControl); ctx.setRequestControls(searchControl);
// Search for the dn based on the username. // Search for the dn based on the username.
SearchControls constraints = new SearchControls(); SearchControls searchControls = new SearchControls();
constraints.setSearchScope(SearchControls.SUBTREE_SCOPE); // See if recursive searching is enabled. Otherwise, only search one level.
constraints.setReturningAttributes(new String[] { manager.getUsernameField() }); if (manager.isSubTreeSearch()) {
searchControls.setSearchScope(SearchControls.SUBTREE_SCOPE);
}
else {
searchControls.setSearchScope(SearchControls.ONELEVEL_SCOPE);
}
searchControls.setReturningAttributes(new String[] { manager.getUsernameField() });
// Limit results to those we'll need to process unless client-side sorting // Limit results to those we'll need to process unless client-side sorting
// is turned on. // is turned on.
if (!(Boolean.valueOf(JiveGlobals.getXMLProperty("ldap.clientSideSorting")))) { if (!(Boolean.valueOf(JiveGlobals.getXMLProperty("ldap.clientSideSorting")))) {
constraints.setCountLimit(startIndex+numResults); searchControls.setCountLimit(startIndex+numResults);
} }
String filter = MessageFormat.format(manager.getSearchFilter(), "*"); String filter = MessageFormat.format(manager.getSearchFilter(), "*");
NamingEnumeration answer = ctx.search("", filter, constraints); NamingEnumeration answer = ctx.search("", filter, searchControls);
// If client-side sorting is enabled, read in all results, sort, then get a sublist. // If client-side sorting is enabled, read in all results, sort, then get a sublist.
if (Boolean.valueOf(JiveGlobals.getXMLProperty("ldap.clientSideSorting"))) { if (Boolean.valueOf(JiveGlobals.getXMLProperty("ldap.clientSideSorting"))) {
while (answer.hasMoreElements()) { while (answer.hasMoreElements()) {
...@@ -334,9 +352,15 @@ public class LdapUserProvider implements UserProvider { ...@@ -334,9 +352,15 @@ public class LdapUserProvider implements UserProvider {
ctx.setRequestControls(searchControl); ctx.setRequestControls(searchControl);
// Search for the dn based on the username. // Search for the dn based on the username.
SearchControls constraints = new SearchControls(); SearchControls searchControls = new SearchControls();
constraints.setSearchScope(SearchControls.SUBTREE_SCOPE); // See if recursive searching is enabled. Otherwise, only search one level.
constraints.setReturningAttributes(new String[] { manager.getUsernameField() }); if (manager.isSubTreeSearch()) {
searchControls.setSearchScope(SearchControls.SUBTREE_SCOPE);
}
else {
searchControls.setSearchScope(SearchControls.ONELEVEL_SCOPE);
}
searchControls.setReturningAttributes(new String[] { manager.getUsernameField() });
StringBuilder filter = new StringBuilder(); StringBuilder filter = new StringBuilder();
if (fields.size() > 1) { if (fields.size() > 1) {
filter.append("(|"); filter.append("(|");
...@@ -348,7 +372,7 @@ public class LdapUserProvider implements UserProvider { ...@@ -348,7 +372,7 @@ public class LdapUserProvider implements UserProvider {
if (fields.size() > 1) { if (fields.size() > 1) {
filter.append(")"); filter.append(")");
} }
NamingEnumeration answer = ctx.search("", filter.toString(), constraints); NamingEnumeration answer = ctx.search("", filter.toString(), searchControls);
while (answer.hasMoreElements()) { while (answer.hasMoreElements()) {
// Get the next userID. // Get the next userID.
String username = (String)((SearchResult)answer.next()).getAttributes().get( String username = (String)((SearchResult)answer.next()).getAttributes().get(
...@@ -398,9 +422,15 @@ public class LdapUserProvider implements UserProvider { ...@@ -398,9 +422,15 @@ public class LdapUserProvider implements UserProvider {
ctx.setRequestControls(searchControl); ctx.setRequestControls(searchControl);
// Search for the dn based on the username. // Search for the dn based on the username.
SearchControls constraints = new SearchControls(); SearchControls searchControls = new SearchControls();
constraints.setSearchScope(SearchControls.SUBTREE_SCOPE); // See if recursive searching is enabled. Otherwise, only search one level.
constraints.setReturningAttributes(new String[] { manager.getUsernameField() }); if (manager.isSubTreeSearch()) {
searchControls.setSearchScope(SearchControls.SUBTREE_SCOPE);
}
else {
searchControls.setSearchScope(SearchControls.ONELEVEL_SCOPE);
}
searchControls.setReturningAttributes(new String[] { manager.getUsernameField() });
StringBuilder filter = new StringBuilder(); StringBuilder filter = new StringBuilder();
if (fields.size() > 1) { if (fields.size() > 1) {
filter.append("(|"); filter.append("(|");
...@@ -413,7 +443,7 @@ public class LdapUserProvider implements UserProvider { ...@@ -413,7 +443,7 @@ public class LdapUserProvider implements UserProvider {
filter.append(")"); filter.append(")");
} }
// TODO: used paged results is supported by LDAP server. // TODO: used paged results is supported by LDAP server.
NamingEnumeration answer = ctx.search("", filter.toString(), constraints); NamingEnumeration answer = ctx.search("", filter.toString(), searchControls);
for (int i=0; i < startIndex; i++) { for (int i=0; i < startIndex; i++) {
if (answer.hasMoreElements()) { if (answer.hasMoreElements()) {
answer.next(); answer.next();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment