diff options
-rw-r--r-- | ChangeLog | 38 | ||||
-rw-r--r-- | netx/net/sourceforge/jnlp/Launcher.java | 14 | ||||
-rw-r--r-- | netx/net/sourceforge/jnlp/resources/Messages.properties | 5 | ||||
-rw-r--r-- | netx/net/sourceforge/jnlp/runtime/Boot.java | 1 | ||||
-rw-r--r-- | netx/net/sourceforge/jnlp/runtime/JNLPClassLoader.java | 14 | ||||
-rw-r--r-- | netx/net/sourceforge/jnlp/runtime/JNLPRuntime.java | 11 | ||||
-rw-r--r-- | netx/net/sourceforge/jnlp/security/CertWarningPane.java | 9 | ||||
-rw-r--r-- | netx/net/sourceforge/jnlp/security/KeyStores.java | 3 | ||||
-rw-r--r-- | netx/net/sourceforge/jnlp/security/viewer/CertificatePane.java | 19 | ||||
-rw-r--r-- | netx/net/sourceforge/jnlp/services/SingleInstanceLock.java | 13 | ||||
-rw-r--r-- | netx/net/sourceforge/jnlp/services/XFileSaveService.java | 3 | ||||
-rw-r--r-- | netx/net/sourceforge/jnlp/services/XPersistenceService.java | 5 | ||||
-rw-r--r-- | netx/net/sourceforge/jnlp/util/FileUtils.java | 75 | ||||
-rw-r--r-- | netx/net/sourceforge/jnlp/util/XDesktopEntry.java | 3 |
14 files changed, 184 insertions, 29 deletions
@@ -1,3 +1,41 @@ +2010-11-24 Omair Majid <[email protected]> + + * netx/net/sourceforge/jnlp/util/FileUtils.java + (createRestrictedDirectory): New method. Creates a directory with reduced + permissions. + (createRestrictedFile(File,boolean)): New method. Creates a file with reduced + permissions. + (createRestrictedFile(File,boolean,boolean): New method. Creates a file or + a directory with reduced permissions. + * netx/net/sourceforge/jnlp/Launcher.java + (markNetxRunning): Do not grant unnecessary file permissions. + * netx/net/sourceforge/jnlp/runtime/Boot.java: Remove umask from + help message. + * netx/net/sourceforge/jnlp/runtime/JNLPClassLoader.java + (activateNative): Create file with proper permissions. + (getNativeDir): Create directory with proper permissions. + * netx/net/sourceforge/jnlp/runtime/JNLPRuntime.java + (initializeStreams): Create files with proper permissions. + * netx/net/sourceforge/jnlp/security/CertWarningPane.java + (CheckBoxListener.actionPerformed): Likewise. + * netx/net/sourceforge/jnlp/security/KeyStores.java + (createKeyStoreFromFile): Likewise. + * netx/net/sourceforge/jnlp/security/viewer/CertificatePane.java + (ImportButtonListener.actionPerformed): Likewise. + (RemoveButtonListener.actionPerformed): Likewise. + * netx/net/sourceforge/jnlp/services/SingleInstanceLock.java + (createWithPort): Likewise. + (getLockFile): Likewise. + * netx/net/sourceforge/jnlp/services/XExtendedService.java + (openFile): Likewise. + * netx/net/sourceforge/jnlp/services/XPersistenceService.java + (create): Likewise. + * netx/net/sourceforge/jnlp/util/XDesktopEntry.java + (installDesktopLauncher): Likewise. + * netx/net/sourceforge/jnlp/resources/Messages.properties: Add + CantCreateFile, RCantCreateDir and RCantRename. Remove BNoBase and + BOUmask. + 2010-11-24 Deepak Bhole <[email protected]> Fix PR593: Increment of invalidated iterator in IcedTeaPluginUtils (patch diff --git a/netx/net/sourceforge/jnlp/Launcher.java b/netx/net/sourceforge/jnlp/Launcher.java index a69400c..13e0f52 100644 --- a/netx/net/sourceforge/jnlp/Launcher.java +++ b/netx/net/sourceforge/jnlp/Launcher.java @@ -48,6 +48,7 @@ import net.sourceforge.jnlp.runtime.JNLPClassLoader; import net.sourceforge.jnlp.runtime.JNLPRuntime; import net.sourceforge.jnlp.services.InstanceExistsException; import net.sourceforge.jnlp.services.ServiceUtil; +import net.sourceforge.jnlp.util.FileUtils; import net.sourceforge.jnlp.util.Reflect; import javax.swing.SwingUtilities; @@ -727,8 +728,9 @@ public class Launcher { File netxRunningFile = new File(JNLPRuntime.getConfiguration() .getProperty(DeploymentConfiguration.KEY_USER_NETX_RUNNING_FILE)); - netxRunningFile.getParentFile().mkdirs(); - if (netxRunningFile.createNewFile()) { + if (!netxRunningFile.exists()) { + netxRunningFile.getParentFile().mkdirs(); + FileUtils.createRestrictedFile(netxRunningFile, true); FileOutputStream fos = new FileOutputStream(netxRunningFile); try { fos.write(message.getBytes()); @@ -737,14 +739,6 @@ public class Launcher { } } - if (!netxRunningFile.isFile()) { - if (JNLPRuntime.isDebug()) { - System.err.println("Unable to create instance file"); - } - fileLock = null; - return; - } - FileInputStream is = new FileInputStream(netxRunningFile); FileChannel channel = is.getChannel(); fileLock = channel.tryLock(0, Long.MAX_VALUE, true); diff --git a/netx/net/sourceforge/jnlp/resources/Messages.properties b/netx/net/sourceforge/jnlp/resources/Messages.properties index ffe5b19..19112bb 100644 --- a/netx/net/sourceforge/jnlp/resources/Messages.properties +++ b/netx/net/sourceforge/jnlp/resources/Messages.properties @@ -124,11 +124,13 @@ BParamNA=Parameters not used for this type of JNLP file (ignored). BBadProp=Incorrect property format {0} (should be key=value)
BBadParam=Incorrect parameter format {0} (should be name=value)
BNoDir=Directory {0} does not exist.
-BNoBase=No base directory (contains cache and other data)
RNoResource=Missing Resource: {0}
RShutdown=This exception to prevent shutdown of JVM, but the process has been terminated.
RExitTaken=Exit class already set and caller is not exit class.
RCantReplaceSM=Changing the SecurityManager is not allowed.
+RCantCreateFile=Cant create file {0}
+RCantCreateDir=Cant create directory {0}
+RCantRename=Cant rename {0} to {0}
RDenyStopped=Stopped applications have no permissions.
RExitNoApp=Can not exit the JVM because the current application cannot be determined.
RNoLockDir=Unable to create locks directory ({0})
@@ -152,7 +154,6 @@ BONoupdate = Disables checking for updates. BOHeadless = Disables download window, other UIs.
BOStrict = Enables strict checking of JNLP file format.
BOViewer = Shows the trusted certificate viewer.
-BOUmask = Sets the umask for files created by an application.
BXnofork = Do not create another JVM.
BXclearcache= Clean the JNLP application cache.
BOHelp = Print this message and exit.
diff --git a/netx/net/sourceforge/jnlp/runtime/Boot.java b/netx/net/sourceforge/jnlp/runtime/Boot.java index 8883235..50ab81f 100644 --- a/netx/net/sourceforge/jnlp/runtime/Boot.java +++ b/netx/net/sourceforge/jnlp/runtime/Boot.java @@ -105,7 +105,6 @@ public final class Boot implements PrivilegedAction<Void> { + " -noupdate "+R("BONoupdate")+"\n" + " -headless "+R("BOHeadless")+"\n" + " -strict "+R("BOStrict")+"\n" - + " -umask=value "+R("BOUmask")+"\n" + " -Xnofork "+R("BXnofork")+"\n" + " -Xclearcache "+R("BXclearcache")+"\n" + " -help "+R("BOHelp")+"\n"; diff --git a/netx/net/sourceforge/jnlp/runtime/JNLPClassLoader.java b/netx/net/sourceforge/jnlp/runtime/JNLPClassLoader.java index 104bf09..b353a9d 100644 --- a/netx/net/sourceforge/jnlp/runtime/JNLPClassLoader.java +++ b/netx/net/sourceforge/jnlp/runtime/JNLPClassLoader.java @@ -815,7 +815,9 @@ public class JNLPClassLoader extends URLClassLoader { nativeDir = getNativeDir(); File outFile = new File(nativeDir, name); - + if (!outFile.isFile()) { + FileUtils.createRestrictedFile(outFile, true); + } CacheUtil.streamCopy(jarFile.getInputStream(e), new FileOutputStream(outFile)); @@ -837,12 +839,18 @@ public class JNLPClassLoader extends URLClassLoader { + File.separator + "netx-native-" + (new Random().nextInt() & 0xFFFF)); - if (!nativeDir.mkdirs()) + File parent = nativeDir.getParentFile(); + if (!parent.isDirectory() && !parent.mkdirs()) { return null; - else { + } + + try { + FileUtils.createRestrictedDirectory(nativeDir); // add this new native directory to the search path addNativeDirectory(nativeDir); return nativeDir; + } catch (IOException e) { + return null; } } diff --git a/netx/net/sourceforge/jnlp/runtime/JNLPRuntime.java b/netx/net/sourceforge/jnlp/runtime/JNLPRuntime.java index 13feed2..848a198 100644 --- a/netx/net/sourceforge/jnlp/runtime/JNLPRuntime.java +++ b/netx/net/sourceforge/jnlp/runtime/JNLPRuntime.java @@ -268,12 +268,15 @@ public class JNLPRuntime { .getProperty(DeploymentConfiguration.KEY_ENABLE_LOGGING)); if (redirectStreams || enableLogging) { String logDir = config.getProperty(DeploymentConfiguration.KEY_USER_LOG_DIR); - File errFile = new File(logDir, JNLPRuntime.STDERR_FILE); - errFile.getParentFile().mkdirs(); - File outFile = new File(logDir, JNLPRuntime.STDOUT_FILE); - outFile.getParentFile().mkdirs(); try { + File errFile = new File(logDir, JNLPRuntime.STDERR_FILE); + errFile.getParentFile().mkdirs(); + FileUtils.createRestrictedFile(errFile, true); + File outFile = new File(logDir, JNLPRuntime.STDOUT_FILE); + outFile.getParentFile().mkdirs(); + FileUtils.createRestrictedFile(outFile, true); + if (redirectStreams) { System.setErr(new PrintStream(new FileOutputStream(errFile))); System.setOut(new PrintStream(new FileOutputStream(outFile))); diff --git a/netx/net/sourceforge/jnlp/security/CertWarningPane.java b/netx/net/sourceforge/jnlp/security/CertWarningPane.java index e1ebecb..56105e9 100644 --- a/netx/net/sourceforge/jnlp/security/CertWarningPane.java +++ b/netx/net/sourceforge/jnlp/security/CertWarningPane.java @@ -47,6 +47,7 @@ import java.awt.Font; import java.awt.GridLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; +import java.io.File; import java.io.FileOutputStream; import java.io.OutputStream; import java.security.KeyStore; @@ -68,6 +69,7 @@ import net.sourceforge.jnlp.runtime.JNLPRuntime; import net.sourceforge.jnlp.security.KeyStores.Level; import net.sourceforge.jnlp.security.KeyStores.Type; import net.sourceforge.jnlp.security.SecurityWarning.AccessType; +import net.sourceforge.jnlp.util.FileUtils; /** * Provides the panel for using inside a SecurityWarningDialog. These dialogs are @@ -246,7 +248,12 @@ public class CertWarningPane extends SecurityDialogPanel { KeyStore ks = KeyStores.getKeyStore(Level.USER, Type.CERTS); X509Certificate c = (X509Certificate) parent.getJarSigner().getPublisher(); CertificateUtils.addToKeyStore(c, ks); - OutputStream os = new FileOutputStream(KeyStores.getKeyStoreLocation(Level.USER, Type.CERTS)); + File keyStoreFile = new File(KeyStores.getKeyStoreLocation(Level.USER, Type.CERTS)); + if (!keyStoreFile.isFile()) { + FileUtils.createRestrictedFile(keyStoreFile, true); + } + + OutputStream os = new FileOutputStream(keyStoreFile); ks.store(os, KeyStores.getPassword()); if (JNLPRuntime.isDebug()) { System.out.println("certificate is now permanently trusted"); diff --git a/netx/net/sourceforge/jnlp/security/KeyStores.java b/netx/net/sourceforge/jnlp/security/KeyStores.java index 05bc150..de4aff3 100644 --- a/netx/net/sourceforge/jnlp/security/KeyStores.java +++ b/netx/net/sourceforge/jnlp/security/KeyStores.java @@ -53,6 +53,7 @@ import java.util.StringTokenizer; import net.sourceforge.jnlp.runtime.DeploymentConfiguration; import net.sourceforge.jnlp.runtime.JNLPRuntime; import net.sourceforge.jnlp.runtime.Translator; +import net.sourceforge.jnlp.util.FileUtils; /** * The <code>KeyStores</code> class allows easily accessing the various KeyStores @@ -339,6 +340,8 @@ public final class KeyStores { if (!parent.isDirectory() && !parent.mkdirs()) { throw new IOException("unable to create " + parent); } + FileUtils.createRestrictedFile(file, true); + ks = KeyStore.getInstance(KEYSTORE_TYPE); ks.load(null, password.toCharArray()); FileOutputStream fos = new FileOutputStream(file); diff --git a/netx/net/sourceforge/jnlp/security/viewer/CertificatePane.java b/netx/net/sourceforge/jnlp/security/viewer/CertificatePane.java index f309b02..ce36154 100644 --- a/netx/net/sourceforge/jnlp/security/viewer/CertificatePane.java +++ b/netx/net/sourceforge/jnlp/security/viewer/CertificatePane.java @@ -45,6 +45,7 @@ import java.awt.FlowLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.KeyEvent; +import java.io.File; import java.io.FileOutputStream; import java.io.OutputStream; import java.io.PrintStream; @@ -76,6 +77,7 @@ import net.sourceforge.jnlp.security.KeyStores; import net.sourceforge.jnlp.security.SecurityUtil; import net.sourceforge.jnlp.security.SecurityWarningDialog; import net.sourceforge.jnlp.security.KeyStores.Level; +import net.sourceforge.jnlp.util.FileUtils; public class CertificatePane extends JPanel { @@ -361,8 +363,13 @@ public class CertificatePane extends JPanel { try { KeyStore ks = keyStore; CertificateUtils.addToKeyStore(chooser.getSelectedFile(), ks); - OutputStream os = new FileOutputStream( - KeyStores.getKeyStoreLocation(currentKeyStoreLevel, currentKeyStoreType)); + File keyStoreFile = new File(KeyStores + .getKeyStoreLocation(currentKeyStoreLevel, currentKeyStoreType)); + if (!keyStoreFile.isFile()) { + FileUtils.createRestrictedFile(keyStoreFile, true); + } + + OutputStream os = new FileOutputStream(keyStoreFile); ks.store(os, KeyStores.getPassword()); repopulateTables(); } catch (Exception ex) { @@ -436,8 +443,12 @@ public class CertificatePane extends JPanel { JOptionPane.YES_NO_OPTION); if (i == 0) { keyStore.deleteEntry(alias); - FileOutputStream fos = new FileOutputStream( - KeyStores.getKeyStoreLocation(currentKeyStoreLevel, currentKeyStoreType)); + File keyStoreFile = new File(KeyStores + .getKeyStoreLocation(currentKeyStoreLevel, currentKeyStoreType)); + if (!keyStoreFile.isFile()) { + FileUtils.createRestrictedFile(keyStoreFile, true); + } + FileOutputStream fos = new FileOutputStream(keyStoreFile); keyStore.store(fos, KeyStores.getPassword()); fos.close(); } diff --git a/netx/net/sourceforge/jnlp/services/SingleInstanceLock.java b/netx/net/sourceforge/jnlp/services/SingleInstanceLock.java index 3e6b3d6..d9430a3 100644 --- a/netx/net/sourceforge/jnlp/services/SingleInstanceLock.java +++ b/netx/net/sourceforge/jnlp/services/SingleInstanceLock.java @@ -67,6 +67,7 @@ class SingleInstanceLock { */ public void createWithPort(int localPort) throws IOException { + FileUtils.createRestrictedFile(lockFile, true); BufferedWriter lockFileWriter = new BufferedWriter(new FileWriter(lockFile, false)); lockFileWriter.write(String.valueOf(localPort)); lockFileWriter.newLine(); @@ -132,9 +133,17 @@ class SingleInstanceLock { File baseDir = new File(JNLPRuntime.getConfiguration() .getProperty(DeploymentConfiguration.KEY_USER_LOCKS_DIR)); - if (!baseDir.isDirectory() && !baseDir.mkdirs()) { - throw new RuntimeException(R("RNoLockDir", baseDir)); + if (!baseDir.isDirectory()) { + if (!baseDir.getParentFile().isDirectory() && !baseDir.getParentFile().mkdirs()) { + throw new RuntimeException(R("RNoLockDir", baseDir)); + } + try { + FileUtils.createRestrictedDirectory(baseDir); + } catch (IOException e) { + throw new RuntimeException(R("RNoLockDir", baseDir)); + } } + String lockFileName = getLockFileName(); File applicationLockFile = new File(baseDir, lockFileName); return applicationLockFile; diff --git a/netx/net/sourceforge/jnlp/services/XFileSaveService.java b/netx/net/sourceforge/jnlp/services/XFileSaveService.java index dc4fdc0..c4e856b 100644 --- a/netx/net/sourceforge/jnlp/services/XFileSaveService.java +++ b/netx/net/sourceforge/jnlp/services/XFileSaveService.java @@ -44,6 +44,7 @@ import java.lang.ref.*; import javax.jnlp.*; import net.sourceforge.jnlp.security.SecurityWarning.AccessType; +import net.sourceforge.jnlp.util.FileUtils; import javax.swing.JFileChooser; import javax.swing.JOptionPane; @@ -121,7 +122,7 @@ class XFileSaveService implements FileSaveService { if (!replace) return; } else { - file.createNewFile(); + FileUtils.createRestrictedFile(file, true); } if (file.canWrite()) { diff --git a/netx/net/sourceforge/jnlp/services/XPersistenceService.java b/netx/net/sourceforge/jnlp/services/XPersistenceService.java index bbef251..b409f82 100644 --- a/netx/net/sourceforge/jnlp/services/XPersistenceService.java +++ b/netx/net/sourceforge/jnlp/services/XPersistenceService.java @@ -26,6 +26,7 @@ import javax.jnlp.*; import net.sourceforge.jnlp.*; import net.sourceforge.jnlp.cache.*; import net.sourceforge.jnlp.runtime.*; +import net.sourceforge.jnlp.util.FileUtils; /** * The BasicService JNLP service. @@ -96,9 +97,11 @@ class XPersistenceService implements PersistenceService { File file = toCacheFile(location); file.getParentFile().mkdirs(); - if (!file.createNewFile()) + if (file.exists()) throw new IOException("File already exists."); + FileUtils.createRestrictedFile(file, true); + return maxsize; } diff --git a/netx/net/sourceforge/jnlp/util/FileUtils.java b/netx/net/sourceforge/jnlp/util/FileUtils.java index aa1c316..b006424 100644 --- a/netx/net/sourceforge/jnlp/util/FileUtils.java +++ b/netx/net/sourceforge/jnlp/util/FileUtils.java @@ -16,6 +16,8 @@ package net.sourceforge.jnlp.util; +import static net.sourceforge.jnlp.runtime.Translator.R; + import java.io.File; import java.io.IOException; @@ -72,6 +74,79 @@ public final class FileUtils { } /** + * Creates a new directory with minimum permissions. The directory is not + * readable or writable by anyone other than the owner. The parent + * directories are not created; they must exist before this is called. + * + * @throws IOException + */ + public static void createRestrictedDirectory(File directory) throws IOException { + createRestrictedFile(directory, true, true); + } + + /** + * Creates a new file with minimum permissions. The file is not readable or + * writable by anyone other than the owner. If writeableByOnwer is false, + * even the owner can not write to it. + * + * @throws IOException + */ + public static void createRestrictedFile(File file, boolean writableByOwner) throws IOException { + createRestrictedFile(file, false, writableByOwner); + } + + /** + * Creates a new file or directory with minimum permissions. The file is not + * readable or writable by anyone other than the owner. If writeableByOnwer + * is false, even the owner can not write to it. If isDir is true, then the + * directory can be executed by the owner + * + * @throws IOException + */ + private static void createRestrictedFile(File file, boolean isDir, boolean writableByOwner) throws IOException { + + File tempFile = null; + + tempFile = new File(file.getCanonicalPath() + ".temp"); + + if (isDir) { + if (!tempFile.mkdir()) { + throw new IOException(R("RCantCreateDir", tempFile)); + } + } else { + if (!tempFile.createNewFile()) { + throw new IOException(R("RCantCreateFile", tempFile)); + } + } + + // remove all permissions + tempFile.setExecutable(false, false); + tempFile.setReadable(false, false); + tempFile.setWritable(false, false); + + // allow owner to read + tempFile.setReadable(true, true); + + // allow owner to write + if (writableByOwner) { + tempFile.setWritable(true, true); + } + + // allow owner to enter directories + if (isDir) { + tempFile.setExecutable(true, true); + } + + // 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)); + } + + } + + /** * Returns a String that is suitable for using in GUI elements for * displaying (long) paths to users. * diff --git a/netx/net/sourceforge/jnlp/util/XDesktopEntry.java b/netx/net/sourceforge/jnlp/util/XDesktopEntry.java index d5ebf0f..eae4146 100644 --- a/netx/net/sourceforge/jnlp/util/XDesktopEntry.java +++ b/netx/net/sourceforge/jnlp/util/XDesktopEntry.java @@ -158,6 +158,9 @@ public class XDesktopEntry { if (!shortcutFile.getParentFile().isDirectory() && !shortcutFile.getParentFile().mkdirs()) { throw new IOException(shortcutFile.getParentFile().toString()); } + + FileUtils.createRestrictedFile(shortcutFile, true); + /* * Write out a Java String (UTF-16) as a UTF-8 file */ |