new version. many bugfixes and new functionality
authormb
Fri, 07 Mar 2014 14:32:12 +0100
changeset 90bfd41c38d156
parent 89 7a925dd96e2d
child 91 a26757850ea9
child 95 cdebb7e0ba10
new version. many bugfixes and new functionality
OpenSecurity/bin/cygwin.py
OpenSecurity/bin/opensecurity_client_restful_server.py
OpenSecurity/bin/opensecurity_tray.pyw
OpenSecurity/bin/opensecurityd.pyw
OpenSecurity/bin/vmmanager.pyw
     1.1 --- a/OpenSecurity/bin/cygwin.py	Wed Mar 05 12:00:11 2014 +0100
     1.2 +++ b/OpenSecurity/bin/cygwin.py	Fri Mar 07 14:32:12 2014 +0100
     1.3 @@ -1,229 +1,222 @@
     1.4 -#!/bin/env python
     1.5 -# -*- coding: utf-8 -*-
     1.6 -
     1.7 -# ------------------------------------------------------------
     1.8 -# cygwin command
     1.9 -# 
    1.10 -# executes a cygwin command inside the opensecurity project
    1.11 -#
    1.12 -# Autor: Mihai Bartha, <mihai.bartha@ait.ac.at>
    1.13 -#        Oliver Maurhart, <oliver.maurhart@ait.ac.at>
    1.14 -#
    1.15 -# Copyright (C) 2013 AIT Austrian Institute of Technology
    1.16 -# AIT Austrian Institute of Technology GmbH
    1.17 -# Donau-City-Strasse 1 | 1220 Vienna | Austria
    1.18 -# http://www.ait.ac.at
    1.19 -#
    1.20 -# This program is free software; you can redistribute it and/or
    1.21 -# modify it under the terms of the GNU General Public License
    1.22 -# as published by the Free Software Foundation version 2.
    1.23 -# 
    1.24 -# This program is distributed in the hope that it will be useful,
    1.25 -# but WITHOUT ANY WARRANTY; without even the implied warranty of
    1.26 -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    1.27 -# GNU General Public License for more details.
    1.28 -# 
    1.29 -# You should have received a copy of the GNU General Public License
    1.30 -# along with this program; if not, write to the Free Software
    1.31 -# Foundation, Inc., 51 Franklin Street, Fifth Floor, 
    1.32 -# Boston, MA  02110-1301, USA.
    1.33 -# ------------------------------------------------------------
    1.34 -
    1.35 -
    1.36 -# ------------------------------------------------------------
    1.37 -# imports
    1.38 -
    1.39 -import os
    1.40 -import subprocess
    1.41 -import sys
    1.42 -import _winreg
    1.43 -from subprocess import Popen, PIPE, call, STARTUPINFO, _subprocess
    1.44 -import threading
    1.45 -# local
    1.46 -from environment import Environment
    1.47 -from opensecurity_util import logger, setupLogger, OpenSecurityException
    1.48 -
    1.49 -# ------------------------------------------------------------
    1.50 -# code
    1.51 -
    1.52 -def once(theClass):
    1.53 -    """get the path to our local cygwin installment"""
    1.54 -    home_drive = os.path.expandvars("%HOMEDRIVE%") + os.sep
    1.55 -    path_hint = [ 
    1.56 -        os.path.abspath(os.path.join(Environment('OpenSecurity').prefix_path, '..', 'cygwin')), 
    1.57 -        os.path.abspath(os.path.join(Environment('OpenSecurity').prefix_path, '..', 'cygwin64')), 
    1.58 -        os.path.abspath(os.path.join(home_drive, 'cygwin')),
    1.59 -        os.path.abspath(os.path.join(home_drive, 'cygwin64'))
    1.60 -    ]
    1.61 -    path_valid = [ p for p in path_hint if os.path.exists(p) ]
    1.62 -        
    1.63 -    theClass.cygwin_root = path_valid[0]
    1.64 -    theClass.cygwin_bin = os.path.join(theClass.cygwin_root, 'bin') + os.path.sep
    1.65 -    theClass.cygwin_bash = os.path.join(theClass.cygwin_bin, 'bash.exe')
    1.66 -    theClass.cygwin_ssh = os.path.join(theClass.cygwin_bin, 'ssh.exe')
    1.67 -    theClass.cygwin_x11 = os.path.join(theClass.cygwin_bin, 'XWin.exe')
    1.68 -    theClass.win_cmd = os.environ.get("COMSPEC", "cmd.exe") 
    1.69 -    
    1.70 -    """get the path to the VirtualBox installation on this system"""
    1.71 -    try:
    1.72 -        k = _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE, 'SOFTWARE\Oracle\VirtualBox')
    1.73 -        theClass.vbox_root = _winreg.QueryValueEx(k, 'InstallDir')[0]
    1.74 -        theClass.vbox_man = os.path.join(theClass.vbox_root, 'VBoxManage.exe')
    1.75 -        _winreg.CloseKey(k)
    1.76 -    except:
    1.77 -        pass
    1.78 -    return theClass
    1.79 -
    1.80 -@once
    1.81 -class Cygwin(object):
    1.82 -    cygwin_root = ''
    1.83 -    cygwin_bin = ''
    1.84 -    cygwin_bash = ''
    1.85 -    cygwin_ssh = ''
    1.86 -    cygwin_x11 = ''
    1.87 -    vbox_root = ''
    1.88 -    vbox_man = ''
    1.89 -    win_cmd = ''
    1.90 -    """Some nifty methods working with Cygwin"""
    1.91 -    
    1.92 -    def __call__(self, command, arguments, wait_return=True, window = False):
    1.93 -        """make an instance of this object act as a function"""
    1.94 -        return self.execute(command, arguments, wait_return, window)
    1.95 -
    1.96 -        
    1.97 -    @staticmethod
    1.98 -    def root():
    1.99 -        return Cygwin.cygwin_root
   1.100 -
   1.101 -    @staticmethod
   1.102 -    def bin():
   1.103 -        return Cygwin.cygwin_bin
   1.104 -    
   1.105 -    @staticmethod
   1.106 -    def bash():
   1.107 -        return Cygwin.cygwin_bash
   1.108 -    
   1.109 -    @staticmethod    
   1.110 -    def ssh():
   1.111 -        return Cygwin.cygwin_ssh
   1.112 -
   1.113 -    @staticmethod    
   1.114 -    def x11():
   1.115 -        return Cygwin.cygwin_x11
   1.116 -    
   1.117 -    @staticmethod
   1.118 -    def vboxman():
   1.119 -        return Cygwin.vbox_man
   1.120 -    
   1.121 -    @staticmethod
   1.122 -    def cmd():
   1.123 -        return Cygwin.win_cmd
   1.124 -    
   1.125 -    executeLock = threading.Lock()
   1.126 -    #executes command on host system
   1.127 -    @staticmethod
   1.128 -    def execute(program, arguments, wait_return=True, window = False):
   1.129 -        _startupinfo = STARTUPINFO()
   1.130 -        if not window:
   1.131 -            _startupinfo.dwFlags |= _subprocess.STARTF_USESHOWWINDOW
   1.132 -            _startupinfo.wShowWindow = _subprocess.SW_HIDE
   1.133 -
   1.134 -            #logger.debug('trying to launch: ' + program + ' ' + ''.join(arguments))
   1.135 -        res_stderr = None
   1.136 -        try:
   1.137 -            process = Popen(executable=program, args=' ' + arguments, startupinfo = _startupinfo, stdin=PIPE, stdout=PIPE, stderr=PIPE, shell = False)
   1.138 -            logger.debug('Launched: ' + program + ' ' + ''.join(arguments))
   1.139 -            if not wait_return:
   1.140 -                return [0, 'working in background', '']
   1.141 -            result = process.wait()
   1.142 -            res_stdout = process.stdout.read();
   1.143 -            res_stderr = process.stderr.read();
   1.144 -
   1.145 -        except Exception as ex:
   1.146 -            res_stderr = ''.join(ex.args)
   1.147 -            result = -1 
   1.148 -        
   1.149 -        if result != 0:
   1.150 -            logger.error('Failed to execute cygwin command.\n\tcommand=' + program + ' ' + ''.join(arguments) + '\n' + res_stderr)
   1.151 -            raise OpenSecurityException('Failed to execute cygwin command.\n\tcommand=' + program + ' ' + ''.join(arguments) + '\n' + res_stderr)
   1.152 -            
   1.153 -        return result, res_stdout, res_stderr
   1.154 -    
   1.155 -    @staticmethod
   1.156 -    def vboxExecute(command, wait_return=True, window = False, bash_opts=''):
   1.157 -        if Cygwin.executeLock.acquire(True):
   1.158 -            retry = 0
   1.159 -            while retry < 3:
   1.160 -                try:
   1.161 -                    result = Cygwin.execute(Cygwin.vbox_man, command, wait_return, window)
   1.162 -                    Cygwin.executeLock.release()
   1.163 -                    return result
   1.164 -                except OpenSecurityException as inst:
   1.165 -                    retry+=1
   1.166 -            Cygwin.executeLock.release()
   1.167 -            raise inst
   1.168 -        return result
   1.169 -        
   1.170 -    
   1.171 -    @staticmethod
   1.172 -    def bashExecute(command, wait_return=True, window = False, bash_opts=''):
   1.173 -        command = bash_opts + ' -l -c '  + command
   1.174 -        return Cygwin.execute(Cygwin.cygwin_bash, command, wait_return, window)
   1.175 -    
   1.176 -    @staticmethod
   1.177 -    def cmdExecute(command, wait_return=True, window = False, bash_opts=''):
   1.178 -        command = ' /c ' + command 
   1.179 -        return Cygwin.execute(Cygwin.win_cmd, command, wait_return, window)
   1.180 -
   1.181 -    # executes command over ssh on guest vm
   1.182 -    @staticmethod
   1.183 -    def sshExecute(command, address, user_name, certificate, wait_return=True, window = False):
   1.184 -        command = ' -v -i "' + certificate + '" ' + user_name + '@' + address + ' ' + command        
   1.185 -        return Cygwin.execute(Cygwin.cygwin_ssh, command, wait_return, window)     
   1.186 -    
   1.187 -    #machineFolder + '/' + vm_name + '/dvm_key
   1.188 -    #address = self.getHostOnlyIP(vm_name)
   1.189 -    #machineFolder = self.getDefaultMachineFolder()
   1.190 -    #machineFolder = Cygwin.cygwinPath(machineFolder)
   1.191 -    
   1.192 -    # executes command over ssh on guest vm with X forwarding
   1.193 -    @staticmethod
   1.194 -    def sshExecuteX11(command, address, user_name, certificate, wait_return=True):
   1.195 -        return Cygwin.bashExecute('"DISPLAY=:0.0 /usr/bin/ssh -v -Y -i \\"' + certificate +'\\" ' + user_name + '@' + address + ' ' + command + '\"')
   1.196 -
   1.197 -    @staticmethod
   1.198 -    def is_X11_running():
   1.199 -        """check if we can connect to a X11 running instance"""
   1.200 -        p = Cygwin.bashExecute('"DISPLAY=:0 /usr/bin/xset -q"')
   1.201 -        return p[0] == 0
   1.202 -        
   1.203 -        
   1.204 -    @staticmethod
   1.205 -    def start_X11():
   1.206 -        """start X11 in the background (if not already running) on DISPLAY=:0"""
   1.207 -        # do not start if already running
   1.208 -        if Cygwin.is_X11_running():
   1.209 -            return           
   1.210 -        # launch X11 (forget output and return immediately)
   1.211 -        return Cygwin.execute(Cygwin.cygwin_x11, ':0 -multiwindow', wait_return = False, window = False)
   1.212 -    
   1.213 -    @staticmethod    
   1.214 -    def cygPath(path):
   1.215 -        cmd = '"/usr/bin/cygpath -u \\"' + path + '\\""'
   1.216 -        return Cygwin.bashExecute(cmd)[1].rstrip('\n')
   1.217 -    
   1.218 -# start
   1.219 -if __name__ == "__main__":
   1.220 -    logger = setupLogger('Cygwin')
   1.221 -    c = Cygwin()
   1.222 -    logger.info(c.root())
   1.223 -    logger.info(c.bin())
   1.224 -    logger.info(c.bash())
   1.225 -    logger.info(c.ssh())
   1.226 -    
   1.227 -    c.cygPath('C:')
   1.228 -    c.start_X11()
   1.229 -
   1.230 -        
   1.231 -    
   1.232 -    
   1.233 +#!/bin/env python
   1.234 +# -*- coding: utf-8 -*-
   1.235 +
   1.236 +# ------------------------------------------------------------
   1.237 +# cygwin command
   1.238 +# 
   1.239 +# executes a cygwin command inside the opensecurity project
   1.240 +#
   1.241 +# Autor: Mihai Bartha, <mihai.bartha@ait.ac.at>
   1.242 +#        Oliver Maurhart, <oliver.maurhart@ait.ac.at>
   1.243 +#
   1.244 +# Copyright (C) 2013 AIT Austrian Institute of Technology
   1.245 +# AIT Austrian Institute of Technology GmbH
   1.246 +# Donau-City-Strasse 1 | 1220 Vienna | Austria
   1.247 +# http://www.ait.ac.at
   1.248 +#
   1.249 +# This program is free software; you can redistribute it and/or
   1.250 +# modify it under the terms of the GNU General Public License
   1.251 +# as published by the Free Software Foundation version 2.
   1.252 +# 
   1.253 +# This program is distributed in the hope that it will be useful,
   1.254 +# but WITHOUT ANY WARRANTY; without even the implied warranty of
   1.255 +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   1.256 +# GNU General Public License for more details.
   1.257 +# 
   1.258 +# You should have received a copy of the GNU General Public License
   1.259 +# along with this program; if not, write to the Free Software
   1.260 +# Foundation, Inc., 51 Franklin Street, Fifth Floor, 
   1.261 +# Boston, MA  02110-1301, USA.
   1.262 +# ------------------------------------------------------------
   1.263 +
   1.264 +
   1.265 +# ------------------------------------------------------------
   1.266 +# imports
   1.267 +
   1.268 +import os
   1.269 +import subprocess
   1.270 +import sys
   1.271 +import _winreg
   1.272 +from subprocess import Popen, PIPE, call, STARTUPINFO, _subprocess
   1.273 +import threading
   1.274 +# local
   1.275 +from environment import Environment
   1.276 +from opensecurity_util import logger, setupLogger, OpenSecurityException
   1.277 +
   1.278 +# ------------------------------------------------------------
   1.279 +# code
   1.280 +
   1.281 +def once(theClass):
   1.282 +    """get the path to our local cygwin installment"""
   1.283 +    home_drive = os.path.expandvars("%HOMEDRIVE%") + os.sep
   1.284 +    path_hint = [ 
   1.285 +        os.path.abspath(os.path.join(Environment('OpenSecurity').prefix_path, '..', 'cygwin')), 
   1.286 +        os.path.abspath(os.path.join(Environment('OpenSecurity').prefix_path, '..', 'cygwin64')), 
   1.287 +        os.path.abspath(os.path.join(home_drive, 'cygwin')),
   1.288 +        os.path.abspath(os.path.join(home_drive, 'cygwin64'))
   1.289 +    ]
   1.290 +    path_valid = [ p for p in path_hint if os.path.exists(p) ]
   1.291 +        
   1.292 +    theClass.cygwin_root = path_valid[0]
   1.293 +    theClass.cygwin_bin = os.path.join(theClass.cygwin_root, 'bin') + os.path.sep
   1.294 +    theClass.cygwin_bash = os.path.join(theClass.cygwin_bin, 'bash.exe')
   1.295 +    theClass.cygwin_ssh = os.path.join(theClass.cygwin_bin, 'ssh.exe')
   1.296 +    theClass.cygwin_x11 = os.path.join(theClass.cygwin_bin, 'XWin.exe')
   1.297 +    theClass.win_cmd = os.environ.get("COMSPEC", "cmd.exe") 
   1.298 +    """get the path to the VirtualBox installation on this system"""
   1.299 +    theClass.vbox_root = theClass.getRegEntry('SOFTWARE\Oracle\VirtualBox', 'InstallDir')[0]
   1.300 +    theClass.vbox_man = os.path.join(theClass.vbox_root, 'VBoxManage.exe')
   1.301 +    
   1.302 +    return theClass
   1.303 +
   1.304 +@once
   1.305 +class Cygwin(object):
   1.306 +    cygwin_root = ''
   1.307 +    cygwin_bin = ''
   1.308 +    cygwin_bash = ''
   1.309 +    cygwin_ssh = ''
   1.310 +    cygwin_x11 = ''
   1.311 +    vbox_root = ''
   1.312 +    vbox_man = ''
   1.313 +    win_cmd = ''
   1.314 +    """Some nifty methods working with Cygwin"""
   1.315 +    
   1.316 +    def __call__(self, command, arguments, wait_return=True, window = False):
   1.317 +        """make an instance of this object act as a function"""
   1.318 +        return self.execute(command, arguments, wait_return, window)
   1.319 +
   1.320 +    @staticmethod
   1.321 +    def getRegEntry(key, value):
   1.322 +        try:
   1.323 +            k = _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE, key)
   1.324 +            value = _winreg.QueryValueEx(k, value)
   1.325 +            _winreg.CloseKey(k)
   1.326 +            return value
   1.327 +        except:
   1.328 +            pass
   1.329 +            
   1.330 +    @staticmethod
   1.331 +    def root():
   1.332 +        return Cygwin.cygwin_root
   1.333 +
   1.334 +    @staticmethod
   1.335 +    def bin():
   1.336 +        return Cygwin.cygwin_bin
   1.337 +    
   1.338 +    @staticmethod
   1.339 +    def bash():
   1.340 +        return Cygwin.cygwin_bash
   1.341 +    
   1.342 +    @staticmethod    
   1.343 +    def ssh():
   1.344 +        return Cygwin.cygwin_ssh
   1.345 +
   1.346 +    @staticmethod    
   1.347 +    def x11():
   1.348 +        return Cygwin.cygwin_x11
   1.349 +    
   1.350 +    @staticmethod
   1.351 +    def vboxman():
   1.352 +        return Cygwin.vbox_man
   1.353 +    
   1.354 +    @staticmethod
   1.355 +    def cmd():
   1.356 +        return Cygwin.win_cmd
   1.357 +    
   1.358 +    executeLock = threading.Lock()
   1.359 +    #executes command on host system
   1.360 +    @staticmethod
   1.361 +    def execute(program, arguments, wait_return=True, window = False):
   1.362 +        _startupinfo = STARTUPINFO()
   1.363 +        if not window:
   1.364 +            _startupinfo.dwFlags |= _subprocess.STARTF_USESHOWWINDOW
   1.365 +            _startupinfo.wShowWindow = _subprocess.SW_HIDE
   1.366 +
   1.367 +            #logger.debug('trying to launch: ' + program + ' ' + ''.join(arguments))
   1.368 +        res_stderr = None
   1.369 +        try:
   1.370 +            process = Popen(executable=program, args=' ' + arguments, startupinfo = _startupinfo, stdin=PIPE, stdout=PIPE, stderr=PIPE, shell = False)
   1.371 +            logger.debug('Launched: ' + program + ' ' + ''.join(arguments))
   1.372 +            if not wait_return:
   1.373 +                return [0, 'working in background', '']
   1.374 +            result = process.wait()
   1.375 +            res_stdout = process.stdout.read();
   1.376 +            res_stderr = process.stderr.read();
   1.377 +
   1.378 +        except Exception as ex:
   1.379 +            res_stderr.join(ex.args)
   1.380 +            result = 1 
   1.381 +            
   1.382 +        return result, res_stdout, res_stderr
   1.383 +    
   1.384 +    @staticmethod
   1.385 +    def vboxExecute(command, wait_return=True, window = False, bash_opts=''):
   1.386 +        retry = 0
   1.387 +        result = None
   1.388 +        while retry < 3:
   1.389 +            if Cygwin.executeLock.acquire(True):
   1.390 +                result = Cygwin.execute(Cygwin.vbox_man, command, wait_return, window)
   1.391 +                Cygwin.executeLock.release()
   1.392 +                if result[0] == 0:
   1.393 +                    return result
   1.394 +                retry+=1
   1.395 +        return result
   1.396 +        
   1.397 +    
   1.398 +    @staticmethod
   1.399 +    def bashExecute(command, wait_return=True, window = False, bash_opts=''):
   1.400 +        command = bash_opts + ' -l -c '  + command
   1.401 +        return Cygwin.execute(Cygwin.cygwin_bash, command, wait_return, window)
   1.402 +    
   1.403 +    @staticmethod
   1.404 +    def cmdExecute(command, wait_return=True, window = False, bash_opts=''):
   1.405 +        command = ' /c ' + command 
   1.406 +        return Cygwin.execute(Cygwin.win_cmd, command, wait_return, window)
   1.407 +
   1.408 +    # executes command over ssh on guest vm
   1.409 +    @staticmethod
   1.410 +    def sshExecute(command, address, user_name, certificate, wait_return=True, window = False):
   1.411 +        command = ' -v -i "' + certificate + '" ' + user_name + '@' + address + ' ' + command        
   1.412 +        return Cygwin.execute(Cygwin.cygwin_ssh, command, wait_return, window)     
   1.413 +    
   1.414 +    #machineFolder + '/' + vm_name + '/dvm_key
   1.415 +    #address = self.getHostOnlyIP(vm_name)
   1.416 +    #machineFolder = self.getDefaultMachineFolder()
   1.417 +    #machineFolder = Cygwin.cygwinPath(machineFolder)
   1.418 +    
   1.419 +    # executes command over ssh on guest vm with X forwarding
   1.420 +    @staticmethod
   1.421 +    def sshExecuteX11(command, address, user_name, certificate, wait_return=True):
   1.422 +        return Cygwin.bashExecute('"DISPLAY=:0.0 /usr/bin/ssh -v -Y -i \\"' + certificate +'\\" ' + user_name + '@' + address + ' ' + command + '\"')
   1.423 +
   1.424 +    @staticmethod
   1.425 +    def is_X11_running():
   1.426 +        """check if we can connect to a X11 running instance"""
   1.427 +        p = Cygwin.bashExecute('"DISPLAY=:0 /usr/bin/xset -q"')
   1.428 +        return p[0] == 0
   1.429 +        
   1.430 +        
   1.431 +    @staticmethod
   1.432 +    def start_X11():
   1.433 +        """start X11 in the background (if not already running) on DISPLAY=:0"""
   1.434 +        # do not start if already running
   1.435 +        if Cygwin.is_X11_running():
   1.436 +            return           
   1.437 +        # launch X11 (forget output and return immediately)
   1.438 +        return Cygwin.execute(Cygwin.cygwin_x11, ':0 -multiwindow', wait_return = False, window = False)
   1.439 +    
   1.440 +    @staticmethod    
   1.441 +    def cygPath(path):
   1.442 +        return Cygwin.bashExecute('"/usr/bin/cygpath -u \\"' + path + '\\""')[1].rstrip('\n')
   1.443 +    
   1.444 +# start
   1.445 +if __name__ == "__main__":
   1.446 +    logger = setupLogger('Cygwin')
   1.447 +    c = Cygwin()
   1.448 +    logger.info(c.root())
   1.449 +    logger.info(c.bin())
   1.450 +    logger.info(c.bash())
   1.451 +    logger.info(c.ssh())
   1.452 +    
   1.453 +    c.cygPath('C:')
   1.454 +    c.start_X11()
     2.1 --- a/OpenSecurity/bin/opensecurity_client_restful_server.py	Wed Mar 05 12:00:11 2014 +0100
     2.2 +++ b/OpenSecurity/bin/opensecurity_client_restful_server.py	Fri Mar 07 14:32:12 2014 +0100
     2.3 @@ -39,6 +39,8 @@
     2.4  import urllib
     2.5  import urllib2
     2.6  import web
     2.7 +import threading
     2.8 +import time
     2.9  
    2.10  # local
    2.11  from environment import Environment
    2.12 @@ -155,6 +157,9 @@
    2.13          # pick the arguments
    2.14          args = web.input()
    2.15          
    2.16 +        if "message" in args:
    2.17 +            print args.message
    2.18 +        
    2.19          # we _need_ a type
    2.20          if not "msgtype" in args:
    2.21              raise web.badrequest('no msgtype given')
    2.22 @@ -172,6 +177,43 @@
    2.23          process = subprocess.Popen(process_command, shell = False, stdout = subprocess.PIPE)
    2.24          return "Ok"
    2.25  
    2.26 +class PasswordSender(threading.Thread):
    2.27 +    remote_ip = None
    2.28 +    args = None
    2.29 +    def __init__(self, remote_ip, args): 
    2.30 +        threading.Thread.__init__(self)
    2.31 +        self.args = args
    2.32 +        self.remote_ip = remote_ip
    2.33 + 
    2.34 +    def stop(self):
    2.35 +        self.running = False
    2.36 +        
    2.37 +    def run(self):
    2.38 +        # invoke the user dialog as a subprocess
    2.39 +        dlg_image = os.path.join(sys.path[0], 'opensecurity_dialog.py')
    2.40 +        process_command = [sys.executable, dlg_image, 'password', self.args.text]
    2.41 +        process = subprocess.Popen(process_command, shell = False, stdout = subprocess.PIPE)
    2.42 +        result = process.communicate()[0]
    2.43 +        if process.returncode != 0:
    2.44 +            print 'password request has been aborted.'
    2.45 +            return
    2.46 +        
    2.47 +        # all ok, tell send request back appropriate destination
    2.48 +        try:
    2.49 +            password = result.split(':')[1].split("'")[1]
    2.50 +        except:
    2.51 +            print 'error in password parsing'
    2.52 +            return
    2.53 +        
    2.54 +        url_addr = 'http://' + self.remote_ip + ':58080/password'
    2.55 +        url_data = urllib.urlencode({ 'password': password})
    2.56 +        url = url_addr + '?' + url_data
    2.57 +        req = urllib2.Request(url)
    2.58 +        try:
    2.59 +            res = urllib2.urlopen(req)
    2.60 +        except:
    2.61 +            print 'failed to contact: ' + url_addr
    2.62 +            return 
    2.63  
    2.64  class os_password:
    2.65      """OpenSecurity '/password' handler.
    2.66 @@ -193,36 +235,8 @@
    2.67          # remember remote ip
    2.68          remote_ip = web.ctx.environ['REMOTE_ADDR']
    2.69          
    2.70 -        # invoke the user dialog as a subprocess
    2.71 -        dlg_image = os.path.join(sys.path[0], 'opensecurity_dialog.py')
    2.72 -        process_command = [sys.executable, dlg_image, 'password', args.text]
    2.73 -        process = subprocess.Popen(process_command, shell = False, stdout = subprocess.PIPE)
    2.74 -        result = process.communicate()[0]
    2.75 -        if process.returncode != 0:
    2.76 -            return 'password request has been aborted.'
    2.77 -        
    2.78 -        # all ok, tell send request back appropriate destination
    2.79 -        
    2.80 -        # the returned value of the dialog is a jason object like
    2.81 -        # "{ 'password': 'THE_PASSWORD' }"
    2.82 -        # so we _could_ call eval(...) on this.
    2.83 -        #
    2.84 -        # However, anyone malicious enough _could_ encode a certain
    2.85 -        # "password" making some nasty things within that eval code. :(
    2.86 -        #
    2.87 -        # So this is plain old-school string hacking then ...
    2.88 -        try:
    2.89 -            password = result.split(':')[1].split("'")[1]
    2.90 -        except:
    2.91 -            raise web.internalerror('error in password parsing')
    2.92 -        
    2.93 -        url_addr = 'http://' + remote_ip + ':58080/password'
    2.94 -        url_data = urllib.urlencode({ 'password': password})
    2.95 -        req = urllib2.Request(url = url_addr + '?' + url_data)
    2.96 -        try:
    2.97 -            res = urllib2.urlopen(req)
    2.98 -        except:
    2.99 -            raise web.internalerror('failed to contact: ' + url_addr)
   2.100 +        sender = PasswordSender(remote_ip, args)
   2.101 +        sender.start()
   2.102          
   2.103          return 'password told'
   2.104  
     3.1 --- a/OpenSecurity/bin/opensecurity_tray.pyw	Wed Mar 05 12:00:11 2014 +0100
     3.2 +++ b/OpenSecurity/bin/opensecurity_tray.pyw	Fri Mar 07 14:32:12 2014 +0100
     3.3 @@ -44,7 +44,7 @@
     3.4  # local
     3.5  from about import About
     3.6  from environment import Environment
     3.7 -
     3.8 +from cygwin import Cygwin
     3.9  
    3.10  # ------------------------------------------------------------
    3.11  # code
    3.12 @@ -103,12 +103,13 @@
    3.13          try:
    3.14          
    3.15              # get a proper browsing VM
    3.16 +            Cygwin.start_X11()
    3.17              browsing_vm = urllib2.urlopen('http://127.0.0.1:8080/browsing').readline()
    3.18 -            dlg_launch_image = os.path.join(sys.path[0], 'launch.pyw')
    3.19 +            #dlg_launch_image = os.path.join(sys.path[0], 'launch.pyw')
    3.20              #process_command = [sys.executable, dlg_launch_image, browsing_vm, '/usr/bin/iceweasel']
    3.21 -            process_command = [sys.executable, dlg_launch_image, browsing_vm, '/usr/bin/midori']
    3.22 -            print(process_command)
    3.23 -            process = subprocess.Popen(process_command, shell = False)
    3.24 +            #process_command = [sys.executable, dlg_launch_image, browsing_vm, '/usr/bin/midori']
    3.25 +            #print(process_command)
    3.26 +            #process = subprocess.Popen(process_command, shell = False)
    3.27              
    3.28          except:
    3.29              dlg.hide()
     4.1 --- a/OpenSecurity/bin/opensecurityd.pyw	Wed Mar 05 12:00:11 2014 +0100
     4.2 +++ b/OpenSecurity/bin/opensecurityd.pyw	Fri Mar 07 14:32:12 2014 +0100
     4.3 @@ -90,8 +90,8 @@
     4.4          log_call(web.ctx.environ)
     4.5          global gvm_mgr
     4.6          try:
     4.7 -            browsingVM = gvm_mgr.handleBrowsingRequest()
     4.8 -            return browsingVM
     4.9 +            result = gvm_mgr.handleBrowsingRequest()
    4.10 +            return result
    4.11          except:
    4.12              raise web.internalerror()
    4.13  
    4.14 @@ -141,8 +141,7 @@
    4.15          global gvm_mgr
    4.16          command = '/' + command
    4.17          result = Cygwin.sshExecuteX11(command, gvm_mgr.getHostOnlyIP(name), 'osecuser', Cygwin.cygPath(gvm_mgr.getMachineFolder()) + '/' + name + '/dvm_key'  )
    4.18 -        self.poweroffVM(name)
    4.19 -        return gvm_mgr.removeVM(name)
    4.20 +        return result
    4.21      
    4.22  
    4.23  class os_sdvm_ip:
     5.1 --- a/OpenSecurity/bin/vmmanager.pyw	Wed Mar 05 12:00:11 2014 +0100
     5.2 +++ b/OpenSecurity/bin/vmmanager.pyw	Fri Mar 07 14:32:12 2014 +0100
     5.3 @@ -1,598 +1,672 @@
     5.4 -'''
     5.5 -Created on Nov 19, 2013
     5.6 -
     5.7 -@author: BarthaM
     5.8 -'''
     5.9 -import os
    5.10 -import os.path
    5.11 -from subprocess import Popen, PIPE, call, STARTUPINFO, _subprocess
    5.12 -import sys
    5.13 -import re
    5.14 -
    5.15 -from cygwin import Cygwin
    5.16 -from environment import Environment
    5.17 -import threading
    5.18 -import time
    5.19 -import string
    5.20 -
    5.21 -import shutil
    5.22 -import stat
    5.23 -import tempfile
    5.24 -from opensecurity_util import logger, setupLogger, OpenSecurityException
    5.25 -import ctypes
    5.26 -import itertools
    5.27 -DEBUG = True
    5.28 -
    5.29 -class VMManagerException(Exception):
    5.30 -    def __init__(self, value):
    5.31 -        self.value = value
    5.32 -    def __str__(self):
    5.33 -        return repr(self.value)
    5.34 -
    5.35 -class USBFilter:
    5.36 -    vendorid = ""
    5.37 -    productid = ""
    5.38 -    revision = ""
    5.39 -    
    5.40 -    def __init__(self, vendorid, productid, revision):
    5.41 -        self.vendorid = vendorid.lower()
    5.42 -        self.productid = productid.lower()
    5.43 -        self.revision = revision.lower()
    5.44 -        return
    5.45 -    
    5.46 -    def __eq__(self, other):
    5.47 -        return self.vendorid == other.vendorid and self.productid == other.productid and self.revision == other.revision
    5.48 -    
    5.49 -    def __hash__(self):
    5.50 -        return hash(self.vendorid) ^ hash(self.productid) ^ hash(self.revision)
    5.51 -    
    5.52 -    def __repr__(self):
    5.53 -        return "VendorId = \'" + str(self.vendorid) + "\' ProductId = \'" + str(self.productid) + "\' Revision = \'" + str(self.revision) + "\'"
    5.54 - 
    5.55 -class VMManager(object):
    5.56 -    vmRootName = "SecurityDVM"
    5.57 -    systemProperties = None
    5.58 -    _instance = None
    5.59 -    machineFolder = ''
    5.60 -    rsdHandler = None
    5.61 -    
    5.62 -    def __init__(self):
    5.63 -        self.systemProperties = self.getSystemProperties()
    5.64 -        self.machineFolder = self.systemProperties["Default machine folder"]
    5.65 -        self.cleanup()
    5.66 -        self.rsdHandler = DeviceHandler(self)
    5.67 -        self.rsdHandler.start()
    5.68 -        return
    5.69 -    
    5.70 -    @staticmethod
    5.71 -    def getInstance():
    5.72 -        if VMManager._instance == None:
    5.73 -            VMManager._instance = VMManager()
    5.74 -        return VMManager._instance
    5.75 -    
    5.76 -    def cleanup(self):
    5.77 -        if self.rsdHandler != None:
    5.78 -            self.rsdHandler.stop()
    5.79 -            self.rsdHandler.join()
    5.80 -        drives = self.getNetworkDrives()
    5.81 -        for drive in drives.keys():
    5.82 -            self.unmapNetworkDrive(drive)
    5.83 -        for vm in self.listSDVM():
    5.84 -            self.poweroffVM(vm)
    5.85 -            self.removeVM(vm)
    5.86 -        
    5.87 -    # return hosty system properties
    5.88 -    def getSystemProperties(self):
    5.89 -        result = Cygwin.vboxExecute('list systemproperties')
    5.90 -        if result[1]=='':
    5.91 -            return None
    5.92 -        props = dict((k.strip(),v.strip().strip('"')) for k,v in (line.split(':', 1) for line in result[1].strip().splitlines()))
    5.93 -        #logger.debug(props)
    5.94 -        return props
    5.95 -    
    5.96 -    # return the folder containing the guest VMs     
    5.97 -    def getMachineFolder(self):
    5.98 -        return self.machineFolder
    5.99 -
   5.100 -    # list all existing VMs registered with VBox
   5.101 -    def listVM(self):
   5.102 -        result = Cygwin.vboxExecute('list vms')[1]
   5.103 -        vms = list(k.strip().strip('"') for k,_ in (line.split(' ') for line in result.splitlines()))
   5.104 -        return vms
   5.105 -    
   5.106 -    # list running VMs
   5.107 -    def listRunningVMS(self):
   5.108 -        result = Cygwin.vboxExecute('list runningvms')[1]
   5.109 -        vms = list(k.strip().strip('"') for k,_ in (line.split(' ') for line in result.splitlines()))
   5.110 -        return vms
   5.111 -    
   5.112 -    # list existing SDVMs
   5.113 -    def listSDVM(self):
   5.114 -        vms = self.listVM()
   5.115 -        svdms = []
   5.116 -        for vm in vms:
   5.117 -            if vm.startswith(self.vmRootName) and vm != self.vmRootName:
   5.118 -                svdms.append(vm)
   5.119 -        return svdms
   5.120 -    
   5.121 -    # generate valid (not already existing SDVM name). necessary for creating a new VM
   5.122 -    def generateSDVMName(self):
   5.123 -        vms = self.listVM()
   5.124 -        for i in range(0,999):
   5.125 -            if(not self.vmRootName+str(i) in vms):
   5.126 -                return self.vmRootName+str(i)
   5.127 -        return ''
   5.128 -    
   5.129 -    # return the RSDs connected to the host
   5.130 -    def getConnectedRSDS(self):
   5.131 -        results = Cygwin.vboxExecute('list usbhost')[1]
   5.132 -        results = results.split('Host USB Devices:')[1].strip()
   5.133 -        
   5.134 -        items = list( "UUID:"+result for result in results.split('UUID:') if result != '')
   5.135 -        rsds = dict()   
   5.136 -        for item in items:
   5.137 -            props = dict()
   5.138 -            for line in item.splitlines():
   5.139 -                if line != "":         
   5.140 -                    k,v = line[:line.index(':')].strip(), line[line.index(':')+1:].strip()
   5.141 -                    props[k] = v
   5.142 -            
   5.143 -            if 'Product' in props.keys() and props['Product'] == 'Mass Storage':
   5.144 -                usb_filter = USBFilter( re.search(r"\((?P<vid>[0-9A-Fa-f]+)\)", props['VendorId']).groupdict()['vid'], 
   5.145 -                                        re.search(r"\((?P<pid>[0-9A-Fa-f]+)\)", props['ProductId']).groupdict()['pid'],
   5.146 -                                        re.search(r"\((?P<rev>[0-9A-Fa-f]+)\)", props['Revision']).groupdict()['rev'] )
   5.147 -                rsds[props['UUID']] = usb_filter;
   5.148 -                logger.debug(usb_filter)
   5.149 -        return rsds
   5.150 -    
   5.151 -    # return the RSDs attached to all existing SDVMs
   5.152 -    def getAttachedRSDs(self):
   5.153 -        vms = self.listSDVM()
   5.154 -        attached_devices = dict()
   5.155 -        for vm in vms:
   5.156 -            rsd_filter = self.getUSBFilter(vm)
   5.157 -            if rsd_filter != None:
   5.158 -                attached_devices[vm] = rsd_filter
   5.159 -        return attached_devices
   5.160 -    
   5.161 -    # configures hostonly networking and DHCP server. requires admin rights
   5.162 -    def configureHostNetworking(self):
   5.163 -        #cmd = 'vboxmanage list hostonlyifs'
   5.164 -        #Cygwin.vboxExecute(cmd)
   5.165 -        #cmd = 'vboxmanage hostonlyif remove \"VirtualBox Host-Only Ethernet Adapter\"'
   5.166 -        #Cygwin.vboxExecute(cmd)
   5.167 -        #cmd = 'vboxmanage hostonlyif create'
   5.168 -        #Cygwin.vboxExecute(cmd)
   5.169 -        Cygwin.vboxExecute('hostonlyif ipconfig \"VirtualBox Host-Only Ethernet Adapter\" --ip 192.168.56.1 --netmask 255.255.255.0')
   5.170 -        #cmd = 'vboxmanage dhcpserver add'
   5.171 -        #Cygwin.vboxExecute(cmd)
   5.172 -        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')
   5.173 -    
   5.174 -    #create new virtual machine instance based on template vm named SecurityDVM (\SecurityDVM\SecurityDVM.vmdk)
   5.175 -    def createVM(self, vm_name):
   5.176 -        hostonly_if = self.getHostOnlyIFs()
   5.177 -        Cygwin.vboxExecute('createvm --name ' + vm_name + ' --ostype Debian --register')
   5.178 -        Cygwin.vboxExecute('modifyvm ' + vm_name + ' --memory 512 --vram 10 --cpus 1 --usb on --usbehci on --nic1 hostonly --hostonlyadapter1 \"' + hostonly_if['Name'] + '\" --nic2 nat')
   5.179 -        Cygwin.vboxExecute('storagectl ' + vm_name + ' --name SATA --add sata --portcount 2')
   5.180 -        return
   5.181 -    
   5.182 -    # attach storage image to controller
   5.183 -    def storageAttach(self, vm_name):
   5.184 -        if self.isStorageAttached(vm_name):
   5.185 -            self.storageDetach(vm_name)
   5.186 -        Cygwin.vboxExecute('storageattach ' + vm_name + ' --storagectl SATA --port 0 --device 0 --type hdd --medium \"'+ self.machineFolder + '\SecurityDVM\SecurityDVM.vmdk\"')
   5.187 -        return
   5.188 -    
   5.189 -    # return true if storage is attached 
   5.190 -    def isStorageAttached(self, vm_name):
   5.191 -        info = self.getVMInfo(vm_name)
   5.192 -        return (info['SATA-0-0']!='none')
   5.193 -    
   5.194 -    # detach storage from controller
   5.195 -    def storageDetach(self, vm_name):
   5.196 -        if self.isStorageAttached(vm_name):
   5.197 -            Cygwin.vboxExecute('storageattach ' + vm_name + ' --storagectl SATA --port 0 --device 0 --type hdd --medium none')
   5.198 -        return
   5.199 -    
   5.200 -    def changeStorageType(self, filename, storage_type):
   5.201 -        Cygwin.vboxExecute('modifyhd \"' + filename + '\" --type ' + storage_type)
   5.202 -        return
   5.203 -    
   5.204 -    # list storage snaphots for VM
   5.205 -    def updateTemplate(self):
   5.206 -        self.cleanup()
   5.207 -        self.poweroffVM('SecurityDVM')
   5.208 -        self.waitShutdown('SecurityDVM')
   5.209 -        
   5.210 -        # check for updates
   5.211 -        self.genCertificateISO('SecurityDVM')
   5.212 -        self.attachCertificateISO('SecurityDVM')
   5.213 -        
   5.214 -        self.storageDetach('SecurityDVM')
   5.215 -        results = Cygwin.vboxExecute('list hdds')[1]
   5.216 -        results = results.replace('Parent UUID', 'Parent')
   5.217 -        items = list( "UUID:"+result for result in results.split('UUID:') if result != '')
   5.218 -        
   5.219 -        snaps = dict()   
   5.220 -        for item in items:
   5.221 -            props = dict()
   5.222 -            for line in item.splitlines():
   5.223 -                if line != "":         
   5.224 -                    k,v = line[:line.index(':')].strip(), line[line.index(':')+1:].strip()
   5.225 -                    props[k] = v;
   5.226 -            snaps[props['UUID']] = props
   5.227 -        
   5.228 -        
   5.229 -        template_storage = self.machineFolder + '\SecurityDVM\SecurityDVM.vmdk'
   5.230 -        
   5.231 -        # find template uuid
   5.232 -        template_uuid = ''
   5.233 -        for hdd in snaps.values():
   5.234 -            if hdd['Location'] == template_storage:
   5.235 -                template_uuid = hdd['UUID']
   5.236 -        logger.debug('found parent uuid ' + template_uuid)
   5.237 -        
   5.238 -        # remove snapshots 
   5.239 -        for hdd in snaps.values():
   5.240 -            if hdd['Parent'] == template_uuid:
   5.241 -                #template_uuid = hdd['UUID']
   5.242 -                logger.debug('removing snapshot ' + hdd['UUID'])
   5.243 -                results = Cygwin.vboxExecute('closemedium disk {' + hdd['UUID'] + '} --delete')[1]
   5.244 -                # parse result 0%...10%...20%...30%...40%...50%...60%...70%...80%...90%...100%
   5.245 -        
   5.246 -        self.changeStorageType(template_storage,'normal')
   5.247 -        self.storageAttach('SecurityDVM')
   5.248 -        self.startVM('SecurityDVM')
   5.249 -        self.waitStartup('SecurityDVM')
   5.250 -        Cygwin.sshExecute('"sudo apt-get -y update"', VMManager.getHostOnlyIP('SecurityDVM'), 'osecuser', Cygwin.cygPath(self.machineFolder) + '/' + 'SecurityDVM' + '/dvm_key'  )
   5.251 -        Cygwin.sshExecute('"sudo apt-get -y upgrade"', VMManager.getHostOnlyIP('SecurityDVM'), 'osecuser', Cygwin.cygPath(self.machineFolder) + '/' + 'SecurityDVM' + '/dvm_key'  )
   5.252 -        #self.stopVM('SecurityDVM')
   5.253 -        self.hibernateVM('SecurityDVM')
   5.254 -        self.waitShutdown('SecurityDVM')
   5.255 -        self.storageDetach('SecurityDVM')
   5.256 -        self.changeStorageType(template_storage,'immutable')
   5.257 -        self.storageAttach('SecurityDVM')
   5.258 -        self.rsdHandler = DeviceHandler(self)
   5.259 -        self.rsdHandler.start()
   5.260 -    
   5.261 -    #remove VM from the system. should be used on VMs returned by listSDVMs    
   5.262 -    def removeVM(self, vm_name):
   5.263 -        logger.info('Removing ' + vm_name)
   5.264 -        Cygwin.vboxExecute('unregistervm ' + vm_name + ' --delete')
   5.265 -        machineFolder = Cygwin.cygPath(self.machineFolder)
   5.266 -        Cygwin.bashExecute('"/usr/bin/rm -rf ' + machineFolder + '/' + vm_name + '"')
   5.267 -    
   5.268 -    # start VM
   5.269 -    def startVM(self, vm_name):
   5.270 -        logger.info('Starting ' +  vm_name)
   5.271 -        result = Cygwin.vboxExecute('startvm ' + vm_name + ' --type headless' )
   5.272 -        while not string.find(str(result), 'successfully started',):
   5.273 -            logger.error("Failed to start SDVM: " + vm_name + " retrying")
   5.274 -            time.sleep(1)
   5.275 -            result = Cygwin.vboxExecute('startvm ' + vm_name + ' --type headless')
   5.276 -        return result[0]
   5.277 -    
   5.278 -    # return wether VM is running or not
   5.279 -    def isVMRunning(self, vm_name):
   5.280 -        return vm_name in self.listRunningVMS()    
   5.281 -    
   5.282 -    # stop VM
   5.283 -    def stopVM(self, vm_name):
   5.284 -        logger.info('Sending shutdown signal to ' + vm_name)
   5.285 -        Cygwin.sshExecute( '"sudo shutdown -h now"', VMManager.getHostOnlyIP(vm_name), 'osecuser', Cygwin.cygPath(self.machineFolder) + '/' + vm_name + '/dvm_key' )
   5.286 -    
   5.287 -    # stop VM
   5.288 -    def hibernateVM(self, vm_name):
   5.289 -        logger.info('Sending shutdown signal to ' + vm_name)
   5.290 -        Cygwin.sshExecute( '"sudo hibernate-disk&"', VMManager.getHostOnlyIP(vm_name), 'osecuser', Cygwin.cygPath(self.machineFolder) + '/' + vm_name + '/dvm_key', wait_return=False )
   5.291 -            
   5.292 -    # poweroff VM
   5.293 -    def poweroffVM(self, vm_name):
   5.294 -        if not self.isVMRunning(vm_name):
   5.295 -            return
   5.296 -        logger.info('Powering off ' + vm_name)
   5.297 -        return Cygwin.vboxExecute('controlvm ' + vm_name + ' poweroff')
   5.298 -    
   5.299 -    #list the hostonly IFs exposed by the VBox host
   5.300 -    @staticmethod    
   5.301 -    def getHostOnlyIFs():
   5.302 -        result = Cygwin.vboxExecute('list hostonlyifs')[1]
   5.303 -        if result=='':
   5.304 -            return None
   5.305 -        props = dict((k.strip(),v.strip().strip('"')) for k,v in (line.split(':', 1) for line in result.strip().splitlines()))
   5.306 -        return props
   5.307 -    
   5.308 -    # return the hostOnly IP for a running guest or the host
   5.309 -    @staticmethod    
   5.310 -    def getHostOnlyIP(vm_name):
   5.311 -        if vm_name == None:
   5.312 -            logger.info('Gettting hostOnly IP address for Host')
   5.313 -            return VMManager.getHostOnlyIFs()['IPAddress']
   5.314 -        else:
   5.315 -            logger.info('Gettting hostOnly IP address ' + vm_name)
   5.316 -            result = Cygwin.vboxExecute('guestproperty get ' + vm_name + ' /VirtualBox/GuestInfo/Net/0/V4/IP')
   5.317 -            if result=='':
   5.318 -                return None
   5.319 -            result = result[1]
   5.320 -            if result.startswith('No value set!'):
   5.321 -                return None
   5.322 -            return result[result.index(':')+1:].strip()
   5.323 -            
   5.324 -    # attach removable storage device to VM by provision of filter
   5.325 -    def attachRSD(self, vm_name, rsd_filter):
   5.326 -        return Cygwin.vboxExecute('usbfilter add 0 --target ' + vm_name + ' --name OpenSecurityRSD --vendorid ' + rsd_filter.vendorid + ' --productid ' + rsd_filter.productid + ' --revision ' + rsd_filter.revision)
   5.327 -    
   5.328 -    # detach removable storage from VM by 
   5.329 -    def detachRSD(self, vm_name):
   5.330 -        return Cygwin.vboxExecute('usbfilter remove 0 --target ' + vm_name )
   5.331 -        
   5.332 -    
   5.333 -    # return the description set for an existing VM
   5.334 -    def getVMInfo(self, vm_name):
   5.335 -        results = Cygwin.vboxExecute('showvminfo ' + vm_name + ' --machinereadable')[1]
   5.336 -        props = dict((k.strip().strip('"'),v.strip().strip('"')) for k,v in (line.split('=', 1) for line in results.splitlines()))
   5.337 -        #logger.debug(props)
   5.338 -        return props
   5.339 -    
   5.340 -    # return the configured USB filter for an existing VM 
   5.341 -    def getUSBFilter(self, vm_name):
   5.342 -        props = self.getVMInfo(vm_name)
   5.343 -        keys = set(['USBFilterVendorId1', 'USBFilterProductId1', 'USBFilterRevision1'])
   5.344 -        keyset = set(props.keys())
   5.345 -        usb_filter = None
   5.346 -        if keyset.issuperset(keys):
   5.347 -            usb_filter = USBFilter(props['USBFilterVendorId1'], props['USBFilterProductId1'], props['USBFilterRevision1'])
   5.348 -        return usb_filter
   5.349 -    
   5.350 -    #generates ISO containing authorized_keys for use with guest VM
   5.351 -    def genCertificateISO(self, vm_name):
   5.352 -        machineFolder = Cygwin.cygPath(self.machineFolder)
   5.353 -        # remove .ssh folder if exists
   5.354 -        cmd = '\"/usr/bin/rm -rf \\\"' + machineFolder + '/' + vm_name + '/.ssh\\\"\"'
   5.355 -        Cygwin.bashExecute(cmd)
   5.356 -        # remove .ssh folder if exists
   5.357 -        Cygwin.bashExecute('\"/usr/bin/rm -rf \\\"' + machineFolder + '/' + vm_name + '/dvm_key\\\"\"')
   5.358 -        # create .ssh folder in vm_name
   5.359 -        Cygwin.bashExecute('\"/usr/bin/mkdir -p \\\"' + machineFolder + '/' + vm_name + '/.ssh\\\"\"')
   5.360 -        # generate dvm_key pair in vm_name / .ssh     
   5.361 -        Cygwin.bashExecute('\"/usr/bin/ssh-keygen -q -t rsa -N \\"\\" -C \\\"' + vm_name + '\\\" -f \\\"' + machineFolder + '/' + vm_name + '/.ssh/dvm_key\\\"\"')
   5.362 -        # move out private key
   5.363 -        Cygwin.bashExecute('\"/usr/bin/mv \\\"' + machineFolder + '/' + vm_name + '/.ssh/dvm_key\\\" \\\"' + machineFolder + '/' + vm_name + '\\\"')
   5.364 -        # set permissions for private key
   5.365 -        Cygwin.bashExecute('\"/usr/bin/chmod 500 \\\"' + machineFolder + '/' + vm_name + '/dvm_key\\\"\"')
   5.366 -        # rename public key to authorized_keys
   5.367 -        Cygwin.bashExecute('\"/usr/bin/mv \\\"' + machineFolder + '/' + vm_name + '/.ssh/dvm_key.pub\\\" \\\"' + machineFolder + '/' + vm_name + '/.ssh/authorized_keys\\\"')
   5.368 -        # set permissions for authorized_keys
   5.369 -        Cygwin.bashExecute('\"/usr/bin/chmod 500 \\\"' + machineFolder + '/' + vm_name + '/.ssh/authorized_keys\\\"\"')
   5.370 -        # generate iso image with .ssh/authorized keys
   5.371 -        Cygwin.bashExecute('\"/usr/bin/genisoimage -J -R -o \\\"' + machineFolder + '/' + vm_name + '/'+ vm_name + '.iso\\\" \\\"' + machineFolder + '/' + vm_name + '/.ssh\\\"\"')
   5.372 -    
   5.373 -    # attaches generated ssh public cert to guest vm
   5.374 -    def attachCertificateISO(self, vm_name):
   5.375 -        result = Cygwin.vboxExecute('storageattach ' + vm_name + ' --storagectl SATA --port 1 --device 0 --type dvddrive --mtype readonly --medium \"' + self.machineFolder + '\\' + vm_name + '\\'+ vm_name + '.iso\"')
   5.376 -        return result
   5.377 -    
   5.378 -    # wait for machine to come up
   5.379 -    def waitStartup(self, vm_name, timeout_ms = 30000):
   5.380 -        result = Cygwin.vboxExecute('guestproperty wait ' + vm_name + ' SDVMStarted --timeout ' + str(timeout_ms) + ' --fail-on-timeout')
   5.381 -        return VMManager.getHostOnlyIP(vm_name)
   5.382 -    
   5.383 -    # wait for machine to shutdown
   5.384 -    def waitShutdown(self, vm_name):
   5.385 -        while vm_name in self.listRunningVMS():
   5.386 -            time.sleep(1)
   5.387 -        return
   5.388 -        
   5.389 -    # handles browsing request    
   5.390 -    def handleBrowsingRequest(self):
   5.391 -        if VMManager.handleDeviceChangeLock.acquire(True):
   5.392 -            new_sdvm = self.generateSDVMName()
   5.393 -            self.createVM(new_sdvm)
   5.394 -            self.storageAttach(new_sdvm)
   5.395 -            self.genCertificateISO(new_sdvm)
   5.396 -            self.attachCertificateISO(new_sdvm)
   5.397 -            self.startVM(new_sdvm)
   5.398 -            new_ip = self.waitStartup(new_sdvm)
   5.399 -            if new_ip != None:
   5.400 -                self.mapNetworkDrive('g:', '\\\\' + new_ip + '\\Download', None, None)
   5.401 -            #TODO: cleanup notifications somwhere else (eg. machine shutdown)
   5.402 -            VMManager.handleDeviceChangeLock.release()
   5.403 -        return new_sdvm
   5.404 -    
   5.405 -    #Small function to check the availability of network resource.
   5.406 -    #def isAvailable(self, path):
   5.407 -        #return os.path.exists(path)
   5.408 -        #result = Cygwin.cmdExecute('IF EXIST "' + path + '" echo YES')
   5.409 -        #return string.find(result[1], 'YES',)
   5.410 -    
   5.411 -    #Small function to check if the mention location is a directory
   5.412 -    def isDirectory(self, path):
   5.413 -        result = Cygwin.cmdExecute('dir ' + path + ' | FIND ".."')
   5.414 -        return string.find(result[1], 'DIR',)
   5.415 -
   5.416 -    def mapNetworkDrive(self, drive, networkPath, user, password):
   5.417 -        self.unmapNetworkDrive(drive)
   5.418 -        #Check for drive availability
   5.419 -        if os.path.exists(drive):
   5.420 -            logger.error("Drive letter is already in use: " + drive)
   5.421 -            return -1
   5.422 -        #Check for network resource availability
   5.423 -        while not os.path.exists(networkPath):
   5.424 -            time.sleep(1)
   5.425 -            logger.info("Path not accessible: " + networkPath + " retrying")
   5.426 -            #return -1
   5.427 -    
   5.428 -        command = 'USE ' + drive + ' ' + networkPath + ' /PERSISTENT:NO'
   5.429 -        if user != None:
   5.430 -            command += ' ' + password + ' /User' + user
   5.431 -    
   5.432 -        #TODO: Execute 'NET USE' command with authentication
   5.433 -        result = Cygwin.execute('C:\\Windows\\system32\\net.exe', command)
   5.434 -        if string.find(result[1], 'successfully',) == -1:
   5.435 -            logger.error("Failed: NET " + command)
   5.436 -            return -1
   5.437 -        return 1
   5.438 -    
   5.439 -    def unmapNetworkDrive(self, drive):
   5.440 -        drives = self.getNetworkDrives()
   5.441 -        if drive not in drives.keys():
   5.442 -            return 1 
   5.443 -        result = Cygwin.execute('C:\\Windows\\system32\\net.exe', 'USE ' + drive + ' /DELETE /YES')
   5.444 -        if string.find(str(result[1]), 'successfully',) == -1:
   5.445 -            logger.error(result[2])
   5.446 -            return -1
   5.447 -        return 1
   5.448 -    
   5.449 -    def getNetworkDrives(self):
   5.450 -        ip = VMManager.getHostOnlyIP(None)
   5.451 -        ip = ip[:ip.rindex('.')]
   5.452 -        drives = dict()    
   5.453 -        result = Cygwin.execute('C:\\Windows\\system32\\net.exe', 'USE')
   5.454 -        for line in result[1].splitlines():
   5.455 -            if ip in line:
   5.456 -                parts = line.split()
   5.457 -                drives[parts[1]] = parts[2]
   5.458 -        return drives
   5.459 -            
   5.460 -    def genNetworkDrive(self):
   5.461 -        network_drives = self.getNetworkDrives()
   5.462 -        logical_drives = self.getLogicalDrives()
   5.463 -        drives = list(map(chr, range(68, 91)))  
   5.464 -        for drive in drives:
   5.465 -            if drive+':' not in network_drives and drive not in logical_drives:
   5.466 -                return drive+':'
   5.467 -
   5.468 -    def getNetworkDrive(self, vm_name):
   5.469 -        ip = self.getHostOnlyIP(vm_name)
   5.470 -        result = Cygwin.execute('C:\\Windows\\system32\\net.exe', 'USE')
   5.471 -        for line in result[1].splitlines():
   5.472 -            if ip in line:
   5.473 -                parts = line.split()
   5.474 -                return parts[0]
   5.475 -    
   5.476 -    def getLogicalDrives(self):
   5.477 -        drive_bitmask = ctypes.cdll.kernel32.GetLogicalDrives()
   5.478 -        return list(itertools.compress(string.ascii_uppercase,  map(lambda x:ord(x) - ord('0'), bin(drive_bitmask)[:1:-1])))
   5.479 -                    
   5.480 -        #vms = self.listSDVM()
   5.481 -        #for vm in vms:
   5.482 -        #    ip = self.getHostOnlyIP(vm)
   5.483 -        
   5.484 -class DeviceHandler(threading.Thread): 
   5.485 -    vmm = None
   5.486 -    #handleDeviceChangeLock = threading.Lock()
   5.487 -    attachedRSDs = None  
   5.488 -    connectedRSDs = None
   5.489 -    running = True
   5.490 -    def __init__(self, vmmanger): 
   5.491 -        threading.Thread.__init__(self)
   5.492 -        self.vmm = vmmanger
   5.493 - 
   5.494 -    def stop(self):
   5.495 -        self.running = False
   5.496 -        
   5.497 -    def run(self):
   5.498 -        self.connectedRSDs = dict()#self.vmm.getConnectedRSDS()
   5.499 -        self.attachedRSDs = self.vmm.getAttachedRSDs()
   5.500 -        while self.running:
   5.501 -            tmp_rsds = self.vmm.getConnectedRSDS()
   5.502 -            if tmp_rsds.keys() == self.connectedRSDs.keys():
   5.503 -                logger.debug("Nothing's changed. sleep(3)")
   5.504 -                time.sleep(3)
   5.505 -                continue
   5.506 -            
   5.507 -            logger.info("Something's changed")          
   5.508 -            
   5.509 -            self.connectedRSDs = tmp_rsds
   5.510 -            self.attachedRSDs = self.vmm.getAttachedRSDs()
   5.511 -            
   5.512 -            
   5.513 -            for vm_name in self.attachedRSDs.keys():
   5.514 -                if self.attachedRSDs[vm_name] not in self.connectedRSDs.values():
   5.515 -                    drive = self.vmm.getNetworkDrive(vm_name)
   5.516 -                    self.vmm.unmapNetworkDrive(drive)
   5.517 -                    #self.stopVM(vm_name)
   5.518 -                    self.vmm.detachRSD(vm_name)
   5.519 -                    self.vmm.poweroffVM(vm_name)
   5.520 -                    self.vmm.removeVM(vm_name)
   5.521 -            #create new vm for attached device if any
   5.522 -            self.attachedRSDs = self.vmm.getAttachedRSDs()
   5.523 -            self.connectedRSDs = self.vmm.getConnectedRSDS()
   5.524 -            
   5.525 -            new_ip = None
   5.526 -            for connected_device in self.connectedRSDs.values():
   5.527 -                if (self.attachedRSDs and False) or (connected_device not in self.attachedRSDs.values()):
   5.528 -                    new_sdvm = self.vmm.generateSDVMName()
   5.529 -                    self.vmm.createVM(new_sdvm)
   5.530 -                    self.vmm.storageAttach(new_sdvm)
   5.531 -                    self.vmm.attachRSD(new_sdvm, connected_device)
   5.532 -                    self.vmm.startVM(new_sdvm)
   5.533 -                    new_ip = self.vmm.waitStartup(new_sdvm)
   5.534 -                    drive = self.vmm.genNetworkDrive()
   5.535 -                    if new_ip != None:
   5.536 -                        self.vmm.mapNetworkDrive(drive, '\\\\' + new_ip + '\\USB', None, None)
   5.537 -                    #TODO: cleanup notifications somwhere else (eg. machine shutdown)
   5.538 -            #self.handleDeviceChangeLock.release()
   5.539 -                
   5.540 -
   5.541 -if __name__ == '__main__':
   5.542 -    #man = VMManager.getInstance()
   5.543 -    #man.listVM()
   5.544 -    #print man.getConnectedRSDs()
   5.545 -    #print man.getNetworkDrives()
   5.546 -    #man.genNetworkDrive()
   5.547 -    drive_bitmask = ctypes.cdll.kernel32.GetLogicalDrives()
   5.548 -    print list(itertools.compress(string.ascii_uppercase,  map(lambda x:ord(x) - ord('0'), bin(drive_bitmask)[:1:-1])))
   5.549 -    #print list(map(chr, range(68, 91))) 
   5.550 -    
   5.551 -    #time.sleep(-1)
   5.552 -    #man.listVM()
   5.553 -    #man.listVM()
   5.554 -    #man.listVM()
   5.555 -    #man.listVM()
   5.556 -    #man.genCertificateISO('SecurityDVM0')
   5.557 -    #man.guestExecute('SecurityDVM0', '/bin/ls -la')
   5.558 -    #logger = setupLogger('VMManager')
   5.559 -    #c = Cygwin()
   5.560 -    
   5.561 -    #man.sshExecute('/bin/ls -la', 'SecurityDVM0')
   5.562 -    #man.sshExecuteX11('/usr/bin/iceweasel', 'SecurityDVM0')
   5.563 -    #man.removeVM('SecurityDVM0')
   5.564 -    #man.netUse('192.168.56.134', 'USB\\')
   5.565 -    #ip = '192.168.56.139'
   5.566 -    
   5.567 -    #man.cygwin_path = 'c:\\cygwin64\\bin\\'
   5.568 -    #man.handleDeviceChange()
   5.569 -    #print man.listSDVM()
   5.570 -    #man.configureHostNetworking()
   5.571 -    #new_vm = man.generateSDVMName()
   5.572 -    #man.createVM(new_vm)
   5.573 -    
   5.574 -    #print Cygwin.cmd()
   5.575 -    #man.isAvailable('c:')
   5.576 -    #ip = man.getHostOnlyIP('SecurityDVM0')
   5.577 -    #man.mapNetworkDrive('h:', '\\\\' + ip + '\Download', None, None)
   5.578 -    
   5.579 -    #man.genCertificateISO(new_vm)
   5.580 -    #man.attachCertificateISO(new_vm)
   5.581 -    
   5.582 -    #man.attachCertificateISO(vm_name)
   5.583 -    #man.guestExecute(vm_name, "ls")
   5.584 -    #man.sshGuestX11Execute('SecurityDVM1', '/usr/bin/iceweasel')
   5.585 -    #time.sleep(60)
   5.586 -    #print man.cygwinPath("C:\Users\BarthaM\VirtualBox VMs\SecurityDVM\.ssh\*")
   5.587 -    #man.genCertificateISO('SecurityDVM')
   5.588 -    #man.attachCertificateISO('SecurityDVM')
   5.589 -    #man.isStorageAttached('SecurityDVM')
   5.590 -    #man.guestExecute('SecurityDVM', 'sudo apt-get -y update')
   5.591 -    #man.guestExecute('SecurityDVM', 'sudo apt-get -y upgrade' )
   5.592 -    
   5.593 -    #man.stopVM('SecurityDVM')
   5.594 -    #man.storageDetach('SecurityDVM')
   5.595 -    #man.changeStorageType('C:\Users\BarthaM\VirtualBox VMs\SecurityDVM\SecurityDVM.vmdk','immutable')
   5.596 -    #man.storageAttach('SecurityDVM')
   5.597 -    
   5.598 -    
   5.599 -    #cmd = "c:\\cygwin64\\bin\\bash.exe --login -c \"/bin/ls\""
   5.600 -    #man.execute(cmd)
   5.601 -    
   5.602 +'''
   5.603 +Created on Nov 19, 2013
   5.604 +
   5.605 +@author: BarthaM
   5.606 +'''
   5.607 +import os
   5.608 +import os.path
   5.609 +from subprocess import Popen, PIPE, call, STARTUPINFO, _subprocess
   5.610 +import sys
   5.611 +import re
   5.612 +
   5.613 +from cygwin import Cygwin
   5.614 +from environment import Environment
   5.615 +import threading
   5.616 +import time
   5.617 +import string
   5.618 +
   5.619 +import shutil
   5.620 +import stat
   5.621 +import tempfile
   5.622 +from opensecurity_util import logger, setupLogger, OpenSecurityException
   5.623 +import ctypes
   5.624 +import itertools
   5.625 +import _winreg
   5.626 +DEBUG = True
   5.627 +
   5.628 +class VMManagerException(Exception):
   5.629 +    def __init__(self, value):
   5.630 +        self.value = value
   5.631 +    def __str__(self):
   5.632 +        return repr(self.value)
   5.633 +
   5.634 +class USBFilter:
   5.635 +    vendorid = ""
   5.636 +    productid = ""
   5.637 +    revision = ""
   5.638 +    
   5.639 +    def __init__(self, vendorid, productid, revision):
   5.640 +        self.vendorid = vendorid.lower()
   5.641 +        self.productid = productid.lower()
   5.642 +        self.revision = revision.lower()
   5.643 +        return
   5.644 +    
   5.645 +    def __eq__(self, other):
   5.646 +        return self.vendorid == other.vendorid and self.productid == other.productid and self.revision == other.revision
   5.647 +    
   5.648 +    def __hash__(self):
   5.649 +        return hash(self.vendorid) ^ hash(self.productid) ^ hash(self.revision)
   5.650 +    
   5.651 +    def __repr__(self):
   5.652 +        return "VendorId = \'" + str(self.vendorid) + "\' ProductId = \'" + str(self.productid) + "\' Revision = \'" + str(self.revision) + "\'"
   5.653 +    
   5.654 +    #def __getitem__(self, item):
   5.655 +    #    return self.coords[item]
   5.656 + 
   5.657 +class VMManager(object):
   5.658 +    vmRootName = "SecurityDVM"
   5.659 +    systemProperties = None
   5.660 +    _instance = None
   5.661 +    machineFolder = ''
   5.662 +    rsdHandler = None
   5.663 +    
   5.664 +    def __init__(self):
   5.665 +        self.systemProperties = self.getSystemProperties()
   5.666 +        self.machineFolder = self.systemProperties["Default machine folder"]
   5.667 +        self.cleanup()
   5.668 +        self.rsdHandler = DeviceHandler(self)
   5.669 +        self.rsdHandler.start()
   5.670 +        return
   5.671 +    
   5.672 +    @staticmethod
   5.673 +    def getInstance():
   5.674 +        if VMManager._instance == None:
   5.675 +            VMManager._instance = VMManager()
   5.676 +        return VMManager._instance
   5.677 +    
   5.678 +    def cleanup(self):
   5.679 +        if self.rsdHandler != None:
   5.680 +            self.rsdHandler.stop()
   5.681 +            self.rsdHandler.join()
   5.682 +        drives = self.getNetworkDrives()
   5.683 +        for drive in drives.keys():
   5.684 +            self.unmapNetworkDrive(drive)
   5.685 +        for vm in self.listSDVM():
   5.686 +            self.poweroffVM(vm)
   5.687 +            self.removeVM(vm)
   5.688 +        
   5.689 +    # return hosty system properties
   5.690 +    def getSystemProperties(self):
   5.691 +        result = checkResult(Cygwin.vboxExecute('list systemproperties'))
   5.692 +        if result[1]=='':
   5.693 +            return None
   5.694 +        props = dict((k.strip(),v.strip().strip('"')) for k,v in (line.split(':', 1) for line in result[1].strip().splitlines()))
   5.695 +        return props
   5.696 +    
   5.697 +    # return the folder containing the guest VMs     
   5.698 +    def getMachineFolder(self):
   5.699 +        return self.machineFolder
   5.700 +
   5.701 +    # list all existing VMs registered with VBox
   5.702 +    def listVM(self):
   5.703 +        result = checkResult(Cygwin.vboxExecute('list vms'))[1]
   5.704 +        vms = list(k.strip().strip('"') for k,_ in (line.split(' ') for line in result.splitlines()))
   5.705 +        return vms
   5.706 +    
   5.707 +    # list running VMs
   5.708 +    def listRunningVMS(self):
   5.709 +        result = checkResult(Cygwin.vboxExecute('list runningvms'))[1]
   5.710 +        vms = list(k.strip().strip('"') for k,_ in (line.split(' ') for line in result.splitlines()))
   5.711 +        return vms
   5.712 +    
   5.713 +    # list existing SDVMs
   5.714 +    def listSDVM(self):
   5.715 +        vms = self.listVM()
   5.716 +        svdms = []
   5.717 +        for vm in vms:
   5.718 +            if vm.startswith(self.vmRootName) and vm != self.vmRootName:
   5.719 +                svdms.append(vm)
   5.720 +        return svdms
   5.721 +    
   5.722 +    # generate valid (not already existing SDVM name). necessary for creating a new VM
   5.723 +    def generateSDVMName(self):
   5.724 +        vms = self.listVM()
   5.725 +        for i in range(0,999):
   5.726 +            if(not self.vmRootName+str(i) in vms):
   5.727 +                return self.vmRootName+str(i)
   5.728 +        return ''
   5.729 +    
   5.730 +    # check if the device is mass storage type
   5.731 +    @staticmethod
   5.732 +    def isMassStorageDevice(device):
   5.733 +        keyname = 'SYSTEM\CurrentControlSet\Enum\USB' + '\VID_' + device.vendorid+'&'+'PID_'+ device.productid
   5.734 +        key = _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE, keyname)
   5.735 +        #subkeys = _winreg.QueryInfoKey(key)[0]
   5.736 +        #for i in range(0, subkeys):
   5.737 +        #    print _winreg.EnumKey(key, i)     
   5.738 +        devinfokeyname = _winreg.EnumKey(key, 0)
   5.739 +        _winreg.CloseKey(key)
   5.740 +
   5.741 +        devinfokey = _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE, keyname+'\\'+devinfokeyname)
   5.742 +        value = _winreg.QueryValueEx(devinfokey, 'SERVICE')[0]
   5.743 +        _winreg.CloseKey(devinfokey)
   5.744 +        
   5.745 +        return 'USBSTOR' in value
   5.746 +    
   5.747 +    # return the RSDs connected to the host
   5.748 +    @staticmethod
   5.749 +    def getConnectedRSDS():
   5.750 +        results = checkResult(Cygwin.vboxExecute('list usbhost'))[1]
   5.751 +        results = results.split('Host USB Devices:')[1].strip()
   5.752 +        
   5.753 +        items = list( "UUID:"+result for result in results.split('UUID:') if result != '')
   5.754 +        rsds = dict()   
   5.755 +        for item in items:
   5.756 +            props = dict()
   5.757 +            for line in item.splitlines():
   5.758 +                if line != "":         
   5.759 +                    k,v = line[:line.index(':')].strip(), line[line.index(':')+1:].strip()
   5.760 +                    props[k] = v
   5.761 +            
   5.762 +            #if 'Product' in props.keys() and props['Product'] == 'Mass Storage':
   5.763 +            
   5.764 +            usb_filter = USBFilter( re.search(r"\((?P<vid>[0-9A-Fa-f]+)\)", props['VendorId']).groupdict()['vid'], 
   5.765 +                                    re.search(r"\((?P<pid>[0-9A-Fa-f]+)\)", props['ProductId']).groupdict()['pid'],
   5.766 +                                    re.search(r"\((?P<rev>[0-9A-Fa-f]+)\)", props['Revision']).groupdict()['rev'] )
   5.767 +            if VMManager.isMassStorageDevice(usb_filter):
   5.768 +                rsds[props['UUID']] = usb_filter;
   5.769 +                logger.debug(usb_filter)
   5.770 +        return rsds
   5.771 +    
   5.772 +    # return the RSDs attached to all existing SDVMs
   5.773 +    def getAttachedRSDs(self):
   5.774 +        vms = self.listSDVM()
   5.775 +        attached_devices = dict()
   5.776 +        for vm in vms:
   5.777 +            rsd_filter = self.getUSBFilter(vm)
   5.778 +            if rsd_filter != None:
   5.779 +                attached_devices[vm] = rsd_filter
   5.780 +        return attached_devices
   5.781 +    
   5.782 +    # configures hostonly networking and DHCP server. requires admin rights
   5.783 +    def configureHostNetworking(self):
   5.784 +        #cmd = 'vboxmanage list hostonlyifs'
   5.785 +        #Cygwin.vboxExecute(cmd)
   5.786 +        #cmd = 'vboxmanage hostonlyif remove \"VirtualBox Host-Only Ethernet Adapter\"'
   5.787 +        #Cygwin.vboxExecute(cmd)
   5.788 +        #cmd = 'vboxmanage hostonlyif create'
   5.789 +        #Cygwin.vboxExecute(cmd)
   5.790 +        checkResult(Cygwin.vboxExecute('hostonlyif ipconfig \"VirtualBox Host-Only Ethernet Adapter\" --ip 192.168.56.1 --netmask 255.255.255.0'))
   5.791 +        #cmd = 'vboxmanage dhcpserver add'
   5.792 +        #Cygwin.vboxExecute(cmd)
   5.793 +        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'))
   5.794 +    
   5.795 +    #create new virtual machine instance based on template vm named SecurityDVM (\SecurityDVM\SecurityDVM.vmdk)
   5.796 +    def createVM(self, vm_name):
   5.797 +        hostonly_if = self.getHostOnlyIFs()
   5.798 +        checkResult(Cygwin.vboxExecute('createvm --name ' + vm_name + ' --ostype Debian --register'))
   5.799 +        checkResult(Cygwin.vboxExecute('modifyvm ' + vm_name + ' --memory 512 --vram 10 --cpus 1 --usb on --usbehci on --nic1 hostonly --hostonlyadapter1 \"' + hostonly_if['Name'] + '\" --nic2 nat'))
   5.800 +        checkResult(Cygwin.vboxExecute('storagectl ' + vm_name + ' --name SATA --add sata --portcount 2'))
   5.801 +        return
   5.802 +    
   5.803 +    # attach storage image to controller
   5.804 +    def storageAttach(self, vm_name):
   5.805 +        if self.isStorageAttached(vm_name):
   5.806 +            self.storageDetach(vm_name)
   5.807 +        checkResult(Cygwin.vboxExecute('storageattach ' + vm_name + ' --storagectl SATA --port 0 --device 0 --type hdd --medium \"'+ self.machineFolder + '\SecurityDVM\SecurityDVM.vmdk\"'))
   5.808 +    
   5.809 +    # return true if storage is attached 
   5.810 +    def isStorageAttached(self, vm_name):
   5.811 +        info = self.getVMInfo(vm_name)
   5.812 +        return (info['SATA-0-0']!='none')
   5.813 +    
   5.814 +    # detach storage from controller
   5.815 +    def storageDetach(self, vm_name):
   5.816 +        if self.isStorageAttached(vm_name):
   5.817 +            checkResult(Cygwin.vboxExecute('storageattach ' + vm_name + ' --storagectl SATA --port 0 --device 0 --type hdd --medium none'))
   5.818 +    
   5.819 +    def changeStorageType(self, filename, storage_type):
   5.820 +        checkResult(Cygwin.vboxExecute('modifyhd \"' + filename + '\" --type ' + storage_type))
   5.821 +    
   5.822 +    # list storage snaphots for VM
   5.823 +    def updateTemplate(self):
   5.824 +        self.cleanup()
   5.825 +        self.poweroffVM('SecurityDVM')
   5.826 +        self.waitShutdown('SecurityDVM')
   5.827 +        
   5.828 +        # check for updates
   5.829 +        self.genCertificateISO('SecurityDVM')
   5.830 +        self.attachCertificateISO('SecurityDVM')
   5.831 +        
   5.832 +        self.storageDetach('SecurityDVM')
   5.833 +        results = checkResult(Cygwin.vboxExecute('list hdds'))[1]
   5.834 +        results = results.replace('Parent UUID', 'Parent')
   5.835 +        items = list( "UUID:"+result for result in results.split('UUID:') if result != '')
   5.836 +        
   5.837 +        snaps = dict()   
   5.838 +        for item in items:
   5.839 +            props = dict()
   5.840 +            for line in item.splitlines():
   5.841 +                if line != "":         
   5.842 +                    k,v = line[:line.index(':')].strip(), line[line.index(':')+1:].strip()
   5.843 +                    props[k] = v;
   5.844 +            snaps[props['UUID']] = props
   5.845 +        
   5.846 +        
   5.847 +        template_storage = self.machineFolder + '\SecurityDVM\SecurityDVM.vmdk'
   5.848 +        
   5.849 +        # find template uuid
   5.850 +        template_uuid = ''
   5.851 +        for hdd in snaps.values():
   5.852 +            if hdd['Location'] == template_storage:
   5.853 +                template_uuid = hdd['UUID']
   5.854 +        logger.debug('found parent uuid ' + template_uuid)
   5.855 +        
   5.856 +        # remove snapshots 
   5.857 +        for hdd in snaps.values():
   5.858 +            if hdd['Parent'] == template_uuid:
   5.859 +                #template_uuid = hdd['UUID']
   5.860 +                logger.debug('removing snapshot ' + hdd['UUID'])
   5.861 +                checkResult(Cygwin.vboxExecute('closemedium disk {' + hdd['UUID'] + '} --delete'))#[1]
   5.862 +                # parse result 0%...10%...20%...30%...40%...50%...60%...70%...80%...90%...100%
   5.863 +        
   5.864 +        self.changeStorageType(template_storage,'normal')
   5.865 +        self.storageAttach('SecurityDVM')
   5.866 +        self.startVM('SecurityDVM')
   5.867 +        self.waitStartup('SecurityDVM')
   5.868 +        checkResult(Cygwin.sshExecute('"sudo apt-get -y update"', VMManager.getHostOnlyIP('SecurityDVM'), 'osecuser', Cygwin.cygPath(self.machineFolder) + '/' + 'SecurityDVM' + '/dvm_key'))
   5.869 +        checkResult(Cygwin.sshExecute('"sudo apt-get -y upgrade"', VMManager.getHostOnlyIP('SecurityDVM'), 'osecuser', Cygwin.cygPath(self.machineFolder) + '/' + 'SecurityDVM' + '/dvm_key'))
   5.870 +        #self.stopVM('SecurityDVM')
   5.871 +        self.hibernateVM('SecurityDVM')
   5.872 +        self.waitShutdown('SecurityDVM')
   5.873 +        self.storageDetach('SecurityDVM')
   5.874 +        self.changeStorageType(template_storage,'immutable')
   5.875 +        self.storageAttach('SecurityDVM')
   5.876 +        self.rsdHandler = DeviceHandler(self)
   5.877 +        self.rsdHandler.start()
   5.878 +    
   5.879 +    #remove VM from the system. should be used on VMs returned by listSDVMs    
   5.880 +    def removeVM(self, vm_name):
   5.881 +        logger.info('Removing ' + vm_name)
   5.882 +        checkResult(Cygwin.vboxExecute('unregistervm ' + vm_name + ' --delete'))
   5.883 +        machineFolder = Cygwin.cygPath(self.machineFolder)
   5.884 +        checkResult(Cygwin.bashExecute('"/usr/bin/rm -rf ' + machineFolder + '/' + vm_name + '"'))
   5.885 +    
   5.886 +    # start VM
   5.887 +    def startVM(self, vm_name):
   5.888 +        logger.info('Starting ' +  vm_name)
   5.889 +        result = checkResult(Cygwin.vboxExecute('startvm ' + vm_name + ' --type headless' ))
   5.890 +        while 'successfully started' not in result[1]:
   5.891 +            logger.error("Failed to start SDVM: " + vm_name + " retrying")
   5.892 +            time.sleep(1)
   5.893 +            result = checkResult(Cygwin.vboxExecute('startvm ' + vm_name + ' --type headless'))
   5.894 +        return result[0]
   5.895 +    
   5.896 +    # return wether VM is running or not
   5.897 +    def isVMRunning(self, vm_name):
   5.898 +        return vm_name in self.listRunningVMS()    
   5.899 +    
   5.900 +    # stop VM
   5.901 +    def stopVM(self, vm_name):
   5.902 +        logger.info('Sending shutdown signal to ' + vm_name)
   5.903 +        checkResult(Cygwin.sshExecute( '"sudo shutdown -h now"', VMManager.getHostOnlyIP(vm_name), 'osecuser', Cygwin.cygPath(self.machineFolder) + '/' + vm_name + '/dvm_key' ))
   5.904 +    
   5.905 +    # stop VM
   5.906 +    def hibernateVM(self, vm_name):
   5.907 +        logger.info('Sending shutdown signal to ' + vm_name)
   5.908 +        checkResult(Cygwin.sshExecute( '"sudo hibernate-disk&"', VMManager.getHostOnlyIP(vm_name), 'osecuser', Cygwin.cygPath(self.machineFolder) + '/' + vm_name + '/dvm_key', wait_return=False))
   5.909 +            
   5.910 +    # poweroff VM
   5.911 +    def poweroffVM(self, vm_name):
   5.912 +        if not self.isVMRunning(vm_name):
   5.913 +            return
   5.914 +        logger.info('Powering off ' + vm_name)
   5.915 +        return checkResult(Cygwin.vboxExecute('controlvm ' + vm_name + ' poweroff'))
   5.916 +    
   5.917 +    #list the hostonly IFs exposed by the VBox host
   5.918 +    @staticmethod    
   5.919 +    def getHostOnlyIFs():
   5.920 +        result = Cygwin.vboxExecute('list hostonlyifs')[1]
   5.921 +        if result=='':
   5.922 +            return None
   5.923 +        props = dict((k.strip(),v.strip().strip('"')) for k,v in (line.split(':', 1) for line in result.strip().splitlines()))
   5.924 +        return props
   5.925 +    
   5.926 +    # return the hostOnly IP for a running guest or the host
   5.927 +    @staticmethod    
   5.928 +    def getHostOnlyIP(vm_name):
   5.929 +        if vm_name == None:
   5.930 +            logger.info('Gettting hostOnly IP address for Host')
   5.931 +            return VMManager.getHostOnlyIFs()['IPAddress']
   5.932 +        else:
   5.933 +            logger.info('Gettting hostOnly IP address ' + vm_name)
   5.934 +            result = checkResult(Cygwin.vboxExecute('guestproperty get ' + vm_name + ' /VirtualBox/GuestInfo/Net/0/V4/IP'))
   5.935 +            if result=='':
   5.936 +                return None
   5.937 +            result = result[1]
   5.938 +            if result.startswith('No value set!'):
   5.939 +                return None
   5.940 +            return result[result.index(':')+1:].strip()
   5.941 +            
   5.942 +    # attach removable storage device to VM by provision of filter
   5.943 +    def attachRSD(self, vm_name, rsd_filter):
   5.944 +        return checkResult(Cygwin.vboxExecute('usbfilter add 0 --target ' + vm_name + ' --name OpenSecurityRSD --vendorid ' + rsd_filter.vendorid + ' --productid ' + rsd_filter.productid + ' --revision ' + rsd_filter.revision))
   5.945 +    
   5.946 +    # detach removable storage from VM by 
   5.947 +    def detachRSD(self, vm_name):
   5.948 +        return checkResult(Cygwin.vboxExecute('usbfilter remove 0 --target ' + vm_name))
   5.949 +        
   5.950 +    # return the description set for an existing VM
   5.951 +    def getVMInfo(self, vm_name):
   5.952 +        results = checkResult(Cygwin.vboxExecute('showvminfo ' + vm_name + ' --machinereadable'))[1]
   5.953 +        props = dict((k.strip().strip('"'),v.strip().strip('"')) for k,v in (line.split('=', 1) for line in results.splitlines()))
   5.954 +        return props
   5.955 +    
   5.956 +    # return the configured USB filter for an existing VM 
   5.957 +    def getUSBFilter(self, vm_name):
   5.958 +        props = self.getVMInfo(vm_name)
   5.959 +        keys = set(['USBFilterVendorId1', 'USBFilterProductId1', 'USBFilterRevision1'])
   5.960 +        keyset = set(props.keys())
   5.961 +        usb_filter = None
   5.962 +        if keyset.issuperset(keys):
   5.963 +            usb_filter = USBFilter(props['USBFilterVendorId1'], props['USBFilterProductId1'], props['USBFilterRevision1'])
   5.964 +        return usb_filter
   5.965 +    
   5.966 +    #generates ISO containing authorized_keys for use with guest VM
   5.967 +    def genCertificateISO(self, vm_name):
   5.968 +        machineFolder = Cygwin.cygPath(self.machineFolder)
   5.969 +        # remove .ssh folder if exists
   5.970 +        checkResult(Cygwin.bashExecute('\"/usr/bin/rm -rf \\\"' + machineFolder + '/' + vm_name + '/.ssh\\\"\"'))
   5.971 +        # remove .ssh folder if exists
   5.972 +        checkResult(Cygwin.bashExecute('\"/usr/bin/rm -rf \\\"' + machineFolder + '/' + vm_name + '/dvm_key\\\"\"'))
   5.973 +        # create .ssh folder in vm_name
   5.974 +        checkResult(Cygwin.bashExecute('\"/usr/bin/mkdir -p \\\"' + machineFolder + '/' + vm_name + '/.ssh\\\"\"'))
   5.975 +        # generate dvm_key pair in vm_name / .ssh     
   5.976 +        checkResult(Cygwin.bashExecute('\"/usr/bin/ssh-keygen -q -t rsa -N \\"\\" -C \\\"' + vm_name + '\\\" -f \\\"' + machineFolder + '/' + vm_name + '/.ssh/dvm_key\\\"\"'))
   5.977 +        # move out private key
   5.978 +        checkResult(Cygwin.bashExecute('\"/usr/bin/mv \\\"' + machineFolder + '/' + vm_name + '/.ssh/dvm_key\\\" \\\"' + machineFolder + '/' + vm_name + '\\\"'))
   5.979 +        # set permissions for private key
   5.980 +        checkResult(Cygwin.bashExecute('\"/usr/bin/chmod 500 \\\"' + machineFolder + '/' + vm_name + '/dvm_key\\\"\"'))
   5.981 +        # rename public key to authorized_keys
   5.982 +        checkResult(Cygwin.bashExecute('\"/usr/bin/mv \\\"' + machineFolder + '/' + vm_name + '/.ssh/dvm_key.pub\\\" \\\"' + machineFolder + '/' + vm_name + '/.ssh/authorized_keys\\\"'))
   5.983 +        # set permissions for authorized_keys
   5.984 +        checkResult(Cygwin.bashExecute('\"/usr/bin/chmod 500 \\\"' + machineFolder + '/' + vm_name + '/.ssh/authorized_keys\\\"\"'))
   5.985 +        # generate iso image with .ssh/authorized keys
   5.986 +        checkResult(Cygwin.bashExecute('\"/usr/bin/genisoimage -J -R -o \\\"' + machineFolder + '/' + vm_name + '/'+ vm_name + '.iso\\\" \\\"' + machineFolder + '/' + vm_name + '/.ssh\\\"\"'))
   5.987 +    
   5.988 +    # attaches generated ssh public cert to guest vm
   5.989 +    def attachCertificateISO(self, vm_name):
   5.990 +        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\"'))
   5.991 +        return result
   5.992 +    
   5.993 +    # wait for machine to come up
   5.994 +    def waitStartup(self, vm_name, timeout_ms = 30000):
   5.995 +        checkResult(Cygwin.vboxExecute('guestproperty wait ' + vm_name + ' SDVMStarted --timeout ' + str(timeout_ms) + ' --fail-on-timeout'))
   5.996 +        return VMManager.getHostOnlyIP(vm_name)
   5.997 +    
   5.998 +    # wait for machine to shutdown
   5.999 +    def waitShutdown(self, vm_name):
  5.1000 +        while vm_name in self.listRunningVMS():
  5.1001 +            time.sleep(1)
  5.1002 +        return
  5.1003 +        
  5.1004 +    # handles browsing request    
  5.1005 +    def handleBrowsingRequest(self):
  5.1006 +        handler = BrowsingHandler(self)
  5.1007 +        handler.start()
  5.1008 +        return 'ok'
  5.1009 +    
  5.1010 +    #Small function to check the availability of network resource.
  5.1011 +    #def isAvailable(self, path):
  5.1012 +        #return os.path.exists(path)
  5.1013 +        #result = Cygwin.cmdExecute('IF EXIST "' + path + '" echo YES')
  5.1014 +        #return string.find(result[1], 'YES',)
  5.1015 +    
  5.1016 +    #Small function to check if the mention location is a directory
  5.1017 +    def isDirectory(self, path):
  5.1018 +        result = checkResult(Cygwin.cmdExecute('dir ' + path + ' | FIND ".."'))
  5.1019 +        return string.find(result[1], 'DIR',)
  5.1020 +
  5.1021 +    def mapNetworkDrive(self, drive, networkPath, user, password):
  5.1022 +        self.unmapNetworkDrive(drive)
  5.1023 +        #Check for drive availability
  5.1024 +        if os.path.exists(drive):
  5.1025 +            logger.error("Drive letter is already in use: " + drive)
  5.1026 +            return -1
  5.1027 +        #Check for network resource availability
  5.1028 +        retry = 5
  5.1029 +        while not os.path.exists(networkPath):
  5.1030 +            time.sleep(1)
  5.1031 +            if retry == 0:
  5.1032 +                return -1
  5.1033 +            logger.info("Path not accessible: " + networkPath + " retrying")
  5.1034 +            retry-=1
  5.1035 +            #return -1
  5.1036 +    
  5.1037 +        command = 'USE ' + drive + ' ' + networkPath + ' /PERSISTENT:NO'
  5.1038 +        if user != None:
  5.1039 +            command += ' ' + password + ' /User' + user
  5.1040 +    
  5.1041 +        #TODO: Execute 'NET USE' command with authentication
  5.1042 +        result = checkResult(Cygwin.execute('C:\\Windows\\system32\\net.exe', command))
  5.1043 +        if string.find(result[1], 'successfully',) == -1:
  5.1044 +            logger.error("Failed: NET " + command)
  5.1045 +            return -1
  5.1046 +        return 1
  5.1047 +    
  5.1048 +    def unmapNetworkDrive(self, drive):
  5.1049 +        drives = self.getNetworkDrives()
  5.1050 +        if drive not in drives.keys():
  5.1051 +            return 1 
  5.1052 +        result = checkResult(Cygwin.execute('C:\\Windows\\system32\\net.exe', 'USE ' + drive + ' /DELETE /YES'))
  5.1053 +        if string.find(str(result[1]), 'successfully',) == -1:
  5.1054 +            logger.error(result[2])
  5.1055 +            return -1
  5.1056 +        return 1
  5.1057 +    
  5.1058 +    def getNetworkDrives(self):
  5.1059 +        ip = VMManager.getHostOnlyIP(None)
  5.1060 +        ip = ip[:ip.rindex('.')]
  5.1061 +        drives = dict()    
  5.1062 +        result = checkResult(Cygwin.execute('C:\\Windows\\system32\\net.exe', 'USE'))
  5.1063 +        for line in result[1].splitlines():
  5.1064 +            if ip in line:
  5.1065 +                parts = line.split()
  5.1066 +                drives[parts[1]] = parts[2]
  5.1067 +        return drives
  5.1068 +            
  5.1069 +    def genNetworkDrive(self):
  5.1070 +        network_drives = self.getNetworkDrives()
  5.1071 +        logical_drives = VMManager.getLogicalDrives()
  5.1072 +        drives = list(map(chr, range(68, 91)))  
  5.1073 +        for drive in drives:
  5.1074 +            if drive+':' not in network_drives and drive not in logical_drives:
  5.1075 +                return drive+':'
  5.1076 +
  5.1077 +    def getNetworkDrive(self, vm_name):
  5.1078 +        ip = self.getHostOnlyIP(vm_name)
  5.1079 +        result = checkResult(Cygwin.execute('C:\\Windows\\system32\\net.exe', 'USE'))
  5.1080 +        for line in result[1].splitlines():
  5.1081 +            if line != None and ip in line:
  5.1082 +                parts = line.split()
  5.1083 +                return parts[0]
  5.1084 +    @staticmethod
  5.1085 +    def getLogicalDrives():
  5.1086 +        drive_bitmask = ctypes.cdll.kernel32.GetLogicalDrives()
  5.1087 +        return list(itertools.compress(string.ascii_uppercase,  map(lambda x:ord(x) - ord('0'), bin(drive_bitmask)[:1:-1])))
  5.1088 +    
  5.1089 +    @staticmethod
  5.1090 +    def getDriveType(drive):
  5.1091 +        return ctypes.cdll.kernel32.GetDriveTypeW(u"%s:\\"%drive)
  5.1092 +    
  5.1093 +    @staticmethod
  5.1094 +    def getVolumeInfo(drive):
  5.1095 +        volumeNameBuffer = ctypes.create_unicode_buffer(1024)
  5.1096 +        fileSystemNameBuffer = ctypes.create_unicode_buffer(1024)
  5.1097 +        serial_number = None
  5.1098 +        max_component_length = None
  5.1099 +        file_system_flags = None
  5.1100 +        
  5.1101 +        rc = ctypes.cdll.kernel32.GetVolumeInformationW(
  5.1102 +            #ctypes.c_wchar_p("F:\\"),
  5.1103 +            u"%s:\\"%drive,
  5.1104 +            volumeNameBuffer,
  5.1105 +            ctypes.sizeof(volumeNameBuffer),
  5.1106 +            serial_number,
  5.1107 +            max_component_length,
  5.1108 +            file_system_flags,
  5.1109 +            fileSystemNameBuffer,
  5.1110 +            ctypes.sizeof(fileSystemNameBuffer)
  5.1111 +        )
  5.1112 +        
  5.1113 +        return volumeNameBuffer.value, fileSystemNameBuffer.value
  5.1114 +
  5.1115 +def checkResult(result):
  5.1116 +    if result[0] != 0:
  5.1117 +        logger.error('Command failed:' + ''.join(result[2]))
  5.1118 +        raise OpenSecurityException('Command failed:' + ''.join(result[2]))
  5.1119 +    return result
  5.1120 +
  5.1121 +# handles browsing request                    
  5.1122 +class BrowsingHandler(threading.Thread):
  5.1123 +    vmm = None
  5.1124 +    def __init__(self, vmmanager):
  5.1125 +        threading.Thread.__init__(self)
  5.1126 +        self.vmm = vmmanager
  5.1127 +     
  5.1128 +    def run(self):
  5.1129 +        try:
  5.1130 +            new_sdvm = self.vmm.generateSDVMName()
  5.1131 +            self.vmm.createVM(new_sdvm)
  5.1132 +            self.vmm.storageAttach(new_sdvm)
  5.1133 +            self.vmm.genCertificateISO(new_sdvm)
  5.1134 +            self.vmm.attachCertificateISO(new_sdvm)
  5.1135 +            self.vmm.startVM(new_sdvm)
  5.1136 +            new_ip = self.vmm.waitStartup(new_sdvm)
  5.1137 +            drive = self.vmm.genNetworkDrive()
  5.1138 +            if new_ip != None:
  5.1139 +                self.vmm.mapNetworkDrive(drive, '\\\\' + new_ip + '\\Download', None, None)
  5.1140 +            result = checkResult(Cygwin.sshExecuteX11('/usr/bin/iceweasel', new_ip, 'osecuser', Cygwin.cygPath(self.vmm.getMachineFolder()) + '/' + new_sdvm + '/dvm_key'))
  5.1141 +        except:
  5.1142 +            logger.error("BrowsingHandler failed. Cleaning up")
  5.1143 +            
  5.1144 +        self.vmm.unmapNetworkDrive(drive)
  5.1145 +        self.vmm.poweroffVM(new_sdvm)
  5.1146 +        self.vmm.removeVM(new_sdvm)
  5.1147 +                
  5.1148 +class DeviceHandler(threading.Thread): 
  5.1149 +    vmm = None
  5.1150 +    #handleDeviceChangeLock = threading.Lock()
  5.1151 +    attachedRSDs = None  
  5.1152 +    connectedRSDs = None
  5.1153 +    running = True
  5.1154 +    def __init__(self, vmmanger): 
  5.1155 +        threading.Thread.__init__(self)
  5.1156 +        self.vmm = vmmanger
  5.1157 + 
  5.1158 +    def stop(self):
  5.1159 +        self.running = False
  5.1160 +        
  5.1161 +    def run(self):
  5.1162 +        self.connectedRSDs = dict()
  5.1163 +        self.attachedRSDs = self.vmm.getAttachedRSDs()
  5.1164 +        while self.running:
  5.1165 +            tmp_rsds = self.vmm.getConnectedRSDS()
  5.1166 +            if tmp_rsds.keys() == self.connectedRSDs.keys():
  5.1167 +                logger.debug("Nothing's changed. sleep(3)")
  5.1168 +                time.sleep(3)
  5.1169 +                continue
  5.1170 +            
  5.1171 +            logger.info("Something's changed")          
  5.1172 +            self.connectedRSDs = tmp_rsds
  5.1173 +            self.attachedRSDs = self.vmm.getAttachedRSDs()
  5.1174 +            
  5.1175 +            for vm_name in self.attachedRSDs.keys():
  5.1176 +                if self.attachedRSDs[vm_name] not in self.connectedRSDs.values():
  5.1177 +                    drive = self.vmm.getNetworkDrive(vm_name)
  5.1178 +                    self.vmm.unmapNetworkDrive(drive)
  5.1179 +                    #self.stopVM(vm_name)
  5.1180 +                    self.vmm.detachRSD(vm_name)
  5.1181 +                    self.vmm.poweroffVM(vm_name)
  5.1182 +                    self.vmm.removeVM(vm_name)
  5.1183 +            #create new vm for attached device if any
  5.1184 +            self.attachedRSDs = self.vmm.getAttachedRSDs()
  5.1185 +            self.connectedRSDs = self.vmm.getConnectedRSDS()
  5.1186 +            
  5.1187 +            new_ip = None
  5.1188 +            for connected_device in self.connectedRSDs.values():
  5.1189 +                if (self.attachedRSDs and False) or (connected_device not in self.attachedRSDs.values()):
  5.1190 +                    new_sdvm = self.vmm.generateSDVMName()
  5.1191 +                    self.vmm.createVM(new_sdvm)
  5.1192 +                    self.vmm.storageAttach(new_sdvm)
  5.1193 +                    self.vmm.attachRSD(new_sdvm, connected_device)
  5.1194 +                    self.vmm.startVM(new_sdvm)
  5.1195 +                    new_ip = self.vmm.waitStartup(new_sdvm)
  5.1196 +                    drive = self.vmm.genNetworkDrive()
  5.1197 +                    if new_ip != None:
  5.1198 +                        self.vmm.mapNetworkDrive(drive, '\\\\' + new_ip + '\\USB', None, None)
  5.1199 +
  5.1200 +if __name__ == '__main__':
  5.1201 +    #man = VMManager.getInstance()
  5.1202 +    #man.listVM()
  5.1203 +    #print man.getConnectedRSDs()
  5.1204 +    #print man.getNetworkDrives()
  5.1205 +    #man.genNetworkDrive()
  5.1206 +    #drive_bitmask = ctypes.cdll.kernel32.GetLogicalDrives()
  5.1207 +    #print list(itertools.compress(string.ascii_uppercase,  map(lambda x:ord(x) - ord('0'), bin(drive_bitmask)[:1:-1])))
  5.1208 +    #print list(map(chr, range(68, 91))) 
  5.1209 +    #print Cygwin.getRegEntry('SYSTEM\CurrentControlSet\Enum\USB', 'VID_1058&PID_0704')[0]
  5.1210 +    #devices = VMManager.getConnectedRSDS()
  5.1211 +    #print devices
  5.1212 +    
  5.1213 +    drives = VMManager.getLogicalDrives()
  5.1214 +    print drives
  5.1215 +    print VMManager.getDriveType("E")
  5.1216 +    print VMManager.getVolumeInfo("E")
  5.1217 +    #for device in devices.values():
  5.1218 +    #    #print device
  5.1219 +    #    if VMManager.isMassStorageDevice(device):
  5.1220 +    #        print device
  5.1221 +        
  5.1222 +    
  5.1223 +    
  5.1224 +    #time.sleep(-1)
  5.1225 +    #man.listVM()
  5.1226 +    #man.listVM()
  5.1227 +    #man.listVM()
  5.1228 +    #man.listVM()
  5.1229 +    #man.genCertificateISO('SecurityDVM0')
  5.1230 +    #man.guestExecute('SecurityDVM0', '/bin/ls -la')
  5.1231 +    #logger = setupLogger('VMManager')
  5.1232 +    #c = Cygwin()
  5.1233 +    
  5.1234 +    #man.sshExecute('/bin/ls -la', 'SecurityDVM0')
  5.1235 +    #man.sshExecuteX11('/usr/bin/iceweasel', 'SecurityDVM0')
  5.1236 +    #man.removeVM('SecurityDVM0')
  5.1237 +    #man.netUse('192.168.56.134', 'USB\\')
  5.1238 +    #ip = '192.168.56.139'
  5.1239 +    
  5.1240 +    #man.cygwin_path = 'c:\\cygwin64\\bin\\'
  5.1241 +    #man.handleDeviceChange()
  5.1242 +    #print man.listSDVM()
  5.1243 +    #man.configureHostNetworking()
  5.1244 +    #new_vm = man.generateSDVMName()
  5.1245 +    #man.createVM(new_vm)
  5.1246 +    
  5.1247 +    #print Cygwin.cmd()
  5.1248 +    #man.isAvailable('c:')
  5.1249 +    #ip = man.getHostOnlyIP('SecurityDVM0')
  5.1250 +    #man.mapNetworkDrive('h:', '\\\\' + ip + '\Download', None, None)
  5.1251 +    
  5.1252 +    #man.genCertificateISO(new_vm)
  5.1253 +    #man.attachCertificateISO(new_vm)
  5.1254 +    
  5.1255 +    #man.attachCertificateISO(vm_name)
  5.1256 +    #man.guestExecute(vm_name, "ls")
  5.1257 +    #man.sshGuestX11Execute('SecurityDVM1', '/usr/bin/iceweasel')
  5.1258 +    #time.sleep(60)
  5.1259 +    #print man.cygwinPath("C:\Users\BarthaM\VirtualBox VMs\SecurityDVM\.ssh\*")
  5.1260 +    #man.genCertificateISO('SecurityDVM')
  5.1261 +    #man.attachCertificateISO('SecurityDVM')
  5.1262 +    #man.isStorageAttached('SecurityDVM')
  5.1263 +    #man.guestExecute('SecurityDVM', 'sudo apt-get -y update')
  5.1264 +    #man.guestExecute('SecurityDVM', 'sudo apt-get -y upgrade' )
  5.1265 +    
  5.1266 +    #man.stopVM('SecurityDVM')
  5.1267 +    #man.storageDetach('SecurityDVM')
  5.1268 +    #man.changeStorageType('C:\Users\BarthaM\VirtualBox VMs\SecurityDVM\SecurityDVM.vmdk','immutable')
  5.1269 +    #man.storageAttach('SecurityDVM')
  5.1270 +    
  5.1271 +    
  5.1272 +    #cmd = "c:\\cygwin64\\bin\\bash.exe --login -c \"/bin/ls\""
  5.1273 +    #man.execute(cmd)