Handle security-sensitive operations correctly in DirectoryContent. (FELIX-2738)


git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@1052034 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/framework/src/main/java/org/apache/felix/framework/cache/DirectoryContent.java b/framework/src/main/java/org/apache/felix/framework/cache/DirectoryContent.java
index 1dfef13..3452ff8 100644
--- a/framework/src/main/java/org/apache/felix/framework/cache/DirectoryContent.java
+++ b/framework/src/main/java/org/apache/felix/framework/cache/DirectoryContent.java
@@ -94,7 +94,8 @@
 
         try
         {
-            is = new BufferedInputStream(new FileInputStream(new File(m_dir, name)));
+            is = new BufferedInputStream(
+                BundleCache.getSecureAction().getFileInputStream(new File(m_dir, name)));
             baos = new ByteArrayOutputStream(BUFSIZE);
             byte[] buf = new byte[BUFSIZE];
             int n = 0;
@@ -136,7 +137,7 @@
             name = name.substring(1);
         }
 
-        return new FileInputStream(new File(m_dir, name));
+        return BundleCache.getSecureAction().getFileInputStream(new File(m_dir, name));
     }
 
     public URL getEntryAsURL(String name)
@@ -148,7 +149,7 @@
 
         try
         {
-            return new File(m_dir, name).toURI().toURL();
+            return BundleCache.getSecureAction().toURI(new File(m_dir, name)).toURL();
         }
         catch (MalformedURLException e)
         {
@@ -162,7 +163,8 @@
         // just return it immediately.
         if (entryName.equals(FelixConstants.CLASS_PATH_DOT))
         {
-            return new DirectoryContent(m_logger, m_configMap, m_revisionLock, m_rootDir, m_dir);
+            return new DirectoryContent(
+                m_logger, m_configMap, m_revisionLock, m_rootDir, m_dir);
         }
 
         // Remove any leading slash, since all bundle class path
@@ -178,7 +180,8 @@
         File file = new File(m_dir, entryName);
         if (BundleCache.getSecureAction().isFileDirectory(file))
         {
-            return new DirectoryContent(m_logger, m_configMap, m_revisionLock, m_rootDir, file);
+            return new DirectoryContent(
+                m_logger, m_configMap, m_revisionLock, m_rootDir, file);
         }
         else if (BundleCache.getSecureAction().fileExists(file)
             && entryName.endsWith(".jar"))
@@ -199,7 +202,8 @@
                     }
                 }
             }
-            return new JarContent(m_logger, m_configMap, m_revisionLock, extractDir, file, null);
+            return new JarContent(
+                m_logger, m_configMap, m_revisionLock, extractDir, file, null);
         }
 
         // The entry could not be found, so return null.
@@ -261,7 +265,7 @@
                         try
                         {
                             is = new BufferedInputStream(
-                                new FileInputStream(entryFile),
+                                BundleCache.getSecureAction().getFileInputStream(entryFile),
                                 BundleCache.BUFSIZE);
                             if (is == null)
                             {
@@ -347,15 +351,15 @@
             }
 
             // Convert the file separator character to slashes.
-            String abs = m_children[m_counter].getAbsolutePath()
-                .replace(File.separatorChar, '/');
+            String abs = BundleCache.getSecureAction()
+                .getAbsolutePath(m_children[m_counter]).replace(File.separatorChar, '/');
 
             // Remove the leading path of the reference directory, since the
             // entry paths are supposed to be relative to the root.
             StringBuffer sb = new StringBuffer(abs);
-            sb.delete(0, m_dir.getAbsolutePath().length() + 1);
+            sb.delete(0, BundleCache.getSecureAction().getAbsolutePath(m_dir).length() + 1);
             // Add a '/' to the end of directory entries.
-            if (m_children[m_counter].isDirectory())
+            if (BundleCache.getSecureAction().isFileDirectory(m_children[m_counter]))
             {
                 sb.append('/');
             }
@@ -365,18 +369,19 @@
 
         private File[] listFilesRecursive(File dir)
         {
-            File[] children = dir.listFiles();
+            File[] children = BundleCache.getSecureAction().listDirectory(dir);
             File[] combined = children;
             for (int i = 0; i < children.length; i++)
             {
-                if (children[i].isDirectory())
+                if (BundleCache.getSecureAction().isFileDirectory(children[i]))
                 {
                     File[] grandchildren = listFilesRecursive(children[i]);
                     if (grandchildren.length > 0)
                     {
                         File[] tmp = new File[combined.length + grandchildren.length];
                         System.arraycopy(combined, 0, tmp, 0, combined.length);
-                        System.arraycopy(grandchildren, 0, tmp, combined.length, grandchildren.length);
+                        System.arraycopy(
+                            grandchildren, 0, tmp, combined.length, grandchildren.length);
                         combined = tmp;
                     }
                 }
diff --git a/framework/src/main/java/org/apache/felix/framework/util/SecureAction.java b/framework/src/main/java/org/apache/felix/framework/util/SecureAction.java
index 0c140f8..1410f0f 100644
--- a/framework/src/main/java/org/apache/felix/framework/util/SecureAction.java
+++ b/framework/src/main/java/org/apache/felix/framework/util/SecureAction.java
@@ -61,7 +61,7 @@
             try
             {
                 Actions actions = (Actions) m_actions.get();
-                actions.set(Actions.INITIALIZE_CONTEXT, null);
+                actions.set(Actions.INITIALIZE_CONTEXT_ACTION, null);
                 m_acc = (AccessControlContext) AccessController.doPrivileged(actions);
             }
             catch (PrivilegedActionException ex)
@@ -462,6 +462,27 @@
         }
     }
 
+    public URI toURI(File file)
+    {
+        if (System.getSecurityManager() != null)
+        {
+            try
+            {
+                Actions actions = (Actions) m_actions.get();
+                actions.set(Actions.TO_URI_ACTION, file);
+                return (URI) AccessController.doPrivileged(actions, m_acc);
+            }
+            catch (PrivilegedActionException ex)
+            {
+                throw (RuntimeException) ex.getException();
+            }
+        }
+        else
+        {
+            return file.toURI();
+        }
+    }
+
     public InputStream getURLConnectionInputStream(URLConnection conn)
         throws IOException
     {
@@ -682,7 +703,7 @@
         if (System.getSecurityManager() != null)
         {
             Actions actions = (Actions) m_actions.get();
-            actions.set(Actions.ADD_EXTENSION_URL, extension, loader);
+            actions.set(Actions.ADD_EXTENSION_URL_ACTION, extension, loader);
             try
             {
                 AccessController.doPrivileged(actions, m_acc);
@@ -1046,8 +1067,8 @@
 
     private static class Actions implements PrivilegedExceptionAction
     {
-        public static final int INITIALIZE_CONTEXT = 0;
-        public static final int ADD_EXTENSION_URL = 1;
+        public static final int INITIALIZE_CONTEXT_ACTION = 0;
+        public static final int ADD_EXTENSION_URL_ACTION = 1;
         public static final int CREATE_TMPFILE_ACTION = 2;
         public static final int CREATE_URL_ACTION = 3;
         public static final int CREATE_URL_WITH_CONTEXT_ACTION = 4;
@@ -1063,29 +1084,30 @@
         public static final int GET_FIELD_ACTION = 14;
         public static final int GET_FILE_INPUT_ACTION = 15;
         public static final int GET_FILE_OUTPUT_ACTION = 16;
-        public static final int GET_METHOD_ACTION = 17;
-        public static final int GET_POLICY_ACTION = 18;
-        public static final int GET_PROPERTY_ACTION = 19;
-        public static final int GET_PARENT_CLASS_LOADER_ACTION = 20;
-        public static final int GET_SYSTEM_CLASS_LOADER_ACTION = 21;
-        public static final int GET_URL_INPUT_ACTION = 22;
-        public static final int INVOKE_CONSTRUCTOR_ACTION = 23;
-        public static final int INVOKE_DIRECTMETHOD_ACTION = 24;
-        public static final int INVOKE_METHOD_ACTION = 25;
-        public static final int LIST_DIRECTORY_ACTION = 26;
-        public static final int MAKE_DIRECTORIES_ACTION = 27;
-        public static final int MAKE_DIRECTORY_ACTION = 28;
-        public static final int OPEN_JARX_ACTION = 29;
-        public static final int OPEN_JARX_VERIFY_ACTION = 30;
-        public static final int OPEN_URLCONNECTION_ACTION = 31;
-        public static final int RENAME_FILE_ACTION = 32;
-        public static final int SET_ACCESSIBLE_ACTION = 33;
-        public static final int START_ACTIVATOR_ACTION = 34;
-        public static final int STOP_ACTIVATOR_ACTION = 35;
-        public static final int SWAP_FIELD_ACTION = 36;
-        public static final int SYSTEM_EXIT_ACTION = 37;
-        public static final int FLUSH_FIELD_ACTION = 38;
-        public static final int GET_CLASS_LOADER_ACTION = 39;
+        public static final int TO_URI_ACTION = 17;
+        public static final int GET_METHOD_ACTION = 18;
+        public static final int GET_POLICY_ACTION = 19;
+        public static final int GET_PROPERTY_ACTION = 20;
+        public static final int GET_PARENT_CLASS_LOADER_ACTION = 21;
+        public static final int GET_SYSTEM_CLASS_LOADER_ACTION = 22;
+        public static final int GET_URL_INPUT_ACTION = 23;
+        public static final int INVOKE_CONSTRUCTOR_ACTION = 24;
+        public static final int INVOKE_DIRECTMETHOD_ACTION = 25;
+        public static final int INVOKE_METHOD_ACTION = 26;
+        public static final int LIST_DIRECTORY_ACTION = 27;
+        public static final int MAKE_DIRECTORIES_ACTION = 28;
+        public static final int MAKE_DIRECTORY_ACTION = 29;
+        public static final int OPEN_JARX_ACTION = 30;
+        public static final int OPEN_JARX_VERIFY_ACTION = 31;
+        public static final int OPEN_URLCONNECTION_ACTION = 32;
+        public static final int RENAME_FILE_ACTION = 33;
+        public static final int SET_ACCESSIBLE_ACTION = 34;
+        public static final int START_ACTIVATOR_ACTION = 35;
+        public static final int STOP_ACTIVATOR_ACTION = 36;
+        public static final int SWAP_FIELD_ACTION = 37;
+        public static final int SYSTEM_EXIT_ACTION = 38;
+        public static final int FLUSH_FIELD_ACTION = 39;
+        public static final int GET_CLASS_LOADER_ACTION = 40;
 
         private int m_action = -1;
         private Object m_arg1 = null;
@@ -1162,179 +1184,105 @@
 
             unset();
 
-            if (action == INITIALIZE_CONTEXT)
+            switch (action)
             {
-                return AccessController.getContext();
-            }
-            else if (action == GET_PROPERTY_ACTION)
-            {
-                return System.getProperty((String) arg1, (String) arg2);
-            }
-            else if (action == GET_PARENT_CLASS_LOADER_ACTION)
-            {
-                return ((ClassLoader) arg1).getParent();
-            }
-            else if (action == GET_SYSTEM_CLASS_LOADER_ACTION)
-            {
-                return ClassLoader.getSystemClassLoader();
-            }
-            else if (action == FOR_NAME_ACTION)
-            {
-                return Class.forName((String) arg1);
-            }
-            else if (action == CREATE_URL_ACTION)
-            {
-                return new URL((String) arg1, (String) arg2,
-                    ((Integer) arg3).intValue(), (String) arg4,
-                    (URLStreamHandler) arg5);
-            }
-            else if (action == CREATE_URL_WITH_CONTEXT_ACTION)
-            {
-                return new URL((URL) arg1, (String) arg2,
-                    (URLStreamHandler) arg3);
-            }
-            else if (action == EXEC_ACTION)
-            {
-                return Runtime.getRuntime().exec((String) arg1);
-            }
-            else if (action == GET_ABSOLUTE_PATH_ACTION)
-            {
-                return ((File) arg1).getAbsolutePath();
-            }
-            else if (action == FILE_EXISTS_ACTION)
-            {
-                return ((File) arg1).exists() ? Boolean.TRUE : Boolean.FALSE;
-            }
-            else if (action == FILE_IS_DIRECTORY_ACTION)
-            {
-                return ((File) arg1).isDirectory() ? Boolean.TRUE : Boolean.FALSE;
-            }
-            else if (action == MAKE_DIRECTORY_ACTION)
-            {
-                return ((File) arg1).mkdir() ? Boolean.TRUE : Boolean.FALSE;
-            }
-            else if (action == MAKE_DIRECTORIES_ACTION)
-            {
-                return ((File) arg1).mkdirs() ? Boolean.TRUE : Boolean.FALSE;
-            }
-            else if (action == LIST_DIRECTORY_ACTION)
-            {
-                return ((File) arg1).listFiles();
-            }
-            else if (action == RENAME_FILE_ACTION)
-            {
-                return ((File) arg1).renameTo((File) arg2) ? Boolean.TRUE : Boolean.FALSE;
-            }
-            else if (action == GET_FILE_INPUT_ACTION)
-            {
-                return new FileInputStream((File) arg1);
-            }
-            else if (action == GET_FILE_OUTPUT_ACTION)
-            {
-                return new FileOutputStream((File) arg1);
-            }
-            else if (action == DELETE_FILE_ACTION)
-            {
-                return ((File) arg1).delete() ? Boolean.TRUE : Boolean.FALSE;
-            }
-            else if (action == OPEN_JARX_ACTION)
-            {
-                return new JarFileX((File) arg1);
-            }
-            else if (action == OPEN_JARX_VERIFY_ACTION)
-            {
-                return new JarFileX((File) arg1, ((Boolean) arg2).booleanValue());
-            }
-            else if (action == GET_URL_INPUT_ACTION)
-            {
-                return ((URLConnection) arg1).getInputStream();
-            }
-            else if (action == START_ACTIVATOR_ACTION)
-            {
-                ((BundleActivator) arg1).start((BundleContext) arg2);
-                return null;
-            }
-            else if (action == STOP_ACTIVATOR_ACTION)
-            {
-                ((BundleActivator) arg1).stop((BundleContext) arg2);
-                return null;
-            }
-            else if (action == SYSTEM_EXIT_ACTION)
-            {
-                System.exit(((Integer) arg1).intValue());
-            }
-            else if (action == GET_POLICY_ACTION)
-            {
-                return Policy.getPolicy();
-            }
-            else if (action == CREATE_TMPFILE_ACTION)
-            {
-                return File.createTempFile((String) arg1, (String) arg2,
-                    (File) arg3);
-            }
-            else if (action == OPEN_URLCONNECTION_ACTION)
-            {
-                return ((URL) arg1).openConnection();
-            }
-            else if (action == ADD_EXTENSION_URL)
-            {
-                Method addURL =
-                    URLClassLoader.class.getDeclaredMethod("addURL",
-                    new Class[] {URL.class});
-                addURL.setAccessible(true);
-                addURL.invoke(arg2, new Object[]{arg1});
-            }
-            else if (action == GET_CONSTRUCTOR_ACTION)
-            {
-                return ((Class) arg1).getConstructor((Class[]) arg2);
-            }
-            else if (action == GET_DECLARED_CONSTRUCTOR_ACTION)
-            {
-                return ((Class) arg1).getDeclaredConstructor((Class[]) arg2);
-            }
-            else if (action == GET_METHOD_ACTION)
-            {
-                return ((Class) arg1).getMethod((String) arg2, (Class[]) arg3);
-            }
-            else if (action == INVOKE_METHOD_ACTION)
-            {
-                ((Method) arg1).setAccessible(true);
-                return ((Method) arg1).invoke(arg2, (Object[]) arg3);
-            }
-            else if (action == INVOKE_DIRECTMETHOD_ACTION)
-            {
-                return ((Method) arg1).invoke(arg2, (Object[]) arg3);
-            }
-            else if (action == INVOKE_CONSTRUCTOR_ACTION)
-            {
-                return ((Constructor) arg1).newInstance((Object[]) arg2);
-            }
-            else if (action == SWAP_FIELD_ACTION)
-            {
-                return _swapStaticFieldIfNotClass((Class) arg1,
-                    (Class) arg2, (Class) arg3, (String) arg4);
-            }
-            else if (action == GET_FIELD_ACTION)
-            {
-                Field field = ((Class) arg1).getDeclaredField((String) arg2);
-                field.setAccessible(true);
-                return field.get(arg3);
-            }
-            else if (action == GET_DECLARED_METHOD_ACTION)
-            {
-                return ((Class) arg1).getDeclaredMethod((String) arg2, (Class[]) arg3);
-            }
-            else if (action == SET_ACCESSIBLE_ACTION)
-            {
-                ((AccessibleObject) arg1).setAccessible(true);
-            }
-            else if (action == FLUSH_FIELD_ACTION)
-            {
-                _flush(((Class) arg1), arg2);
-            }
-            else if (action == GET_CLASS_LOADER_ACTION)
-            {
-                return ((Class) arg1).getClassLoader();
+                case INITIALIZE_CONTEXT_ACTION:
+                    return AccessController.getContext();
+                case ADD_EXTENSION_URL_ACTION:
+                    Method addURL =
+                        URLClassLoader.class.getDeclaredMethod("addURL",
+                        new Class[] {URL.class});
+                    addURL.setAccessible(true);
+                    addURL.invoke(arg2, new Object[]{arg1});
+                    return null;
+                case CREATE_TMPFILE_ACTION:
+                    return File.createTempFile((String) arg1, (String) arg2, (File) arg3);
+                case CREATE_URL_ACTION:
+                    return new URL((String) arg1, (String) arg2,
+                        ((Integer) arg3).intValue(), (String) arg4,
+                        (URLStreamHandler) arg5);
+                case CREATE_URL_WITH_CONTEXT_ACTION:
+                    return new URL((URL) arg1, (String) arg2, (URLStreamHandler) arg3);
+                case DELETE_FILE_ACTION:
+                    return ((File) arg1).delete() ? Boolean.TRUE : Boolean.FALSE;
+                case EXEC_ACTION:
+                    return Runtime.getRuntime().exec((String) arg1);
+                case FILE_EXISTS_ACTION:
+                    return ((File) arg1).exists() ? Boolean.TRUE : Boolean.FALSE;
+                case FILE_IS_DIRECTORY_ACTION:
+                    return ((File) arg1).isDirectory() ? Boolean.TRUE : Boolean.FALSE;
+                case FOR_NAME_ACTION:
+                    return Class.forName((String) arg1);
+                case GET_ABSOLUTE_PATH_ACTION:
+                    return ((File) arg1).getAbsolutePath();
+                case GET_CONSTRUCTOR_ACTION:
+                    return ((Class) arg1).getConstructor((Class[]) arg2);
+                case GET_DECLARED_CONSTRUCTOR_ACTION:
+                    return ((Class) arg1).getDeclaredConstructor((Class[]) arg2);
+                case GET_DECLARED_METHOD_ACTION:
+                    return ((Class) arg1).getDeclaredMethod((String) arg2, (Class[]) arg3);
+                case GET_FIELD_ACTION:
+                    Field field = ((Class) arg1).getDeclaredField((String) arg2);
+                    field.setAccessible(true);
+                    return field.get(arg3);
+                case GET_FILE_INPUT_ACTION:
+                    return new FileInputStream((File) arg1);
+                case GET_FILE_OUTPUT_ACTION:
+                    return new FileOutputStream((File) arg1);
+                case TO_URI_ACTION:
+                    return ((File) arg1).toURI();
+                case GET_METHOD_ACTION:
+                    return ((Class) arg1).getMethod((String) arg2, (Class[]) arg3);
+                case GET_POLICY_ACTION:
+                    return Policy.getPolicy();
+                case GET_PROPERTY_ACTION:
+                    return System.getProperty((String) arg1, (String) arg2);
+                case GET_PARENT_CLASS_LOADER_ACTION:
+                    return ((ClassLoader) arg1).getParent();
+                case GET_SYSTEM_CLASS_LOADER_ACTION:
+                    return ClassLoader.getSystemClassLoader();
+                case GET_URL_INPUT_ACTION:
+                    return ((URLConnection) arg1).getInputStream();
+                case INVOKE_CONSTRUCTOR_ACTION:
+                    return ((Constructor) arg1).newInstance((Object[]) arg2);
+                case INVOKE_DIRECTMETHOD_ACTION:
+                    return ((Method) arg1).invoke(arg2, (Object[]) arg3);
+                case INVOKE_METHOD_ACTION:
+                    ((Method) arg1).setAccessible(true);
+                    return ((Method) arg1).invoke(arg2, (Object[]) arg3);
+                case LIST_DIRECTORY_ACTION:
+                    return ((File) arg1).listFiles();
+                case MAKE_DIRECTORIES_ACTION:
+                    return ((File) arg1).mkdirs() ? Boolean.TRUE : Boolean.FALSE;
+                case MAKE_DIRECTORY_ACTION:
+                    return ((File) arg1).mkdir() ? Boolean.TRUE : Boolean.FALSE;
+                case OPEN_JARX_ACTION:
+                    return new JarFileX((File) arg1);
+                case OPEN_JARX_VERIFY_ACTION:
+                    return new JarFileX((File) arg1, ((Boolean) arg2).booleanValue());
+                case OPEN_URLCONNECTION_ACTION:
+                    return ((URL) arg1).openConnection();
+                case RENAME_FILE_ACTION:
+                    return ((File) arg1).renameTo((File) arg2) ? Boolean.TRUE : Boolean.FALSE;
+                case SET_ACCESSIBLE_ACTION:
+                    ((AccessibleObject) arg1).setAccessible(true);
+                    return null;
+                case START_ACTIVATOR_ACTION:
+                    ((BundleActivator) arg1).start((BundleContext) arg2);
+                    return null;
+                case STOP_ACTIVATOR_ACTION:
+                    ((BundleActivator) arg1).stop((BundleContext) arg2);
+                    return null;
+                case SWAP_FIELD_ACTION:
+                    return _swapStaticFieldIfNotClass((Class) arg1,
+                        (Class) arg2, (Class) arg3, (String) arg4);
+                case SYSTEM_EXIT_ACTION:
+                    System.exit(((Integer) arg1).intValue());
+                case FLUSH_FIELD_ACTION:
+                    _flush(((Class) arg1), arg2);
+                    return null;
+                case GET_CLASS_LOADER_ACTION:
+                    return ((Class) arg1).getClassLoader();
             }
 
             return null;