diff --git a/onionshare/onion.py b/onionshare/onion.py index 07c516b2..45dba2f9 100644 --- a/onionshare/onion.py +++ b/onionshare/onion.py @@ -154,7 +154,6 @@ class Onion(object): self.tor_control_port = self._get_available_port() 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: @@ -163,8 +162,7 @@ class Onion(object): 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_socks_port = self._get_available_port() self.tor_torrc = os.path.join(self.tor_data_directory.name, 'torrc') torrc_template = torrc_template.replace('{{data_directory}}', self.tor_data_directory.name) @@ -392,6 +390,17 @@ class Onion(object): self.tor_proc.kill() self.tor_proc = None + def get_tor_socks_port(self): + """ + Returns a (address, port) tuple for the Tor SOCKS port + """ + if self.settings.get('connection_type') == 'bundled': + return ('127.0.0.1', self.tor_socks_port) + elif self.settings.get('connection_type') == 'automatic': + return ('127.0.0.1', 9150) + else: + return (self.settings.get('socks_address'), self.settings.get('socks_port')) + def _get_available_port(self): """ Find a random available port diff --git a/onionshare/settings.py b/onionshare/settings.py index 2e0b68e7..72e79a7f 100644 --- a/onionshare/settings.py +++ b/onionshare/settings.py @@ -38,6 +38,8 @@ class Settings(object): 'connection_type': 'bundled', 'control_port_address': '127.0.0.1', 'control_port_port': 9051, + 'socks_address': '127.0.0.1', + 'socks_port': 9050, 'socket_file_path': '/var/run/tor/control', 'auth_type': 'no_auth', 'auth_password': '', @@ -98,4 +100,14 @@ class Settings(object): return self._settings[key] def set(self, key, val): + # If typecasting int values fails, fallback to default values + if key == 'control_port_port' or key == 'socks_port': + try: + val = int(val) + except: + if key == 'control_port_port': + val = self.default_settings['control_port_port'] + elif key == 'socks_port': + val = self.default_settings['socks_port'] + self._settings[key] = val diff --git a/onionshare_gui/settings_dialog.py b/onionshare_gui/settings_dialog.py index 447a97df..e14749e0 100644 --- a/onionshare_gui/settings_dialog.py +++ b/onionshare_gui/settings_dialog.py @@ -18,7 +18,7 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . """ from PyQt5 import QtCore, QtWidgets, QtGui -import sys, platform +import sys, platform, datetime from onionshare import strings, helpers from onionshare.settings import Settings @@ -139,6 +139,19 @@ class SettingsDialog(QtWidgets.QDialog): self.connection_type_socket_file_extras.setLayout(connection_type_socket_file_extras_layout) self.connection_type_socket_file_extras.hide() + # Tor SOCKS address and port + gui_settings_socks_label = QtWidgets.QLabel(strings._('gui_settings_socks_label', True)) + self.connection_type_socks_address = QtWidgets.QLineEdit() + self.connection_type_socks_port = QtWidgets.QLineEdit() + connection_type_socks_layout = QtWidgets.QHBoxLayout() + connection_type_socks_layout.addWidget(gui_settings_socks_label) + connection_type_socks_layout.addWidget(self.connection_type_socks_address) + connection_type_socks_layout.addWidget(self.connection_type_socks_port) + + self.connection_type_socks = QtWidgets.QWidget() + self.connection_type_socks.setLayout(connection_type_socks_layout) + self.connection_type_socks.hide() + # Authentication options # No authentication @@ -179,6 +192,7 @@ class SettingsDialog(QtWidgets.QDialog): connection_type_group_layout.addWidget(self.connection_type_socket_file_radio) connection_type_group_layout.addWidget(self.connection_type_control_port_extras) connection_type_group_layout.addWidget(self.connection_type_socket_file_extras) + connection_type_group_layout.addWidget(self.connection_type_socks) connection_type_group_layout.addWidget(self.authenticate_group) connection_type_group_layout.addWidget(self.connection_type_test_button) connection_type_group = QtWidgets.QGroupBox(strings._("gui_settings_connection_type_label", True)) @@ -256,6 +270,8 @@ class SettingsDialog(QtWidgets.QDialog): self.connection_type_control_port_extras_address.setText(settings.get('control_port_address')) self.connection_type_control_port_extras_port.setText(str(settings.get('control_port_port'))) self.connection_type_socket_file_extras_path.setText(settings.get('socket_file_path')) + self.connection_type_socks_address.setText(settings.get('socks_address')) + self.connection_type_socks_port.setText(str(settings.get('socks_port'))) auth_type = settings.get('auth_type') if auth_type == 'no_auth': self.authenticate_no_auth_radio.setChecked(True) @@ -272,6 +288,7 @@ class SettingsDialog(QtWidgets.QDialog): """ if checked: self.authenticate_group.hide() + self.connection_type_socks.hide() def connection_type_automatic_toggled(self, checked): """ @@ -279,6 +296,7 @@ class SettingsDialog(QtWidgets.QDialog): """ if checked: self.authenticate_group.hide() + self.connection_type_socks.hide() def connection_type_control_port_toggled(self, checked): """ @@ -288,6 +306,7 @@ class SettingsDialog(QtWidgets.QDialog): if checked: self.authenticate_group.show() self.connection_type_control_port_extras.show() + self.connection_type_socks.show() else: self.connection_type_control_port_extras.hide() @@ -300,6 +319,7 @@ class SettingsDialog(QtWidgets.QDialog): if checked: self.authenticate_group.show() self.connection_type_socket_file_extras.show() + self.connection_type_socks.show() else: self.connection_type_socket_file_extras.hide() @@ -402,9 +422,12 @@ class SettingsDialog(QtWidgets.QDialog): settings.set('connection_type', 'socket_file') settings.set('control_port_address', self.connection_type_control_port_extras_address.text()) - settings.set('control_port_port', int(self.connection_type_control_port_extras_port.text())) + settings.set('control_port_port', self.connection_type_control_port_extras_port.text()) settings.set('socket_file_path', self.connection_type_socket_file_extras_path.text()) + settings.set('socks_address', self.connection_type_socks_address.text()) + settings.set('socks_port', self.connection_type_socks_port.text()) + if self.authenticate_no_auth_radio.isChecked(): settings.set('auth_type', 'no_auth') if self.authenticate_password_radio.isChecked(): diff --git a/share/locale/en.json b/share/locale/en.json index 0d5ba84f..b245ec2a 100644 --- a/share/locale/en.json +++ b/share/locale/en.json @@ -74,6 +74,7 @@ "gui_settings_connection_type_test_button": "Test Tor Settings", "gui_settings_control_port_label": "Control port", "gui_settings_socket_file_label": "Socket file", + "gui_settings_socks_label": "SOCKS port", "gui_settings_authenticate_label": "Tor authentication options", "gui_settings_authenticate_no_auth_option": "No authentication, or cookie authentication", "gui_settings_authenticate_password_option": "Password",