Author: remy.maucherat(a)jboss.com
Date: 2009-05-01 12:52:00 -0400 (Fri, 01 May 2009)
New Revision: 1040
Modified:
trunk/java/org/apache/catalina/core/StandardHostValve.java
trunk/java/org/apache/catalina/realm/JNDIRealm.java
trunk/java/org/apache/catalina/startup/Tomcat.java
trunk/webapps/docs/changelog.xml
Log:
- Port 3 Tomcat patches (mostly the JNDI realm rewrite).
Modified: trunk/java/org/apache/catalina/core/StandardHostValve.java
===================================================================
--- trunk/java/org/apache/catalina/core/StandardHostValve.java 2009-04-30 17:50:00 UTC
(rev 1039)
+++ trunk/java/org/apache/catalina/core/StandardHostValve.java 2009-05-01 16:52:00 UTC
(rev 1040)
@@ -33,7 +33,6 @@
import org.apache.catalina.connector.Request;
import org.apache.catalina.connector.Response;
import org.apache.catalina.deploy.ErrorPage;
-import org.apache.catalina.util.RequestUtil;
import org.apache.catalina.util.StringManager;
import org.apache.catalina.valves.ValveBase;
import org.jboss.logging.Logger;
@@ -251,10 +250,10 @@
(ApplicationFilterFactory.DISPATCHER_REQUEST_PATH_ATTR,
errorPage.getLocation());
request.setAttribute(ApplicationFilterFactory.DISPATCHER_TYPE_ATTR,
- new Integer(ApplicationFilterFactory.ERROR));
+ Integer.valueOf(ApplicationFilterFactory.ERROR));
request.setAttribute
(Globals.STATUS_CODE_ATTR,
- new Integer(HttpServletResponse.SC_INTERNAL_SERVER_ERROR));
+ Integer.valueOf(HttpServletResponse.SC_INTERNAL_SERVER_ERROR));
request.setAttribute(Globals.ERROR_MESSAGE_ATTR,
throwable.getMessage());
request.setAttribute(Globals.EXCEPTION_ATTR,
@@ -320,9 +319,9 @@
if (errorPage != null) {
response.setAppCommitted(false);
request.setAttribute(Globals.STATUS_CODE_ATTR,
- new Integer(statusCode));
+ Integer.valueOf(statusCode));
- String message = RequestUtil.filter(response.getMessage());
+ String message = response.getMessage();
if (message == null)
message = "";
request.setAttribute(Globals.ERROR_MESSAGE_ATTR, message);
@@ -330,7 +329,7 @@
(ApplicationFilterFactory.DISPATCHER_REQUEST_PATH_ATTR,
errorPage.getLocation());
request.setAttribute(ApplicationFilterFactory.DISPATCHER_TYPE_ATTR,
- new Integer(ApplicationFilterFactory.ERROR));
+ Integer.valueOf(ApplicationFilterFactory.ERROR));
Wrapper wrapper = request.getWrapper();
Modified: trunk/java/org/apache/catalina/realm/JNDIRealm.java
===================================================================
--- trunk/java/org/apache/catalina/realm/JNDIRealm.java 2009-04-30 17:50:00 UTC (rev
1039)
+++ trunk/java/org/apache/catalina/realm/JNDIRealm.java 2009-05-01 16:52:00 UTC (rev
1040)
@@ -29,7 +29,6 @@
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
-import java.util.Map;
import java.util.Set;
import javax.naming.AuthenticationException;
@@ -145,9 +144,10 @@
* authenticated by setting the <code>commonRole</code> property to the
* name of this role. The role doesn't have to exist in the directory.</li>
*
- * <li>If the directory server contains nested roles, you can search for roles
- * recursively by setting <code>roleRecursionLimit</code> to some positive
value.
- * The default value is <code>0</code>, so role searches do not
recurse.</li>
+ * <li>If the directory server contains nested roles, you can search for them
+ * by setting <code>roleNested</code> to <code>true</code>.
+ * The default value is <code>false</code>, so role searches will not find
+ * nested roles.</li>
*
* <li>Note that the standard
<code><security-role-ref></code> element in
* the web application deployment descriptor allows applications to refer
@@ -320,15 +320,7 @@
*/
protected MessageFormat[] userPatternFormatArray = null;
-
/**
- * The maximum recursion depth when resolving roles recursively.
- * By default we don't resolve roles recursively.
- */
- protected int roleRecursionLimit = 0;
-
-
- /**
* The base element for role searches.
*/
protected String roleBase = "";
@@ -365,7 +357,13 @@
* Should we search the entire subtree for matching memberships?
*/
protected boolean roleSubtree = false;
+
+ /**
+ * Should we look for nested group in order to determine roles?
+ */
+ protected boolean roleNested = false;
+
/**
* An alternate URL, to which, we should connect if connectionURL fails.
*/
@@ -655,28 +653,6 @@
/**
- * Return the maximum recursion depth for role searches.
- */
- public int getRoleRecursionLimit() {
-
- return (this.roleRecursionLimit);
-
- }
-
-
- /**
- * Set the maximum recursion depth for role searches.
- *
- * @param roleRecursionLimit The new recursion limit
- */
- public void setRoleRecursionLimit(int roleRecursionLimit) {
-
- this.roleRecursionLimit = roleRecursionLimit;
-
- }
-
-
- /**
* Return the base element for role searches.
*/
public String getRoleBase() {
@@ -766,9 +742,31 @@
this.roleSubtree = roleSubtree;
}
+
+ /**
+ * Return the "The nested group search flag" flag.
+ */
+ public boolean getRoleNested() {
+ return (this.roleNested);
+ }
+
+
/**
+ * Set the "search subtree for roles" flag.
+ *
+ * @param roleNested The nested group search flag
+ */
+ public void setRoleNested(boolean roleNested) {
+
+ this.roleNested = roleNested;
+
+ }
+
+
+
+ /**
* Return the password attribute used to retrieve the user password.
*/
public String getUserPassword() {
@@ -1297,7 +1295,7 @@
attrIds = new String[0];
constraints.setReturningAttributes(attrIds);
- NamingEnumeration results =
+ NamingEnumeration<SearchResult> results =
context.search(userBase, filter, constraints);
@@ -1314,7 +1312,7 @@
}
// Get result for the first entry found
- SearchResult result = (SearchResult)results.next();
+ SearchResult result = results.next();
// Check no further entries were found
try {
@@ -1549,71 +1547,7 @@
return (validated);
}
-
/**
- * Add roles to a user and search for other roles containing them themselves.
- * We search recursively with a limited depth.
- * By default the depth is 0, and we only use direct roles.
- * The search needs to use the distinguished role names,
- * but to return the role names.
- *
- * @param depth Recursion depth, starting at zero
- * @param context The directory context we are searching
- * @param recursiveMap The cumulative result map of role names and DNs.
- * @param recursiveSet The cumulative result set of role names.
- * @param groupName The role name to add to the list.
- * @param groupDName The distinguished name of the role.
- *
- * @exception NamingException if a directory server error occurs
- */
- private void getRolesRecursive(int depth, DirContext context, Map<String,
String> recursiveMap, Set<String> recursiveSet,
- String groupName, String groupDName) throws
NamingException {
- if (containerLog.isTraceEnabled())
- containerLog.trace("Recursive search depth " + depth + " for
group '" + groupDName + " (" + groupName + ")'");
- // Adding the given group to the result set if not already found
- if (!recursiveSet.contains(groupDName)) {
- recursiveSet.add(groupDName);
- recursiveMap.put(groupDName, groupName);
- if (depth >= roleRecursionLimit) {
- if (roleRecursionLimit > 0)
- containerLog.warn("Terminating recursive role search because of
recursion limit " +
- roleRecursionLimit + ", results might be
incomplete");
- return;
- }
- // Prepare the parameters for searching groups
- String filter = roleFormat.format(new String[] { groupDName });
- SearchControls controls = new SearchControls();
- controls.setSearchScope(roleSubtree ? SearchControls.SUBTREE_SCOPE :
SearchControls.ONELEVEL_SCOPE);
- controls.setReturningAttributes(new String[] { roleName });
- if (containerLog.isTraceEnabled()) {
- containerLog.trace("Recursive search in role base '" +
roleBase + "' for attribute '" + roleName + "'" +
- " with filter expression '" + filter +
"'");
- }
- // Searching groups that assign the given group
- NamingEnumeration results = context.search(roleBase, filter, controls);
- if (results != null) {
- // Iterate over the resulting groups
- try {
- while (results.hasMore()) {
- SearchResult result = (SearchResult) results.next();
- Attributes attrs = result.getAttributes();
- if (attrs == null)
- continue;
- String dname = getDistinguishedName(context, roleBase, result);
- String name = getAttributeValue(roleName, attrs);
- if (name != null && dname != null) {
- getRolesRecursive(depth+1, context, recursiveMap,
recursiveSet, name, dname);
- }
- }
- } catch (PartialResultException ex) {
- if (!adCompat)
- throw ex;
- }
- }
- }
- }
-
- /**
* Return a List of roles associated with the given User. Any
* roles present in the user's directory entry are supplemented by
* a directory search. If no roles are associated with this user,
@@ -1648,19 +1582,15 @@
list.add(commonRole);
if (containerLog.isTraceEnabled()) {
- if (list != null) {
- containerLog.trace(" Found " + list.size() + " user
internal roles");
- for (int i=0; i<list.size(); i++)
- containerLog.trace( " Found user internal role " +
list.get(i));
- } else {
- containerLog.trace(" Found no user internal roles");
- }
+ containerLog.trace(" Found " + list.size() + " user internal
roles");
+ for (int i=0; i<list.size(); i++)
+ containerLog.trace( " Found user internal role " +
list.get(i));
}
// Are we configured to do role searches?
if ((roleFormat == null) || (roleName == null))
return (list);
-
+
// Set up parameters for an appropriate search
String filter = roleFormat.format(new String[] { doRFC2254Encoding(dn), username
});
SearchControls controls = new SearchControls();
@@ -1671,7 +1601,7 @@
controls.setReturningAttributes(new String[] {roleName});
// Perform the configured search and process the results
- NamingEnumeration results =
+ NamingEnumeration<SearchResult> results =
context.search(roleBase, filter, controls);
if (results == null)
return (list); // Should never happen, but just in case ...
@@ -1679,7 +1609,7 @@
HashMap<String, String> groupMap = new HashMap<String, String>();
try {
while (results.hasMore()) {
- SearchResult result = (SearchResult) results.next();
+ SearchResult result = results.next();
Attributes attrs = result.getAttributes();
if (attrs == null)
continue;
@@ -1697,30 +1627,60 @@
Set<String> keys = groupMap.keySet();
if (containerLog.isTraceEnabled()) {
containerLog.trace(" Found " + keys.size() + " direct
roles");
- for (Iterator<String> i = keys.iterator(); i.hasNext();) {
- Object k = i.next();
- containerLog.trace( " Found direct role " + k + " ->
" + groupMap.get(k));
+ for (String key: keys) {
+ containerLog.trace( " Found direct role " + key + "
-> " + groupMap.get(key));
}
}
- HashSet<String> recursiveSet = new HashSet<String>();
- HashMap<String, String> recursiveMap = new HashMap<String,
String>();
+ // if nested group search is enabled, perform searches for nested groups until no
new group is found
+ if (getRoleNested()) {
- for (Iterator<String> i = keys.iterator(); i.hasNext();) {
- String k = i.next();
- getRolesRecursive(0, context, recursiveMap, recursiveSet, groupMap.get(k),
k);
- }
+ // The following efficient algorithm is known as memberOf Algorithm, as
described in "Practices in
+ // Directory Groups". It avoids group slurping and handles cyclic group
memberships as well.
+ // See
http://middleware.internet2.edu/dir/ for details
- HashSet<String> resultSet = new HashSet<String>(list);
- resultSet.addAll(recursiveMap.values());
+ Set<String> newGroupDNs = new
HashSet<String>(groupMap.keySet());
+ while (!newGroupDNs.isEmpty()) {
+ Set<String> newThisRound = new HashSet<String>(); // Stores
the groups we find in this iteration
- if (containerLog.isTraceEnabled()) {
- containerLog.trace(" Returning " + resultSet.size() + "
roles");
- for (Iterator<String> i = resultSet.iterator(); i.hasNext();)
- containerLog.trace( " Found role " + i.next());
+ for (String groupDN : newGroupDNs) {
+ filter = roleFormat.format(new String[] { groupDN });
+
+ if (containerLog.isTraceEnabled()) {
+ containerLog.trace("Perform a nested group search with base
"+ roleBase + " and filter " + filter);
+ }
+
+ results = context.search(roleBase, filter, controls);
+
+ try {
+ while (results.hasMore()) {
+ SearchResult result = results.next();
+ Attributes attrs = result.getAttributes();
+ if (attrs == null)
+ continue;
+ String dname = getDistinguishedName(context, roleBase,
result);
+ String name = getAttributeValue(roleName, attrs);
+ if (name != null && dname != null &&
!groupMap.keySet().contains(dname)) {
+ groupMap.put(dname, name);
+ newThisRound.add(dname);
+
+ if (containerLog.isTraceEnabled()) {
+ containerLog.trace(" Found nested role " +
dname + " -> " + name);
+ }
+
+ }
+ }
+ } catch (PartialResultException ex) {
+ if (!adCompat)
+ throw ex;
+ }
+ }
+
+ newGroupDNs = newThisRound;
+ }
}
- return new ArrayList<String>(resultSet);
+ return new ArrayList<String>(groupMap.values());
}
@@ -1781,7 +1741,7 @@
Attribute attr = attrs.get(attrId);
if (attr == null)
return (values);
- NamingEnumeration e = attr.getAll();
+ NamingEnumeration<?> e = attr.getAll();
try {
while(e.hasMore()) {
String value = (String)e.next();
@@ -1972,7 +1932,7 @@
*
* @return java.util.Hashtable the configuration for the directory context.
*/
- protected Hashtable getDirectoryContextEnvironment() {
+ protected Hashtable<String,String> getDirectoryContextEnvironment() {
Hashtable<String,String> env = new Hashtable<String,String>();
@@ -2011,7 +1971,7 @@
*/
protected void release(DirContext context) {
- ; // NO-OP since we are not pooling anything
+ // NO-OP since we are not pooling anything
}
@@ -2095,7 +2055,7 @@
startingPoint = endParenLoc+1;
startParenLoc = userPatternString.indexOf('(', startingPoint);
}
- return (String[])pathList.toArray(new String[] {});
+ return pathList.toArray(new String[] {});
}
return null;
Modified: trunk/java/org/apache/catalina/startup/Tomcat.java
===================================================================
--- trunk/java/org/apache/catalina/startup/Tomcat.java 2009-04-30 17:50:00 UTC (rev 1039)
+++ trunk/java/org/apache/catalina/startup/Tomcat.java 2009-05-01 16:52:00 UTC (rev 1040)
@@ -359,7 +359,7 @@
if(engine == null ) {
getServer();
engine = new StandardEngine();
- engine.setName( "default" );
+ engine.setName( "Tomcat" );
engine.setDefaultHost(hostname);
service.setContainer(engine);
}
Modified: trunk/webapps/docs/changelog.xml
===================================================================
--- trunk/webapps/docs/changelog.xml 2009-04-30 17:50:00 UTC (rev 1039)
+++ trunk/webapps/docs/changelog.xml 2009-05-01 16:52:00 UTC (rev 1040)
@@ -77,6 +77,13 @@
<add>
New JarRepository component to handle better management of JarFiles following the
Servlet 3.0 update. (remm)
</add>
+ <fix>
+ <bug>47050</bug>: Remove unnecessary filtering in StandardHostValve.
(markt)
+ </fix>
+ <fix>
+ <bug>46925</bug>: Improve search for nested roles in JNDIRealm by
replacing recursive search with
+ iterative search. Patch provided by Stefan Zoerner. (rjung)
+ </fix>
</changelog>
</subsection>
<subsection name="Coyote">