aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog38
-rw-r--r--netx/net/sourceforge/jnlp/Launcher.java14
-rw-r--r--netx/net/sourceforge/jnlp/resources/Messages.properties5
-rw-r--r--netx/net/sourceforge/jnlp/runtime/Boot.java1
-rw-r--r--netx/net/sourceforge/jnlp/runtime/JNLPClassLoader.java14
-rw-r--r--netx/net/sourceforge/jnlp/runtime/JNLPRuntime.java11
-rw-r--r--netx/net/sourceforge/jnlp/security/CertWarningPane.java9
-rw-r--r--netx/net/sourceforge/jnlp/security/KeyStores.java3
-rw-r--r--netx/net/sourceforge/jnlp/security/viewer/CertificatePane.java19
-rw-r--r--netx/net/sourceforge/jnlp/services/SingleInstanceLock.java13
-rw-r--r--netx/net/sourceforge/jnlp/services/XFileSaveService.java3
-rw-r--r--netx/net/sourceforge/jnlp/services/XPersistenceService.java5
-rw-r--r--netx/net/sourceforge/jnlp/util/FileUtils.java75
-rw-r--r--netx/net/sourceforge/jnlp/util/XDesktopEntry.java3
14 files changed, 184 insertions, 29 deletions
diff --git a/ChangeLog b/ChangeLog
index b3c76a0..d2cf778 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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
*/