$OpenBSD: patch-plugin_npapi_plugin_cpp,v 1.7 2011/12/19 21:23:24 sthen Exp $

Fix creating world-readable cookies under /tmp with predictable filenames. CVE-2011-4328

--- plugin/npapi/plugin.cpp.orig	Fri Mar 18 09:44:30 2011
+++ plugin/npapi/plugin.cpp	Thu Dec 15 05:12:51 2011
@@ -25,6 +25,9 @@
 #include <boost/scoped_array.hpp>
 #include <boost/algorithm/string/replace.hpp>
 #include <boost/algorithm/string/find.hpp>
+#define BOOST_IOSTREAMS_USE_DEPRECATED
+#include <boost/iostreams/device/file_descriptor.hpp>
+#include <boost/iostreams/stream.hpp>
 #include <cassert>
 #include <string>
 #include <cstdlib> // getenv
@@ -150,6 +153,37 @@ getPluginDescription() 
     return desc;
 }
 
+boost::iostreams::file_descriptor_sink getfdsink(char mkstemplate[]);
+
+boost::iostreams::file_descriptor_sink
+getfdsink(char mksTemplate[])
+{
+  int fd, suffix = std::string(mksTemplate).size() - std::string(mksTemplate).find("XXXXXX") - 6;
+#ifdef HAVE_MKSTEMPS
+  fd = mkstemps (mksTemplate, suffix);
+#else
+  if (suffix > 0) {
+    char *mksTNoSuff = const_cast<char*>(std::string(mksTemplate).substr(0, std::string(mksTemplate).size() - suffix).c_str());
+    fd = mkstemp (mksTNoSuff);
+    const char *mksTSuffix = std::string(mksTemplate).substr(std::string(mksTemplate).size() - suffix, suffix).c_str();
+    std::stringstream mksTFull;
+    mksTFull << mksTNoSuff << mksTSuffix;
+    if (rename (mksTNoSuff, mksTFull.str().c_str()) != 0) {
+      gnash::log_error("Failed to rename %s", mksTNoSuff);
+    }
+    strcpy (mksTemplate, mksTFull.str().c_str());
+  } else {
+    fd = mkstemp (mksTemplate);
+  }
+#endif
+#if BOOST_VERSION < 104400
+  boost::iostreams::file_descriptor_sink fdsink(fd, true);
+#else
+  boost::iostreams::file_descriptor_sink fdsink(fd, boost::iostreams::close_handle);
+#endif
+  return fdsink;
+}
+
 //
 // general initialization and shutdown
 //
@@ -954,22 +988,25 @@ create_standalone_launcher(const std::string& page_url
         return;
     }
 
-    std::ofstream saLauncher;
+    char debugname[] = "/tmp/gnash-debug-XXXXXX.sh";
+    boost::iostreams::file_descriptor_sink fdsink = getfdsink(debugname);
+#if BOOST_VERSION >= 104400
+    if (fdsink.handle() == -1) {
+        gnash::log_error("Failed to create sink: %s", debugname);
+        return;
+    }
+#endif
+    boost::iostreams::stream<boost::iostreams::file_descriptor_sink>
+        saLauncher (fdsink);
 
-    std::stringstream ss;
-    static int debugno = 0;
-    debugno = (debugno + 1) % 10;
-    ss << "/tmp/gnash-debug-" << debugno << ".sh";
-    saLauncher.open(ss.str().c_str(), std::ios::out | std::ios::trunc);
-
     if (!saLauncher) {
-        gnash::log_error("Failed to open new file for standalone launcher: " + ss.str());
+        gnash::log_error("Failed to open new file for standalone launcher: %s", debugname);
         return;
     }
 
     saLauncher << "#!/bin/sh" << std::endl
                << "export GNASH_COOKIES_IN="
-               << "/tmp/gnash-cookies." << getpid() << std::endl
+               << std::getenv("GNASH_COOKIES_IN") << std::endl
                << getGnashExecutable() << " ";
 
     if (!page_url.empty()) {
@@ -992,6 +1029,7 @@ create_standalone_launcher(const std::string& page_url
                << std::endl;
 
     saLauncher.close();
+    fdsink.close();
 #endif
 }
 
@@ -1097,12 +1135,17 @@ nsPluginInstance::setupCookies(const std::string& page
     }
 
     gnash::log_debug("The Cookie for %s is %s", url, ncookie);
-    std::ofstream cookiefile;
-    std::stringstream ss;
-    ss << "/tmp/gnash-cookies." << getpid();
+    char cookiename[] = "/tmp/gnash-cookies.XXXXXX";
+    boost::iostreams::file_descriptor_sink fdsink = getfdsink(cookiename);
+#if BOOST_VERSION >= 104400
+    if (fdsink.handle() == -1) {
+        gnash::log_error("Failed to create sink: %s", cookiename);
+        return;
+    }
+#endif
+    boost::iostreams::stream<boost::iostreams::file_descriptor_sink>
+        cookiefile (fdsink);
 
-    cookiefile.open(ss.str().c_str(), std::ios::out | std::ios::trunc);
-
     // Firefox provides cookies in the following format:
     //
     // cookie1=value1;cookie2=value2;cookie3=value3
@@ -1121,8 +1164,9 @@ nsPluginInstance::setupCookies(const std::string& page
     }
  
     cookiefile.close();
+    fdsink.close();
   
-    if (setenv("GNASH_COOKIES_IN", ss.str().c_str(), 1) < 0) {
+    if (setenv("GNASH_COOKIES_IN", cookiename, 1) < 0) {
         gnash::log_error(
             "Couldn't set environment variable GNASH_COOKIES_IN to %s",
             ncookie);
