Commit 8b56e3f6 authored by bertagaz's avatar bertagaz
Browse files

Merge branch 'master' into stable

parents 52eaf89d 0e901e24
# Allow our gdm-x-session wrapper to kill the GDM service
Debian-gdm ALL = NOPASSWD: /bin/systemctl kill --signal=9 gdm
# XXX:Buster this sudo rule should be replaced by a polkit rule once we have
# policykit >= 0.106. The rule is already in
# [[blueprint/additional_software_packages/org.boum.tails.additional-software.rules]]
# and should be installed in /usr/share/polkit-1/rules.d/
amnesia ALL = NOPASSWD: /bin/systemctl start tails-additional-software-install.service
......@@ -50,3 +50,8 @@ pref("mailnews.auto_config.oauth2.enabled", false);
// resolver, but over HTTPS to some DNS web service, but that web
// service could still be targeted.
pref("mailnews.auto_config.dns_mx_lookup.enabled", false);
// We disable Memory Hole for encrypted email until support is more
// mature and widely spread (#15201).
pref("extensions.enigmail.protectHeaders", false);
pref("extensions.torbirdy.custom.extensions.enigmail.protectHeaders", false);
// As suggested in TBB's start-tor-browser script for system-wide Tor
// instances
pref("extensions.torbutton.banned_ports", "631,6136,4444,4445,6668,7656,7657,7658,7659,7660,8998,9040,9050,9061,9062,9150,9051");
pref("extensions.torbutton.banned_ports", "631,6136,4444,4445,6668,7656,7657,7658,7659,7660,8998,9040,9050,9062,9150,9051");
pref("extensions.torbutton.custom.socks_host", "127.0.0.1");
pref("extensions.torbutton.custom.socks_port", 9150);
pref("extensions.torbutton.launch_warning", false);
......
......@@ -15,8 +15,6 @@
## Default SocksPort
SocksPort 127.0.0.1:9050 IsolateDestAddr IsolateDestPort
## SocksPort for the MUA
SocksPort 127.0.0.1:9061 IsolateDestAddr
## SocksPort for Tails-specific applications
SocksPort 127.0.0.1:9062 IsolateDestAddr IsolateDestPort
## SocksPort for the default web browser
......
pref("extensions.torbirdy.custom.network.proxy.socks_port", 9061);
pref("extensions.torbirdy.emailwizard", true);
pref("extensions.torbirdy.gpg_already_torified", true);
[Unit]
Description=Install Additional Software Packages
Documentation=https://tails.boum.org/contribute/design/persistence/
ConditionFileNotEmpty=/live/persistence/TailsData_unlocked/live-additional-software.conf
[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/usr/local/sbin/tails-additional-software install
ExecStartPost=/usr/bin/install -m 0644 -D /dev/null /run/live-additional-software/installed
TimeoutStartSec=infinity
PrivateDevices=yes
PrivateTmp=yes
# Capabilities needed by tails-additional-software
CapabilityBoundingSet=CAP_DAC_READ_SEARCH
# Capabilities needed by apt/dpkg
CapabilityBoundingSet=CAP_CHOWN CAP_DAC_OVERRIDE CAP_FOWNER CAP_FSETID
CapabilityBoundingSet=CAP_SETGID CAP_SETUID
ProtectSystem=no
# Capabilities needed by tails-notify-user
CapabilityBoundingSet=CAP_SYS_PTRACE CAP_AUDIT_WRITE CAP_SYS_RESOURCE
ProtectHome=no
[Unit]
Description=Trigger upgrade of Additional Software Packages
Documentation=https://tails.boum.org/contribute/design/persistence/
After=tails-additional-software-install.service
After=tor-has-bootstrapped.service
ConditionFileNotEmpty=/live/persistence/TailsData_unlocked/live-additional-software.conf
[Path]
PathExists=/run/live-additional-software/installed
[Unit]
Description=Upgrade Additional Software Packages
Documentation=https://tails.boum.org/contribute/design/persistence/
After=tails-additional-software-install.service
After=tor-has-bootstrapped.service
ConditionFileNotEmpty=/live/persistence/TailsData_unlocked/live-additional-software.conf
[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/usr/local/sbin/tails-additional-software upgrade
TimeoutStartSec=infinity
PrivateDevices=yes
PrivateTmp=yes
# Capabilities needed by tails-additional-software
CapabilityBoundingSet=CAP_DAC_READ_SEARCH
# Capabilities needed by apt/dpkg
CapabilityBoundingSet=CAP_CHOWN CAP_DAC_OVERRIDE CAP_FOWNER CAP_FSETID
CapabilityBoundingSet=CAP_SETGID CAP_SETUID
ProtectSystem=no
# Capabilities needed by tails-notify-user
CapabilityBoundingSet=CAP_SYS_PTRACE CAP_AUDIT_WRITE CAP_SYS_RESOURCE
ProtectHome=no
[Unit]
Description=Break Xorg for Tails test suite
Documentation=https://tails.boum.org/contribute/release_process/test/automated_tests/
ConditionKernelCommandLine=autotest_broken_Xorg
Before=gdm.service
[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/bin/sh -c 'echo "#!/bin/sh\nexit 1" > /usr/bin/Xorg'
[Install]
WantedBy=multi-user.target
[Unit]
Description=Guide the user when GDM fails to start
# GDM normally runs "plymouth --quit" when it fails to start the X server
# (see on_display_status_changed that calls plymouth_quit_without_transition).
# But when this happens we kill -9 GDM in our gdm-x-session wrapper, so it
# might not have time to quit plymouth yet. Therefore we ensure plymouth
# has quit before we start: we run after plymouth-quit.service (which is started
# by gdm.service's default OnFailure=), we have plymouth-quit-wait.service start,
# and we wait for it to complete.
After=plymouth-quit.service
Requires=plymouth-quit-wait.service
After=plymouth-quit-wait.service
[Service]
Type=oneshot
# We use VT5 that is clean of boot messages and does not get a getty started
# when we switch there, thanks to our custom NAutoVTs=4 logind.conf setting
#
# There are queued udev events when we run plymouthd so on Stretch, so
# watch_for_coldplug_completion will set up a watcher and return before
# there's any place where plymouthd can create a seat to display its
# splash and messages on. So we tell plymouthd to ignore udev which makes
# it create a fallback seat.
# XXX:Buster: check if plymouth.ignore-udev is still necessary (this code path
# has changed in plymouth 0.9.3)
ExecStart=/bin/sh -c \
'/sbin/plymouthd --mode=shutdown --tty=tty5 \
--kernel-command-line="plymouth.ignore-udev $(cat /proc/cmdline)"'
ExecStart=/bin/chvt 5
ExecStart=/bin/plymouth show-splash
ExecStart=/bin/sh -c \
'MAX_LENGTH=254 ; \
PREFIX="Error starting GDM with your graphics card: " ; \
SUFFIX=". Please take note of this error and visit https://tails.boum.org/gdm for troubleshooting." ; \
MAX_VIDEO_CARD_LENGTH=$(($MAX_LENGTH - $(echo -n "$PREFIX$SUFFIX" | wc -c))) ; \
VIDEO_CARD=$(lspci -d::0300 -nn | sed -E "s,.* VGA compatible controller \[0300\]:\s*,," | cut -c "1-$MAX_VIDEO_CARD_LENGTH") ; \
/bin/plymouth display-message --text="$PREFIX$VIDEO_CARD$SUFFIX" \
'
# We remove /etc/ssl/certs/java/cacert at build-time to ensure a
# deterministic build, so we need to re-create it at boot time.
[Unit]
Description=Update /etc/ssl/certs and ca-certificates.crt
After=local-fs.target systemd-tmpfiles-setup.service
Before=systemd-user-sessions.service
DefaultDependencies=no
[Service]
Type=oneshot
ExecStart=/usr/sbin/update-ca-certificates --fresh
RemainAfterExit=yes
CapabilityBoundingSet=
PrivateDevices=yes
PrivateTmp=yes
ProtectHome=yes
ProtectSystem=yes
[Install]
WantedBy=multi-user.target
#!/bin/sh
# No "set -e" because we need to capture the exit status of gdm-x-session.real
set -u
FAILURES_COUNT_FILE=/var/lib/gdm3/gdm-x-session_failures
MAX_FAILURES=5
get_failures () {
local failures=0
if [ -f "$FAILURES_COUNT_FILE" ] ; then
failures=$(cat "$FAILURES_COUNT_FILE")
fi
echo -n "$failures"
}
increment_failures () {
failures=$(($(get_failures) + 1))
echo -n "$failures" > "$FAILURES_COUNT_FILE"
}
/usr/lib/gdm3/gdm-x-session.real "$@"
RET=$?
if [ $RET -ne 0 ] ; then
increment_failures
if [ $(get_failures) -ge "$MAX_FAILURES" ] ; then
# Trigger OnFailure=tails-gdm-failed-to-start.service
echo "gdm-x-session failed too many times, stopping GDM"
sudo -n /bin/systemctl kill --signal=9 gdm
fi
fi
exit $RET
# This user unit triggers installation of additional software packages after
# the desktop has started by starting the identically named system unit.
[Unit]
Description=Trigger installation of Additional Software Packages
Documentation=https://tails.boum.org/contribute/design/persistence/
[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/usr/bin/sudo /bin/systemctl start tails-additional-software-install.service
# XXX:Buster: when policykit-1 >= 0.106 is available in Tails, we should
# use the following, and remove sudoers.d configuration:
#ExecStart=/bin/systemctl start tails-additional-software-install.service
TimeoutStartSec=0
[Install]
WantedBy=desktop.target
#!/bin/sh
#! /usr/bin/env python3
"""
Tails electrum wrapper
set -e
set -u
Test with "python3 electrum.py doctest".
The tests will start the tor-browser so you probably
want to use a tester that handles user interaction or
run the tests from the command line and answer prompts as needed.
. gettext.sh
TEXTDOMAIN="tails"
export TEXTDOMAIN
goodcrypto.com converted from bash to python and added basic tests.
CONF_DIR="${HOME}"/.electrum
>>> # run script
>>> sh.Command(sys.argv[0])()
<BLANKLINE>
"""
electrum_config_is_persistent() {
[ "$(findmnt --noheadings --output SOURCE --target "${CONF_DIR}")" = "/dev/mapper/TailsData_unlocked[/electrum]" ]
}
import os
import sys
from gettext import gettext
verify_start () {
local dialog_msg="<b><big>`gettext \"Persistence is disabled for Electrum\"`</big></b>
import sh
`gettext \"When you reboot Tails, all of Electrum's data will be lost, including your Bitcoin wallet. It is strongly recommended to only run Electrum when its persistence feature is activated.\"`
os.environ['TEXTDOMAIN'] = 'tails'
`gettext \"Do you want to start Electrum anyway?\"`
"
local launch="`gettext \"_Launch\"`"
local exit="`gettext \"_Exit\"`"
zenity --question --title "" --text "${dialog_msg}" --default-cancel \
--ok-label "${launch}" --cancel-label "${exit}"
}
HOME_DIR = os.environ['HOME']
CONF_DIR = os.path.join(HOME_DIR, '.electrum')
if ! electrum_config_is_persistent; then
verify_start || exit 0
fi
exec /usr/bin/electrum "${@}"
def main(*args):
if not electrum_config_is_persistent():
if not verify_start():
return
os.execv('/usr/bin/electrum', ['/usr/bin/electrum'] + list(args))
def electrum_config_is_persistent():
"""Return True iff electrum config is persistent.
>>> electrum_config_is_persistent()
False
"""
filesystem = sh.findmnt('--noheadings',
'--output', 'SOURCE',
'--target', CONF_DIR).stdout.decode().strip()
return filesystem in sh.glob('/dev/mapper/TailsData_unlocked[/electrum]')
def verify_start():
"""Ask user whether to start Electrum.
>>> verify_start() in (True, False)
True
"""
disabled_text = gettext('Persistence is disabled for Electrum')
warning_text = gettext(
"When you reboot Tails, all of Electrum's data will be lost, including your Bitcoin wallet. It is strongly recommended to only run Electrum when its persistence feature is activated.")
question_text = gettext('Do you want to start Electrum anyway?')
dialog_msg = ('<b><big>{}</big></b>\n\n{}\n\n{}\n'.
format(disabled_text, warning_text, question_text))
launch_text = gettext('_Launch')
exit_text = gettext('_Exit')
# results 0 == True; 1 == False; 5 == Timeout
results = sh.zenity('--question', '--title', '', '--default-cancel',
'--ok-label', launch_text,
'--cancel-label', exit_text,
'--text', dialog_msg,
_ok_code=[0,1,5])
start = results.exit_code == 0
return start
if __name__ == '__main__':
if len(sys.argv) > 1 and sys.argv[1] == 'doctest':
import doctest
doctest.testmod()
else:
main(*sys.argv[1:])
......@@ -86,6 +86,13 @@ try:
page = sys.argv[1]
except IndexError:
page = 'getting_started'
# If possible, let's hand-off to our website, which should be the most
# up-to-date option.
if os.system('/usr/local/sbin/tor-has-bootstrapped') == 0:
os.execv('/usr/local/bin/tor-browser',
['--new-tab', 'https://tails.boum.org/' + page])
wiki_path = '/usr/share/doc/tails/website'
lang_code = os.getenv('LANG', 'en')[0:2]
trials = [
......
#!/bin/sh
LIVE_IMAGE_MOUNTPOINT=/lib/live/mount/medium
for arg in $(cat /proc/cmdline) ; do
case "$arg" in
BOOT_IMAGE=*)
kernel="${arg#BOOT_IMAGE=}"
;;
initrd=*)
initrd="${arg#initrd=}"
;;
esac
done
# Sanity checks
[ -n "$kernel" ] || exit 4
[ -n "$initrd" ] || exit 5
case "$1" in
kernel)
echo "${LIVE_IMAGE_MOUNTPOINT}${kernel}"
;;
initrd)
echo "${LIVE_IMAGE_MOUNTPOINT}${initrd}"
;;
*)
echo "Usage: $0 kernel|initrd" >&2
exit 3
esac
exit 0
#! /usr/bin/env python3
"""
Get Tails boot info.
Test with "python3 tails-get-bootinfo.py doctest".
goodcrypto.com converted from bash to python and added basic tests.
>>> import sh
>>> sh.Command(sys.argv[0])('kernel')
/lib/live/mount/medium/live/vmlinuz
>>> sh.Command(sys.argv[0])('initrd')
/lib/live/mount/medium/live/initrd.img
>>> sh.Command(sys.argv[0])(_ok_code=(1))
Usage: tails-get-bootinfo kernel|initrd
<BLANKLINE>
"""
import sys
LIVE_IMAGE_MOUNTPOINT = '/lib/live/mount/medium'
def main(*args):
kernel = None
initrd = None
with open('/proc/cmdline') as f:
kernel_params = f.read().split()
for param in kernel_params:
if param.startswith('BOOT_IMAGE='):
kernel = param[len('BOOT_IMAGE='):]
elif param.startswith('initrd='):
initrd = param[len('initrd='):]
if not kernel or not initrd:
print('Failed to parse /proc/cmdline', file=sys.stderr)
sys.exit(1)
if 'kernel' in args:
print(LIVE_IMAGE_MOUNTPOINT + kernel, end="")
elif 'initrd' in args:
print(LIVE_IMAGE_MOUNTPOINT + initrd, end="")
else:
print('Usage: tails-get-bootinfo kernel|initrd', file=sys.stderr)
sys.exit(1)
if __name__ == "__main__":
if len(sys.argv) > 1 and sys.argv[1] == 'doctest':
import doctest
doctest.testmod()
elif len(sys.argv) == 2:
main(*sys.argv[1:])
else:
print('Usage: tails-get-bootinfo kernel|initrd', file=sys.stderr)
sys.exit(1)
#!/usr/bin/env python3
import logging
import socket
import sys
import gettext
import subprocess
from pydbus import SessionBus, SystemBus
import os
from pam import pam
import time
import pwd
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk, GLib
gi.require_version('Gdk', '3.0')
from gi.repository import Gdk
_ = gettext.gettext
gettext.textdomain("tails")
logging.basicConfig(level=logging.DEBUG)
mainloop = GLib.MainLoop()
def lock_screen():
# org.gnome.ScreenSaver.Lock() sometimes does not return, so we set a timeout of 5 seconds
try:
SessionBus().get("org.gnome.ScreenSaver").Lock(timeout=5)
except Exception as e:
logging.exception(e)
finally:
sys.exit()
class PasswordDialog(object):
def on_cancel_clicked(self, button, data=None):
sys.exit(1)
def on_entry_changed(self, entry, data=None):
if not self.entry1.get_text() or not self.entry2.get_text():
self.ok_button.set_sensitive(False)
elif self.entry1.get_text() == self.entry2.get_text():
# Passwords match
self.ok_button.set_sensitive(True)
self.entry2.set_icon_from_icon_name(1, None)
else:
# Passwords don't match
self.ok_button.set_sensitive(False)
self.entry2.set_icon_from_stock(1, "gtk-dialog-warning")
def on_ok_clicked(self, button, data=None):
pw1 = self.entry1.get_text()
pw2 = self.entry2.get_text()
if not pw1 == pw2:
return
self.pw = pw1.encode('ascii')
bus = SystemBus()
object_path = bus.get("org.freedesktop.Accounts").FindUserById(os.getuid())
user_object = bus.get("org.freedesktop.Accounts", object_path)
# lock the screen once the 'Changed' signal was received
user_object.Changed.connect(self.wait_until_password_set_and_lock_screen)
p = subprocess.Popen("passwd", stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
p.stdin.write(self.pw + b"\n")
p.stdin.write(self.pw)
p.stdin.flush()
out, err = p.communicate()
if p.returncode != 0:
print("passwd stdout: %s" % out)
print("passwd stderr: %s" % err)
raise RuntimeError("passwd returned %r" % p.returncode)
# We close the window here for the case that lock_screen does not return immediately,
# otherwise it would look like the app is unresponsive
self.window.close()
def on_key_pressed(self, widget, event):
if Gdk.keyval_name(event.keyval) == "Escape":
sys.exit(1)
if self.ok_button.get_sensitive() and Gdk.keyval_name(event.keyval) == "Return":
self.ok_button.clicked()
def wait_until_password_set_and_lock_screen(self):
# TODO: Remove this once this is fixed: https://bugzilla.gnome.org/show_bug.cgi?id=761969
p = pam()
while not p.authenticate(pwd.getpwuid(os.getuid()).pw_name, self.pw):
logging.debug("PAM not updated yet...")
time.sleep(0.01)
# We close the window here for the case that lock_screen does not return immediately,
# otherwise it would look like the app is unresponsive
self.window.close()
GLib.idle_add(lock_screen)
def run(self):
self.window.show()
def __init__(self):
self.pw = None
self.ok_button = Gtk.Button(
label=_("Lock Screen"),
receives_default=True,
sensitive=False,
width_request=86
)
self.ok_button.connect("clicked", self.on_ok_clicked)
self.ok_button.get_style_context().add_class('suggested-action')
cancel_button = Gtk.Button(
label=_("Cancel"),
width_request=86
)
cancel_button.connect("clicked", self.on_cancel_clicked)
headerbar = Gtk.HeaderBar(
title=_("Screen Locker"),
)
headerbar.pack_start(cancel_button)
headerbar.pack_end(self.ok_button)