OpenSecurity/bin/vmmanager.pyw
author Oliver Maurhart <oliver.maurhart@ait.ac.at>
Wed, 23 Apr 2014 14:55:02 +0200
changeset 129 abf3500eaf87
parent 125 7149f29e9570
child 131 8b4df474e577
permissions -rwxr-xr-x
fix on debug output
     1 '''
     2 Created on Nov 19, 2013
     3 
     4 @author: BarthaM
     5 '''
     6 import os
     7 import os.path
     8 from subprocess import Popen, PIPE, call, STARTUPINFO, _subprocess
     9 import sys
    10 import re
    11 
    12 from cygwin import Cygwin
    13 from environment import Environment
    14 import threading
    15 import time
    16 import string
    17 
    18 import shutil
    19 import stat
    20 import tempfile
    21 from opensecurity_util import logger, setupLogger, OpenSecurityException
    22 import ctypes
    23 import itertools
    24 import _winreg
    25 DEBUG = True
    26 
    27 class VMManagerException(Exception):
    28     def __init__(self, value):
    29         self.value = value
    30     def __str__(self):
    31         return repr(self.value)
    32 
    33 class USBFilter:
    34     vendorid = ""
    35     productid = ""
    36     revision = ""
    37     
    38     def __init__(self, vendorid, productid, revision):
    39         self.vendorid = vendorid.lower()
    40         self.productid = productid.lower()
    41         self.revision = revision.lower()
    42         return
    43     
    44     def __eq__(self, other):
    45         return self.vendorid == other.vendorid and self.productid == other.productid and self.revision == other.revision
    46     
    47     def __hash__(self):
    48         return hash(self.vendorid) ^ hash(self.productid) ^ hash(self.revision)
    49     
    50     def __repr__(self):
    51         return "VendorId = \'" + str(self.vendorid) + "\' ProductId = \'" + str(self.productid) + "\' Revision = \'" + str(self.revision) + "\'"
    52     
    53     #def __getitem__(self, item):
    54     #    return self.coords[item]
    55  
    56 class VMManager(object):
    57     vmRootName = "SecurityDVM"
    58     systemProperties = None
    59     _instance = None
    60     machineFolder = ''
    61     rsdHandler = None
    62     
    63     def __init__(self):
    64         self.systemProperties = self.getSystemProperties()
    65         self.machineFolder = self.systemProperties["Default machine folder"]
    66         self.cleanup()
    67         self.rsdHandler = DeviceHandler(self)
    68         self.rsdHandler.start()
    69         return
    70     
    71     @staticmethod
    72     def getInstance():
    73         if VMManager._instance == None:
    74             VMManager._instance = VMManager()
    75         return VMManager._instance
    76     
    77     def cleanup(self):
    78         if self.rsdHandler != None:
    79             self.rsdHandler.stop()
    80             self.rsdHandler.join()
    81         drives = self.getNetworkDrives()
    82         for drive in drives.keys():
    83             self.unmapNetworkDrive(drive)
    84         for vm in self.listSDVM():
    85             self.poweroffVM(vm)
    86             self.removeVM(vm)
    87         
    88     # return hosty system properties
    89     def getSystemProperties(self):
    90         result = checkResult(Cygwin.vboxExecute('list systemproperties'))
    91         if result[1]=='':
    92             return None
    93         props = dict((k.strip(),v.strip().strip('"')) for k,v in (line.split(':', 1) for line in result[1].strip().splitlines()))
    94         return props
    95     
    96     # return the folder containing the guest VMs     
    97     def getMachineFolder(self):
    98         return self.machineFolder
    99 
   100     # list all existing VMs registered with VBox
   101     def listVM(self):
   102         result = checkResult(Cygwin.vboxExecute('list vms'))[1]
   103         vms = list(k.strip().strip('"') for k,_ in (line.split(' ') for line in result.splitlines()))
   104         return vms
   105     
   106     # list running VMs
   107     def listRunningVMS(self):
   108         result = checkResult(Cygwin.vboxExecute('list runningvms'))[1]
   109         vms = list(k.strip().strip('"') for k,_ in (line.split(' ') for line in result.splitlines()))
   110         return vms
   111     
   112     # list existing SDVMs
   113     def listSDVM(self):
   114         vms = self.listVM()
   115         svdms = []
   116         for vm in vms:
   117             if vm.startswith(self.vmRootName) and vm != self.vmRootName:
   118                 svdms.append(vm)
   119         return svdms
   120     
   121     # generate valid (not already existing SDVM name). necessary for creating a new VM
   122     def generateSDVMName(self):
   123         vms = self.listVM()
   124         for i in range(0,999):
   125             if(not self.vmRootName+str(i) in vms):
   126                 return self.vmRootName+str(i)
   127         return ''
   128     
   129     # check if the device is mass storage type
   130     @staticmethod
   131     def isMassStorageDevice(device):
   132         keyname = 'SYSTEM\CurrentControlSet\Enum\USB' + '\VID_' + device.vendorid+'&'+'PID_'+ device.productid
   133         key = _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE, keyname)
   134         #subkeys = _winreg.QueryInfoKey(key)[0]
   135         #for i in range(0, subkeys):
   136         #    print _winreg.EnumKey(key, i)     
   137         devinfokeyname = _winreg.EnumKey(key, 0)
   138         _winreg.CloseKey(key)
   139 
   140         devinfokey = _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE, keyname+'\\'+devinfokeyname)
   141         value = _winreg.QueryValueEx(devinfokey, 'SERVICE')[0]
   142         _winreg.CloseKey(devinfokey)
   143         
   144         return 'USBSTOR' in value
   145     
   146     # return the RSDs connected to the host
   147     @staticmethod
   148     def getConnectedRSDS():
   149         results = checkResult(Cygwin.vboxExecute('list usbhost'))[1]
   150         results = results.split('Host USB Devices:')[1].strip()
   151         
   152         items = list( "UUID:"+result for result in results.split('UUID:') if result != '')
   153         rsds = dict()   
   154         for item in items:
   155             props = dict()
   156             for line in item.splitlines():
   157                 if line != "":         
   158                     k,v = line[:line.index(':')].strip(), line[line.index(':')+1:].strip()
   159                     props[k] = v
   160             
   161             #if 'Product' in props.keys() and props['Product'] == 'Mass Storage':
   162             
   163             usb_filter = USBFilter( re.search(r"\((?P<vid>[0-9A-Fa-f]+)\)", props['VendorId']).groupdict()['vid'], 
   164                                     re.search(r"\((?P<pid>[0-9A-Fa-f]+)\)", props['ProductId']).groupdict()['pid'],
   165                                     re.search(r"\((?P<rev>[0-9A-Fa-f]+)\)", props['Revision']).groupdict()['rev'] )
   166             if VMManager.isMassStorageDevice(usb_filter):
   167                 rsds[props['UUID']] = usb_filter;
   168                 logger.debug(usb_filter)
   169         return rsds
   170     
   171     # return the RSDs attached to all existing SDVMs
   172     def getAttachedRSDs(self):
   173         vms = self.listSDVM()
   174         attached_devices = dict()
   175         for vm in vms:
   176             rsd_filter = self.getUSBFilter(vm)
   177             if rsd_filter != None:
   178                 attached_devices[vm] = rsd_filter
   179         return attached_devices
   180     
   181     # configures hostonly networking and DHCP server. requires admin rights
   182     def configureHostNetworking(self):
   183         #cmd = 'vboxmanage list hostonlyifs'
   184         #Cygwin.vboxExecute(cmd)
   185         #cmd = 'vboxmanage hostonlyif remove \"VirtualBox Host-Only Ethernet Adapter\"'
   186         #Cygwin.vboxExecute(cmd)
   187         #cmd = 'vboxmanage hostonlyif create'
   188         #Cygwin.vboxExecute(cmd)
   189         checkResult(Cygwin.vboxExecute('hostonlyif ipconfig \"VirtualBox Host-Only Ethernet Adapter\" --ip 192.168.56.1 --netmask 255.255.255.0'))
   190         #cmd = 'vboxmanage dhcpserver add'
   191         #Cygwin.vboxExecute(cmd)
   192         checkResult(Cygwin.vboxExecute('dhcpserver modify --ifname \"VirtualBox Host-Only Ethernet Adapter\" --ip 192.168.56.100 --netmask 255.255.255.0 --lowerip 192.168.56.101 --upperip 192.168.56.200'))
   193     
   194     def isSDVMExisting(self, vm_name):
   195         sdvms = self.listSDVM()
   196         return vm_name in sdvms
   197         
   198     #create new virtual machine instance based on template vm named SecurityDVM (\SecurityDVM\SecurityDVM.vmdk)
   199     def createVM(self, vm_name):
   200         if self.isSDVMExisting(vm_name):
   201             return
   202         #remove eventually existing SDVM folder
   203         machineFolder = Cygwin.cygPath(self.machineFolder)
   204         checkResult(Cygwin.bashExecute('/usr/bin/rm -rf \\\"' + machineFolder + '/' + vm_name + '\\\"'))
   205         hostonly_if = self.getHostOnlyIFs()
   206         checkResult(Cygwin.vboxExecute('createvm --name ' + vm_name + ' --ostype Debian --register'))
   207         checkResult(Cygwin.vboxExecute('modifyvm ' + vm_name + ' --memory 512 --vram 10 --cpus 1 --usb on --usbehci on --nic1 hostonly --hostonlyadapter1 \"' + hostonly_if['Name'] + '\" --nic2 nat'))
   208         checkResult(Cygwin.vboxExecute('storagectl ' + vm_name + ' --name SATA --add sata --portcount 2'))
   209         return
   210     
   211     # attach storage image to controller
   212     def storageAttach(self, vm_name):
   213         if self.isStorageAttached(vm_name):
   214             self.storageDetach(vm_name)
   215         checkResult(Cygwin.vboxExecute('storageattach ' + vm_name + ' --storagectl SATA --port 0 --device 0 --type hdd --medium \"'+ self.machineFolder + '\SecurityDVM\SecurityDVM.vmdk\"'))
   216     
   217     # return true if storage is attached 
   218     def isStorageAttached(self, vm_name):
   219         info = self.getVMInfo(vm_name)
   220         return (info['SATA-0-0']!='none')
   221     
   222     # detach storage from controller
   223     def storageDetach(self, vm_name):
   224         if self.isStorageAttached(vm_name):
   225             checkResult(Cygwin.vboxExecute('storageattach ' + vm_name + ' --storagectl SATA --port 0 --device 0 --type hdd --medium none'))
   226     
   227     def changeStorageType(self, filename, storage_type):
   228         checkResult(Cygwin.vboxExecute('modifyhd \"' + filename + '\" --type ' + storage_type))
   229     
   230     # list storage snaphots for VM
   231     def updateTemplate(self):
   232 
   233         self.cleanup()
   234         self.poweroffVM('SecurityDVM')
   235         self.waitShutdown('SecurityDVM')
   236         
   237         # check for updates
   238         self.genCertificateISO('SecurityDVM')
   239         self.attachCertificateISO('SecurityDVM')
   240         
   241         self.storageDetach('SecurityDVM')
   242         results = checkResult(Cygwin.vboxExecute('list hdds'))[1]
   243         results = results.replace('Parent UUID', 'Parent')
   244         items = list( "UUID:"+result for result in results.split('UUID:') if result != '')
   245         
   246         snaps = dict()   
   247         for item in items:
   248             props = dict()
   249             for line in item.splitlines():
   250                 if line != "":         
   251                     k,v = line[:line.index(':')].strip(), line[line.index(':')+1:].strip()
   252                     props[k] = v;
   253             snaps[props['UUID']] = props
   254         
   255         
   256         template_storage = self.machineFolder + '\SecurityDVM\SecurityDVM.vmdk'
   257         
   258         # find template uuid
   259         template_uuid = ''
   260         for hdd in snaps.values():
   261             if hdd['Location'] == template_storage:
   262                 template_uuid = hdd['UUID']
   263         logger.debug('found parent uuid ' + template_uuid)
   264         
   265         # remove snapshots 
   266         for hdd in snaps.values():
   267             if hdd['Parent'] == template_uuid:
   268                 #template_uuid = hdd['UUID']
   269                 logger.debug('removing snapshot ' + hdd['UUID'])
   270                 checkResult(Cygwin.vboxExecute('closemedium disk {' + hdd['UUID'] + '} --delete'))#[1]
   271                 # parse result 0%...10%...20%...30%...40%...50%...60%...70%...80%...90%...100%
   272         
   273         self.changeStorageType(template_storage,'normal')
   274         self.storageAttach('SecurityDVM')
   275         self.startVM('SecurityDVM')
   276         self.waitStartup('SecurityDVM')
   277         checkResult(Cygwin.sshExecute('"sudo apt-get -y update"', VMManager.getHostOnlyIP('SecurityDVM'), 'osecuser', Cygwin.cygPath(self.machineFolder) + '/' + 'SecurityDVM' + '/dvm_key'))
   278         checkResult(Cygwin.sshExecute('"sudo apt-get -y upgrade"', VMManager.getHostOnlyIP('SecurityDVM'), 'osecuser', Cygwin.cygPath(self.machineFolder) + '/' + 'SecurityDVM' + '/dvm_key'))
   279         #self.stopVM('SecurityDVM')
   280         self.hibernateVM('SecurityDVM')
   281         self.waitShutdown('SecurityDVM')
   282         self.storageDetach('SecurityDVM')
   283         self.changeStorageType(template_storage,'immutable')
   284         self.storageAttach('SecurityDVM')
   285         self.rsdHandler = DeviceHandler(self)
   286         self.rsdHandler.start()
   287     
   288     #remove VM from the system. should be used on VMs returned by listSDVMs    
   289     def removeVM(self, vm_name):
   290         logger.info('Removing ' + vm_name)
   291         checkResult(Cygwin.vboxExecute('unregistervm ' + vm_name + ' --delete'))
   292         machineFolder = Cygwin.cygPath(self.machineFolder)
   293         checkResult(Cygwin.bashExecute('/usr/bin/rm -rf \\\"' + machineFolder + '/' + vm_name + '\\\"'))
   294     
   295     # start VM
   296     def startVM(self, vm_name):
   297         logger.info('Starting ' +  vm_name)
   298         result = checkResult(Cygwin.vboxExecute('startvm ' + vm_name + ' --type headless' ))
   299         while 'successfully started' not in result[1]:
   300             logger.error("Failed to start SDVM: " + vm_name + " retrying")
   301             logger.error("Command returned:\n" + result[2])
   302             time.sleep(1)
   303             result = checkResult(Cygwin.vboxExecute('startvm ' + vm_name + ' --type headless'))
   304         return result[0]
   305     
   306     # return wether VM is running or not
   307     def isVMRunning(self, vm_name):
   308         return vm_name in self.listRunningVMS()    
   309     
   310     # stop VM
   311     def stopVM(self, vm_name):
   312         logger.info('Sending shutdown signal to ' + vm_name)
   313         checkResult(Cygwin.sshExecute( '"sudo shutdown -h now"', VMManager.getHostOnlyIP(vm_name), 'osecuser', Cygwin.cygPath(self.machineFolder) + '/' + vm_name + '/dvm_key' ))
   314     
   315     # stop VM
   316     def hibernateVM(self, vm_name):
   317         logger.info('Sending hibernate-disk signal to ' + vm_name)
   318         checkResult(Cygwin.sshExecute( '"sudo hibernate-disk&"', VMManager.getHostOnlyIP(vm_name), 'osecuser', Cygwin.cygPath(self.machineFolder) + '/' + vm_name + '/dvm_key', wait_return=False))
   319             
   320     # poweroff VM
   321     def poweroffVM(self, vm_name):
   322         if not self.isVMRunning(vm_name):
   323             return
   324         logger.info('Powering off ' + vm_name)
   325         return checkResult(Cygwin.vboxExecute('controlvm ' + vm_name + ' poweroff'))
   326     
   327     #list the hostonly IFs exposed by the VBox host
   328     @staticmethod    
   329     def getHostOnlyIFs():
   330         result = Cygwin.vboxExecute('list hostonlyifs')[1]
   331         if result=='':
   332             return None
   333         props = dict((k.strip(),v.strip().strip('"')) for k,v in (line.split(':', 1) for line in result.strip().splitlines()))
   334         return props
   335     
   336     # return the hostOnly IP for a running guest or the host
   337     @staticmethod    
   338     def getHostOnlyIP(vm_name):
   339         if vm_name == None:
   340             logger.info('Getting hostOnly IP address for Host')
   341             return VMManager.getHostOnlyIFs()['IPAddress']
   342         else:
   343             logger.info('Getting hostOnly IP address ' + vm_name)
   344             result = checkResult(Cygwin.vboxExecute('guestproperty get ' + vm_name + ' /VirtualBox/GuestInfo/Net/0/V4/IP'))
   345             if result=='':
   346                 return None
   347             result = result[1]
   348             if result.startswith('No value set!'):
   349                 return None
   350             return result[result.index(':')+1:].strip()
   351             
   352     # attach removable storage device to VM by provision of filter
   353     def attachRSD(self, vm_name, rsd_filter):
   354         return checkResult(Cygwin.vboxExecute('usbfilter add 0 --target ' + vm_name + ' --name OpenSecurityRSD --vendorid ' + rsd_filter.vendorid + ' --productid ' + rsd_filter.productid + ' --revision ' + rsd_filter.revision))
   355     
   356     # detach removable storage from VM by 
   357     def detachRSD(self, vm_name):
   358         return checkResult(Cygwin.vboxExecute('usbfilter remove 0 --target ' + vm_name))
   359         
   360     # return the description set for an existing VM
   361     def getVMInfo(self, vm_name):
   362         results = checkResult(Cygwin.vboxExecute('showvminfo ' + vm_name + ' --machinereadable'))[1]
   363         props = dict((k.strip().strip('"'),v.strip().strip('"')) for k,v in (line.split('=', 1) for line in results.splitlines()))
   364         return props
   365     
   366     # return the configured USB filter for an existing VM 
   367     def getUSBFilter(self, vm_name):
   368         props = self.getVMInfo(vm_name)
   369         keys = set(['USBFilterVendorId1', 'USBFilterProductId1', 'USBFilterRevision1'])
   370         keyset = set(props.keys())
   371         usb_filter = None
   372         if keyset.issuperset(keys):
   373             usb_filter = USBFilter(props['USBFilterVendorId1'], props['USBFilterProductId1'], props['USBFilterRevision1'])
   374         return usb_filter
   375     
   376     #generates ISO containing authorized_keys for use with guest VM
   377     def genCertificateISO(self, vm_name):
   378         machineFolder = Cygwin.cygPath(self.machineFolder)
   379         # remove .ssh folder if exists
   380         checkResult(Cygwin.bashExecute('/usr/bin/rm -rf \\\"' + machineFolder + '/' + vm_name + '/.ssh\\\"'))
   381         # remove .ssh folder if exists
   382         checkResult(Cygwin.bashExecute('/usr/bin/rm -rf \\\"' + machineFolder + '/' + vm_name + '/dvm_key\\\"'))
   383         # create .ssh folder in vm_name
   384         checkResult(Cygwin.bashExecute('/usr/bin/mkdir -p \\\"' + machineFolder + '/' + vm_name + '/.ssh\\\"'))
   385         # generate dvm_key pair in vm_name / .ssh     
   386         checkResult(Cygwin.bashExecute('/usr/bin/ssh-keygen -q -t rsa -N \\\"\\\" -C \\\"' + vm_name + '\\\" -f \\\"' + machineFolder + '/' + vm_name + '/.ssh/dvm_key\\\"'))
   387         # move out private key
   388         checkResult(Cygwin.bashExecute('/usr/bin/mv \\\"' + machineFolder + '/' + vm_name + '/.ssh/dvm_key\\\" \\\"' + machineFolder + '/' + vm_name + '\\\"'))
   389         # set permissions for private key
   390         checkResult(Cygwin.bashExecute('/usr/bin/chmod 500 \\\"' + machineFolder + '/' + vm_name + '/dvm_key\\\"'))
   391         # rename public key to authorized_keys
   392         checkResult(Cygwin.bashExecute('/usr/bin/mv \\\"' + machineFolder + '/' + vm_name + '/.ssh/dvm_key.pub\\\" \\\"' + machineFolder + '/' + vm_name + '/.ssh/authorized_keys\\\"'))
   393         # set permissions for authorized_keys
   394         checkResult(Cygwin.bashExecute('/usr/bin/chmod 500 \\\"' + machineFolder + '/' + vm_name + '/.ssh/authorized_keys\\\"'))
   395         # generate iso image with .ssh/authorized keys
   396         checkResult(Cygwin.bashExecute('/usr/bin/genisoimage -J -R -o \\\"' + machineFolder + '/' + vm_name + '/'+ vm_name + '.iso\\\" \\\"' + machineFolder + '/' + vm_name + '/.ssh\\\"'))
   397     
   398     # attaches generated ssh public cert to guest vm
   399     def attachCertificateISO(self, vm_name):
   400         result = checkResult(Cygwin.vboxExecute('storageattach ' + vm_name + ' --storagectl SATA --port 1 --device 0 --type dvddrive --mtype readonly --medium \"' + self.machineFolder + '\\' + vm_name + '\\'+ vm_name + '.iso\"'))
   401         return result
   402     
   403     # wait for machine to come up
   404     def waitStartup(self, vm_name, timeout_ms = 30000):
   405         checkResult(Cygwin.vboxExecute('guestproperty wait ' + vm_name + ' SDVMStarted --timeout ' + str(timeout_ms) + ' --fail-on-timeout'))
   406         return VMManager.getHostOnlyIP(vm_name)
   407     
   408     # wait for machine to shutdown
   409     def waitShutdown(self, vm_name):
   410         while vm_name in self.listRunningVMS():
   411             time.sleep(1)
   412         return
   413         
   414     # handles browsing request    
   415     def handleBrowsingRequest(self):
   416         handler = BrowsingHandler(self)
   417         handler.start()
   418         return 'ok'
   419     
   420     #Small function to check the availability of network resource.
   421     #def isAvailable(self, path):
   422         #return os.path.exists(path)
   423         #result = Cygwin.cmdExecute('IF EXIST "' + path + '" echo YES')
   424         #return string.find(result[1], 'YES',)
   425     
   426     #Small function to check if the mention location is a directory
   427     def isDirectory(self, path):
   428         result = checkResult(Cygwin.cmdExecute('dir ' + path + ' | FIND ".."'))
   429         return string.find(result[1], 'DIR',)
   430 
   431     def mapNetworkDrive(self, drive, networkPath, user, password):
   432         self.unmapNetworkDrive(drive)
   433         #Check for drive availability
   434         if os.path.exists(drive):
   435             logger.error("Drive letter is already in use: " + drive)
   436             return -1
   437         #Check for network resource availability
   438         retry = 5
   439         while not os.path.exists(networkPath):
   440             time.sleep(1)
   441             if retry == 0:
   442                 return -1
   443             logger.info("Path not accessible: " + networkPath + " retrying")
   444             retry-=1
   445             #return -1
   446     
   447         command = 'USE ' + drive + ' ' + networkPath + ' /PERSISTENT:NO'
   448         if user != None:
   449             command += ' ' + password + ' /User' + user
   450     
   451         #TODO: Execute 'NET USE' command with authentication
   452         result = checkResult(Cygwin.execute('C:\\Windows\\system32\\net.exe', command))
   453         if string.find(result[1], 'successfully',) == -1:
   454             logger.error("Failed: NET " + command)
   455             return -1
   456         return 1
   457     
   458     def unmapNetworkDrive(self, drive):
   459         drives = self.getNetworkDrives()
   460         if drive not in drives.keys():
   461             return 1 
   462         result = checkResult(Cygwin.execute('C:\\Windows\\system32\\net.exe', 'USE ' + drive + ' /DELETE /YES'))
   463         if string.find(str(result[1]), 'successfully',) == -1:
   464             logger.error(result[2])
   465             return -1
   466         return 1
   467     
   468     def getNetworkDrives(self):
   469         ip = VMManager.getHostOnlyIP(None)
   470         ip = ip[:ip.rindex('.')]
   471         drives = dict()    
   472         result = checkResult(Cygwin.execute('C:\\Windows\\system32\\net.exe', 'USE'))
   473         for line in result[1].splitlines():
   474             if ip in line:
   475                 parts = line.split()
   476                 drives[parts[1]] = parts[2]
   477         return drives
   478             
   479     def genNetworkDrive(self):
   480         network_drives = self.getNetworkDrives()
   481         logical_drives = VMManager.getLogicalDrives()
   482         drives = list(map(chr, range(68, 91)))  
   483         for drive in drives:
   484             if drive+':' not in network_drives and drive not in logical_drives:
   485                 return drive+':'
   486 
   487     def getNetworkDrive(self, vm_name):
   488         ip = self.getHostOnlyIP(vm_name)
   489         result = checkResult(Cygwin.execute('C:\\Windows\\system32\\net.exe', 'USE'))
   490         for line in result[1].splitlines():
   491             if line != None and ip in line:
   492                 parts = line.split()
   493                 return parts[0]
   494     @staticmethod
   495     def getLogicalDrives():
   496         drive_bitmask = ctypes.cdll.kernel32.GetLogicalDrives()
   497         return list(itertools.compress(string.ascii_uppercase,  map(lambda x:ord(x) - ord('0'), bin(drive_bitmask)[:1:-1])))
   498     
   499     @staticmethod
   500     def getDriveType(drive):
   501         return ctypes.cdll.kernel32.GetDriveTypeW(u"%s:\\"%drive)
   502     
   503     @staticmethod
   504     def getVolumeInfo(drive):
   505         volumeNameBuffer = ctypes.create_unicode_buffer(1024)
   506         fileSystemNameBuffer = ctypes.create_unicode_buffer(1024)
   507         serial_number = None
   508         max_component_length = None
   509         file_system_flags = None
   510         
   511         rc = ctypes.cdll.kernel32.GetVolumeInformationW(
   512             #ctypes.c_wchar_p("F:\\"),
   513             u"%s:\\"%drive,
   514             volumeNameBuffer,
   515             ctypes.sizeof(volumeNameBuffer),
   516             serial_number,
   517             max_component_length,
   518             file_system_flags,
   519             fileSystemNameBuffer,
   520             ctypes.sizeof(fileSystemNameBuffer)
   521         )
   522         
   523         return volumeNameBuffer.value, fileSystemNameBuffer.value
   524 
   525 def checkResult(result):
   526     if result[0] != 0:
   527         logger.error('Command failed:\n' + result[2])
   528         raise OpenSecurityException('Command failed:' + ''.join(result[2]))
   529     return result
   530 
   531 
   532             
   533 # handles browsing request                    
   534 class BrowsingHandler(threading.Thread):   
   535     vmm = None
   536     #Cygwin.start_X11()
   537     def __init__(self, vmmanager):
   538         threading.Thread.__init__(self)
   539         self.vmm = vmmanager
   540      
   541     def run(self):
   542         drive = None
   543         try:
   544             new_sdvm = self.vmm.generateSDVMName()
   545             self.vmm.createVM(new_sdvm)
   546             self.vmm.storageAttach(new_sdvm)
   547             self.vmm.genCertificateISO(new_sdvm)
   548             self.vmm.attachCertificateISO(new_sdvm)
   549             self.vmm.startVM(new_sdvm)
   550             new_ip = self.vmm.waitStartup(new_sdvm)
   551             drive = self.vmm.genNetworkDrive()
   552             if new_ip != None:
   553                 self.vmm.mapNetworkDrive(drive, '\\\\' + new_ip + '\\Download', None, None)
   554             #browser = '/usr/bin/iceweasel'
   555             #browser = '/usr/bin/midori'
   556             #browser = '/usr/bin/chromium '
   557             browser = '\\\"/usr/bin/chromium; pidof dbus-launch | xargs kill\\\"'
   558             Cygwin.start_X11()
   559            
   560             #if Cygwin.is_X11_running()==True:
   561             #result = checkResult(Cygwin.bashExecute('DISPLAY=:0 xhost '+new_ip))
   562             result = checkResult(Cygwin.sshExecuteX11(browser, new_ip, 'osecuser', Cygwin.cygPath(self.vmm.getMachineFolder()) + '/' + new_sdvm + '/dvm_key'))
   563         except:
   564             logger.error("BrowsingHandler failed. Cleaning up")
   565         if drive != None:    
   566             self.vmm.unmapNetworkDrive(drive)
   567         self.vmm.poweroffVM(new_sdvm)
   568         self.vmm.removeVM(new_sdvm)
   569                 
   570 class DeviceHandler(threading.Thread): 
   571     vmm = None
   572     attachedRSDs = None  
   573     connectedRSDs = None
   574     running = True
   575     def __init__(self, vmmanger): 
   576         threading.Thread.__init__(self)
   577         self.vmm = vmmanger
   578  
   579     def stop(self):
   580         self.running = False
   581         
   582     def run(self):
   583         self.connectedRSDs = dict()
   584         while self.running:
   585             tmp_rsds = self.vmm.getConnectedRSDS()
   586             
   587             self.attachedRSDs = self.vmm.getAttachedRSDs()
   588             for vm_name in self.attachedRSDs.keys():
   589                 if self.attachedRSDs[vm_name] not in tmp_rsds.values():
   590                     drive = self.vmm.getNetworkDrive(vm_name)
   591                     self.vmm.unmapNetworkDrive(drive)
   592                     #self.stopVM(vm_name)
   593                     self.vmm.detachRSD(vm_name)
   594                     self.vmm.poweroffVM(vm_name)
   595                     self.vmm.removeVM(vm_name)
   596                     break
   597                     
   598                     
   599             if tmp_rsds.keys() == self.connectedRSDs.keys():
   600                 logger.debug("Nothing's changed. sleep(3)")
   601                 time.sleep(3)
   602                 continue
   603             
   604             logger.info("Something's changed")          
   605             self.connectedRSDs = tmp_rsds
   606             
   607             
   608             
   609             #create new vm for attached device if any
   610             self.attachedRSDs = self.vmm.getAttachedRSDs()
   611             self.connectedRSDs = self.vmm.getConnectedRSDS()
   612             
   613             new_ip = None
   614             for connected_device in self.connectedRSDs.values():
   615                 if (self.attachedRSDs and False) or (connected_device not in self.attachedRSDs.values()):
   616                     new_sdvm = self.vmm.generateSDVMName()
   617                     self.vmm.createVM(new_sdvm)
   618                     self.vmm.storageAttach(new_sdvm)
   619                     self.vmm.attachRSD(new_sdvm, connected_device)
   620                     self.vmm.startVM(new_sdvm)
   621                     new_ip = self.vmm.waitStartup(new_sdvm)
   622                     drive = self.vmm.genNetworkDrive()
   623                     if new_ip != None:
   624                         self.vmm.mapNetworkDrive(drive, '\\\\' + new_ip + '\\USB', None, None)
   625 
   626 if __name__ == '__main__':
   627     #man = VMManager.getInstance()
   628     #man.listVM()
   629     #print man.getConnectedRSDs()
   630     #print man.getNetworkDrives()
   631     #man.genNetworkDrive()
   632     #drive_bitmask = ctypes.cdll.kernel32.GetLogicalDrives()
   633     #print list(itertools.compress(string.ascii_uppercase,  map(lambda x:ord(x) - ord('0'), bin(drive_bitmask)[:1:-1])))
   634     #print list(map(chr, range(68, 91))) 
   635     #print Cygwin.getRegEntry('SYSTEM\CurrentControlSet\Enum\USB', 'VID_1058&PID_0704')[0]
   636     #devices = VMManager.getConnectedRSDS()
   637     #print devices
   638     
   639     drives = VMManager.getLogicalDrives()
   640     print drives
   641     print VMManager.getDriveType("E")
   642     print VMManager.getVolumeInfo("E")
   643     #for device in devices.values():
   644     #    #print device
   645     #    if VMManager.isMassStorageDevice(device):
   646     #        print device
   647         
   648     
   649     
   650     #time.sleep(-1)
   651     #man.listVM()
   652     #man.listVM()
   653     #man.listVM()
   654     #man.listVM()
   655     #man.genCertificateISO('SecurityDVM0')
   656     #man.guestExecute('SecurityDVM0', '/bin/ls -la')
   657     #logger = setupLogger('VMManager')
   658     #c = Cygwin()
   659     
   660     #man.sshExecute('/bin/ls -la', 'SecurityDVM0')
   661     #man.sshExecuteX11('/usr/bin/iceweasel', 'SecurityDVM0')
   662     #man.removeVM('SecurityDVM0')
   663     #man.netUse('192.168.56.134', 'USB\\')
   664     #ip = '192.168.56.139'
   665     
   666     #man.cygwin_path = 'c:\\cygwin64\\bin\\'
   667     #man.handleDeviceChange()
   668     #print man.listSDVM()
   669     #man.configureHostNetworking()
   670     #new_vm = man.generateSDVMName()
   671     #man.createVM(new_vm)
   672     
   673     #print Cygwin.cmd()
   674     #man.isAvailable('c:')
   675     #ip = man.getHostOnlyIP('SecurityDVM0')
   676     #man.mapNetworkDrive('h:', '\\\\' + ip + '\Download', None, None)
   677     
   678     #man.genCertificateISO(new_vm)
   679     #man.attachCertificateISO(new_vm)
   680     
   681     #man.attachCertificateISO(vm_name)
   682     #man.guestExecute(vm_name, "ls")
   683     #man.sshGuestX11Execute('SecurityDVM1', '/usr/bin/iceweasel')
   684     #time.sleep(60)
   685     #print man.cygwinPath("C:\Users\BarthaM\VirtualBox VMs\SecurityDVM\.ssh\*")
   686     #man.genCertificateISO('SecurityDVM')
   687     #man.attachCertificateISO('SecurityDVM')
   688     #man.isStorageAttached('SecurityDVM')
   689     #man.guestExecute('SecurityDVM', 'sudo apt-get -y update')
   690     #man.guestExecute('SecurityDVM', 'sudo apt-get -y upgrade' )
   691     
   692     #man.stopVM('SecurityDVM')
   693     #man.storageDetach('SecurityDVM')
   694     #man.changeStorageType('C:\Users\BarthaM\VirtualBox VMs\SecurityDVM\SecurityDVM.vmdk','immutable')
   695     #man.storageAttach('SecurityDVM')
   696     
   697     
   698     #cmd = "c:\\cygwin64\\bin\\bash.exe --login -c \"/bin/ls\""
   699     #man.execute(cmd)