Merge pull request #253 from mikeprimm/master

Add better URI path normalization, option to allow symlinks in web path
This commit is contained in:
mikeprimm 2011-06-29 11:44:58 -07:00
commit 3875486fbf
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) # Disables Webserver portion of Dynmap (Advanced users only)
disable-webserver: false 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) # Period between tile renders for fullrender, in seconds (non-zero to pace fullrenders, lessen CPU load)
timesliceinterval: 0.0 timesliceinterval: 0.0

View File

@ -136,10 +136,14 @@ public class DynmapPlugin extends JavaPlugin {
} }
} }
int port = configuration.getInteger("webserver-port", 8123); 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 = new HttpServer(bindAddress, port);
webServer.handlers.put("/", new FilesystemHandler(getFile(configuration.getString("webpath", "web")))); webServer.handlers.put("/", new FilesystemHandler(getFile(configuration.getString("webpath", "web")), allow_symlinks));
webServer.handlers.put("/tiles/", new FilesystemHandler(tilesDirectory)); webServer.handlers.put("/tiles/", new FilesystemHandler(tilesDirectory, allow_symlinks));
webServer.handlers.put("/up/configuration", new ClientConfigurationHandler(this)); 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.FileNotFoundException;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.util.ArrayList;
import org.dynmap.Log; import org.dynmap.Log;
import org.dynmap.utils.FileLockManager; import org.dynmap.utils.FileLockManager;
@ -15,21 +16,33 @@ import org.dynmap.web.HttpResponse;
public class FilesystemHandler extends FileHandler { public class FilesystemHandler extends FileHandler {
private File root; 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()) if (!root.isDirectory())
throw new IllegalArgumentException(); throw new IllegalArgumentException();
this.root = root; this.root = root;
this.allow_symlinks = allow_symlinks;
this.root_path = root.getAbsolutePath();
} }
@Override @Override
protected InputStream getFileInput(String path, HttpRequest request, HttpResponse response) { 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); File file = new File(root, path);
if(!file.isFile())
return null;
if(!FileLockManager.getReadLock(file, 5000)) { /* Wait up to 5 seconds for lock */ if(!FileLockManager.getReadLock(file, 5000)) { /* Wait up to 5 seconds for lock */
Log.severe("Timeout waiting for lock on file " + file.getPath()); Log.severe("Timeout waiting for lock on file " + file.getPath());
return null; return null;
} }
FileInputStream result = null; FileInputStream result = null;
try { 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 { try {
result = new FileInputStream(file); result = new FileInputStream(file);
} catch (FileNotFoundException e) { } catch (FileNotFoundException e) {
@ -46,6 +59,7 @@ public class FilesystemHandler extends FileHandler {
return null; return null;
} }
protected void closeFileInput(String path, InputStream in) throws IOException { protected void closeFileInput(String path, InputStream in) throws IOException {
path = getNormalizedPath(path);
try { try {
super.closeFileInput(path, in); super.closeFileInput(path, in);
} finally { } finally {
@ -53,4 +67,28 @@ public class FilesystemHandler extends FileHandler {
FileLockManager.releaseReadLock(file); 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;
}
} }