merge
authorOliver Maurhart <oliver.maurhart@ait.ac.at>
Mon, 31 Mar 2014 15:28:48 +0200
changeset 1059cc91074deb8
parent 104 e30b476d23a0
parent 99 fff411611308
child 106 c5101320b46c
merge
OpenSecurity/bin/opensecurity_tray.pyw
     1.1 --- a/OpenSecurity.iss	Mon Mar 31 15:26:56 2014 +0200
     1.2 +++ b/OpenSecurity.iss	Mon Mar 31 15:28:48 2014 +0200
     1.3 @@ -8,12 +8,12 @@
     1.4  AppContact=AIT Austrian Institute of Technology
     1.5  AppPublisher=AIT Austrian Institute of Technology
     1.6  AppPublisherURL=http://www.ait.ac.at/
     1.7 -AppVersion=0.2.2
     1.8 +AppVersion=0.2.3
     1.9  ArchitecturesInstallIn64BitMode=x64
    1.10  DefaultDirName={pf}\OpenSecurity
    1.11  DefaultGroupName=OpenSecurity
    1.12  OutputDir="."
    1.13 -OutputBaseFilename="OpenSecurity Setup V0.2.2"
    1.14 +OutputBaseFilename="OpenSecurity Setup V0.2.3"
    1.15  OutputManifestFile=OpenSecurity-Setup-Manifest.txt
    1.16  SetupIconFile=OpenSecurity\gfx\OpenSecurity.ico
    1.17  SolidCompression=yes
    1.18 @@ -26,6 +26,8 @@
    1.19  Source: "OpenSecurity\gfx\*"; DestDir: "{app}\gfx"; Flags: recursesubdirs createallsubdirs;
    1.20  Source: "OpenSecurity\install\*"; DestDir: "{app}\install"; Flags: recursesubdirs createallsubdirs;
    1.21  Source: "OpenSecurity\python27\*"; DestDir: "{app}\python27"; Flags: recursesubdirs createallsubdirs;
    1.22 +Source: "OpenSecurity\python27\python27.dll"; DestDir: "{sys}"; Flags: sharedfile;
    1.23 +Source: "OpenSecurity\python27\Lib\site-packages\pywin32_system32\pywintypes27.dll"; DestDir: "{sys}"; Flags: sharedfile;
    1.24  
    1.25  [Dirs]
    1.26  Name: "{app}\cygwin64\var\log\xwin"; Permissions: everyone-modify
    1.27 @@ -45,7 +47,6 @@
    1.28  Filename: "{app}\cygwin64\bin\dash.exe"; Parameters: "/bin/rebaseall"; Description: "Rebasing background system"; WorkingDir: "{app}"; StatusMsg: "Rebasing background system..."; Flags: runascurrentuser
    1.29  Filename: "{app}\install\fix_cygwin_paths.bat"; Description: "Fixing Cygwin paths"; WorkingDir: "{app}\install"; StatusMsg: "Fixing Cygwin Paths...";
    1.30  Filename: "{app}\cygwin64\bin\bash.exe"; Parameters: "-l -i -c echo -n"; Description: "Enforcing login environment for shells"; WorkingDir: "{app}"; StatusMsg: "Enforcing login environment for shells...";
    1.31 -Filename: "{app}\python27\pythonw.exe"; Parameters: """{app}python27\Scripts\pywin32_postinstall.py"" --install"; Description: "Registering Python Win32 Extensions"; WorkingDir: "{app}"; StatusMsg: "Registering Python Win32 Extensions"; Flags: runascurrentuser
    1.32  Filename: "{app}\python27\pythonw.exe"; Parameters: """{app}\bin\opensecurity_service.pyw"" --startup auto install"; Description: "Installing the OpenSecurity Service"; WorkingDir: "{app}"; StatusMsg: "Installing the OpenSecurity Service"; Flags: runascurrentuser
    1.33  Filename: "{app}\python27\pythonw.exe"; Parameters: """{app}\bin\opensecurity_service.pyw"" start"; Description: "Starting OpenSecurity Service"; WorkingDir: "{app}"; StatusMsg: "Starting OpenSecurity Service"; Flags: runascurrentuser
    1.34  Filename: "{app}\python27\pythonw.exe"; Parameters: """{app}\bin\opensecurity_tray.pyw"""; WorkingDir: "{userappdata}"; Description: "Launching OpenSecurity Tray Icon"; Flags: nowait
    1.35 @@ -54,7 +55,6 @@
    1.36  ; When uninstalling run this command prior
    1.37  Filename: "{app}\python27\pythonw.exe"; Parameters: """{app}\bin\opensecurity_service.pyw"" stop"; WorkingDir: "{app}"; StatusMsg: "Stopping the OpenSecurity Service"; Flags: runascurrentuser
    1.38  Filename: "{app}\python27\pythonw.exe"; Parameters: """{app}\bin\opensecurity_service.pyw"" remove"; WorkingDir: "{app}"; StatusMsg: "Removing the OpenSecurity Service"; Flags: runascurrentuser
    1.39 -Filename: "{app}\python27\pythonw.exe"; Parameters: """{app}python27\Scripts\pywin32_postinstall.py"" --uninstall"; WorkingDir: "{app}"; StatusMsg: "Unregistering Python Win32 Extensions"; Flags: runascurrentuser
    1.40  
    1.41  [UninstallDelete]
    1.42  Type: filesandordirs; Name: "{app}"
     2.1 --- a/OpenSecurity/bin/cygwin.py	Mon Mar 31 15:26:56 2014 +0200
     2.2 +++ b/OpenSecurity/bin/cygwin.py	Mon Mar 31 15:28:48 2014 +0200
     2.3 @@ -197,12 +197,12 @@
     2.4      # executes command over ssh on guest vm with X forwarding
     2.5      @staticmethod
     2.6      def sshExecuteX11(command, address, user_name, certificate, wait_return=True):
     2.7 -        return Cygwin.bashExecute('"DISPLAY=:0.0 /usr/bin/ssh -v -Y -i \\"' + certificate +'\\" ' + user_name + '@' + address + ' ' + command + '\"')
     2.8 +        return Cygwin.bashExecute('DISPLAY=:0.0 /usr/bin/ssh -v -Y -i \\\"' + certificate +'\\\" ' + user_name + '@' + address + ' ' + command + '')
     2.9  
    2.10      @staticmethod
    2.11      def is_X11_running():
    2.12          """check if we can connect to a X11 running instance"""
    2.13 -        p = Cygwin.bashExecute('DISPLAY=:0 /usr/bin/xset -q')
    2.14 +        p = Cygwin.bashExecute('DISPLAY=:0 xset -q') #/usr/bin/
    2.15          return p[0] == 0
    2.16          
    2.17          
    2.18 @@ -232,5 +232,4 @@
    2.19      print(c.bashExecute('echo $PATH')[1])
    2.20      print(c.cygPath('C:'))
    2.21      print('C:\\Program Files\\OpenSecurity: ' + c.cygPath('C:\\Program Files\\OpenSecurity'))
    2.22 -    c.start_X11()
    2.23 -
    2.24 +    c.start_X11()
     3.1 --- a/OpenSecurity/bin/opensecurity_tray.pyw	Mon Mar 31 15:26:56 2014 +0200
     3.2 +++ b/OpenSecurity/bin/opensecurity_tray.pyw	Mon Mar 31 15:28:48 2014 +0200
     3.3 @@ -48,7 +48,6 @@
     3.4  from ui import AboutDialog
     3.5  from ui import opensecurity_rc
     3.6  
     3.7 -
     3.8  # ------------------------------------------------------------
     3.9  # code
    3.10  
    3.11 @@ -110,7 +109,6 @@
    3.12          try:
    3.13          
    3.14              # get a proper browsing VM
    3.15 -            Cygwin.start_X11()
    3.16              browsing_vm = urllib2.urlopen('http://127.0.0.1:8080/browsing').readline()
    3.17              #dlg_launch_image = os.path.join(sys.path[0], 'launch.pyw')
    3.18              #process_command = [sys.executable, dlg_launch_image, browsing_vm, '/usr/bin/iceweasel']
     4.1 --- a/OpenSecurity/bin/opensecurityd.pyw	Mon Mar 31 15:26:56 2014 +0200
     4.2 +++ b/OpenSecurity/bin/opensecurityd.pyw	Mon Mar 31 15:28:48 2014 +0200
     4.3 @@ -50,7 +50,7 @@
     4.4  # ------------------------------------------------------------
     4.5  # const
     4.6  
     4.7 -__version__ = "0.2"
     4.8 +__version__ = "0.2.3"
     4.9  
    4.10  
    4.11  """All the URLs we know mapping to class handler"""
    4.12 @@ -385,6 +385,8 @@
    4.13      global gvm_mgr
    4.14      gvm_mgr = vmmanager.VMManager.getInstance()
    4.15      
    4.16 +    # tweak sys.argv to control wep.py server start behavior
    4.17 +    sys.argv = [__file__, "8080"]
    4.18      server = web.application(opensecurity_urls, globals(), autoreload = False)
    4.19      server.run()
    4.20      
     5.1 --- a/OpenSecurity/bin/os-admind.bat	Mon Mar 31 15:26:56 2014 +0200
     5.2 +++ b/OpenSecurity/bin/os-admind.bat	Mon Mar 31 15:28:48 2014 +0200
     5.3 @@ -1,4 +1,4 @@
     5.4  @echo off
     5.5  cd %0%\..
     5.6 -C:\Python27\python opensecurityd.pyw 8080
     5.7 +C:\Python27\pythonw opensecurityd.pyw 8080
     5.8  
     6.1 --- a/OpenSecurity/bin/vmmanager.pyw	Mon Mar 31 15:26:56 2014 +0200
     6.2 +++ b/OpenSecurity/bin/vmmanager.pyw	Mon Mar 31 15:28:48 2014 +0200
     6.3 @@ -1,681 +1,682 @@
     6.4 -'''
     6.5 -Created on Nov 19, 2013
     6.6 -
     6.7 -@author: BarthaM
     6.8 -'''
     6.9 -import os
    6.10 -import os.path
    6.11 -from subprocess import Popen, PIPE, call, STARTUPINFO, _subprocess
    6.12 -import sys
    6.13 -import re
    6.14 -
    6.15 -from cygwin import Cygwin
    6.16 -from environment import Environment
    6.17 -import threading
    6.18 -import time
    6.19 -import string
    6.20 -
    6.21 -import shutil
    6.22 -import stat
    6.23 -import tempfile
    6.24 -from opensecurity_util import logger, setupLogger, OpenSecurityException
    6.25 -import ctypes
    6.26 -import itertools
    6.27 -import _winreg
    6.28 -DEBUG = True
    6.29 -
    6.30 -class VMManagerException(Exception):
    6.31 -    def __init__(self, value):
    6.32 -        self.value = value
    6.33 -    def __str__(self):
    6.34 -        return repr(self.value)
    6.35 -
    6.36 -class USBFilter:
    6.37 -    vendorid = ""
    6.38 -    productid = ""
    6.39 -    revision = ""
    6.40 -    
    6.41 -    def __init__(self, vendorid, productid, revision):
    6.42 -        self.vendorid = vendorid.lower()
    6.43 -        self.productid = productid.lower()
    6.44 -        self.revision = revision.lower()
    6.45 -        return
    6.46 -    
    6.47 -    def __eq__(self, other):
    6.48 -        return self.vendorid == other.vendorid and self.productid == other.productid and self.revision == other.revision
    6.49 -    
    6.50 -    def __hash__(self):
    6.51 -        return hash(self.vendorid) ^ hash(self.productid) ^ hash(self.revision)
    6.52 -    
    6.53 -    def __repr__(self):
    6.54 -        return "VendorId = \'" + str(self.vendorid) + "\' ProductId = \'" + str(self.productid) + "\' Revision = \'" + str(self.revision) + "\'"
    6.55 -    
    6.56 -    #def __getitem__(self, item):
    6.57 -    #    return self.coords[item]
    6.58 - 
    6.59 -class VMManager(object):
    6.60 -    vmRootName = "SecurityDVM"
    6.61 -    systemProperties = None
    6.62 -    _instance = None
    6.63 -    machineFolder = ''
    6.64 -    rsdHandler = None
    6.65 -    _running = True
    6.66 -    
    6.67 -    def __init__(self):
    6.68 -        self._running = True
    6.69 -        self.systemProperties = self.getSystemProperties()
    6.70 -        self.machineFolder = self.systemProperties["Default machine folder"]
    6.71 -        self.cleanup()
    6.72 -        self.rsdHandler = DeviceHandler(self)
    6.73 -        self.rsdHandler.start()
    6.74 -        return
    6.75 -    
    6.76 -    @staticmethod
    6.77 -    def getInstance():
    6.78 -        if VMManager._instance == None:
    6.79 -            VMManager._instance = VMManager()
    6.80 -        return VMManager._instance
    6.81 -    
    6.82 -    def cleanup(self):
    6.83 -        if self.rsdHandler != None:
    6.84 -            self.rsdHandler.stop()
    6.85 -            self.rsdHandler.join()
    6.86 -        drives = self.getNetworkDrives()
    6.87 -        for drive in drives.keys():
    6.88 -            self.unmapNetworkDrive(drive)
    6.89 -        for vm in self.listSDVM():
    6.90 -            self.poweroffVM(vm)
    6.91 -            self.removeVM(vm)
    6.92 -        
    6.93 -    # return hosty system properties
    6.94 -    def getSystemProperties(self):
    6.95 -        result = checkResult(Cygwin.vboxExecute('list systemproperties'))
    6.96 -        if result[1]=='':
    6.97 -            return None
    6.98 -        props = dict((k.strip(),v.strip().strip('"')) for k,v in (line.split(':', 1) for line in result[1].strip().splitlines()))
    6.99 -        return props
   6.100 -    
   6.101 -    # return the folder containing the guest VMs     
   6.102 -    def getMachineFolder(self):
   6.103 -        return self.machineFolder
   6.104 -
   6.105 -    # list all existing VMs registered with VBox
   6.106 -    def listVM(self):
   6.107 -        result = checkResult(Cygwin.vboxExecute('list vms'))[1]
   6.108 -        vms = list(k.strip().strip('"') for k,_ in (line.split(' ') for line in result.splitlines()))
   6.109 -        return vms
   6.110 -    
   6.111 -    # list running VMs
   6.112 -    def listRunningVMS(self):
   6.113 -        result = checkResult(Cygwin.vboxExecute('list runningvms'))[1]
   6.114 -        vms = list(k.strip().strip('"') for k,_ in (line.split(' ') for line in result.splitlines()))
   6.115 -        return vms
   6.116 -    
   6.117 -    # list existing SDVMs
   6.118 -    def listSDVM(self):
   6.119 -        vms = self.listVM()
   6.120 -        svdms = []
   6.121 -        for vm in vms:
   6.122 -            if vm.startswith(self.vmRootName) and vm != self.vmRootName:
   6.123 -                svdms.append(vm)
   6.124 -        return svdms
   6.125 -    
   6.126 -    # generate valid (not already existing SDVM name). necessary for creating a new VM
   6.127 -    def generateSDVMName(self):
   6.128 -        vms = self.listVM()
   6.129 -        for i in range(0,999):
   6.130 -            if(not self.vmRootName+str(i) in vms):
   6.131 -                return self.vmRootName+str(i)
   6.132 -        return ''
   6.133 -    
   6.134 -    # check if the device is mass storage type
   6.135 -    @staticmethod
   6.136 -    def isMassStorageDevice(device):
   6.137 -        keyname = 'SYSTEM\CurrentControlSet\Enum\USB' + '\VID_' + device.vendorid+'&'+'PID_'+ device.productid
   6.138 -        key = _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE, keyname)
   6.139 -        #subkeys = _winreg.QueryInfoKey(key)[0]
   6.140 -        #for i in range(0, subkeys):
   6.141 -        #    print _winreg.EnumKey(key, i)     
   6.142 -        devinfokeyname = _winreg.EnumKey(key, 0)
   6.143 -        _winreg.CloseKey(key)
   6.144 -
   6.145 -        devinfokey = _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE, keyname+'\\'+devinfokeyname)
   6.146 -        value = _winreg.QueryValueEx(devinfokey, 'SERVICE')[0]
   6.147 -        _winreg.CloseKey(devinfokey)
   6.148 -        
   6.149 -        return 'USBSTOR' in value
   6.150 -    
   6.151 -    # return the RSDs connected to the host
   6.152 -    @staticmethod
   6.153 -    def getConnectedRSDS():
   6.154 -        results = checkResult(Cygwin.vboxExecute('list usbhost'))[1]
   6.155 -        results = results.split('Host USB Devices:')[1].strip()
   6.156 -        
   6.157 -        items = list( "UUID:"+result for result in results.split('UUID:') if result != '')
   6.158 -        rsds = dict()   
   6.159 -        for item in items:
   6.160 -            props = dict()
   6.161 -            for line in item.splitlines():
   6.162 -                if line != "":         
   6.163 -                    k,v = line[:line.index(':')].strip(), line[line.index(':')+1:].strip()
   6.164 -                    props[k] = v
   6.165 -            
   6.166 -            #if 'Product' in props.keys() and props['Product'] == 'Mass Storage':
   6.167 -            
   6.168 -            usb_filter = USBFilter( re.search(r"\((?P<vid>[0-9A-Fa-f]+)\)", props['VendorId']).groupdict()['vid'], 
   6.169 -                                    re.search(r"\((?P<pid>[0-9A-Fa-f]+)\)", props['ProductId']).groupdict()['pid'],
   6.170 -                                    re.search(r"\((?P<rev>[0-9A-Fa-f]+)\)", props['Revision']).groupdict()['rev'] )
   6.171 -            if VMManager.isMassStorageDevice(usb_filter):
   6.172 -                rsds[props['UUID']] = usb_filter;
   6.173 -                logger.debug(usb_filter)
   6.174 -        return rsds
   6.175 -    
   6.176 -    # return the RSDs attached to all existing SDVMs
   6.177 -    def getAttachedRSDs(self):
   6.178 -        vms = self.listSDVM()
   6.179 -        attached_devices = dict()
   6.180 -        for vm in vms:
   6.181 -            rsd_filter = self.getUSBFilter(vm)
   6.182 -            if rsd_filter != None:
   6.183 -                attached_devices[vm] = rsd_filter
   6.184 -        return attached_devices
   6.185 -    
   6.186 -    # configures hostonly networking and DHCP server. requires admin rights
   6.187 -    def configureHostNetworking(self):
   6.188 -        #cmd = 'vboxmanage list hostonlyifs'
   6.189 -        #Cygwin.vboxExecute(cmd)
   6.190 -        #cmd = 'vboxmanage hostonlyif remove \"VirtualBox Host-Only Ethernet Adapter\"'
   6.191 -        #Cygwin.vboxExecute(cmd)
   6.192 -        #cmd = 'vboxmanage hostonlyif create'
   6.193 -        #Cygwin.vboxExecute(cmd)
   6.194 -        checkResult(Cygwin.vboxExecute('hostonlyif ipconfig \"VirtualBox Host-Only Ethernet Adapter\" --ip 192.168.56.1 --netmask 255.255.255.0'))
   6.195 -        #cmd = 'vboxmanage dhcpserver add'
   6.196 -        #Cygwin.vboxExecute(cmd)
   6.197 -        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'))
   6.198 -    
   6.199 -    #create new virtual machine instance based on template vm named SecurityDVM (\SecurityDVM\SecurityDVM.vmdk)
   6.200 -    def createVM(self, vm_name):
   6.201 -        hostonly_if = self.getHostOnlyIFs()
   6.202 -        checkResult(Cygwin.vboxExecute('createvm --name ' + vm_name + ' --ostype Debian --register'))
   6.203 -        checkResult(Cygwin.vboxExecute('modifyvm ' + vm_name + ' --memory 512 --vram 10 --cpus 1 --usb on --usbehci on --nic1 hostonly --hostonlyadapter1 \"' + hostonly_if['Name'] + '\" --nic2 nat'))
   6.204 -        checkResult(Cygwin.vboxExecute('storagectl ' + vm_name + ' --name SATA --add sata --portcount 2'))
   6.205 -        return
   6.206 -    
   6.207 -    # attach storage image to controller
   6.208 -    def storageAttach(self, vm_name):
   6.209 -        if self.isStorageAttached(vm_name):
   6.210 -            self.storageDetach(vm_name)
   6.211 -        checkResult(Cygwin.vboxExecute('storageattach ' + vm_name + ' --storagectl SATA --port 0 --device 0 --type hdd --medium \"'+ self.machineFolder + '\SecurityDVM\SecurityDVM.vmdk\"'))
   6.212 -    
   6.213 -    # return true if storage is attached 
   6.214 -    def isStorageAttached(self, vm_name):
   6.215 -        info = self.getVMInfo(vm_name)
   6.216 -        return (info['SATA-0-0']!='none')
   6.217 -    
   6.218 -    # detach storage from controller
   6.219 -    def storageDetach(self, vm_name):
   6.220 -        if self.isStorageAttached(vm_name):
   6.221 -            checkResult(Cygwin.vboxExecute('storageattach ' + vm_name + ' --storagectl SATA --port 0 --device 0 --type hdd --medium none'))
   6.222 -    
   6.223 -    def changeStorageType(self, filename, storage_type):
   6.224 -        checkResult(Cygwin.vboxExecute('modifyhd \"' + filename + '\" --type ' + storage_type))
   6.225 -    
   6.226 -    # list storage snaphots for VM
   6.227 -    def updateTemplate(self):
   6.228 -        self.cleanup()
   6.229 -        self.poweroffVM('SecurityDVM')
   6.230 -        self.waitShutdown('SecurityDVM')
   6.231 -        
   6.232 -        # check for updates
   6.233 -        self.genCertificateISO('SecurityDVM')
   6.234 -        self.attachCertificateISO('SecurityDVM')
   6.235 -        
   6.236 -        self.storageDetach('SecurityDVM')
   6.237 -        results = checkResult(Cygwin.vboxExecute('list hdds'))[1]
   6.238 -        results = results.replace('Parent UUID', 'Parent')
   6.239 -        items = list( "UUID:"+result for result in results.split('UUID:') if result != '')
   6.240 -        
   6.241 -        snaps = dict()   
   6.242 -        for item in items:
   6.243 -            props = dict()
   6.244 -            for line in item.splitlines():
   6.245 -                if line != "":         
   6.246 -                    k,v = line[:line.index(':')].strip(), line[line.index(':')+1:].strip()
   6.247 -                    props[k] = v;
   6.248 -            snaps[props['UUID']] = props
   6.249 -        
   6.250 -        
   6.251 -        template_storage = self.machineFolder + '\SecurityDVM\SecurityDVM.vmdk'
   6.252 -        
   6.253 -        # find template uuid
   6.254 -        template_uuid = ''
   6.255 -        for hdd in snaps.values():
   6.256 -            if hdd['Location'] == template_storage:
   6.257 -                template_uuid = hdd['UUID']
   6.258 -        logger.debug('found parent uuid ' + template_uuid)
   6.259 -        
   6.260 -        # remove snapshots 
   6.261 -        for hdd in snaps.values():
   6.262 -            if hdd['Parent'] == template_uuid:
   6.263 -                #template_uuid = hdd['UUID']
   6.264 -                logger.debug('removing snapshot ' + hdd['UUID'])
   6.265 -                checkResult(Cygwin.vboxExecute('closemedium disk {' + hdd['UUID'] + '} --delete'))#[1]
   6.266 -                # parse result 0%...10%...20%...30%...40%...50%...60%...70%...80%...90%...100%
   6.267 -        
   6.268 -        self.changeStorageType(template_storage,'normal')
   6.269 -        self.storageAttach('SecurityDVM')
   6.270 -        self.startVM('SecurityDVM')
   6.271 -        self.waitStartup('SecurityDVM')
   6.272 -        checkResult(Cygwin.sshExecute('"sudo apt-get -y update"', VMManager.getHostOnlyIP('SecurityDVM'), 'osecuser', Cygwin.cygPath(self.machineFolder) + '/' + 'SecurityDVM' + '/dvm_key'))
   6.273 -        checkResult(Cygwin.sshExecute('"sudo apt-get -y upgrade"', VMManager.getHostOnlyIP('SecurityDVM'), 'osecuser', Cygwin.cygPath(self.machineFolder) + '/' + 'SecurityDVM' + '/dvm_key'))
   6.274 -        #self.stopVM('SecurityDVM')
   6.275 -        self.hibernateVM('SecurityDVM')
   6.276 -        self.waitShutdown('SecurityDVM')
   6.277 -        self.storageDetach('SecurityDVM')
   6.278 -        self.changeStorageType(template_storage,'immutable')
   6.279 -        self.storageAttach('SecurityDVM')
   6.280 -        self.rsdHandler = DeviceHandler(self)
   6.281 -        self.rsdHandler.start()
   6.282 -    
   6.283 -    #remove VM from the system. should be used on VMs returned by listSDVMs    
   6.284 -    def removeVM(self, vm_name):
   6.285 -        logger.info('Removing ' + vm_name)
   6.286 -        checkResult(Cygwin.vboxExecute('unregistervm ' + vm_name + ' --delete'))
   6.287 -        vm_file = Cygwin.cygPath(self.machineFolder + '\\' + vm_name)
   6.288 -        checkResult(Cygwin.bashExecute('rm -rf \'' + vm_file + '\''))
   6.289 -    
   6.290 -    # start VM
   6.291 -    def startVM(self, vm_name):
   6.292 -        logger.info('Starting ' +  vm_name)
   6.293 -        result = checkResult(Cygwin.vboxExecute('startvm ' + vm_name + ' --type headless' ))
   6.294 -        while 'successfully started' not in result[1] and _running:
   6.295 -            logger.error("Failed to start SDVM: " + vm_name + " retrying")
   6.296 -            time.sleep(1)
   6.297 -            result = checkResult(Cygwin.vboxExecute('startvm ' + vm_name + ' --type headless'))
   6.298 -        return result[0]
   6.299 -    
   6.300 -    # return wether VM is running or not
   6.301 -    def isVMRunning(self, vm_name):
   6.302 -        return vm_name in self.listRunningVMS()    
   6.303 -    
   6.304 -    # stop VM
   6.305 -    def stopVM(self, vm_name):
   6.306 -        logger.info('Sending shutdown signal to ' + vm_name)
   6.307 -        checkResult(Cygwin.sshExecute( '"sudo shutdown -h now"', VMManager.getHostOnlyIP(vm_name), 'osecuser', Cygwin.cygPath(self.machineFolder) + '/' + vm_name + '/dvm_key' ))
   6.308 -    
   6.309 -    # stop VM
   6.310 -    def hibernateVM(self, vm_name):
   6.311 -        logger.info('Sending shutdown signal to ' + vm_name)
   6.312 -        checkResult(Cygwin.sshExecute( '"sudo hibernate-disk&"', VMManager.getHostOnlyIP(vm_name), 'osecuser', Cygwin.cygPath(self.machineFolder) + '/' + vm_name + '/dvm_key', wait_return=False))
   6.313 -            
   6.314 -    # poweroff VM
   6.315 -    def poweroffVM(self, vm_name):
   6.316 -        if not self.isVMRunning(vm_name):
   6.317 -            return
   6.318 -        logger.info('Powering off ' + vm_name)
   6.319 -        return checkResult(Cygwin.vboxExecute('controlvm ' + vm_name + ' poweroff'))
   6.320 -    
   6.321 -    #list the hostonly IFs exposed by the VBox host
   6.322 -    @staticmethod    
   6.323 -    def getHostOnlyIFs():
   6.324 -        result = Cygwin.vboxExecute('list hostonlyifs')[1]
   6.325 -        if result=='':
   6.326 -            return None
   6.327 -        props = dict((k.strip(),v.strip().strip('"')) for k,v in (line.split(':', 1) for line in result.strip().splitlines()))
   6.328 -        return props
   6.329 -    
   6.330 -    # return the hostOnly IP for a running guest or the host
   6.331 -    @staticmethod    
   6.332 -    def getHostOnlyIP(vm_name):
   6.333 -        if vm_name == None:
   6.334 -            logger.info('Gettting hostOnly IP address for Host')
   6.335 -            return VMManager.getHostOnlyIFs()['IPAddress']
   6.336 -        else:
   6.337 -            logger.info('Gettting hostOnly IP address ' + vm_name)
   6.338 -            result = checkResult(Cygwin.vboxExecute('guestproperty get ' + vm_name + ' /VirtualBox/GuestInfo/Net/0/V4/IP'))
   6.339 -            if result=='':
   6.340 -                return None
   6.341 -            result = result[1]
   6.342 -            if result.startswith('No value set!'):
   6.343 -                return None
   6.344 -            return result[result.index(':')+1:].strip()
   6.345 -            
   6.346 -    # attach removable storage device to VM by provision of filter
   6.347 -    def attachRSD(self, vm_name, rsd_filter):
   6.348 -        return checkResult(Cygwin.vboxExecute('usbfilter add 0 --target ' + vm_name + ' --name OpenSecurityRSD --vendorid ' + rsd_filter.vendorid + ' --productid ' + rsd_filter.productid + ' --revision ' + rsd_filter.revision))
   6.349 -    
   6.350 -    # detach removable storage from VM by 
   6.351 -    def detachRSD(self, vm_name):
   6.352 -        return checkResult(Cygwin.vboxExecute('usbfilter remove 0 --target ' + vm_name))
   6.353 -        
   6.354 -    # return the description set for an existing VM
   6.355 -    def getVMInfo(self, vm_name):
   6.356 -        results = checkResult(Cygwin.vboxExecute('showvminfo ' + vm_name + ' --machinereadable'))[1]
   6.357 -        props = dict((k.strip().strip('"'),v.strip().strip('"')) for k,v in (line.split('=', 1) for line in results.splitlines()))
   6.358 -        return props
   6.359 -    
   6.360 -    # return the configured USB filter for an existing VM 
   6.361 -    def getUSBFilter(self, vm_name):
   6.362 -        props = self.getVMInfo(vm_name)
   6.363 -        keys = set(['USBFilterVendorId1', 'USBFilterProductId1', 'USBFilterRevision1'])
   6.364 -        keyset = set(props.keys())
   6.365 -        usb_filter = None
   6.366 -        if keyset.issuperset(keys):
   6.367 -            usb_filter = USBFilter(props['USBFilterVendorId1'], props['USBFilterProductId1'], props['USBFilterRevision1'])
   6.368 -        return usb_filter
   6.369 -    
   6.370 -    #generates ISO containing authorized_keys for use with guest VM
   6.371 -    def genCertificateISO(self, vm_name):
   6.372 -        machineFolder = Cygwin.cygPath(self.machineFolder)
   6.373 -        # remove .ssh folder if exists
   6.374 -        checkResult(Cygwin.bashExecute('\"/usr/bin/rm -rf \\\"' + machineFolder + '/' + vm_name + '/.ssh\\\"\"'))
   6.375 -        # remove .ssh folder if exists
   6.376 -        checkResult(Cygwin.bashExecute('\"/usr/bin/rm -rf \\\"' + machineFolder + '/' + vm_name + '/dvm_key\\\"\"'))
   6.377 -        # create .ssh folder in vm_name
   6.378 -        checkResult(Cygwin.bashExecute('\"/usr/bin/mkdir -p \\\"' + machineFolder + '/' + vm_name + '/.ssh\\\"\"'))
   6.379 -        # generate dvm_key pair in vm_name / .ssh     
   6.380 -        checkResult(Cygwin.bashExecute('\"/usr/bin/ssh-keygen -q -t rsa -N \\"\\" -C \\\"' + vm_name + '\\\" -f \\\"' + machineFolder + '/' + vm_name + '/.ssh/dvm_key\\\"\"'))
   6.381 -        # move out private key
   6.382 -        checkResult(Cygwin.bashExecute('\"/usr/bin/mv \\\"' + machineFolder + '/' + vm_name + '/.ssh/dvm_key\\\" \\\"' + machineFolder + '/' + vm_name + '\\\"'))
   6.383 -        # set permissions for private key
   6.384 -        checkResult(Cygwin.bashExecute('\"/usr/bin/chmod 500 \\\"' + machineFolder + '/' + vm_name + '/dvm_key\\\"\"'))
   6.385 -        # rename public key to authorized_keys
   6.386 -        checkResult(Cygwin.bashExecute('\"/usr/bin/mv \\\"' + machineFolder + '/' + vm_name + '/.ssh/dvm_key.pub\\\" \\\"' + machineFolder + '/' + vm_name + '/.ssh/authorized_keys\\\"'))
   6.387 -        # set permissions for authorized_keys
   6.388 -        checkResult(Cygwin.bashExecute('\"/usr/bin/chmod 500 \\\"' + machineFolder + '/' + vm_name + '/.ssh/authorized_keys\\\"\"'))
   6.389 -        # generate iso image with .ssh/authorized keys
   6.390 -        checkResult(Cygwin.bashExecute('\"/usr/bin/genisoimage -J -R -o \\\"' + machineFolder + '/' + vm_name + '/'+ vm_name + '.iso\\\" \\\"' + machineFolder + '/' + vm_name + '/.ssh\\\"\"'))
   6.391 -    
   6.392 -    # attaches generated ssh public cert to guest vm
   6.393 -    def attachCertificateISO(self, vm_name):
   6.394 -        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\"'))
   6.395 -        return result
   6.396 -    
   6.397 -    # wait for machine to come up
   6.398 -    def waitStartup(self, vm_name, timeout_ms = 30000):
   6.399 -        checkResult(Cygwin.vboxExecute('guestproperty wait ' + vm_name + ' SDVMStarted --timeout ' + str(timeout_ms) + ' --fail-on-timeout'))
   6.400 -        return VMManager.getHostOnlyIP(vm_name)
   6.401 -    
   6.402 -    # wait for machine to shutdown
   6.403 -    def waitShutdown(self, vm_name):
   6.404 -        while vm_name in self.listRunningVMS() and _running:
   6.405 -            time.sleep(1)
   6.406 -        return
   6.407 -        
   6.408 -    # handles browsing request    
   6.409 -    def handleBrowsingRequest(self):
   6.410 -        handler = BrowsingHandler(self)
   6.411 -        handler.start()
   6.412 -        return 'ok'
   6.413 -    
   6.414 -    #Small function to check the availability of network resource.
   6.415 -    #def isAvailable(self, path):
   6.416 -        #return os.path.exists(path)
   6.417 -        #result = Cygwin.cmdExecute('IF EXIST "' + path + '" echo YES')
   6.418 -        #return string.find(result[1], 'YES',)
   6.419 -    
   6.420 -    #Small function to check if the mention location is a directory
   6.421 -    def isDirectory(self, path):
   6.422 -        result = checkResult(Cygwin.cmdExecute('dir ' + path + ' | FIND ".."'))
   6.423 -        return string.find(result[1], 'DIR',)
   6.424 -
   6.425 -    def mapNetworkDrive(self, drive, networkPath, user, password):
   6.426 -        self.unmapNetworkDrive(drive)
   6.427 -        #Check for drive availability
   6.428 -        if os.path.exists(drive):
   6.429 -            logger.error("Drive letter is already in use: " + drive)
   6.430 -            return -1
   6.431 -        #Check for network resource availability
   6.432 -        retry = 5
   6.433 -        while not os.path.exists(networkPath):
   6.434 -            time.sleep(1)
   6.435 -            if retry == 0:
   6.436 -                return -1
   6.437 -            logger.info("Path not accessible: " + networkPath + " retrying")
   6.438 -            retry-=1
   6.439 -            #return -1
   6.440 -    
   6.441 -        command = 'USE ' + drive + ' ' + networkPath + ' /PERSISTENT:NO'
   6.442 -        if user != None:
   6.443 -            command += ' ' + password + ' /User' + user
   6.444 -    
   6.445 -        #TODO: Execute 'NET USE' command with authentication
   6.446 -        result = checkResult(Cygwin.execute('C:\\Windows\\system32\\net.exe', command))
   6.447 -        if string.find(result[1], 'successfully',) == -1:
   6.448 -            logger.error("Failed: NET " + command)
   6.449 -            return -1
   6.450 -        return 1
   6.451 -    
   6.452 -    def unmapNetworkDrive(self, drive):
   6.453 -        drives = self.getNetworkDrives()
   6.454 -        if drive not in drives.keys():
   6.455 -            return 1 
   6.456 -        result = checkResult(Cygwin.execute('C:\\Windows\\system32\\net.exe', 'USE ' + drive + ' /DELETE /YES'))
   6.457 -        if string.find(str(result[1]), 'successfully',) == -1:
   6.458 -            logger.error(result[2])
   6.459 -            return -1
   6.460 -        return 1
   6.461 -    
   6.462 -    def getNetworkDrives(self):
   6.463 -        ip = VMManager.getHostOnlyIP(None)
   6.464 -        ip = ip[:ip.rindex('.')]
   6.465 -        drives = dict()    
   6.466 -        result = checkResult(Cygwin.execute('C:\\Windows\\system32\\net.exe', 'USE'))
   6.467 -        for line in result[1].splitlines():
   6.468 -            if ip in line:
   6.469 -                parts = line.split()
   6.470 -                drives[parts[1]] = parts[2]
   6.471 -        return drives
   6.472 -            
   6.473 -    def genNetworkDrive(self):
   6.474 -        network_drives = self.getNetworkDrives()
   6.475 -        logical_drives = VMManager.getLogicalDrives()
   6.476 -        drives = list(map(chr, range(68, 91)))  
   6.477 -        for drive in drives:
   6.478 -            if drive+':' not in network_drives and drive not in logical_drives:
   6.479 -                return drive+':'
   6.480 -
   6.481 -    def getNetworkDrive(self, vm_name):
   6.482 -        ip = self.getHostOnlyIP(vm_name)
   6.483 -        result = checkResult(Cygwin.execute('C:\\Windows\\system32\\net.exe', 'USE'))
   6.484 -        for line in result[1].splitlines():
   6.485 -            if line != None and ip in line:
   6.486 -                parts = line.split()
   6.487 -                return parts[0]
   6.488 -    @staticmethod
   6.489 -    def getLogicalDrives():
   6.490 -        drive_bitmask = ctypes.cdll.kernel32.GetLogicalDrives()
   6.491 -        return list(itertools.compress(string.ascii_uppercase,  map(lambda x:ord(x) - ord('0'), bin(drive_bitmask)[:1:-1])))
   6.492 -    
   6.493 -    @staticmethod
   6.494 -    def getDriveType(drive):
   6.495 -        return ctypes.cdll.kernel32.GetDriveTypeW(u"%s:\\"%drive)
   6.496 -    
   6.497 -    @staticmethod
   6.498 -    def getVolumeInfo(drive):
   6.499 -        volumeNameBuffer = ctypes.create_unicode_buffer(1024)
   6.500 -        fileSystemNameBuffer = ctypes.create_unicode_buffer(1024)
   6.501 -        serial_number = None
   6.502 -        max_component_length = None
   6.503 -        file_system_flags = None
   6.504 -        
   6.505 -        rc = ctypes.cdll.kernel32.GetVolumeInformationW(
   6.506 -            #ctypes.c_wchar_p("F:\\"),
   6.507 -            u"%s:\\"%drive,
   6.508 -            volumeNameBuffer,
   6.509 -            ctypes.sizeof(volumeNameBuffer),
   6.510 -            serial_number,
   6.511 -            max_component_length,
   6.512 -            file_system_flags,
   6.513 -            fileSystemNameBuffer,
   6.514 -            ctypes.sizeof(fileSystemNameBuffer)
   6.515 -        )
   6.516 -        
   6.517 -        return volumeNameBuffer.value, fileSystemNameBuffer.value
   6.518 -
   6.519 -    @staticmethod
   6.520 -    def stop():
   6.521 -        """stop all running infinite loops now --> needed for gracefull shutdown"""
   6.522 -        _running = False
   6.523 -
   6.524 -
   6.525 -
   6.526 -def checkResult(result):
   6.527 -    if result[0] != 0:
   6.528 -        logger.error('Command failed:' + ''.join(result[2]))
   6.529 -        raise OpenSecurityException('Command failed:' + ''.join(result[2]))
   6.530 -    return result
   6.531 -
   6.532 -# handles browsing request                    
   6.533 -class BrowsingHandler(threading.Thread):
   6.534 -    vmm = None
   6.535 -    def __init__(self, vmmanager):
   6.536 -        threading.Thread.__init__(self)
   6.537 -        self.vmm = vmmanager
   6.538 -     
   6.539 -    def run(self):
   6.540 -        try:
   6.541 -            new_sdvm = self.vmm.generateSDVMName()
   6.542 -            self.vmm.createVM(new_sdvm)
   6.543 -            self.vmm.storageAttach(new_sdvm)
   6.544 -            self.vmm.genCertificateISO(new_sdvm)
   6.545 -            self.vmm.attachCertificateISO(new_sdvm)
   6.546 -            self.vmm.startVM(new_sdvm)
   6.547 -            new_ip = self.vmm.waitStartup(new_sdvm)
   6.548 -            drive = self.vmm.genNetworkDrive()
   6.549 -            if new_ip != None:
   6.550 -                self.vmm.mapNetworkDrive(drive, '\\\\' + new_ip + '\\Download', None, None)
   6.551 -            result = checkResult(Cygwin.sshExecuteX11('/usr/bin/iceweasel', new_ip, 'osecuser', Cygwin.cygPath(self.vmm.getMachineFolder()) + '/' + new_sdvm + '/dvm_key'))
   6.552 -        except:
   6.553 -            logger.error("BrowsingHandler failed. Cleaning up")
   6.554 -            
   6.555 -        self.vmm.unmapNetworkDrive(drive)
   6.556 -        self.vmm.poweroffVM(new_sdvm)
   6.557 -        self.vmm.removeVM(new_sdvm)
   6.558 -                
   6.559 -class DeviceHandler(threading.Thread): 
   6.560 -    vmm = None
   6.561 -    #handleDeviceChangeLock = threading.Lock()
   6.562 -    attachedRSDs = None  
   6.563 -    connectedRSDs = None
   6.564 -    running = True
   6.565 -    def __init__(self, vmmanger): 
   6.566 -        threading.Thread.__init__(self)
   6.567 -        self.vmm = vmmanger
   6.568 - 
   6.569 -    def stop(self):
   6.570 -        self.running = False
   6.571 -        
   6.572 -    def run(self):
   6.573 -        self.connectedRSDs = dict()
   6.574 -        self.attachedRSDs = self.vmm.getAttachedRSDs()
   6.575 -        while self.running:
   6.576 -            tmp_rsds = self.vmm.getConnectedRSDS()
   6.577 -            if tmp_rsds.keys() == self.connectedRSDs.keys():
   6.578 -                logger.debug("Nothing's changed. sleep(3)")
   6.579 -                time.sleep(3)
   6.580 -                continue
   6.581 -            
   6.582 -            logger.info("Something's changed")          
   6.583 -            self.connectedRSDs = tmp_rsds
   6.584 -            self.attachedRSDs = self.vmm.getAttachedRSDs()
   6.585 -            
   6.586 -            for vm_name in self.attachedRSDs.keys():
   6.587 -                if self.attachedRSDs[vm_name] not in self.connectedRSDs.values():
   6.588 -                    drive = self.vmm.getNetworkDrive(vm_name)
   6.589 -                    self.vmm.unmapNetworkDrive(drive)
   6.590 -                    #self.stopVM(vm_name)
   6.591 -                    self.vmm.detachRSD(vm_name)
   6.592 -                    self.vmm.poweroffVM(vm_name)
   6.593 -                    self.vmm.removeVM(vm_name)
   6.594 -            #create new vm for attached device if any
   6.595 -            self.attachedRSDs = self.vmm.getAttachedRSDs()
   6.596 -            self.connectedRSDs = self.vmm.getConnectedRSDS()
   6.597 -            
   6.598 -            new_ip = None
   6.599 -            for connected_device in self.connectedRSDs.values():
   6.600 -                if (self.attachedRSDs and False) or (connected_device not in self.attachedRSDs.values()):
   6.601 -                    new_sdvm = self.vmm.generateSDVMName()
   6.602 -                    self.vmm.createVM(new_sdvm)
   6.603 -                    self.vmm.storageAttach(new_sdvm)
   6.604 -                    self.vmm.attachRSD(new_sdvm, connected_device)
   6.605 -                    self.vmm.startVM(new_sdvm)
   6.606 -                    new_ip = self.vmm.waitStartup(new_sdvm)
   6.607 -                    drive = self.vmm.genNetworkDrive()
   6.608 -                    if new_ip != None:
   6.609 -                        self.vmm.mapNetworkDrive(drive, '\\\\' + new_ip + '\\USB', None, None)
   6.610 -
   6.611 -if __name__ == '__main__':
   6.612 -    #man = VMManager.getInstance()
   6.613 -    #man.listVM()
   6.614 -    #print man.getConnectedRSDs()
   6.615 -    #print man.getNetworkDrives()
   6.616 -    #man.genNetworkDrive()
   6.617 -    #drive_bitmask = ctypes.cdll.kernel32.GetLogicalDrives()
   6.618 -    #print list(itertools.compress(string.ascii_uppercase,  map(lambda x:ord(x) - ord('0'), bin(drive_bitmask)[:1:-1])))
   6.619 -    #print list(map(chr, range(68, 91))) 
   6.620 -    #print Cygwin.getRegEntry('SYSTEM\CurrentControlSet\Enum\USB', 'VID_1058&PID_0704')[0]
   6.621 -    #devices = VMManager.getConnectedRSDS()
   6.622 -    #print devices
   6.623 -    
   6.624 -    drives = VMManager.getLogicalDrives()
   6.625 -    print drives
   6.626 -    print VMManager.getDriveType("E")
   6.627 -    print VMManager.getVolumeInfo("E")
   6.628 -    #for device in devices.values():
   6.629 -    #    #print device
   6.630 -    #    if VMManager.isMassStorageDevice(device):
   6.631 -    #        print device
   6.632 -        
   6.633 -    
   6.634 -    
   6.635 -    #time.sleep(-1)
   6.636 -    #man.listVM()
   6.637 -    #man.listVM()
   6.638 -    #man.listVM()
   6.639 -    #man.listVM()
   6.640 -    #man.genCertificateISO('SecurityDVM0')
   6.641 -    #man.guestExecute('SecurityDVM0', '/bin/ls -la')
   6.642 -    #logger = setupLogger('VMManager')
   6.643 -    #c = Cygwin()
   6.644 -    
   6.645 -    #man.sshExecute('/bin/ls -la', 'SecurityDVM0')
   6.646 -    #man.sshExecuteX11('/usr/bin/iceweasel', 'SecurityDVM0')
   6.647 -    #man.removeVM('SecurityDVM0')
   6.648 -    #man.netUse('192.168.56.134', 'USB\\')
   6.649 -    #ip = '192.168.56.139'
   6.650 -    
   6.651 -    #man.cygwin_path = 'c:\\cygwin64\\bin\\'
   6.652 -    #man.handleDeviceChange()
   6.653 -    #print man.listSDVM()
   6.654 -    #man.configureHostNetworking()
   6.655 -    #new_vm = man.generateSDVMName()
   6.656 -    #man.createVM(new_vm)
   6.657 -    
   6.658 -    #print Cygwin.cmd()
   6.659 -    #man.isAvailable('c:')
   6.660 -    #ip = man.getHostOnlyIP('SecurityDVM0')
   6.661 -    #man.mapNetworkDrive('h:', '\\\\' + ip + '\Download', None, None)
   6.662 -    
   6.663 -    #man.genCertificateISO(new_vm)
   6.664 -    #man.attachCertificateISO(new_vm)
   6.665 -    
   6.666 -    #man.attachCertificateISO(vm_name)
   6.667 -    #man.guestExecute(vm_name, "ls")
   6.668 -    #man.sshGuestX11Execute('SecurityDVM1', '/usr/bin/iceweasel')
   6.669 -    #time.sleep(60)
   6.670 -    #print man.cygwinPath("C:\Users\BarthaM\VirtualBox VMs\SecurityDVM\.ssh\*")
   6.671 -    #man.genCertificateISO('SecurityDVM')
   6.672 -    #man.attachCertificateISO('SecurityDVM')
   6.673 -    #man.isStorageAttached('SecurityDVM')
   6.674 -    #man.guestExecute('SecurityDVM', 'sudo apt-get -y update')
   6.675 -    #man.guestExecute('SecurityDVM', 'sudo apt-get -y upgrade' )
   6.676 -    
   6.677 -    #man.stopVM('SecurityDVM')
   6.678 -    #man.storageDetach('SecurityDVM')
   6.679 -    #man.changeStorageType('C:\Users\BarthaM\VirtualBox VMs\SecurityDVM\SecurityDVM.vmdk','immutable')
   6.680 -    #man.storageAttach('SecurityDVM')
   6.681 -    
   6.682 -    
   6.683 -    #cmd = "c:\\cygwin64\\bin\\bash.exe --login -c \"/bin/ls\""
   6.684 -    #man.execute(cmd)
   6.685 +'''
   6.686 +Created on Nov 19, 2013
   6.687 +
   6.688 +@author: BarthaM
   6.689 +'''
   6.690 +import os
   6.691 +import os.path
   6.692 +from subprocess import Popen, PIPE, call, STARTUPINFO, _subprocess
   6.693 +import sys
   6.694 +import re
   6.695 +
   6.696 +from cygwin import Cygwin
   6.697 +from environment import Environment
   6.698 +import threading
   6.699 +import time
   6.700 +import string
   6.701 +
   6.702 +import shutil
   6.703 +import stat
   6.704 +import tempfile
   6.705 +from opensecurity_util import logger, setupLogger, OpenSecurityException
   6.706 +import ctypes
   6.707 +import itertools
   6.708 +import _winreg
   6.709 +DEBUG = True
   6.710 +
   6.711 +class VMManagerException(Exception):
   6.712 +    def __init__(self, value):
   6.713 +        self.value = value
   6.714 +    def __str__(self):
   6.715 +        return repr(self.value)
   6.716 +
   6.717 +class USBFilter:
   6.718 +    vendorid = ""
   6.719 +    productid = ""
   6.720 +    revision = ""
   6.721 +    
   6.722 +    def __init__(self, vendorid, productid, revision):
   6.723 +        self.vendorid = vendorid.lower()
   6.724 +        self.productid = productid.lower()
   6.725 +        self.revision = revision.lower()
   6.726 +        return
   6.727 +    
   6.728 +    def __eq__(self, other):
   6.729 +        return self.vendorid == other.vendorid and self.productid == other.productid and self.revision == other.revision
   6.730 +    
   6.731 +    def __hash__(self):
   6.732 +        return hash(self.vendorid) ^ hash(self.productid) ^ hash(self.revision)
   6.733 +    
   6.734 +    def __repr__(self):
   6.735 +        return "VendorId = \'" + str(self.vendorid) + "\' ProductId = \'" + str(self.productid) + "\' Revision = \'" + str(self.revision) + "\'"
   6.736 +    
   6.737 +    #def __getitem__(self, item):
   6.738 +    #    return self.coords[item]
   6.739 + 
   6.740 +class VMManager(object):
   6.741 +    vmRootName = "SecurityDVM"
   6.742 +    systemProperties = None
   6.743 +    _instance = None
   6.744 +    machineFolder = ''
   6.745 +    rsdHandler = None
   6.746 +    
   6.747 +    def __init__(self):
   6.748 +        self.systemProperties = self.getSystemProperties()
   6.749 +        self.machineFolder = self.systemProperties["Default machine folder"]
   6.750 +        self.cleanup()
   6.751 +        self.rsdHandler = DeviceHandler(self)
   6.752 +        self.rsdHandler.start()
   6.753 +        return
   6.754 +    
   6.755 +    @staticmethod
   6.756 +    def getInstance():
   6.757 +        if VMManager._instance == None:
   6.758 +            VMManager._instance = VMManager()
   6.759 +        return VMManager._instance
   6.760 +    
   6.761 +    def cleanup(self):
   6.762 +        if self.rsdHandler != None:
   6.763 +            self.rsdHandler.stop()
   6.764 +            self.rsdHandler.join()
   6.765 +        drives = self.getNetworkDrives()
   6.766 +        for drive in drives.keys():
   6.767 +            self.unmapNetworkDrive(drive)
   6.768 +        for vm in self.listSDVM():
   6.769 +            self.poweroffVM(vm)
   6.770 +            self.removeVM(vm)
   6.771 +        
   6.772 +    # return hosty system properties
   6.773 +    def getSystemProperties(self):
   6.774 +        result = checkResult(Cygwin.vboxExecute('list systemproperties'))
   6.775 +        if result[1]=='':
   6.776 +            return None
   6.777 +        props = dict((k.strip(),v.strip().strip('"')) for k,v in (line.split(':', 1) for line in result[1].strip().splitlines()))
   6.778 +        return props
   6.779 +    
   6.780 +    # return the folder containing the guest VMs     
   6.781 +    def getMachineFolder(self):
   6.782 +        return self.machineFolder
   6.783 +
   6.784 +    # list all existing VMs registered with VBox
   6.785 +    def listVM(self):
   6.786 +        result = checkResult(Cygwin.vboxExecute('list vms'))[1]
   6.787 +        vms = list(k.strip().strip('"') for k,_ in (line.split(' ') for line in result.splitlines()))
   6.788 +        return vms
   6.789 +    
   6.790 +    # list running VMs
   6.791 +    def listRunningVMS(self):
   6.792 +        result = checkResult(Cygwin.vboxExecute('list runningvms'))[1]
   6.793 +        vms = list(k.strip().strip('"') for k,_ in (line.split(' ') for line in result.splitlines()))
   6.794 +        return vms
   6.795 +    
   6.796 +    # list existing SDVMs
   6.797 +    def listSDVM(self):
   6.798 +        vms = self.listVM()
   6.799 +        svdms = []
   6.800 +        for vm in vms:
   6.801 +            if vm.startswith(self.vmRootName) and vm != self.vmRootName:
   6.802 +                svdms.append(vm)
   6.803 +        return svdms
   6.804 +    
   6.805 +    # generate valid (not already existing SDVM name). necessary for creating a new VM
   6.806 +    def generateSDVMName(self):
   6.807 +        vms = self.listVM()
   6.808 +        for i in range(0,999):
   6.809 +            if(not self.vmRootName+str(i) in vms):
   6.810 +                return self.vmRootName+str(i)
   6.811 +        return ''
   6.812 +    
   6.813 +    # check if the device is mass storage type
   6.814 +    @staticmethod
   6.815 +    def isMassStorageDevice(device):
   6.816 +        keyname = 'SYSTEM\CurrentControlSet\Enum\USB' + '\VID_' + device.vendorid+'&'+'PID_'+ device.productid
   6.817 +        key = _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE, keyname)
   6.818 +        #subkeys = _winreg.QueryInfoKey(key)[0]
   6.819 +        #for i in range(0, subkeys):
   6.820 +        #    print _winreg.EnumKey(key, i)     
   6.821 +        devinfokeyname = _winreg.EnumKey(key, 0)
   6.822 +        _winreg.CloseKey(key)
   6.823 +
   6.824 +        devinfokey = _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE, keyname+'\\'+devinfokeyname)
   6.825 +        value = _winreg.QueryValueEx(devinfokey, 'SERVICE')[0]
   6.826 +        _winreg.CloseKey(devinfokey)
   6.827 +        
   6.828 +        return 'USBSTOR' in value
   6.829 +    
   6.830 +    # return the RSDs connected to the host
   6.831 +    @staticmethod
   6.832 +    def getConnectedRSDS():
   6.833 +        results = checkResult(Cygwin.vboxExecute('list usbhost'))[1]
   6.834 +        results = results.split('Host USB Devices:')[1].strip()
   6.835 +        
   6.836 +        items = list( "UUID:"+result for result in results.split('UUID:') if result != '')
   6.837 +        rsds = dict()   
   6.838 +        for item in items:
   6.839 +            props = dict()
   6.840 +            for line in item.splitlines():
   6.841 +                if line != "":         
   6.842 +                    k,v = line[:line.index(':')].strip(), line[line.index(':')+1:].strip()
   6.843 +                    props[k] = v
   6.844 +            
   6.845 +            #if 'Product' in props.keys() and props['Product'] == 'Mass Storage':
   6.846 +            
   6.847 +            usb_filter = USBFilter( re.search(r"\((?P<vid>[0-9A-Fa-f]+)\)", props['VendorId']).groupdict()['vid'], 
   6.848 +                                    re.search(r"\((?P<pid>[0-9A-Fa-f]+)\)", props['ProductId']).groupdict()['pid'],
   6.849 +                                    re.search(r"\((?P<rev>[0-9A-Fa-f]+)\)", props['Revision']).groupdict()['rev'] )
   6.850 +            if VMManager.isMassStorageDevice(usb_filter):
   6.851 +                rsds[props['UUID']] = usb_filter;
   6.852 +                logger.debug(usb_filter)
   6.853 +        return rsds
   6.854 +    
   6.855 +    # return the RSDs attached to all existing SDVMs
   6.856 +    def getAttachedRSDs(self):
   6.857 +        vms = self.listSDVM()
   6.858 +        attached_devices = dict()
   6.859 +        for vm in vms:
   6.860 +            rsd_filter = self.getUSBFilter(vm)
   6.861 +            if rsd_filter != None:
   6.862 +                attached_devices[vm] = rsd_filter
   6.863 +        return attached_devices
   6.864 +    
   6.865 +    # configures hostonly networking and DHCP server. requires admin rights
   6.866 +    def configureHostNetworking(self):
   6.867 +        #cmd = 'vboxmanage list hostonlyifs'
   6.868 +        #Cygwin.vboxExecute(cmd)
   6.869 +        #cmd = 'vboxmanage hostonlyif remove \"VirtualBox Host-Only Ethernet Adapter\"'
   6.870 +        #Cygwin.vboxExecute(cmd)
   6.871 +        #cmd = 'vboxmanage hostonlyif create'
   6.872 +        #Cygwin.vboxExecute(cmd)
   6.873 +        checkResult(Cygwin.vboxExecute('hostonlyif ipconfig \"VirtualBox Host-Only Ethernet Adapter\" --ip 192.168.56.1 --netmask 255.255.255.0'))
   6.874 +        #cmd = 'vboxmanage dhcpserver add'
   6.875 +        #Cygwin.vboxExecute(cmd)
   6.876 +        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'))
   6.877 +    
   6.878 +    #create new virtual machine instance based on template vm named SecurityDVM (\SecurityDVM\SecurityDVM.vmdk)
   6.879 +    def createVM(self, vm_name):
   6.880 +        hostonly_if = self.getHostOnlyIFs()
   6.881 +        checkResult(Cygwin.vboxExecute('createvm --name ' + vm_name + ' --ostype Debian --register'))
   6.882 +        checkResult(Cygwin.vboxExecute('modifyvm ' + vm_name + ' --memory 512 --vram 10 --cpus 1 --usb on --usbehci on --nic1 hostonly --hostonlyadapter1 \"' + hostonly_if['Name'] + '\" --nic2 nat'))
   6.883 +        checkResult(Cygwin.vboxExecute('storagectl ' + vm_name + ' --name SATA --add sata --portcount 2'))
   6.884 +        return
   6.885 +    
   6.886 +    # attach storage image to controller
   6.887 +    def storageAttach(self, vm_name):
   6.888 +        if self.isStorageAttached(vm_name):
   6.889 +            self.storageDetach(vm_name)
   6.890 +        checkResult(Cygwin.vboxExecute('storageattach ' + vm_name + ' --storagectl SATA --port 0 --device 0 --type hdd --medium \"'+ self.machineFolder + '\SecurityDVM\SecurityDVM.vmdk\"'))
   6.891 +    
   6.892 +    # return true if storage is attached 
   6.893 +    def isStorageAttached(self, vm_name):
   6.894 +        info = self.getVMInfo(vm_name)
   6.895 +        return (info['SATA-0-0']!='none')
   6.896 +    
   6.897 +    # detach storage from controller
   6.898 +    def storageDetach(self, vm_name):
   6.899 +        if self.isStorageAttached(vm_name):
   6.900 +            checkResult(Cygwin.vboxExecute('storageattach ' + vm_name + ' --storagectl SATA --port 0 --device 0 --type hdd --medium none'))
   6.901 +    
   6.902 +    def changeStorageType(self, filename, storage_type):
   6.903 +        checkResult(Cygwin.vboxExecute('modifyhd \"' + filename + '\" --type ' + storage_type))
   6.904 +    
   6.905 +    # list storage snaphots for VM
   6.906 +    def updateTemplate(self):
   6.907 +
   6.908 +        self.cleanup()
   6.909 +        self.poweroffVM('SecurityDVM')
   6.910 +        self.waitShutdown('SecurityDVM')
   6.911 +        
   6.912 +        # check for updates
   6.913 +        self.genCertificateISO('SecurityDVM')
   6.914 +        self.attachCertificateISO('SecurityDVM')
   6.915 +        
   6.916 +        self.storageDetach('SecurityDVM')
   6.917 +        results = checkResult(Cygwin.vboxExecute('list hdds'))[1]
   6.918 +        results = results.replace('Parent UUID', 'Parent')
   6.919 +        items = list( "UUID:"+result for result in results.split('UUID:') if result != '')
   6.920 +        
   6.921 +        snaps = dict()   
   6.922 +        for item in items:
   6.923 +            props = dict()
   6.924 +            for line in item.splitlines():
   6.925 +                if line != "":         
   6.926 +                    k,v = line[:line.index(':')].strip(), line[line.index(':')+1:].strip()
   6.927 +                    props[k] = v;
   6.928 +            snaps[props['UUID']] = props
   6.929 +        
   6.930 +        
   6.931 +        template_storage = self.machineFolder + '\SecurityDVM\SecurityDVM.vmdk'
   6.932 +        
   6.933 +        # find template uuid
   6.934 +        template_uuid = ''
   6.935 +        for hdd in snaps.values():
   6.936 +            if hdd['Location'] == template_storage:
   6.937 +                template_uuid = hdd['UUID']
   6.938 +        logger.debug('found parent uuid ' + template_uuid)
   6.939 +        
   6.940 +        # remove snapshots 
   6.941 +        for hdd in snaps.values():
   6.942 +            if hdd['Parent'] == template_uuid:
   6.943 +                #template_uuid = hdd['UUID']
   6.944 +                logger.debug('removing snapshot ' + hdd['UUID'])
   6.945 +                checkResult(Cygwin.vboxExecute('closemedium disk {' + hdd['UUID'] + '} --delete'))#[1]
   6.946 +                # parse result 0%...10%...20%...30%...40%...50%...60%...70%...80%...90%...100%
   6.947 +        
   6.948 +        self.changeStorageType(template_storage,'normal')
   6.949 +        self.storageAttach('SecurityDVM')
   6.950 +        self.startVM('SecurityDVM')
   6.951 +        self.waitStartup('SecurityDVM')
   6.952 +        checkResult(Cygwin.sshExecute('"sudo apt-get -y update"', VMManager.getHostOnlyIP('SecurityDVM'), 'osecuser', Cygwin.cygPath(self.machineFolder) + '/' + 'SecurityDVM' + '/dvm_key'))
   6.953 +        checkResult(Cygwin.sshExecute('"sudo apt-get -y upgrade"', VMManager.getHostOnlyIP('SecurityDVM'), 'osecuser', Cygwin.cygPath(self.machineFolder) + '/' + 'SecurityDVM' + '/dvm_key'))
   6.954 +        #self.stopVM('SecurityDVM')
   6.955 +        self.hibernateVM('SecurityDVM')
   6.956 +        self.waitShutdown('SecurityDVM')
   6.957 +        self.storageDetach('SecurityDVM')
   6.958 +        self.changeStorageType(template_storage,'immutable')
   6.959 +        self.storageAttach('SecurityDVM')
   6.960 +        self.rsdHandler = DeviceHandler(self)
   6.961 +        self.rsdHandler.start()
   6.962 +    
   6.963 +    #remove VM from the system. should be used on VMs returned by listSDVMs    
   6.964 +    def removeVM(self, vm_name):
   6.965 +        logger.info('Removing ' + vm_name)
   6.966 +        checkResult(Cygwin.vboxExecute('unregistervm ' + vm_name + ' --delete'))
   6.967 +        machineFolder = Cygwin.cygPath(self.machineFolder)
   6.968 +        checkResult(Cygwin.bashExecute('/usr/bin/rm -rf \\\"' + machineFolder + '/' + vm_name + '\\\"'))
   6.969 +    
   6.970 +    # start VM
   6.971 +    def startVM(self, vm_name):
   6.972 +        logger.info('Starting ' +  vm_name)
   6.973 +        result = checkResult(Cygwin.vboxExecute('startvm ' + vm_name + ' --type headless' ))
   6.974 +        while 'successfully started' not in result[1]:
   6.975 +            logger.error("Failed to start SDVM: " + vm_name + " retrying")
   6.976 +            time.sleep(1)
   6.977 +            result = checkResult(Cygwin.vboxExecute('startvm ' + vm_name + ' --type headless'))
   6.978 +        return result[0]
   6.979 +    
   6.980 +    # return wether VM is running or not
   6.981 +    def isVMRunning(self, vm_name):
   6.982 +        return vm_name in self.listRunningVMS()    
   6.983 +    
   6.984 +    # stop VM
   6.985 +    def stopVM(self, vm_name):
   6.986 +        logger.info('Sending shutdown signal to ' + vm_name)
   6.987 +        checkResult(Cygwin.sshExecute( '"sudo shutdown -h now"', VMManager.getHostOnlyIP(vm_name), 'osecuser', Cygwin.cygPath(self.machineFolder) + '/' + vm_name + '/dvm_key' ))
   6.988 +    
   6.989 +    # stop VM
   6.990 +    def hibernateVM(self, vm_name):
   6.991 +        logger.info('Sending hibernate-disk signal to ' + vm_name)
   6.992 +        checkResult(Cygwin.sshExecute( '"sudo hibernate-disk&"', VMManager.getHostOnlyIP(vm_name), 'osecuser', Cygwin.cygPath(self.machineFolder) + '/' + vm_name + '/dvm_key', wait_return=False))
   6.993 +            
   6.994 +    # poweroff VM
   6.995 +    def poweroffVM(self, vm_name):
   6.996 +        if not self.isVMRunning(vm_name):
   6.997 +            return
   6.998 +        logger.info('Powering off ' + vm_name)
   6.999 +        return checkResult(Cygwin.vboxExecute('controlvm ' + vm_name + ' poweroff'))
  6.1000 +    
  6.1001 +    #list the hostonly IFs exposed by the VBox host
  6.1002 +    @staticmethod    
  6.1003 +    def getHostOnlyIFs():
  6.1004 +        result = Cygwin.vboxExecute('list hostonlyifs')[1]
  6.1005 +        if result=='':
  6.1006 +            return None
  6.1007 +        props = dict((k.strip(),v.strip().strip('"')) for k,v in (line.split(':', 1) for line in result.strip().splitlines()))
  6.1008 +        return props
  6.1009 +    
  6.1010 +    # return the hostOnly IP for a running guest or the host
  6.1011 +    @staticmethod    
  6.1012 +    def getHostOnlyIP(vm_name):
  6.1013 +        if vm_name == None:
  6.1014 +            logger.info('Gettting hostOnly IP address for Host')
  6.1015 +            return VMManager.getHostOnlyIFs()['IPAddress']
  6.1016 +        else:
  6.1017 +            logger.info('Gettting hostOnly IP address ' + vm_name)
  6.1018 +            result = checkResult(Cygwin.vboxExecute('guestproperty get ' + vm_name + ' /VirtualBox/GuestInfo/Net/0/V4/IP'))
  6.1019 +            if result=='':
  6.1020 +                return None
  6.1021 +            result = result[1]
  6.1022 +            if result.startswith('No value set!'):
  6.1023 +                return None
  6.1024 +            return result[result.index(':')+1:].strip()
  6.1025 +            
  6.1026 +    # attach removable storage device to VM by provision of filter
  6.1027 +    def attachRSD(self, vm_name, rsd_filter):
  6.1028 +        return checkResult(Cygwin.vboxExecute('usbfilter add 0 --target ' + vm_name + ' --name OpenSecurityRSD --vendorid ' + rsd_filter.vendorid + ' --productid ' + rsd_filter.productid + ' --revision ' + rsd_filter.revision))
  6.1029 +    
  6.1030 +    # detach removable storage from VM by 
  6.1031 +    def detachRSD(self, vm_name):
  6.1032 +        return checkResult(Cygwin.vboxExecute('usbfilter remove 0 --target ' + vm_name))
  6.1033 +        
  6.1034 +    # return the description set for an existing VM
  6.1035 +    def getVMInfo(self, vm_name):
  6.1036 +        results = checkResult(Cygwin.vboxExecute('showvminfo ' + vm_name + ' --machinereadable'))[1]
  6.1037 +        props = dict((k.strip().strip('"'),v.strip().strip('"')) for k,v in (line.split('=', 1) for line in results.splitlines()))
  6.1038 +        return props
  6.1039 +    
  6.1040 +    # return the configured USB filter for an existing VM 
  6.1041 +    def getUSBFilter(self, vm_name):
  6.1042 +        props = self.getVMInfo(vm_name)
  6.1043 +        keys = set(['USBFilterVendorId1', 'USBFilterProductId1', 'USBFilterRevision1'])
  6.1044 +        keyset = set(props.keys())
  6.1045 +        usb_filter = None
  6.1046 +        if keyset.issuperset(keys):
  6.1047 +            usb_filter = USBFilter(props['USBFilterVendorId1'], props['USBFilterProductId1'], props['USBFilterRevision1'])
  6.1048 +        return usb_filter
  6.1049 +    
  6.1050 +    #generates ISO containing authorized_keys for use with guest VM
  6.1051 +    def genCertificateISO(self, vm_name):
  6.1052 +        machineFolder = Cygwin.cygPath(self.machineFolder)
  6.1053 +        # remove .ssh folder if exists
  6.1054 +        checkResult(Cygwin.bashExecute('/usr/bin/rm -rf \\\"' + machineFolder + '/' + vm_name + '/.ssh\\\"'))
  6.1055 +        # remove .ssh folder if exists
  6.1056 +        checkResult(Cygwin.bashExecute('/usr/bin/rm -rf \\\"' + machineFolder + '/' + vm_name + '/dvm_key\\\"'))
  6.1057 +        # create .ssh folder in vm_name
  6.1058 +        checkResult(Cygwin.bashExecute('/usr/bin/mkdir -p \\\"' + machineFolder + '/' + vm_name + '/.ssh\\\"'))
  6.1059 +        # generate dvm_key pair in vm_name / .ssh     
  6.1060 +        checkResult(Cygwin.bashExecute('/usr/bin/ssh-keygen -q -t rsa -N \\\"\\\" -C \\\"' + vm_name + '\\\" -f \\\"' + machineFolder + '/' + vm_name + '/.ssh/dvm_key\\\"'))
  6.1061 +        # move out private key
  6.1062 +        checkResult(Cygwin.bashExecute('/usr/bin/mv \\\"' + machineFolder + '/' + vm_name + '/.ssh/dvm_key\\\" \\\"' + machineFolder + '/' + vm_name + '\\\"'))
  6.1063 +        # set permissions for private key
  6.1064 +        checkResult(Cygwin.bashExecute('/usr/bin/chmod 500 \\\"' + machineFolder + '/' + vm_name + '/dvm_key\\\"'))
  6.1065 +        # rename public key to authorized_keys
  6.1066 +        checkResult(Cygwin.bashExecute('/usr/bin/mv \\\"' + machineFolder + '/' + vm_name + '/.ssh/dvm_key.pub\\\" \\\"' + machineFolder + '/' + vm_name + '/.ssh/authorized_keys\\\"'))
  6.1067 +        # set permissions for authorized_keys
  6.1068 +        checkResult(Cygwin.bashExecute('/usr/bin/chmod 500 \\\"' + machineFolder + '/' + vm_name + '/.ssh/authorized_keys\\\"'))
  6.1069 +        # generate iso image with .ssh/authorized keys
  6.1070 +        checkResult(Cygwin.bashExecute('/usr/bin/genisoimage -J -R -o \\\"' + machineFolder + '/' + vm_name + '/'+ vm_name + '.iso\\\" \\\"' + machineFolder + '/' + vm_name + '/.ssh\\\"'))
  6.1071 +    
  6.1072 +    # attaches generated ssh public cert to guest vm
  6.1073 +    def attachCertificateISO(self, vm_name):
  6.1074 +        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\"'))
  6.1075 +        return result
  6.1076 +    
  6.1077 +    # wait for machine to come up
  6.1078 +    def waitStartup(self, vm_name, timeout_ms = 30000):
  6.1079 +        checkResult(Cygwin.vboxExecute('guestproperty wait ' + vm_name + ' SDVMStarted --timeout ' + str(timeout_ms) + ' --fail-on-timeout'))
  6.1080 +        return VMManager.getHostOnlyIP(vm_name)
  6.1081 +    
  6.1082 +    # wait for machine to shutdown
  6.1083 +    def waitShutdown(self, vm_name):
  6.1084 +        while vm_name in self.listRunningVMS():
  6.1085 +            time.sleep(1)
  6.1086 +        return
  6.1087 +        
  6.1088 +    # handles browsing request    
  6.1089 +    def handleBrowsingRequest(self):
  6.1090 +        handler = BrowsingHandler(self)
  6.1091 +        handler.start()
  6.1092 +        return 'ok'
  6.1093 +    
  6.1094 +    #Small function to check the availability of network resource.
  6.1095 +    #def isAvailable(self, path):
  6.1096 +        #return os.path.exists(path)
  6.1097 +        #result = Cygwin.cmdExecute('IF EXIST "' + path + '" echo YES')
  6.1098 +        #return string.find(result[1], 'YES',)
  6.1099 +    
  6.1100 +    #Small function to check if the mention location is a directory
  6.1101 +    def isDirectory(self, path):
  6.1102 +        result = checkResult(Cygwin.cmdExecute('dir ' + path + ' | FIND ".."'))
  6.1103 +        return string.find(result[1], 'DIR',)
  6.1104 +
  6.1105 +    def mapNetworkDrive(self, drive, networkPath, user, password):
  6.1106 +        self.unmapNetworkDrive(drive)
  6.1107 +        #Check for drive availability
  6.1108 +        if os.path.exists(drive):
  6.1109 +            logger.error("Drive letter is already in use: " + drive)
  6.1110 +            return -1
  6.1111 +        #Check for network resource availability
  6.1112 +        retry = 5
  6.1113 +        while not os.path.exists(networkPath):
  6.1114 +            time.sleep(1)
  6.1115 +            if retry == 0:
  6.1116 +                return -1
  6.1117 +            logger.info("Path not accessible: " + networkPath + " retrying")
  6.1118 +            retry-=1
  6.1119 +            #return -1
  6.1120 +    
  6.1121 +        command = 'USE ' + drive + ' ' + networkPath + ' /PERSISTENT:NO'
  6.1122 +        if user != None:
  6.1123 +            command += ' ' + password + ' /User' + user
  6.1124 +    
  6.1125 +        #TODO: Execute 'NET USE' command with authentication
  6.1126 +        result = checkResult(Cygwin.execute('C:\\Windows\\system32\\net.exe', command))
  6.1127 +        if string.find(result[1], 'successfully',) == -1:
  6.1128 +            logger.error("Failed: NET " + command)
  6.1129 +            return -1
  6.1130 +        return 1
  6.1131 +    
  6.1132 +    def unmapNetworkDrive(self, drive):
  6.1133 +        drives = self.getNetworkDrives()
  6.1134 +        if drive not in drives.keys():
  6.1135 +            return 1 
  6.1136 +        result = checkResult(Cygwin.execute('C:\\Windows\\system32\\net.exe', 'USE ' + drive + ' /DELETE /YES'))
  6.1137 +        if string.find(str(result[1]), 'successfully',) == -1:
  6.1138 +            logger.error(result[2])
  6.1139 +            return -1
  6.1140 +        return 1
  6.1141 +    
  6.1142 +    def getNetworkDrives(self):
  6.1143 +        ip = VMManager.getHostOnlyIP(None)
  6.1144 +        ip = ip[:ip.rindex('.')]
  6.1145 +        drives = dict()    
  6.1146 +        result = checkResult(Cygwin.execute('C:\\Windows\\system32\\net.exe', 'USE'))
  6.1147 +        for line in result[1].splitlines():
  6.1148 +            if ip in line:
  6.1149 +                parts = line.split()
  6.1150 +                drives[parts[1]] = parts[2]
  6.1151 +        return drives
  6.1152 +            
  6.1153 +    def genNetworkDrive(self):
  6.1154 +        network_drives = self.getNetworkDrives()
  6.1155 +        logical_drives = VMManager.getLogicalDrives()
  6.1156 +        drives = list(map(chr, range(68, 91)))  
  6.1157 +        for drive in drives:
  6.1158 +            if drive+':' not in network_drives and drive not in logical_drives:
  6.1159 +                return drive+':'
  6.1160 +
  6.1161 +    def getNetworkDrive(self, vm_name):
  6.1162 +        ip = self.getHostOnlyIP(vm_name)
  6.1163 +        result = checkResult(Cygwin.execute('C:\\Windows\\system32\\net.exe', 'USE'))
  6.1164 +        for line in result[1].splitlines():
  6.1165 +            if line != None and ip in line:
  6.1166 +                parts = line.split()
  6.1167 +                return parts[0]
  6.1168 +    @staticmethod
  6.1169 +    def getLogicalDrives():
  6.1170 +        drive_bitmask = ctypes.cdll.kernel32.GetLogicalDrives()
  6.1171 +        return list(itertools.compress(string.ascii_uppercase,  map(lambda x:ord(x) - ord('0'), bin(drive_bitmask)[:1:-1])))
  6.1172 +    
  6.1173 +    @staticmethod
  6.1174 +    def getDriveType(drive):
  6.1175 +        return ctypes.cdll.kernel32.GetDriveTypeW(u"%s:\\"%drive)
  6.1176 +    
  6.1177 +    @staticmethod
  6.1178 +    def getVolumeInfo(drive):
  6.1179 +        volumeNameBuffer = ctypes.create_unicode_buffer(1024)
  6.1180 +        fileSystemNameBuffer = ctypes.create_unicode_buffer(1024)
  6.1181 +        serial_number = None
  6.1182 +        max_component_length = None
  6.1183 +        file_system_flags = None
  6.1184 +        
  6.1185 +        rc = ctypes.cdll.kernel32.GetVolumeInformationW(
  6.1186 +            #ctypes.c_wchar_p("F:\\"),
  6.1187 +            u"%s:\\"%drive,
  6.1188 +            volumeNameBuffer,
  6.1189 +            ctypes.sizeof(volumeNameBuffer),
  6.1190 +            serial_number,
  6.1191 +            max_component_length,
  6.1192 +            file_system_flags,
  6.1193 +            fileSystemNameBuffer,
  6.1194 +            ctypes.sizeof(fileSystemNameBuffer)
  6.1195 +        )
  6.1196 +        
  6.1197 +        return volumeNameBuffer.value, fileSystemNameBuffer.value
  6.1198 +
  6.1199 +def checkResult(result):
  6.1200 +    if result[0] != 0:
  6.1201 +        logger.error('Command failed:' + ''.join(result[2]))
  6.1202 +        raise OpenSecurityException('Command failed:' + ''.join(result[2]))
  6.1203 +    return result
  6.1204 +
  6.1205 +# handles browsing request                    
  6.1206 +class BrowsingHandler(threading.Thread):   
  6.1207 +    vmm = None
  6.1208 +    def __init__(self, vmmanager):
  6.1209 +        threading.Thread.__init__(self)
  6.1210 +        self.vmm = vmmanager
  6.1211 +     
  6.1212 +    def run(self):
  6.1213 +        drive = None
  6.1214 +        try:
  6.1215 +            Cygwin.start_X11()
  6.1216 +            new_sdvm = self.vmm.generateSDVMName()
  6.1217 +            self.vmm.createVM(new_sdvm)
  6.1218 +            self.vmm.storageAttach(new_sdvm)
  6.1219 +            self.vmm.genCertificateISO(new_sdvm)
  6.1220 +            self.vmm.attachCertificateISO(new_sdvm)
  6.1221 +            self.vmm.startVM(new_sdvm)
  6.1222 +            new_ip = self.vmm.waitStartup(new_sdvm)
  6.1223 +            drive = self.vmm.genNetworkDrive()
  6.1224 +            if new_ip != None:
  6.1225 +                self.vmm.mapNetworkDrive(drive, '\\\\' + new_ip + '\\Download', None, None)
  6.1226 +            #browser = '/usr/bin/iceweasel'
  6.1227 +            #browser = '/usr/bin/midori'
  6.1228 +            browser = '/usr/bin/chromium'
  6.1229 +            result = checkResult(Cygwin.sshExecuteX11(browser, new_ip, 'osecuser', Cygwin.cygPath(self.vmm.getMachineFolder()) + '/' + new_sdvm + '/dvm_key'))
  6.1230 +        except:
  6.1231 +            logger.error("BrowsingHandler failed. Cleaning up")
  6.1232 +        if drive != None:    
  6.1233 +            self.vmm.unmapNetworkDrive(drive)
  6.1234 +        self.vmm.poweroffVM(new_sdvm)
  6.1235 +        self.vmm.removeVM(new_sdvm)
  6.1236 +                
  6.1237 +class DeviceHandler(threading.Thread): 
  6.1238 +    vmm = None
  6.1239 +    attachedRSDs = None  
  6.1240 +    connectedRSDs = None
  6.1241 +    running = True
  6.1242 +    def __init__(self, vmmanger): 
  6.1243 +        threading.Thread.__init__(self)
  6.1244 +        self.vmm = vmmanger
  6.1245 + 
  6.1246 +    def stop(self):
  6.1247 +        self.running = False
  6.1248 +        
  6.1249 +    def run(self):
  6.1250 +        self.connectedRSDs = dict()
  6.1251 +        while self.running:
  6.1252 +            tmp_rsds = self.vmm.getConnectedRSDS()
  6.1253 +            
  6.1254 +            self.attachedRSDs = self.vmm.getAttachedRSDs()
  6.1255 +            for vm_name in self.attachedRSDs.keys():
  6.1256 +                if self.attachedRSDs[vm_name] not in tmp_rsds.values():
  6.1257 +                    drive = self.vmm.getNetworkDrive(vm_name)
  6.1258 +                    self.vmm.unmapNetworkDrive(drive)
  6.1259 +                    #self.stopVM(vm_name)
  6.1260 +                    self.vmm.detachRSD(vm_name)
  6.1261 +                    self.vmm.poweroffVM(vm_name)
  6.1262 +                    self.vmm.removeVM(vm_name)
  6.1263 +                    break
  6.1264 +                    
  6.1265 +                    
  6.1266 +            if tmp_rsds.keys() == self.connectedRSDs.keys():
  6.1267 +                logger.debug("Nothing's changed. sleep(3)")
  6.1268 +                time.sleep(3)
  6.1269 +                continue
  6.1270 +            
  6.1271 +            logger.info("Something's changed")          
  6.1272 +            self.connectedRSDs = tmp_rsds
  6.1273 +            
  6.1274 +            
  6.1275 +            
  6.1276 +            #create new vm for attached device if any
  6.1277 +            self.attachedRSDs = self.vmm.getAttachedRSDs()
  6.1278 +            self.connectedRSDs = self.vmm.getConnectedRSDS()
  6.1279 +            
  6.1280 +            new_ip = None
  6.1281 +            for connected_device in self.connectedRSDs.values():
  6.1282 +                if (self.attachedRSDs and False) or (connected_device not in self.attachedRSDs.values()):
  6.1283 +                    new_sdvm = self.vmm.generateSDVMName()
  6.1284 +                    self.vmm.createVM(new_sdvm)
  6.1285 +                    self.vmm.storageAttach(new_sdvm)
  6.1286 +                    self.vmm.attachRSD(new_sdvm, connected_device)
  6.1287 +                    self.vmm.startVM(new_sdvm)
  6.1288 +                    new_ip = self.vmm.waitStartup(new_sdvm)
  6.1289 +                    drive = self.vmm.genNetworkDrive()
  6.1290 +                    if new_ip != None:
  6.1291 +                        self.vmm.mapNetworkDrive(drive, '\\\\' + new_ip + '\\USB', None, None)
  6.1292 +
  6.1293 +if __name__ == '__main__':
  6.1294 +    #man = VMManager.getInstance()
  6.1295 +    #man.listVM()
  6.1296 +    #print man.getConnectedRSDs()
  6.1297 +    #print man.getNetworkDrives()
  6.1298 +    #man.genNetworkDrive()
  6.1299 +    #drive_bitmask = ctypes.cdll.kernel32.GetLogicalDrives()
  6.1300 +    #print list(itertools.compress(string.ascii_uppercase,  map(lambda x:ord(x) - ord('0'), bin(drive_bitmask)[:1:-1])))
  6.1301 +    #print list(map(chr, range(68, 91))) 
  6.1302 +    #print Cygwin.getRegEntry('SYSTEM\CurrentControlSet\Enum\USB', 'VID_1058&PID_0704')[0]
  6.1303 +    #devices = VMManager.getConnectedRSDS()
  6.1304 +    #print devices
  6.1305 +    
  6.1306 +    drives = VMManager.getLogicalDrives()
  6.1307 +    print drives
  6.1308 +    print VMManager.getDriveType("E")
  6.1309 +    print VMManager.getVolumeInfo("E")
  6.1310 +    #for device in devices.values():
  6.1311 +    #    #print device
  6.1312 +    #    if VMManager.isMassStorageDevice(device):
  6.1313 +    #        print device
  6.1314 +        
  6.1315 +    
  6.1316 +    
  6.1317 +    #time.sleep(-1)
  6.1318 +    #man.listVM()
  6.1319 +    #man.listVM()
  6.1320 +    #man.listVM()
  6.1321 +    #man.listVM()
  6.1322 +    #man.genCertificateISO('SecurityDVM0')
  6.1323 +    #man.guestExecute('SecurityDVM0', '/bin/ls -la')
  6.1324 +    #logger = setupLogger('VMManager')
  6.1325 +    #c = Cygwin()
  6.1326 +    
  6.1327 +    #man.sshExecute('/bin/ls -la', 'SecurityDVM0')
  6.1328 +    #man.sshExecuteX11('/usr/bin/iceweasel', 'SecurityDVM0')
  6.1329 +    #man.removeVM('SecurityDVM0')
  6.1330 +    #man.netUse('192.168.56.134', 'USB\\')
  6.1331 +    #ip = '192.168.56.139'
  6.1332 +    
  6.1333 +    #man.cygwin_path = 'c:\\cygwin64\\bin\\'
  6.1334 +    #man.handleDeviceChange()
  6.1335 +    #print man.listSDVM()
  6.1336 +    #man.configureHostNetworking()
  6.1337 +    #new_vm = man.generateSDVMName()
  6.1338 +    #man.createVM(new_vm)
  6.1339 +    
  6.1340 +    #print Cygwin.cmd()
  6.1341 +    #man.isAvailable('c:')
  6.1342 +    #ip = man.getHostOnlyIP('SecurityDVM0')
  6.1343 +    #man.mapNetworkDrive('h:', '\\\\' + ip + '\Download', None, None)
  6.1344 +    
  6.1345 +    #man.genCertificateISO(new_vm)
  6.1346 +    #man.attachCertificateISO(new_vm)
  6.1347 +    
  6.1348 +    #man.attachCertificateISO(vm_name)
  6.1349 +    #man.guestExecute(vm_name, "ls")
  6.1350 +    #man.sshGuestX11Execute('SecurityDVM1', '/usr/bin/iceweasel')
  6.1351 +    #time.sleep(60)
  6.1352 +    #print man.cygwinPath("C:\Users\BarthaM\VirtualBox VMs\SecurityDVM\.ssh\*")
  6.1353 +    #man.genCertificateISO('SecurityDVM')
  6.1354 +    #man.attachCertificateISO('SecurityDVM')
  6.1355 +    #man.isStorageAttached('SecurityDVM')
  6.1356 +    #man.guestExecute('SecurityDVM', 'sudo apt-get -y update')
  6.1357 +    #man.guestExecute('SecurityDVM', 'sudo apt-get -y upgrade' )
  6.1358 +    
  6.1359 +    #man.stopVM('SecurityDVM')
  6.1360 +    #man.storageDetach('SecurityDVM')
  6.1361 +    #man.changeStorageType('C:\Users\BarthaM\VirtualBox VMs\SecurityDVM\SecurityDVM.vmdk','immutable')
  6.1362 +    #man.storageAttach('SecurityDVM')
  6.1363 +    
  6.1364 +    
  6.1365 +    #cmd = "c:\\cygwin64\\bin\\bash.exe --login -c \"/bin/ls\""
  6.1366 +    #man.execute(cmd)