Ejemplo n.º 1
0
    def __init__(self, **kwargs):
        super(QubesNetVm, self).__init__(**kwargs)
        self.connected_vms = QubesVmCollection()

        self.__network = "10.137.{0}.0".format(self.netid)
        self.__netmask = defaults["vm_default_netmask"]
        self.__gateway = self.netprefix + "1"
        self.__secondary_dns = self.netprefix + "254"

        self.__external_ip_allowed_xids = set()

        self.log.debug('network={} netmask={} gateway={} secondary_dns={}'.format(
            self.network, self.netmask, self.gateway, self.secondary_dns))
Ejemplo n.º 2
0
def main():

    global qubes_host
    qubes_host = QubesHost()

    global app
    app = QApplication(sys.argv)
    app.setOrganizationName("The Qubes Project")
    app.setOrganizationDomain("http://qubes-os.org")
    app.setApplicationName("Qubes VM Settings")

    sys.excepthook = handle_exception

    qvm_collection = QubesVmCollection()
    qvm_collection.lock_db_for_reading()
    qvm_collection.load()
    qvm_collection.unlock_db()

    vm = None
    tab = "basic"

    if len(sys.argv) > 1:
        vm = qvm_collection.get_vm_by_name(sys.argv[1])
        if vm is None or vm.qid not in qvm_collection:
            QMessageBox.critical(None, "Qubes VM Settings Error",
                    "A VM with the name '{0}' does not exist in the system.".format(sys.argv[1]))
            sys.exit(1)
        if len(sys.argv) > 2:
            tab_arg = sys.argv[2]
            print tab_arg
            if tab_arg in VMSettingsWindow.tabs_indices:
                tab = tab_arg
            else: QMessageBox.warning(None, "Qubes VM Settings Error",
                    "There is no such tab as '{0}'. Opening default tab instead.".format(tab_arg))

    else:
        vms_list = [vm.name for vm in qvm_collection.values() if (vm.is_appvm() or vm.is_template())]
        vmname = QInputDialog.getItem(None, "Select VM", "Select VM:", vms_list, editable = False)
        if not vmname[1]:
            sys.exit(1)
        vm = qvm_collection.get_vm_by_name(vmname[0])


    global settings_window
    settings_window = VMSettingsWindow(vm, app, qvm_collection, tab)

    settings_window.show()

    app.exec_()
    app.exit()
Ejemplo n.º 3
0
def ext_pillar(minion_id, pillar, *args, **kwargs):
    qc = QubesVmCollection()
    qc.lock_db_for_reading()
    qc.load()
    qc.unlock_db()
    vm = qc.get_vm_by_name(minion_id)
    if vm is None:
        return {}
    qvm_pillar = {}
    if vm.qid == 0:
        qvm_pillar['type'] = 'admin'
    elif vm.is_template():
        qvm_pillar['type'] = 'template'
    elif vm.template is None:
        qvm_pillar['type'] = 'standalone'
    else:
        qvm_pillar['type'] = 'app'

    if vm.template:
        qvm_pillar['template'] = vm.template.name

    if vm.netvm:
        qvm_pillar['netvm'] = vm.netvm.name

    # TODO: consider other properties; target VM will learn them!

    return {'qubes': qvm_pillar}
Ejemplo n.º 4
0
def main():

    global qubes_host
    qubes_host = QubesHost()

    global app
    app = QApplication(sys.argv)
    app.setOrganizationName("The Qubes Project")
    app.setOrganizationDomain("http://qubes-os.org")
    app.setApplicationName("Qubes Restore VMs")

    sys.excepthook = handle_exception

    qvm_collection = QubesVmCollection()
    qvm_collection.lock_db_for_reading()
    qvm_collection.load()
    qvm_collection.unlock_db()

    global restore_window
    restore_window = RestoreVMsWindow()

    restore_window.show()

    app.exec_()
    app.exit()
 def vm(self, value):  # pylint: disable=C0103
     '''
     Get Qubes VM object from qvm.collection and set it here.
     '''
     if value:
         qvm_collection = QubesVmCollection()
         qvm_collection.lock_db_for_reading()
         qvm_collection.load()
         qvm_collection.unlock_db()
         qvm = qvm_collection.get_vm_by_name(value)
         if qvm and qvm.qid in qvm_collection:
             self._vm = qvm  # pylint: disable=W0212
             return
     self._vm = None  # pylint: disable=W0212
Ejemplo n.º 6
0
def app_main():

    global qubes_host
    qubes_host = QubesHost()

    global app
    app = QApplication(sys.argv)
    app.setOrganizationName("The Qubes Project")
    app.setOrganizationDomain("http://qubes-os.org")
    app.setApplicationName("Qubes Backup VMs")

    sys.excepthook = handle_exception

    qvm_collection = QubesVmCollection()
    qvm_collection.lock_db_for_reading()
    qvm_collection.load()
    qvm_collection.unlock_db()

    global backup_window
    backup_window = BackupVMsWindow()

    backup_window.show()

    app.exec_()
    app.exit()
Ejemplo n.º 7
0
 def setUp(self):
     self.qc = QubesVmCollection()
     self.qc.lock_db_for_writing()
     self.qc.load()
     self.updatevm = self.qc.add_new_vm(
         "QubesProxyVm",
         name="%supdatevm" % VM_PREFIX,
         template=self.qc.get_default_template())
     self.updatevm.create_on_disk(verbose=False)
     self.saved_updatevm = self.qc.get_updatevm_vm()
     self.qc.set_updatevm_vm(self.updatevm)
     self.qc.save()
     self.qc.unlock_db()
     subprocess.call(['sudo', 'rpm', '-e', self.pkg_name],
                     stderr=open(os.devnull, 'w'))
     subprocess.check_call([
         'sudo', 'rpm', '--import',
         os.path.join(self.tmpdir, 'pubkey.asc')
     ])
     self.updatevm.start()
Ejemplo n.º 8
0
def notify_vms():

    monitor_layout = get_monitor_layout()

    if len(monitor_layout) == 0:
        return

    qc = QubesVmCollection()
    qc.lock_db_for_reading()
    qc.load()
    qc.unlock_db()

    pipes = []
    for vm in qc.values():
        if vm.qid == 0:
            continue
        if vm.is_running():
            pipes.append(notify_vm(vm, monitor_layout))

    for p in pipes:
        p.wait()
Ejemplo n.º 9
0
def notify_vm_by_name(vmname):
    monitor_layout = get_monitor_layout()

    if len(monitor_layout) == 0:
        return

    qc = QubesVmCollection()
    qc.lock_db_for_reading()
    qc.load()
    qc.unlock_db()

    vm = qc.get_vm_by_name(vmname)
    if not vm:
        print >> sys.stderr, "No such VM!"
        return 1
    if not vm.is_running():
        print >> sys.stderr, "VM not running!"
        return 1
    pipe = notify_vm(vm, monitor_layout)
    pipe.wait()

    return 0
Ejemplo n.º 10
0
 def setUp(self):
     self.qc = QubesVmCollection()
     self.qc.lock_db_for_writing()
     self.qc.load()
     self.updatevm = self.qc.add_new_vm("QubesProxyVm",
                                        name="%supdatevm" % VM_PREFIX,
                                        template=self.qc.get_default_template())
     self.updatevm.create_on_disk(verbose=False)
     self.saved_updatevm = self.qc.get_updatevm_vm()
     self.qc.set_updatevm_vm(self.updatevm)
     self.qc.save()
     self.qc.unlock_db()
     subprocess.call(['sudo', 'rpm', '-e', self.pkg_name],
                     stderr=open(os.devnull, 'w'))
     subprocess.check_call(['sudo', 'rpm', '--import',
                            os.path.join(self.tmpdir, 'pubkey.asc')])
     self.updatevm.start()
def notify_vms():

    monitor_layout = get_monitor_layout()

    if len(monitor_layout) == 0:
        return

    qc = QubesVmCollection()
    qc.lock_db_for_reading()
    qc.load()
    qc.unlock_db()

    pipes = []
    for vm in qc.values():
        if vm.qid == 0:
            continue
        if vm.is_running():
            pipes.append(notify_vm(vm, monitor_layout))

    for p in pipes:
        p.wait()
def notify_vm_by_name(vmname):
    monitor_layout = get_monitor_layout()

    if len(monitor_layout) == 0:
        return

    qc = QubesVmCollection()
    qc.lock_db_for_reading()
    qc.load()
    qc.unlock_db()

    vm = qc.get_vm_by_name(vmname)
    if not vm:
        print >>sys.stderr, "No such VM!"
        return 1
    if not vm.is_running():
        print >>sys.stderr, "VM not running!"
        return 1
    pipe = notify_vm(vm, monitor_layout)
    pipe.wait()

    return 0
Ejemplo n.º 13
0
class QubesTemplateHVm(QubesHVm):
    """
    A class that represents an HVM template. A child of QubesHVm.
    """

    # In which order load this VM type from qubes.xml
    load_order = 50

    def get_attrs_config(self):
        attrs_config = super(QubesTemplateHVm, self).get_attrs_config()
        attrs_config['dir_path']['func'] = \
            lambda value: value if value is not None else \
                os.path.join(system_path["qubes_templates_dir"], self.name)
        attrs_config['label']['default'] = defaults["template_label"]
        return attrs_config

    def __init__(self, **kwargs):

        super(QubesTemplateHVm, self).__init__(**kwargs)

        self.appvms = QubesVmCollection()

    @property
    def type(self):
        return "TemplateHVM"

    @property
    def updateable(self):
        return True

    def is_template(self):
        return True

    def is_appvm(self):
        return False

    @property
    def rootcow_img(self):
        return self.storage.rootcow_img

    @classmethod
    def is_template_compatible(cls, template):
        if template is None:
            return True
        return False

    def resize_root_img(self, size):
        for vm in self.appvms.values():
            if vm.is_running():
                raise QubesException("Cannot resize root.img while any VM "
                                     "based on this tempate is running")
        return super(QubesTemplateHVm, self).resize_root_img(size)

    def start(self, *args, **kwargs):
        for vm in self.appvms.values():
            if vm.is_running():
                raise QubesException(
                    "Cannot start HVM template while VMs based on it are running"
                )
        return super(QubesTemplateHVm, self).start(*args, **kwargs)

    def commit_changes(self, verbose=False):
        self.log.debug('commit_changes()')

        if not vmm.offline_mode:
            assert not self.is_running(
            ), "Attempt to commit changes on running Template VM!"

        if verbose:
            print >> sys.stderr, "--> Commiting template updates... COW: {0}...".format(
                self.rootcow_img)

        if dry_run:
            return

        self.storage.commit_template_changes()
Ejemplo n.º 14
0
    def setUpClass(cls):
        if cls.template == 'whonix-gw' or 'minimal' in cls.template:
            raise unittest.SkipTest(
                'Template {} not supported by this test'.format(cls.template))

        if cls.template == 'whonix-ws':
            # TODO remove when Whonix-based DispVMs will work (Whonix 13?)
            raise unittest.SkipTest(
                'Template {} not supported by this test'.format(cls.template))

        qc = QubesVmCollection()

        cls._kill_test_vms(qc, prefix=qubes.tests.CLSVMPREFIX)

        qc.lock_db_for_writing()
        qc.load()

        cls._remove_test_vms(qc, qubes.qubes.vmm.libvirt_conn,
                            prefix=qubes.tests.CLSVMPREFIX)

        cls.source_vmname = cls.make_vm_name('source', True)
        source_vm = qc.add_new_vm("QubesAppVm",
                                  template=qc.get_vm_by_name(cls.template),
                                  name=cls.source_vmname)
        source_vm.create_on_disk(verbose=False)

        cls.target_vmname = cls.make_vm_name('target', True)
        target_vm = qc.add_new_vm("QubesAppVm",
                                  template=qc.get_vm_by_name(cls.template),
                                  name=cls.target_vmname)
        target_vm.create_on_disk(verbose=False)

        qc.save()
        qc.unlock_db()
        source_vm.start()
        target_vm.start()

        # make sure that DispVMs will be started of the same template
        retcode = subprocess.call(['/usr/bin/qvm-create-default-dvm',
                                   cls.template],
                                  stderr=open(os.devnull, 'w'))
        assert retcode == 0, "Error preparing DispVM"
Ejemplo n.º 15
0
frontend=sys.argv[3].split('-')
if len(frontend)!=2:
    print 'Error: frontendvm-device must be in <controller>-<port> format'
    sys.exit(1)
(controller, port)=frontend

if len(sys.argv)>4:
    backendvm_xid=int(sys.argv[4])
    backendvm_name=xen.lowlevel.xl.ctx().domid_to_name(backendvm_xid)
else:
    backendvm_xid=0

cmd = "/usr/lib/qubes/vusb-ctl.py unbind '%s'" % backendvm_device
if backendvm_xid == 0:
    os.system("sudo %s" % cmd)
else:
    from qubes.qubes import QubesVmCollection
    qvm_collection = QubesVmCollection()
    qvm_collection.lock_db_for_reading()
    qvm_collection.load()
    qvm_collection.unlock_db()

    # launch
    qvm_collection.get_vm_by_name(backendvm_name).run(cmd, user="******")

# FIXME: command injection
os.system("xenstore-write /local/domain/%s/backend/vusb/%s/%s/port/%s ''"
	% (backendvm_xid, frontendvm_xid, controller, port))

Ejemplo n.º 16
0
def main():

    global qubes_host
    qubes_host = QubesHost()

    global app
    app = QApplication(sys.argv)
    app.setOrganizationName("The Qubes Project")
    app.setOrganizationDomain("http://qubes-os.org")
    app.setApplicationName("Qubes VM Settings")

    sys.excepthook = handle_exception

    qvm_collection = QubesVmCollection()
    qvm_collection.lock_db_for_reading()
    qvm_collection.load()
    qvm_collection.unlock_db()

    vm = None
    tab = "basic"

    if len(sys.argv) > 1:
        vm = qvm_collection.get_vm_by_name(sys.argv[1])
        if vm is None or vm.qid not in qvm_collection:
            QMessageBox.critical(
                None, "Qubes VM Settings Error",
                "A VM with the name '{0}' does not exist in the system.".
                format(sys.argv[1]))
            sys.exit(1)
        if len(sys.argv) > 2:
            tab_arg = sys.argv[2]
            print tab_arg
            if tab_arg in VMSettingsWindow.tabs_indices:
                tab = tab_arg
            else:
                QMessageBox.warning(
                    None, "Qubes VM Settings Error",
                    "There is no such tab as '{0}'. Opening default tab instead."
                    .format(tab_arg))

    else:
        vms_list = [
            vm.name for vm in qvm_collection.values()
            if (vm.is_appvm() or vm.is_template())
        ]
        vmname = QInputDialog.getItem(None,
                                      "Select VM",
                                      "Select VM:",
                                      vms_list,
                                      editable=False)
        if not vmname[1]:
            sys.exit(1)
        vm = qvm_collection.get_vm_by_name(vmname[0])

    global settings_window
    settings_window = VMSettingsWindow(vm, app, qvm_collection, tab)

    settings_window.show()

    app.exec_()
    app.exit()
Ejemplo n.º 17
0
def main():
    module = AnsibleModule(argument_spec=dict(
        name=dict(required=True, type='str'),
        state=dict(default='present', choices=['present', 'absent']),
        type=dict(default='appvm',
                  choices=['appvm', 'netvm', 'proxyvm', 'hvm', 'templatehvm']),
        template=dict(type='str'),
        standalone=dict(default=False, type='bool'),
        label=dict(choices=[
            'red', 'orange', 'yellow', 'green', 'gray', 'blue', 'purple',
            'black'
        ]),
        pool_name=dict(default='default', type='str'),
        memory=dict(type='int'),
        maxmem=dict(type='int'),
        mac=dict(type='str'),
        pci_strictreset=dict(type='bool'),
        pci_e820_host=dict(default=False, type='bool'),
        netvm=dict(type='str'),
        dispvm_netvm=dict(type='str'),
        kernel=dict(type='str'),
        vcpus=dict(type='int'),
        kernelopts=dict(type='str'),
        drive=dict(type='str'),
        debug=dict(type='bool'),
        default_user=dict(type='str'),
        include_in_backups=dict(type='bool'),
        qrexec_installed=dict(type='bool'),
        internal=dict(type='bool'),
        guiagent_installed=dict(type='bool'),
        seamless_gui_mode=dict(type='bool'),
        autostart=dict(type='bool'),
        qrexec_timeout=dict(type='int'),
        timezone=dict(),
    ))

    if not QUBES_DOM0:
        module.fail_json(msg='This module must be run from QubeOS dom0')

    qvm_collection = QubesVmCollection()
    qvm_collection.lock_db_for_writing()
    qvm_collection.load()

    # Set parameters
    changed = True
    options = set_options(module, qvm_collection)

    if options['state'] == 'present':
        if qvm_collection.get_vm_by_name(options['args']['name']) is not None:
            changed = False
            qube = qvm_collection.get_vm_by_name(options['args']['name'])

            for key in options['args']:
                if key == 'pool_name':
                    if qube.pool_name != options['args']['pool_name']:
                        module.fail_json(
                            msg='Existing VM storage pool cannot be changed')
                elif getattr(qube, key) != options['args'][key]:
                    setattr(qube, key, options['args'][key])
                    changed = True

            if not isinstance(qube, QubesVmClasses[options['type']]):
                module.fail_json(msg='Existing VM type cannot be changed')

        else:
            try:
                qube = qvm_collection.add_new_vm(options['type'],
                                                 **options['args'])
            except QubesException as e:
                module.fail_json(msg='Unable to create VM: %s' % e)

            qube.create_on_disk(source_template=options['base_template'])

    elif options['state'] == 'absent':
        if qvm_collection.get_vm_by_name(options['args']['name']) is None:
            changed = False
        else:
            qube = qvm_collection.get_vm_by_name(options['args']['name'])

            if qube.is_running():
                try:
                    qube.force_shutdown()
                except (IOError, OSError, QubesException) as e:
                    module.fail_json(msg='Unable to shutdown VM: %s' % e)

            if qube.is_template():  # Report what VMs use this template
                dependent_qubes = qube.qvm_collection.get_vms_based_on(
                    qube.qid)
                if len(dependent_qubes) > 0:
                    module.fail_json(
                        msg='Please remove VMs dependent on this template first'
                    )
                if qvm_collection.default_template_qid == qube.qid:
                    qvm_collection.default_template_qid = None

            if qube.is_netvm():
                if qvm_collection.default_netvm_qid == qube.qid:
                    qvm_collection.default_netvm_qid = None

            if qube.installed_by_rpm:
                module.fail_json(msg='Qube managed by RPM/DNF')

            qube.remove_from_disk()
            qvm_collection.pop(qube.qid)

    qvm_collection.save()
    qvm_collection.unlock_db()
    module.exit_json(changed=changed)
Ejemplo n.º 18
0
    def do_create_vm(vmclass, vmname, label, template_vm, netvm, standalone,
                     allow_networking, thread_monitor):
        vm = None
        qc = QubesVmCollection()
        qc.lock_db_for_writing()
        qc.load()
        try:
            if not standalone:
                vm = qc.add_new_vm(vmclass,
                                   name=vmname,
                                   template=template_vm,
                                   label=label)
            else:
                vm = qc.add_new_vm(vmclass,
                                   name=vmname,
                                   template=None,
                                   label=label)
            vm.create_on_disk(verbose=False, source_template=template_vm)

            if not allow_networking:
                vm.uses_default_netvm = False
                vm.netvm = None
            else:
                vm.netvm = netvm
                if vm.netvm.qid == qc.get_default_netvm().qid:
                    vm.uses_default_netvm = True
                else:
                    vm.uses_default_netvm = False

            qc.save()
        except Exception as ex:
            thread_monitor.set_error_msg(str(ex))
            if vm:
                vm.remove_from_disk()
                qc.pop(vm.qid)
        finally:
            qc.unlock_db()

        thread_monitor.set_finished()
Ejemplo n.º 19
0
    def __init__(self, **kwargs):

        super(QubesTemplateHVm, self).__init__(**kwargs)

        self.appvms = QubesVmCollection()
Ejemplo n.º 20
0
class TC_00_Dom0Upgrade(qubes.tests.QubesTestCase):
    cleanup_paths = []
    pkg_name = 'qubes-test-pkg'
    dom0_update_common_opts = [
        '--disablerepo=*', '--enablerepo=test', '--setopt=test.copy_local=1'
    ]

    @classmethod
    def generate_key(cls, keydir):
        gpg_opts = [
            'gpg', '--quiet', '--no-default-keyring', '--homedir', keydir
        ]
        p = subprocess.Popen(gpg_opts + ['--gen-key', '--batch'],
                             stdin=subprocess.PIPE,
                             stderr=open(os.devnull, 'w'))
        p.stdin.write('''
Key-Type: RSA
Key-Length: 1024
Key-Usage: sign
Name-Real: Qubes test
Expire-Date: 0
%commit
        '''.format(keydir=keydir))
        p.stdin.close()
        p.wait()

        subprocess.check_call(
            gpg_opts +
            ['-a', '--export', '--output',
             os.path.join(keydir, 'pubkey.asc')])
        p = subprocess.Popen(gpg_opts + ['--with-colons', '--list-keys'],
                             stdout=subprocess.PIPE)
        for line in p.stdout.readlines():
            fields = line.split(':')
            if fields[0] == 'pub':
                return fields[4][-8:].lower()
        raise RuntimeError

    @classmethod
    def setUpClass(cls):
        super(TC_00_Dom0Upgrade, cls).setUpClass()

        cls.tmpdir = tempfile.mkdtemp()
        cls.cleanup_paths += [cls.tmpdir]

        cls.keyid = cls.generate_key(cls.tmpdir)

        p = subprocess.Popen(
            ['sudo', 'dd', 'status=none', 'of=/etc/yum.repos.d/test.repo'],
            stdin=subprocess.PIPE)
        p.stdin.write('''
[test]
name = Test
baseurl = file:///tmp/repo
enabled = 1
        ''')
        p.stdin.close()
        p.wait()

    @classmethod
    def tearDownClass(cls):
        subprocess.check_call(
            ['sudo', 'rm', '-f', '/etc/yum.repos.d/test.repo'])

        for dir in cls.cleanup_paths:
            shutil.rmtree(dir)
        cls.cleanup_paths = []

    def setUp(self):
        self.qc = QubesVmCollection()
        self.qc.lock_db_for_writing()
        self.qc.load()
        self.updatevm = self.qc.add_new_vm(
            "QubesProxyVm",
            name="%supdatevm" % VM_PREFIX,
            template=self.qc.get_default_template())
        self.updatevm.create_on_disk(verbose=False)
        self.saved_updatevm = self.qc.get_updatevm_vm()
        self.qc.set_updatevm_vm(self.updatevm)
        self.qc.save()
        self.qc.unlock_db()
        subprocess.call(['sudo', 'rpm', '-e', self.pkg_name],
                        stderr=open(os.devnull, 'w'))
        subprocess.check_call([
            'sudo', 'rpm', '--import',
            os.path.join(self.tmpdir, 'pubkey.asc')
        ])
        self.updatevm.start()

    def remove_vms(self, vms):
        self.qc.lock_db_for_writing()
        self.qc.load()

        self.qc.set_updatevm_vm(self.qc[self.saved_updatevm.qid])

        for vm in vms:
            if isinstance(vm, str):
                vm = self.qc.get_vm_by_name(vm)
            else:
                vm = self.qc[vm.qid]
            if vm.is_running():
                try:
                    vm.force_shutdown()
                except:
                    pass
            try:
                vm.remove_from_disk()
            except OSError:
                pass
            self.qc.pop(vm.qid)
        self.qc.save()
        self.qc.unlock_db()

    def tearDown(self):
        vmlist = [
            vm for vm in self.qc.values() if vm.name.startswith(VM_PREFIX)
        ]
        self.remove_vms(vmlist)

        subprocess.call(['sudo', 'rpm', '-e', self.pkg_name],
                        stderr=open(os.devnull, 'w'))
        subprocess.call(
            ['sudo', 'rpm', '-e', 'gpg-pubkey-{}'.format(self.keyid)],
            stderr=open(os.devnull, 'w'))

        for pkg in os.listdir(self.tmpdir):
            if pkg.endswith('.rpm'):
                os.unlink(pkg)

    def create_pkg(self, dir, name, version):
        spec_path = os.path.join(dir, name + '.spec')
        spec = open(spec_path, 'w')
        spec.write('''
Name:       {name}
Summary:    Test Package
Version:    {version}
Release:        1
Vendor:         Invisible Things Lab
License:        GPL
Group:          Qubes
URL:            http://www.qubes-os.org

%description
Test package

%install

%files
            '''.format(name=name, version=version))
        spec.close()
        subprocess.check_call([
            'rpmbuild', '--quiet', '-bb', '--define', '_rpmdir {}'.format(dir),
            spec_path
        ])
        pkg_path = os.path.join(dir, 'x86_64',
                                '{}-{}-1.x86_64.rpm'.format(name, version))
        subprocess.check_call(['sudo', 'chmod', 'go-rw', '/dev/tty'])
        subprocess.check_call([
            'rpm', '--quiet', '--define=_gpg_path {}'.format(dir),
            '--define=_gpg_name {}'.format("Qubes test"), '--addsign', pkg_path
        ],
                              stdin=open(os.devnull),
                              stdout=open(os.devnull, 'w'),
                              stderr=subprocess.STDOUT)
        subprocess.check_call(['sudo', 'chmod', 'go+rw', '/dev/tty'])
        return pkg_path

    def send_pkg(self, filename):
        p = self.updatevm.run('mkdir -p /tmp/repo; cat > /tmp/repo/{}'.format(
            os.path.basename(filename)),
                              passio_popen=True)
        p.stdin.write(open(filename).read())
        p.stdin.close()
        p.wait()
        self.updatevm.run('cd /tmp/repo; createrepo .', wait=True)

    def test_000_update(self):
        filename = self.create_pkg(self.tmpdir, self.pkg_name, '1.0')
        subprocess.check_call(['sudo', 'rpm', '-i', filename])
        filename = self.create_pkg(self.tmpdir, self.pkg_name, '2.0')
        self.send_pkg(filename)

        logpath = os.path.join(self.tmpdir, 'dom0-update-output.txt')
        try:
            subprocess.check_call(['sudo', 'qubes-dom0-update', '-y'] +
                                  self.dom0_update_common_opts,
                                  stdout=open(logpath, 'w'),
                                  stderr=subprocess.STDOUT)
        except subprocess.CalledProcessError:
            self.fail("qubes-dom0-update failed: " + open(logpath).read())

        retcode = subprocess.call(
            ['rpm', '-q', '{}-1.0'.format(self.pkg_name)],
            stdout=open(os.devnull, 'w'))
        self.assertEqual(
            retcode, 1, 'Package {}-1.0 still installed after '
            'update'.format(self.pkg_name))
        retcode = subprocess.call(
            ['rpm', '-q', '{}-2.0'.format(self.pkg_name)],
            stdout=open(os.devnull, 'w'))
        self.assertEqual(
            retcode, 0, 'Package {}-2.0 not installed after '
            'update'.format(self.pkg_name))

    def test_010_instal(self):
        filename = self.create_pkg(self.tmpdir, self.pkg_name, '1.0')
        self.send_pkg(filename)

        logpath = os.path.join(self.tmpdir, 'dom0-update-output.txt')
        try:
            subprocess.check_call(['sudo', 'qubes-dom0-update', '-y'] +
                                  self.dom0_update_common_opts +
                                  [self.pkg_name],
                                  stdout=open(logpath, 'w'),
                                  stderr=subprocess.STDOUT)
        except subprocess.CalledProcessError:
            self.fail("qubes-dom0-update failed: " + open(logpath).read())

        retcode = subprocess.call(
            ['rpm', '-q', '{}-1.0'.format(self.pkg_name)],
            stdout=open('/dev/null', 'w'))
        self.assertEqual(retcode, 0,
                         'Package {}-1.0 not installed'.format(self.pkg_name))

    def test_020_install_wrong_sign(self):
        subprocess.call(
            ['sudo', 'rpm', '-e', 'gpg-pubkey-{}'.format(self.keyid)])
        filename = self.create_pkg(self.tmpdir, self.pkg_name, '1.0')
        self.send_pkg(filename)

        logpath = os.path.join(self.tmpdir, 'dom0-update-output.txt')
        try:
            subprocess.check_call(['sudo', 'qubes-dom0-update', '-y'] +
                                  self.dom0_update_common_opts +
                                  [self.pkg_name],
                                  stdout=open(logpath, 'w'),
                                  stderr=subprocess.STDOUT)
            self.fail("qubes-dom0-update unexpectedly succeeded: " +
                      open(logpath).read())
        except subprocess.CalledProcessError:
            pass

        retcode = subprocess.call(
            ['rpm', '-q', '{}-1.0'.format(self.pkg_name)],
            stdout=open('/dev/null', 'w'))
        self.assertEqual(
            retcode, 1, 'Package {}-1.0 installed although '
            'signature is invalid'.format(self.pkg_name))

    def test_030_install_unsigned(self):
        filename = self.create_pkg(self.tmpdir, self.pkg_name, '1.0')
        subprocess.check_call(['rpm', '--delsign', filename],
                              stdout=open(os.devnull, 'w'),
                              stderr=subprocess.STDOUT)
        self.send_pkg(filename)

        logpath = os.path.join(self.tmpdir, 'dom0-update-output.txt')
        try:
            subprocess.check_call(['sudo', 'qubes-dom0-update', '-y'] +
                                  self.dom0_update_common_opts +
                                  [self.pkg_name],
                                  stdout=open(logpath, 'w'),
                                  stderr=subprocess.STDOUT)
            self.fail("qubes-dom0-update unexpectedly succeeded: " +
                      open(logpath).read())
        except subprocess.CalledProcessError:
            pass

        retcode = subprocess.call(
            ['rpm', '-q', '{}-1.0'.format(self.pkg_name)],
            stdout=open('/dev/null', 'w'))
        self.assertEqual(
            retcode, 1,
            'UNSIGNED package {}-1.0 installed'.format(self.pkg_name))
Ejemplo n.º 21
0
class QubesNetVm(QubesVm):
    """
    A class that represents a NetVM. A child of QubesCowVM.
    """

    # In which order load this VM type from qubes.xml
    load_order = 70

    def get_attrs_config(self):
        attrs_config = super(QubesNetVm, self).get_attrs_config()
        attrs_config['dir_path']['func'] = \
            lambda value: value if value is not None else \
                os.path.join(system_path["qubes_servicevms_dir"], self.name)
        attrs_config['label']['default'] = defaults["servicevm_label"]
        attrs_config['memory']['default'] = 300

        # New attributes
        attrs_config['netid'] = {
            'save': lambda: str(self.netid),
            'order': 30,
            'func': lambda value: value if value is not None else
            self._collection.get_new_unused_netid() }
        attrs_config['netprefix'] = {
            'func': lambda x: "10.137.{0}.".format(self.netid) }
        attrs_config['dispnetprefix'] = {
            'func': lambda x: "10.138.{0}.".format(self.netid) }

        # Dont save netvm prop
        attrs_config['netvm'].pop('save')
        attrs_config['uses_default_netvm'].pop('save')

        return attrs_config

    def __init__(self, **kwargs):
        super(QubesNetVm, self).__init__(**kwargs)
        self.connected_vms = QubesVmCollection()

        self.__network = "10.137.{0}.0".format(self.netid)
        self.__netmask = defaults["vm_default_netmask"]
        self.__gateway = self.netprefix + "1"
        self.__secondary_dns = self.netprefix + "254"

        self.__external_ip_allowed_xids = set()

        self.log.debug('network={} netmask={} gateway={} secondary_dns={}'.format(
            self.network, self.netmask, self.gateway, self.secondary_dns))

    @property
    def type(self):
        return "NetVM"

    def is_netvm(self):
        return True

    @property
    def gateway(self):
        return self.__gateway

    @property
    def secondary_dns(self):
        return self.__secondary_dns

    @property
    def netmask(self):
        return self.__netmask

    @property
    def network(self):
        return self.__network

    def get_ip_for_vm(self, qid):
        lo = qid % 253 + 2
        assert lo >= 2 and lo <= 254, "Wrong IP address for VM"
        return self.netprefix  + "{0}".format(lo)

    def get_ip_for_dispvm(self, dispid):
        lo = dispid % 254 + 1
        assert lo >= 1 and lo <= 254, "Wrong IP address for VM"
        return self.dispnetprefix  + "{0}".format(lo)

    def update_external_ip_permissions(self, xid = -1):
        # TODO: VMs in __external_ip_allowed_xids should be notified via RPC
        # service on exteran IP change
        pass

    def start(self, **kwargs):
        if dry_run:
            return

        xid=super(QubesNetVm, self).start(**kwargs)

        # Connect vif's of already running VMs
        for vm in self.connected_vms.values():
            if not vm.is_running():
                continue

            if 'verbose' in kwargs and kwargs['verbose']:
                print >> sys.stderr, "--> Attaching network to '{0}'...".format(vm.name)

            # Cleanup stale VIFs
            vm.cleanup_vifs()

            # force frontend to forget about this device
            #  module actually will be loaded back by udev, as soon as network is attached
            try:
                vm.run("modprobe -r xen-netfront xennet", user="******")
            except:
                pass

            try:
                vm.attach_network(wait=False)
            except QubesException as ex:
                print >> sys.stderr, ("WARNING: Cannot attach to network to '{0}': {1}".format(vm.name, ex))

        return xid

    def shutdown(self, force=False):
        if dry_run:
            return

        connected_vms =  [vm for vm in self.connected_vms.values() if vm.is_running()]
        if connected_vms and not force:
            raise QubesException("There are other VMs connected to this VM: " + str([vm.name for vm in connected_vms]))

        super(QubesNetVm, self).shutdown(force=force)

    def add_external_ip_permission(self, xid):
        if int(xid) < 0:
            return
        self.__external_ip_allowed_xids.add(int(xid))
        self.update_external_ip_permissions()

    def remove_external_ip_permission(self, xid):
        self.__external_ip_allowed_xids.discard(int(xid))
        self.update_external_ip_permissions()
Ejemplo n.º 22
0
    def __init__(self, **kwargs):

        super(QubesTemplateHVm, self).__init__(**kwargs)

        self.appvms = QubesVmCollection()
Ejemplo n.º 23
0
class QubesTemplateHVm(QubesHVm):
    """
    A class that represents an HVM template. A child of QubesHVm.
    """

    # In which order load this VM type from qubes.xml
    load_order = 50

    def get_attrs_config(self):
        attrs_config = super(QubesTemplateHVm, self).get_attrs_config()
        attrs_config['dir_path']['func'] = \
            lambda value: value if value is not None else \
                os.path.join(system_path["qubes_templates_dir"], self.name)
        attrs_config['label']['default'] = defaults["template_label"]
        return attrs_config


    def __init__(self, **kwargs):

        super(QubesTemplateHVm, self).__init__(**kwargs)

        self.appvms = QubesVmCollection()

    @property
    def type(self):
        return "TemplateHVM"

    @property
    def updateable(self):
        return True

    def is_template(self):
        return True

    def is_appvm(self):
        return False

    @property
    def rootcow_img(self):
        return self.storage.rootcow_img

    @classmethod
    def is_template_compatible(cls, template):
        if template is None:
            return True
        return False

    def resize_root_img(self, size):
        for vm in self.appvms.values():
            if vm.is_running():
                raise QubesException("Cannot resize root.img while any VM "
                                     "based on this tempate is running")
        return super(QubesTemplateHVm, self).resize_root_img(size)

    def start(self, *args, **kwargs):
        for vm in self.appvms.values():
            if vm.is_running():
                raise QubesException("Cannot start HVM template while VMs based on it are running")
        return super(QubesTemplateHVm, self).start(*args, **kwargs)

    def commit_changes (self, verbose = False):
        self.log.debug('commit_changes()')

        if not vmm.offline_mode:
            assert not self.is_running(), "Attempt to commit changes on running Template VM!"

        if verbose:
            print >> sys.stderr, "--> Commiting template updates... COW: {0}...".format (self.rootcow_img)

        if dry_run:
            return

        self.storage.commit_template_changes()
Ejemplo n.º 24
0
    def do_create_vm(vmclass, vmname, label, template_vm, netvm,
                     standalone, allow_networking, thread_monitor):
        vm = None
        qc = QubesVmCollection()
        qc.lock_db_for_writing()
        qc.load()
        try:
            if not standalone:
                vm = qc.add_new_vm(vmclass, name=vmname, template=template_vm,
                                   label=label)
            else:
                vm = qc.add_new_vm(vmclass, name=vmname, template=None,
                                   label=label)
            vm.create_on_disk(verbose=False, source_template=template_vm)

            if not allow_networking:
                vm.uses_default_netvm = False
                vm.netvm = None
            else:
                vm.netvm = netvm
                if vm.netvm.qid == qc.get_default_netvm().qid:
                    vm.uses_default_netvm = True
                else:
                    vm.uses_default_netvm = False

            qc.save()
        except Exception as ex:
            thread_monitor.set_error_msg(str(ex))
            if vm:
                vm.remove_from_disk()
                qc.pop(vm.qid)
        finally:
            qc.unlock_db()

        thread_monitor.set_finished()
Ejemplo n.º 25
0
#!/usr/bin/python
# -*- coding: utf-8 -*-
"""
Show network tree

@author: unman
"""

from qubes.qubes import QubesVmCollection
qvm_collection = QubesVmCollection()
qvm_collection.lock_db_for_reading()
qvm_collection.load()
qvm_collection.unlock_db()
qvm_collection.pop(0)


def tree(netvm, padding):
    names = {}
    padding = padding + '      '
    connected = netvm.connected_vms
    for i in connected:
        names[i] = connected[i].name
    for name in sorted(names.values()):
        vm = qvm_collection.get_qid_by_name(name)
        if qvm_collection[vm].is_running():
            vm_name = qvm_collection[vm].name + '* '
        else:
            vm_name = qvm_collection[vm].name
        if qvm_collection[vm].is_template():
            print padding, '|->', vm_name, '(Tpl)'
        else:
Ejemplo n.º 26
0
class TC_00_Dom0Upgrade(qubes.tests.QubesTestCase):
    cleanup_paths = []
    pkg_name = 'qubes-test-pkg'
    dom0_update_common_opts = ['--disablerepo=*', '--enablerepo=test',
                               '--setopt=test.copy_local=1']

    @classmethod
    def generate_key(cls, keydir):
        gpg_opts = ['gpg', '--quiet', '--no-default-keyring',
                    '--homedir', keydir]
        p = subprocess.Popen(gpg_opts + ['--gen-key', '--batch'],
                             stdin=subprocess.PIPE,
                             stderr=open(os.devnull, 'w'))
        p.stdin.write('''
Key-Type: RSA
Key-Length: 1024
Key-Usage: sign
Name-Real: Qubes test
Expire-Date: 0
%commit
        '''.format(keydir=keydir))
        p.stdin.close()
        p.wait()

        subprocess.check_call(gpg_opts + ['-a', '--export',
                                          '--output', os.path.join(keydir, 'pubkey.asc')])
        p = subprocess.Popen(gpg_opts + ['--with-colons', '--list-keys'],
                             stdout=subprocess.PIPE)
        for line in p.stdout.readlines():
            fields = line.split(':')
            if fields[0] == 'pub':
                return fields[4][-8:].lower()
        raise RuntimeError

    @classmethod
    def setUpClass(cls):
        super(TC_00_Dom0Upgrade, cls).setUpClass()

        cls.tmpdir = tempfile.mkdtemp()
        cls.cleanup_paths += [cls.tmpdir]

        cls.keyid = cls.generate_key(cls.tmpdir)

        p = subprocess.Popen(['sudo', 'dd',
                              'status=none', 'of=/etc/yum.repos.d/test.repo'],
                             stdin=subprocess.PIPE)
        p.stdin.write('''
[test]
name = Test
baseurl = file:///tmp/repo
enabled = 1
        ''')
        p.stdin.close()
        p.wait()


    @classmethod
    def tearDownClass(cls):
        subprocess.check_call(['sudo', 'rm', '-f',
                               '/etc/yum.repos.d/test.repo'])

        for dir in cls.cleanup_paths:
            shutil.rmtree(dir)
        cls.cleanup_paths = []

    def setUp(self):
        self.qc = QubesVmCollection()
        self.qc.lock_db_for_writing()
        self.qc.load()
        self.updatevm = self.qc.add_new_vm("QubesProxyVm",
                                           name="%supdatevm" % VM_PREFIX,
                                           template=self.qc.get_default_template())
        self.updatevm.create_on_disk(verbose=False)
        self.saved_updatevm = self.qc.get_updatevm_vm()
        self.qc.set_updatevm_vm(self.updatevm)
        self.qc.save()
        self.qc.unlock_db()
        subprocess.call(['sudo', 'rpm', '-e', self.pkg_name],
                        stderr=open(os.devnull, 'w'))
        subprocess.check_call(['sudo', 'rpm', '--import',
                               os.path.join(self.tmpdir, 'pubkey.asc')])
        self.updatevm.start()


    def remove_vms(self, vms):
        self.qc.lock_db_for_writing()
        self.qc.load()

        self.qc.set_updatevm_vm(self.qc[self.saved_updatevm.qid])

        for vm in vms:
            if isinstance(vm, str):
                vm = self.qc.get_vm_by_name(vm)
            else:
                vm = self.qc[vm.qid]
            if vm.is_running():
                try:
                    vm.force_shutdown()
                except:
                    pass
            try:
                vm.remove_from_disk()
            except OSError:
                pass
            self.qc.pop(vm.qid)
        self.qc.save()
        self.qc.unlock_db()

    def tearDown(self):
        vmlist = [vm for vm in self.qc.values() if vm.name.startswith(
            VM_PREFIX)]
        self.remove_vms(vmlist)

        subprocess.call(['sudo', 'rpm', '-e', self.pkg_name], stderr=open(
            os.devnull, 'w'))
        subprocess.call(['sudo', 'rpm', '-e', 'gpg-pubkey-{}'.format(
            self.keyid)], stderr=open(os.devnull, 'w'))

        for pkg in os.listdir(self.tmpdir):
            if pkg.endswith('.rpm'):
                os.unlink(pkg)

    def create_pkg(self, dir, name, version):
        spec_path = os.path.join(dir, name+'.spec')
        spec = open(spec_path, 'w')
        spec.write(
            '''
Name:       {name}
Summary:    Test Package
Version:    {version}
Release:        1
Vendor:         Invisible Things Lab
License:        GPL
Group:          Qubes
URL:            http://www.qubes-os.org

%description
Test package

%install

%files
            '''.format(name=name, version=version)
        )
        spec.close()
        subprocess.check_call(
            ['rpmbuild', '--quiet', '-bb', '--define', '_rpmdir {}'.format(dir),
             spec_path])
        pkg_path = os.path.join(dir, 'x86_64',
                                '{}-{}-1.x86_64.rpm'.format(name, version))
        subprocess.check_call(['sudo', 'chmod', 'go-rw', '/dev/tty'])
        subprocess.check_call(
            ['rpm', '--quiet', '--define=_gpg_path {}'.format(dir),
             '--define=_gpg_name {}'.format("Qubes test"),
             '--addsign', pkg_path],
            stdin=open(os.devnull),
            stdout=open(os.devnull, 'w'),
            stderr=subprocess.STDOUT)
        subprocess.check_call(['sudo', 'chmod', 'go+rw', '/dev/tty'])
        return pkg_path

    def send_pkg(self, filename):
        p = self.updatevm.run('mkdir -p /tmp/repo; cat > /tmp/repo/{}'.format(
            os.path.basename(
                filename)), passio_popen=True)
        p.stdin.write(open(filename).read())
        p.stdin.close()
        p.wait()
        self.updatevm.run('cd /tmp/repo; createrepo .', wait=True)

    def test_000_update(self):
        filename = self.create_pkg(self.tmpdir, self.pkg_name, '1.0')
        subprocess.check_call(['sudo', 'rpm', '-i', filename])
        filename = self.create_pkg(self.tmpdir, self.pkg_name, '2.0')
        self.send_pkg(filename)

        logpath = os.path.join(self.tmpdir, 'dom0-update-output.txt')
        try:
            subprocess.check_call(['sudo', 'qubes-dom0-update', '-y'] +
                                  self.dom0_update_common_opts,
                                  stdout=open(logpath, 'w'),
                                  stderr=subprocess.STDOUT)
        except subprocess.CalledProcessError:
            self.fail("qubes-dom0-update failed: " + open(
                logpath).read())

        retcode = subprocess.call(['rpm', '-q', '{}-1.0'.format(
            self.pkg_name)], stdout=open(os.devnull, 'w'))
        self.assertEqual(retcode, 1, 'Package {}-1.0 still installed after '
                                     'update'.format(self.pkg_name))
        retcode = subprocess.call(['rpm', '-q', '{}-2.0'.format(
            self.pkg_name)], stdout=open(os.devnull, 'w'))
        self.assertEqual(retcode, 0, 'Package {}-2.0 not installed after '
                                     'update'.format(self.pkg_name))

    def test_010_instal(self):
        filename = self.create_pkg(self.tmpdir, self.pkg_name, '1.0')
        self.send_pkg(filename)

        logpath = os.path.join(self.tmpdir, 'dom0-update-output.txt')
        try:
            subprocess.check_call(['sudo', 'qubes-dom0-update', '-y'] +
                                  self.dom0_update_common_opts + [
                self.pkg_name],
                                  stdout=open(logpath, 'w'),
                                  stderr=subprocess.STDOUT)
        except subprocess.CalledProcessError:
            self.fail("qubes-dom0-update failed: " + open(
                logpath).read())

        retcode = subprocess.call(['rpm', '-q', '{}-1.0'.format(
            self.pkg_name)], stdout=open('/dev/null', 'w'))
        self.assertEqual(retcode, 0, 'Package {}-1.0 not installed'.format(
            self.pkg_name))

    def test_020_install_wrong_sign(self):
        subprocess.call(['sudo', 'rpm', '-e', 'gpg-pubkey-{}'.format(
            self.keyid)])
        filename = self.create_pkg(self.tmpdir, self.pkg_name, '1.0')
        self.send_pkg(filename)

        logpath = os.path.join(self.tmpdir, 'dom0-update-output.txt')
        try:
            subprocess.check_call(['sudo', 'qubes-dom0-update', '-y'] +
                                  self.dom0_update_common_opts + [
                self.pkg_name],
                                  stdout=open(logpath, 'w'),
                                  stderr=subprocess.STDOUT)
            self.fail("qubes-dom0-update unexpectedly succeeded: " + open(
                logpath).read())
        except subprocess.CalledProcessError:
            pass

        retcode = subprocess.call(['rpm', '-q', '{}-1.0'.format(
            self.pkg_name)], stdout=open('/dev/null', 'w'))
        self.assertEqual(retcode, 1,
                         'Package {}-1.0 installed although '
                         'signature is invalid'.format(self.pkg_name))

    def test_030_install_unsigned(self):
        filename = self.create_pkg(self.tmpdir, self.pkg_name, '1.0')
        subprocess.check_call(['rpm', '--delsign', filename],
                              stdout=open(os.devnull, 'w'),
                              stderr=subprocess.STDOUT)
        self.send_pkg(filename)

        logpath = os.path.join(self.tmpdir, 'dom0-update-output.txt')
        try:
            subprocess.check_call(['sudo', 'qubes-dom0-update', '-y'] +
                                  self.dom0_update_common_opts +
                                  [self.pkg_name],
                                  stdout=open(logpath, 'w'),
                                  stderr=subprocess.STDOUT
                                  )
            self.fail("qubes-dom0-update unexpectedly succeeded: " + open(
                logpath).read())
        except subprocess.CalledProcessError:
            pass

        retcode = subprocess.call(['rpm', '-q', '{}-1.0'.format(
            self.pkg_name)], stdout=open('/dev/null', 'w'))
        self.assertEqual(retcode, 1,
                         'UNSIGNED package {}-1.0 installed'.format(self.pkg_name))