diff --git a/onionshare/__init__.py b/onionshare/__init__.py index 4cfc5e13..58f6a1c7 100644 --- a/onionshare/__init__.py +++ b/onionshare/__init__.py @@ -155,7 +155,7 @@ def main(cwd=None): app = OnionShare(debug, local_only, stay_open, transparent_torification, stealth) app.choose_port() app.start_onion_service() - except (onion.TorTooOld, onion.TorErrorInvalidSetting, onion.TorErrorAutomatic, onion.TorErrorSocketPort, onion.TorErrorSocketFile, onion.TorErrorMissingPassword, onion.TorErrorUnreadableCookieFile, onion.TorErrorAuthError) as e: + except (onion.TorTooOld, onion.TorErrorInvalidSetting, onion.TorErrorAutomatic, onion.TorErrorSocketPort, onion.TorErrorSocketFile, onion.TorErrorMissingPassword, onion.TorErrorUnreadableCookieFile, onion.TorErrorAuthError, onion.TorErrorProtocolError) as e: sys.exit(e.args[0]) except KeyboardInterrupt: print("") diff --git a/onionshare/onion.py b/onionshare/onion.py index 4e72a481..bb2bca72 100644 --- a/onionshare/onion.py +++ b/onionshare/onion.py @@ -19,7 +19,7 @@ along with this program. If not, see . """ from stem.control import Controller -from stem import SocketError +from stem import ProtocolError from stem.connection import MissingPassword, UnreadableCookieFile, AuthenticationFailure import os, sys, tempfile, shutil, urllib, platform @@ -72,6 +72,13 @@ class TorErrorAuthError(Exception): """ pass +class TorErrorProtocolError(Exception): + """ + This exception is raised if onionshare connects to the Tor controller, but it + isn't acting like a Tor controller (such as in Whonix). + """ + pass + class TorTooOld(Exception): """ This exception is raised if onionshare needs to use a feature of Tor or stem @@ -233,11 +240,15 @@ class Onion(object): else: basic_auth = None - if basic_auth != None : - res = self.c.create_ephemeral_hidden_service({ 80: port }, await_publication=True, basic_auth=basic_auth) - else : - # if the stem interface is older than 1.5.0, basic_auth isn't a valid keyword arg - res = self.c.create_ephemeral_hidden_service({ 80: port }, await_publication=True) + try: + if basic_auth != None : + res = self.c.create_ephemeral_hidden_service({ 80: port }, await_publication=True, basic_auth=basic_auth) + else : + # if the stem interface is older than 1.5.0, basic_auth isn't a valid keyword arg + res = self.c.create_ephemeral_hidden_service({ 80: port }, await_publication=True) + + except ProtocolError: + raise TorErrorProtocolError(strings._('error_tor_protocol_error')) self.service_id = res.content()[0][2].split('=')[1] onion_host = self.service_id + '.onion' diff --git a/onionshare/web.py b/onionshare/web.py index 0b400053..4da6fd0b 100644 --- a/onionshare/web.py +++ b/onionshare/web.py @@ -358,7 +358,14 @@ def start(port, stay_open=False, transparent_torification=False): set_stay_open(stay_open) set_transparent_torification(transparent_torification) - app.run(port=port, threaded=True) + + # In Whonix, listen on 0.0.0.0 instead of 127.0.0.1 (#220) + if os.path.exists('/usr/share/anon-ws-base-files/workstation'): + host = '0.0.0.0' + else: + host = '127.0.0.1' + + app.run(host=host, port=port, threaded=True) def stop(port): diff --git a/onionshare_gui/__init__.py b/onionshare_gui/__init__.py index 07ed6db2..d57b8420 100644 --- a/onionshare_gui/__init__.py +++ b/onionshare_gui/__init__.py @@ -177,7 +177,7 @@ class OnionShareGui(QtWidgets.QMainWindow): self.app.start_onion_service() self.starting_server_step2.emit() - except (onionshare.onion.TorTooOld, onionshare.onion.TorErrorInvalidSetting, onionshare.onion.TorErrorAutomatic, onionshare.onion.TorErrorSocketPort, onionshare.onion.TorErrorSocketFile, onionshare.onion.TorErrorMissingPassword, onionshare.onion.TorErrorUnreadableCookieFile, onionshare.onion.TorErrorAuthError) as e: + except (onionshare.onion.TorTooOld, onionshare.onion.TorErrorInvalidSetting, onionshare.onion.TorErrorAutomatic, onionshare.onion.TorErrorSocketPort, onionshare.onion.TorErrorSocketFile, onionshare.onion.TorErrorMissingPassword, onionshare.onion.TorErrorUnreadableCookieFile, onionshare.onion.TorErrorAuthError, onionshare.onion.TorErrorProtocolError) as e: self.starting_server_error.emit(e.args[0]) return diff --git a/onionshare_gui/settings_dialog.py b/onionshare_gui/settings_dialog.py index 8db649f8..521abbcc 100644 --- a/onionshare_gui/settings_dialog.py +++ b/onionshare_gui/settings_dialog.py @@ -21,7 +21,7 @@ from PyQt5 import QtCore, QtWidgets, QtGui from onionshare import strings from onionshare.settings import Settings -from onionshare.onion import Onion, TorErrorInvalidSetting, TorErrorAutomatic, TorErrorSocketPort, TorErrorSocketFile, TorErrorMissingPassword, TorErrorUnreadableCookieFile, TorErrorAuthError +from onionshare.onion import Onion, TorErrorInvalidSetting, TorErrorAutomatic, TorErrorSocketPort, TorErrorSocketFile, TorErrorMissingPassword, TorErrorUnreadableCookieFile, TorErrorAuthError, TorErrorProtocolError from .alert import Alert @@ -216,7 +216,7 @@ class SettingsDialog(QtWidgets.QDialog): # 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) as e: + except (TorErrorInvalidSetting, TorErrorAutomatic, TorErrorSocketPort, TorErrorSocketFile, TorErrorMissingPassword, TorErrorUnreadableCookieFile, TorErrorAuthError, TorErrorProtocolError) 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 7b25b64b..f4342169 100644 --- a/share/locale/en.json +++ b/share/locale/en.json @@ -82,5 +82,6 @@ "settings_error_auth": "Connected to {}:{}, but can't authenticate. Maybe this isn't a Tor controller?", "settings_error_missing_password": "Connected to Tor controller, but it requires a password to authenticate.", "settings_error_unreadable_cookie_file": "Connected to Tor controller, but can't authenticate because your password may be wrong, and your user doesn't have permission to read the cookie file.", - "settings_test_success": "Congratulations, OnionShare can connect to the Tor controller.\n\nTor version: {}\nSupports ephemeral onion services: {}\nSupports stealth onion services: {}" + "settings_test_success": "Congratulations, OnionShare can connect to the Tor controller.\n\nTor version: {}\nSupports ephemeral onion services: {}\nSupports stealth onion services: {}", + "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." }