Forbid Files.isHidden.
As Robert pointed out on #12465, it has the undesirable property of relying on the operating system. So it would be better to use a simple rule such as checking whether the file name starts with a dot.
This commit is contained in:
parent
a14913f7b6
commit
a832987ada
|
@ -49,6 +49,7 @@ import org.elasticsearch.common.Strings;
|
||||||
import org.elasticsearch.common.component.AbstractComponent;
|
import org.elasticsearch.common.component.AbstractComponent;
|
||||||
import org.elasticsearch.common.compress.CompressedXContent;
|
import org.elasticsearch.common.compress.CompressedXContent;
|
||||||
import org.elasticsearch.common.inject.Inject;
|
import org.elasticsearch.common.inject.Inject;
|
||||||
|
import org.elasticsearch.common.io.FileSystemUtils;
|
||||||
import org.elasticsearch.common.io.Streams;
|
import org.elasticsearch.common.io.Streams;
|
||||||
import org.elasticsearch.common.regex.Regex;
|
import org.elasticsearch.common.regex.Regex;
|
||||||
import org.elasticsearch.common.settings.Settings;
|
import org.elasticsearch.common.settings.Settings;
|
||||||
|
@ -465,7 +466,7 @@ public class MetaDataCreateIndexService extends AbstractComponent {
|
||||||
try (DirectoryStream<Path> stream = Files.newDirectoryStream(mappingsDir)) {
|
try (DirectoryStream<Path> stream = Files.newDirectoryStream(mappingsDir)) {
|
||||||
for (Path mappingFile : stream) {
|
for (Path mappingFile : stream) {
|
||||||
final String fileName = mappingFile.getFileName().toString();
|
final String fileName = mappingFile.getFileName().toString();
|
||||||
if (Files.isHidden(mappingFile)) {
|
if (FileSystemUtils.isHidden(mappingFile)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
int lastDotIndex = fileName.lastIndexOf('.');
|
int lastDotIndex = fileName.lastIndexOf('.');
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
package org.elasticsearch.common.io;
|
package org.elasticsearch.common.io;
|
||||||
|
|
||||||
import com.google.common.collect.Iterators;
|
import com.google.common.collect.Iterators;
|
||||||
|
|
||||||
import org.apache.lucene.util.IOUtils;
|
import org.apache.lucene.util.IOUtils;
|
||||||
import org.elasticsearch.common.logging.ESLogger;
|
import org.elasticsearch.common.logging.ESLogger;
|
||||||
|
|
||||||
|
@ -84,6 +85,20 @@ public final class FileSystemUtils {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check whether the file denoted by the given path is hidden.
|
||||||
|
* In practice, this will check if the file name starts with a dot.
|
||||||
|
* This should be preferred to {@link Files#isHidden(Path)} as this
|
||||||
|
* does not depend on the operating system.
|
||||||
|
*/
|
||||||
|
public static boolean isHidden(Path path) {
|
||||||
|
Path fileName = path.getFileName();
|
||||||
|
if (fileName == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return fileName.toString().startsWith(".");
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Appends the path to the given base and strips N elements off the path if strip is > 0.
|
* Appends the path to the given base and strips N elements off the path if strip is > 0.
|
||||||
*/
|
*/
|
||||||
|
@ -334,4 +349,5 @@ public final class FileSystemUtils {
|
||||||
return Iterators.toArray(stream.iterator(), Path.class);
|
return Iterators.toArray(stream.iterator(), Path.class);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,6 +23,7 @@ import com.google.common.collect.ImmutableMap;
|
||||||
|
|
||||||
import org.elasticsearch.common.component.AbstractLifecycleComponent;
|
import org.elasticsearch.common.component.AbstractLifecycleComponent;
|
||||||
import org.elasticsearch.common.inject.Inject;
|
import org.elasticsearch.common.inject.Inject;
|
||||||
|
import org.elasticsearch.common.io.FileSystemUtils;
|
||||||
import org.elasticsearch.common.settings.Settings;
|
import org.elasticsearch.common.settings.Settings;
|
||||||
import org.elasticsearch.env.Environment;
|
import org.elasticsearch.env.Environment;
|
||||||
import org.elasticsearch.node.service.NodeService;
|
import org.elasticsearch.node.service.NodeService;
|
||||||
|
@ -183,7 +184,7 @@ public class HttpServer extends AbstractLifecycleComponent<HttpServer> {
|
||||||
Path file = siteFile.resolve(sitePath);
|
Path file = siteFile.resolve(sitePath);
|
||||||
|
|
||||||
// return not found instead of forbidden to prevent malicious requests to find out if files exist or dont exist
|
// return not found instead of forbidden to prevent malicious requests to find out if files exist or dont exist
|
||||||
if (!Files.exists(file) || Files.isHidden(file) || !file.toAbsolutePath().normalize().startsWith(siteFile.toAbsolutePath().normalize())) {
|
if (!Files.exists(file) || FileSystemUtils.isHidden(file) || !file.toAbsolutePath().normalize().startsWith(siteFile.toAbsolutePath().normalize())) {
|
||||||
channel.sendResponse(new BytesRestResponse(NOT_FOUND));
|
channel.sendResponse(new BytesRestResponse(NOT_FOUND));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -197,7 +198,7 @@ public class HttpServer extends AbstractLifecycleComponent<HttpServer> {
|
||||||
}
|
}
|
||||||
// We don't serve dir but if index.html exists in dir we should serve it
|
// We don't serve dir but if index.html exists in dir we should serve it
|
||||||
file = file.resolve("index.html");
|
file = file.resolve("index.html");
|
||||||
if (!Files.exists(file) || Files.isHidden(file) || !Files.isRegularFile(file)) {
|
if (!Files.exists(file) || FileSystemUtils.isHidden(file) || !Files.isRegularFile(file)) {
|
||||||
channel.sendResponse(new BytesRestResponse(FORBIDDEN));
|
channel.sendResponse(new BytesRestResponse(FORBIDDEN));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,7 +23,6 @@ import com.google.common.collect.ImmutableList;
|
||||||
import com.google.common.collect.ImmutableMap;
|
import com.google.common.collect.ImmutableMap;
|
||||||
|
|
||||||
import org.elasticsearch.ElasticsearchException;
|
import org.elasticsearch.ElasticsearchException;
|
||||||
import org.elasticsearch.Version;
|
|
||||||
import org.elasticsearch.action.admin.cluster.node.info.PluginsInfo;
|
import org.elasticsearch.action.admin.cluster.node.info.PluginsInfo;
|
||||||
import org.elasticsearch.bootstrap.Bootstrap;
|
import org.elasticsearch.bootstrap.Bootstrap;
|
||||||
import org.elasticsearch.bootstrap.JarHell;
|
import org.elasticsearch.bootstrap.JarHell;
|
||||||
|
@ -33,6 +32,7 @@ import org.elasticsearch.common.collect.Tuple;
|
||||||
import org.elasticsearch.common.component.AbstractComponent;
|
import org.elasticsearch.common.component.AbstractComponent;
|
||||||
import org.elasticsearch.common.component.LifecycleComponent;
|
import org.elasticsearch.common.component.LifecycleComponent;
|
||||||
import org.elasticsearch.common.inject.Module;
|
import org.elasticsearch.common.inject.Module;
|
||||||
|
import org.elasticsearch.common.io.FileSystemUtils;
|
||||||
import org.elasticsearch.common.logging.ESLogger;
|
import org.elasticsearch.common.logging.ESLogger;
|
||||||
import org.elasticsearch.common.logging.Loggers;
|
import org.elasticsearch.common.logging.Loggers;
|
||||||
import org.elasticsearch.common.settings.Settings;
|
import org.elasticsearch.common.settings.Settings;
|
||||||
|
@ -40,7 +40,6 @@ import org.elasticsearch.env.Environment;
|
||||||
|
|
||||||
import java.io.Closeable;
|
import java.io.Closeable;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.net.URLClassLoader;
|
import java.net.URLClassLoader;
|
||||||
|
@ -54,7 +53,6 @@ import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Properties;
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import static org.elasticsearch.common.io.FileSystemUtils.isAccessibleDirectory;
|
import static org.elasticsearch.common.io.FileSystemUtils.isAccessibleDirectory;
|
||||||
|
@ -312,7 +310,7 @@ public class PluginsService extends AbstractComponent {
|
||||||
try (DirectoryStream<Path> stream = Files.newDirectoryStream(pluginsDirectory)) {
|
try (DirectoryStream<Path> stream = Files.newDirectoryStream(pluginsDirectory)) {
|
||||||
for (Path plugin : stream) {
|
for (Path plugin : stream) {
|
||||||
try {
|
try {
|
||||||
if (Files.isHidden(plugin)) {
|
if (FileSystemUtils.isHidden(plugin)) {
|
||||||
logger.trace("--- skip hidden plugin file[{}]", plugin.toAbsolutePath());
|
logger.trace("--- skip hidden plugin file[{}]", plugin.toAbsolutePath());
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,6 +32,7 @@ import java.net.URISyntaxException;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertFileExists;
|
import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertFileExists;
|
||||||
import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertFileNotExists;
|
import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertFileNotExists;
|
||||||
|
@ -173,4 +174,39 @@ public class FileSystemUtilsTests extends ElasticsearchTestCase {
|
||||||
assertEquals(FileSystemUtils.append(PathUtils.get("/foo/bar"), PathUtils.get("/hello/world/this_is/awesome"), 1),
|
assertEquals(FileSystemUtils.append(PathUtils.get("/foo/bar"), PathUtils.get("/hello/world/this_is/awesome"), 1),
|
||||||
PathUtils.get("/foo/bar/world/this_is/awesome"));
|
PathUtils.get("/foo/bar/world/this_is/awesome"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testIsHidden() {
|
||||||
|
for (String p : Arrays.asList(
|
||||||
|
"/",
|
||||||
|
"foo",
|
||||||
|
"/foo",
|
||||||
|
"foo.bar",
|
||||||
|
"/foo.bar",
|
||||||
|
"foo/bar",
|
||||||
|
"foo/./bar",
|
||||||
|
"foo/../bar",
|
||||||
|
"/foo/./bar",
|
||||||
|
"/foo/../bar"
|
||||||
|
)) {
|
||||||
|
Path path = PathUtils.get(p);
|
||||||
|
assertFalse(FileSystemUtils.isHidden(path));
|
||||||
|
}
|
||||||
|
for (String p : Arrays.asList(
|
||||||
|
".hidden",
|
||||||
|
".hidden.ext",
|
||||||
|
"/.hidden",
|
||||||
|
"/.hidden.ext",
|
||||||
|
"foo/.hidden",
|
||||||
|
"foo/.hidden.ext",
|
||||||
|
"/foo/.hidden",
|
||||||
|
"/foo/.hidden.ext",
|
||||||
|
".",
|
||||||
|
"..",
|
||||||
|
"foo/.",
|
||||||
|
"foo/.."
|
||||||
|
)) {
|
||||||
|
Path path = PathUtils.get(p);
|
||||||
|
assertTrue(FileSystemUtils.isHidden(path));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -61,3 +61,5 @@ java.io.ObjectOutputStream
|
||||||
java.io.ObjectOutput
|
java.io.ObjectOutput
|
||||||
java.io.ObjectInputStream
|
java.io.ObjectInputStream
|
||||||
java.io.ObjectInput
|
java.io.ObjectInput
|
||||||
|
|
||||||
|
java.nio.file.Files#isHidden(java.nio.file.Path) @ Dependent on the operating system, use FileSystemUtils.isHidden instead
|
||||||
|
|
Loading…
Reference in New Issue