[tor-commits] [tor-browser/tor-browser-91.5.0esr-11.5-1] fixup! Bug 40597: Implement TorSettings module

gk at torproject.org gk at torproject.org
Mon Jan 17 15:48:21 UTC 2022


commit 58466dd7347595752663d96bdc6e4f2bdcebbe5f
Author: Richard Pospesel <richard at torproject.org>
Date:   Wed Nov 10 16:03:45 2021 +0100

    fixup! Bug 40597: Implement TorSettings module
    
    resolves tor-browser#40598
---
 browser/modules/TorSettings.jsm | 243 ++++++++++------------------------------
 1 file changed, 61 insertions(+), 182 deletions(-)

diff --git a/browser/modules/TorSettings.jsm b/browser/modules/TorSettings.jsm
index 6d2a6c4a07cf..1b5b564e1e62 100644
--- a/browser/modules/TorSettings.jsm
+++ b/browser/modules/TorSettings.jsm
@@ -303,214 +303,49 @@ const TorSettings = (() => {
             return settings;
         },
 
-        /* try and load our settings, and register observers */
+        /* load or init our settings, and register observers */
         init: function() {
             if (TorProtocolService.ownsTorDaemon) {
                 // if the settings branch exists, load settings from prefs
                 if (Services.prefs.getBoolPref(TorSettingsPrefs.enabled, false)) {
                     this.loadFromPrefs();
-                    Services.obs.notifyObservers(null, TorSettingsTopics.Ready);
+                } else {
+                    // otherwise load defaults
+                    this._settings = this.defaultSettings();
                 }
                 Services.obs.addObserver(this, BrowserTopics.ProfileAfterChange);
                 Services.obs.addObserver(this, TorTopics.ProcessIsReady);
             }
         },
 
-        /* wait for relevant life-cycle events to load and/or apply saved settings */
+        /* wait for relevant life-cycle events to apply saved settings */
         observe: async function(subject, topic, data) {
-            console.log(`TorSettings: observed ${topic}`);
+            console.log(`TorSettings: Observed ${topic}`);
 
-            // once the process is ready, we need to apply our settings
+            // once the tor daemon is ready, we need to apply our settings
             let handleProcessReady = async () => {
-                Services.obs.removeObserver(this, TorTopics.ProcessIsReady);
-                if (this._settings == null) {
-                    // load settings from tor if our load in init() failed and save them to prefs
-                    await this.loadLegacy();
-                    this.saveToPrefs();
-                } else {
-                    // push down settings to tor
-                    await this.applySettings();
-                }
+                // push down settings to tor
+                await this.applySettings();
+                console.log("TorSettings: Ready");
                 Services.obs.notifyObservers(null, TorSettingsTopics.Ready);
             };
 
             switch (topic) {
                 case BrowserTopics.ProfileAfterChange: {
+                    Services.obs.removeObserver(this, BrowserTopics.ProfileAfterChange);
                     if (TorProtocolService.torProcessStatus == TorProcessStatus.Running) {
                         await handleProcessReady();
                     }
                 }
                 break;
                 case TorTopics.ProcessIsReady: {
+                    Services.obs.removeObserver(this, TorTopics.ProcessIsReady);
                     await handleProcessReady();
                 }
                 break;
             }
         },
 
-        // load our settings from old locations (misc prefs and from tor daemon)
-        // TODO: remove this after some time has elapsed to ensure users have migrated to pref settings
-        loadLegacy: async function() {
-            console.log("TorSettings: loadLegacy()");
-
-            let settings = this.defaultSettings();
-
-            /* Quickstart */
-            settings.quickstart.enabled = Services.prefs.getBoolPref(TorLauncherPrefs.quickstart, false);
-
-            /* Bridges
-
-            So the way tor-launcher determines the origin of the configured bridges is a bit
-            weird and depends on inferring our scenario based on some firefox prefs and the
-            relationship between the saved list of bridges in about:config vs the list saved in torrc
-
-            first off, if "extensions.torlauncher.default_bridge_type" is set to one of our
-            builtin default types (obfs4, meek-azure, snowflake, etc) then we provide the
-            bridges in "extensions.torlauncher.default_bridge.*" (filtered by our default_bridge_type)
-
-            next, we compare the list of bridges saved in torrc to the bridges stored in the
-            "extensions.torlauncher.bridgedb_bridge."" branch. If they match *exactly* then we assume
-            the bridges were retrieved from BridgeDB and use those. If the torrc list is empty then we know
-            we have no bridge settings
-
-            finally, if none of the previous conditions are not met, it is assumed the bridges stored in
-            torrc are user-provided
-            */
-
-            let builtinType = Services.prefs.getCharPref(TorLauncherPrefs.default_bridge_type, null);
-
-            // check if source is built-in
-            if (builtinType) {
-                let builtinBridgeStrings = getBuiltinBridgeStrings(builtinType);
-                if (builtinBridgeStrings.length > 0) {
-                    settings.bridges.enabled = true;
-                    settings.bridges.source = TorBridgeSource.BuiltIn;
-                    settings.bridges.builtin_type = builtinType;
-                    settings.bridges.bridge_strings = builtinBridgeStrings;
-                }
-            } else  {
-                // get our currently configured bridges from tor
-                let torrcBridgeStrings = await (async () => {
-                    let bridgeList = await TorProtocolService.readStringArraySetting(TorConfigKeys.bridgeList);
-                    let retval = [];
-                    for (const line of bridgeList) {
-                      let trimmedLine = line.trim();
-                      if (trimmedLine) {
-                        retval.push(trimmedLine);
-                      }
-                    }
-                    return retval;
-                })();
-
-                // torrc has bridges configured
-                if (torrcBridgeStrings.length > 0) {
-                    // compare tor's bridges to our saved bridgedb bridges
-                    let bridgedbBBridgeStrings = (() => {
-                        let bridgeBranch = Services.prefs.getBranch(TorLauncherPrefs.bridgedb_bridge);
-                        let bridgeBranchPrefs = bridgeBranch.getChildList("");
-                        // the child prefs do not come in any particular order so sort the keys
-                        // so the values can be compared to what we get out off torrc
-                        bridgeBranchPrefs.sort();
-
-                        // just assume all of the prefs under the parent point to valid bridge string
-                        let retval = bridgeBranchPrefs.map(key =>
-                          bridgeBranch.getCharPref(key).trim()
-                        );
-                        return retval;
-                    })();
-
-                    let arraysEqual = (left, right) => {
-                        if (left.length != right.length) {
-                            return false;
-                        }
-                        const length = left.length;
-                        for (let i = 0; i < length; ++i) {
-                            if (left[i] != right[i]) {
-                                return false;
-                            }
-                        }
-                        return true;
-                    };
-
-                    if (arraysEqual(torrcBridgeStrings, bridgedbBBridgeStrings)) {
-                        settings.bridges.enabled = true;
-                        settings.bridges.source = TorBridgeSource.BridgeDB;
-                        settings.bridges.builtin_type = null;
-                        settings.bridges.bridge_strings = torrcBridgeStrings;
-                    } else {
-                        settings.bridges.enabled = true;
-                        settings.bridges.source = TorBridgeSource.UserProvided;
-                        settings.bridges.builtin_type = null;
-                        settings.bridges.bridge_strings = torrcBridgeStrings;
-                    }
-                } else {
-                    // tor has no bridge strings saved, so bridges not in use
-                    settings.bridges.enabled = false;
-                    settings.bridges.source = TorBridgeSource.Invalid;
-                    settings.bridges.builtin_type = null;
-                    settings.bridges.bridge_strings = [];
-                }
-            }
-
-            /* Proxy */
-
-            let proxyString = null;
-            if (proxyString = await TorProtocolService.readStringSetting(TorConfigKeys.socks4Proxy)) {
-                let [address, port] = parseAddrPort(proxyString);
-
-                settings.proxy.enabled = true;
-                settings.proxy.type = TorProxyType.Socks4;
-                settings.proxy.address = address;
-                settings.proxy.port = port;
-                settings.proxy.username = null;
-                settings.proxy.password = null;
-            } else if (proxyString = await TorProtocolService.readStringSetting(TorConfigKeys.socks5Proxy)) {
-                let [address, port] = parseAddrPort(proxyString);
-                let username = await TorProtocolService.readStringSetting(TorConfigKeys.socks5ProxyUsername);
-                let password = await TorProtocolService.readStringSetting(TorConfigKeys.socks5ProxyPassword);
-
-                settings.proxy.enabled = true;
-                settings.proxy.type = TorProxyType.Socks5;
-                settings.proxy.address = address;
-                settings.proxy.port = port;
-                settings.proxy.username = username;
-                settings.proxy.password = password;
-            } else if (proxyString = await TorProtocolService.readStringSetting(TorConfigKeys.httpsProxy)) {
-                let [address, port] = parseAddrPort(proxyString);
-                let authenticator = await TorProtocolService.readStringSetting(TorConfigKeys.httpsProxyAuthenticator);
-                let [username, password] = parseUsernamePassword(authenticator);
-
-                settings.proxy.enabled = true;
-                settings.proxy.type = TorProxyType.HTTPS;
-                settings.proxy.address = address;
-                settings.proxy.port = port;
-                settings.proxy.username = username;
-                settings.proxy.password = password;
-            } else {
-                settings.proxy.enabled = false;
-                settings.proxy.type = TorProxyType.Invalid;
-                settings.proxy.address = null;
-                settings.proxy.port = 0;
-                settings.proxy.username = null;
-                settings.proxy.password = null;
-            }
-
-            /* Firewall */
-            let firewallString = await TorProtocolService.readStringSetting(TorConfigKeys.reachableAddresses);
-            if (firewallString) {
-                let allowedPorts = parseAddrPortList(firewallString);
-                settings.firewall.enabled = allowedPorts.length > 0;
-                settings.firewall.allowed_ports = allowedPorts;
-            } else {
-                settings.firewall.enabled = false;
-                settings.firewall.allowed_ports = [];
-            }
-
-            this._settings = settings;
-
-            return this;
-        },
-
         // load our settings from prefs
         loadFromPrefs: function() {
             console.log("TorSettings: loadFromPrefs()");
@@ -704,16 +539,60 @@ const TorSettings = (() => {
             return this;
         },
 
-        /* Getters and Setters */
+        // set all of our settings at once from a settings object
+        setSettings: function(settings) {
+            console.log("TorSettings: setSettings()");
+            let backup = this.getSettings();
+
+            try {
+                if (settings.bridges.enabled) {
+                    this._settings.bridges.enabled = true;
+                    this._settings.bridges.source = settings.bridges.source;
+                    switch(settings.bridges.source) {
+                        case TorBridgeSource.BridgeDB:
+                        case TorBridgeSource.UserProvided:
+                            this._settings.bridges.bridge_strings = settings.bridges.bridge_strings
+                            break;
+                        case TorBridgeSource.BuiltIn: {
+                            this._settings.bridges.builtin_type = settings.bridges.builtin_type;
+                            let bridgeStrings =  getBuiltinBridgeStrings(settings.bridges.builtin_type);
+                            if (bridgeStrings.length > 0) {
+                                this._settings.bridges.bridge_strings = bridgeStrings;
+                            } else {
+                                throw new Error(`No available builtin bridges of type ${settings.bridges.builtin_type}`);
+                            }
+                            break;
+                        }
+                        default:
+                            throw new Error(`Bridge source '${settings.source}' is not a valid source`);
+                    }
+                } else {
+                    this.bridges.enabled = false;
+                }
+
+                // TODO: proxy and firewall
+            } catch(ex) {
+                this._settings = backup;
+                console.log(`TorSettings: setSettings failed => ${ex.message}`);
+            }
+
+            console.log("TorSettings: setSettings result");
+            console.log(this._settings);
+        },
+
+        // get a copy of all our settings
+        getSettings: function() {
+            console.log("TorSettings: getSettings()");
+            // TODO: replace with structuredClone someday (post esr94): https://developer.mozilla.org/en-US/docs/Web/API/structuredClone
+            return JSON.parse(JSON.stringify(this._settings));
+        },
 
+        /* Getters and Setters */
 
         // Quickstart
         get quickstart() {
             return {
-                // Avoid a race-condition on first-start where this property
-                // may be accessed before `self._settings` is initialized.
-                // This work-around can be removed when #40598 is resolved.
-                get enabled() { return (self._settings ? self._settings.quickstart.enabled : false); },
+                get enabled() { return self._settings.quickstart.enabled; },
                 set enabled(val) {
                     if (val != self._settings.quickstart.enabled)
                     {





More information about the tor-commits mailing list