Description: fix info disclosure via insecure temporary directory use
Origin: backport, http://icedtea.classpath.org/hg/release/icedtea-web-1.4/rev/b9733f552c79
Origin: backport, http://icedtea.classpath.org/hg/release/icedtea-web-1.4/rev/35f4d27451fd
Origin: backport, http://icedtea.classpath.org/hg/release/icedtea-web-1.4/rev/1ae3613c82f2
Bug-RedHat: https://bugzilla.redhat.com/show_bug.cgi?id=CVE-2013-6493

Index: icedtea-web-1.2.3/plugin/icedteanp/IcedTeaNPPlugin.cc
===================================================================
--- icedtea-web-1.2.3.orig/plugin/icedteanp/IcedTeaNPPlugin.cc	2014-03-04 15:57:17.915676497 -0500
+++ icedtea-web-1.2.3/plugin/icedteanp/IcedTeaNPPlugin.cc	2014-03-04 16:00:48.775682144 -0500
@@ -38,6 +38,9 @@
 
 // System includes.
 #include <dlfcn.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <dirent.h>
 #include <errno.h>
 #include <libgen.h>
 #include <stdio.h>
@@ -154,10 +157,11 @@
 #endif
 
 // Data directory for plugin.
-static gchar* data_directory = NULL;
+static std::string data_directory;
+static DIR *data_directory_descriptor;
 
 // Fully-qualified appletviewer executable.
-static gchar* appletviewer_executable = NULL;
+static const char* appletviewer_executable = ICEDTEA_WEB_JRE "/bin/java";
 
 // Applet viewer input channel (needs to be static because it is used in plugin_in_pipe_callback)
 static GIOChannel* in_from_appletviewer = NULL;
@@ -238,7 +242,7 @@
 NPError get_cookie_info(const char* siteAddr, char** cookieString, uint32_t* len);
 NPError get_proxy_info(const char* siteAddr, char** proxy, uint32_t* len);
 void consume_message(gchar* message);
-void start_jvm_if_needed();
+NPError start_jvm_if_needed();
 static void appletviewer_monitor(GPid pid, gint status, gpointer data);
 void plugin_send_initialization_message(char* instance, gulong handle,
                                                int width, int height,
@@ -285,7 +289,21 @@
 
 #endif
 
-
+static void cleanUpDir(){
+  //free data_directory descriptor 
+  if (data_directory_descriptor != NULL) {
+    closedir(data_directory_descriptor);
+  }
+  //clean up pipes directory
+  PLUGIN_DEBUG ("Removing runtime directory %s \n", data_directory.c_str());
+  int removed = rmdir(data_directory.c_str());
+  if (removed != 0) {
+    PLUGIN_ERROR_THREE ("Failed to remove runtime directory %s, because of  %s \n", data_directory.c_str(), strerror(errno));
+  } else {
+    PLUGIN_DEBUG ("Removed runtime directory %s \n", data_directory.c_str());
+  }
+  data_directory_descriptor = NULL;
+}
 /* 
  * Find first member in GHashTable* depending on version of glib
  */
@@ -351,6 +369,7 @@
   gchar* cookie_info = NULL;
 
   NPObject* npPluginObj = NULL;
+  NPError startup_error = NPERR_NO_ERROR; 
 
   if (!instance)
     {
@@ -369,7 +388,7 @@
     }
 
   // start the jvm if needed
-  start_jvm_if_needed();
+  startup_error = start_jvm_if_needed();
 
   // Initialize data->instance_id.
   //
@@ -468,7 +487,7 @@
 }
 
 // Starts the JVM if it is not already running
-void start_jvm_if_needed()
+NPError start_jvm_if_needed()
 {
 
   // This is asynchronized function. It must
@@ -483,7 +502,7 @@
   if (jvm_up)
   {
       PLUGIN_DEBUG("JVM is up. Returning.\n");
-      return;
+      return  NPERR_NO_ERROR;
   }
 
   PLUGIN_DEBUG("No JVM is running. Attempting to start one...\n");
@@ -496,7 +515,7 @@
 
   // in_pipe_name
   in_pipe_name = g_strdup_printf ("%s/%d-icedteanp-appletviewer-to-plugin",
-                                         data_directory, getpid());
+                                         data_directory.c_str(), getpid());
   if (!in_pipe_name)
     {
       PLUGIN_ERROR ("Failed to create input pipe name.");
@@ -523,7 +542,7 @@
 
   // out_pipe_name
   out_pipe_name = g_strdup_printf ("%s/%d-icedteanp-plugin-to-appletviewer",
-                                         data_directory, getpid());
+                                         data_directory.c_str(), getpid());
 
   if (!out_pipe_name)
     {
@@ -651,10 +670,12 @@
   g_free (in_pipe_name);
   in_pipe_name = NULL;
 
+  cleanUpDir();
  done:
 
   // Now other threads may re-enter.. unlock the mutex
   g_mutex_unlock(vm_start_mutex);
+  return np_error;
 
 }
 
@@ -2176,91 +2197,43 @@
   if (initialized)
     return NPERR_NO_ERROR;
 
+  NPError np_error = NPERR_NO_ERROR;
   // Make sure the plugin data directory exists, creating it if
   // necessary.
-  data_directory = g_strconcat (P_tmpdir, NULL);
-  if (!data_directory)
-    {
-      PLUGIN_ERROR ("Failed to create data directory name.");
-      return NPERR_OUT_OF_MEMORY_ERROR;
-    }
-  NPError np_error = NPERR_NO_ERROR;
-  gchar* filename = NULL;
-
-  // If P_tmpdir does not exist, try /tmp directly
-
-  if (!g_file_test (data_directory,
-                    (GFileTest) (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR)))
-    {
-      int file_error = 0;
-
-      data_directory = g_strconcat ("/tmp", NULL);
-        if (!data_directory)
-          {
-            PLUGIN_ERROR ("Failed to create data directory name.");
-            return NPERR_OUT_OF_MEMORY_ERROR;
-          }
-
-    }
-
-  data_directory = g_strconcat (data_directory, "/icedteaplugin-", getenv("USER"), NULL);
 
-  if (!data_directory)
-  {
-      PLUGIN_ERROR ("Failed to create data directory name.");
-      return NPERR_OUT_OF_MEMORY_ERROR;
+  data_directory = IcedTeaPluginUtilities::getRuntimePath() + "/icedteaplugin-";
+  if (getenv("USER") != NULL) {
+    data_directory = data_directory + getenv("USER") + "-";
   }
-
+  data_directory += "XXXXXX";
   // Now create a icedteaplugin subdir
-  if (!g_file_test (data_directory,
-                    (GFileTest) (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR)))
-    {
-      int file_error = 0;
-
-      file_error = g_mkdir (data_directory, 0700);
-      if (file_error != 0)
-        {
-          PLUGIN_ERROR_THREE ("Failed to create data directory",
-                          data_directory,
-                          strerror (errno));
-          np_error = NPERR_GENERIC_ERROR;
-          goto cleanup_data_directory;
-        }
-    }
-
-
-  // If data directory doesn't exit by this point, bail
-  if (!g_file_test (data_directory,
-                    (GFileTest) (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR)))
-    {
-      PLUGIN_ERROR_THREE ("Temp directory does not exist: ",
-                          data_directory,
-                          strerror (errno));
-
-      np_error = NPERR_GENERIC_ERROR;
-            goto cleanup_data_directory;
+  char fileNameX[data_directory.length()+1];
+  std::strcpy (fileNameX, data_directory.c_str());
+  char * fileName = mkdtemp(fileNameX);
+  if (fileName == NULL) {
+    PLUGIN_ERROR_THREE ("Failed to create data directory %s, %s\n",
+                        data_directory.c_str(),
+                        strerror (errno));
+    return NPERR_GENERIC_ERROR;
+  }
+  data_directory = std::string(fileName);
 
-    }
+  //open uniques icedteaplugin subdir for one single run  
+  data_directory_descriptor = opendir(data_directory.c_str());
+  if (data_directory_descriptor == NULL) {
+      PLUGIN_ERROR_THREE ("Failed to open data directory %s %s\n",
+                      data_directory.c_str(), strerror (errno));
+      return NPERR_GENERIC_ERROR;
+  }
 
   // Set appletviewer_executable.
-  filename = g_strdup(ICEDTEA_WEB_JRE);
-  appletviewer_executable = g_strdup_printf ("%s/bin/java",
-                                             filename);
   PLUGIN_DEBUG("Executing java at %s\n", appletviewer_executable);
-  if (!appletviewer_executable)
-    {
-      PLUGIN_ERROR ("Failed to create appletviewer executable name.");
-      np_error = NPERR_OUT_OF_MEMORY_ERROR;
-      goto cleanup_filename;
-    }
-
   np_error = plugin_test_appletviewer ();
   if (np_error != NPERR_NO_ERROR)
     {
       plugin_display_failure_dialog ();
-      goto cleanup_appletviewer_executable;
+      return np_error;
     }
-  g_free (filename);
 
   initialized = true;
 
@@ -2296,30 +2269,6 @@
   PLUGIN_DEBUG ("NP_Initialize return\n");
 
   return NPERR_NO_ERROR;
-
- cleanup_appletviewer_executable:
-  if (appletviewer_executable)
-    {
-      g_free (appletviewer_executable);
-      appletviewer_executable = NULL;
-    }
-
- cleanup_filename:
-  if (filename)
-    {
-      g_free (filename);
-      filename = NULL;
-    }
-
- cleanup_data_directory:
-  if (data_directory)
-    {
-      g_free (data_directory);
-      data_directory = NULL;
-    }
-
-
-  return np_error;
 }
 
 // Returns a string describing the MIME type that this plugin
@@ -2385,18 +2334,6 @@
       plugin_instance_mutex = NULL;
     }
 
-  if (data_directory)
-    {
-      g_free (data_directory);
-      data_directory = NULL;
-    }
-
-  if (appletviewer_executable)
-    {
-      g_free (appletviewer_executable);
-      appletviewer_executable = NULL;
-    }
-
   // stop the appletviewer
   plugin_stop_appletviewer();
 
@@ -2467,6 +2404,8 @@
   delete plugin_to_java_bus;
   //delete internal_bus;
 
+  cleanUpDir();
+  
   PLUGIN_DEBUG ("NP_Shutdown return\n");
 
   return NPERR_NO_ERROR;
Index: icedtea-web-1.2.3/plugin/icedteanp/IcedTeaPluginUtils.cc
===================================================================
--- icedtea-web-1.2.3.orig/plugin/icedteanp/IcedTeaPluginUtils.cc	2014-03-04 15:57:17.915676497 -0500
+++ icedtea-web-1.2.3/plugin/icedteanp/IcedTeaPluginUtils.cc	2014-03-04 15:57:17.915676497 -0500
@@ -1014,6 +1014,36 @@
     } while(1);
 }
 
+std::string IcedTeaPluginUtilities::getTmpPath(){
+  const char* tmpdir_env = getenv("TMPDIR");
+  if (tmpdir_env != NULL && g_file_test (tmpdir_env,
+                    (GFileTest) (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR)))
+  {
+    return std::string(tmpdir_env);
+  }
+  else if (g_file_test (P_tmpdir,
+                    (GFileTest) (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR)))
+  {
+    return std::string(P_tmpdir);
+  }
+  else
+  {
+    // If TMPDIR and P_tmpdir do not exist, try /tmp directly
+    return "/tmp";
+  }
+}
+
+std::string IcedTeaPluginUtilities::getRuntimePath(){
+ const char* rntdir_env = getenv("XDG_RUNTIME_DIR");
+  if (rntdir_env != NULL && g_file_test (rntdir_env,
+                    (GFileTest) (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR)))
+  {
+    return std::string(rntdir_env);
+  }
+  return IcedTeaPluginUtilities::getTmpPath();
+}
+
+
 /******************************************
  * Begin JavaMessageSender implementation *
  ******************************************
Index: icedtea-web-1.2.3/plugin/icedteanp/IcedTeaPluginUtils.h
===================================================================
--- icedtea-web-1.2.3.orig/plugin/icedteanp/IcedTeaPluginUtils.h	2014-03-04 15:57:17.915676497 -0500
+++ icedtea-web-1.2.3/plugin/icedteanp/IcedTeaPluginUtils.h	2014-03-04 15:57:17.915676497 -0500
@@ -267,6 +267,9 @@
 
     	/* Posts call in async queue and waits till execution completes */
     	static void callAndWaitForResult(NPP instance, void (*func) (void *), AsyncCallThreadData* data);
+        static std::string getTmpPath();
+        static std::string getRuntimePath();
+
 };
 
 /*
