Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
With mapperContextRootRedirectEnabled ste to false, the redirect needs to be handled elsewhere.
- Ensure the Mapper does not add the '/'
- Handle the redirect in the DefaultServlet
- Add a redirect to FORM auth if auth is occurring at the context root else the login page could be submitted to the wrong web application
This is part 2 of 3 of the fix for CVE-2015-5345

git-svn-id: https://svn.apache.org/repos/asf/tomcat/trunk@1716882 13f79535-47bb-0310-9956-ffa450edef68
  • Loading branch information
markt-asf committed Nov 27, 2015
1 parent a253eef commit 66daa4a
Show file tree
Hide file tree
Showing 3 changed files with 47 additions and 19 deletions.
14 changes: 14 additions & 0 deletions java/org/apache/catalina/authenticator/FormAuthenticator.java
Expand Up @@ -219,6 +219,20 @@ public boolean authenticate(Request request, HttpServletResponse response)

// No -- Save this request and redirect to the form login page
if (!loginAction) {
// If this request was to the root of the context without a trailing
// '/', need to redirect to add it else the submit of the login form
// may not go to the correct web application
if (request.getServletPath().length() == 0 && request.getPathInfo() == null) {
StringBuilder location = new StringBuilder(requestURI);
location.append('/');
if (request.getQueryString() != null) {
location.append('?');
location.append(request.getQueryString());
}
response.sendRedirect(response.encodeRedirectURL(location.toString()));
return false;
}

session = request.getSessionInternal(true);
if (log.isDebugEnabled()) {
log.debug("Save request in session '" + session.getIdInternal() + "'");
Expand Down
19 changes: 9 additions & 10 deletions java/org/apache/catalina/mapper/Mapper.java
Expand Up @@ -835,20 +835,13 @@ private final void internalMapWrapper(ContextVersion contextVersion,

int pathOffset = path.getOffset();
int pathEnd = path.getEnd();
int servletPath = pathOffset;
boolean noServletPath = false;

int length = contextVersion.path.length();
if (length != (pathEnd - pathOffset)) {
servletPath = pathOffset + length;
} else {
if (length == (pathEnd - pathOffset)) {
noServletPath = true;
path.append('/');
pathOffset = path.getOffset();
pathEnd = path.getEnd();
servletPath = pathOffset+length;
}

int servletPath = pathOffset + length;
path.setOffset(servletPath);

// Rule 1 -- Exact Match
Expand Down Expand Up @@ -1002,7 +995,13 @@ private final void internalMapWrapper(ContextVersion contextVersion,
char[] buf = path.getBuffer();
if (contextVersion.resources != null && buf[pathEnd -1 ] != '/') {
String pathStr = path.toString();
WebResource file = contextVersion.resources.getResource(pathStr);
WebResource file;
// Handle context root
if (pathStr.length() == 0) {
file = contextVersion.resources.getResource("/");
} else {
file = contextVersion.resources.getResource(pathStr);
}
if (file != null && file.isDirectory() &&
mappingData.context.getMapperDirectoryRedirectEnabled()) {
// Note: this mutates the path: do not do any processing
Expand Down
33 changes: 24 additions & 9 deletions java/org/apache/catalina/servlets/DefaultServlet.java
Expand Up @@ -331,6 +331,10 @@ public void init() throws ServletException {
* @param request The servlet request we are processing
*/
protected String getRelativePath(HttpServletRequest request) {
return getRelativePath(request, false);
}

protected String getRelativePath(HttpServletRequest request, boolean allowEmptyPath) {
// IMPORTANT: DefaultServlet can be mapped to '/' or '/path/*' but always
// serves resources from the web app root with context rooted paths.
// i.e. it cannot be used to mount the web app root under a sub-path
Expand All @@ -356,7 +360,7 @@ protected String getRelativePath(HttpServletRequest request) {
if (pathInfo != null) {
result.append(pathInfo);
}
if (result.length() == 0) {
if (result.length() == 0 && !allowEmptyPath) {
result.append('/');
}

Expand Down Expand Up @@ -686,7 +690,8 @@ protected void serveResource(HttpServletRequest request,
boolean serveContent = content;

// Identify the requested resource path
String path = getRelativePath(request);
String path = getRelativePath(request, true);

if (debug > 0) {
if (serveContent)
log("DefaultServlet.serveResource: Serving resource '" +
Expand All @@ -696,6 +701,12 @@ protected void serveResource(HttpServletRequest request,
path + "' headers only");
}

if (path.length() == 0) {
// Context root redirect
doDirectoryRedirect(request, response);
return;
}

WebResource resource = resources.getResource(path);

if (!resource.exists()) {
Expand Down Expand Up @@ -811,13 +822,7 @@ protected void serveResource(HttpServletRequest request,

if (resource.isDirectory()) {
if (!path.endsWith("/")) {
StringBuilder location = new StringBuilder(request.getRequestURI());
location.append('/');
if (request.getQueryString() != null) {
location.append('?');
location.append(request.getQueryString());
}
response.sendRedirect(response.encodeRedirectURL(location.toString()));
doDirectoryRedirect(request, response);
return;
}

Expand Down Expand Up @@ -1026,6 +1031,16 @@ protected void serveResource(HttpServletRequest request,
}
}

private void doDirectoryRedirect(HttpServletRequest request, HttpServletResponse response)
throws IOException {
StringBuilder location = new StringBuilder(request.getRequestURI());
location.append('/');
if (request.getQueryString() != null) {
location.append('?');
location.append(request.getQueryString());
}
response.sendRedirect(response.encodeRedirectURL(location.toString()));
}

/**
* Parse the content-range header.
Expand Down

0 comments on commit 66daa4a

Please sign in to comment.