wni.py 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. #!/usr/bin/python2
  2. #
  3. # The Qubes OS Project, http://www.qubes-os.org
  4. #
  5. # Copyright (C) 2013 Marek Marczykowski <marmarek@invisiblethingslab.com>
  6. #
  7. # This program is free software; you can redistribute it and/or
  8. # modify it under the terms of the GNU General Public License
  9. # as published by the Free Software Foundation; either version 2
  10. # of the License, or (at your option) any later version.
  11. #
  12. # This program is distributed in the hope that it will be useful,
  13. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. # GNU General Public License for more details.
  16. #
  17. # You should have received a copy of the GNU General Public License
  18. # along with this program; if not, write to the Free Software
  19. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  20. #
  21. #
  22. from __future__ import absolute_import
  23. import sys
  24. import os
  25. import os.path
  26. import win32api
  27. import win32net
  28. import win32netcon
  29. import win32security
  30. import win32profile
  31. import pywintypes
  32. import random
  33. from qubes.storage import QubesVmStorage
  34. from qubes.qubes import QubesException,system_path
  35. class QubesWniVmStorage(QubesVmStorage):
  36. """
  37. Class for VM storage of WNI VMs.
  38. """
  39. def __init__(self, *args, **kwargs):
  40. super(QubesWniVmStorage, self).__init__(*args, **kwargs)
  41. # Use the user profile as "private.img"
  42. self.home_root = win32profile.GetProfilesDirectory()
  43. # FIXME: the assignment below may not always be correct,
  44. # but GetUserProfileDirectory needs a user token...
  45. self.private_img = os.path.join(self.home_root, self._get_username())
  46. # Pass paths for WNI libvirt driver
  47. os.putenv("WNI_DRIVER_QUBESDB_PATH", system_path['qubesdb_daemon_path'])
  48. os.putenv("WNI_DRIVER_QREXEC_AGENT_PATH", system_path['qrexec_agent_path'])
  49. def _get_username(self, vmname = None):
  50. if vmname is None:
  51. vmname = self.vm.name
  52. return "qubes-vm-%s" % vmname
  53. def _get_random_password(self, vmname = None):
  54. if vmname is None:
  55. vmname = self.vm.name
  56. return '%x' % random.SystemRandom().getrandombits(256)
  57. def get_config_params(self):
  58. return {}
  59. def create_on_disk_private_img(self, verbose, source_template = None):
  60. # FIXME: this may not always be correct
  61. home_dir = os.path.join(self.home_root, self._get_username())
  62. # Create user data in information level 1 (PyUSER_INFO_1) format.
  63. user_data = {}
  64. user_data['name'] = self._get_username()
  65. user_data['full_name'] = self._get_username()
  66. # libvirt driver doesn't need to know the password anymore
  67. user_data['password'] = self._get_random_password()
  68. user_data['flags'] = (
  69. win32netcon.UF_NORMAL_ACCOUNT |
  70. win32netcon.UF_SCRIPT |
  71. win32netcon.UF_DONT_EXPIRE_PASSWD |
  72. win32netcon.UF_PASSWD_CANT_CHANGE
  73. )
  74. user_data['priv'] = win32netcon.USER_PRIV_USER
  75. user_data['home_dir'] = home_dir
  76. user_data['max_storage'] = win32netcon.USER_MAXSTORAGE_UNLIMITED
  77. # TODO: catch possible exception
  78. win32net.NetUserAdd(None, 1, user_data)
  79. def create_on_disk_root_img(self, verbose, source_template = None):
  80. pass
  81. def remove_from_disk(self):
  82. try:
  83. sid = win32security.LookupAccountName(None, self._get_username())[0]
  84. string_sid = win32security.ConvertSidToStringSid(sid)
  85. win32profile.DeleteProfile(string_sid)
  86. win32net.NetUserDel(None, self._get_username())
  87. except pywintypes.error, details:
  88. if details[0] == 2221:
  89. # "The user name cannot be found."
  90. raise IOError("User %s doesn't exist" % self._get_username())
  91. else:
  92. raise
  93. super(QubesWniVmStorage, self).remove_from_disk()
  94. def rename(self, old_name, new_name):
  95. super(QubesWniVmStorage, self).rename(old_name, new_name)
  96. user_data = {}
  97. user_data['name'] = self._get_username(new_name)
  98. win32net.NetUserSetInfo(None,
  99. self._get_username(old_name), 0, user_data)
  100. #TODO: rename user profile
  101. def verify_files(self):
  102. if not os.path.exists (self.vmdir):
  103. raise QubesException (
  104. "VM directory doesn't exist: {0}".\
  105. format(self.vmdir))
  106. try:
  107. # TemplateVm in WNI is quite virtual, so do not require the user
  108. if not self.vm.is_template():
  109. win32net.NetUserGetInfo(None, self._get_username(), 0)
  110. except pywintypes.error, details:
  111. if details[0] == 2221:
  112. # "The user name cannot be found."
  113. raise QubesException("User %s doesn't exist" % self._get_username())
  114. else:
  115. raise
  116. def reset_volatile_storage(self, verbose = False, source_template = None):
  117. pass
  118. def prepare_for_vm_startup(self, verbose = False):
  119. if self.vm.is_template():
  120. raise QubesException("Starting TemplateVM is not supported")