[Pkg-privacy-commits] [onionshare] 127/256: Connecting to Tor in bundled mode now creates a temporary tor data dir, starts a new tor process, and connects to it. Also, refactored Settings dialog to allow Linux to use bundled tor as well
Ulrike Uhlig
ulrike at moszumanska.debian.org
Fri May 26 12:53:26 UTC 2017
This is an automated email from the git hooks/post-receive script.
ulrike pushed a commit to branch master
in repository onionshare.
commit 169be518eb9140cfdffa611afa82eb5592cf9873
Author: Micah Lee <micah at micahflee.com>
Date: Thu Apr 13 22:22:34 2017 -0700
Connecting to Tor in bundled mode now creates a temporary tor data dir, starts a new tor process, and connects to it. Also, refactored Settings dialog to allow Linux to use bundled tor as well
---
onionshare/onion.py | 88 ++++++++++++++++++++++++++++++++-------
onionshare_gui/settings_dialog.py | 29 ++++---------
share/locale/en.json | 3 +-
share/torrc_template | 9 ++++
4 files changed, 92 insertions(+), 37 deletions(-)
diff --git a/onionshare/onion.py b/onionshare/onion.py
index ccfdd4b..1018153 100644
--- a/onionshare/onion.py
+++ b/onionshare/onion.py
@@ -21,7 +21,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
from stem.control import Controller
from stem import ProtocolError
from stem.connection import MissingPassword, UnreadableCookieFile, AuthenticationFailure
-import os, sys, tempfile, shutil, urllib, platform
+import os, sys, tempfile, shutil, urllib, platform, subprocess, time, shlex
from . import socks
from . import helpers, strings
@@ -103,6 +103,8 @@ class Onion(object):
self.stealth = stealth
self.service_id = None
+ system = platform.system()
+
# Either use settings that are passed in, or load them from disk
if settings:
self.settings = settings
@@ -110,21 +112,73 @@ class Onion(object):
self.settings = Settings()
self.settings.load()
+ # Is bundled tor supported?
+ if (system == 'Windows' or system == 'Darwin') and getattr(sys, 'onionshare_dev_mode', False):
+ bundle_tor_supported = False
+ else:
+ bundle_tor_supported = True
+
+ # Set the path of the tor binary, for bundled tor
+ if system == 'Linux':
+ self.tor_path = '/usr/bin/tor'
+ self.tor_geo_ip_file_path = '/usr/share/tor/geoip'
+ self.tor_geo_ipv6_file_path = '/usr/share/tor/geoip6'
+ elif system == 'Windows':
+ # TODO: implement
+ pass
+ elif system == 'Darwin':
+ # TODO: implement
+ pass
+
+ # The tor process
+ self.tor_p = None
+
# Try to connect to Tor
self.c = None
if self.settings.get('connection_type') == 'bundled':
- dev_mode = getattr(sys, 'onionshare_dev_mode', False)
- p = platform.system()
-
- if (p != 'Windows' and p != 'Darwin') or dev_mode:
+ if not bundle_tor_supported:
raise BundledTorNotSupported(strings._('settings_error_bundled_tor_not_supported'))
- # TODO: actually implement bundled Tor
-
- if self.settings.get('connection_type') == 'automatic':
+ # Create a torrc for this session
+ self.tor_data_directory = tempfile.TemporaryDirectory()
+ self.tor_control_socket = os.path.join(self.tor_data_directory.name, 'control_socket')
+ self.tor_cookie_auth_file = os.path.join(self.tor_data_directory.name, 'cookie')
+ self.tor_socks_port_file = os.path.join(self.tor_data_directory.name, 'socks_socket')
+ self.tor_socks_port = 'unix:{}'.format(self.tor_socks_port_file)
+ self.tor_torrc = os.path.join(self.tor_data_directory.name, 'torrc')
+ torrc_template = open(helpers.get_resource_path('torrc_template')).read()
+ torrc_template = torrc_template.replace('{{data_directory}}', self.tor_data_directory.name)
+ torrc_template = torrc_template.replace('{{control_socket}}', self.tor_control_socket)
+ torrc_template = torrc_template.replace('{{cookie_auth_file}}', self.tor_cookie_auth_file)
+ torrc_template = torrc_template.replace('{{geo_ip_file}}', self.tor_geo_ip_file_path)
+ torrc_template = torrc_template.replace('{{geo_ipv6_file}}', self.tor_geo_ipv6_file_path)
+ torrc_template = torrc_template.replace('{{socks_port}}', self.tor_socks_port)
+ open(self.tor_torrc, 'w').write(torrc_template)
+
+ # Open tor in a subprocess, wait for the controller to start
+ self.tor_proc = subprocess.Popen([self.tor_path, '-f', self.tor_torrc], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+ time.sleep(0.2)
+
+ # Connect to the controller
+ self.c = Controller.from_socket_file(path=self.tor_control_socket)
+ self.c.authenticate()
+
+ while True:
+ res = self.c.get_info("status/bootstrap-phase")
+ res_parts = shlex.split(res)
+ progress = res_parts[2].split('=')[1]
+ summary = res_parts[4].split('=')[1]
+
+ # "\033[K" clears the rest of the line
+ print("{}: {}% - {}{}".format(strings._('connecting_to_tor'), progress, summary, "\033[K"), end="\r")
+ if summary == 'Done':
+ print("")
+ break
+ time.sleep(0.2)
+
+ elif self.settings.get('connection_type') == 'automatic':
# Automatically try to guess the right way to connect to Tor Browser
- p = platform.system()
# Try connecting to control port
found_tor = False
@@ -152,7 +206,7 @@ class Onion(object):
socket_file_path = ''
if not found_tor:
try:
- if p == 'Darwin':
+ if system == 'Darwin':
socket_file_path = os.path.expanduser('~/Library/Application Support/TorBrowser-Data/Tor/control.socket')
self.c = Controller.from_socket_file(path=socket_file_path)
@@ -164,12 +218,12 @@ class Onion(object):
# guessing the socket file name next
if not found_tor:
try:
- if p == 'Linux':
+ if system == 'Linux':
socket_file_path = '/run/user/{}/Tor/control.socket'.format(os.geteuid())
- elif p == 'Darwin':
+ elif system == 'Darwin':
# TODO: figure out the unix socket path in OS X
socket_file_path = '/run/user/{}/Tor/control.socket'.format(os.geteuid())
- elif p == 'Windows':
+ elif system == 'Windows':
# Windows doesn't support unix sockets
raise TorErrorAutomatic(strings._('settings_error_automatic'))
@@ -276,12 +330,16 @@ class Onion(object):
def cleanup(self):
"""
- Stop onion services that were created earlier.
+ Stop onion services that were created earlier. If there's a tor subprocess running, kill it.
"""
- # cleanup the ephemeral onion service
+ # Cleanup the ephemeral onion service
if self.service_id:
try:
self.c.remove_ephemeral_hidden_service(self.service_id)
except:
pass
self.service_id = None
+
+ # Stop tor process
+ if self.tor_proc:
+ self.tor_proc.terminate()
diff --git a/onionshare_gui/settings_dialog.py b/onionshare_gui/settings_dialog.py
index 13c6255..6cb6cdf 100644
--- a/onionshare_gui/settings_dialog.py
+++ b/onionshare_gui/settings_dialog.py
@@ -25,7 +25,6 @@ from onionshare.settings import Settings
from onionshare.onion import *
from .alert import Alert
-from .tor_dialog import TorDialog
class SettingsDialog(QtWidgets.QDialog):
"""
@@ -74,16 +73,10 @@ class SettingsDialog(QtWidgets.QDialog):
self.connection_type_bundled_radio = QtWidgets.QRadioButton(strings._('gui_settings_connection_type_bundled_option', True))
self.connection_type_bundled_radio.toggled.connect(self.connection_type_bundled_toggled)
- # Bundled Tor only works in Windows and Mac
+ # Bundled Tor doesn't work on dev mode in Windows or Mac
p = platform.system()
- if (p == 'Windows' or p == 'Darwin'):
- # Bundled Tor doesn't work on dev mode
- if getattr(sys, 'onionshare_dev_mode', False):
- self.connection_type_bundled_radio.setEnabled(False)
- else:
- # If not using Windows or Mac, disable and hide bundled Tor
+ if (p == 'Windows' or p == 'Darwin') and getattr(sys, 'onionshare_dev_mode', False):
self.connection_type_bundled_radio.setEnabled(False)
- self.connection_type_bundled_radio.hide()
# Automatic
self.connection_type_automatic_radio = QtWidgets.QRadioButton(strings._('gui_settings_connection_type_automatic_option', True))
@@ -285,20 +278,14 @@ class SettingsDialog(QtWidgets.QDialog):
"""
settings = self.settings_from_fields()
- # If using bundled Tor, first connect to Tor
- if settings.get('connection_type') == 'bundled':
- tor_dialog = TorDialog()
- tor_dialog.start()
-
- else:
- try:
- onion = Onion(settings=settings)
+ try:
+ onion = Onion(settings=settings)
- # If an exception hasn't been raised yet, the Tor settings work
- Alert(strings._('settings_test_success', True).format(onion.tor_version, onion.supports_ephemeral, onion.supports_stealth))
+ # If an exception hasn't been raised yet, the Tor settings work
+ Alert(strings._('settings_test_success', True).format(onion.tor_version, onion.supports_ephemeral, onion.supports_stealth))
- except (TorErrorInvalidSetting, TorErrorAutomatic, TorErrorSocketPort, TorErrorSocketFile, TorErrorMissingPassword, TorErrorUnreadableCookieFile, TorErrorAuthError, TorErrorProtocolError, BundledTorNotSupported) as e:
- Alert(e.args[0], QtWidgets.QMessageBox.Warning)
+ except (TorErrorInvalidSetting, TorErrorAutomatic, TorErrorSocketPort, TorErrorSocketFile, TorErrorMissingPassword, TorErrorUnreadableCookieFile, TorErrorAuthError, TorErrorProtocolError, BundledTorNotSupported) as e:
+ Alert(e.args[0], QtWidgets.QMessageBox.Warning)
def save_clicked(self):
"""
diff --git a/share/locale/en.json b/share/locale/en.json
index c0db438..e50f93e 100644
--- a/share/locale/en.json
+++ b/share/locale/en.json
@@ -90,5 +90,6 @@
"error_tor_protocol_error": "Error talking to the Tor controller.\nIf you're using Whonix, check out https://www.whonix.org/wiki/onionshare to make OnionShare work.",
"gui_tor_window_title": "Tor Connection",
"gui_tor_button_close": "Close",
- "gui_tor_button_restart": "Restart Tor"
+ "gui_tor_button_restart": "Restart Tor",
+ "connecting_to_tor": "Connecting to the Tor network"
}
diff --git a/share/torrc_template b/share/torrc_template
new file mode 100644
index 0000000..464adf3
--- /dev/null
+++ b/share/torrc_template
@@ -0,0 +1,9 @@
+DataDirectory {{data_directory}}
+SocksPort {{socks_port}}
+ControlSocket {{control_socket}}
+CookieAuthentication 1
+CookieAuthFile {{cookie_auth_file}}
+AvoidDiskWrites 1
+Log notice stdout
+GeoIPFile {{geo_ip_file}}
+GeoIPv6File {{geo_ipv6_file}}
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-privacy/packages/onionshare.git
More information about the Pkg-privacy-commits
mailing list