Commit 49c079f7 authored by anonym's avatar anonym
Browse files

Merge remote-tracking branch 'origin/web/release-4.24'

parents 9e75753d afc279cc
......@@ -78,7 +78,8 @@ test-iuk:
gnutls-bin
libdata-dumper-concise-perl
libdatetime-perl
libfile-copy-recursive-perl'
libfile-copy-recursive-perl
libtest-lwp-useragent-perl'
- apt-get update -qq # Take into account APT configuration added by apt-file
# Otherwise, apt-get called by "dzil authordebs --install" asks confirmation
- echo 'APT::Get::Assume-Yes "true";' > /etc/apt/apt.conf.d/yes
......
......@@ -116,6 +116,9 @@ Style/HashTransformValues:
Style/HashSyntax:
EnforcedStyle: ruby19_no_mixed_keys
Style/IfUnlessModifier:
Enabled: false
Style/MethodCallWithArgsParentheses:
Enabled: true
IgnoredMethods:
......
......@@ -271,7 +271,7 @@ task :parse_build_options do
warn "Building a release ⇒ ignoring #{opt} build option"
ENV['MKSQUASHFS_OPTIONS'] = nil
else
ENV['MKSQUASHFS_OPTIONS'] = '-comp xz -no-exports'
ENV['MKSQUASHFS_OPTIONS'] = '-comp zstd -no-exports'
end
when 'defaultcomp'
ENV['MKSQUASHFS_OPTIONS'] = nil
......
......@@ -20,7 +20,7 @@ AMNESIA_APPEND="live-media=removable nopersistence noprompt timezone=Etc/UTC spl
AMNESIA_ISOHYBRID_OPTS="-h 255 -s 63 --id 42 --verbose"
# Kernel version
KERNEL_VERSION='5.10.0-8'
KERNEL_VERSION='5.10.0-9'
KERNEL_SOURCE_VERSION=$(
echo "$KERNEL_VERSION" \
| perl -p -E 's{\A (\d+ [.] \d+) [.] .*}{$1}xms'
......
This diff is collapsed.
......@@ -11,6 +11,11 @@ Package: electrum python3-electrum python3-aiohttp-socks python3-aiorpcx python3
Pin: release o=Debian,n=bullseye
Pin-Priority: 999
Explanation: unavailable in Buster
Package: electrum python3-electrum python3-aiohttp-socks python3-aiorpcx python3-ecdsa
Pin: release o=Debian,n=bullseye-security
Pin-Priority: 999
Explanation: Electrum needs a version newer than the one in Buster
Package: python3-attr python3-protobuf libprotobuf23
Pin: release o=Debian,n=buster-backports
......@@ -31,6 +36,11 @@ Package: python3-btchip
Pin: release o=Debian,n=bullseye
Pin-Priority: 999
Explanation: Electrum 4.0.2 needs >= 0.1.30
Package: python3-btchip
Pin: release o=Debian,n=bullseye-security
Pin-Priority: 999
Package: firmware-b43-installer
Pin: release o=Debian,n=sid
Pin-Priority: 999
......@@ -48,11 +58,6 @@ Package: firmware-linux firmware-linux-nonfree firmware-amd-graphics firmware-at
Pin: release o=Debian,n=sid
Pin-Priority: 990
Explanation: freeze exception (#18556)
Package: firmware-linux firmware-linux-nonfree firmware-amd-graphics firmware-atheros firmware-brcm80211 firmware-intel-sound firmware-ipw2x00 firmware-iwlwifi firmware-libertas firmware-misc-nonfree firmware-realtek firmware-ti-connectivity
Pin: origin deb.tails.boum.org
Pin-Priority: 999
Package: firmware-sof-signed
Pin: release o=Debian,n=sid
Pin-Priority: 999
......@@ -66,6 +71,11 @@ Package: grub*
Pin: release o=Debian,n=bullseye
Pin-Priority: 999
Explanation: install 2.04 (refs: #15806)
Package: grub*
Pin: release o=Debian,n=bullseye-security
Pin-Priority: 999
Explanation: We want to set default database directory to ~/Persistent, which
Explanation: is only possible since 2.4.0, which is unavailable in Buster.
Package: keepassxc
......@@ -73,7 +83,11 @@ Pin: release o=Debian,n=buster-backports
Pin-Priority: 999
Package: linux-compiler-* linux-headers-* linux-image-* linux-kbuild-* linux-source-*
Pin: release o=Debian,n=sid
Pin: release o=Debian,n=bullseye
Pin-Priority: 999
Package: linux-compiler-* linux-headers-* linux-image-* linux-kbuild-* linux-source-*
Pin: release o=Debian,n=bullseye-security
Pin-Priority: 999
Explanation: src:live-boot (#15477)
......@@ -89,17 +103,34 @@ Package: onionshare
Pin: release o=Debian,n=bullseye
Pin-Priority: 999
Package: onionshare
Pin: release o=Debian,n=bullseye-security
Pin-Priority: 999
Package: python3-dogtail
Pin: release o=Debian,n=bullseye
Pin-Priority: 999
Package: python3-dogtail
Pin: release o=Debian,n=bullseye-security
Pin-Priority: 999
Explanation: #18464
Package: shim*
Pin: release o=Debian,n=bullseye
Pin-Priority: 999
Package: squashfs-tools
Pin: release o=Debian,n=sid
Explanation: #18464
Package: shim*
Pin: release o=Debian,n=bullseye-security
Pin-Priority: 999
Package: squashfs-tools libzstd1
Pin: release o=Debian,n=bullseye
Pin-Priority: 999
Package: squashfs-tools libzstd1
Pin: release o=Debian,n=bullseye-security
Pin-Priority: 999
Package: virtualbox*
......
......@@ -252,7 +252,7 @@ class TailsInstallerCreator(object):
self.log.debug(pformat(data))
if not force_partitions and self.opts.partition:
if self.device_can_be_upgraded(data):
if self.device_can_be_upgraded(data) or data['fstype'] == 'crypto_LUKS':
self.drives[data['device']] = data
# Add whole drive in partitioning mode
elif data['parent'] is None:
......
......@@ -432,19 +432,6 @@ class TailsInstallerWindow(Gtk.ApplicationWindow):
def add_devices():
self.__liststore_target.clear()
if not len(self.live.drives):
self.__infobar.set_message_type(Gtk.MessageType.INFO)
self.__label_infobar_title.set_text(
_('No device suitable to install Tails could be found'))
self.__label_infobar_details.set_text(
_('Please plug a USB flash drive or SD card of at least %0.1f GB.')
% (CONFIG['official_min_installation_device_size'] / 1000.))
self.__infobar.set_visible(True)
self.target_available = False
self.update_start_button()
return
else:
self.__infobar.set_visible(False)
self.live.log.debug('drives: %s' % self.live.drives)
target_list = []
self.devices_with_persistence = []
......@@ -502,11 +489,23 @@ class TailsInstallerWindow(Gtk.ApplicationWindow):
continue
target_list.append([pretty_name, device])
if len(target_list):
self.__infobar.set_visible(False)
for target in target_list:
self.__liststore_target.append(target)
self.target_available = True
self.__combobox_target.set_active(0)
self.update_start_button()
else:
self.__infobar.set_message_type(Gtk.MessageType.INFO)
self.__label_infobar_title.set_text(
_('No device suitable to install Tails could be found'))
self.__label_infobar_details.set_text(
_('Please plug a USB flash drive or SD card of at least %0.1f GB.')
% (CONFIG['official_min_installation_device_size'] / 1000.))
self.__infobar.set_visible(True)
self.target_available = False
self.update_start_button()
return
try:
self.live.detect_supported_drives(callback=add_devices)
......@@ -584,6 +583,8 @@ class TailsInstallerWindow(Gtk.ApplicationWindow):
if not warning:
dialog.add_button(_('Cancel'), Gtk.ResponseType.CANCEL)
dialog.add_button(label_string, Gtk.ResponseType.YES)
ok_button = dialog.get_widget_for_response(response_id=Gtk.ResponseType.YES)
Gtk.StyleContext.add_class(ok_button.get_style_context(),'destructive-action')
reply = dialog.run()
dialog.hide()
if reply == Gtk.ResponseType.YES:
......@@ -624,57 +625,47 @@ class TailsInstallerWindow(Gtk.ApplicationWindow):
if self.opts.partition:
if not self.confirmed:
if self.show_confirmation_dialog(
_('Confirm the target USB stick'),
_('%(size)s %(vendor)s %(model)s device (%(device)s)\n\n'
'All data on this USB stick will be lost.') %
{'vendor': self.live.drive['vendor'],
'model': self.live.drive['model'],
'device': self.live.drive['device'],
'size': _format_bytes_in_gb(self.live.drive['parent_size']
if self.live.drive['parent_size']
else self.live.drive['size'])},
False,
label_string=_('Install')):
description = _('%(parent_size)s %(vendor)s %(model)s device (%(device)s)') % {
'vendor': self.live.drive['vendor'],
'model': self.live.drive['model'],
'device': self.live.drive['device'],
'parent_size': _format_bytes_in_gb(self.live.drive['parent_size']
if self.live.drive['parent_size']
else self.live.drive['size'])
}
if self.live.drive['parent'] in self.devices_with_persistence:
delete_message = _('\n\nThe persistent storage on this USB stick will be lost.')
confirmation_label = _('Delete Persistent Storage and Reinstall')
else:
delete_message = _('\n\nAll data on this USB stick will be lost.')
confirmation_label = _('Delete All Data and Install')
msg = _('%(description)s%(delete_message)s') % {
'description': description,
'delete_message': delete_message,
}
if self.show_confirmation_dialog(_('Confirm the target USB stick'),
msg, False,confirmation_label):
self.confirmed = True
else:
if self.force_reinstall_button_available:
self.force_reinstall = False
self.opts.partition = False
return
else:
# The user has confirmed that they wish to partition their device,
# let's go on
self.confirmed = False
else:
description = _('%(parent_size)s %(vendor)s %(model)s device (%(device)s)') % {
'vendor': self.live.drive['vendor'],
'model': self.live.drive['model'],
'device': self.live.drive['device'],
'parent_size': _format_bytes_in_gb(self.live.drive['parent_size']),
}
persistence_message = ''
if self.devices_with_persistence:
persistence_message = _('\n\nThe persistent storage on this USB stick will be preserved.')
msg = _('%(description)s%(persistence_message)s') % {
'description': description,
'persistence_message': persistence_message,
}
if self.show_confirmation_dialog(_('Confirm the target USB stick'),
msg, False, label_string=_('Upgrade')):
# The user has confirmed that they wish to overwrite their
# existing Live OS. Here we delete it first, in order to
# accurately calculate progress.
self.delete_existing_liveos_confirmed = False
try:
self.live.delete_liveos()
except TailsInstallerError as ex:
self.status(ex.args[0])
# self.live.unmount_device()
self.enable_widgets(True)
return
else:
self.delete_existing_liveos_confirmed = False
try:
self.live.delete_liveos()
except TailsInstallerError as ex:
self.status(ex.args[0])
# self.live.unmount_device()
self.enable_widgets(True)
return
# Remove the log handler, because our live thread will register its own
......
import sh
import os.path
from logging import getLogger
import subprocess
log = getLogger(os.path.basename(__file__))
import sh
def systemd_ready():
try:
# XXX: discard stdout/stderr
subprocess.Popen(["systemd-notify", "--ready"])
except FileNotFoundError:
# systemd not installed
pass
else:
log.info("systemd was notified")
log = getLogger(os.path.basename(__file__))
def tor_has_bootstrapped() -> bool:
......
......@@ -107,7 +107,6 @@ class TCAApplication(Gtk.Application):
def check_tor_state(self, repeat: bool):
# this is called periodically
# XXX: change with proper notification handling from tor daemon itself
changed = set()
for infokey in ["DisableNetwork"]:
resp = self.controller.get_conf(infokey)
......
......@@ -545,12 +545,8 @@ class TorLauncherNetworkUtils:
It does NOT care if we're really connected to the Internet
"""
# XXX: does it do the right thing? we should check!
try:
subprocess.check_call(["nm-online", "-xq"])
return True
except subprocess.CalledProcessError:
return False
# nm-online -xq could be what we need
raise NotImplementedError()
def is_internet_up(self):
"""
......
import os
from typing import Dict, List, Callable, Optional
import socket
from logging import getLogger
import gi
from tinyrpc.protocols.jsonrpc import JSONRPCProtocol
......@@ -11,6 +12,7 @@ gi.require_version("GLib", "2.0")
from gi.repository import GObject # noqa: E402
from gi.repository import GLib # noqa: E402
log = getLogger('asyncutils')
class GJsonRpcClient(GObject.GObject):
"""
......@@ -56,7 +58,7 @@ class GJsonRpcClient(GObject.GObject):
def call_async(self, method: str, callback: Optional[Callable], *args, **kwargs):
req = self.protocol.create_request(method, args, kwargs)
print('call async', req.unique_id)
log.debug('call async %s %s %s %d', method, args, kwargs, req.unique_id)
if callback is not None:
self.connect('response::%d' % req.unique_id, callback)
output = req.serialize() + "\n"
......
import datetime
from typing import Optional
from typing import Optional, List, Dict
from logging import getLogger
from collections import defaultdict
import pytz
import gi
from tailsgreeter.ui.popover import Popover
import tca.config
gi.require_version("Gdk", "3.0")
gi.require_version("Gtk", "3.0")
gi.require_version("GLib", "2.0")
gi.require_version("Pango", "1.0")
from gi.repository import Gdk, GdkPixbuf, Gtk, GLib # noqa: E402
from gi.repository import Gdk, GdkPixbuf, Gtk, GLib, Pango # noqa: E402
log = getLogger('dialogs')
def get_tz_model():
store = Gtk.ListStore(str)
for tz in pytz.common_timezones:
store.append([tz])
return store
log = getLogger("dialogs")
def get_time_dialog(initial_tz: Optional[str] = None):
......@@ -28,25 +25,14 @@ def get_time_dialog(initial_tz: Optional[str] = None):
builder.set_translation_domain("tails")
builder.add_from_file(tca.config.data_path + "time-dialog.ui")
time_dialog = builder.get_object("dialog") # noqa: N806
tz_model = get_tz_model()
select_tz = builder.get_object("select_tz")
select_tz.set_model(tz_model)
if initial_tz:
for row in tz_model:
if row[0] == initial_tz:
select_tz.set_active_iter(row.iter)
break
else:
log.warning("Cannot find user-selected timezone %s", initial_tz)
renderer_text = Gtk.CellRendererText()
select_tz.pack_start(renderer_text, True)
select_tz.add_attribute(renderer_text, "text", 0)
select_tz.set_entry_text_column(0)
builder.get_object('listbox_tz_label_value').set_text(initial_tz)
popover = TimezonePopover(builder, builder.get_object('listbox_tz_label_value'))
DEFAULT_TIMEZONE = 'UTC (Greenwich time)'
def get_tz_name(_=None):
return tz_model.get_value(select_tz.get_active_iter(), 0)
return builder.get_object('listbox_tz_label_value').get_text()
# return tz_model.get_value(select_tz.get_active_iter(), 0)
def get_date(_=None):
spec = {
......@@ -55,10 +41,21 @@ def get_time_dialog(initial_tz: Optional[str] = None):
}
spec["month"] = int(builder.get_object("select_month").get_active_id())
naive_dt = datetime.datetime(**spec)
tz = pytz.timezone(get_tz_name())
tz_name = get_tz_name()
if tz_name == DEFAULT_TIMEZONE:
tz_name = 'UTC'
tz = pytz.timezone(tz_name)
aware_dt = tz.localize(naive_dt)
return aware_dt
def cb_listbox_tz_clicked(*args):
def on_close(popover, tzpopover):
if tzpopover.value_changed_by_user:
builder.get_object('listbox_tz_label_value').set_text(tzpopover.value)
check_input_valid()
popover.popover.open(on_close, popover)
time_dialog.get_date = get_date
time_dialog.get_tz_name = get_tz_name
......@@ -69,9 +66,7 @@ def get_time_dialog(initial_tz: Optional[str] = None):
Let Apply be sensitive accordingly
"""
def is_valid():
if not select_tz.get_active_iter():
return False
if not tz_model.get_value(select_tz.get_active_iter(), 0):
if not time_dialog.get_tz_name():
return False
try:
# checks if the date is correct (ie: what about February 31?)
......@@ -99,7 +94,7 @@ def get_time_dialog(initial_tz: Optional[str] = None):
builder.get_object(spin).set_numeric(True)
builder.get_object(spin).set_increments(1, 6)
for obj in ["hour", "minute", "day", "year", "select_month", "select_tz"]:
for obj in ["hour", "minute", "day", "year", "select_month"]:
builder.get_object(obj).connect("changed", check_input_valid)
builder.get_object("btn_cancel").connect(
......@@ -109,4 +104,132 @@ def get_time_dialog(initial_tz: Optional[str] = None):
"clicked", lambda *_: time_dialog.response(Gtk.ResponseType.APPLY)
)
builder.get_object('listbox_tz').connect("row-activated", cb_listbox_tz_clicked)
return time_dialog
class TimezonePopover:
def _create_tz_store(self) -> Gtk.TreeStore:
self.treestore = Gtk.TreeStore(str)
timezones = pytz.common_timezones
timezone_tree: Dict[List[str]] = defaultdict(list)
toplevel_timezones: List[str] = []
for tz in timezones:
if "/" not in tz: # GMT and UTC
toplevel_timezones.append(tz)
else: # everything else
region, city = tz.split("/", 1)
timezone_tree[region].append(tz)
for region in sorted(timezone_tree):
regioniter = self.treestore.append(parent=None, row=[region])
for city in sorted(timezone_tree[region]):
self.treestore.append(parent=regioniter, row=[city])
for tz in toplevel_timezones:
self.treestore.append(parent=None, row=[tz])
def __init__(self, builder, relative_to):
self.id = "tz"
self.builder = builder
self.relative_to = relative_to
self._create_tz_store()
self.value_changed_by_user = False
popover_box = self.builder.get_object("box_{}_popover".format(self.id))
self.popover = Popover(self.relative_to, popover_box)
self.popover.widget.set_constrain_to(Gtk.PopoverConstraint.NONE)
self.popover.widget.set_position(Gtk.PositionType.RIGHT)
self.treeview = self.builder.get_object("treeview_{}".format(self.id))
self.treeview.connect("row-activated", self.cb_treeview_row_activated)
# Fill the treeview
renderer = Gtk.CellRendererText()
renderer.props.ellipsize = Pango.EllipsizeMode.END
column = Gtk.TreeViewColumn("", renderer, text=0)
self.treeview.append_column(column)
searchentry = self.builder.get_object("searchentry_{}".format(self.id))
searchentry.connect("search-changed", self.cb_searchentry_search_changed)
searchentry.connect("activate", self.cb_searchentry_activate)
self.treestore_filtered = self.treestore.filter_new()
self.treestore_filtered.set_visible_func(
self.cb_liststore_filtered_visible_func, data=searchentry
)
self.treeview.set_model(self.treestore_filtered)
def cb_searchentry_activate(self, searchentry, user_data=None):
"""Select the topmost item in the treeview when pressing Enter."""
if not searchentry.get_text():
self.popover.close(Gtk.ResponseType.CANCEL)
return
store = self.treestore_filtered
first_item_iter: Gtk.TreeIter = store.get_iter_first()
if first_item_iter is None: # store is empty
return
# Right now, this is always true. But if we add UTC again,
# then this could fail, so let's have this check
if store.iter_has_child(first_item_iter):
first_item_iter = store.iter_nth_child(first_item_iter, 0)
first_item_path: Gtk.TreePath = store.get_path(first_item_iter)
self.treeview.row_activated(
first_item_path, self.treeview.get_column(0)
)
def cb_searchentry_search_changed(self, searchentry, user_data=None):
self.treestore_filtered.refilter()
if searchentry.get_text():
self.treeview.expand_all()
self.treeview.scroll_to_point(0, 0) # scroll to top
else:
self.treeview.collapse_all()
return False
def cb_treeview_row_activated(self, treeview, path, column, user_data=None):
treemodel = treeview.get_model()
treeiter = treemodel.get_iter(path)
if treemodel.iter_parent(treeiter) is None: # is top-level
if (
treemodel.iter_children(treeiter) is not None
): # has children: it is a region
# user cannot select a parent node like "Europe", because that's not a timezone
# XXX: expand/collapse this row would probably be better UX
return
self.value = treemodel.get_value(treeiter, 0)
self.value_changed_by_user = True
self.popover.close(Gtk.ResponseType.YES)
def cb_liststore_filtered_visible_func(self, model, treeiter, searchentry):
search_query = searchentry.get_text().replace(' ', '_').lower()
value = model.get_value(treeiter, 0)
def matcher(v: str):
return search_query in v.lower()
if not search_query: # display everything
return True