Pier Angelo Vendrame pushed to branch tor-browser-102.5.0esr-12.5-1 at The Tor Project / Applications / Tor Browser
Commits: d84fac57 by hackademix at 2022-12-17T13:28:36+00:00 fixup! Bug 10760: Integrate TorButton to TorBrowser core
- - - - - a1ee91a6 by hackademix at 2022-12-17T13:28:36+00:00 Bug 8324: Prevent DNS proxy bypasses caused by Drag&Drop
- - - - -
5 changed files:
- browser/components/places/PlacesUIUtils.jsm - browser/components/places/content/controller.js - dom/base/ContentAreaDropListener.jsm - toolkit/components/places/PlacesUtils.jsm - toolkit/torbutton/components/dragDropFilter.js
Changes:
===================================== browser/components/places/PlacesUIUtils.jsm ===================================== @@ -1903,7 +1903,11 @@ XPCOMUtils.defineLazyGetter(PlacesUIUtils, "URI_FLAVORS", () => { return [PlacesUtils.TYPE_X_MOZ_URL, TAB_DROP_TYPE, PlacesUtils.TYPE_UNICODE]; }); XPCOMUtils.defineLazyGetter(PlacesUIUtils, "SUPPORTED_FLAVORS", () => { - return [...PlacesUIUtils.PLACES_FLAVORS, ...PlacesUIUtils.URI_FLAVORS]; + return [ + ...PlacesUIUtils.PLACES_FLAVORS, + ...PlacesUIUtils.URI_FLAVORS, + "application/x-torbrowser-opaque", + ]; });
XPCOMUtils.defineLazyGetter(PlacesUIUtils, "ellipsis", function() {
===================================== browser/components/places/content/controller.js ===================================== @@ -1251,6 +1251,7 @@ PlacesController.prototype = { [ PlacesUtils.TYPE_X_MOZ_PLACE, PlacesUtils.TYPE_X_MOZ_URL, + "application/x-torbrowser-opaque", PlacesUtils.TYPE_UNICODE, ].forEach(type => xferable.addDataFlavor(type));
===================================== dom/base/ContentAreaDropListener.jsm ===================================== @@ -5,6 +5,16 @@ const { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm"); const { OS } = ChromeUtils.import("resource://gre/modules/osfile.jsm");
+const { XPCOMUtils } = ChromeUtils.import( + "resource://gre/modules/XPCOMUtils.jsm" +); + +XPCOMUtils.defineLazyGetter(this, "gOpaqueDrag", () => { + return Cc["@torproject.org/torbutton-dragDropFilter;1"].getService( + Ci.nsISupports + ).wrappedJSObject.opaqueDrag; +}); + // This component is used for handling dragover and drop of urls. // // It checks to see whether a drop of a url is allowed. For instance, a url @@ -43,10 +53,15 @@ ContentAreaDropListener.prototype = { } }
- type = "text/x-moz-url"; - if (types.contains(type)) { + for (let type of ["text/x-moz-url", "application/x-torbrowser-opaque"]) { + if (!types.contains(type)) { + continue; + } data = dt.mozGetDataAt(type, i); if (data) { + if (type === "application/x-torbrowser-opaque") { + ({ type, value: data = "" } = gOpaqueDrag.get(data)); + } let lines = data.split("\n"); for (let i = 0, length = lines.length; i < length; i += 2) { this._addLink(links, lines[i], lines[i + 1], type); @@ -250,6 +265,7 @@ ContentAreaDropListener.prototype = { if ( !types.includes("application/x-moz-file") && !types.includes("text/x-moz-url") && + !types.includes("application/x-torbrowser-opaque") && !types.includes("text/uri-list") && !types.includes("text/x-moz-text-internal") && !types.includes("text/plain")
===================================== toolkit/components/places/PlacesUtils.jsm ===================================== @@ -32,6 +32,12 @@ XPCOMUtils.defineLazyGetter(this, "gCryptoHash", () => { return Cc["@mozilla.org/security/hash;1"].createInstance(Ci.nsICryptoHash); });
+XPCOMUtils.defineLazyGetter(this, "gOpaqueDrag", () => { + return Cc["@torproject.org/torbutton-dragDropFilter;1"].getService( + Ci.nsISupports + ).wrappedJSObject.opaqueDrag; +}); + // On Mac OSX, the transferable system converts "\r\n" to "\n\n", where // we really just want "\n". On other platforms, the transferable system // converts "\r\n" to "\n". @@ -1132,6 +1138,9 @@ var PlacesUtils = { unwrapNodes: function PU_unwrapNodes(blob, type) { // We split on "\n" because the transferable system converts "\r\n" to "\n" var nodes = []; + if (type === "application/x-torbrowser-opaque") { + ({ value: blob, type } = gOpaqueDrag.get(blob)); + } switch (type) { case this.TYPE_X_MOZ_PLACE: case this.TYPE_X_MOZ_PLACE_SEPARATOR:
===================================== toolkit/torbutton/components/dragDropFilter.js ===================================== @@ -13,6 +13,7 @@ const { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm"); XPCOMUtils.defineLazyModuleGetters(this, { ComponentUtils: "resource://gre/modules/ComponentUtils.jsm", }); +XPCOMUtils.defineLazyGlobalGetters(this, ["crypto"]);
// Module specific constants const kMODULE_NAME = "Torbutton Drag and Drop Handler"; @@ -28,50 +29,55 @@ const URLISH_TYPES = Object.freeze([ "application/x-moz-file-promise-url", ]);
-/* - Returns true if the text resembles a URL or even just a hostname - in a way that may prompt the O.S. or other applications to send out a - validation DNS query, if not a full request (e.g. " torproject.org", - even with the leading whitespace). -*/ -function isURLish(text) { - // Ignore leading whitespace. - text = text.trim(); - - // Without any protocol or dot in the first chunk, this is unlikely - // to be considered URLish (exception: localhost, but we don't care). - if (!/^[a-z][a-z0-9+-]*:///i.test(text)) { - // no protocol - if (!/^[^.\s/]+.[^.\s/]/.test(text)) { - // no dot - return false; +const MAIN_PROCESS = + Services.appinfo.processType === Services.appinfo.PROCESS_TYPE_DEFAULT; + +const EMPTY_PAYLOAD = {}; +const OpaqueDrag = { + listening: false, + payload: EMPTY_PAYLOAD, + store(value, type) { + let opaqueKey = crypto.randomUUID(); + this.payload = { opaqueKey, value, type }; + if (!this.listening && MAIN_PROCESS) { + Services.ppmm.addMessageListener( + "DragDropFilter:GetOpaqueDrag", + () => this.payload + ); + this.listening = true; } - // Prepare for hostname validation via relative URL building. - text = `//${text}`; - } - // Validate URL or hostname. - try { - new URL(text, "https://localhost"); - return true; - } catch (e) { - // invalid URL, bail out - } - return false; -} - -// Returns true if any chunk of text is URLish -const hasURLish = text => text.split(/[^\p{L}_.-:/%~@$-]+/u).some(isURLish); + return opaqueKey; + }, + retrieve(key) { + let { opaqueKey, value, type } = this.payload; + if (opaqueKey === key) { + return { value, type }; + } + if (!MAIN_PROCESS) { + this.payload = Services.cpmm.sendSyncMessage( + "DragDropFilter:GetOpaqueDrag" + )[0]; + if (key === this.payload.opaqueKey) { + return this.retrieve(key); + } + } + return EMPTY_PAYLOAD; + }, +};
function DragDropFilter() { this.logger = Cc["@torproject.org/torbutton-logger;1"].getService( Ci.nsISupports ).wrappedJSObject; this.logger.log(3, "Component Load 0: New DragDropFilter."); - - try { - Services.obs.addObserver(this, "on-datatransfer-available"); - } catch (e) { - this.logger.log(5, "Failed to register drag observer"); + if (MAIN_PROCESS) { + // We want to update our status in the main process only, in order to + // serve the same opaque drag payload in every process. + try { + Services.obs.addObserver(this, "on-datatransfer-available"); + } catch (e) { + this.logger.log(5, "Failed to register drag observer"); + } } }
@@ -109,23 +115,38 @@ DragDropFilter.prototype = { const types = aDataTransfer.mozTypesAt(i); for (const type of types) { this.logger.log(3, `Type is: ${type}.`); - if ( - URLISH_TYPES.includes(type) || - ((type === "text/plain" || type === "text/html") && - hasURLish(aDataTransfer.getData(type))) - ) { + if (URLISH_TYPES.includes(type)) { this.logger.log( 3, - `Removing transfer data ${aDataTransfer.getData(type)}` + `Removing transfer data ${aDataTransfer.mozGetDataAt(type, i)}` ); + const urlType = "text/x-moz-url"; + // Fallback url type, to be parsed by this browser but not externally + const INTERNAL_FALLBACK = "application/x-torbrowser-opaque"; + if (types.contains(urlType)) { + const link = aDataTransfer.mozGetDataAt(urlType, i); + const opaqueKey = OpaqueDrag.store(link, urlType); + aDataTransfer.mozSetDataAt(INTERNAL_FALLBACK, opaqueKey, i); + } for (const type of types) { - aDataTransfer.clearData(type); + if ( + type !== INTERNAL_FALLBACK && + type !== "text/x-moz-place" // don't touch bookmarks + ) { + aDataTransfer.mozClearDataAt(type, i); + } } break; } } } }, + + opaqueDrag: { + get(opaqueKey) { + return OpaqueDrag.retrieve(opaqueKey); + }, + }, };
// Assign factory to global object.
View it on GitLab: https://gitlab.torproject.org/tpo/applications/tor-browser/-/compare/fdfd2b9...