diff --git a/docs/changelog/126990.yaml b/docs/changelog/126990.yaml new file mode 100644 index 000000000000..a8b875cc6a22 --- /dev/null +++ b/docs/changelog/126990.yaml @@ -0,0 +1,7 @@ +pr: 126990 +summary: "Fix: consider case sensitiveness differences in Windows/Unix-like filesystems\ + \ for files entitlements" +area: Infra/Core +type: bug +issues: + - 127047 diff --git a/libs/entitlement/src/main/java/org/elasticsearch/entitlement/runtime/policy/CaseInsensitiveComparison.java b/libs/entitlement/src/main/java/org/elasticsearch/entitlement/runtime/policy/CaseInsensitiveComparison.java new file mode 100644 index 000000000000..4f122b9c36ed --- /dev/null +++ b/libs/entitlement/src/main/java/org/elasticsearch/entitlement/runtime/policy/CaseInsensitiveComparison.java @@ -0,0 +1,31 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the "Elastic License + * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side + * Public License v 1"; you may not use this file except in compliance with, at + * your election, the "Elastic License 2.0", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +package org.elasticsearch.entitlement.runtime.policy; + +class CaseInsensitiveComparison extends FileAccessTreeComparison { + + CaseInsensitiveComparison(char separatorChar) { + super(CaseInsensitiveComparison::caseInsensitiveCharacterComparator, separatorChar); + } + + private static int caseInsensitiveCharacterComparator(char c1, char c2) { + return Character.compare(Character.toLowerCase(c1), Character.toLowerCase(c2)); + } + + @Override + protected boolean pathStartsWith(String pathString, String pathPrefix) { + return pathString.regionMatches(true, 0, pathPrefix, 0, pathPrefix.length()); + } + + @Override + protected boolean pathsAreEqual(String path1, String path2) { + return path1.equalsIgnoreCase(path2); + } +} diff --git a/libs/entitlement/src/main/java/org/elasticsearch/entitlement/runtime/policy/CaseSensitiveComparison.java b/libs/entitlement/src/main/java/org/elasticsearch/entitlement/runtime/policy/CaseSensitiveComparison.java new file mode 100644 index 000000000000..700dc4b7cc79 --- /dev/null +++ b/libs/entitlement/src/main/java/org/elasticsearch/entitlement/runtime/policy/CaseSensitiveComparison.java @@ -0,0 +1,27 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the "Elastic License + * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side + * Public License v 1"; you may not use this file except in compliance with, at + * your election, the "Elastic License 2.0", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +package org.elasticsearch.entitlement.runtime.policy; + +class CaseSensitiveComparison extends FileAccessTreeComparison { + + CaseSensitiveComparison(char separatorChar) { + super(Character::compare, separatorChar); + } + + @Override + protected boolean pathStartsWith(String pathString, String pathPrefix) { + return pathString.startsWith(pathPrefix); + } + + @Override + protected boolean pathsAreEqual(String path1, String path2) { + return path1.equals(path2); + } +} diff --git a/libs/entitlement/src/main/java/org/elasticsearch/entitlement/runtime/policy/FileAccessTree.java b/libs/entitlement/src/main/java/org/elasticsearch/entitlement/runtime/policy/FileAccessTree.java index 4b3b7cca75db..5f9af60c802b 100644 --- a/libs/entitlement/src/main/java/org/elasticsearch/entitlement/runtime/policy/FileAccessTree.java +++ b/libs/entitlement/src/main/java/org/elasticsearch/entitlement/runtime/policy/FileAccessTree.java @@ -11,11 +11,13 @@ package org.elasticsearch.entitlement.runtime.policy; import org.elasticsearch.core.Nullable; import org.elasticsearch.core.Strings; +import org.elasticsearch.core.SuppressForbidden; import org.elasticsearch.entitlement.runtime.policy.entitlements.FilesEntitlement; import org.elasticsearch.entitlement.runtime.policy.entitlements.FilesEntitlement.Mode; import org.elasticsearch.logging.LogManager; import org.elasticsearch.logging.Logger; +import java.io.File; import java.io.IOException; import java.io.UncheckedIOException; import java.nio.file.Files; @@ -33,7 +35,6 @@ import java.util.function.BiConsumer; import static java.util.Comparator.comparing; import static org.elasticsearch.core.PathUtils.getDefaultFileSystem; -import static org.elasticsearch.entitlement.runtime.policy.FileUtils.PATH_ORDER; import static org.elasticsearch.entitlement.runtime.policy.PathLookup.BaseDir.CONFIG; import static org.elasticsearch.entitlement.runtime.policy.PathLookup.BaseDir.TEMP; import static org.elasticsearch.entitlement.runtime.policy.entitlements.FilesEntitlement.Mode.READ_WRITE; @@ -70,9 +71,9 @@ import static org.elasticsearch.entitlement.runtime.policy.entitlements.FilesEnt * Secondly, the path separator (whether slash or backslash) sorts after the dot character. This means, for example, if the array contains * {@code ["/a", "/a.xml"]} and we look up {@code "/a/b"} using normal string comparison, the binary search would land on {@code "/a.xml"}, * which is neither an exact match nor a containing directory, and so the lookup would incorrectly report no match, even though - * {@code "/a"} is in the array. To fix this, we define {@link FileUtils#PATH_ORDER} which sorts path separators before any other - * character. In the example, this would cause {@code "/a/b"} to sort between {@code "/a"} and {@code "/a.xml"} so that it correctly - * finds {@code "/a"}. + * {@code "/a"} is in the array. To fix this, we define {@link FileAccessTreeComparison#pathComparator()} which sorts path separators + * before any other character. In the example, this would cause {@code "/a/b"} to sort between {@code "/a"} and {@code "/a.xml"} so that + * it correctly finds {@code "/a"}. *

* With the paths pruned, sorted, and segregated by permission, each binary search has the following properties: *