Skip to content

Commit

Permalink
Remove 3 of the essentially 4 duplicate normalise implementations.
Browse files Browse the repository at this point in the history
Minor tweaks where required to use the new single implementation.
Remove unnecessary normalisation calls.
This includes the fix for CVE-2008-5515.

git-svn-id: https://svn.apache.org/repos/asf/tomcat/trunk@734734 13f79535-47bb-0310-9956-ffa450edef68
  • Loading branch information
markt-asf committed Jan 15, 2009
1 parent e3c54fb commit 6b61911
Show file tree
Hide file tree
Showing 8 changed files with 40 additions and 166 deletions.
5 changes: 2 additions & 3 deletions java/org/apache/catalina/connector/Request.java
Original file line number Diff line number Diff line change
Expand Up @@ -1297,10 +1297,9 @@ else if (path.startsWith("/"))
int pos = requestPath.lastIndexOf('/');
String relative = null;
if (pos >= 0) {
relative = RequestUtil.normalize
(requestPath.substring(0, pos + 1) + path);
relative = requestPath.substring(0, pos + 1) + path;
} else {
relative = RequestUtil.normalize(requestPath + path);
relative = requestPath + path;
}

return (context.getServletContext().getRequestDispatcher(relative));
Expand Down
53 changes: 9 additions & 44 deletions java/org/apache/catalina/core/ApplicationContext.java
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@
import org.apache.catalina.deploy.FilterDef;
import org.apache.catalina.deploy.FilterMap;
import org.apache.catalina.util.Enumerator;
import org.apache.catalina.util.RequestUtil;
import org.apache.catalina.util.ResourceSet;
import org.apache.catalina.util.ServerInfo;
import org.apache.catalina.util.StringManager;
Expand Down Expand Up @@ -410,7 +411,7 @@ public RequestDispatcher getRequestDispatcher(String path) {
path = path.substring(0, pos);
}

path = normalize(path);
path = RequestUtil.normalize(path);
if (path == null)
return (null);

Expand Down Expand Up @@ -495,7 +496,7 @@ public URL getResource(String path)
throw new MalformedURLException(sm.getString("applicationContext.requestDispatcher.iae", path));


path = normalize(path);
path = RequestUtil.normalize(path);
if (path == null)
return (null);

Expand Down Expand Up @@ -544,13 +545,16 @@ public URL getResource(String path)
*/
public InputStream getResourceAsStream(String path) {

path = normalize(path);
if (path == null)
return (null);

if (!path.startsWith("/") && Globals.STRICT_SERVLET_COMPLIANCE)
return null;


path = RequestUtil.normalize(path);
if (path == null)
return (null);

DirContext resources = context.getResources();
if (resources != null) {
try {
Expand Down Expand Up @@ -583,7 +587,7 @@ public Set<String> getResourcePaths(String path) {
(sm.getString("applicationContext.resourcePaths.iae", path));
}

path = normalize(path);
path = RequestUtil.normalize(path);
if (path == null)
return (null);

Expand Down Expand Up @@ -1056,45 +1060,6 @@ void setAttributeReadOnly(String name) {
// -------------------------------------------------------- Private Methods


/**
* Return a context-relative path, beginning with a "/", that represents
* the canonical version of the specified path after ".." and "." elements
* are resolved out. If the specified path attempts to go outside the
* boundaries of the current context (i.e. too many ".." path elements
* are present), return <code>null</code> instead.
*
* @param path Path to be normalized
*/
private String normalize(String path) {

if (path == null) {
return null;
}

String normalized = path;

// Normalize the slashes
if (normalized.indexOf('\\') >= 0)
normalized = normalized.replace('\\', '/');

// Resolve occurrences of "/../" in the normalized path
while (true) {
int index = normalized.indexOf("/../");
if (index < 0)
break;
if (index == 0)
return (null); // Trying to go outside our context
int index2 = normalized.lastIndexOf('/', index - 1);
normalized = normalized.substring(0, index2) +
normalized.substring(index + 3);
}

// Return the normalized path that we have completed
return (normalized);

}


/**
* Merge the context initialization parameters specified in the application
* deployment descriptor with the application parameters described in the
Expand Down
5 changes: 2 additions & 3 deletions java/org/apache/catalina/core/ApplicationHttpRequest.java
Original file line number Diff line number Diff line change
Expand Up @@ -318,10 +318,9 @@ else if (path.startsWith("/"))
int pos = requestPath.lastIndexOf('/');
String relative = null;
if (pos >= 0) {
relative = RequestUtil.normalize
(requestPath.substring(0, pos + 1) + path);
relative = requestPath.substring(0, pos + 1) + path;
} else {
relative = RequestUtil.normalize(requestPath + path);
relative = requestPath + path;
}

return (context.getServletContext().getRequestDispatcher(relative));
Expand Down
67 changes: 3 additions & 64 deletions java/org/apache/catalina/servlets/WebdavServlet.java
Original file line number Diff line number Diff line change
Expand Up @@ -1412,68 +1412,6 @@ protected void doUnlock(HttpServletRequest req, HttpServletResponse resp)

}

/**
* Return a context-relative path, beginning with a "/", that represents
* the canonical version of the specified path after ".." and "." elements
* are resolved out. If the specified path attempts to go outside the
* boundaries of the current context (i.e. too many ".." path elements
* are present), return <code>null</code> instead.
*
* @param path Path to be normalized
*/
protected String normalize(String path) {

if (path == null)
return null;

// Create a place for the normalized path
String normalized = path;

if (normalized.equals("/."))
return "/";

// Normalize the slashes and add leading slash if necessary
if (normalized.indexOf('\\') >= 0)
normalized = normalized.replace('\\', '/');
if (!normalized.startsWith("/"))
normalized = "/" + normalized;

// Resolve occurrences of "//" in the normalized path
while (true) {
int index = normalized.indexOf("//");
if (index < 0)
break;
normalized = normalized.substring(0, index) +
normalized.substring(index + 1);
}

// Resolve occurrences of "/./" in the normalized path
while (true) {
int index = normalized.indexOf("/./");
if (index < 0)
break;
normalized = normalized.substring(0, index) +
normalized.substring(index + 2);
}

// Resolve occurrences of "/../" in the normalized path
while (true) {
int index = normalized.indexOf("/../");
if (index < 0)
break;
if (index == 0)
return (null); // Trying to go outside our context
int index2 = normalized.lastIndexOf('/', index - 1);
normalized = normalized.substring(0, index2) +
normalized.substring(index + 3);
}

// Return the normalized path that we have completed
return (normalized);

}


// -------------------------------------------------------- Private Methods

/**
Expand Down Expand Up @@ -1628,7 +1566,7 @@ private boolean copyResource(HttpServletRequest req,
}

// Normalise destination path (remove '.' and '..')
destinationPath = normalize(destinationPath);
destinationPath = RequestUtil.normalize(destinationPath);

String contextPath = req.getContextPath();
if ((contextPath != null) &&
Expand Down Expand Up @@ -2383,7 +2321,8 @@ private void parseLockNullProperties(HttpServletRequest req,
if (!toAppend.startsWith("/"))
toAppend = "/" + toAppend;

generatedXML.writeText(rewriteUrl(normalize(absoluteUri + toAppend)));
generatedXML.writeText(rewriteUrl(RequestUtil.normalize(
absoluteUri + toAppend)));

generatedXML.writeElement(null, "href", XMLWriter.CLOSING);

Expand Down
5 changes: 3 additions & 2 deletions java/org/apache/catalina/ssi/SSIServletExternalResolver.java
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.catalina.connector.Request;
import org.apache.catalina.util.RequestUtil;
import org.apache.coyote.Constants;

/**
Expand Down Expand Up @@ -370,7 +371,7 @@ protected String getAbsolutePath(String path) throws IOException {
+ pathWithoutContext);
}
String fullPath = prefix + path;
String retVal = SSIServletRequestUtil.normalize(fullPath);
String retVal = RequestUtil.normalize(fullPath);
if (retVal == null) {
throw new IOException("Normalization yielded null on path: "
+ fullPath);
Expand Down Expand Up @@ -403,7 +404,7 @@ protected ServletContextAndPath getServletContextAndPathFromVirtualPath(
return new ServletContextAndPath(context,
getAbsolutePath(virtualPath));
} else {
String normalized = SSIServletRequestUtil.normalize(virtualPath);
String normalized = RequestUtil.normalize(virtualPath);
if (isVirtualWebappRelative) {
return new ServletContextAndPath(context, normalized);
} else {
Expand Down
12 changes: 3 additions & 9 deletions java/org/apache/catalina/ssi/SSIServletRequestUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ public static String getRelativePath(HttpServletRequest request) {
if ((result == null) || (result.equals(""))) {
result = "/";
}
return normalize(result);
return RequestUtil.normalize(result);
}


Expand All @@ -63,15 +63,9 @@ public static String getRelativePath(HttpServletRequest request) {
*
* @param path
* Path to be normalized
* @deprecated
*/
public static String normalize(String path) {
if (path == null) return null;
String normalized = path;
//Why doesn't RequestUtil do this??
// Normalize the slashes and add leading slash if necessary
if (normalized.indexOf('\\') >= 0)
normalized = normalized.replace('\\', '/');
normalized = RequestUtil.normalize(path);
return normalized;
return RequestUtil.normalize(path);
}
}
16 changes: 16 additions & 0 deletions java/org/apache/catalina/util/RequestUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -93,13 +93,29 @@ public static String filter(String message) {
* @param path Relative path to be normalized
*/
public static String normalize(String path) {
return normalize(path, true);
}

/**
* Normalize a relative URI path that may have relative values ("/./",
* "/../", and so on ) it it. <strong>WARNING</strong> - This method is
* useful only for normalizing application-generated paths. It does not
* try to perform security checks for malicious input.
*
* @param path Relative path to be normalized
* @param replaceBackSlash Should '\\' be replaced with '/'
*/
public static String normalize(String path, boolean replaceBackSlash) {

if (path == null)
return null;

// Create a place for the normalized path
String normalized = path;

if (replaceBackSlash && normalized.indexOf('\\') >= 0)
normalized = normalized.replace('\\', '/');

if (normalized.equals("/."))
return "/";

Expand Down
43 changes: 2 additions & 41 deletions java/org/apache/naming/resources/FileDirContext.java
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
import javax.naming.directory.SearchControls;
import javax.naming.directory.SearchResult;

import org.apache.catalina.util.RequestUtil;
import org.apache.naming.NamingContextBindingsEnumeration;
import org.apache.naming.NamingContextEnumeration;
import org.apache.naming.NamingEntry;
Expand Down Expand Up @@ -768,50 +769,10 @@ public NamingEnumeration<SearchResult> search(String name,
*/
protected String normalize(String path) {

String normalized = path;

// Normalize the slashes and add leading slash if necessary
if (File.separatorChar == '\\' && normalized.indexOf('\\') >= 0)
normalized = normalized.replace('\\', '/');
if (!normalized.startsWith("/"))
normalized = "/" + normalized;

// Resolve occurrences of "//" in the normalized path
while (true) {
int index = normalized.indexOf("//");
if (index < 0)
break;
normalized = normalized.substring(0, index) +
normalized.substring(index + 1);
}

// Resolve occurrences of "/./" in the normalized path
while (true) {
int index = normalized.indexOf("/./");
if (index < 0)
break;
normalized = normalized.substring(0, index) +
normalized.substring(index + 2);
}
return RequestUtil.normalize(path, File.separatorChar == '\\');

// Resolve occurrences of "/../" in the normalized path
while (true) {
int index = normalized.indexOf("/../");
if (index < 0)
break;
if (index == 0)
return (null); // Trying to go outside our context
int index2 = normalized.lastIndexOf('/', index - 1);
normalized = normalized.substring(0, index2) +
normalized.substring(index + 3);
}

// Return the normalized path that we have completed
return (normalized);

}


/**
* Return a File object representing the specified normalized
* context-relative path if it exists and is readable. Otherwise,
Expand Down

0 comments on commit 6b61911

Please sign in to comment.