Rip out support for non-ephemeral onion services

This commit is contained in:
Micah Lee 2017-02-22 14:10:06 -08:00
parent a57703cb5a
commit 6370139d2e
No known key found for this signature in database
GPG Key ID: 403C2657CD994F73
4 changed files with 33 additions and 196 deletions

View File

@ -84,7 +84,7 @@ class OnionShare(object):
return return
if not self.onion: if not self.onion:
self.onion = onion.Onion(self.transparent_torification, self.stealth) self.onion = onion.Onion(self.stealth)
self.onion_host = self.onion.start(self.port) self.onion_host = self.onion.start(self.port)
@ -178,14 +178,8 @@ def main(cwd=None):
t.start() t.start()
try: # Trap Ctrl-C try: # Trap Ctrl-C
# wait for hs, only if using old version of tor # Wait for web.generate_slug() to finish running
if not app.local_only and not app.onion.supports_ephemeral: time.sleep(0.2)
ready = app.onion.wait_for_hs(app.onion_host)
if not ready:
sys.exit()
else:
# Wait for web.generate_slug() to finish running
time.sleep(0.2)
if(stealth): if(stealth):
print(strings._("give_this_url_stealth")) print(strings._("give_this_url_stealth"))

View File

@ -83,21 +83,12 @@ class TorTooOld(Exception):
class Onion(object): class Onion(object):
""" """
Onion is an abstraction layer for connecting to the Tor control port and Onion is an abstraction layer for connecting to the Tor control port and
creating onion services. OnionShare supports creating onion services creating onion services. OnionShare supports creating onion services by
using two methods: connecting to the Tor controller and using ADD_ONION, DEL_ONION.
- Modifying the Tor configuration through the control port is the old
method, and will be deprecated in favor of ephemeral onion services.
- Using the control port to create ephemeral onion servers is the
preferred method.
This class detects the versions of Tor and stem to determine if ephemeral
onion services are supported. If not, it falls back to modifying the
Tor configuration.
""" """
def __init__(self, transparent_torification=False, stealth=False, settings=False): def __init__(self, stealth=False, settings=False):
self.transparent_torification = transparent_torification
self.stealth = stealth self.stealth = stealth
self.service_id = None
# Either use settings that are passed in, or load them from disk # Either use settings that are passed in, or load them from disk
if settings: if settings:
@ -106,10 +97,6 @@ class Onion(object):
self.settings = Settings() self.settings = Settings()
self.settings.load() self.settings.load()
# files and dirs to delete on shutdown
self.cleanup_filenames = []
self.service_id = None
# Try to connect to Tor # Try to connect to Tor
self.c = None self.c = None
@ -210,14 +197,14 @@ class Onion(object):
except AuthenticationFailure: except AuthenticationFailure:
raise TorErrorAuthError(strings._('settings_error_auth').format(self.settings.get('control_port_address'), self.settings.get('control_port_port'))) raise TorErrorAuthError(strings._('settings_error_auth').format(self.settings.get('control_port_address'), self.settings.get('control_port_port')))
# get the tor version # Get the tor version
self.tor_version = self.c.get_version().version_str self.tor_version = self.c.get_version().version_str
# do the versions of stem and tor that I'm using support ephemeral onion services? # Do the versions of stem and tor that I'm using support ephemeral onion services?
list_ephemeral_hidden_services = getattr(self.c, "list_ephemeral_hidden_services", None) list_ephemeral_hidden_services = getattr(self.c, "list_ephemeral_hidden_services", None)
self.supports_ephemeral = callable(list_ephemeral_hidden_services) and self.tor_version >= '0.2.7.1' self.supports_ephemeral = callable(list_ephemeral_hidden_services) and self.tor_version >= '0.2.7.1'
# do the versions of stem and tor that I'm using support stealth onion services? # Do the versions of stem and tor that I'm using support stealth onion services?
try: try:
res = self.c.create_ephemeral_hidden_service({1:1}, basic_auth={'onionshare':None}, await_publication=False) res = self.c.create_ephemeral_hidden_service({1:1}, basic_auth={'onionshare':None}, await_publication=False)
tmp_service_id = res.content()[0][2].split('=')[1] tmp_service_id = res.content()[0][2].split('=')[1]
@ -233,181 +220,42 @@ class Onion(object):
return the onion hostname. return the onion hostname.
""" """
self.auth_string = None self.auth_string = None
if not self.supports_ephemeral:
raise TorTooOld(strings._('error_ephemeral_not_supported'))
if self.stealth and not self.supports_stealth: if self.stealth and not self.supports_stealth:
raise TorTooOld(strings._('error_stealth_not_supported')) raise TorTooOld(strings._('error_stealth_not_supported'))
print(strings._("config_onion_service").format(int(port))) print(strings._("config_onion_service").format(int(port)))
if self.supports_ephemeral: print(strings._('using_ephemeral'))
print(strings._('using_ephemeral'))
if self.stealth:
basic_auth = {'onionshare':None}
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)
self.service_id = res.content()[0][2].split('=')[1]
onion_host = self.service_id + '.onion'
if self.stealth:
auth_cookie = res.content()[2][2].split('=')[1].split(':')[1]
self.auth_string = 'HidServAuth {} {}'.format(onion_host, auth_cookie)
return onion_host
if self.stealth:
basic_auth = {'onionshare':None}
else: else:
# come up with a onion service directory name basic_auth = None
if helpers.get_platform() == 'Windows':
self.hidserv_dir = tempfile.mkdtemp()
self.hidserv_dir = self.hidserv_dir.replace('\\', '/')
else: if basic_auth != None :
self.hidserv_dir = tempfile.mkdtemp(suffix='onionshare',dir='/tmp') 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)
self.cleanup_filenames.append(self.hidserv_dir) self.service_id = res.content()[0][2].split('=')[1]
onion_host = self.service_id + '.onion'
# set up onion service if self.stealth:
hsdic = self.c.get_conf_map('HiddenServiceOptions') or { auth_cookie = res.content()[2][2].split('=')[1].split(':')[1]
'HiddenServiceDir': [], 'HiddenServicePort': [] self.auth_string = 'HidServAuth {} {}'.format(onion_host, auth_cookie)
}
if self.hidserv_dir in hsdic.get('HiddenServiceDir', []):
# Maybe a stale service with the wrong local port
dropme = hsdic['HiddenServiceDir'].index(self.hidserv_dir)
del hsdic['HiddenServiceDir'][dropme]
del hsdic['HiddenServicePort'][dropme]
hsdic['HiddenServiceDir'] = hsdic.get('HiddenServiceDir', [])+[self.hidserv_dir]
hsdic['HiddenServicePort'] = hsdic.get('HiddenServicePort', [])+[
'80 127.0.0.1:{0:d}'.format(port)]
self.c.set_options(self._hsdic2list(hsdic)) return onion_host
# figure out the .onion hostname
hostname_file = '{0:s}/hostname'.format(self.hidserv_dir)
onion_host = open(hostname_file, 'r').read().strip()
return onion_host
def wait_for_hs(self, onion_host):
"""
This function is only required when using non-ephemeral onion services. After
creating a onion service, continually attempt to connect to it until it
successfully connects.
"""
# legacy only, this function is no longer required with ephemeral onion services
print(strings._('wait_for_hs'))
ready = False
while not ready:
try:
sys.stdout.write('{0:s} '.format(strings._('wait_for_hs_trying')))
sys.stdout.flush()
if self.transparent_torification:
# no need to set the socks5 proxy
urllib.request.urlopen('http://{0:s}'.format(onion_host))
else:
tor_exists = False
ports = [9150, 9152, 9050]
for port in ports:
try:
s = socks.socksocket()
s.setproxy(socks.PROXY_TYPE_SOCKS5, '127.0.0.1', port)
s.connect((onion_host, 80))
s.close()
tor_exists = True
break
except socks.ProxyConnectionError:
pass
if not tor_exists:
raise NoTor(strings._("cant_connect_socksport").format(str(ports)))
ready = True
sys.stdout.write('{0:s}\n'.format(strings._('wait_for_hs_yup')))
except socks.GeneralProxyError:
sys.stdout.write('{0:s}\n'.format(strings._('wait_for_hs_nope')))
sys.stdout.flush()
except socks.SOCKS5Error:
sys.stdout.write('{0:s}\n'.format(strings._('wait_for_hs_nope')))
sys.stdout.flush()
except urllib.error.HTTPError: # torification error
sys.stdout.write('{0:s}\n'.format(strings._('wait_for_hs_nope')))
sys.stdout.flush()
except KeyboardInterrupt:
return False
return True
def cleanup(self): def cleanup(self):
""" """
Stop onion services that were created earlier, and delete any temporary Stop onion services that were created earlier.
files that were created.
""" """
if self.supports_ephemeral: # cleanup the ephemeral onion service
# cleanup the ephemeral onion service if self.service_id:
if self.service_id:
try:
self.c.remove_ephemeral_hidden_service(self.service_id)
except:
pass
self.service_id = None
else:
# cleanup onion service
try: try:
if self.controller: self.c.remove_ephemeral_hidden_service(self.service_id)
# Get fresh onion services (maybe changed since last time)
# and remove ourselves
hsdic = self.controller.get_conf_map('HiddenServiceOptions') or {
'HiddenServiceDir': [], 'HiddenServicePort': []
}
if self.hidserv_dir and self.hidserv_dir in hsdic.get('HiddenServiceDir', []):
dropme = hsdic['HiddenServiceDir'].index(self.hidserv_dir)
del hsdic['HiddenServiceDir'][dropme]
del hsdic['HiddenServicePort'][dropme]
self.controller.set_options(self._hsdic2list(hsdic))
# Politely close the controller
self.controller.close()
except: except:
pass pass
self.service_id = None
# cleanup files
for filename in self.cleanup_filenames:
if os.path.isfile(filename):
os.remove(filename)
elif os.path.isdir(filename):
shutil.rmtree(filename)
self.cleanup_filenames = []
def _hsdic2list(self, dic):
"""
Convert what we get from get_conf_map to what we need for set_options.
For example, if input looks like this:
{
'HiddenServicePort': [
'80 127.0.0.1:47906',
'80 127.0.0.1:33302'
],
'HiddenServiceDir': [
'/tmp/onionsharelTfZZu',
'/tmp/onionsharechDai3'
]
}
Output will look like this:
[
('HiddenServiceDir', '/tmp/onionsharelTfZZu'),
('HiddenServicePort', '80 127.0.0.1:47906'),
('HiddenServiceDir', '/tmp/onionsharechDai3'),
('HiddenServicePort', '80 127.0.0.1:33302')
]
"""
l = []
for dir, port in zip(dic['HiddenServiceDir'], dic['HiddenServicePort']):
l.append(('HiddenServiceDir', dir))
l.append(('HiddenServicePort', port))
return l

View File

@ -206,11 +206,6 @@ class OnionShareGui(QtWidgets.QMainWindow):
self.app.cleanup_filenames.append(web.zip_filename) self.app.cleanup_filenames.append(web.zip_filename)
self.starting_server_step3.emit() self.starting_server_step3.emit()
# wait for hs
if not self.app.local_only and not self.app.onion.supports_ephemeral:
self.status_bar.showMessage(strings._('gui_starting_server3', True))
self.app.onion.wait_for_hs(self.app.onion_host)
# done # done
self.start_server_finished.emit() self.start_server_finished.emit()

View File

@ -38,7 +38,6 @@
"gui_copied_hidservauth": "Copied HidServAuth line to clipboard", "gui_copied_hidservauth": "Copied HidServAuth line to clipboard",
"gui_starting_server1": "Starting Tor onion service...", "gui_starting_server1": "Starting Tor onion service...",
"gui_starting_server2": "Crunching files...", "gui_starting_server2": "Crunching files...",
"gui_starting_server3": "Waiting for Tor onion service...",
"gui_please_wait": "Please wait...", "gui_please_wait": "Please wait...",
"error_hs_dir_cannot_create": "Cannot create onion service dir {0:s}", "error_hs_dir_cannot_create": "Cannot create onion service dir {0:s}",
"error_hs_dir_not_writable": "onion service dir {0:s} is not writable", "error_hs_dir_not_writable": "onion service dir {0:s} is not writable",
@ -53,6 +52,7 @@
"error_rate_limit": "An attacker might be trying to guess your URL. To prevent this, OnionShare has automatically stopped the server. To share the files you must start it again and share the new URL.", "error_rate_limit": "An attacker might be trying to guess your URL. To prevent this, OnionShare has automatically stopped the server. To share the files you must start it again and share the new URL.",
"zip_progress_bar_format": "Crunching files: %p%", "zip_progress_bar_format": "Crunching files: %p%",
"error_stealth_not_supported": "To create stealth onion services, you need at least Tor 0.2.9.1-alpha (or Tor Browser 6.5) and at least python3-stem 1.5.0.", "error_stealth_not_supported": "To create stealth onion services, you need at least Tor 0.2.9.1-alpha (or Tor Browser 6.5) and at least python3-stem 1.5.0.",
"error_ephemeral_not_supported": "OnionShare requires at least at least Tor 0.2.7.1 and at least python3-stem 1.4.0.",
"gui_advanced_options": "Advanced Options", "gui_advanced_options": "Advanced Options",
"gui_create_stealth": "Create Stealth Onion Service", "gui_create_stealth": "Create Stealth Onion Service",
"gui_menu_file_menu": "&File", "gui_menu_file_menu": "&File",