qubes-notify-tools 3.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  1. #!/usr/bin/python2
  2. import os
  3. import re
  4. import sys
  5. import subprocess
  6. from qubes.qubes import QubesVmCollection,QubesException,QubesHVm
  7. def main():
  8. source = os.getenv("QREXEC_REMOTE_DOMAIN")
  9. if source is None:
  10. print >> sys.stderr, 'This script must be called as qrexec service!'
  11. exit(1)
  12. prev_qrexec_installed = False
  13. source_vm = None
  14. qvm_collection = QubesVmCollection()
  15. qvm_collection.lock_db_for_writing()
  16. try:
  17. qvm_collection.load()
  18. source_vm = qvm_collection.get_vm_by_name(source)
  19. if source_vm is None:
  20. raise QubesException('Domain ' + source + ' does not exists (?!)')
  21. if not isinstance(source_vm, QubesHVm):
  22. raise QubesException('Service qubes.ToolsNotify is designed only for HVM domains')
  23. # for now used only to check for the tools presence
  24. untrusted_version = source_vm.qdb.read('/qubes-tools/version')
  25. # reserved for future use
  26. untrusted_os = source_vm.qdb.read('/qubes-tools/os')
  27. # qrexec agent presence (0 or 1)
  28. untrusted_qrexec = source_vm.qdb.read('/qubes-tools/qrexec')
  29. # gui agent presence (0 or 1)
  30. untrusted_gui = source_vm.qdb.read('/qubes-tools/gui')
  31. # default user for qvm-run etc
  32. untrusted_user = source_vm.qdb.read('/qubes-tools/default-user')
  33. if untrusted_version is None:
  34. # tools didn't advertised its features; it's strange that this
  35. # service is called, but ignore it
  36. return
  37. # any suspicious string will raise exception here
  38. version = int(untrusted_version)
  39. # untrusted_os - ignore for now
  40. if untrusted_qrexec is None:
  41. qrexec = 0
  42. else:
  43. qrexec = int(untrusted_qrexec)
  44. if untrusted_gui is None:
  45. gui = 0
  46. else:
  47. gui = int(untrusted_gui)
  48. if untrusted_user is not None and re.match(r'^[a-zA-Z0-9-]{1,255}$', untrusted_user):
  49. assert '@' not in untrusted_user
  50. assert '/' not in untrusted_user
  51. user = untrusted_user
  52. else:
  53. user = None
  54. prev_qrexec_installed = source_vm.qrexec_installed
  55. # Let the tools to be able to enable *or disable* each particular component
  56. source_vm.qrexec_installed = qrexec > 0
  57. source_vm.guiagent_installed = gui > 0
  58. if user is not None:
  59. source_vm.default_user = user
  60. qvm_collection.save()
  61. except Exception as e:
  62. print >> sys.stderr, e.message
  63. exit(1)
  64. finally:
  65. qvm_collection.unlock_db()
  66. if not prev_qrexec_installed and source_vm.qrexec_installed:
  67. retcode = subprocess.call(['qvm-sync-appmenus', '--force-rpc'])
  68. if retcode == 0 and hasattr(source_vm, 'appmenus_recreate'):
  69. # TODO: call the same for child VMs? This isn't done for Linux VMs,
  70. # so probably should be ignored for Windows also
  71. source_vm.appmenus_recreate()
  72. main()