#!/usr/bin/python2 import os import re import sys import subprocess from qubes.qubes import QubesVmCollection,QubesException,QubesHVm def main(): source = os.getenv("QREXEC_REMOTE_DOMAIN") if source is None: print >> sys.stderr, 'This script must be called as qrexec service!' exit(1) prev_qrexec_installed = False source_vm = None qvm_collection = QubesVmCollection() qvm_collection.lock_db_for_writing() try: qvm_collection.load() source_vm = qvm_collection.get_vm_by_name(source) if source_vm is None: raise QubesException('Domain ' + source + ' does not exists (?!)') if not isinstance(source_vm, QubesHVm): raise QubesException('Service qubes.ToolsNotify is designed only for HVM domains') # for now used only to check for the tools presence untrusted_version = source_vm.qdb.read('/qubes-tools/version') # reserved for future use untrusted_os = source_vm.qdb.read('/qubes-tools/os') # qrexec agent presence (0 or 1) untrusted_qrexec = source_vm.qdb.read('/qubes-tools/qrexec') # gui agent presence (0 or 1) untrusted_gui = source_vm.qdb.read('/qubes-tools/gui') # default user for qvm-run etc untrusted_user = source_vm.qdb.read('/qubes-tools/default-user') if untrusted_version is None: # tools didn't advertised its features; it's strange that this # service is called, but ignore it return # any suspicious string will raise exception here version = int(untrusted_version) # untrusted_os - ignore for now if untrusted_qrexec is None: qrexec = 0 else: qrexec = int(untrusted_qrexec) if untrusted_gui is None: gui = 0 else: gui = int(untrusted_gui) if untrusted_user is not None and re.match(r'^[a-zA-Z0-9-]{1,255}$', untrusted_user): assert '@' not in untrusted_user assert '/' not in untrusted_user user = untrusted_user else: user = None prev_qrexec_installed = source_vm.qrexec_installed # Let the tools to be able to enable *or disable* each particular component source_vm.qrexec_installed = qrexec > 0 source_vm.guiagent_installed = gui > 0 if user is not None: source_vm.default_user = user qvm_collection.save() except Exception as e: print >> sys.stderr, e.message exit(1) finally: qvm_collection.unlock_db() if not prev_qrexec_installed and source_vm.qrexec_installed: retcode = subprocess.call(['qvm-sync-appmenus', '--force-rpc']) if retcode == 0 and hasattr(source_vm, 'appmenus_recreate'): # TODO: call the same for child VMs? This isn't done for Linux VMs, # so probably should be ignored for Windows also source_vm.appmenus_recreate() main()