Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,8 @@
import java.nio.file.attribute.FileAttribute;
import java.nio.file.attribute.UserPrincipal;
import java.nio.file.spi.FileSystemProvider;
import java.security.KeyStore;
import java.security.Provider;
import java.security.cert.CertStoreParameters;
import java.util.List;
import java.util.Locale;
Expand Down Expand Up @@ -621,12 +623,50 @@ public interface EntitlementChecker {

void check$java_io_RandomAccessFile$(Class<?> callerClass, File file, String mode);

void check$java_security_KeyStore$$getInstance(Class<?> callerClass, File file, char[] password);

void check$java_security_KeyStore$$getInstance(Class<?> callerClass, File file, KeyStore.LoadStoreParameter param);

void check$java_security_KeyStore$Builder$$newInstance(Class<?> callerClass, File file, KeyStore.ProtectionParameter protection);

void check$java_security_KeyStore$Builder$$newInstance(
Class<?> callerClass,
String type,
Provider provider,
File file,
KeyStore.ProtectionParameter protection
);

void check$java_util_Scanner$(Class<?> callerClass, File source);

void check$java_util_Scanner$(Class<?> callerClass, File source, String charsetName);

void check$java_util_Scanner$(Class<?> callerClass, File source, Charset charset);

void check$java_util_jar_JarFile$(Class<?> callerClass, String name);

void check$java_util_jar_JarFile$(Class<?> callerClass, String name, boolean verify);

void check$java_util_jar_JarFile$(Class<?> callerClass, File file);

void check$java_util_jar_JarFile$(Class<?> callerClass, File file, boolean verify);

void check$java_util_jar_JarFile$(Class<?> callerClass, File file, boolean verify, int mode);

void check$java_util_jar_JarFile$(Class<?> callerClass, File file, boolean verify, int mode, Runtime.Version version);

void check$java_util_zip_ZipFile$(Class<?> callerClass, String name);

void check$java_util_zip_ZipFile$(Class<?> callerClass, String name, Charset charset);

void check$java_util_zip_ZipFile$(Class<?> callerClass, File file);

void check$java_util_zip_ZipFile$(Class<?> callerClass, File file, int mode);

void check$java_util_zip_ZipFile$(Class<?> callerClass, File file, Charset charset);

void check$java_util_zip_ZipFile$(Class<?> callerClass, File file, int mode, Charset charset);

// nio
void check$java_nio_file_Files$$getOwner(Class<?> callerClass, Path path, LinkOption... options);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

package org.elasticsearch.entitlement.qa.test;

import org.elasticsearch.core.CheckedRunnable;
import org.elasticsearch.core.SuppressForbidden;
import org.elasticsearch.entitlement.qa.entitled.EntitledActions;

Expand All @@ -26,12 +27,22 @@
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.attribute.UserPrincipal;
import java.security.GeneralSecurityException;
import java.security.KeyStore;
import java.util.Scanner;

import java.util.jar.JarFile;
import java.util.zip.ZipException;
import java.util.zip.ZipFile;

import static java.nio.charset.Charset.defaultCharset;
import static java.util.zip.ZipFile.OPEN_DELETE;
import static java.util.zip.ZipFile.OPEN_READ;
import static org.elasticsearch.entitlement.qa.entitled.EntitledActions.createTempFileForWrite;
import static org.elasticsearch.entitlement.qa.test.EntitlementTest.ExpectedAccess.ALWAYS_DENIED;
import static org.elasticsearch.entitlement.qa.test.EntitlementTest.ExpectedAccess.PLUGINS;

@SuppressForbidden(reason = "Explicitly checking APIs that are forbidden")
@SuppressWarnings("unused") // Called via reflection
class FileCheckActions {

static Path testRootDir = Paths.get(System.getProperty("es.entitlements.testdir"));
Expand Down Expand Up @@ -207,21 +218,6 @@ static void fileSetWritableOwner() throws IOException {
readWriteFile().toFile().setWritable(true, false);
}

@EntitlementTest(expectedAccess = PLUGINS)
static void createScannerFile() throws FileNotFoundException {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Aren't all of the rest of the methods in this file also in java.base? I don't understand the distinction as to why they belong in a separate files vs in this one.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh I didn't check. I just moved over the ones that were on the spreadsheet tab.

What would you like to do? Merge them together?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe split them based on some explainable attributes? I don't feel strongly, but it seems like having a test file that implies java.base classes should be tested in it, yet other test files contain java.base classes, will cause confusion.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure I can explain why these ended up in their own spreadsheet tab. Maybe I'll just merge them into FileCheckActions.

new Scanner(readFile().toFile());
}

@EntitlementTest(expectedAccess = PLUGINS)
static void createScannerFileWithCharset() throws IOException {
new Scanner(readFile().toFile(), StandardCharsets.UTF_8);
}

@EntitlementTest(expectedAccess = PLUGINS)
static void createScannerFileWithCharsetName() throws FileNotFoundException {
new Scanner(readFile().toFile(), "UTF-8");
}

@EntitlementTest(expectedAccess = PLUGINS)
static void createFileInputStreamFile() throws IOException {
new FileInputStream(readFile().toFile()).close();
Expand Down Expand Up @@ -363,5 +359,140 @@ static void filesSetOwner() throws IOException {
Files.setOwner(readWriteFile(), owner); // set to existing owner, just trying to execute the method
}

@EntitlementTest(expectedAccess = PLUGINS)
static void keystoreGetInstance_FileCharArray() throws IOException {
try {
KeyStore.getInstance(readFile().toFile(), new char[0]);
} catch (GeneralSecurityException expected) {
return;
}
throw new AssertionError("Expected an exception");
}

@EntitlementTest(expectedAccess = PLUGINS)
static void keystoreGetInstance_FileLoadStoreParameter() throws IOException {
try {
KeyStore.LoadStoreParameter loadStoreParameter = () -> null;
KeyStore.getInstance(readFile().toFile(), loadStoreParameter);
} catch (GeneralSecurityException expected) {
return;
}
throw new AssertionError("Expected an exception");
}

@EntitlementTest(expectedAccess = PLUGINS)
static void keystoreBuilderNewInstance() {
try {
KeyStore.Builder.newInstance("", null, readFile().toFile(), null);
} catch (NullPointerException expected) {
return;
}
throw new AssertionError("Expected an exception");
}

@EntitlementTest(expectedAccess = PLUGINS)
static void zipFile_String() throws IOException {
expectZipException(() -> new ZipFile(readFile().toString()).close());
}

@EntitlementTest(expectedAccess = PLUGINS)
static void zipFile_StringCharset() throws IOException {
expectZipException(() -> new ZipFile(readFile().toString(), defaultCharset()).close());
}

@EntitlementTest(expectedAccess = PLUGINS)
static void zipFile_File() throws IOException {
expectZipException(() -> new ZipFile(readFile().toFile()).close());
}

@EntitlementTest(expectedAccess = PLUGINS)
static void zipFile_FileCharset() throws IOException {
expectZipException(() -> new ZipFile(readFile().toFile(), defaultCharset()).close());
}

@EntitlementTest(expectedAccess = PLUGINS)
static void zipFile_FileReadOnly() throws IOException {
expectZipException(() -> new ZipFile(readFile().toFile(), OPEN_READ).close());
}

@EntitlementTest(expectedAccess = PLUGINS)
static void zipFile_FileReadAndDelete() throws IOException {
expectZipException(() -> new ZipFile(createTempFileForWrite().toFile(), OPEN_READ | OPEN_DELETE).close());
}

@EntitlementTest(expectedAccess = PLUGINS)
static void zipFile_ReadOnlyCharset() throws IOException {
expectZipException(() -> new ZipFile(readFile().toFile(), OPEN_READ, defaultCharset()).close());
}

@EntitlementTest(expectedAccess = PLUGINS)
static void zipFile_ReadAndDeleteCharset() throws IOException {
expectZipException(() -> new ZipFile(createTempFileForWrite().toFile(), OPEN_READ | OPEN_DELETE, defaultCharset()).close());
}

@EntitlementTest(expectedAccess = PLUGINS)
static void jarFile_String() throws IOException {
expectZipException(() -> new JarFile(readFile().toString()).close());
}

@EntitlementTest(expectedAccess = PLUGINS)
static void jarFile_StringBoolean() throws IOException {
expectZipException(() -> new JarFile(readFile().toString(), false).close());
}

@EntitlementTest(expectedAccess = PLUGINS)
static void jarFile_FileReadOnly() throws IOException {
expectZipException(() -> new JarFile(readFile().toFile(), false, OPEN_READ).close());
}

@EntitlementTest(expectedAccess = PLUGINS)
static void jarFile_FileReadAndDelete() throws IOException {
expectZipException(() -> new JarFile(createTempFileForWrite().toFile(), false, OPEN_READ | OPEN_DELETE).close());
}

@EntitlementTest(expectedAccess = PLUGINS)
static void jarFile_FileBooleanReadOnlyVersion() throws IOException {
expectZipException(() -> new JarFile(readFile().toFile(), false, OPEN_READ, Runtime.version()).close());
}

@EntitlementTest(expectedAccess = PLUGINS)
static void jarFile_FileBooleanReadAndDeleteOnlyVersion() throws IOException {
expectZipException(() -> new JarFile(createTempFileForWrite().toFile(), false, OPEN_READ | OPEN_DELETE, Runtime.version()).close());
}

@EntitlementTest(expectedAccess = PLUGINS)
static void jarFile_File() throws IOException {
expectZipException(() -> new JarFile(readFile().toFile()).close());
}

@EntitlementTest(expectedAccess = PLUGINS)
static void jarFileFileBoolean() throws IOException {
expectZipException(() -> new JarFile(readFile().toFile(), false).close());
}

private static void expectZipException(CheckedRunnable<IOException> action) throws IOException {
try {
action.run();
} catch (ZipException expected) {
return;
}
throw new AssertionError("Expected an exception");
}

@EntitlementTest(expectedAccess = PLUGINS)
static void createScannerFile() throws FileNotFoundException {
new Scanner(readFile().toFile());
}

@EntitlementTest(expectedAccess = PLUGINS)
static void createScannerFileWithCharset() throws IOException {
new Scanner(readFile().toFile(), StandardCharsets.UTF_8);
}

@EntitlementTest(expectedAccess = PLUGINS)
static void createScannerFileWithCharsetName() throws FileNotFoundException {
new Scanner(readFile().toFile(), "UTF-8");
}

private FileCheckActions() {}
}
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,8 @@
import java.nio.file.attribute.FileAttribute;
import java.nio.file.attribute.UserPrincipal;
import java.nio.file.spi.FileSystemProvider;
import java.security.KeyStore;
import java.security.Provider;
import java.security.cert.CertStoreParameters;
import java.util.List;
import java.util.Locale;
Expand Down Expand Up @@ -1232,6 +1234,36 @@ public void checkSelectorProviderInheritedChannel(Class<?> callerClass, Selector
}
}

@Override
public void check$java_security_KeyStore$$getInstance(Class<?> callerClass, File file, char[] password) {
policyManager.checkFileRead(callerClass, file);
}

@Override
public void check$java_security_KeyStore$$getInstance(Class<?> callerClass, File file, KeyStore.LoadStoreParameter param) {
policyManager.checkFileRead(callerClass, file);
}

@Override
public void check$java_security_KeyStore$Builder$$newInstance(
Class<?> callerClass,
File file,
KeyStore.ProtectionParameter protection
) {
policyManager.checkFileRead(callerClass, file);
}

@Override
public void check$java_security_KeyStore$Builder$$newInstance(
Class<?> callerClass,
String type,
Provider provider,
File file,
KeyStore.ProtectionParameter protection
) {
policyManager.checkFileRead(callerClass, file);
}

@Override
public void check$java_util_Scanner$(Class<?> callerClass, File source) {
policyManager.checkFileRead(callerClass, source);
Expand All @@ -1247,6 +1279,66 @@ public void checkSelectorProviderInheritedChannel(Class<?> callerClass, Selector
policyManager.checkFileRead(callerClass, source);
}

@Override
public void check$java_util_jar_JarFile$(Class<?> callerClass, String name) {
policyManager.checkFileRead(callerClass, new File(name));
}

@Override
public void check$java_util_jar_JarFile$(Class<?> callerClass, String name, boolean verify) {
policyManager.checkFileRead(callerClass, new File(name));
}

@Override
public void check$java_util_jar_JarFile$(Class<?> callerClass, File file) {
policyManager.checkFileRead(callerClass, file);
}

@Override
public void check$java_util_jar_JarFile$(Class<?> callerClass, File file, boolean verify) {
policyManager.checkFileRead(callerClass, file);
}

@Override
public void check$java_util_jar_JarFile$(Class<?> callerClass, File file, boolean verify, int mode) {
policyManager.checkFileWithZipMode(callerClass, file, mode);
}

@Override
public void check$java_util_jar_JarFile$(Class<?> callerClass, File file, boolean verify, int mode, Runtime.Version version) {
policyManager.checkFileWithZipMode(callerClass, file, mode);
}

@Override
public void check$java_util_zip_ZipFile$(Class<?> callerClass, String name) {
policyManager.checkFileRead(callerClass, new File(name));
}

@Override
public void check$java_util_zip_ZipFile$(Class<?> callerClass, String name, Charset charset) {
policyManager.checkFileRead(callerClass, new File(name));
}

@Override
public void check$java_util_zip_ZipFile$(Class<?> callerClass, File file) {
policyManager.checkFileRead(callerClass, file);
}

@Override
public void check$java_util_zip_ZipFile$(Class<?> callerClass, File file, int mode) {
policyManager.checkFileWithZipMode(callerClass, file, mode);
}

@Override
public void check$java_util_zip_ZipFile$(Class<?> callerClass, File file, Charset charset) {
policyManager.checkFileRead(callerClass, file);
}

@Override
public void check$java_util_zip_ZipFile$(Class<?> callerClass, File file, int mode, Charset charset) {
policyManager.checkFileWithZipMode(callerClass, file, mode);
}

// nio

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@
import static java.util.function.Predicate.not;
import static java.util.stream.Collectors.groupingBy;
import static java.util.stream.Collectors.toUnmodifiableMap;
import static java.util.zip.ZipFile.OPEN_DELETE;
import static java.util.zip.ZipFile.OPEN_READ;

public class PolicyManager {
private static final Logger logger = LogManager.getLogger(PolicyManager.class);
Expand Down Expand Up @@ -304,6 +306,18 @@ public void checkFileWrite(Class<?> callerClass, Path path) {
}
}

@SuppressForbidden(reason = "Explicitly checking File apis")
public void checkFileWithZipMode(Class<?> callerClass, File file, int zipMode) {
assert zipMode == OPEN_READ || zipMode == (OPEN_READ | OPEN_DELETE);
if ((zipMode & OPEN_DELETE) == OPEN_DELETE) {
// This needs both read and write, but we happen to know that checkFileWrite
// actually checks both.
checkFileWrite(callerClass, file);
} else {
checkFileRead(callerClass, file);
}
}

public void checkFileDescriptorRead(Class<?> callerClass) {
neverEntitled(callerClass, () -> "read file descriptor");
}
Expand Down