1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/ait/poc/scanner/99-qubes_block.rule Sat May 04 12:17:31 2013 -0400
1.3 @@ -0,0 +1,20 @@
1.4 +# Expose all (except xen-frontend) block devices via xenstore
1.5 +
1.6 +# Only block devices are interesting
1.7 +SUBSYSTEM!="block", GOTO="qubes_block_end"
1.8 +
1.9 +# Skip xen-blkfront devices
1.10 +ENV{MAJOR}=="202", GOTO="qubes_block_end"
1.11 +
1.12 +# Skip device-mapper devices
1.13 +ENV{MAJOR}=="253", GOTO="qubes_block_end"
1.14 +
1.15 +IMPORT{db}="QUBES_EXPOSED"
1.16 +ACTION=="add", IMPORT{program}="/usr/lib/qubes/block_add_change"
1.17 +ACTION=="change", IMPORT{program}="/usr/lib/qubes/block_add_change"
1.18 +ACTION=="remove", RUN+="/usr/lib/qubes/block_remove"
1.19 +
1.20 +LABEL="qubes_block_end"
1.21 +
1.22 +# Cleanup disconnected frontend from xenstore
1.23 +ACTION=="remove", SUBSYSTEM=="block", ENV{MAJOR}=="202", RUN+="/usr/lib/qubes/block_cleanup"
2.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2.2 +++ b/ait/poc/scanner/create_dvm.py Sat May 04 12:17:31 2013 -0400
2.3 @@ -0,0 +1,280 @@
2.4 +#!/bin/python
2.5 +import os
2.6 +import time
2.7 +import dbus
2.8 +import sys
2.9 +import subprocess
2.10 +from qubes.qubes import QubesVmCollection
2.11 +from qubes.qubes import QubesDispVmLabels
2.12 +from qubes.qubes import QubesException
2.13 +from qubes.qubes import QubesVmLabels
2.14 +from qubes.qmemman_client import QMemmanClient
2.15 +from qubes.qubesutils import block_list,block_attach,block_detach,block_detach_all,block_check_attached
2.16 +from qubes.qubesutils import kbytes_to_kmg, bytes_to_kmg
2.17 +
2.18 +
2.19 +notify_object = None
2.20 +current_savefile = '/var/run/qubes/current_savefile'
2.21 +current_dvm_conf = '/var/run/qubes/current_dvm.conf'
2.22 +avir_appvm_template = 'avir-template'
2.23 +avir_dvm_template = 'avir-template-dvm'
2.24 +
2.25 +def get_vm_collection():
2.26 + vm_collection = QubesVmCollection()
2.27 + vm_collection.lock_db_for_reading()
2.28 + vm_collection.load()
2.29 + vm_collection.unlock_db()
2.30 + return vm_collection
2.31 +
2.32 +def get_vm_by_name(vmname):
2.33 + return get_vm_collection().get_vm_by_name(vmname)
2.34 +
2.35 +def gen_scanner_name():
2.36 + vm_collection = get_vm_collection()
2.37 + vms = [vm for vm in vm_collection.values()]
2.38 + vm_names = []
2.39 + for vm in vms:
2.40 + if vm.is_appvm() and vm.template.name == avir_appvm_template:
2.41 + vm_names.append (vm.name)
2.42 + print vm_names
2.43 +
2.44 + ids = range(100)
2.45 + for id in ids:
2.46 + if "scanner"+str(id) not in vm_names:
2.47 + return "scanner"+str(id)
2.48 + print >> sys.stderr, "Unable to generate new scanner vm name"
2.49 + exit(1)
2.50 +
2.51 +class VMFactory:
2.52 + def __init__(self):
2.53 + self.tray_notify(str="Initialized")
2.54 +
2.55 + def tray_notify(self, str, timeout = 3000):
2.56 + notify_object.Notify("Qubes", 0, "red", "Qubes", str, [], [], timeout, dbus_interface="org.freedesktop.Notifications")
2.57 +
2.58 + def tray_notify_error(self, str, timeout = 3000):
2.59 + notify_object.Notify("Qubes", 0, "dialog-error", "Qubes", str, [], [], timeout, dbus_interface="org.freedesktop.Notifications")
2.60 +
2.61 + def create_appvm(self):
2.62 + #generate new avir-scanner name
2.63 + scanner_vmname = gen_scanner_name()
2.64 + print "Generating new scanner vm %s " % scanner_vmname
2.65 +
2.66 + #create new vscanner virtual machine from template "avir-template"
2.67 + qvm_collection = QubesVmCollection()
2.68 + qvm_collection.lock_db_for_writing()
2.69 + qvm_collection.load()
2.70 + avir_template = qvm_collection.get_vm_by_name(avir_appvm_template)
2.71 + if not avir_template.is_template():
2.72 + print >> sys.stderr, "VM '{0}' is not a TemplateVM".format(avir_template)
2.73 + exit (1)
2.74 + vmtype = "QubesAppVm"
2.75 +
2.76 + try:
2.77 + scanner_vm = qvm_collection.add_new_vm(vmtype, name=scanner_vmname, template=avir_template, label = QubesVmLabels["orange"])
2.78 + except QubesException as err:
2.79 + print >> sys.stderr, "ERROR: {0}".format(err)
2.80 + exit (1)
2.81 +
2.82 + scanner_vm.memory = 512
2.83 + scanner_vm.vcpus = 2
2.84 + try:
2.85 + scanner_vm.create_on_disk(verbose=True, source_template=avir_template)
2.86 + #if options.root:
2.87 + # os.unlink(vm.root_img)
2.88 + # os.rename(options.root, vm.root_img)
2.89 + except (IOError, OSError) as err:
2.90 + print >> sys.stderr, "ERROR: {0}".format(err)
2.91 + exit (1)
2.92 +
2.93 + qvm_collection.save()
2.94 + qvm_collection.unlock_db()
2.95 + return scanner_vmname
2.96 +
2.97 + def start_vm(self, vmname):
2.98 + vm = get_vm_by_name(vmname)
2.99 + if vm is None or vm.qid not in get_vm_collection():
2.100 + print >> sys.stderr, "A VM with the name '{0}' does not exist in the system.".format(vmname)
2.101 + exit(1)
2.102 + try:
2.103 + vm.verify_files()
2.104 + xid = vm.start(verbose=True, preparing_dvm=False, start_guid=True, notify_function=None)
2.105 + except (IOError, OSError, QubesException, MemoryError) as err:
2.106 + #if options.tray:
2.107 + # tray_notify_error(str(err))
2.108 + #else:
2.109 + print >> sys.stderr, "ERROR: {0}".format(err)
2.110 + exit (1)
2.111 +
2.112 + def create_dvm(self):
2.113 + qmemman_client = QMemmanClient()
2.114 + if not qmemman_client.request_memory(400*1024*1024):
2.115 + qmemman_client.close()
2.116 + errmsg = 'Not enough memory to create DVM. '
2.117 + errmsg +='Terminate some appVM and retry.'
2.118 + if os.path.exists('/usr/bin/kdialog'):
2.119 + subprocess.call(['/usr/bin/kdialog', '--sorry', errmsg])
2.120 + else:
2.121 + subprocess.call(['/usr/bin/zenity', '--warning', errmsg])
2.122 + return None
2.123 + self.tray_notify("Starting new DispVM...")
2.124 +
2.125 + qvm_collection = QubesVmCollection()
2.126 + qvm_collection.lock_db_for_writing()
2.127 + qvm_collection.load()
2.128 + avir_template = qvm_collection.get_vm_by_name(avir_dvm_template)
2.129 + if avir_template is None:
2.130 + sys.stderr.write( 'Domain ' + avir_dvm_template + ' does not exist ?')
2.131 + qvm_collection.unlock_db()
2.132 + qmemman_client.close()
2.133 + return None
2.134 + label = avir_template.label
2.135 + retcode = subprocess.call(['/usr/lib/qubes/qubes_restore',
2.136 + current_savefile,
2.137 + current_dvm_conf,
2.138 + '-u', str(avir_template.default_user),
2.139 + '-c', label.color,
2.140 + '-i', label.icon_path,
2.141 + '-l', str(label.index)])
2.142 + qmemman_client.close()
2.143 + if retcode != 0:
2.144 + if os.path.exists('/usr/bin/kdialog'):
2.145 + subprocess.call(['/usr/bin/kdialog', '--sorry', 'DisposableVM creation failed, see qubes_restore.log'])
2.146 + else:
2.147 + subprocess.call(['/usr/bin/zenity', '--warning', 'DisposableVM creation failed, see qubes_restore.log'])
2.148 + qvm_collection.unlock_db()
2.149 + return None
2.150 +
2.151 + f = open('/var/run/qubes/dispVM_xid', 'r');
2.152 + disp_xid = f.readline().rstrip('\n')
2.153 + disp_name = f.readline().rstrip('\n')
2.154 + disptempl = f.readline().rstrip('\n')
2.155 + f.close()
2.156 +
2.157 + print >>sys.stderr, "getting vm %s" % disptempl
2.158 + avir_disptempl = qvm_collection.get_vm_by_name(disptempl);
2.159 + if avir_disptempl is None:
2.160 + sys.stderr.write( 'Domain ' + disptempl + ' does not exist ?')
2.161 + qvm_collection.unlock_db()
2.162 + return None
2.163 +
2.164 + dispid = int(disp_name[4:])
2.165 + dispvm = qvm_collection.add_new_disposablevm(disp_name, avir_disptempl.template, label=label, dispid=dispid, netvm=avir_disptempl.netvm)
2.166 + print >> sys.stderr, "Waiting for the VM %s to startup...", dispvm.name
2.167 + startup_counter = 0
2.168 + startup_counter_max = 60
2.169 + while startup_counter < startup_counter_max:
2.170 + if dispvm.is_running():
2.171 + break
2.172 + shutdown_counter += 1
2.173 + time.sleep (1)
2.174 +
2.175 + qvm_collection.save()
2.176 + qvm_collection.unlock_db()
2.177 + return dispvm.name
2.178 +
2.179 + def stop_vm(self, vmname):
2.180 + vm = get_vm_by_name(vmname)
2.181 + if vm is None or vm.qid not in get_vm_collection():
2.182 + print >> sys.stderr, "A VM with the name '{0}' does not exist in the system.".format(vmname)
2.183 + exit(1)
2.184 + vm.shutdown(force=True)
2.185 + print >> sys.stderr, "Waiting for the VM %s to shutdown...", vmname
2.186 + shutdown_counter = 0
2.187 + shutdown_counter_max = 60
2.188 + while shutdown_counter < shutdown_counter_max:
2.189 + if not vm.is_running():
2.190 + return
2.191 + shutdown_counter += 1
2.192 + time.sleep (1)
2.193 +
2.194 + def remove_vm(self, vmname):
2.195 + qvm_collection = QubesVmCollection()
2.196 + qvm_collection.lock_db_for_writing()
2.197 + qvm_collection.load()
2.198 + vm = qvm_collection.get_vm_by_name(vmname)
2.199 +
2.200 + if vm is None or vm.qid not in qvm_collection:
2.201 + print >> sys.stderr, "A VM with the name '{0}' does not exist in the system.".format(vmname)
2.202 + exit(1)
2.203 +
2.204 + if vm.is_running():
2.205 + print >> sys.stderr, "Cannot remove a running VM, stop it first"
2.206 + exit (1)
2.207 +
2.208 + if vm.is_template():
2.209 + dependent_vms = qvm_collection.get_vms_based_on(vm.qid)
2.210 + if len(dependent_vms) > 0:
2.211 + print >> sys.stderr, "The following AppVMs use '{0}' as a template:".format(vmname)
2.212 + for vm in dependent_vms:
2.213 + print >> sys.stderr, "{name:<12} (qid={qid})".format(qid=vm.qid, name=vm.name)
2.214 + print >> sys.stderr, "Please remove those VMs first."
2.215 + exit (1)
2.216 + if qvm_collection.default_template_qid == vm.qid:
2.217 + qvm_collection.default_template_qid = None
2.218 +
2.219 + try:
2.220 + vm.remove_from_disk()
2.221 + except (IOError, OSError) as err:
2.222 + print >> sys.stderr, "Warning: {0}".format(err)
2.223 +
2.224 + # Do not exit, perhaps the VM files were somehow removed
2.225 + # so just remove it from Qubes DB
2.226 + qvm_collection.pop(vm.qid)
2.227 + qvm_collection.save()
2.228 + qvm_collection.unlock_db()
2.229 +
2.230 + def attach_dev(self, vmname, devname):
2.231 + vm = get_vm_by_name(vmname)
2.232 + if vm is None or vm.qid not in get_vm_collection():
2.233 + print >> sys.stderr, "A VM with the name '{0}' does not exist in the system.".format(vmname)
2.234 + exit(1)
2.235 + print "Attaching %s to vm - %s" % (devname, vm.name)
2.236 + kwargs = {}
2.237 + kwargs['auto_detach'] = True
2.238 + try:
2.239 + backend_vm = get_vm_by_name("dom0")
2.240 + block_attach(vm, backend_vm, devname, **kwargs)
2.241 + except QubesException as e:
2.242 + print >> sys.stderr, "ERROR: %s" % str(e)
2.243 + exit(1)
2.244 +
2.245 + def detach_dev(self, vmname, devname):
2.246 + vm = get_vm_by_name(vmname)
2.247 + if vm is None or vm.qid not in get_vm_collection():
2.248 + print >> sys.stderr, "A VM with the name '{0}' does not exist in the system.".format(vmname)
2.249 + exit(1)
2.250 + print "Detaching %s from vm - %s" % (devname, vmname)
2.251 + kwargs = {}
2.252 + #kwargs['frontend'] = "to_scan"
2.253 + try:
2.254 + block_detach(vm, **kwargs)
2.255 + except QubesException as e:
2.256 + print >> sys.stderr, "ERROR: %s" % str(e)
2.257 + sys.exit(1)
2.258 +
2.259 + def scan(self, vmname):
2.260 + vm = get_vm_by_name(vmname)
2.261 + if vm is None or vm.qid not in get_vm_collection():
2.262 + print >> sys.stderr, "A VM with the name '{0}' does not exist in the system.".format(vmname)
2.263 + exit(1)
2.264 + subprocess.call(['/usr/lib/qubes/qrexec_client', '-d', vmname, 'root:mount /dev/xvdi /mnt/removable'])
2.265 + #subprocess.call(['/usr/lib/qubes/qrexec_client', '-d', vmname, 'root:clamscan /mnt/removable'])
2.266 + subprocess.call(['/usr/lib/qubes/qrexec_client', '-d', vmname, 'root:umount /mnt/removable'])
2.267 +
2.268 +
2.269 +def main():
2.270 + global notify_object
2.271 + print >>sys.stderr, "time=%s, qfile-daemon-dvm init" % (str(time.time()))
2.272 + notify_object = dbus.SessionBus().get_object("org.freedesktop.Notifications", "/org/freedesktop/Notifications")
2.273 + vm_factory = VMFactory()
2.274 + #vmname = vm_factory.create_dvm()
2.275 + vmname = vm_factory.create_appvm()
2.276 + vm_factory.start_vm(vmname)
2.277 + vm_factory.attach_dev(vmname, "sdb")
2.278 + vm_factory.scan(vmname)
2.279 + vm_factory.detach_dev(vmname, "sdb")
2.280 + #vm_factory.stop_vm(vmname)
2.281 + #vm_factory.remove_vm(vmname)
2.282 +
2.283 +main()
3.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
3.2 +++ b/ait/poc/scanner/start_scan.sh Sat May 04 12:17:31 2013 -0400
3.3 @@ -0,0 +1,3 @@
3.4 +#!/bin/bash
3.5 +python /home/bartham/scan.py $1 &
3.6 +exit 0
4.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
4.2 +++ b/ait/poc/scanner/test.py Sat May 04 12:17:31 2013 -0400
4.3 @@ -0,0 +1,7 @@
4.4 +#!/bin/python
4.5 +import subprocess
4.6 +
4.7 +def main():
4.8 + subprocess.call(['/usr/lib/qubes/qrexec_client', '-d', 'scanner1', 'root:ls -la'])
4.9 +
4.10 +main()