OpenSecurity/bin/vmmanager.pyw
author BarthaM@N3SIM1218.D03.arc.local
Thu, 03 Apr 2014 09:52:11 +0100
changeset 125 7149f29e9570
parent 110 490a78181935
child 129 abf3500eaf87
permissions -rwxr-xr-x
added sdvm cleanup method
     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             time.sleep(1)
   302             result = checkResult(Cygwin.vboxExecute('startvm ' + vm_name + ' --type headless'))
   303         return result[0]
   304     
   305     # return wether VM is running or not
   306     def isVMRunning(self, vm_name):
   307         return vm_name in self.listRunningVMS()    
   308     
   309     # stop VM
   310     def stopVM(self, vm_name):
   311         logger.info('Sending shutdown signal to ' + vm_name)
   312         checkResult(Cygwin.sshExecute( '"sudo shutdown -h now"', VMManager.getHostOnlyIP(vm_name), 'osecuser', Cygwin.cygPath(self.machineFolder) + '/' + vm_name + '/dvm_key' ))
   313     
   314     # stop VM
   315     def hibernateVM(self, vm_name):
   316         logger.info('Sending hibernate-disk signal to ' + vm_name)
   317         checkResult(Cygwin.sshExecute( '"sudo hibernate-disk&"', VMManager.getHostOnlyIP(vm_name), 'osecuser', Cygwin.cygPath(self.machineFolder) + '/' + vm_name + '/dvm_key', wait_return=False))
   318             
   319     # poweroff VM
   320     def poweroffVM(self, vm_name):
   321         if not self.isVMRunning(vm_name):
   322             return
   323         logger.info('Powering off ' + vm_name)
   324         return checkResult(Cygwin.vboxExecute('controlvm ' + vm_name + ' poweroff'))
   325     
   326     #list the hostonly IFs exposed by the VBox host
   327     @staticmethod    
   328     def getHostOnlyIFs():
   329         result = Cygwin.vboxExecute('list hostonlyifs')[1]
   330         if result=='':
   331             return None
   332         props = dict((k.strip(),v.strip().strip('"')) for k,v in (line.split(':', 1) for line in result.strip().splitlines()))
   333         return props
   334     
   335     # return the hostOnly IP for a running guest or the host
   336     @staticmethod    
   337     def getHostOnlyIP(vm_name):
   338         if vm_name == None:
   339             logger.info('Gettting hostOnly IP address for Host')
   340             return VMManager.getHostOnlyIFs()['IPAddress']
   341         else:
   342             logger.info('Gettting hostOnly IP address ' + vm_name)
   343             result = checkResult(Cygwin.vboxExecute('guestproperty get ' + vm_name + ' /VirtualBox/GuestInfo/Net/0/V4/IP'))
   344             if result=='':
   345                 return None
   346             result = result[1]
   347             if result.startswith('No value set!'):
   348                 return None
   349             return result[result.index(':')+1:].strip()
   350             
   351     # attach removable storage device to VM by provision of filter
   352     def attachRSD(self, vm_name, rsd_filter):
   353         return checkResult(Cygwin.vboxExecute('usbfilter add 0 --target ' + vm_name + ' --name OpenSecurityRSD --vendorid ' + rsd_filter.vendorid + ' --productid ' + rsd_filter.productid + ' --revision ' + rsd_filter.revision))
   354     
   355     # detach removable storage from VM by 
   356     def detachRSD(self, vm_name):
   357         return checkResult(Cygwin.vboxExecute('usbfilter remove 0 --target ' + vm_name))
   358         
   359     # return the description set for an existing VM
   360     def getVMInfo(self, vm_name):
   361         results = checkResult(Cygwin.vboxExecute('showvminfo ' + vm_name + ' --machinereadable'))[1]
   362         props = dict((k.strip().strip('"'),v.strip().strip('"')) for k,v in (line.split('=', 1) for line in results.splitlines()))
   363         return props
   364     
   365     # return the configured USB filter for an existing VM 
   366     def getUSBFilter(self, vm_name):
   367         props = self.getVMInfo(vm_name)
   368         keys = set(['USBFilterVendorId1', 'USBFilterProductId1', 'USBFilterRevision1'])
   369         keyset = set(props.keys())
   370         usb_filter = None
   371         if keyset.issuperset(keys):
   372             usb_filter = USBFilter(props['USBFilterVendorId1'], props['USBFilterProductId1'], props['USBFilterRevision1'])
   373         return usb_filter
   374     
   375     #generates ISO containing authorized_keys for use with guest VM
   376     def genCertificateISO(self, vm_name):
   377         machineFolder = Cygwin.cygPath(self.machineFolder)
   378         # remove .ssh folder if exists
   379         checkResult(Cygwin.bashExecute('/usr/bin/rm -rf \\\"' + machineFolder + '/' + vm_name + '/.ssh\\\"'))
   380         # remove .ssh folder if exists
   381         checkResult(Cygwin.bashExecute('/usr/bin/rm -rf \\\"' + machineFolder + '/' + vm_name + '/dvm_key\\\"'))
   382         # create .ssh folder in vm_name
   383         checkResult(Cygwin.bashExecute('/usr/bin/mkdir -p \\\"' + machineFolder + '/' + vm_name + '/.ssh\\\"'))
   384         # generate dvm_key pair in vm_name / .ssh     
   385         checkResult(Cygwin.bashExecute('/usr/bin/ssh-keygen -q -t rsa -N \\\"\\\" -C \\\"' + vm_name + '\\\" -f \\\"' + machineFolder + '/' + vm_name + '/.ssh/dvm_key\\\"'))
   386         # move out private key
   387         checkResult(Cygwin.bashExecute('/usr/bin/mv \\\"' + machineFolder + '/' + vm_name + '/.ssh/dvm_key\\\" \\\"' + machineFolder + '/' + vm_name + '\\\"'))
   388         # set permissions for private key
   389         checkResult(Cygwin.bashExecute('/usr/bin/chmod 500 \\\"' + machineFolder + '/' + vm_name + '/dvm_key\\\"'))
   390         # rename public key to authorized_keys
   391         checkResult(Cygwin.bashExecute('/usr/bin/mv \\\"' + machineFolder + '/' + vm_name + '/.ssh/dvm_key.pub\\\" \\\"' + machineFolder + '/' + vm_name + '/.ssh/authorized_keys\\\"'))
   392         # set permissions for authorized_keys
   393         checkResult(Cygwin.bashExecute('/usr/bin/chmod 500 \\\"' + machineFolder + '/' + vm_name + '/.ssh/authorized_keys\\\"'))
   394         # generate iso image with .ssh/authorized keys
   395         checkResult(Cygwin.bashExecute('/usr/bin/genisoimage -J -R -o \\\"' + machineFolder + '/' + vm_name + '/'+ vm_name + '.iso\\\" \\\"' + machineFolder + '/' + vm_name + '/.ssh\\\"'))
   396     
   397     # attaches generated ssh public cert to guest vm
   398     def attachCertificateISO(self, vm_name):
   399         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\"'))
   400         return result
   401     
   402     # wait for machine to come up
   403     def waitStartup(self, vm_name, timeout_ms = 30000):
   404         checkResult(Cygwin.vboxExecute('guestproperty wait ' + vm_name + ' SDVMStarted --timeout ' + str(timeout_ms) + ' --fail-on-timeout'))
   405         return VMManager.getHostOnlyIP(vm_name)
   406     
   407     # wait for machine to shutdown
   408     def waitShutdown(self, vm_name):
   409         while vm_name in self.listRunningVMS():
   410             time.sleep(1)
   411         return
   412         
   413     # handles browsing request    
   414     def handleBrowsingRequest(self):
   415         handler = BrowsingHandler(self)
   416         handler.start()
   417         return 'ok'
   418     
   419     #Small function to check the availability of network resource.
   420     #def isAvailable(self, path):
   421         #return os.path.exists(path)
   422         #result = Cygwin.cmdExecute('IF EXIST "' + path + '" echo YES')
   423         #return string.find(result[1], 'YES',)
   424     
   425     #Small function to check if the mention location is a directory
   426     def isDirectory(self, path):
   427         result = checkResult(Cygwin.cmdExecute('dir ' + path + ' | FIND ".."'))
   428         return string.find(result[1], 'DIR',)
   429 
   430     def mapNetworkDrive(self, drive, networkPath, user, password):
   431         self.unmapNetworkDrive(drive)
   432         #Check for drive availability
   433         if os.path.exists(drive):
   434             logger.error("Drive letter is already in use: " + drive)
   435             return -1
   436         #Check for network resource availability
   437         retry = 5
   438         while not os.path.exists(networkPath):
   439             time.sleep(1)
   440             if retry == 0:
   441                 return -1
   442             logger.info("Path not accessible: " + networkPath + " retrying")
   443             retry-=1
   444             #return -1
   445     
   446         command = 'USE ' + drive + ' ' + networkPath + ' /PERSISTENT:NO'
   447         if user != None:
   448             command += ' ' + password + ' /User' + user
   449     
   450         #TODO: Execute 'NET USE' command with authentication
   451         result = checkResult(Cygwin.execute('C:\\Windows\\system32\\net.exe', command))
   452         if string.find(result[1], 'successfully',) == -1:
   453             logger.error("Failed: NET " + command)
   454             return -1
   455         return 1
   456     
   457     def unmapNetworkDrive(self, drive):
   458         drives = self.getNetworkDrives()
   459         if drive not in drives.keys():
   460             return 1 
   461         result = checkResult(Cygwin.execute('C:\\Windows\\system32\\net.exe', 'USE ' + drive + ' /DELETE /YES'))
   462         if string.find(str(result[1]), 'successfully',) == -1:
   463             logger.error(result[2])
   464             return -1
   465         return 1
   466     
   467     def getNetworkDrives(self):
   468         ip = VMManager.getHostOnlyIP(None)
   469         ip = ip[:ip.rindex('.')]
   470         drives = dict()    
   471         result = checkResult(Cygwin.execute('C:\\Windows\\system32\\net.exe', 'USE'))
   472         for line in result[1].splitlines():
   473             if ip in line:
   474                 parts = line.split()
   475                 drives[parts[1]] = parts[2]
   476         return drives
   477             
   478     def genNetworkDrive(self):
   479         network_drives = self.getNetworkDrives()
   480         logical_drives = VMManager.getLogicalDrives()
   481         drives = list(map(chr, range(68, 91)))  
   482         for drive in drives:
   483             if drive+':' not in network_drives and drive not in logical_drives:
   484                 return drive+':'
   485 
   486     def getNetworkDrive(self, vm_name):
   487         ip = self.getHostOnlyIP(vm_name)
   488         result = checkResult(Cygwin.execute('C:\\Windows\\system32\\net.exe', 'USE'))
   489         for line in result[1].splitlines():
   490             if line != None and ip in line:
   491                 parts = line.split()
   492                 return parts[0]
   493     @staticmethod
   494     def getLogicalDrives():
   495         drive_bitmask = ctypes.cdll.kernel32.GetLogicalDrives()
   496         return list(itertools.compress(string.ascii_uppercase,  map(lambda x:ord(x) - ord('0'), bin(drive_bitmask)[:1:-1])))
   497     
   498     @staticmethod
   499     def getDriveType(drive):
   500         return ctypes.cdll.kernel32.GetDriveTypeW(u"%s:\\"%drive)
   501     
   502     @staticmethod
   503     def getVolumeInfo(drive):
   504         volumeNameBuffer = ctypes.create_unicode_buffer(1024)
   505         fileSystemNameBuffer = ctypes.create_unicode_buffer(1024)
   506         serial_number = None
   507         max_component_length = None
   508         file_system_flags = None
   509         
   510         rc = ctypes.cdll.kernel32.GetVolumeInformationW(
   511             #ctypes.c_wchar_p("F:\\"),
   512             u"%s:\\"%drive,
   513             volumeNameBuffer,
   514             ctypes.sizeof(volumeNameBuffer),
   515             serial_number,
   516             max_component_length,
   517             file_system_flags,
   518             fileSystemNameBuffer,
   519             ctypes.sizeof(fileSystemNameBuffer)
   520         )
   521         
   522         return volumeNameBuffer.value, fileSystemNameBuffer.value
   523 
   524 def checkResult(result):
   525     if result[0] != 0:
   526         logger.error('Command failed:' + ''.join(result[2]))
   527         raise OpenSecurityException('Command failed:' + ''.join(result[2]))
   528     return result
   529 
   530 
   531             
   532 # handles browsing request                    
   533 class BrowsingHandler(threading.Thread):   
   534     vmm = None
   535     #Cygwin.start_X11()
   536     def __init__(self, vmmanager):
   537         threading.Thread.__init__(self)
   538         self.vmm = vmmanager
   539      
   540     def run(self):
   541         drive = None
   542         try:
   543             new_sdvm = self.vmm.generateSDVMName()
   544             self.vmm.createVM(new_sdvm)
   545             self.vmm.storageAttach(new_sdvm)
   546             self.vmm.genCertificateISO(new_sdvm)
   547             self.vmm.attachCertificateISO(new_sdvm)
   548             self.vmm.startVM(new_sdvm)
   549             new_ip = self.vmm.waitStartup(new_sdvm)
   550             drive = self.vmm.genNetworkDrive()
   551             if new_ip != None:
   552                 self.vmm.mapNetworkDrive(drive, '\\\\' + new_ip + '\\Download', None, None)
   553             #browser = '/usr/bin/iceweasel'
   554             #browser = '/usr/bin/midori'
   555             #browser = '/usr/bin/chromium '
   556             browser = '\\\"/usr/bin/chromium; pidof dbus-launch | xargs kill\\\"'
   557             Cygwin.start_X11()
   558            
   559             #if Cygwin.is_X11_running()==True:
   560             #result = checkResult(Cygwin.bashExecute('DISPLAY=:0 xhost '+new_ip))
   561             result = checkResult(Cygwin.sshExecuteX11(browser, new_ip, 'osecuser', Cygwin.cygPath(self.vmm.getMachineFolder()) + '/' + new_sdvm + '/dvm_key'))
   562         except:
   563             logger.error("BrowsingHandler failed. Cleaning up")
   564         if drive != None:    
   565             self.vmm.unmapNetworkDrive(drive)
   566         self.vmm.poweroffVM(new_sdvm)
   567         self.vmm.removeVM(new_sdvm)
   568                 
   569 class DeviceHandler(threading.Thread): 
   570     vmm = None
   571     attachedRSDs = None  
   572     connectedRSDs = None
   573     running = True
   574     def __init__(self, vmmanger): 
   575         threading.Thread.__init__(self)
   576         self.vmm = vmmanger
   577  
   578     def stop(self):
   579         self.running = False
   580         
   581     def run(self):
   582         self.connectedRSDs = dict()
   583         while self.running:
   584             tmp_rsds = self.vmm.getConnectedRSDS()
   585             
   586             self.attachedRSDs = self.vmm.getAttachedRSDs()
   587             for vm_name in self.attachedRSDs.keys():
   588                 if self.attachedRSDs[vm_name] not in tmp_rsds.values():
   589                     drive = self.vmm.getNetworkDrive(vm_name)
   590                     self.vmm.unmapNetworkDrive(drive)
   591                     #self.stopVM(vm_name)
   592                     self.vmm.detachRSD(vm_name)
   593                     self.vmm.poweroffVM(vm_name)
   594                     self.vmm.removeVM(vm_name)
   595                     break
   596                     
   597                     
   598             if tmp_rsds.keys() == self.connectedRSDs.keys():
   599                 logger.debug("Nothing's changed. sleep(3)")
   600                 time.sleep(3)
   601                 continue
   602             
   603             logger.info("Something's changed")          
   604             self.connectedRSDs = tmp_rsds
   605             
   606             
   607             
   608             #create new vm for attached device if any
   609             self.attachedRSDs = self.vmm.getAttachedRSDs()
   610             self.connectedRSDs = self.vmm.getConnectedRSDS()
   611             
   612             new_ip = None
   613             for connected_device in self.connectedRSDs.values():
   614                 if (self.attachedRSDs and False) or (connected_device not in self.attachedRSDs.values()):
   615                     new_sdvm = self.vmm.generateSDVMName()
   616                     self.vmm.createVM(new_sdvm)
   617                     self.vmm.storageAttach(new_sdvm)
   618                     self.vmm.attachRSD(new_sdvm, connected_device)
   619                     self.vmm.startVM(new_sdvm)
   620                     new_ip = self.vmm.waitStartup(new_sdvm)
   621                     drive = self.vmm.genNetworkDrive()
   622                     if new_ip != None:
   623                         self.vmm.mapNetworkDrive(drive, '\\\\' + new_ip + '\\USB', None, None)
   624 
   625 if __name__ == '__main__':
   626     #man = VMManager.getInstance()
   627     #man.listVM()
   628     #print man.getConnectedRSDs()
   629     #print man.getNetworkDrives()
   630     #man.genNetworkDrive()
   631     #drive_bitmask = ctypes.cdll.kernel32.GetLogicalDrives()
   632     #print list(itertools.compress(string.ascii_uppercase,  map(lambda x:ord(x) - ord('0'), bin(drive_bitmask)[:1:-1])))
   633     #print list(map(chr, range(68, 91))) 
   634     #print Cygwin.getRegEntry('SYSTEM\CurrentControlSet\Enum\USB', 'VID_1058&PID_0704')[0]
   635     #devices = VMManager.getConnectedRSDS()
   636     #print devices
   637     
   638     drives = VMManager.getLogicalDrives()
   639     print drives
   640     print VMManager.getDriveType("E")
   641     print VMManager.getVolumeInfo("E")
   642     #for device in devices.values():
   643     #    #print device
   644     #    if VMManager.isMassStorageDevice(device):
   645     #        print device
   646         
   647     
   648     
   649     #time.sleep(-1)
   650     #man.listVM()
   651     #man.listVM()
   652     #man.listVM()
   653     #man.listVM()
   654     #man.genCertificateISO('SecurityDVM0')
   655     #man.guestExecute('SecurityDVM0', '/bin/ls -la')
   656     #logger = setupLogger('VMManager')
   657     #c = Cygwin()
   658     
   659     #man.sshExecute('/bin/ls -la', 'SecurityDVM0')
   660     #man.sshExecuteX11('/usr/bin/iceweasel', 'SecurityDVM0')
   661     #man.removeVM('SecurityDVM0')
   662     #man.netUse('192.168.56.134', 'USB\\')
   663     #ip = '192.168.56.139'
   664     
   665     #man.cygwin_path = 'c:\\cygwin64\\bin\\'
   666     #man.handleDeviceChange()
   667     #print man.listSDVM()
   668     #man.configureHostNetworking()
   669     #new_vm = man.generateSDVMName()
   670     #man.createVM(new_vm)
   671     
   672     #print Cygwin.cmd()
   673     #man.isAvailable('c:')
   674     #ip = man.getHostOnlyIP('SecurityDVM0')
   675     #man.mapNetworkDrive('h:', '\\\\' + ip + '\Download', None, None)
   676     
   677     #man.genCertificateISO(new_vm)
   678     #man.attachCertificateISO(new_vm)
   679     
   680     #man.attachCertificateISO(vm_name)
   681     #man.guestExecute(vm_name, "ls")
   682     #man.sshGuestX11Execute('SecurityDVM1', '/usr/bin/iceweasel')
   683     #time.sleep(60)
   684     #print man.cygwinPath("C:\Users\BarthaM\VirtualBox VMs\SecurityDVM\.ssh\*")
   685     #man.genCertificateISO('SecurityDVM')
   686     #man.attachCertificateISO('SecurityDVM')
   687     #man.isStorageAttached('SecurityDVM')
   688     #man.guestExecute('SecurityDVM', 'sudo apt-get -y update')
   689     #man.guestExecute('SecurityDVM', 'sudo apt-get -y upgrade' )
   690     
   691     #man.stopVM('SecurityDVM')
   692     #man.storageDetach('SecurityDVM')
   693     #man.changeStorageType('C:\Users\BarthaM\VirtualBox VMs\SecurityDVM\SecurityDVM.vmdk','immutable')
   694     #man.storageAttach('SecurityDVM')
   695     
   696     
   697     #cmd = "c:\\cygwin64\\bin\\bash.exe --login -c \"/bin/ls\""
   698     #man.execute(cmd)