diff options
Diffstat (limited to 'src/java/com/jogamp/common/util')
-rw-r--r-- | src/java/com/jogamp/common/util/IOUtil.java | 100 | ||||
-rw-r--r-- | src/java/com/jogamp/common/util/PropertyAccess.java | 67 | ||||
-rw-r--r-- | src/java/com/jogamp/common/util/SecurityUtil.java | 141 | ||||
-rw-r--r-- | src/java/com/jogamp/common/util/cache/TempFileCache.java | 8 |
4 files changed, 178 insertions, 138 deletions
diff --git a/src/java/com/jogamp/common/util/IOUtil.java b/src/java/com/jogamp/common/util/IOUtil.java index 46d6b24..2f0c77f 100644 --- a/src/java/com/jogamp/common/util/IOUtil.java +++ b/src/java/com/jogamp/common/util/IOUtil.java @@ -33,12 +33,10 @@ import java.io.BufferedOutputStream; import java.io.Closeable; import java.io.File; import java.io.FileOutputStream; +import java.io.FilePermission; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; -import java.security.AccessControlContext; -import java.security.AccessController; -import java.security.PrivilegedAction; import java.lang.reflect.Constructor; import java.net.URI; import java.net.URISyntaxException; @@ -817,20 +815,12 @@ public class IOUtil { * @param dir the directory to process * @param create true if the directory shall be created if not existing * @param executable true if the user intents to launch executables from the temporary directory, otherwise false. - * @param acc The security {@link AccessControlContext} to create directories and test <i>executability</i> * @throws SecurityException if file creation and process execution is not allowed within the current security context */ - public static File testDir(final File dir, final boolean create, final boolean executable, AccessControlContext acc) + public static File testDir(final File dir, final boolean create, final boolean executable) throws SecurityException { - if( null != acc ) { - return AccessController.doPrivileged(new PrivilegedAction<File>() { - public File run() { - return testDirImpl(dir, create, executable); - } }, acc); - } else { - return testDirImpl(dir, create, executable); - } + return testDirImpl(dir, create, executable); } private static boolean isStringSet(String s) { return null != s && 0 < s.length(); } @@ -873,9 +863,35 @@ public class IOUtil { return tmpBaseDir; } - private static File getTempDirImpl(boolean executable) + /** + * Returns a platform independent writable directory for temporary files + * consisting of the platform's {@code temp-root} + {@link #tmpSubDir}, + * e.g. {@code /tmp/jogamp_0000/}. + * <p> + * On standard Java the {@code temp-root} folder is specified by <code>java.io.tempdir</code>. + * </p> + * <p> + * On Android the {@code temp-root} folder is relative to the applications local folder + * (see {@link Context#getDir(String, int)}) is returned, if + * the Android application/activity has registered it's Application Context + * via {@link jogamp.common.os.android.StaticContext.StaticContext#init(Context, ClassLoader) StaticContext.init(..)}. + * This allows using the temp folder w/o the need for <code>sdcard</code> + * access, which would be the <code>java.io.tempdir</code> location on Android! + * </p> + * <p> + * In case {@code temp-root} is the users home folder, + * a dot is being prepended to {@link #tmpSubDir}, i.e.: {@code /home/user/.jogamp_0000/}. + * </p> + * @param executable true if the user intents to launch executables from the temporary directory, otherwise false. + * @throws RuntimeException if no temporary directory could be determined + * @throws SecurityException if access to <code>java.io.tmpdir</code> is not allowed within the current security context + * + * @see PropertyAccess#getProperty(String, boolean) + * @see Context#getDir(String, int) + */ + public static File getTempDir(final boolean executable) throws SecurityException, RuntimeException - { + { if(!tempRootSet) { // volatile: ok synchronized(IOUtil.class) { if(!tempRootSet) { @@ -889,8 +905,8 @@ public class IOUtil { } } - final String java_io_tmpdir = PropertyAccess.getProperty(java_io_tmpdir_propkey, false, null); - final String user_home = PropertyAccess.getProperty(user_home_propkey, false, null); + final String java_io_tmpdir = PropertyAccess.getProperty(java_io_tmpdir_propkey, false); + final String user_home = PropertyAccess.getProperty(user_home_propkey, false); final String xdg_cache_home; { @@ -951,6 +967,8 @@ public class IOUtil { if(null == r) { throw new RuntimeException("Could not determine a temporary directory"); } + final FilePermission fp = new FilePermission(r.getAbsolutePath(), "read,write,delete"); + SecurityUtil.checkPermission(fp); return r; } private static File tempRootExec = null; // writeable and executable @@ -958,53 +976,13 @@ public class IOUtil { private static volatile boolean tempRootSet = false; /** - * Returns a platform independent writable directory for temporary files - * consisting of the platform's {@code temp-root} + {@link #tmpSubDir}, - * e.g. {@code /tmp/jogamp_0000/}. - * <p> - * On standard Java the {@code temp-root} folder is specified by <code>java.io.tempdir</code>. - * </p> - * <p> - * On Android the {@code temp-root} folder is relative to the applications local folder - * (see {@link Context#getDir(String, int)}) is returned, if - * the Android application/activity has registered it's Application Context - * via {@link jogamp.common.os.android.StaticContext.StaticContext#init(Context, ClassLoader) StaticContext.init(..)}. - * This allows using the temp folder w/o the need for <code>sdcard</code> - * access, which would be the <code>java.io.tempdir</code> location on Android! - * </p> - * <p> - * In case {@code temp-root} is the users home folder, - * a dot is being prepended to {@link #tmpSubDir}, i.e.: {@code /home/user/.jogamp_0000/}. - * </p> - * @param executable true if the user intents to launch executables from the temporary directory, otherwise false. - * @param acc The security {@link AccessControlContext} to access properties, environment vars, create directories and test <i>executability</i> - * @throws SecurityException if access to <code>java.io.tmpdir</code> is not allowed within the current security context - * @throws RuntimeException if no temporary directory could be determined - * - * @see PropertyAccess#getProperty(String, boolean, java.security.AccessControlContext) - * @see Context#getDir(String, int) - */ - public static File getTempDir(final boolean executable, AccessControlContext acc) - throws SecurityException, RuntimeException - { - if( null != acc ) { - return AccessController.doPrivileged(new PrivilegedAction<File>() { - public File run() { - return getTempDirImpl(executable); - } }, acc); - } else { - return getTempDirImpl(executable); - } - } - - /** * Utilizing {@link File#createTempFile(String, String, File)} using - * {@link #getTempRoot(AccessControlContext, boolean)} as the directory parameter, ie. location + * {@link #getTempDir(boolean)} as the directory parameter, ie. location * of the root temp folder. * * @see File#createTempFile(String, String) * @see File#createTempFile(String, String, File) - * @see #getTempRoot(AccessControlContext, boolean) + * @see #getTempDir(boolean) * * @param prefix * @param suffix @@ -1014,10 +992,10 @@ public class IOUtil { * @throws IOException * @throws SecurityException */ - public static File createTempFile(String prefix, String suffix, boolean executable, AccessControlContext acc) + public static File createTempFile(String prefix, String suffix, boolean executable) throws IllegalArgumentException, IOException, SecurityException { - return File.createTempFile( prefix, suffix, getTempDir(executable, acc) ); + return File.createTempFile( prefix, suffix, getTempDir(executable) ); } public static void close(Closeable stream, boolean throwRuntimeException) throws RuntimeException { diff --git a/src/java/com/jogamp/common/util/PropertyAccess.java b/src/java/com/jogamp/common/util/PropertyAccess.java index 51b9533..dde6b50 100644 --- a/src/java/com/jogamp/common/util/PropertyAccess.java +++ b/src/java/com/jogamp/common/util/PropertyAccess.java @@ -48,12 +48,13 @@ public class PropertyAccess { // 'jogamp.' and maybe other trusted prefixes will be added later via 'addTrustedPrefix()' } - public static final void addTrustedPrefix(String prefix, Class<?> certClass) { - if(SecurityUtil.equalsLocalCert(certClass)) { - trustedPrefixes.add(prefix); - } else { - throw new SecurityException("Illegal Access - prefix "+prefix+", with cert class "+certClass); - } + /** + * @param prefix New prefix to be registered as trusted. + * @throws AccessControlException as thrown by {@link SecurityUtil#checkAllPermissions()}. + */ + protected static final void addTrustedPrefix(String prefix) throws AccessControlException { + SecurityUtil.checkAllPermissions(); + trustedPrefixes.add(prefix); } public static final boolean isTrusted(String propertyKey) { @@ -65,11 +66,11 @@ public class PropertyAccess { } } - /** @see #getProperty(String, boolean, AccessControlContext) */ - public static final int getIntProperty(final String property, final boolean jnlpAlias, final AccessControlContext acc, int defaultValue) { + /** @see #getProperty(String, boolean) */ + public static final int getIntProperty(final String property, final boolean jnlpAlias, int defaultValue) { int i=defaultValue; try { - final String sv = PropertyAccess.getProperty(property, jnlpAlias, acc); + final String sv = PropertyAccess.getProperty(property, jnlpAlias); if(null!=sv) { i = Integer.valueOf(sv).intValue(); } @@ -77,11 +78,11 @@ public class PropertyAccess { return i; } - /** @see #getProperty(String, boolean, AccessControlContext) */ - public static final long getLongProperty(final String property, final boolean jnlpAlias, final AccessControlContext acc, long defaultValue) { + /** @see #getProperty(String, boolean) */ + public static final long getLongProperty(final String property, final boolean jnlpAlias, long defaultValue) { long l=defaultValue; try { - final String sv = PropertyAccess.getProperty(property, jnlpAlias, acc); + final String sv = PropertyAccess.getProperty(property, jnlpAlias); if(null!=sv) { l = Long.valueOf(sv).longValue(); } @@ -89,23 +90,23 @@ public class PropertyAccess { return l; } - /** @see #getProperty(String, boolean, AccessControlContext) */ - public static final boolean getBooleanProperty(final String property, final boolean jnlpAlias, final AccessControlContext acc) { - return Boolean.valueOf(PropertyAccess.getProperty(property, jnlpAlias, acc)).booleanValue(); + /** @see #getProperty(String, boolean) */ + public static final boolean getBooleanProperty(final String property, final boolean jnlpAlias) { + return Boolean.valueOf(PropertyAccess.getProperty(property, jnlpAlias)).booleanValue(); } - /** @see #getProperty(String, boolean, AccessControlContext) */ - public static final boolean getBooleanProperty(final String property, final boolean jnlpAlias, final AccessControlContext acc, boolean defaultValue) { - final String valueS = PropertyAccess.getProperty(property, jnlpAlias, acc); + /** @see #getProperty(String, boolean) */ + public static final boolean getBooleanProperty(final String property, final boolean jnlpAlias, boolean defaultValue) { + final String valueS = PropertyAccess.getProperty(property, jnlpAlias); if(null != valueS) { return Boolean.valueOf(valueS).booleanValue(); } return defaultValue; } - /** @see #getProperty(String, boolean, AccessControlContext) */ - public static final boolean isPropertyDefined(final String property, final boolean jnlpAlias, final AccessControlContext acc) { - return (PropertyAccess.getProperty(property, jnlpAlias, acc) != null) ? true : false; + /** @see #getProperty(String, boolean) */ + public static final boolean isPropertyDefined(final String property, final boolean jnlpAlias) { + return (PropertyAccess.getProperty(property, jnlpAlias) != null) ? true : false; } /** @@ -119,8 +120,6 @@ public class PropertyAccess { * @param propertyKey the property name to query. * @param jnlpAlias true if a fallback attempt to query the JNLP aliased <i>trusted property</i> shall be made, * otherwise false. - * @param acc the AccessControlerContext to be used for privileged access to the system property, or null. - * * @return the property value if exists, or null * * @throws NullPointerException if the property name is null @@ -129,7 +128,7 @@ public class PropertyAccess { * * @see System#getProperty(String) */ - public static final String getProperty(final String propertyKey, final boolean jnlpAlias, final AccessControlContext acc) + public static final String getProperty(final String propertyKey, final boolean jnlpAlias) throws SecurityException, NullPointerException, IllegalArgumentException { if(null == propertyKey) { throw new NullPointerException("propertyKey is NULL"); @@ -138,23 +137,13 @@ public class PropertyAccess { throw new IllegalArgumentException("propertyKey is empty"); } String s=null; - // int cause = 0; if( isTrusted(propertyKey) ) { // 'trusted' property (jnlp., javaws., jogamp., ..) s = getTrustedPropKey(propertyKey); - // cause = null != s ? 1 : 0; } else { - if( null != acc ) { - s = AccessController.doPrivileged(new PrivilegedAction<String>() { - public String run() { - return System.getProperty(propertyKey); - } }, acc); - // cause = null != s ? 2 : 0; - } else { - s = System.getProperty(propertyKey); - // cause = null != s ? 3 : 0; - } + // may throw SecurityException, AccessControlerException + s = System.getProperty(propertyKey); } if( null == s && jnlpAlias ) { // Try 'jnlp.' aliased property .. @@ -162,11 +151,8 @@ public class PropertyAccess { // Properties within the namespace "jnlp." or "javaws." should be considered trusted, // i.e. always granted w/o special privileges. s = getTrustedPropKey(jnlp_prefix + propertyKey); - // cause = null != s ? 4 : 0; } - } - // System.err.println("Prop: <"+propertyKey+"> = <"+s+">, cause "+cause); - + } return s; } @@ -177,7 +163,6 @@ public class PropertyAccess { return System.getProperty(propertyKey); } catch (SecurityException se) { throw new SecurityException("Could not access trusted property '"+propertyKey+"'", se); - } } }); diff --git a/src/java/com/jogamp/common/util/SecurityUtil.java b/src/java/com/jogamp/common/util/SecurityUtil.java index 4583201..4d7aa5d 100644 --- a/src/java/com/jogamp/common/util/SecurityUtil.java +++ b/src/java/com/jogamp/common/util/SecurityUtil.java @@ -27,30 +27,127 @@ */ package com.jogamp.common.util; -import java.security.AccessControlContext; import java.security.AccessController; +import java.security.AllPermission; import java.security.CodeSource; +import java.security.Permission; import java.security.PrivilegedAction; import java.security.ProtectionDomain; import java.security.cert.Certificate; public class SecurityUtil { - /* package private */ static final AccessControlContext localACC; - /* package private */ static final Certificate[] localCerts; + private static final SecurityManager securityManager; + private static final Permission allPermissions; + private static final boolean DEBUG = false; static { - localACC = AccessController.doPrivileged(new PrivilegedAction<AccessControlContext>() { - public AccessControlContext run() { - return AccessController.getContext(); - } } ); - localCerts = getCerts(SecurityUtil.class); + allPermissions = new AllPermission(); + securityManager = System.getSecurityManager(); + + if( DEBUG ) { + final boolean hasAllPermissions; + { + final ProtectionDomain insecPD = AccessController.doPrivileged(new PrivilegedAction<ProtectionDomain>() { + public ProtectionDomain run() { + return SecurityUtil.class.getProtectionDomain(); + } } ); + boolean _hasAllPermissions; + try { + insecPD.implies(allPermissions); + _hasAllPermissions = true; + } catch( SecurityException ace ) { + _hasAllPermissions = false; + } + hasAllPermissions = _hasAllPermissions; + } + + System.err.println("SecurityUtil: Has SecurityManager: "+ ( null != securityManager ) ) ; + System.err.println("SecurityUtil: Has AllPermissions: "+hasAllPermissions); + final Certificate[] certs = AccessController.doPrivileged(new PrivilegedAction<Certificate[]>() { + public Certificate[] run() { + return getCerts(SecurityUtil.class); + } } ); + System.err.println("SecurityUtil: Cert count: "+ ( null != certs ? certs.length : 0 )); + if( null != certs ) { + for(int i=0; i<certs.length; i++) { + System.err.println("\t cert["+i+"]: "+certs[i].toString()); + } + } + } + } + + /** + * Returns <code>true</code> if no {@link SecurityManager} has been installed + * or the installed {@link SecurityManager}'s <code>checkPermission(new AllPermission())</code> + * passes. Otherwise method returns <code>false</code>. + */ + public static final boolean hasAllPermissions() { + return hasPermission(allPermissions); + } + + /** + * Returns <code>true</code> if no {@link SecurityManager} has been installed + * or the installed {@link SecurityManager}'s <code>checkPermission(perm)</code> + * passes. Otherwise method returns <code>false</code>. + */ + public static final boolean hasPermission(Permission perm) { + try { + checkPermission(perm); + return true; + } catch( SecurityException ace ) { + return false; + } + } + + /** + * Throws an {@link SecurityException} if an installed {@link SecurityManager} + * does not permit the requested {@link AllPermission}. + */ + public static final void checkAllPermissions() throws SecurityException { + checkPermission(allPermissions); + } + + /** + * Throws an {@link SecurityException} if an installed {@link SecurityManager} + * does not permit the requested {@link Permission}. + */ + public static final void checkPermission(Permission perm) throws SecurityException { + if( null != securityManager ) { + securityManager.checkPermission(perm); + } + } + + /** + * Returns <code>true</code> if no {@link SecurityManager} has been installed + * or the installed {@link SecurityManager}'s <code>checkLink(libName)</code> + * passes. Otherwise method returns <code>false</code>. + */ + public static final boolean hasLinkPermission(String libName) { + try { + checkLinkPermission(libName); + return true; + } catch( SecurityException ace ) { + return false; + } } - public static final Certificate[] getCerts(final Class<?> clz) { - final ProtectionDomain pd = AccessController.doPrivileged(new PrivilegedAction<ProtectionDomain>() { - public ProtectionDomain run() { - return clz.getProtectionDomain(); - } } ); + /** + * Throws an {@link SecurityException} if an installed {@link SecurityManager} + * does not permit to dynamically link the given libName. + */ + public static final void checkLinkPermission(String libName) throws SecurityException { + if( null != securityManager ) { + securityManager.checkLink(libName); + } + } + + /** + * @param clz + * @return + * @throws SecurityException if the caller has no permission to access the ProtectedDomain of the given class. + */ + public static final Certificate[] getCerts(final Class<?> clz) throws SecurityException { + final ProtectionDomain pd = clz.getProtectionDomain(); final CodeSource cs = (null != pd) ? pd.getCodeSource() : null; final Certificate[] certs = (null != cs) ? cs.getCertificates() : null; return (null != certs && certs.length>0) ? certs : null; @@ -72,21 +169,5 @@ public class SecurityUtil { i++; } return i == a.length; - } - - public static final boolean equalsLocalCert(Certificate[] b) { - return equals(localCerts, b); - } - - public static final boolean equalsLocalCert(Class<?> clz) { - return equalsLocalCert(getCerts(clz)); - } - - public static final AccessControlContext getCommonAccessControlContext(Class<?> clz) { - if(equalsLocalCert(clz)) { - return localACC; - } else { - return null; - } - } + } } diff --git a/src/java/com/jogamp/common/util/cache/TempFileCache.java b/src/java/com/jogamp/common/util/cache/TempFileCache.java index 755ed7b..32f5c2a 100644 --- a/src/java/com/jogamp/common/util/cache/TempFileCache.java +++ b/src/java/com/jogamp/common/util/cache/TempFileCache.java @@ -33,10 +33,8 @@ import java.io.FilenameFilter; import java.io.IOException; import java.nio.channels.FileChannel; import java.nio.channels.FileLock; -import java.security.AccessControlContext; import com.jogamp.common.util.IOUtil; -import com.jogamp.common.util.SecurityUtil; import jogamp.common.Debug; @@ -72,8 +70,6 @@ public class TempFileCache { private File individualTmpDir; static { - final AccessControlContext acc = SecurityUtil.getCommonAccessControlContext(TempFileCache.class); - // Global Lock ! synchronized (System.out) { // Create / initialize the temp root directory, starting the Reaper @@ -81,8 +77,8 @@ public class TempFileCache { // exception, set an error code. File _tmpBaseDir = null; try { - _tmpBaseDir = new File(IOUtil.getTempDir(true /* executable */, acc), tmpDirPrefix); - _tmpBaseDir = IOUtil.testDir(_tmpBaseDir, true /* create */, false /* executable */, acc); // executable already checked + _tmpBaseDir = new File(IOUtil.getTempDir(true /* executable */), tmpDirPrefix); + _tmpBaseDir = IOUtil.testDir(_tmpBaseDir, true /* create */, false /* executable */); // executable already checked } catch (Exception ex) { System.err.println("Warning: Catched Exception while retrieving temp base directory:"); ex.printStackTrace(); |