commit 286900688251c4e89662d34a42e08ff32de14b29 Author: Richard Pospesel richard@torproject.org Date: Thu Jan 6 18:27:51 2022 +0100
fixup! Bug 40645: Migrate Moat APIs to Moat.jsm module --- browser/modules/Moat.jsm | 133 ++++++++++++++++++++++++++++++++++------------- 1 file changed, 98 insertions(+), 35 deletions(-)
diff --git a/browser/modules/Moat.jsm b/browser/modules/Moat.jsm index b26eb32bdfb3..d02075e4412f 100644 --- a/browser/modules/Moat.jsm +++ b/browser/modules/Moat.jsm @@ -16,7 +16,7 @@ const { TorProtocolService } = ChromeUtils.import( "resource:///modules/TorProtocolService.jsm" );
-const { TorSettings } = ChromeUtils.import( +const { TorSettings, TorBridgeSource, TorProxyType } = ChromeUtils.import( "resource:///modules/TorSettings.jsm" );
@@ -489,11 +489,10 @@ class MoatRPC { await ch.asyncOpen(listener, ch);
// wait for response - const response = await listener.response(); + const responseJSON = await listener.response();
// parse that JSON - const retval = JSON.parse(response); - return retval; + return JSON.parse(responseJSON); }
// @@ -527,16 +526,16 @@ class MoatRPC { }, ], }; - const retval = await this._makeRequest("fetch", args); - if ("errors" in retval) { - const code = retval.errors[0].code; - const detail = retval.errors[0].detail; + const response = await this._makeRequest("fetch", args); + if ("errors" in response) { + const code = response.errors[0].code; + const detail = response.errors[0].detail; throw new Error(`MoatRPC: ${detail} (${code})`); }
- const transport = retval.data[0].transport; - const image = retval.data[0].image; - const challenge = retval.data[0].challenge; + const transport = response.data[0].transport; + const image = response.data[0].image; + const challenge = response.data[0].challenge;
return { transport, image, challenge }; } @@ -568,10 +567,10 @@ class MoatRPC { }, ], }; - const retval = await this._makeRequest("check", args); - if ("errors" in retval) { - const code = retval.errors[0].code; - const detail = retval.errors[0].detail; + const response = await this._makeRequest("check", args); + if ("errors" in response) { + const code = response.errors[0].code; + const detail = response.errors[0].detail; if (code == 419 && detail === "The CAPTCHA solution was incorrect.") { return {}; } @@ -579,12 +578,74 @@ class MoatRPC { throw new Error(`MoatRPC: ${detail} (${code})`); }
- const bridges = retval.data[0].bridges; - const qrcodeImg = qrcode ? retval.data[0].qrcode : null; + const bridges = response.data[0].bridges; + const qrcodeImg = qrcode ? response.data[0].qrcode : null;
return { bridges, qrcode: qrcodeImg }; }
+ // Convert received settings object to format used by TorSettings module + // In the event of error, just return null + _fixupSettings(settings) { + try { + let retval = TorSettings.defaultSettings() + if ("bridges" in settings) { + retval.bridges.enabled = true; + switch(settings.bridges.source) { + case "builtin": + retval.bridges.source = TorBridgeSource.BuiltIn; + retval.bridges.builtin_type = settings.bridges.type; + // Tor Browser will periodically update the built-in bridge strings list using the + // circumvention_builtin() function, so we can ignore the bridge strings we have received here; + // BridgeDB only returns a subset of the available built-in bridges through the circumvention_settings() + // function which is fine for our 3rd parties, but we're better off ignoring them in Tor Browser, otherwise + // we get in a weird situation of needing to update our built-in bridges in a piece-meal fashion which + // seems over-complicated/error-prone + break; + case "bridgedb": + retval.bridges.source = TorBridgeSource.BridgeDB; + if (settings.bridges.bridge_strings) { + retval.bridges.bridge_strings = settings.bridges.bridge_strings; + } else { + throw new Error("MoatRPC::_fixupSettings(): Received no bridge-strings for BridgeDB bridge source"); + } + break; + default: + throw new Error(`MoatRPC::_fixupSettings(): Unexpected bridge source '${settings.bridges.source}'`); + } + } + if ("proxy" in settings) { + // TODO: populate proxy settings + } + if ("firewall" in settings) { + // TODO: populate firewall settings + } + return retval; + } catch(ex) { + console.log(ex.message); + return null; + } + } + + // Converts a list of settings objects received from BridgeDB to a list of settings objects + // understood by the TorSettings module + // In the event of error, returns and empty list + _fixupSettingsList(settingsList) { + try { + let retval = []; + for (let settings of settingsList) { + settings = this._fixupSettings(settings); + if (settings != null) { + retval.push(settings); + } + } + return retval; + } catch (ex) { + console.log(ex.message); + return []; + } + } + // Request tor settings for the user optionally based on their location (derived // from their IP), takes the following parameters: // - transports: optional, an array of transports available to the client; if empty (or not @@ -596,16 +657,16 @@ class MoatRPC { // object on the TorSettings module. // - If the server cannot determine the user's country (and no country code is provided), // then null is returned - // - If the country has no associated settings, an empty object is returned + // - If the country has no associated settings, an empty array is returned async circumvention_settings(transports, country) { const args = { transports: transports ? transports : [], country: country, }; - const retval = await this._makeRequest("circumvention/settings", args); - if ("errors" in retval) { - const code = retval.errors[0].code; - const detail = retval.errors[0].detail; + const response = await this._makeRequest("circumvention/settings", args); + if ("errors" in response) { + const code = response.errors[0].code; + const detail = response.errors[0].detail; if (code == 406) { console.log("MoatRPC::circumvention_settings(): Cannot automatically determine user's country-code"); // cannot determine user's country @@ -613,28 +674,30 @@ class MoatRPC { }
throw new Error(`MoatRPC: ${detail} (${code})`); + } else if ("settings" in response) { + return this._fixupSettingsList(response.settings); }
- return retval; + return []; }
// Request a copy of the censorship circumvention map (as if cirumvention_settings were // queried for all country codes) // - // returns a map whose key is an ISO 3166-1 alpha-2 country code and those + // returns a map whose key is an ISO 3166-1 alpha-2 country code and whose // values are arrays of settings objects async circumvention_map() { const args = { }; - const retval = await this._makeRequest("circumvention/map", args); - if ("errors" in retval) { - const code = retval.errors[0].code; - const detail = retval.errors[0].detail; + const response = await this._makeRequest("circumvention/map", args); + if ("errors" in response) { + const code = response.errors[0].code; + const detail = response.errors[0].detail; throw new Error(`MoatRPC: ${detail} (${code})`); }
let map = new Map(); - for (const [country, config] of Object.entries(retval)) { - map.set(country, config); + for (const [country, config] of Object.entries(response)) { + map.set(country, this._fixupSettingsList(config.settings)); }
return map; @@ -650,15 +713,15 @@ class MoatRPC { const args = { transports: transports ? transports : [], }; - const retval = await this._makeRequest("circumvention/builtin", args); - if ("errors" in retval) { - const code = retval.errors[0].code; - const detail = retval.errors[0].detail; + const response = await this._makeRequest("circumvention/builtin", args); + if ("errors" in response) { + const code = response.errors[0].code; + const detail = response.errors[0].detail; throw new Error(`MoatRPC: ${detail} (${code})`); }
let map = new Map(); - for (const [transport, bridge_strings] of Object.entries(retval)) { + for (const [transport, bridge_strings] of Object.entries(response)) { map.set(transport, bridge_strings); }