Mercurial > hg > release > icedtea-web-1.8
changeset 1474:c234bad6f599
support creating cache files with restricted access on windows
author | Alex Kashchenko <akashche@redhat.com> |
---|---|
date | Wed, 08 Nov 2017 11:37:01 +0000 |
parents | a7dc403313cb |
children | 54f9b40dd843 |
files | netx/net/sourceforge/jnlp/util/FileUtils.java tests/netx/unit/net/sourceforge/jnlp/util/FileUtilsTest.java |
diffstat | 2 files changed, 74 insertions(+), 32 deletions(-) [+] |
line wrap: on
line diff
--- a/netx/net/sourceforge/jnlp/util/FileUtils.java Fri Nov 03 12:39:31 2017 +0100 +++ b/netx/net/sourceforge/jnlp/util/FileUtils.java Wed Nov 08 11:37:01 2017 +0000 @@ -33,12 +33,12 @@ import java.io.Writer; import java.nio.channels.FileChannel; import java.nio.channels.FileLock; +import java.nio.file.Files; +import java.nio.file.attribute.*; import java.security.DigestInputStream; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; +import java.util.*; import javax.swing.JFrame; import javax.swing.JOptionPane; @@ -60,6 +60,8 @@ private static final String WIN_DRIVE_LETTER_COLON_WILDCHAR = "WINDOWS_VERY_SPECIFIC_DOUBLEDOT"; + private static final List<String> WIN_ROOT_PRINCIPALS = Arrays.asList("NT AUTHORITY\\SYSTEM", "BUILTIN\\Administrators"); + /** * Indicates whether a file was successfully opened. If not, provides specific reasons * along with a general failure case @@ -242,37 +244,52 @@ } if (JNLPRuntime.isWindows()) { - // remove all permissions - if (!tempFile.setExecutable(false, false)) { - OutputController.getLogger().log(OutputController.Level.ERROR_ALL, R("RRemoveXPermFailed", tempFile)); - } - if (!tempFile.setReadable(false, false)) { - OutputController.getLogger().log(OutputController.Level.ERROR_ALL, R("RRemoveRPermFailed", tempFile)); - } - if (!tempFile.setWritable(false, false)) { - OutputController.getLogger().log(OutputController.Level.ERROR_ALL, R("RRemoveWPermFailed", tempFile)); - } - - // allow owner to read - if (!tempFile.setReadable(true, true)) { - OutputController.getLogger().log(OutputController.Level.ERROR_ALL, R("RGetRPermFailed", tempFile)); + // prepare ACL flags + Set<AclEntryFlag> flags = new LinkedHashSet<>(); + if (tempFile.isDirectory()) { + flags.add(AclEntryFlag.DIRECTORY_INHERIT); + flags.add(AclEntryFlag.FILE_INHERIT); } - // allow owner to write - if (writableByOwner && !tempFile.setWritable(true, true)) { - OutputController.getLogger().log(OutputController.Level.ERROR_ALL, R("RGetWPermFailed", tempFile)); + // prepare ACL permissions + Set<AclEntryPermission> permissions = new LinkedHashSet<>(); + permissions.addAll(Arrays.asList( + AclEntryPermission.READ_DATA, + AclEntryPermission.READ_NAMED_ATTRS, + AclEntryPermission.EXECUTE, + AclEntryPermission.READ_ATTRIBUTES, + AclEntryPermission.READ_ACL, + AclEntryPermission.SYNCHRONIZE)); + if (writableByOwner) { + permissions.addAll(Arrays.asList( + AclEntryPermission.WRITE_DATA, + AclEntryPermission.APPEND_DATA, + AclEntryPermission.WRITE_NAMED_ATTRS, + AclEntryPermission.DELETE_CHILD, + AclEntryPermission.WRITE_ATTRIBUTES, + AclEntryPermission.DELETE, + AclEntryPermission.WRITE_ACL, + AclEntryPermission.WRITE_OWNER)); } - // allow owner to enter directories - if (isDir && !tempFile.setExecutable(true, true)) { - OutputController.getLogger().log(OutputController.Level.ERROR_ALL, R("RGetXPermFailed", tempFile)); + // filter ACL's leaving only root and owner + AclFileAttributeView view = Files.getFileAttributeView(tempFile.toPath(), AclFileAttributeView.class); + List<AclEntry> list = new ArrayList<>(); + String owner = view.getOwner().getName(); + for (AclEntry ae : view.getAcl()) { + String principalName = ae.principal().getName(); + if (WIN_ROOT_PRINCIPALS.contains(principalName) || owner.equals(principalName)) { + list.add(AclEntry.newBuilder() + .setType(AclEntryType.ALLOW) + .setPrincipal(ae.principal()) + .setPermissions(permissions) + .setFlags(flags) + .build()); + } } - // rename this file. Unless the file is moved/renamed, any program that - // opened the file right after it was created might still be able to - // read the data. - if (!tempFile.renameTo(file)) { - OutputController.getLogger().log(OutputController.Level.ERROR_ALL, R("RCantRename", tempFile, file)); - } + + // apply ACL + view.setAcl(list); } else { // remove all permissions if (!tempFile.setExecutable(false, false)) { @@ -299,15 +316,14 @@ if (isDir && !tempFile.setExecutable(true, true)) { throw new IOException(R("RGetXPermFailed", tempFile)); } - + } + // rename this file. Unless the file is moved/renamed, any program that // opened the file right after it was created might still be able to // read the data. if (!tempFile.renameTo(file)) { throw new IOException(R("RCantRename", tempFile, file)); } - } - } /**
--- a/tests/netx/unit/net/sourceforge/jnlp/util/FileUtilsTest.java Fri Nov 03 12:39:31 2017 +0100 +++ b/tests/netx/unit/net/sourceforge/jnlp/util/FileUtilsTest.java Wed Nov 08 11:37:01 2017 +0000 @@ -37,6 +37,9 @@ package net.sourceforge.jnlp.util; import java.io.File; +import java.nio.file.Files; +import java.nio.file.attribute.AclEntry; +import java.nio.file.attribute.AclFileAttributeView; import java.util.ArrayList; import java.util.Arrays; import java.util.List; @@ -130,4 +133,27 @@ assertFalse(testChild.exists()); } + @Test + public void testCreateRestrictedFile() throws Exception { + if (!JNLPRuntime.isWindows()) { + return; + } + final File tmpdir = new File(System.getProperty("java.io.tmpdir")), testfile = new File(tmpdir, "itw_test_create_restricted_file"); + if (testfile.exists()) { + assertTrue(testfile.delete()); + } + testfile.deleteOnExit(); + FileUtils.createRestrictedFile(testfile, true); + boolean hasOwner = false; + AclFileAttributeView view = Files.getFileAttributeView(testfile.toPath(), AclFileAttributeView.class); + for (AclEntry ae : view.getAcl()) { + if (view.getOwner().getName().equals(ae.principal().getName())) { + assertFalse("Duplicate owner entry", hasOwner); + hasOwner = true; + assertEquals("Owner must have all perimissions",14, ae.permissions().size()); + } + } + assertTrue("No owner entry", hasOwner); + } + }