diff --git a/onionshare/settings.py b/onionshare/settings.py index 28523b89..7a017bf0 100644 --- a/onionshare/settings.py +++ b/onionshare/settings.py @@ -114,7 +114,7 @@ class Settings(object): 'password': '', 'hidservauth_string': '', 'data_dir': self.build_default_data_dir(), - 'csp_header_enabled': True, + 'csp_header_disabled': False, 'locale': None # this gets defined in fill_in_defaults() } self._settings = {} diff --git a/onionshare/web/web.py b/onionshare/web/web.py index c1a9ce4c..f3e1e07a 100644 --- a/onionshare/web/web.py +++ b/onionshare/web/web.py @@ -239,7 +239,8 @@ class Web: """ for header, value in self.security_headers: r.headers.set(header, value) - if self.common.settings.get('csp_header_enabled'): + # Set a CSP header unless in website mode and the user has disabled it + if not self.common.settings.get('csp_header_disabled') or self.mode != 'website': r.headers.set('Content-Security-Policy', 'default-src \'self\'; style-src \'self\'; script-src \'self\'; img-src \'self\' data:;') return r diff --git a/onionshare_gui/settings_dialog.py b/onionshare_gui/settings_dialog.py index 432645e6..ec91a491 100644 --- a/onionshare_gui/settings_dialog.py +++ b/onionshare_gui/settings_dialog.py @@ -214,28 +214,10 @@ class SettingsDialog(QtWidgets.QDialog): self.close_after_first_download_checkbox.setText(strings._("gui_settings_close_after_first_download_option")) individual_downloads_label = QtWidgets.QLabel(strings._("gui_settings_individual_downloads_label")) - # Option to disable Content Security Policy (for website sharing) - self.csp_header_enabled_checkbox = QtWidgets.QCheckBox() - self.csp_header_enabled_checkbox.setCheckState(QtCore.Qt.Checked) - self.csp_header_enabled_checkbox.setText(strings._("gui_settings_csp_header_enabled_option")) - csp_header_label = QtWidgets.QLabel(strings._("gui_settings_whats_this").format("https://github.com/micahflee/onionshare/wiki/Content-Security-Policy")) - csp_header_label.setStyleSheet(self.common.css['settings_whats_this']) - csp_header_label.setTextInteractionFlags(QtCore.Qt.TextBrowserInteraction) - csp_header_label.setOpenExternalLinks(True) - csp_header_label.setMinimumSize(csp_header_label.sizeHint()) - csp_header_layout = QtWidgets.QHBoxLayout() - csp_header_layout.addWidget(self.csp_header_enabled_checkbox) - csp_header_layout.addWidget(csp_header_label) - csp_header_layout.addStretch() - csp_header_layout.setContentsMargins(0,0,0,0) - self.csp_header_widget = QtWidgets.QWidget() - self.csp_header_widget.setLayout(csp_header_layout) - # Sharing options layout sharing_group_layout = QtWidgets.QVBoxLayout() sharing_group_layout.addWidget(self.close_after_first_download_checkbox) sharing_group_layout.addWidget(individual_downloads_label) - sharing_group_layout.addWidget(self.csp_header_widget) sharing_group = QtWidgets.QGroupBox(strings._("gui_settings_sharing_label")) sharing_group.setLayout(sharing_group_layout) @@ -256,6 +238,36 @@ class SettingsDialog(QtWidgets.QDialog): receiving_group = QtWidgets.QGroupBox(strings._("gui_settings_receiving_label")) receiving_group.setLayout(receiving_group_layout) + # Option to disable Content Security Policy (for website sharing) + self.csp_header_disabled_checkbox = QtWidgets.QCheckBox() + self.csp_header_disabled_checkbox.setCheckState(QtCore.Qt.Unchecked) + self.csp_header_disabled_checkbox.setText(strings._("gui_settings_csp_header_disabled_option")) + csp_header_label = QtWidgets.QLabel(strings._("gui_settings_whats_this").format("https://github.com/micahflee/onionshare/wiki/Content-Security-Policy")) + csp_header_label.setStyleSheet(self.common.css['settings_whats_this']) + csp_header_label.setTextInteractionFlags(QtCore.Qt.TextBrowserInteraction) + csp_header_label.setOpenExternalLinks(True) + csp_header_label.setMinimumSize(csp_header_label.sizeHint()) + csp_header_layout = QtWidgets.QHBoxLayout() + csp_header_layout.addWidget(self.csp_header_disabled_checkbox) + csp_header_layout.addWidget(csp_header_label) + csp_header_layout.addStretch() + csp_header_layout.setContentsMargins(0,0,0,0) + self.csp_header_widget = QtWidgets.QWidget() + self.csp_header_widget.setLayout(csp_header_layout) + + # Website settings widget + website_settings_layout = QtWidgets.QVBoxLayout() + website_settings_layout.setContentsMargins(0, 0, 0, 0) + website_settings_layout.addWidget(self.csp_header_widget) + self.website_settings_widget = QtWidgets.QWidget() + self.website_settings_widget.setLayout(website_settings_layout) + + # Website mode options layout + website_group_layout = QtWidgets.QVBoxLayout() + website_group_layout.addWidget(self.website_settings_widget) + website_group = QtWidgets.QGroupBox(strings._("gui_settings_website_label")) + website_group.setLayout(website_group_layout) + # Automatic updates options # Autoupdate @@ -500,6 +512,7 @@ class SettingsDialog(QtWidgets.QDialog): left_col_layout.addWidget(onion_group) left_col_layout.addWidget(sharing_group) left_col_layout.addWidget(receiving_group) + left_col_layout.addWidget(website_group) left_col_layout.addWidget(autoupdate_group) left_col_layout.addLayout(language_layout) left_col_layout.addStretch() @@ -535,11 +548,11 @@ class SettingsDialog(QtWidgets.QDialog): else: self.close_after_first_download_checkbox.setCheckState(QtCore.Qt.Unchecked) - csp_header_enabled = self.old_settings.get('csp_header_enabled') - if csp_header_enabled: - self.csp_header_enabled_checkbox.setCheckState(QtCore.Qt.Checked) + csp_header_disabled = self.old_settings.get('csp_header_disabled') + if csp_header_disabled: + self.csp_header_disabled_checkbox.setCheckState(QtCore.Qt.Checked) else: - self.csp_header_enabled_checkbox.setCheckState(QtCore.Qt.Unchecked) + self.csp_header_disabled_checkbox.setCheckState(QtCore.Qt.Unchecked) autostart_timer = self.old_settings.get('autostart_timer') if autostart_timer: @@ -1006,7 +1019,7 @@ class SettingsDialog(QtWidgets.QDialog): settings.load() # To get the last update timestamp settings.set('close_after_first_download', self.close_after_first_download_checkbox.isChecked()) - settings.set('csp_header_enabled', self.csp_header_enabled_checkbox.isChecked()) + settings.set('csp_header_disabled', self.csp_header_disabled_checkbox.isChecked()) settings.set('autostart_timer', self.autostart_timer_checkbox.isChecked()) settings.set('autostop_timer', self.autostop_timer_checkbox.isChecked()) diff --git a/share/locale/en.json b/share/locale/en.json index 6ca5c01f..38500043 100644 --- a/share/locale/en.json +++ b/share/locale/en.json @@ -52,7 +52,7 @@ "gui_settings_onion_label": "Onion settings", "gui_settings_sharing_label": "Sharing settings", "gui_settings_close_after_first_download_option": "Stop sharing after files have been sent", - "gui_settings_csp_header_enabled_option": "Enable Content Security Policy header", + "gui_settings_csp_header_disabled_option": "Disable Content Security Policy header", "gui_settings_individual_downloads_label": "Uncheck to allow downloading individual files", "gui_settings_connection_type_label": "How should OnionShare connect to Tor?", "gui_settings_connection_type_bundled_option": "Use the Tor version built into OnionShare", @@ -142,6 +142,7 @@ "gui_mode_receive_button": "Receive Files", "gui_mode_website_button": "Publish Website", "gui_settings_receiving_label": "Receiving settings", + "gui_settings_website_label": "Website settings", "gui_settings_data_dir_label": "Save files to", "gui_settings_data_dir_browse_button": "Browse", "gui_settings_public_mode_checkbox": "Public mode", diff --git a/tests/GuiWebsiteTest.py b/tests/GuiWebsiteTest.py index f58f4aa2..798c619a 100644 --- a/tests/GuiWebsiteTest.py +++ b/tests/GuiWebsiteTest.py @@ -65,7 +65,7 @@ class GuiWebsiteTest(GuiShareTest): QtTest.QTest.qWait(2000) self.assertTrue('This is a test website hosted by OnionShare' in r.text) - def check_csp_header(self, public_mode, csp_header_enabled): + def check_csp_header(self, public_mode, csp_header_disabled): '''Test that the CSP header is present when enabled or vice versa''' url = "http://127.0.0.1:{}/".format(self.gui.app.port) if public_mode: @@ -74,10 +74,10 @@ class GuiWebsiteTest(GuiShareTest): r = requests.get(url, auth=requests.auth.HTTPBasicAuth('onionshare', self.gui.website_mode.server_status.web.password)) QtTest.QTest.qWait(2000) - if csp_header_enabled: - self.assertTrue('Content-Security-Policy' in r.headers) - else: + if csp_header_disabled: self.assertFalse('Content-Security-Policy' in r.headers) + else: + self.assertTrue('Content-Security-Policy' in r.headers) def run_all_website_mode_setup_tests(self): """Tests in website mode prior to starting a share""" @@ -106,7 +106,7 @@ class GuiWebsiteTest(GuiShareTest): self.run_all_website_mode_setup_tests() self.run_all_website_mode_started_tests(public_mode, startup_time=2000) self.view_website(public_mode) - self.check_csp_header(public_mode, self.gui.common.settings.get('csp_header_enabled')) + self.check_csp_header(public_mode, self.gui.common.settings.get('csp_header_disabled')) self.history_widgets_present(self.gui.website_mode) self.server_is_stopped(self.gui.website_mode, False) self.web_server_is_stopped() diff --git a/tests/local_onionshare_website_mode_csp_enabled_test.py b/tests/local_onionshare_website_mode_csp_enabled_test.py index 3cf79440..fbdc07ea 100644 --- a/tests/local_onionshare_website_mode_csp_enabled_test.py +++ b/tests/local_onionshare_website_mode_csp_enabled_test.py @@ -8,7 +8,7 @@ class LocalWebsiteModeCSPEnabledTest(unittest.TestCase, GuiWebsiteTest): @classmethod def setUpClass(cls): test_settings = { - "csp_header_enabled": True, + "csp_header_disabled": False, } cls.gui = GuiWebsiteTest.set_up(test_settings) diff --git a/tests/local_onionshare_website_mode_test.py b/tests/local_onionshare_website_mode_test.py index 5a7334a4..fc560f70 100644 --- a/tests/local_onionshare_website_mode_test.py +++ b/tests/local_onionshare_website_mode_test.py @@ -8,7 +8,7 @@ class LocalWebsiteModeTest(unittest.TestCase, GuiWebsiteTest): @classmethod def setUpClass(cls): test_settings = { - "csp_header_enabled": False + "csp_header_disabled": True } cls.gui = GuiWebsiteTest.set_up(test_settings) diff --git a/tests/test_onionshare_settings.py b/tests/test_onionshare_settings.py index d46c599b..12200b70 100644 --- a/tests/test_onionshare_settings.py +++ b/tests/test_onionshare_settings.py @@ -67,7 +67,7 @@ class TestSettings: 'hidservauth_string': '', 'data_dir': os.path.expanduser('~/OnionShare'), 'public_mode': False, - 'csp_header_enabled': True + 'csp_header_disabled': False } for key in settings_obj._settings: # Skip locale, it will not always default to the same thing