Added support for bundled tor connection type in Windows, including using ports instead of socket files

This commit is contained in:
Micah Lee 2017-04-14 18:33:44 -07:00
parent 6200cb3b08
commit 9b3cee0878
5 changed files with 77 additions and 25 deletions

View File

@ -8,10 +8,10 @@ REM download tor
python install\get-tor-windows.py python install\get-tor-windows.py
REM sign onionshare-gui.exe REM sign onionshare-gui.exe
signtool.exe sign /v /d "OnionShare" /a /tr http://timestamp.globalsign.com/scripts/timstamp.dll /fd sha256 dist\onionshare\onionshare-gui.exe REM signtool.exe sign /v /d "OnionShare" /a /tr http://timestamp.globalsign.com/scripts/timstamp.dll /fd sha256 dist\onionshare\onionshare-gui.exe
REM build an installer, dist\OnionShare_Setup.exe REM build an installer, dist\OnionShare_Setup.exe
makensis.exe install\onionshare.nsi REM makensis.exe install\onionshare.nsi
REM sign OnionShare_Setup.exe REM sign OnionShare_Setup.exe
signtool.exe sign /v /d "OnionShare" /a /tr http://timestamp.globalsign.com/scripts/timstamp.dll /fd sha256 dist\OnionShare_Setup.exe REM signtool.exe sign /v /d "OnionShare" /a /tr http://timestamp.globalsign.com/scripts/timstamp.dll /fd sha256 dist\OnionShare_Setup.exe

View File

@ -13,6 +13,7 @@ a = Analysis(
('../share/license.txt', 'share'), ('../share/license.txt', 'share'),
('../share/version.txt', 'share'), ('../share/version.txt', 'share'),
('../share/wordlist.txt', 'share'), ('../share/wordlist.txt', 'share'),
('../share/torrc_template-windows', 'share'),
('../share/images/*', 'share/images'), ('../share/images/*', 'share/images'),
('../share/locale/*', 'share/locale'), ('../share/locale/*', 'share/locale'),
('../share/html/*', 'share/html') ('../share/html/*', 'share/html')

View File

@ -53,6 +53,22 @@ def get_resource_path(filename):
return os.path.join(prefix, filename) return os.path.join(prefix, filename)
def get_tor_paths():
p = get_platform()
if p == 'Linux':
tor_path = '/usr/bin/tor'
tor_geo_ip_file_path = '/usr/share/tor/geoip'
tor_geo_ipv6_file_path = '/usr/share/tor/geoip6'
elif p == 'Windows':
base_path = os.path.join(os.path.dirname(os.path.dirname(get_resource_path(''))), 'tor')
tor_path = os.path.join(os.path.join(base_path, 'Tor'), "tor.exe")
tor_geo_ip_file_path = os.path.join(os.path.join(os.path.join(base_path, 'Data'), 'Tor'), 'geoip')
tor_geo_ipv6_file_path = os.path.join(os.path.join(os.path.join(base_path, 'Data'), 'Tor'), 'geoip6')
elif p == 'Darwin':
# TODO: implement
pass
return (tor_path, tor_geo_ip_file_path, tor_geo_ipv6_file_path)
def get_version(): def get_version():
""" """

View File

@ -21,7 +21,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
from stem.control import Controller from stem.control import Controller
from stem import ProtocolError from stem import ProtocolError
from stem.connection import MissingPassword, UnreadableCookieFile, AuthenticationFailure from stem.connection import MissingPassword, UnreadableCookieFile, AuthenticationFailure
import os, sys, tempfile, shutil, urllib, platform, subprocess, time, shlex import os, sys, tempfile, shutil, urllib, platform, subprocess, time, shlex, socket, random
from . import socks from . import socks
from . import helpers, strings from . import helpers, strings
@ -133,16 +133,7 @@ class Onion(object):
bundle_tor_supported = True bundle_tor_supported = True
# Set the path of the tor binary, for bundled tor # Set the path of the tor binary, for bundled tor
if system == 'Linux': (self.tor_path, self.tor_geo_ip_file_path, self.tor_geo_ipv6_file_path) = helpers.get_tor_paths()
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 # The tor process
self.tor_p = None self.tor_p = None
@ -156,28 +147,47 @@ class Onion(object):
# Create a torrc for this session # Create a torrc for this session
self.tor_data_directory = tempfile.TemporaryDirectory() 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') if system == 'Windows':
self.tor_socks_port_file = os.path.join(self.tor_data_directory.name, 'socks_socket') # Windows needs to use network ports, doesn't support unix sockets
self.tor_socks_port = 'unix:{}'.format(self.tor_socks_port_file) torrc_template = open(helpers.get_resource_path('torrc_template-windows')).read()
self.tor_torrc = os.path.join(self.tor_data_directory.name, 'torrc') self.tor_control_port = self._get_available_port()
torrc_template = open(helpers.get_resource_path('torrc_template')).read() self.tor_control_socket = None
self.tor_cookie_auth_file = os.path.join(self.tor_data_directory.name, 'cookie')
self.tor_socks_port_file = None
self.tor_socks_port = self._get_available_port()
self.tor_torrc = os.path.join(self.tor_data_directory.name, 'torrc')
else:
# Linux and Mac can use unix sockets
torrc_template = open(helpers.get_resource_path('torrc_template')).read()
self.tor_control_port = None
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 = torrc_template.replace('{{data_directory}}', self.tor_data_directory.name) 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('{{control_port}}', str(self.tor_control_port))
torrc_template = torrc_template.replace('{{control_socket}}', str(self.tor_control_socket))
torrc_template = torrc_template.replace('{{cookie_auth_file}}', self.tor_cookie_auth_file) 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_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('{{geo_ipv6_file}}', self.tor_geo_ipv6_file_path)
torrc_template = torrc_template.replace('{{socks_port}}', self.tor_socks_port) torrc_template = torrc_template.replace('{{socks_port}}', str(self.tor_socks_port))
open(self.tor_torrc, 'w').write(torrc_template) open(self.tor_torrc, 'w').write(torrc_template)
# Open tor in a subprocess, wait for the controller to start # Open tor in a subprocess, wait for the controller to start
start_ts = time.time() start_ts = time.time()
self.tor_proc = subprocess.Popen([self.tor_path, '-f', self.tor_torrc], stdout=subprocess.PIPE, stderr=subprocess.PIPE) self.tor_proc = subprocess.Popen([self.tor_path, '-f', self.tor_torrc], stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
time.sleep(0.2) time.sleep(0.2)
# Connect to the controller # Connect to the controller
self.c = Controller.from_socket_file(path=self.tor_control_socket) if system == 'Windows':
self.c.authenticate() self.c = Controller.from_port(port=self.tor_control_port)
self.c.authenticate()
else:
elf.c = Controller.from_socket_file(path=self.tor_control_socket)
self.c.authenticate()
while True: while True:
res = self.c.get_info("status/bootstrap-phase") res = self.c.get_info("status/bootstrap-phase")
@ -370,3 +380,19 @@ class Onion(object):
if self.tor_proc: if self.tor_proc:
self.tor_proc.terminate() self.tor_proc.terminate()
self.tor_proc = None self.tor_proc = None
def _get_available_port(self):
"""
Find a random available port
"""
tmpsock = socket.socket()
while True:
try:
tmpsock.bind(("127.0.0.1", random.randint(1000, 65535)))
break
except OSError:
pass
port = tmpsock.getsockname()[1]
tmpsock.close()
return port

View File

@ -0,0 +1,9 @@
DataDirectory {{data_directory}}
SocksPort {{socks_port}}
ControlPort {{control_port}}
CookieAuthentication 1
CookieAuthFile {{cookie_auth_file}}
AvoidDiskWrites 1
Log notice stdout
GeoIPFile {{geo_ip_file}}
GeoIPv6File {{geo_ipv6_file}}