Add better URI path normalization, option to allow symlinks in web

path
This commit is contained in:
Mike Primm 2011-06-29 13:40:02 -05:00
parent e2b55c3b54
commit e6a8e54172
3 changed files with 50 additions and 5 deletions

View File

@ -106,6 +106,9 @@ webserver-port: 8123
# Disables Webserver portion of Dynmap (Advanced users only)
disable-webserver: false
# Enable/disable having the web server allow symbolic links (true=compatible with existing code, false=more secure (default))
allow-symlinks: true
# Period between tile renders for fullrender, in seconds (non-zero to pace fullrenders, lessen CPU load)
timesliceinterval: 0.0

View File

@ -136,10 +136,14 @@ public class DynmapPlugin extends JavaPlugin {
}
}
int port = configuration.getInteger("webserver-port", 8123);
boolean allow_symlinks = configuration.getBoolean("allow-symlinks", false);
if(allow_symlinks)
Log.verboseinfo("Web server is permitting symbolic links");
else
Log.verboseinfo("Web server is not permitting symbolic links");
webServer = new HttpServer(bindAddress, port);
webServer.handlers.put("/", new FilesystemHandler(getFile(configuration.getString("webpath", "web"))));
webServer.handlers.put("/tiles/", new FilesystemHandler(tilesDirectory));
webServer.handlers.put("/", new FilesystemHandler(getFile(configuration.getString("webpath", "web")), allow_symlinks));
webServer.handlers.put("/tiles/", new FilesystemHandler(tilesDirectory, allow_symlinks));
webServer.handlers.put("/up/configuration", new ClientConfigurationHandler(this));
}

View File

@ -5,6 +5,7 @@ import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import org.dynmap.Log;
import org.dynmap.utils.FileLockManager;
@ -15,21 +16,33 @@ import org.dynmap.web.HttpResponse;
public class FilesystemHandler extends FileHandler {
private File root;
public FilesystemHandler(File root) {
private boolean allow_symlinks = false;
private String root_path;
public FilesystemHandler(File root, boolean allow_symlinks) {
if (!root.isDirectory())
throw new IllegalArgumentException();
this.root = root;
this.allow_symlinks = allow_symlinks;
this.root_path = root.getAbsolutePath();
}
@Override
protected InputStream getFileInput(String path, HttpRequest request, HttpResponse response) {
path = getNormalizedPath(path); /* Resolve out relative stuff - nothing allowed above webroot */
File file = new File(root, path);
if(!file.isFile())
return null;
if(!FileLockManager.getReadLock(file, 5000)) { /* Wait up to 5 seconds for lock */
Log.severe("Timeout waiting for lock on file " + file.getPath());
return null;
}
FileInputStream result = null;
try {
if (file.getCanonicalPath().startsWith(root.getAbsolutePath()) && file.isFile()) {
String fpath;
if(allow_symlinks)
fpath = file.getAbsolutePath();
else
fpath = file.getCanonicalPath();
if (fpath.startsWith(root_path)) {
try {
result = new FileInputStream(file);
} catch (FileNotFoundException e) {
@ -46,6 +59,7 @@ public class FilesystemHandler extends FileHandler {
return null;
}
protected void closeFileInput(String path, InputStream in) throws IOException {
path = getNormalizedPath(path);
try {
super.closeFileInput(path, in);
} finally {
@ -53,4 +67,28 @@ public class FilesystemHandler extends FileHandler {
FileLockManager.releaseReadLock(file);
}
}
public static String getNormalizedPath(String p) {
p = p.replace('\\', '/');
String[] tok = p.split("/");
int i, j;
for(i = 0, j = 0; i < tok.length; i++) {
if((tok[i] == null) || (tok[i].length() == 0) || (tok[i].equals("."))) {
tok[i] = null;
}
else if(tok[i].equals("..")) {
if(j > 0) { j--; tok[j] = null; }
tok[i] = null;
}
else {
tok[j] = tok[i];
j++;
}
}
String path = "";
for(i = 0; i < j; i++) {
if(tok[i] != null)
path = path + "/" + tok[i];
}
return path;
}
}