Loading toolkit/components/tor-launcher/TorControlPort.sys.mjs +18 −3 Original line number Diff line number Diff line /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ import { ConsoleAPI } from "resource://gre/modules/Console.sys.mjs"; import { TorParsers } from "resource://gre/modules/TorParsers.sys.mjs"; const logger = new ConsoleAPI({ maxLogLevel: "warn", maxLogLevelPref: "browser.tor_provider.cp_log_level", prefix: "TorControlPort", }); /** * A wrapper around XPCOM sockets and buffers to handle streams in a standard * async JS fashion. Loading Loading @@ -481,14 +493,15 @@ export class TorController { // E.g., if a notification handler fails. Without this internal // try/catch we risk of closing the connection while not actually // needed. console.error("Caught an exception while handling a message", err); logger.error("Caught an exception while handling a message", err); } } } catch (err) { logger.debug("Caught an exception, closing the control port", err); try { this.#close(err); } catch (ec) { console.error( logger.error( "Caught another error while closing the control socket.", ec ); Loading Loading @@ -559,6 +572,7 @@ export class TorController { * rejection reason to the commands that are still queued. */ #close(reason) { logger.info("Closing the control port", reason); const error = new Error( "The control socket has been closed" + (reason ? `: ${reason.message}` : "") Loading Loading @@ -974,8 +988,9 @@ export class TorController { let status; try { status = this.#parseBootstrapStatus(data.groups.data); } catch { } catch (e) { // Probably, a non bootstrap client status logger.debug(`Failed to parse STATUS_CLIENT: ${data.groups.data}`); break; } this.#eventHandler.onBootstrapStatus(status); Loading toolkit/components/tor-launcher/TorProvider.sys.mjs +19 −8 Original line number Diff line number Diff line Loading @@ -522,6 +522,18 @@ export class TorProvider { if (Services.env.exists("TOR_CONTROL_PASSWD")) { const password = Services.env.get("TOR_CONTROL_PASSWD"); // As per 3.5 of control-spec.txt, AUTHENTICATE can use either a quoted // string, or a sequence of hex characters. // However, the password is hashed byte by byte, so we need to convert the // string to its character codes, or the hex digits to actual bytes. // Notice that Tor requires at least one hex character, without an upper // limit, but it does not explicitly tell how to pad an odd number of hex // characters, so we require the user to hand an even number of hex // digits. // We also want to enforce the authentication if we start the daemon. // So, if a password is not valid (not a hex sequence and not a quoted // string), or if it is empty (including the quoted empty string), we // force a random password. if ( password.length >= 2 && password[0] === '"' && Loading @@ -529,15 +541,10 @@ export class TorProvider { ) { const encoder = new TextEncoder(); settings.password = encoder.encode(TorParsers.unescapeString(password)); } else if (password.length && (password.length % 2) === 0) { } else if (/^([0-9a-fA-F]{2})+$/.test(password)) { settings.password = []; for (let i = 0; i < password.length; i += 2) { const byte = parseInt(password.substring(i, i + 2), 16); if (isNaN(byte)) { settings.password = undefined; break; } settings.password.push(byte); settings.password.push(parseInt(password.substring(i, i + 2), 16)); } } if (password && !settings.password?.length) { Loading @@ -554,7 +561,11 @@ export class TorProvider { settings.cookieFilePath = cookiePath; } } if (!settings.password?.length && !settings.cookieFilePath) { if ( TorLauncherUtil.shouldStartAndOwnTor && !settings.password?.length && !settings.cookieFilePath ) { settings.password = this.#generateRandomPassword(); } this.#controlPortSettings = settings; Loading Loading
toolkit/components/tor-launcher/TorControlPort.sys.mjs +18 −3 Original line number Diff line number Diff line /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ import { ConsoleAPI } from "resource://gre/modules/Console.sys.mjs"; import { TorParsers } from "resource://gre/modules/TorParsers.sys.mjs"; const logger = new ConsoleAPI({ maxLogLevel: "warn", maxLogLevelPref: "browser.tor_provider.cp_log_level", prefix: "TorControlPort", }); /** * A wrapper around XPCOM sockets and buffers to handle streams in a standard * async JS fashion. Loading Loading @@ -481,14 +493,15 @@ export class TorController { // E.g., if a notification handler fails. Without this internal // try/catch we risk of closing the connection while not actually // needed. console.error("Caught an exception while handling a message", err); logger.error("Caught an exception while handling a message", err); } } } catch (err) { logger.debug("Caught an exception, closing the control port", err); try { this.#close(err); } catch (ec) { console.error( logger.error( "Caught another error while closing the control socket.", ec ); Loading Loading @@ -559,6 +572,7 @@ export class TorController { * rejection reason to the commands that are still queued. */ #close(reason) { logger.info("Closing the control port", reason); const error = new Error( "The control socket has been closed" + (reason ? `: ${reason.message}` : "") Loading Loading @@ -974,8 +988,9 @@ export class TorController { let status; try { status = this.#parseBootstrapStatus(data.groups.data); } catch { } catch (e) { // Probably, a non bootstrap client status logger.debug(`Failed to parse STATUS_CLIENT: ${data.groups.data}`); break; } this.#eventHandler.onBootstrapStatus(status); Loading
toolkit/components/tor-launcher/TorProvider.sys.mjs +19 −8 Original line number Diff line number Diff line Loading @@ -522,6 +522,18 @@ export class TorProvider { if (Services.env.exists("TOR_CONTROL_PASSWD")) { const password = Services.env.get("TOR_CONTROL_PASSWD"); // As per 3.5 of control-spec.txt, AUTHENTICATE can use either a quoted // string, or a sequence of hex characters. // However, the password is hashed byte by byte, so we need to convert the // string to its character codes, or the hex digits to actual bytes. // Notice that Tor requires at least one hex character, without an upper // limit, but it does not explicitly tell how to pad an odd number of hex // characters, so we require the user to hand an even number of hex // digits. // We also want to enforce the authentication if we start the daemon. // So, if a password is not valid (not a hex sequence and not a quoted // string), or if it is empty (including the quoted empty string), we // force a random password. if ( password.length >= 2 && password[0] === '"' && Loading @@ -529,15 +541,10 @@ export class TorProvider { ) { const encoder = new TextEncoder(); settings.password = encoder.encode(TorParsers.unescapeString(password)); } else if (password.length && (password.length % 2) === 0) { } else if (/^([0-9a-fA-F]{2})+$/.test(password)) { settings.password = []; for (let i = 0; i < password.length; i += 2) { const byte = parseInt(password.substring(i, i + 2), 16); if (isNaN(byte)) { settings.password = undefined; break; } settings.password.push(byte); settings.password.push(parseInt(password.substring(i, i + 2), 16)); } } if (password && !settings.password?.length) { Loading @@ -554,7 +561,11 @@ export class TorProvider { settings.cookieFilePath = cookiePath; } } if (!settings.password?.length && !settings.cookieFilePath) { if ( TorLauncherUtil.shouldStartAndOwnTor && !settings.password?.length && !settings.cookieFilePath ) { settings.password = this.#generateRandomPassword(); } this.#controlPortSettings = settings; Loading