diff options
author | Micah Lee <micah@micahflee.com> | 2020-12-13 11:40:25 -0800 |
---|---|---|
committer | Micah Lee <micah@micahflee.com> | 2020-12-13 11:40:25 -0800 |
commit | b96b83905ba5b62c332a6c8946218ddae4c61517 (patch) | |
tree | f5a8fb5ade60583e12d07c657fde007c8ffe4ce0 /cli | |
parent | ae621b4001dc44d7f07a9fad43376439b855ccd8 (diff) | |
parent | a520057bf4bd0956f03b763bfacdb8145cb5f977 (diff) | |
download | onionshare-b96b83905ba5b62c332a6c8946218ddae4c61517.tar.gz onionshare-b96b83905ba5b62c332a6c8946218ddae4c61517.zip |
Merge branch 'develop' into 929_download_errors
Diffstat (limited to 'cli')
-rw-r--r-- | cli/onionshare_cli/__init__.py | 14 | ||||
-rw-r--r-- | cli/onionshare_cli/common.py | 10 | ||||
-rw-r--r-- | cli/onionshare_cli/onion.py | 129 | ||||
-rw-r--r-- | cli/onionshare_cli/onionshare.py | 1 |
4 files changed, 76 insertions, 78 deletions
diff --git a/cli/onionshare_cli/__init__.py b/cli/onionshare_cli/__init__.py index 12808375..8ba0aac2 100644 --- a/cli/onionshare_cli/__init__.py +++ b/cli/onionshare_cli/__init__.py @@ -22,7 +22,7 @@ import os, sys, time, argparse, threading from datetime import datetime from datetime import timedelta -from .common import Common +from .common import Common, CannotFindTor from .web import Web from .onion import * from .onionshare import OnionShare @@ -320,7 +320,15 @@ def main(cwd=None): web = Web(common, False, mode_settings, mode) # Start the Onion object - onion = Onion(common, use_tmp_dir=True) + try: + onion = Onion(common, use_tmp_dir=True) + except CannotFindTor: + print("You must install tor to use OnionShare from the command line") + if common.platform == "Darwin": + print("In macOS, you can do this with Homebrew (https://brew.sh):") + print(" brew install tor") + sys.exit() + try: onion.connect( custom_settings=False, @@ -332,7 +340,7 @@ def main(cwd=None): print("") sys.exit() except Exception as e: - sys.exit(e.args[0]) + sys.exit() # Start the onionshare app try: diff --git a/cli/onionshare_cli/common.py b/cli/onionshare_cli/common.py index a1213387..e8b174b6 100644 --- a/cli/onionshare_cli/common.py +++ b/cli/onionshare_cli/common.py @@ -34,6 +34,12 @@ from pkg_resources import resource_filename from .settings import Settings +class CannotFindTor(Exception): + """ + OnionShare can't find a tor binary + """ + + class Common: """ The Common object is shared amongst all parts of OnionShare. @@ -82,6 +88,8 @@ class Common: def get_tor_paths(self): if self.platform == "Linux": tor_path = shutil.which("tor") + if not tor_path: + raise CannotFindTor() obfs4proxy_file_path = shutil.which("obfs4proxy") prefix = os.path.dirname(os.path.dirname(tor_path)) tor_geo_ip_file_path = os.path.join(prefix, "share/tor/geoip") @@ -94,6 +102,8 @@ class Common: tor_geo_ipv6_file_path = os.path.join(base_path, "Data", "Tor", "geoip6") elif self.platform == "Darwin": tor_path = shutil.which("tor") + if not tor_path: + raise CannotFindTor() obfs4proxy_file_path = shutil.which("obfs4proxy") prefix = os.path.dirname(os.path.dirname(tor_path)) tor_geo_ip_file_path = os.path.join(prefix, "share/tor/geoip") diff --git a/cli/onionshare_cli/onion.py b/cli/onionshare_cli/onion.py index 56a19133..7c9d0a67 100644 --- a/cli/onionshare_cli/onion.py +++ b/cli/onionshare_cli/onion.py @@ -32,11 +32,8 @@ import getpass import psutil from distutils.version import LooseVersion as Version -from . import common from .settings import Settings -# TODO: Figure out how to localize this for the GUI - class TorErrorAutomatic(Exception): """ @@ -44,40 +41,30 @@ class TorErrorAutomatic(Exception): using automatic settings that should work with Tor Browser. """ - pass - class TorErrorInvalidSetting(Exception): """ This exception is raised if the settings just don't make sense. """ - pass - class TorErrorSocketPort(Exception): """ OnionShare can't connect to the Tor controller using the supplied address and port. """ - pass - class TorErrorSocketFile(Exception): """ OnionShare can't connect to the Tor controller using the supplied socket file. """ - pass - class TorErrorMissingPassword(Exception): """ OnionShare connected to the Tor controller, but it requires a password. """ - pass - class TorErrorUnreadableCookieFile(Exception): """ @@ -85,8 +72,6 @@ class TorErrorUnreadableCookieFile(Exception): to access the cookie file. """ - pass - class TorErrorAuthError(Exception): """ @@ -94,8 +79,6 @@ class TorErrorAuthError(Exception): that a Tor controller isn't listening on this port. """ - pass - class TorErrorProtocolError(Exception): """ @@ -103,17 +86,17 @@ class TorErrorProtocolError(Exception): isn't acting like a Tor controller (such as in Whonix). """ - pass - -class TorTooOld(Exception): +class TorTooOldEphemeral(Exception): """ - This exception is raised if onionshare needs to use a feature of Tor or stem - (like stealth ephemeral onion services) but the version you have installed - is too old. + This exception is raised if the version of tor doesn't support ephemeral onion services """ - pass + +class TorTooOldStealth(Exception): + """ + This exception is raised if the version of tor doesn't support stealth onion services + """ class BundledTorTimeout(Exception): @@ -137,6 +120,12 @@ class BundledTorBroken(Exception): """ +class PortNotAvailable(Exception): + """ + There are no available ports for OnionShare to use, which really shouldn't ever happen + """ + + class Onion(object): """ Onion is an abstraction layer for connecting to the Tor control port and @@ -236,7 +225,8 @@ class Onion(object): try: self.tor_socks_port = self.common.get_available_port(1000, 65535) except: - raise OSError("OnionShare port not available") + print("OnionShare port not available") + raise PortNotAvailable() self.tor_torrc = os.path.join(self.tor_data_directory_name, "torrc") # If there is an existing OnionShare tor process, kill it @@ -268,7 +258,8 @@ class Onion(object): try: self.tor_control_port = self.common.get_available_port(1000, 65535) except: - raise OSError("OnionShare port not available") + print("OnionShare port not available") + raise PortNotAvailable() self.tor_control_socket = None else: # Linux and BSD can use unix sockets @@ -337,10 +328,6 @@ class Onion(object): f.write(self.settings.get("tor_bridges_use_custom_bridges")) f.write("\nUseBridges 1") - # Make sure the tor path is accurate - if not os.path.exists(self.tor_path): - raise BundledTorNotSupported(f"Cannot find tor binary: {self.tor_path}") - # Execute a tor subprocess start_ts = time.time() if self.common.platform == "Windows": @@ -375,10 +362,8 @@ class Onion(object): self.c = Controller.from_socket_file(path=self.tor_control_socket) self.c.authenticate() except Exception as e: - raise BundledTorBroken( - # strings._("settings_error_bundled_tor_broken").format(e.args[0]) - "OnionShare could not connect to Tor:\n{}".format(e.args[0]) - ) + print("OnionShare could not connect to Tor:\n{}".format(e.args[0])) + raise BundledTorBroken(e.args[0]) while True: try: @@ -425,15 +410,16 @@ class Onion(object): print("") try: self.tor_proc.terminate() - raise BundledTorTimeout( - # strings._("settings_error_bundled_tor_timeout") + print( "Taking too long to connect to Tor. Maybe you aren't connected to the Internet, or have an inaccurate system clock?" ) + raise BundledTorTimeout() except FileNotFoundError: pass elif self.settings.get("connection_type") == "automatic": # Automatically try to guess the right way to connect to Tor Browser + automatic_error = "Could not connect to the Tor controller. Is Tor Browser (available from torproject.org) running in the background?" # Try connecting to control port found_tor = False @@ -485,30 +471,25 @@ class Onion(object): ) elif self.common.platform == "Windows": # Windows doesn't support unix sockets - raise TorErrorAutomatic( - # strings._("settings_error_automatic") - "Could not connect to the Tor controller. Is Tor Browser (available from torproject.org) running in the background?" - ) + print(automatic_error) + raise TorErrorAutomatic() self.c = Controller.from_socket_file(path=socket_file_path) except: - raise TorErrorAutomatic( - # strings._("settings_error_automatic") - "Could not connect to the Tor controller. Is Tor Browser (available from torproject.org) running in the background?" - ) + print(automatic_error) + raise TorErrorAutomatic() # Try authenticating try: self.c.authenticate() except: - raise TorErrorAutomatic( - # strings._("settings_error_automatic") - "Could not connect to the Tor controller. Is Tor Browser (available from torproject.org) running in the background?" - ) + print(automatic_error) + raise TorErrorAutomatic() else: # Use specific settings to connect to tor + invalid_settings_error = "Can't connect to Tor controller because your settings don't make sense." # Try connecting try: @@ -522,27 +503,28 @@ class Onion(object): path=self.settings.get("socket_file_path") ) else: - raise TorErrorInvalidSetting( - # strings._("settings_error_unknown") - "Can't connect to Tor controller because your settings don't make sense." - ) + print(invalid_settings_error) + raise TorErrorInvalidSetting() except: if self.settings.get("connection_type") == "control_port": - raise TorErrorSocketPort( - # strings._("settings_error_socket_port") + print( "Can't connect to the Tor controller at {}:{}.".format( self.settings.get("control_port_address"), self.settings.get("control_port_port"), ) ) + raise TorErrorSocketPort( + self.settings.get("control_port_address"), + self.settings.get("control_port_port"), + ) else: - raise TorErrorSocketFile( - # strings._("settings_error_socket_file") + print( "Can't connect to the Tor controller using socket file {}.".format( self.settings.get("socket_file_path") ) ) + raise TorErrorSocketFile(self.settings.get("socket_file_path")) # Try authenticating try: @@ -551,29 +533,30 @@ class Onion(object): elif self.settings.get("auth_type") == "password": self.c.authenticate(self.settings.get("auth_password")) else: - raise TorErrorInvalidSetting( - # strings._("settings_error_unknown") - "Can't connect to Tor controller because your settings don't make sense." - ) + print(invalid_settings_error) + raise TorErrorInvalidSetting() except MissingPassword: - raise TorErrorMissingPassword( - # strings._("settings_error_missing_password") + print( "Connected to Tor controller, but it requires a password to authenticate." ) + raise TorErrorMissingPassword() except UnreadableCookieFile: - raise TorErrorUnreadableCookieFile( - # strings._("settings_error_unreadable_cookie_file") + print( "Connected to the Tor controller, but password may be wrong, or your user is not permitted to read the cookie file." ) + raise TorErrorUnreadableCookieFile() except AuthenticationFailure: - raise TorErrorAuthError( - # strings._("settings_error_auth") + print( "Connected to {}:{}, but can't authenticate. Maybe this isn't a Tor controller?".format( self.settings.get("control_port_address"), self.settings.get("control_port_port"), ) ) + raise TorErrorAuthError( + self.settings.get("control_port_address"), + self.settings.get("control_port_port"), + ) # If we made it this far, we should be connected to Tor self.connected_to_tor = True @@ -628,15 +611,15 @@ class Onion(object): self.common.log("Onion", "start_onion_service", f"port={port}") if not self.supports_ephemeral: - raise TorTooOld( - # strings._("error_ephemeral_not_supported") + print( "Your version of Tor is too old, ephemeral onion services are not supported" ) + raise TorTooOldEphemeral() if mode_settings.get("general", "client_auth") and not self.supports_stealth: - raise TorTooOld( - # strings._("error_stealth_not_supported") + print( "Your version of Tor is too old, stealth onion services are not supported" ) + raise TorTooOldStealth() auth_cookie = None if mode_settings.get("general", "client_auth"): @@ -693,10 +676,8 @@ class Onion(object): ) except ProtocolError as e: - raise TorErrorProtocolError( - # strings._("error_tor_protocol_error") - "Tor error: {}".format(e.args[0]) - ) + print("Tor error: {}".format(e.args[0])) + raise TorErrorProtocolError(e.args[0]) onion_host = res.service_id + ".onion" diff --git a/cli/onionshare_cli/onionshare.py b/cli/onionshare_cli/onionshare.py index 6fead913..db15a03d 100644 --- a/cli/onionshare_cli/onionshare.py +++ b/cli/onionshare_cli/onionshare.py @@ -21,7 +21,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. import os, shutil from . import common -from .onion import TorTooOld, TorErrorProtocolError from .common import AutoStopTimer |