firstboot: disable USB qube option when USB keyboard or disk is present

For keyboard is not totally imposibble to use it with USB qube, but it's
somehow harder to setup (and if something goes wrong, no keyboard will
be available). But currently if booted from USB disk, it is imposible to
work with USB qube then.

At the some time, slightly rework QubesChoice external conditions - have
them checked outside of the object, which make it easier to have
different message when such option is not available (and why).

Fixes QubesOS/qubes-issues#1649
Fixes QubesOS/qubes-issues#1630
This commit is contained in:
Marek Marczykowski-Górecki 2016-02-05 02:40:02 +01:00
parent 2838da02cf
commit dc1374cd95
No known key found for this signature in database
GPG Key ID: 063938BA42CFA724
2 changed files with 59 additions and 14 deletions

View File

@ -34,6 +34,7 @@ Requires(preun): systemd-units
Requires(postun): systemd-units
Requires: firstboot(windowmanager)
Requires: libreport-python
Requires: python-pyudev
Requires: qubes-artwork
Requires: qubes-mgmt-salt-dom0

View File

@ -36,6 +36,8 @@ from firstboot.functions import *
from firstboot.module import *
import gettext
import pyudev
_ = lambda x: gettext.ldgettext("firstboot", x)
N_ = lambda x: x
@ -44,6 +46,37 @@ def is_package_installed(pkgname):
return not subprocess.call(['rpm', '-q', pkgname],
stdout=open(os.devnull, 'w'), stderr=open(os.devnull, 'w'))
def usb_keyboard_present():
context = pyudev.Context()
keyboards = context.list_devices(subsystem='input', ID_INPUT_KEYBOARD='1')
return any([d.get('ID_USB_INTERFACES', False) for d in keyboards])
def started_from_usb():
def get_all_used_devices(dev):
stat = os.stat(dev)
if stat.st_rdev:
# XXX any better idea how to handle device-mapper?
sysfs_slaves = '/sys/dev/block/{}:{}/slaves'.format(
os.major(stat.st_rdev), os.minor(stat.st_rdev))
if os.path.exists(sysfs_slaves):
for slave_dev in os.listdir(sysfs_slaves):
for d in get_all_used_devices('/dev/{}'.format(slave_dev)):
yield d
else:
yield dev
context = pyudev.Context()
mounts = open('/proc/mounts').readlines()
for mount in mounts:
device = mount.split(' ')[0]
if not os.path.exists(device):
continue
for dev in get_all_used_devices(device):
udev_info = pyudev.Device.from_device_file(context, dev)
if udev_info.get('ID_USB_INTERFACES', False):
return True
return False
class QubesChoice(object):
instances = []
@ -74,9 +107,7 @@ class QubesChoice(object):
def set_sensitive(self, sensitive):
self.widget.set_sensitive(sensitive
and (self.extra_check is None or self.extra_check()))
self.widget.set_sensitive(sensitive)
@classmethod
def on_check_advanced_toggled(cls, widget):
@ -97,6 +128,12 @@ class QubesChoice(object):
yield state
class DisabledChoice(QubesChoice):
def __init__(self, label):
super(DisabledChoice, self).__init__(label, ())
self.widget.set_sensitive(False)
class moduleClass(Module):
def __init__(self):
Module.__init__(self)
@ -318,13 +355,15 @@ class moduleClass(Module):
('qvm.personal', 'qvm.work', 'qvm.untrusted', 'qvm.vault'),
depend=self.choice_network)
self.choice_whonix = QubesChoice(
_('Create Whonix Gateway and Workstation qubes '
'(sys-whonix, anon-whonix)'),
('qvm.sys-whonix', 'qvm.anon-whonix'),
depend=self.choice_network,
extra_check=lambda: is_package_installed('qubes-template-whonix-gw')
and is_package_installed('qubes-template-whonix-ws'))
if is_package_installed('qubes-template-whonix-gw') and \
is_package_installed('qubes-template-whonix-ws'):
self.choice_whonix = QubesChoice(
_('Create Whonix Gateway and Workstation qubes '
'(sys-whonix, anon-whonix)'),
('qvm.sys-whonix', 'qvm.anon-whonix'),
depend=self.choice_network)
else:
self.choice_whonix = DisabledChoice(_("Whonix not installed"))
self.choice_whonix_default = QubesChoice(
_('Route applications traffic and updates through Tor anonymity '
@ -332,10 +371,15 @@ class moduleClass(Module):
(),
depend=self.choice_whonix)
self.choice_usb = QubesChoice(
_('Create USB qube holding all USB controllers (sys-usb) '
'[experimental]'),
('qvm.sys-usb',))
if not usb_keyboard_present() and not started_from_usb():
self.choice_usb = QubesChoice(
_('Create USB qube holding all USB controllers (sys-usb) '
'[experimental]'),
('qvm.sys-usb',))
else:
self.choice_usb = DisabledChoice(
_('USB qube configuration disabled - you are using USB '
'keyboard or USB disk'))
self.check_advanced = gtk.CheckButton(
_('Do not configure anything (for advanced users)'))