Skip to content

Commit

Permalink
Generate qubes-guid options based on features
Browse files Browse the repository at this point in the history
Allow configuring options per VM or globally per GuiVM. The
qvm-start-daemon program reads the options from VM features, and
generates a configuration file for qubes-guid.

Requires QubesOS/qubes-gui-daemon#47 (customizing the configuration
file).
  • Loading branch information
pwmarcz committed Jun 25, 2020
1 parent ae39c75 commit 228fe85
Show file tree
Hide file tree
Showing 2 changed files with 130 additions and 1 deletion.
13 changes: 13 additions & 0 deletions doc/manpages/qvm-features.rst
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,19 @@ See also `gui` feature.
If neither `gui` nor `gui-emulated` is set, emulated VGA is used (if
applicable for given VM virtualization mode).

gui-\*, gui-default-\*
^^^^^^^^^^^^^^^^^^^^^^

GUI daemon configuration. See `/etc/qubes/guid.conf` for a list of supported
options.

To change a given GUI option for a specific qube, set the `gui-{option}`
feature (with underscores replaced with dashes). For example, to enable
`allow_utf8_titles` for a qube, set `gui-allow-utf8-titles` to `True`.

To change a given GUI option globally, set the `gui-default-{option}` feature
on the GuiVM for that qube.

qrexec
^^^^^^

Expand Down
118 changes: 117 additions & 1 deletion qubesadmin/tools/qvm_start_daemon.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# -*- encoding: utf8 -*-
# -*- encoding: utf-8 -*-
#
# The Qubes OS Project, http://www.qubes-os.org
#
Expand Down Expand Up @@ -49,6 +49,109 @@
PACAT_DAEMON_PATH = '/usr/bin/pacat-simple-vchan'
QUBES_ICON_DIR = '/usr/share/icons/hicolor/128x128/devices'

GUI_DAEMON_OPTIONS = [
('allow_fullscreen', 'bool'),
('override_redirect_protection', 'bool'),
('allow_utf8_titles', 'bool'),
('secure_copy_sequence', 'str'),
('secure_paste_sequence', 'str'),
('windows_count_limit', 'int'),
('trayicon_mode', 'str'),
('startup_timeout', 'int'),
]


def retrieve_gui_daemon_options(vm, guivm):
'''
Construct a list of GUI daemon options based on VM features.
This checks 'gui-*' features on the VM, and if they're absent,
'gui-default-*' features on the GuiVM.
'''

options = {}

for name, kind in GUI_DAEMON_OPTIONS:
feature_value = vm.features.get(
'gui-' + name.replace('_', '-'), None)
if feature_value is None:
feature_value = guivm.features.get(
'gui-default-' + name.replace('_', '-'), None)
if feature_value is None:
continue

if kind == 'bool':
value = bool(feature_value)
elif kind == 'int':
value = int(feature_value)
elif kind == 'str':
value = feature_value
else:
assert False, kind

options[name] = value
return options


def serialize_gui_daemon_options(options):
'''
Prepare configuration file content for GUI daemon. Currently uses libconfig
format.
'''

lines = [
'# Auto-generated file, do not edit!',
'',
'global: {',
]
for name, kind in GUI_DAEMON_OPTIONS:
if name in options:
value = options[name]
if kind == 'bool':
serialized = 'true' if value else 'false'
elif kind == 'int':
serialized = str(value)
elif kind == 'str':
serialized = escape_config_string(value)
else:
assert False, kind

lines.append(' {} = {};'.format(name, serialized))
lines.append('}')
lines.append('')
return '\n'.join(lines)


NON_ASCII_RE = re.compile(r'[^\x00-\x7F]')
UNPRINTABLE_CHARACTER_RE = re.compile(r'[\x00-\x1F\x7F]')

def escape_config_string(value):
'''
Convert a string to libconfig format.
Format specification:
http://www.hyperrealm.com/libconfig/libconfig_manual.html#String-Values
See dump_string() for python-libconf:
https://github.com/Grk0/python-libconf/blob/master/libconf.py
'''

assert not NON_ASCII_RE.match(value), 'expected an ASCII string: {!r}'.format(value)

value = (
value.replace('\\', '\\\\')
.replace('"', '\\"')
.replace('\f', r'\f')
.replace('\n', r'\n')
.replace('\r', r'\r')
.replace('\t', r'\t')
)
value = UNPRINTABLE_CHARACTER_RE.sub(
lambda m: r'\x{:02x}'.format(ord(m.group(0))),
value)
return '"' + value + '"'


# "LVDS connected 1024x768+0+0 (normal left inverted right) 304mm x 228mm"
REGEX_OUTPUT = re.compile(r"""
(?x) # ignore whitespace
Expand Down Expand Up @@ -262,6 +365,14 @@ def common_guid_args(self, vm):
if vm.features.check_with_template('rpc-clipboard', False):
guid_cmd.extend(['-Q'])

guivm = self.app.domains[self.app.local_name]
options = retrieve_gui_daemon_options(vm, guivm)
config = serialize_gui_daemon_options(options)
config_path = self.guid_config_file(vm.xid)
with open(config_path, 'w') as config_file:
config_file.write(config)
guid_cmd.extend(['-C', config_path])

guid_cmd += self.kde_guid_args(vm)
return guid_cmd

Expand All @@ -270,6 +381,11 @@ def guid_pidfile(xid):
"""Helper function to construct a GUI pidfile path"""
return '/var/run/qubes/guid-running.{}'.format(xid)

@staticmethod
def guid_config_file(xid):
"""Helper function to construct a GUI configuration file path"""
return '/var/run/qubes/guid-conf.{}'.format(xid)

@staticmethod
def pacat_pidfile(xid):
"""Helper function to construct an AUDIO pidfile path"""
Expand Down

0 comments on commit 228fe85

Please sign in to comment.