Commit 9f6e718b authored by segfault's avatar segfault

Add Greeter option to enable the Unsafe Browser (refs: #17085)

... and disable it by default.
parent 0284ea59
......@@ -24,6 +24,7 @@ KBDSET=/etc/default/keyboard
CONSET=/etc/default/console-setup
LOCALE_CFG=/etc/default/locale
CODSET="Uni1" # universal codeset to properly display glyphs in localized console
GREETER_EXPORTED_SETTINGS="tails.macspoof tails.network tails.unsafe-browser"
log() {
echo "$1" >&2
......@@ -62,6 +63,17 @@ grep_n_set() {
log "Entering PostLogin"
### Export the Greeter settings
# It's important we export the settings from tails.macspoof before
# unblocking the network below; doing so will make the user-set MAC
# spoofing option apply (via the custom udev rule) when loading the
# modules for the previously blocked network devices.
for setting in ${GREETER_EXPORTED_SETTINGS}; do \
/usr/bin/install -m 0640 -o root -g root \
"/var/lib/gdm3/settings/$setting" \
"/var/lib/live/config/$setting" ; \
done
### Gather general configuration
# Import the name of the live user
......
......@@ -7,17 +7,6 @@ Type=oneshot
RemainAfterExit=yes
EnvironmentFile=/var/lib/gdm3/settings/tails.network
# It's important we "export" the settings from tails.macspoof before
# unblocking the network; doing so will make the user-set MAC spoofing
# option apply (via the custom udev rule) when loading the modules for the
# previously blocked network devices.
ExecStartPre=/bin/sh -c \
'for setting in macspoof network; do \
/usr/bin/install -m 0640 -o root -g root \
"/var/lib/gdm3/settings/tails.$setting" \
"/var/lib/live/config/tails.$setting" ; \
done'
ExecStartPre=/bin/sync
ExecStartPre=/bin/sh -c \
'if [ "${TAILS_NETCONF}" = "obstacle" ] ; then \
. /usr/local/lib/tails-shell-library/tor.sh ; \
......
......@@ -53,5 +53,8 @@ network_setting_path = os.path.join(settings_dir, 'tails.network')
# File where the MAC address spoofing setting is stored
macspoof_setting_path = os.path.join(settings_dir, 'tails.macspoof')
# File where the unsafe browser setting is stored
unsafe_browser_setting_path = os.path.join(settings_dir, 'tails.unsafe-browser')
# World-readable file where Tails persistence status is stored
persistence_state_file = '/var/lib/live/config/tails.persistence'
......@@ -30,8 +30,9 @@ from tailsgreeter.settings.localization_settings import LocalisationSettings
from tailsgreeter.settings.macspoof import MacSpoofSetting
from tailsgreeter.settings.network import NetworkSetting
from tailsgreeter.settings.persistence import PersistenceSettings
from tailsgreeter.settings.unsafe_browser import UnsafeBrowserSetting
from tailsgreeter.translatable_window import TranslatableWindow
from tailsgreeter.ui.additional_settings import AdminSettingUI, MACSpoofSettingUI, NetworkSettingUI
from tailsgreeter.ui.additional_settings import AdminSettingUI, MACSpoofSettingUI, NetworkSettingUI, UnsafeBrowserSettingUI
from tailsgreeter.ui.main_window import GreeterMainWindow
from tailsgreeter.ui.region_settings import LanguageSettingUI, KeyboardSettingUI, FormatsSettingUI
from tailsgreeter.ui.settings_collection import GreeterSettingsCollection
......@@ -73,8 +74,9 @@ class GreeterApplication(object):
usermanager_loaded_cb=self.usermanager_loaded,
)
self.admin_setting = AdminSetting()
self.network_setting = NetworkSetting()
self.macspoof_setting = MacSpoofSetting()
self.network_setting = NetworkSetting()
self.unsafe_browser_setting = UnsafeBrowserSetting()
# Initialize the settings
self.settings = GreeterSettingsCollection(
......@@ -84,6 +86,7 @@ class GreeterApplication(object):
AdminSettingUI(self.admin_setting),
MACSpoofSettingUI(self.macspoof_setting),
NetworkSettingUI(self.network_setting),
UnsafeBrowserSettingUI(self.unsafe_browser_setting),
)
# Initialize main window
......
import logging
import tailsgreeter.config
from tailsgreeter.settings import SettingNotFoundError
from tailsgreeter.settings.utils import read_settings, write_settings
class UnsafeBrowserSetting(object):
"""Setting controlling whether the Unsafe Browser is available or not"""
def __init__(self):
self.settings_file = tailsgreeter.config.unsafe_browser_setting_path
def save(self, value: bool):
write_settings(self.settings_file, {
'TAILS_UNSAFE_BROWSER_ENABLED': value,
})
logging.debug('unsafe-browser setting written to %s', self.settings_file)
def load(self) -> bool:
try:
settings = read_settings(self.settings_file)
except FileNotFoundError:
raise SettingNotFoundError("No persistent unsafe-browser settings file found (path: %s)" % self.settings_file)
value_str = settings.get('TAILS_UNSAFE_BROWSER_ENABLED')
if value_str is None:
raise SettingNotFoundError("No unsafe-browser setting found in settings file (path: %s)" % self.settings_file)
value = value_str == "true"
logging.debug("Loaded unsafe-browser setting '%s'", value)
return value
......@@ -47,6 +47,12 @@ class AdditionalSetting(GreeterSetting):
def load(self) -> bool:
pass
def cb_listbox_button_press(self, widget, event, user_data=None):
# On double-click: Close the window and apply chosen setting
if event.type == Gdk.EventType._2BUTTON_PRESS:
self.close_window(Gtk.ResponseType.YES)
return False
class AdminSettingUI(AdditionalSetting):
@property
......@@ -194,7 +200,7 @@ class MACSpoofSettingUI(AdditionalSetting):
self.image_macspoof_off = self.builder.get_object('image_macspoof_off')
self.listbox_macspoof_controls = self.builder.get_object('listbox_macspoof_controls')
self.listbox_macspoof_controls.connect('row-activated', self.cb_listbox_macspoof_row_activated)
self.listbox_macspoof_controls.connect('button-press-event', self.cb_listbox_macspoof_button_press)
self.listbox_macspoof_controls.connect('button-press-event', self.cb_listbox_button_press)
self.listboxrow_macspoof_on = self.builder.get_object('listboxrow_macspoof_on')
self.listboxrow_macspoof_off = self.builder.get_object('listboxrow_macspoof_off')
......@@ -229,12 +235,6 @@ class MACSpoofSettingUI(AdditionalSetting):
self.popover.close(Gtk.ResponseType.YES)
return False
def cb_listbox_macspoof_button_press(self, widget, event, user_data=None):
# On double-click: Close the window and apply chosen setting
if event.type == Gdk.EventType._2BUTTON_PRESS:
self.close_window(Gtk.ResponseType.YES)
return False
class NetworkSettingUI(AdditionalSetting):
@property
......@@ -267,7 +267,7 @@ class NetworkSettingUI(AdditionalSetting):
self.icon_network_specific_chosen = self.builder.get_object('image_network_specific')
self.icon_network_off_chosen = self.builder.get_object('image_network_off')
self.listbox_network_controls = self.builder.get_object('listbox_network_controls')
self.listbox_network_controls.connect('button-press-event', self.cb_listbox_network_button_press)
self.listbox_network_controls.connect('button-press-event', self.cb_listbox_button_press)
self.listbox_network_controls.connect('row-activated', self.cb_listbox_network_row_activated)
self.listboxrow_network_clear = self.builder.get_object('listboxrow_network_clear')
self.listboxrow_network_specific = self.builder.get_object('listboxrow_network_specific')
......@@ -299,12 +299,6 @@ class NetworkSettingUI(AdditionalSetting):
self.value = value
return True
def cb_listbox_network_button_press(self, widget, event, user_data=None):
# On double-click: Close the window and apply chosen setting
if event.type == Gdk.EventType._2BUTTON_PRESS:
self.close_window(Gtk.ResponseType.YES)
return False
def cb_listbox_network_row_activated(self, listbox, row, user_data=None):
self.icon_network_clear_chosen.set_visible(False)
self.icon_network_specific_chosen.set_visible(False)
......@@ -325,6 +319,69 @@ class NetworkSettingUI(AdditionalSetting):
return False
class UnsafeBrowserSettingUI(AdditionalSetting):
@property
def id(self) -> str:
return "unsafe_browser"
@property
def title(self) -> str:
return _("_Unsafe Browser")
@property
def icon_name(self) -> str:
return "web-browser-symbolic"
@property
def value_for_display(self) -> str:
return get_on_off_string(self.unsafe_browser_enabled, default=False)
def __init__(self, unsafe_browser_setting):
self._unsafe_browser_setting = unsafe_browser_setting
self.unsafe_browser_enabled = False
super().__init__()
self.accel_key = Gdk.KEY_u
self.listbox_unsafe_browser_controls = self.builder.get_object('listbox_unsafe_browser_controls')
self.listbox_unsafe_browser_controls.connect('button-press-event', self.cb_listbox_button_press)
self.listbox_unsafe_browser_controls.connect('row-activated', self.cb_listbox_unsafe_browser_row_activated)
self.listboxrow_unsafe_browser_off = self.builder.get_object('listboxrow_unsafe_browser_off')
self.listboxrow_unsafe_browser_on = self.builder.get_object('listboxrow_unsafe_browser_on')
self.icon_unsafe_browser_off = self.builder.get_object('image_unsafe_browser_off')
self.icon_unsafe_browser_on = self.builder.get_object('image_unsafe_browser_on')
self.label_unsafe_browser_value = self.builder.get_object('label_unsafe_browser_value')
def apply(self):
self._unsafe_browser_setting.save(self.unsafe_browser_enabled)
super().apply()
def load(self) -> bool:
try:
value = self._unsafe_browser_setting.load()
except SettingNotFoundError:
raise
# Select the correct listboxrow (used in the popover)
if value:
self.listbox_unsafe_browser_controls.select_row(self.listboxrow_unsafe_browser_on)
else:
self.listbox_unsafe_browser_controls.select_row(self.listboxrow_unsafe_browser_off)
if self.unsafe_browser_enabled == value:
return False
self.unsafe_browser_enabled = value
return True
def cb_listbox_unsafe_browser_row_activated(self, listbox, row, user_data=None):
self.unsafe_browser_enabled = row == self.listboxrow_unsafe_browser_on
self.icon_unsafe_browser_on.set_visible(self.unsafe_browser_enabled)
self.icon_unsafe_browser_off.set_visible(not self.unsafe_browser_enabled)
if self.has_popover() and self.popover.is_open():
self.popover.close(Gtk.ResponseType.YES)
return False
def get_on_off_string(value, default=None) -> str:
"""Return "On", "Off", "On (default)", or "Off (default)"""
if value and default:
......
......@@ -3,6 +3,7 @@
PERSISTENCE_SETTING='/var/lib/live/config/tails.persistence'
MACSPOOF_SETTING='/var/lib/live/config/tails.macspoof'
NETWORK_SETTING='/var/lib/live/config/tails.network'
UNSAFE_BROWSER_SETTING='/var/lib/live/config/tails.unsafe-browser'
_get_tg_setting() {
if [ -r "${1}" ]; then
......@@ -33,3 +34,7 @@ mac_spoof_is_enabled() {
tails_netconf() {
_get_tg_setting "${NETWORK_SETTING}" TAILS_NETCONF
}
unsafe_browser_is_enabled() {
[ "$(_get_tg_setting "${UNSAFE_BROWSER_SETTING}" TAILS_UNSAFE_BROWSER_ENABLED)" = true ]
}
\ No newline at end of file
......@@ -20,6 +20,9 @@ export TEXTDOMAIN
# and run_browser_in_chroot().
. /usr/local/lib/tails-shell-library/chroot-browser.sh
# Import unsafe_browser_is_enabled
. /usr/local/lib/tails-shell-library/tails-greeter.sh
error () {
local cli_text="${CMD}: `gettext \"error:\"` ${@}"
local dialog_text="<b><big>`gettext \"Error\"`</big></b>
......@@ -82,6 +85,13 @@ HUMAN_READABLE_NAME="`gettext \"Unsafe Browser\"`"
WARNING_PAGE='/usr/share/doc/tails/website/misc/unsafe_browser_warning'
HOME_PAGE="$(localized_tails_doc_page "${WARNING_PAGE}")"
# Check if the Unsafe Browser was disabled in the startup options
if ! unsafe_browser_is_enabled; then
error "`gettext \"The Unsafe Browser was not enabled on the Welcome Screen.\n\n\
If you want to use the Unsafe Browser, you have to restart Tails and enable \
it in the settings on the Welcome Screen.\"`"
fi
# Prevent multiple instances of the script.
exec 9>"${LOCK}"
if ! flock -x -n 9; then
......
......@@ -494,4 +494,161 @@
</packing>
</child>
</object>
<object class="GtkBox" id="box_unsafe_browser_popover">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="margin_left">18</property>
<property name="margin_right">18</property>
<property name="margin_top">18</property>
<property name="margin_bottom">18</property>
<property name="orientation">vertical</property>
<property name="spacing">18</property>
<child>
<object class="GtkLabel" id="label_unsafe_browser_title">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Unsafe Browser</property>
<attributes>
<attribute name="weight" value="bold"/>
<attribute name="scale" value="1.5"/>
</attributes>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="label_unsafe_browser_description">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">The Unsafe Browser allows you to log in to captive portals before starting Tor. It is also a security risk, because it could be used to deanonymize you.\nYou can enable the Unsafe Browser here if you have to log in to captive portals.</property>
<property name="justify">fill</property>
<property name="wrap">True</property>
<property name="width_chars">50</property>
<property name="max_width_chars">50</property>
<property name="xalign">0</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
<child>
<object class="GtkFrame" id="frame_unsafe_browser">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="margin_bottom">18</property>
<property name="label_xalign">0</property>
<property name="shadow_type">in</property>
<child>
<object class="GtkListBox" id="listbox_unsafe_browser_controls">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="selection_mode">browse</property>
<child>
<object class="GtkListBoxRow" id="listboxrow_unsafe_browser_off">
<property name="visible">True</property>
<property name="can_focus">True</property>
<child>
<object class="GtkBox" id="box_unsafe_browser_off">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="margin_left">6</property>
<property name="margin_right">6</property>
<property name="margin_top">6</property>
<property name="margin_bottom">6</property>
<property name="spacing">12</property>
<child>
<object class="GtkLabel" id="label_unsafe_browser_off">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Disable the Unsafe Browser (default)</property>
<property name="wrap">True</property>
<property name="max_width_chars">45</property>
<property name="xalign">0</property>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkImage" id="image_unsafe_browser_off">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="icon_name">emblem-ok-symbolic</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="pack_type">end</property>
<property name="position">2</property>
</packing>
</child>
</object>
</child>
</object>
</child>
<child>
<object class="GtkListBoxRow" id="listboxrow_unsafe_browser_on">
<property name="visible">True</property>
<property name="can_focus">True</property>
<child>
<object class="GtkBox" id="box_unsafe_browser_on">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="margin_left">6</property>
<property name="margin_right">6</property>
<property name="margin_top">6</property>
<property name="margin_bottom">6</property>
<property name="spacing">12</property>
<child>
<object class="GtkLabel" id="label_unsafe_browser_on">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Enable the Unsafe Browser</property>
<property name="justify">fill</property>
<property name="wrap">True</property>
<property name="max_width_chars">45</property>
<property name="xalign">0</property>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkImage" id="image_unsafe_browser_on">
<property name="can_focus">False</property>
<property name="icon_name">emblem-ok-symbolic</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="pack_type">end</property>
<property name="position">2</property>
</packing>
</child>
</object>
</child>
</object>
</child>
</object>
</child>
<child type="label_item">
<placeholder/>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">3</property>
</packing>
</child>
</object>
</interface>
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment