aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJames Y Knight <jyknight@google.com>2011-05-17 11:45:37 -0400
committerShawn O. Pearce <sop@google.com>2011-06-24 09:21:39 -0700
commit7bb1f97b98c4f1d33b92ed8ee4ce96f5ff40b2f4 (patch)
tree630829d775b4fefe27e463705dd9633bb0722a29
parent183d0f865acd00734b0cbcd3cba2b52d665722ff (diff)
downloadgerrit-7bb1f97b98c4f1d33b92ed8ee4ce96f5ff40b2f4.tar.gz
Allow serving static files in subdirectories
Change-Id: I82447dd9ce47ffc44727d9f886a45a9fa1a2463e Signed-Off-By: James Y Knight <jyknight@google.com> (cherry picked from commit b8ddd05fbf98c63b70bfa3a714952b43bcad549a)
-rw-r--r--gerrit-httpd/src/main/java/com/google/gerrit/httpd/raw/StaticServlet.java39
1 files changed, 29 insertions, 10 deletions
diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/raw/StaticServlet.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/raw/StaticServlet.java
index ea587a4c..c33a2aa7 100644
--- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/raw/StaticServlet.java
+++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/raw/StaticServlet.java
@@ -89,34 +89,53 @@ public class StaticServlet extends HttpServlet {
}
private final File staticBase;
+ private final String staticBasePath;
@Inject
StaticServlet(final SitePaths site) {
- staticBase = site.static_dir;
+ File f;
+ try {
+ f = site.static_dir.getCanonicalFile();
+ } catch (IOException e) {
+ f = site.static_dir.getAbsoluteFile();
+ }
+ staticBase = f;
+ staticBasePath = staticBase.getPath() + File.separator;
}
private File local(final HttpServletRequest req) {
final String name = req.getPathInfo();
- if (name.length() < 2 || !name.startsWith("/")) {
+ if (name.length() < 2 || !name.startsWith("/") || isUnreasonableName(name)) {
// Too short to be a valid file name, or doesn't start with
// the path info separator like we expected.
//
return null;
}
- if (name.indexOf('/', 1) > 0 || name.indexOf('\\', 1) > 0) {
- // Contains a path separator. Don't serve it as the client
- // might be trying something evil like "/../../etc/passwd".
- // This static servlet is just meant to facilitate simple
- // assets like banner images.
- //
- return null;
+ final File p = new File(staticBase, name.substring(1));
+
+ // Ensure that the requested file is *actually* within the static dir base.
+ try {
+ if (!p.getCanonicalFile().getPath().startsWith(staticBasePath))
+ return null;
+ } catch (IOException e) {
+ return null;
}
- final File p = new File(staticBase, name.substring(1));
return p.isFile() ? p : null;
}
+ private static boolean isUnreasonableName(String name) {
+ if (name.charAt(name.length() -1) == '/') return true; // no suffix
+ if (name.indexOf('\\') >= 0) return true; // no windows/dos stlye paths
+ if (name.startsWith("../")) return true; // no "../etc/passwd"
+ if (name.contains("/../")) return true; // no "foo/../etc/passwd"
+ if (name.contains("/./")) return true; // "foo/./foo" is insane to ask
+ if (name.contains("//")) return true; // windows UNC path can be "//..."
+
+ return false; // is a reasonable name
+ }
+
@Override
protected long getLastModified(final HttpServletRequest req) {
final File p = local(req);