You are viewing a plain text version of this content. The canonical link for it is here.
Posted to derby-commits@db.apache.org by ka...@apache.org on 2016/02/05 14:49:04 UTC

svn commit: r1728667 - in /db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests: tests/engine/RestrictiveFilePermissionsTest.java util/PrivilegedFileOpsForTests.java

Author: kahatlen
Date: Fri Feb  5 13:49:03 2016
New Revision: 1728667

URL: http://svn.apache.org/viewvc?rev=1728667&view=rev
Log:
DERBY-6865: RestrictiveFilePermissionsTest fails on Windows

Remove use of reflection in the test. Reflection was used to access
functionality only available on Java 7 and higher. Since Java 8 is
the minimum level now, reflection is no longer needed.

This doesn't fix the test failure, but it makes it easier to debug
the test.

Modified:
    db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/engine/RestrictiveFilePermissionsTest.java
    db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/util/PrivilegedFileOpsForTests.java

Modified: db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/engine/RestrictiveFilePermissionsTest.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/engine/RestrictiveFilePermissionsTest.java?rev=1728667&r1=1728666&r2=1728667&view=diff
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/engine/RestrictiveFilePermissionsTest.java (original)
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/engine/RestrictiveFilePermissionsTest.java Fri Feb  5 13:49:03 2016
@@ -21,11 +21,15 @@
 package org.apache.derbyTesting.functionTests.tests.engine;
 
 import java.io.File;
-import java.lang.reflect.Array;
-import java.lang.reflect.Field;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
 import java.net.URL;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.nio.file.attribute.AclEntry;
+import java.nio.file.attribute.AclFileAttributeView;
+import java.nio.file.attribute.PosixFileAttributeView;
+import java.nio.file.attribute.PosixFilePermission;
+import java.nio.file.attribute.UserPrincipal;
 import java.security.AccessController;
 import java.security.PrivilegedExceptionAction;
 import java.sql.CallableStatement;
@@ -33,16 +37,14 @@ import java.sql.Connection;
 import java.sql.PreparedStatement;
 import java.sql.SQLException;
 import java.sql.Statement;
+import java.util.Arrays;
+import java.util.Collections;
 import java.util.HashSet;
-import java.util.Iterator;
-import java.util.List;
 import java.util.Properties;
 import java.util.Set;
 import javax.sql.DataSource;
 import junit.framework.Test;
 import org.apache.derby.drda.NetworkServerControl;
-import org.apache.derby.iapi.services.info.JVMInfo;
-import org.apache.derby.shared.common.sanity.SanityManager;
 import org.apache.derbyTesting.functionTests.util.PrivilegedFileOpsForTests;
 import org.apache.derbyTesting.functionTests.util.SQLStateConstants;
 import org.apache.derbyTesting.functionTests.util.streams.LoopingAlphabetReader;
@@ -80,14 +82,6 @@ public class RestrictiveFilePermissionsT
 
 
     public static Test suite() throws Exception {
-        // We can not test file permissions before Java 1.7
-        if (JVMInfo.JDK_ID < JVMInfo.J2SE_17) {
-            println("warning: testing of strict permissions in " +
-                    "RestrictiveFilePermissionsTest can not take place, " +
-                    "need Java 7");
-            return new BaseTestSuite();
-        }
-
         File f = new File("system/testPermissions");
         assertTrue(f.mkdirs());
 
@@ -501,51 +495,18 @@ public class RestrictiveFilePermissionsT
     final public static int UNKNOWN = 2;
 
     // Members used by limitAccessToOwner
-    private static boolean initialized = false;
+    private static final Set<PosixFilePermission> UNWANTED_PERMISSIONS =
+            Collections.unmodifiableSet(new HashSet<>(Arrays.asList(
+                    PosixFilePermission.GROUP_EXECUTE,
+                    PosixFilePermission.GROUP_READ,
+                    PosixFilePermission.GROUP_WRITE,
+                    PosixFilePermission.OTHERS_EXECUTE,
+                    PosixFilePermission.OTHERS_READ,
+                    PosixFilePermission.OTHERS_WRITE)));
 
-    // Reflection helper objects for calling into Java >= 7
-    private static Class<?> filesClz;
-    private static Class<?> pathClz;
-    private static Class<?> pathsClz;
-    private static Class<?> aclEntryClz;
-    private static Class<?> aclFileAttributeViewClz;
-    private static Class<?> posixFileAttributeViewClz;
-    private static Class<?> posixFileAttributesClz;
-    private static Class<?> posixFilePermissionClz;
-    private static Class<?> userPrincipalClz;
-    private static Class<?> linkOptionArrayClz;
-    private static Class<?> linkOptionClz;
-    private static Class<?> stringArrayClz;
-
-    private static Method get;
-    private static Method getFileAttributeView;
-    private static Method getOwner;
-    private static Method getAcl;
-    private static Method principal;
-    private static Method getName;
-    private static Method permissionsAcl;
-    private static Method permissionsPosix;
-    private static Method readAttributes;
-
-    private static Field GROUP_EXECUTE;
-    private static Field GROUP_READ;
-    private static Field GROUP_WRITE;
-    private static Field OTHERS_EXECUTE;
-    private static Field OTHERS_READ;
-    private static Field OTHERS_WRITE;
-    private static Set<Object> unwantedPermissions;
     /**
      * Check that the file has access only for the owner. Will throw (JUnit
      * failure) if permissions are not strict.
-     * <p/>
-     * We need Java 7 to ascertain whether we managed to restrict file
-     * permissions: The Java 6 {@code java.io.File} API only lets us check if
-     * this process has access.
-     * <p/>
-     * In this sense this testing code is asymmetric to the implementation in
-     * Derby: Java 6 can be used to restrict accesses in Java 6 on Unix, but
-     * we have no way in Java of checking the results in a portable way. So, if
-     * we do not have at least Java 7, this method will be a no-op.
      *
      * @param file (or directory) for which we want to check permissions
      * @param expectedOutcome NEGATIVE or POSITIVE
@@ -580,247 +541,68 @@ public class RestrictiveFilePermissionsT
         if (doContents) {
             // visit immediately contained file in this directory also
             checkAccessToOwner(file, false, expectedOutcome);
-
-            AccessController.doPrivileged(
-                    new PrivilegedExceptionAction<Void>() {
-                public Void run() throws Exception {
-                    File [] files = file.listFiles();
-                    for (int i = 0; i < files.length; i++){
-                        checkAccessToOwner(
-                            files[i], false, expectedOutcome);
-                    }
-                    return null;
-                }});
+            for (File f : PrivilegedFileOpsForTests.listFiles(file)) {
+                checkAccessToOwner(f, false, expectedOutcome);
+            }
         }
 
         return AccessController.
-            doPrivileged(new PrivilegedExceptionAction<Boolean>() {
-
-                public Boolean run() throws Exception {
-                    // lazy initialization
-                    if (!initialized) {
-                        initialized = true;
-
-                        // If found, we have >= Java 7.
-                        filesClz = Class.forName(
-                            "java.nio.file.Files");
-                        pathClz = Class.forName(
-                            "java.nio.file.Path");
-                        pathsClz = Class.forName(
-                            "java.nio.file.Paths");
-                        aclEntryClz = Class.forName(
-                            "java.nio.file.attribute.AclEntry");
-                        aclFileAttributeViewClz = Class.forName(
-                            "java.nio.file.attribute." +
-                            "AclFileAttributeView");
-                        posixFileAttributeViewClz = Class.forName(
-                            "java.nio.file.attribute." +
-                            "PosixFileAttributeView");
-                        posixFileAttributesClz = Class.forName(
-                            "java.nio.file.attribute." +
-                            "PosixFileAttributes");
-                        posixFilePermissionClz = Class.forName(
-                            "java.nio.file.attribute." +
-                            "PosixFilePermission");
-                        userPrincipalClz = Class.forName(
-                            "java.nio.file.attribute.UserPrincipal");
-                        linkOptionArrayClz = Class.forName(
-                            "[Ljava.nio.file.LinkOption;");
-                        linkOptionClz = Class.forName(
-                            "java.nio.file.LinkOption");
-                        stringArrayClz = Class.forName(
-                            "[Ljava.lang.String;");
-
-                        get = pathsClz.
-                            getMethod("get",
-                                      new Class[]{String.class,
-                                                  stringArrayClz});
-
-                        getFileAttributeView = filesClz.
-                            getMethod("getFileAttributeView",
-                                      new Class[]{pathClz,
-                                                  Class.class,
-                                                  linkOptionArrayClz});
-                        getOwner = filesClz.
-                            getMethod(
-                                "getOwner",
-                                new Class[]{pathClz,
-                                            linkOptionArrayClz});
-                        getAcl = aclFileAttributeViewClz.
-                            getMethod("getAcl", new Class[]{});
-                        principal = aclEntryClz.
-                            getMethod("principal", new Class[]{});
-                        getName = userPrincipalClz.
-                            getMethod("getName", new Class[]{});
-                        permissionsAcl = aclEntryClz.
-                            getMethod("permissions", new Class[]{});
-                        permissionsPosix = posixFileAttributesClz.
-                            getMethod("permissions", new Class[]{});
-                        readAttributes = posixFileAttributeViewClz.
-                            getMethod("readAttributes", new Class[]{});
-
-                        GROUP_EXECUTE =
-                            posixFilePermissionClz.getField("GROUP_EXECUTE");
-                        GROUP_READ =
-                            posixFilePermissionClz.getField("GROUP_READ");
-                        GROUP_WRITE =
-                            posixFilePermissionClz.getField("GROUP_WRITE");
-                        OTHERS_EXECUTE =
-                            posixFilePermissionClz.getField("OTHERS_EXECUTE");
-                        OTHERS_READ =
-                            posixFilePermissionClz.getField("OTHERS_READ");
-                        OTHERS_WRITE =
-                            posixFilePermissionClz.getField("OTHERS_WRITE");
-                        unwantedPermissions = new HashSet<Object>();
-                        unwantedPermissions.add(GROUP_EXECUTE.get(null));
-                        unwantedPermissions.add(GROUP_READ.get(null));
-                        unwantedPermissions.add(GROUP_WRITE.get(null));
-                        unwantedPermissions.add(OTHERS_EXECUTE.get(null));
-                        unwantedPermissions.add(OTHERS_READ.get(null));
-                        unwantedPermissions.add(OTHERS_WRITE.get(null));
-                    }
-
-                    // Only used with expectedOutcome == UNKNOWN, otherwise
-                    // we throw:
-                    boolean someThingBeyondOwnerFound = false;
-
-                    // We have Java 7. We need to call reflectively, since
-                    // the source level isn't yet at Java 7.
-                    try {
-                        Object fileP = get.invoke(
-                            null, new Object[]{file.getPath(),
-                                               new String[]{}});
-
-                        // ACLs supported on this platform? Check the current
-                        // file system:
-                        Object aclView = getFileAttributeView.invoke(
-                            null,
-                            new Object[]{
-                                fileP,
-                                aclFileAttributeViewClz,
-                                Array.newInstance(linkOptionClz, 0)});
-
-                        Object posixView = getFileAttributeView.invoke(
-                            null,
-                            new Object[]{
-                                fileP,
-                                posixFileAttributeViewClz,
-                                Array.newInstance(linkOptionClz, 0)});
-
-                        if (aclView != null && posixView == null) {
-                            // Windows
-                            Object owner = getOwner.invoke(
-                                null,
-                                new Object[]{
-                                    fileP,
-                                    Array.newInstance(linkOptionClz, 0)});
-
-                            List oldAcl =
-                                (List)getAcl.invoke(aclView, (Object[])null);
-
-                            for (Iterator i = oldAcl.iterator(); i.hasNext();) {
-                                Object ace = i.next();
-                                Object princ =
-                                    principal.invoke(ace, (Object[])null);
-                                String princName =
-                                    (String)getName.invoke(
-                                        princ, (Object[])null);
-
-                                if (posixView != null) {
-                                    if (princName.equals("OWNER@")) {
-                                        // OK, permission for owner
-
-                                    } else if (
-                                        princName.equals("GROUP@") ||
-                                        princName.equals("EVERYONE@")) {
-
-                                        Set s = (Set)permissionsAcl.invoke(
-                                            ace,
-                                            (Object[])null);
-
-                                        if (expectedOutcome == POSITIVE) {
-                                            assertTrue(
-                                                "Non-empty set of  " +
-                                                "permissions for uid: " +
-                                                princName + " for file " + file,
-                                                s.isEmpty());
-                                        } else {
-                                            someThingBeyondOwnerFound =
-                                                !s.isEmpty();
-                                        }
-                                    }
-                                } else {
-                                    // NTFS, hopefully
-                                    if (princ.equals(owner)) {
-                                        // OK
-                                    } else {
-                                        if (expectedOutcome == POSITIVE) {
-                                            fail(
-                                                "unexpected uid " + princName +
-                                                " can access file " + file);
-                                        } else {
-                                            someThingBeyondOwnerFound = true;
-                                        }
-                                    }
-
-                                }
+            doPrivileged((PrivilegedExceptionAction<Boolean>) () -> {
+                // Only used with expectedOutcome == UNKNOWN, otherwise
+                // we throw:
+                boolean someThingBeyondOwnerFound = false;
+
+                Path fileP = Paths.get(file.getPath());
+
+                // ACLs supported on this platform? Check the current
+                // file system:
+                AclFileAttributeView aclView = Files.getFileAttributeView(
+                        fileP, AclFileAttributeView.class);
+
+                PosixFileAttributeView posixView = Files.getFileAttributeView(
+                        fileP, PosixFileAttributeView.class);
+
+                if (posixView != null) {
+                    // Unixen
+                    for (PosixFilePermission perm :
+                            posixView.readAttributes().permissions()) {
+                        if (UNWANTED_PERMISSIONS.contains(perm)) {
+                            if (expectedOutcome == POSITIVE) {
+                                fail("unwanted permission " + perm +
+                                     " for file " + file);
                             }
-                        } else if (posixView != null) {
-                            // Unixen
-                            Object posixFileAttributes =
-                                readAttributes.invoke(posixView,
-                                                      new Object[]{});
-                            Set permissionsSet =
-                                (Set)permissionsPosix.invoke(
-                                    posixFileAttributes, new Object[]{});
-
-                            for (Iterator i = permissionsSet.iterator();
-                                 i.hasNext();) {
-                                Object perm = i.next();
-
-                                if (unwantedPermissions.contains(perm)) {
-                                    if (expectedOutcome == POSITIVE) {
-                                        fail("unwanted permission " + perm +
-                                             " for file " + file);
-                                    }
-                                    someThingBeyondOwnerFound = true;
-                                    break;
-                                }
-                            }
-                        } else {
-                            fail();
-                        }
-
-                        if (expectedOutcome == NEGATIVE &&
-                                !someThingBeyondOwnerFound) {
-                            fail(
-                                "unexpected restrictive access: " + file);
-                        }
-
-                    } catch (IllegalAccessException e) {
-                        // coding error
-                        if (SanityManager.DEBUG) {
-                            SanityManager.THROWASSERT(e);
+                            someThingBeyondOwnerFound = true;
+                            break;
                         }
-                    } catch (IllegalArgumentException e) {
-                        // coding error
-                        if (SanityManager.DEBUG) {
-                            SanityManager.THROWASSERT(e);
-                        }
-                    } catch (InvocationTargetException e) {
-                        throw e;
                     }
-
-                    if (expectedOutcome != UNKNOWN) {
-                        println("checked perms on: " + file);
+                } else if (aclView != null) {
+                    // Windows
+                    UserPrincipal owner = Files.getOwner(fileP);
+                    for (AclEntry ace : aclView.getAcl()) {
+                        UserPrincipal princ = ace.principal();
+                        // NTFS, hopefully
+                        if (!princ.equals(owner)) {
+                            if (expectedOutcome == POSITIVE) {
+                                fail("unexpected uid " + princ.getName() +
+                                        " can access file " + file);
+                            }
+                            someThingBeyondOwnerFound = true;
+                            break;
+                        }
                     }
+                } else {
+                    fail();
+                }
+
+                if (expectedOutcome == NEGATIVE && !someThingBeyondOwnerFound) {
+                    fail("unexpected restrictive access: " + file);
+                }
+
+                if (expectedOutcome != UNKNOWN) {
+                    println("checked perms on: " + file);
+                }
 
-                    if (expectedOutcome == UNKNOWN &&
-                            someThingBeyondOwnerFound) {
-                        return Boolean.TRUE;
-                    } else {
-                        return Boolean.FALSE;
-                    }
-                }});
+                return expectedOutcome == UNKNOWN && someThingBeyondOwnerFound;
+        });
     }
 }

Modified: db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/util/PrivilegedFileOpsForTests.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/util/PrivilegedFileOpsForTests.java?rev=1728667&r1=1728666&r2=1728667&view=diff
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/util/PrivilegedFileOpsForTests.java (original)
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/util/PrivilegedFileOpsForTests.java Fri Feb  5 13:49:03 2016
@@ -308,6 +308,16 @@ public class PrivilegedFileOpsForTests {
         }
     }
 
+    /**
+     * In a priv block, get an array with all the files in a directory.
+     * @param dir the directory to scan
+     * @return an array of all the files in the directory
+     * @see java.io.File#listFiles()
+     */
+    public static File[] listFiles(File dir) {
+        return AccessController.doPrivileged(
+                (PrivilegedAction<File[]>) () -> dir.listFiles());
+    }
     
     /**
      * In a priv block, do a recursive copy from source to target.