Bug 418150 - Fix CVE-2007-3670 on SeaMonkey trunk (URI handler injection), r=Neil, a2.0a1=KaiRo
authorFrank Wein <mcsmurf@mcsmurf.de>
Fri, 19 Sep 2008 00:46:08 +0200
changeset 382 cfff34c32e617e80f194da633f56c14d7cc1fabb
parent 381 c141ff9ff184030340b5268bd60bc8f92aef94e1
child 383 b36f9c4ac581796e50040389089e25f87cba3bbf
push idunknown
push userunknown
push dateunknown
reviewersNeil
bugs418150
Bug 418150 - Fix CVE-2007-3670 on SeaMonkey trunk (URI handler injection), r=Neil, a2.0a1=KaiRo
suite/browser/nsBrowserContentHandler.js
--- a/suite/browser/nsBrowserContentHandler.js
+++ b/suite/browser/nsBrowserContentHandler.js
@@ -31,39 +31,40 @@
  * use your version of this file under the terms of the MPL, indicate your
  * decision by deleting the provisions above and replace them with the notice
  * and other provisions required by the GPL or the LGPL. If you do not delete
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
-const nsISupports            = Components.interfaces.nsISupports;
-const nsIBrowserDOMWindow    = Components.interfaces.nsIBrowserDOMWindow;
-const nsIBrowserHistory      = Components.interfaces.nsIBrowserHistory;
-const nsIChannel             = Components.interfaces.nsIChannel;
-const nsICommandLine         = Components.interfaces.nsICommandLine;
-const nsICommandLineHandler  = Components.interfaces.nsICommandLineHandler;
-const nsIComponentRegistrar  = Components.interfaces.nsIComponentRegistrar;
-const nsICategoryManager     = Components.interfaces.nsICategoryManager;
-const nsIContentHandler      = Components.interfaces.nsIContentHandler;
-const nsIDOMWindow           = Components.interfaces.nsIDOMWindow;
-const nsIFactory             = Components.interfaces.nsIFactory;
-const nsIFileURL             = Components.interfaces.nsIFileURL;
-const nsIHttpProtocolHandler = Components.interfaces.nsIHttpProtocolHandler;
-const nsINetUtil             = Components.interfaces.nsINetUtil;
-const nsIIOService           = Components.interfaces.nsIIOService;
-const nsIPrefService         = Components.interfaces.nsIPrefService;
-const nsIPrefBranch          = Components.interfaces.nsIPrefBranch;
-const nsIPrefLocalizedString = Components.interfaces.nsIPrefLocalizedString;
-const nsISupportsString      = Components.interfaces.nsISupportsString;
-const nsIURIFixup            = Components.interfaces.nsIURIFixup;
-const nsIWindowMediator      = Components.interfaces.nsIWindowMediator;
-const nsIWindowWatcher       = Components.interfaces.nsIWindowWatcher;
-const nsIWebNavigationInfo   = Components.interfaces.nsIWebNavigationInfo;
+const nsISupports             = Components.interfaces.nsISupports;
+const nsIBrowserDOMWindow     = Components.interfaces.nsIBrowserDOMWindow;
+const nsIBrowserHistory       = Components.interfaces.nsIBrowserHistory;
+const nsIChannel              = Components.interfaces.nsIChannel;
+const nsICommandLine          = Components.interfaces.nsICommandLine;
+const nsICommandLineHandler   = Components.interfaces.nsICommandLineHandler;
+const nsICommandLineValidator = Components.interfaces.nsICommandLineValidator;
+const nsIComponentRegistrar   = Components.interfaces.nsIComponentRegistrar;
+const nsICategoryManager      = Components.interfaces.nsICategoryManager;
+const nsIContentHandler       = Components.interfaces.nsIContentHandler;
+const nsIDOMWindow            = Components.interfaces.nsIDOMWindow;
+const nsIFactory              = Components.interfaces.nsIFactory;
+const nsIFileURL              = Components.interfaces.nsIFileURL;
+const nsIHttpProtocolHandler  = Components.interfaces.nsIHttpProtocolHandler;
+const nsINetUtil              = Components.interfaces.nsINetUtil;
+const nsIIOService            = Components.interfaces.nsIIOService;
+const nsIPrefService          = Components.interfaces.nsIPrefService;
+const nsIPrefBranch           = Components.interfaces.nsIPrefBranch;
+const nsIPrefLocalizedString  = Components.interfaces.nsIPrefLocalizedString;
+const nsISupportsString       = Components.interfaces.nsISupportsString;
+const nsIURIFixup             = Components.interfaces.nsIURIFixup;
+const nsIWindowMediator       = Components.interfaces.nsIWindowMediator;
+const nsIWindowWatcher        = Components.interfaces.nsIWindowWatcher;
+const nsIWebNavigationInfo    = Components.interfaces.nsIWebNavigationInfo;
 
 const NS_BINDING_ABORTED = 0x804b0002;
 const NS_ERROR_WONT_HANDLE_CONTENT = 0x805d0001;
 
 const URI_INHERITS_SECURITY_CONTEXT = nsIHttpProtocolHandler
                                         .URI_INHERITS_SECURITY_CONTEXT;
 
 const NS_GENERAL_STARTUP_PREFIX = "@mozilla.org/commandlinehandler/general-startup;1?type=";
@@ -232,16 +233,17 @@ var nsBrowserContentHandler = {
     return this;
   },
 
   /* nsISupports */
   QueryInterface: function QueryInterface(iid) {
     if (iid.equals(nsISupports) ||
         iid.equals(nsICommandLineHandler) ||
         iid.equals(nsICommandLine) ||
+        iid.equals(nsICommandLineValidator) ||
         iid.equals(nsIContentHandler) ||
         iid.equals(nsIFactory))
       return this;
 
     throw Components.results.NS_ERROR_NO_INTERFACE;
   },
 
   /* nsICommandLineHandler */
@@ -427,16 +429,40 @@ var nsBrowserContentHandler = {
       if (!cmdLine.preventDefault) {
         openWindow(null, getBrowserURL(), features, homePage);
         cmdLine.preventDefault = true;
       }
     }
 
   },
 
+  /* nsICommandLineValidator */
+  validate: function validate(cmdLine) {
+    var osintFlagIdx = cmdLine.findFlag("osint", false);
+
+    // If the osint flag is not present and we are not called by DDE then we're safe
+    if (cmdLine.state != nsICommandLine.STATE_REMOTE_EXPLICIT &&
+        cmdLine.findFlag("osint", false) == -1)
+    return;
+
+    // Other handlers may use osint so only handle the osint flag if a
+    // flag is also present and the command line is valid.
+    ["url", "news", "compose"].forEach(function(value) {
+      var flagIdx = cmdLine.findFlag(value, false);
+
+      if (flagIdx > -1) {
+        var testExpr = new RegExp("seamonkey" + value + ":");
+        if (cmdLine.length != flagIdx + 2 ||
+            testExpr.test(cmdLine.getArgument(flagIdx + 1)))
+          throw Components.results.NS_ERROR_ABORT;
+        cmdLine.handleFlag("osint", false);
+      }
+    });
+  },
+
   helpInfo: "  -browser <url>       Open a browser window.\n" +
             "  -url <url>           Open the specified url.\n" +
             "  -chrome <url>        Open the specified chrome.\n",
 
   /* nsICommandLine */
   length: 1,
 
   getArgument: function getArgument(index) {
@@ -580,27 +606,32 @@ var Module = {
     registerType("image/x-xbitmap");
     registerType("application/http-index-format");
 
     var catMan = Components.classes["@mozilla.org/categorymanager;1"]
                            .getService(nsICategoryManager);
 
     catMan.addCategoryEntry("command-line-handler", "x-default",
                             BROWSER_CONTRACTID, true, true);
+    catMan.addCategoryEntry("command-line-validator",
+                            "b-default",
+                            BROWSER_CONTRACTID, true, true);
   },
     
   unregisterSelf: function unregisterSelf(compMgr, location, type) {
     var compReg = compMgr.QueryInterface(nsIComponentRegistrar);
     compReg.unregisterFactoryLocation(BROWSER_CID, location);
 
     var catMan = Components.classes["@mozilla.org/categorymanager;1"]
                            .getService(nsICategoryManager);
 
     catMan.deleteCategoryEntry("command-line-handler",
                                "x-default", true);
+    catMan.deleteCategoryEntry("command-line-validator",
+                               "b-default", true);
   },
 
   canUnload: function canUnload(compMgr) {
     return true;
   }
 };
 
 // NSGetModule: Return the nsIModule object.