download and initial import from within service working
authorOliver Maurhart <oliver.maurhart@ait.ac.at>
Mon, 10 Mar 2014 13:01:08 +0100
changeset 91a26757850ea9
parent 90 bfd41c38d156
child 92 bc1255abd544
download and initial import from within service working
OpenSecurity/bin/cygwin.py
OpenSecurity/bin/download_initial_image.sh
OpenSecurity/bin/environment.py
OpenSecurity/bin/initial_vm.sh
OpenSecurity/bin/opensecurity_service.pyw
OpenSecurity/bin/opensecurityd.pyw
OpenSecurity/bin/vmmanager.pyw
     1.1 --- a/OpenSecurity/bin/cygwin.py	Fri Mar 07 14:32:12 2014 +0100
     1.2 +++ b/OpenSecurity/bin/cygwin.py	Mon Mar 10 13:01:08 2014 +0100
     1.3 @@ -1,222 +1,236 @@
     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 -    """get the path to the VirtualBox installation on this system"""
    1.70 -    theClass.vbox_root = theClass.getRegEntry('SOFTWARE\Oracle\VirtualBox', 'InstallDir')[0]
    1.71 -    theClass.vbox_man = os.path.join(theClass.vbox_root, 'VBoxManage.exe')
    1.72 -    
    1.73 -    return theClass
    1.74 -
    1.75 -@once
    1.76 -class Cygwin(object):
    1.77 -    cygwin_root = ''
    1.78 -    cygwin_bin = ''
    1.79 -    cygwin_bash = ''
    1.80 -    cygwin_ssh = ''
    1.81 -    cygwin_x11 = ''
    1.82 -    vbox_root = ''
    1.83 -    vbox_man = ''
    1.84 -    win_cmd = ''
    1.85 -    """Some nifty methods working with Cygwin"""
    1.86 -    
    1.87 -    def __call__(self, command, arguments, wait_return=True, window = False):
    1.88 -        """make an instance of this object act as a function"""
    1.89 -        return self.execute(command, arguments, wait_return, window)
    1.90 -
    1.91 -    @staticmethod
    1.92 -    def getRegEntry(key, value):
    1.93 -        try:
    1.94 -            k = _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE, key)
    1.95 -            value = _winreg.QueryValueEx(k, value)
    1.96 -            _winreg.CloseKey(k)
    1.97 -            return value
    1.98 -        except:
    1.99 -            pass
   1.100 -            
   1.101 -    @staticmethod
   1.102 -    def root():
   1.103 -        return Cygwin.cygwin_root
   1.104 -
   1.105 -    @staticmethod
   1.106 -    def bin():
   1.107 -        return Cygwin.cygwin_bin
   1.108 -    
   1.109 -    @staticmethod
   1.110 -    def bash():
   1.111 -        return Cygwin.cygwin_bash
   1.112 -    
   1.113 -    @staticmethod    
   1.114 -    def ssh():
   1.115 -        return Cygwin.cygwin_ssh
   1.116 -
   1.117 -    @staticmethod    
   1.118 -    def x11():
   1.119 -        return Cygwin.cygwin_x11
   1.120 -    
   1.121 -    @staticmethod
   1.122 -    def vboxman():
   1.123 -        return Cygwin.vbox_man
   1.124 -    
   1.125 -    @staticmethod
   1.126 -    def cmd():
   1.127 -        return Cygwin.win_cmd
   1.128 -    
   1.129 -    executeLock = threading.Lock()
   1.130 -    #executes command on host system
   1.131 -    @staticmethod
   1.132 -    def execute(program, arguments, wait_return=True, window = False):
   1.133 -        _startupinfo = STARTUPINFO()
   1.134 -        if not window:
   1.135 -            _startupinfo.dwFlags |= _subprocess.STARTF_USESHOWWINDOW
   1.136 -            _startupinfo.wShowWindow = _subprocess.SW_HIDE
   1.137 -
   1.138 -            #logger.debug('trying to launch: ' + program + ' ' + ''.join(arguments))
   1.139 -        res_stderr = None
   1.140 -        try:
   1.141 -            process = Popen(executable=program, args=' ' + arguments, startupinfo = _startupinfo, stdin=PIPE, stdout=PIPE, stderr=PIPE, shell = False)
   1.142 -            logger.debug('Launched: ' + program + ' ' + ''.join(arguments))
   1.143 -            if not wait_return:
   1.144 -                return [0, 'working in background', '']
   1.145 -            result = process.wait()
   1.146 -            res_stdout = process.stdout.read();
   1.147 -            res_stderr = process.stderr.read();
   1.148 -
   1.149 -        except Exception as ex:
   1.150 -            res_stderr.join(ex.args)
   1.151 -            result = 1 
   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 -        retry = 0
   1.158 -        result = None
   1.159 -        while retry < 3:
   1.160 -            if Cygwin.executeLock.acquire(True):
   1.161 -                result = Cygwin.execute(Cygwin.vbox_man, command, wait_return, window)
   1.162 -                Cygwin.executeLock.release()
   1.163 -                if result[0] == 0:
   1.164 -                    return result
   1.165 -                retry+=1
   1.166 -        return result
   1.167 -        
   1.168 -    
   1.169 -    @staticmethod
   1.170 -    def bashExecute(command, wait_return=True, window = False, bash_opts=''):
   1.171 -        command = bash_opts + ' -l -c '  + command
   1.172 -        return Cygwin.execute(Cygwin.cygwin_bash, command, wait_return, window)
   1.173 -    
   1.174 -    @staticmethod
   1.175 -    def cmdExecute(command, wait_return=True, window = False, bash_opts=''):
   1.176 -        command = ' /c ' + command 
   1.177 -        return Cygwin.execute(Cygwin.win_cmd, command, wait_return, window)
   1.178 -
   1.179 -    # executes command over ssh on guest vm
   1.180 -    @staticmethod
   1.181 -    def sshExecute(command, address, user_name, certificate, wait_return=True, window = False):
   1.182 -        command = ' -v -i "' + certificate + '" ' + user_name + '@' + address + ' ' + command        
   1.183 -        return Cygwin.execute(Cygwin.cygwin_ssh, command, wait_return, window)     
   1.184 -    
   1.185 -    #machineFolder + '/' + vm_name + '/dvm_key
   1.186 -    #address = self.getHostOnlyIP(vm_name)
   1.187 -    #machineFolder = self.getDefaultMachineFolder()
   1.188 -    #machineFolder = Cygwin.cygwinPath(machineFolder)
   1.189 -    
   1.190 -    # executes command over ssh on guest vm with X forwarding
   1.191 -    @staticmethod
   1.192 -    def sshExecuteX11(command, address, user_name, certificate, wait_return=True):
   1.193 -        return Cygwin.bashExecute('"DISPLAY=:0.0 /usr/bin/ssh -v -Y -i \\"' + certificate +'\\" ' + user_name + '@' + address + ' ' + command + '\"')
   1.194 -
   1.195 -    @staticmethod
   1.196 -    def is_X11_running():
   1.197 -        """check if we can connect to a X11 running instance"""
   1.198 -        p = Cygwin.bashExecute('"DISPLAY=:0 /usr/bin/xset -q"')
   1.199 -        return p[0] == 0
   1.200 -        
   1.201 -        
   1.202 -    @staticmethod
   1.203 -    def start_X11():
   1.204 -        """start X11 in the background (if not already running) on DISPLAY=:0"""
   1.205 -        # do not start if already running
   1.206 -        if Cygwin.is_X11_running():
   1.207 -            return           
   1.208 -        # launch X11 (forget output and return immediately)
   1.209 -        return Cygwin.execute(Cygwin.cygwin_x11, ':0 -multiwindow', wait_return = False, window = False)
   1.210 -    
   1.211 -    @staticmethod    
   1.212 -    def cygPath(path):
   1.213 -        return Cygwin.bashExecute('"/usr/bin/cygpath -u \\"' + path + '\\""')[1].rstrip('\n')
   1.214 -    
   1.215 -# start
   1.216 -if __name__ == "__main__":
   1.217 -    logger = setupLogger('Cygwin')
   1.218 -    c = Cygwin()
   1.219 -    logger.info(c.root())
   1.220 -    logger.info(c.bin())
   1.221 -    logger.info(c.bash())
   1.222 -    logger.info(c.ssh())
   1.223 -    
   1.224 -    c.cygPath('C:')
   1.225 -    c.start_X11()
   1.226 +#!/bin/env python
   1.227 +# -*- coding: utf-8 -*-
   1.228 +
   1.229 +# ------------------------------------------------------------
   1.230 +# cygwin command
   1.231 +# 
   1.232 +# executes a cygwin command inside the opensecurity project
   1.233 +#
   1.234 +# Autor: Mihai Bartha, <mihai.bartha@ait.ac.at>
   1.235 +#        Oliver Maurhart, <oliver.maurhart@ait.ac.at>
   1.236 +#
   1.237 +# Copyright (C) 2013 AIT Austrian Institute of Technology
   1.238 +# AIT Austrian Institute of Technology GmbH
   1.239 +# Donau-City-Strasse 1 | 1220 Vienna | Austria
   1.240 +# http://www.ait.ac.at
   1.241 +#
   1.242 +# This program is free software; you can redistribute it and/or
   1.243 +# modify it under the terms of the GNU General Public License
   1.244 +# as published by the Free Software Foundation version 2.
   1.245 +# 
   1.246 +# This program is distributed in the hope that it will be useful,
   1.247 +# but WITHOUT ANY WARRANTY; without even the implied warranty of
   1.248 +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   1.249 +# GNU General Public License for more details.
   1.250 +# 
   1.251 +# You should have received a copy of the GNU General Public License
   1.252 +# along with this program; if not, write to the Free Software
   1.253 +# Foundation, Inc., 51 Franklin Street, Fifth Floor, 
   1.254 +# Boston, MA  02110-1301, USA.
   1.255 +# ------------------------------------------------------------
   1.256 +
   1.257 +
   1.258 +# ------------------------------------------------------------
   1.259 +# imports
   1.260 +
   1.261 +import os
   1.262 +import subprocess
   1.263 +import sys
   1.264 +import _winreg
   1.265 +from subprocess import Popen, PIPE, call, STARTUPINFO, _subprocess
   1.266 +import threading
   1.267 +# local
   1.268 +from environment import Environment
   1.269 +from opensecurity_util import logger, setupLogger, OpenSecurityException
   1.270 +
   1.271 +# ------------------------------------------------------------
   1.272 +# code
   1.273 +
   1.274 +def once(theClass):
   1.275 +    """get the path to our local cygwin installment"""
   1.276 +    home_drive = os.path.expandvars("%HOMEDRIVE%") + os.sep
   1.277 +    path_hint = [ 
   1.278 +        os.path.abspath(os.path.join(Environment('OpenSecurity').prefix_path, 'cygwin')), 
   1.279 +        os.path.abspath(os.path.join(Environment('OpenSecurity').prefix_path, 'cygwin64')), 
   1.280 +        os.path.abspath(os.path.join(home_drive, 'cygwin')),
   1.281 +        os.path.abspath(os.path.join(home_drive, 'cygwin64'))
   1.282 +    ]
   1.283 +    path_valid = [ p for p in path_hint if os.path.exists(p) ]
   1.284 +        
   1.285 +    theClass.cygwin_root = path_valid[0]
   1.286 +    theClass.cygwin_bin = os.path.join(theClass.cygwin_root, 'bin') + os.path.sep
   1.287 +    theClass.cygwin_bash = os.path.join(theClass.cygwin_bin, 'bash.exe')
   1.288 +    theClass.cygwin_ssh = os.path.join(theClass.cygwin_bin, 'ssh.exe')
   1.289 +    theClass.cygwin_x11 = os.path.join(theClass.cygwin_bin, 'XWin.exe')
   1.290 +    theClass.win_cmd = os.environ.get("COMSPEC", "cmd.exe") 
   1.291 +    """get the path to the VirtualBox installation on this system"""
   1.292 +    theClass.vbox_root = theClass.getRegEntry('SOFTWARE\Oracle\VirtualBox', 'InstallDir')[0]  
   1.293 +    theClass.vbox_man = os.path.join(theClass.vbox_root, 'VBoxManage.exe')
   1.294 +    
   1.295 +    return theClass
   1.296 +
   1.297 +@once
   1.298 +class Cygwin(object):
   1.299 +    cygwin_root = ''
   1.300 +    cygwin_bin = ''
   1.301 +    cygwin_bash = ''
   1.302 +    cygwin_ssh = ''
   1.303 +    cygwin_x11 = ''
   1.304 +    vbox_root = ''
   1.305 +    vbox_man = ''
   1.306 +    win_cmd = ''
   1.307 +    """Some nifty methods working with Cygwin"""
   1.308 +    
   1.309 +    def __call__(self, command, arguments, wait_return=True, window = False):
   1.310 +        """make an instance of this object act as a function"""
   1.311 +        return self.execute(command, arguments, wait_return, window)
   1.312 +
   1.313 +    @staticmethod
   1.314 +    def getRegEntry(key, value):
   1.315 +        try:
   1.316 +            k = _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE, key)
   1.317 +            value = _winreg.QueryValueEx(k, value)
   1.318 +            _winreg.CloseKey(k)
   1.319 +            return value
   1.320 +        except:
   1.321 +            pass
   1.322 +    
   1.323 +            
   1.324 +    @staticmethod
   1.325 +    def root():
   1.326 +        return Cygwin.cygwin_root
   1.327 +
   1.328 +    @staticmethod
   1.329 +    def bin():
   1.330 +        return Cygwin.cygwin_bin
   1.331 +    
   1.332 +    @staticmethod
   1.333 +    def bash():
   1.334 +        return Cygwin.cygwin_bash
   1.335 +    
   1.336 +    @staticmethod    
   1.337 +    def ssh():
   1.338 +        return Cygwin.cygwin_ssh
   1.339 +
   1.340 +    @staticmethod    
   1.341 +    def x11():
   1.342 +        return Cygwin.cygwin_x11
   1.343 +    
   1.344 +    @staticmethod
   1.345 +    def vboxman():
   1.346 +        return Cygwin.vbox_man
   1.347 +    
   1.348 +    @staticmethod
   1.349 +    def cmd():
   1.350 +        return Cygwin.win_cmd
   1.351 +    
   1.352 +    executeLock = threading.Lock()
   1.353 +    #executes command on host system
   1.354 +    @staticmethod
   1.355 +    def execute(program, arguments, wait_return=True, window = False, stdin = PIPE, stdout = PIPE, stderr = PIPE):
   1.356 +        _startupinfo = STARTUPINFO()
   1.357 +        if not window:
   1.358 +            _startupinfo.dwFlags |= _subprocess.STARTF_USESHOWWINDOW
   1.359 +            _startupinfo.wShowWindow = _subprocess.SW_HIDE
   1.360 +
   1.361 +            #logger.debug('trying to launch: ' + program + ' ' + ''.join(arguments))
   1.362 +        res_stderr = None
   1.363 +        try:
   1.364 +            # quote the executable otherwise we run into troubles
   1.365 +            # when the path contains spaces and additonal arguments
   1.366 +            # are presented as well.
   1.367 +            # special: invoking bash as login shell here with
   1.368 +            # an unquoted command does not execute /etc/profile
   1.369 +            args = '"' + program + '" ' + arguments
   1.370 +            process = Popen(args, startupinfo = _startupinfo, stdin = stdin, stdout = stdout, stderr = stderr, 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(str(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='', stdin = PIPE, stdout = PIPE, stderr = PIPE):
   1.400 +        # for some reason, the '-l' is ignored when started via python
   1.401 +        # so the same behavior is triggered by calling /etc/profile 
   1.402 +        # directly
   1.403 +        command = bash_opts + ' -l -c "'  + command + '"'
   1.404 +        return Cygwin.execute(Cygwin.cygwin_bash, command, wait_return, window, stdin = stdin, stdout = stdout, stderr = stderr)
   1.405 +    
   1.406 +    @staticmethod
   1.407 +    def cmdExecute(command, wait_return=True, window = False, bash_opts=''):
   1.408 +        command = ' /c ' + command 
   1.409 +        return Cygwin.execute(Cygwin.win_cmd, command, wait_return, window)
   1.410 +
   1.411 +    # executes command over ssh on guest vm
   1.412 +    @staticmethod
   1.413 +    def sshExecute(command, address, user_name, certificate, wait_return=True, window = False):
   1.414 +        command = ' -v -i "' + certificate + '" ' + user_name + '@' + address + ' ' + command        
   1.415 +        return Cygwin.execute(Cygwin.cygwin_ssh, command, wait_return, window)     
   1.416 +    
   1.417 +    #machineFolder + '/' + vm_name + '/dvm_key
   1.418 +    #address = self.getHostOnlyIP(vm_name)
   1.419 +    #machineFolder = self.getDefaultMachineFolder()
   1.420 +    #machineFolder = Cygwin.cygwinPath(machineFolder)
   1.421 +    
   1.422 +    # executes command over ssh on guest vm with X forwarding
   1.423 +    @staticmethod
   1.424 +    def sshExecuteX11(command, address, user_name, certificate, wait_return=True):
   1.425 +        return Cygwin.bashExecute('"DISPLAY=:0.0 /usr/bin/ssh -v -Y -i \\"' + certificate +'\\" ' + user_name + '@' + address + ' ' + command + '\"')
   1.426 +
   1.427 +    @staticmethod
   1.428 +    def is_X11_running():
   1.429 +        """check if we can connect to a X11 running instance"""
   1.430 +        p = Cygwin.bashExecute('DISPLAY=:0 /usr/bin/xset -q')
   1.431 +        return p[0] == 0
   1.432 +        
   1.433 +        
   1.434 +    @staticmethod
   1.435 +    def start_X11():
   1.436 +        """start X11 in the background (if not already running) on DISPLAY=:0"""
   1.437 +        # do not start if already running
   1.438 +        if Cygwin.is_X11_running():
   1.439 +            return           
   1.440 +        # launch X11 (forget output and return immediately)
   1.441 +        return Cygwin.execute(Cygwin.cygwin_x11, ':0 -multiwindow', wait_return = False, window = False)
   1.442 +    
   1.443 +    @staticmethod    
   1.444 +    def cygPath(path):
   1.445 +        cmd = 'cygpath -u \'' + path + '\''
   1.446 +        return Cygwin.bashExecute(cmd)[1].rstrip('\n')
   1.447 +    
   1.448 +# start
   1.449 +if __name__ == "__main__":
   1.450 +    logger = setupLogger('Cygwin')
   1.451 +    c = Cygwin()
   1.452 +    logger.info(c.root())
   1.453 +    logger.info(c.bin())
   1.454 +    logger.info(c.bash())
   1.455 +    logger.info(c.ssh())
   1.456 +    
   1.457 +    print(c.bashExecute('echo $PATH')[1])
   1.458 +    print(c.cygPath('C:'))
   1.459 +    print('C:\\Program Files\\OpenSecurity: ' + c.cygPath('C:\\Program Files\\OpenSecurity'))
   1.460 +    c.start_X11()
   1.461 +
     2.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.2 +++ b/OpenSecurity/bin/download_initial_image.sh	Mon Mar 10 13:01:08 2014 +0100
     2.3 @@ -0,0 +1,47 @@
     2.4 +#!/bin/bash
     2.5 +
     2.6 +# ------------------------------------------------------------
     2.7 +# download initial VM for
     2.8 +#
     2.9 +#       OpenSecurity V0.2
    2.10 +#
    2.11 +# (C)opyright 2014, AIT Austrian Instiitute of Technology
    2.12 +# ------------------------------------------------------------
    2.13 +
    2.14 +# ------------------------------------------------------------
    2.15 +# code
    2.16 +
    2.17 +
    2.18 +# download the ionitial OsecVM.ova from the X-Net servers
    2.19 +# and place the file in the folder specified by ${1}
    2.20 +
    2.21 +
    2.22 +# ------------------------------
    2.23 +# main ...
    2.24 +#
    2.25 +
    2.26 +# check if we do have elevated rights
    2.27 +# that is "Run as Administrator" invocation
    2.28 +id -G | grep 544 &> /dev/null
    2.29 +if [ "${?}" != 0 ]; then
    2.30 +    echo "Insufficient privileges."
    2.31 +    echo "Is this script executed with 'Run As Administrator'?"
    2.32 +    exit 1
    2.33 +fi
    2.34 +
    2.35 +TARGET_FOLDER="${1}"
    2.36 +echo "fetching OpenSecurity initial VM at " $(date)
    2.37 +echo "target folder: ${TARGET_FOLDER}"
    2.38 +
    2.39 +# sanity check
    2.40 +mkdir -p "${TARGET_FOLDER}" 
    2.41 +if [ ! -d "${TARGET_FOLDER}" ]; then
    2.42 +    echo "failed to access target folder."
    2.43 +    exit 1
    2.44 +fi
    2.45 +
    2.46 +# start download
    2.47 +URL="http://service.x-net.at/opensecurity/OsecVM_latest.ova"
    2.48 +wget --progress=dot:mega ${URL} -O "${TARGET_FOLDER}"/OsecVM.ova
    2.49 +
    2.50 +
     3.1 --- a/OpenSecurity/bin/environment.py	Fri Mar 07 14:32:12 2014 +0100
     3.2 +++ b/OpenSecurity/bin/environment.py	Mon Mar 10 13:01:08 2014 +0100
     3.3 @@ -64,7 +64,7 @@
     3.4          if sys.platform == 'linux2':
     3.5              self._prefix_path = os.path.split(sys.path[0])[0]
     3.6          elif sys.platform == 'win32' or sys.platform == 'cygwin':
     3.7 -            self._prefix_path = sys.path[0]
     3.8 +            self._prefix_path = os.path.normpath(os.path.join(sys.path[0], '..'))
     3.9              
    3.10          # the data path where all data files are stored
    3.11          if sys.platform == 'linux2':
    3.12 @@ -118,7 +118,7 @@
    3.13              # somewhere like C:\Program Files\OpenSecurity\log
    3.14              # having this script residing in 
    3.15              # C:\Progam Files\OpenSecurity\bin
    3.16 -            ideal_log_path = os.path.normpath(os.path.join(self.prefix_path, '..', 'log'))
    3.17 +            ideal_log_path = os.path.normpath(os.path.join(self.prefix_path, 'log'))
    3.18  
    3.19              # check ideal path first
    3.20              if not os.path.exists(ideal_log_path):
    3.21 @@ -147,3 +147,4 @@
    3.22  # test the module			
    3.23  if __name__ == '__main__':
    3.24      test()
    3.25 +
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/OpenSecurity/bin/initial_vm.sh	Mon Mar 10 13:01:08 2014 +0100
     4.3 @@ -0,0 +1,159 @@
     4.4 +#!/bin/bash
     4.5 +
     4.6 +# ------------------------------------------------------------
     4.7 +# install the initial VM for 
     4.8 +#
     4.9 +#       OpenSecurity V0.2
    4.10 +#
    4.11 +# This has been originally a Windows only BAT file.
    4.12 +#
    4.13 +# ... but coding this makes your head hurt and
    4.14 +# supporting this "technology" any further by adding
    4.15 +# software to the world relying on CMD.exe is an act
    4.16 +# against humanity and should be punished by jail.
    4.17 +#
    4.18 +# (C)opyright 2014, AIT Austrian Instiitute of Technology
    4.19 +# ------------------------------------------------------------
    4.20 +
    4.21 +
    4.22 +# ------------------------------------------------------------
    4.23 +# code
    4.24 +
    4.25 +# install the initial VM given by ${1}
    4.26 +
    4.27 +
    4.28 +# ------------------------------
    4.29 +# turns a windows path into a cygwin path
    4.30 +#
    4.31 +#   $1  ...     windows path
    4.32 +#   stdout      the value found
    4.33 +#
    4.34 +function sanitize_path() {
    4.35 +    test -z "${1}" && return
    4.36 +    echo $(cygpath -u "${1}") 
    4.37 +}
    4.38 +
    4.39 +
    4.40 +# ------------------------------
    4.41 +# main ...
    4.42 +#
    4.43 +
    4.44 +# check if we do have elevated rights
    4.45 +# that is "Run as Administrator" invocation
    4.46 +echo 'checking privileges...'
    4.47 +id -G | grep 544 &> /dev/null
    4.48 +if [ "${?}" != 0 ]; then
    4.49 +    echo "Insufficient privileges."
    4.50 +    echo "Is this script executed with 'Run As Administrator'?"
    4.51 +    exit 1
    4.52 +echo 'privileges sufficient.'
    4.53 +fi
    4.54 +
    4.55 +# check OpenSecurity Initial VM Image
    4.56 +#
    4.57 +echo "looking for VM image: ${1}..."
    4.58 +OSECVM_IMAGE=$(cygpath -u "${1}")
    4.59 +echo "looking for VM image: ${1}"
    4.60 +if [ ! -f "${OSECVM_IMAGE}" ]; then
    4.61 +    echo "Warning: no OpenSecurity Initial Image found."
    4.62 +    echo "Please download using the OpenSecurity download tool."
    4.63 +    exit 1
    4.64 +fi
    4.65 +echo "initial VM image: ${1} found"
    4.66 +
    4.67 +# look up VirtulBox installation
    4.68 +#
    4.69 +echo "looking up VirtualBox installation..."
    4.70 +VBOX_MANAGER="$(cat /proc/registry/HKEY_LOCAL_MACHINE/SOFTWARE/Oracle/VirtualBox/InstallDir)/VBoxManage.exe"
    4.71 +VBOX_MANAGER=$(sanitize_path "${VBOX_MANAGER}")
    4.72 +if [ ! -x "${VBOX_MANAGER}" ]; then
    4.73 +    echo "can't execute VBoxManage.exe - is VirtualBox installed?"
    4.74 +    echo "looked at: "$(cygpath -w ${VBOX_MANAGER})""
    4.75 +    exit 1
    4.76 +fi
    4.77 +echo "VirtualBox found at: ${VBOX_MANAGER}"
    4.78 +
    4.79 +# enforce VirtualBox to "feel good" by calling a function
    4.80 +# (that is to "warm up" VirtualBox DCOM server ...)
    4.81 +#
    4.82 +echo "grabing VBox machine folder..."
    4.83 +MACHINE_FOLDER=$("${VBOX_MANAGER}" list systemproperties | grep '^Default machine folder:' | sed 's/^Default machine folder: *//')
    4.84 +MACHINE_FOLDER=$(cygpath -u "${MACHINE_FOLDER}")
    4.85 +echo "machine folder: ${MACHINE_FOLDER}"
    4.86 +
    4.87 +# we have to stop the OpenSecurity service now
    4.88 +# the VMManger does lock the SecurityDVMs so we can't
    4.89 +# change them when he's on
    4.90 +echo "stopping OpenSecurity service..."
    4.91 +net stop "OpenSecurity Service"
    4.92 +echo "OpenSecurity service stopped."
    4.93 +
    4.94 +echo -n "After stopping we'll wait 5 secs to let VirtualBox calm itself"
    4.95 +for i in {1..5}; do
    4.96 +    echo -n .
    4.97 +    sleep 1
    4.98 +done
    4.99 +echo
   4.100 +
   4.101 +# do all stuff relativ to the given machinefolder
   4.102 +pushd "${MACHINE_FOLDER}" &> /dev/null
   4.103 +if [ "$?" != "0" ]; then
   4.104 +    echo "Failed to switch into machine folder."
   4.105 +    exit 1
   4.106 +fi    
   4.107 +
   4.108 +# the Security VM disk image
   4.109 +VDISK_IMAGE="SecurityDVM/SecurityDVM.vmdk"
   4.110 +
   4.111 +# import VM 
   4.112 +#
   4.113 +"${VBOX_MANAGER}" list vms | grep SecurityDVM &> /dev/null
   4.114 +if [ ! "${?}" = "0" ]; then
   4.115 +    echo "importing VM: ${OSECVM_IMAGE}"
   4.116 +    "${VBOX_MANAGER}" import "$(cygpath -w "${OSECVM_IMAGE}")" --vsys 0 --vmname SecurityDVM --unit 12 --disk "${VDISK_IMAGE}"
   4.117 +else
   4.118 +    echo "found SecurityDVM already present in VBox reusing it."
   4.119 +    echo "if you want a complete new import please remove the VM first."
   4.120 +    exit 1
   4.121 +fi
   4.122 +
   4.123 +# grab VM storage controller and port 
   4.124 +#
   4.125 +VDISK_SETUP=$("${VBOX_MANAGER}" showvminfo SecurityDVM | grep SecurityDVM.vmdk | cut -d ':' -f 1 | tr '(),' '   ')
   4.126 +VDISK_CONTROLLER=$(echo ${VDISK_SETUP} | gawk '{print $1;}')
   4.127 +VDISK_PORT=$(echo ${VDISK_SETUP} | gawk '{print $2;}')
   4.128 +VDISK_DEVICE=$(echo ${VDISK_SETUP} | gawk '{print $3;}')
   4.129 +if [ -z "${VDISK_CONTROLLER}" ]; then
   4.130 +    echo "unable to grab virtual disk controller in VM."
   4.131 +    echo "this shouldn't happen. It's a bug."
   4.132 +    exit 1
   4.133 +fi
   4.134 +
   4.135 +# detach disk image
   4.136 +#
   4.137 +echo "detaching disk image ..."
   4.138 +"${VBOX_MANAGER}" storageattach SecurityDVM --storagectl ${VDISK_CONTROLLER} --port ${VDISK_PORT} --medium none
   4.139 +
   4.140 +# turn disk image into writethrough
   4.141 +#
   4.142 +echo "turning disk image into writetrough ..."
   4.143 +"${VBOX_MANAGER}" storageattach SecurityDVM --storagectl ${VDISK_CONTROLLER} --port ${VDISK_PORT} --device ${VDISK_DEVICE} --type hdd --mtype writethrough --medium "${VDISK_IMAGE}" 
   4.144 +
   4.145 +# detach disk image
   4.146 +#
   4.147 +echo "detaching disk image ..."
   4.148 +"${VBOX_MANAGER}" storageattach SecurityDVM --storagectl ${VDISK_CONTROLLER} --port ${VDISK_PORT} --medium none
   4.149 +
   4.150 +# immutablize disk
   4.151 +#
   4.152 +echo "reattach immutable disk image ..."
   4.153 +"${VBOX_MANAGER}" storageattach SecurityDVM --storagectl ${VDISK_CONTROLLER} --port ${VDISK_PORT} --device ${VDISK_DEVICE} --type hdd --mtype immutable --medium "${VDISK_IMAGE}"
   4.154 +
   4.155 +echo "imported initial OsecVM.ova image"
   4.156 +
   4.157 +"${VBOX_MANAGER}" list vms
   4.158 +
   4.159 +echo "starting OpenSecurity service..."
   4.160 +net start "OpenSecurity Service"
   4.161 +echo "OpenSecurity service started"
   4.162 +
     5.1 --- a/OpenSecurity/bin/opensecurity_service.pyw	Fri Mar 07 14:32:12 2014 +0100
     5.2 +++ b/OpenSecurity/bin/opensecurity_service.pyw	Mon Mar 10 13:01:08 2014 +0100
     5.3 @@ -82,7 +82,10 @@
     5.4          # the REST server from a distance ...
     5.5          #
     5.6          # TODO: find a better secure way to do that
     5.7 -        r = urllib2.urlopen('http://localhost:8080/terminate', timeout=1)
     5.8 +        try:
     5.9 +            r = urllib2.urlopen('http://localhost:8080/terminate', timeout=1)
    5.10 +        except:
    5.11 +            pass
    5.12  
    5.13          win32event.SetEvent(self.hWaitStop)
    5.14          self.log('OpenSecurity Service stopped...\n') 
     6.1 --- a/OpenSecurity/bin/opensecurityd.pyw	Fri Mar 07 14:32:12 2014 +0100
     6.2 +++ b/OpenSecurity/bin/opensecurityd.pyw	Mon Mar 10 13:01:08 2014 +0100
     6.3 @@ -36,12 +36,13 @@
     6.4  import os.path
     6.5  import subprocess
     6.6  import sys
     6.7 +import tempfile
     6.8  import web
     6.9 -from cygwin import Cygwin
    6.10  
    6.11  import vmmanager
    6.12  
    6.13  # local
    6.14 +from cygwin import Cygwin
    6.15  from environment import Environment
    6.16  from opensecurity_util import logger
    6.17  
    6.18 @@ -55,6 +56,8 @@
    6.19  """All the URLs we know mapping to class handler"""
    6.20  opensecurity_urls = (
    6.21      '/browsing',                        'os_browsing',          # http://localhost:8080/browsing                                GET
    6.22 +    '/fetch_initial_image',             'os_fetch_image',       # http://localhost:8080/fetch_initial_image                     GET
    6.23 +    '/init',                            'os_init',              # http://localhost:8080/init                                    GET
    6.24      '/sdvms',                           'os_sdvms',             # http://localhost:8080/sdvms                                   GET, PUT
    6.25      '/sdvms/(.*)/application/(.*)',     'os_sdvm_application',  # http://localhost:8080/sdvms/[VMNAME]/application/[COMMAND]    GET
    6.26      '/sdvms/(.*)/ip',                   'os_sdvm_ip',           # http://localhost:8080/sdvms/[VMNAME]/ip                       GET
    6.27 @@ -96,6 +99,52 @@
    6.28              raise web.internalerror()
    6.29  
    6.30         
    6.31 +class os_fetch_image:
    6.32 +    """OpenSecurity '/fetch_initial_image' handler
    6.33 +    
    6.34 +    - GET: fetch the initial image from the X-Net Servers
    6.35 +            The initial image is stored in the
    6.36 +            Virtual Box default machine path.
    6.37 +            The result to this call is a temprary file
    6.38 +            which shows the progress (or error state)
    6.39 +            of this call.
    6.40 +    """
    6.41 +    
    6.42 +    def GET(self):
    6.43 +        
    6.44 +        log_call(web.ctx.environ)
    6.45 +        global gvm_mgr
    6.46 +
    6.47 +        trace_file_name = os.path.join(tempfile.gettempdir(), 'OpenSecurity_fetch_image.log')
    6.48 +        trace_file = open(trace_file_name, 'w+')
    6.49 +
    6.50 +        machine_folder = Cygwin.cygPath(gvm_mgr.getMachineFolder()) 
    6.51 +        download_initial_image_script = '/OpenSecurity/bin/download_initial_image.sh \'' + machine_folder + '\''
    6.52 +        Cygwin.bashExecute(download_initial_image_script, wait_return = False, stdout = trace_file, stderr = trace_file) 
    6.53 +
    6.54 +        return trace_file_name
    6.55 +
    6.56 +
    6.57 +class os_init:
    6.58 +    """OpenSecurity '/init' handler
    6.59 +    
    6.60 +    - GET: Do initial import of OsecVM.ova
    6.61 +    """
    6.62 +    
    6.63 +    def GET(self):
    6.64 +        log_call(web.ctx.environ)
    6.65 +        global gvm_mgr
    6.66 +
    6.67 +        trace_file_name = os.path.join(tempfile.gettempdir(), 'OpenSecurity_initial_import.log')
    6.68 +        trace_file = open(trace_file_name, 'w+')
    6.69 +
    6.70 +        vm_image = Cygwin.cygPath(gvm_mgr.getMachineFolder()) + '/OsecVM.ova'
    6.71 +        initial_import_script = '/OpenSecurity/bin/initial_vm.sh \'' + vm_image + '\''
    6.72 +        Cygwin.bashExecute(initial_import_script, wait_return = False, stdout = trace_file, stderr = trace_file) 
    6.73 +
    6.74 +        return trace_file_name
    6.75 +
    6.76 +
    6.77  class os_root:
    6.78      """OpenSecurity '/' handler
    6.79      
    6.80 @@ -107,7 +156,8 @@
    6.81          global gvm_mgr
    6.82          res = "'os_server': { "
    6.83          res += "'version': '" + __version__ + "', "
    6.84 -        res += "'machine_folder': '" + gvm_mgr.machineFolder + "' "
    6.85 +        res += "'virtual box systemproperties': '" + str(gvm_mgr.systemProperties) + "', "
    6.86 +        res += "'current temporary folder': '" + tempfile.gettempdir() + "' "
    6.87          res += "}"
    6.88          return res
    6.89  
    6.90 @@ -141,7 +191,8 @@
    6.91          global gvm_mgr
    6.92          command = '/' + command
    6.93          result = Cygwin.sshExecuteX11(command, gvm_mgr.getHostOnlyIP(name), 'osecuser', Cygwin.cygPath(gvm_mgr.getMachineFolder()) + '/' + name + '/dvm_key'  )
    6.94 -        return result
    6.95 +        self.poweroffVM(name)
    6.96 +        return gvm_mgr.removeVM(name)
    6.97      
    6.98  
    6.99  class os_sdvm_ip:
   6.100 @@ -229,6 +280,7 @@
   6.101      def GET(self):
   6.102          log_call(web.ctx.environ)
   6.103          global gvm_mgr
   6.104 +        gvm_mgr.stop()
   6.105          gvm_mgr.cleanup()
   6.106          sys.exit(0)
   6.107          return None
     7.1 --- a/OpenSecurity/bin/vmmanager.pyw	Fri Mar 07 14:32:12 2014 +0100
     7.2 +++ b/OpenSecurity/bin/vmmanager.pyw	Mon Mar 10 13:01:08 2014 +0100
     7.3 @@ -1,672 +1,681 @@
     7.4 -'''
     7.5 -Created on Nov 19, 2013
     7.6 -
     7.7 -@author: BarthaM
     7.8 -'''
     7.9 -import os
    7.10 -import os.path
    7.11 -from subprocess import Popen, PIPE, call, STARTUPINFO, _subprocess
    7.12 -import sys
    7.13 -import re
    7.14 -
    7.15 -from cygwin import Cygwin
    7.16 -from environment import Environment
    7.17 -import threading
    7.18 -import time
    7.19 -import string
    7.20 -
    7.21 -import shutil
    7.22 -import stat
    7.23 -import tempfile
    7.24 -from opensecurity_util import logger, setupLogger, OpenSecurityException
    7.25 -import ctypes
    7.26 -import itertools
    7.27 -import _winreg
    7.28 -DEBUG = True
    7.29 -
    7.30 -class VMManagerException(Exception):
    7.31 -    def __init__(self, value):
    7.32 -        self.value = value
    7.33 -    def __str__(self):
    7.34 -        return repr(self.value)
    7.35 -
    7.36 -class USBFilter:
    7.37 -    vendorid = ""
    7.38 -    productid = ""
    7.39 -    revision = ""
    7.40 -    
    7.41 -    def __init__(self, vendorid, productid, revision):
    7.42 -        self.vendorid = vendorid.lower()
    7.43 -        self.productid = productid.lower()
    7.44 -        self.revision = revision.lower()
    7.45 -        return
    7.46 -    
    7.47 -    def __eq__(self, other):
    7.48 -        return self.vendorid == other.vendorid and self.productid == other.productid and self.revision == other.revision
    7.49 -    
    7.50 -    def __hash__(self):
    7.51 -        return hash(self.vendorid) ^ hash(self.productid) ^ hash(self.revision)
    7.52 -    
    7.53 -    def __repr__(self):
    7.54 -        return "VendorId = \'" + str(self.vendorid) + "\' ProductId = \'" + str(self.productid) + "\' Revision = \'" + str(self.revision) + "\'"
    7.55 -    
    7.56 -    #def __getitem__(self, item):
    7.57 -    #    return self.coords[item]
    7.58 - 
    7.59 -class VMManager(object):
    7.60 -    vmRootName = "SecurityDVM"
    7.61 -    systemProperties = None
    7.62 -    _instance = None
    7.63 -    machineFolder = ''
    7.64 -    rsdHandler = None
    7.65 -    
    7.66 -    def __init__(self):
    7.67 -        self.systemProperties = self.getSystemProperties()
    7.68 -        self.machineFolder = self.systemProperties["Default machine folder"]
    7.69 -        self.cleanup()
    7.70 -        self.rsdHandler = DeviceHandler(self)
    7.71 -        self.rsdHandler.start()
    7.72 -        return
    7.73 -    
    7.74 -    @staticmethod
    7.75 -    def getInstance():
    7.76 -        if VMManager._instance == None:
    7.77 -            VMManager._instance = VMManager()
    7.78 -        return VMManager._instance
    7.79 -    
    7.80 -    def cleanup(self):
    7.81 -        if self.rsdHandler != None:
    7.82 -            self.rsdHandler.stop()
    7.83 -            self.rsdHandler.join()
    7.84 -        drives = self.getNetworkDrives()
    7.85 -        for drive in drives.keys():
    7.86 -            self.unmapNetworkDrive(drive)
    7.87 -        for vm in self.listSDVM():
    7.88 -            self.poweroffVM(vm)
    7.89 -            self.removeVM(vm)
    7.90 -        
    7.91 -    # return hosty system properties
    7.92 -    def getSystemProperties(self):
    7.93 -        result = checkResult(Cygwin.vboxExecute('list systemproperties'))
    7.94 -        if result[1]=='':
    7.95 -            return None
    7.96 -        props = dict((k.strip(),v.strip().strip('"')) for k,v in (line.split(':', 1) for line in result[1].strip().splitlines()))
    7.97 -        return props
    7.98 -    
    7.99 -    # return the folder containing the guest VMs     
   7.100 -    def getMachineFolder(self):
   7.101 -        return self.machineFolder
   7.102 -
   7.103 -    # list all existing VMs registered with VBox
   7.104 -    def listVM(self):
   7.105 -        result = checkResult(Cygwin.vboxExecute('list vms'))[1]
   7.106 -        vms = list(k.strip().strip('"') for k,_ in (line.split(' ') for line in result.splitlines()))
   7.107 -        return vms
   7.108 -    
   7.109 -    # list running VMs
   7.110 -    def listRunningVMS(self):
   7.111 -        result = checkResult(Cygwin.vboxExecute('list runningvms'))[1]
   7.112 -        vms = list(k.strip().strip('"') for k,_ in (line.split(' ') for line in result.splitlines()))
   7.113 -        return vms
   7.114 -    
   7.115 -    # list existing SDVMs
   7.116 -    def listSDVM(self):
   7.117 -        vms = self.listVM()
   7.118 -        svdms = []
   7.119 -        for vm in vms:
   7.120 -            if vm.startswith(self.vmRootName) and vm != self.vmRootName:
   7.121 -                svdms.append(vm)
   7.122 -        return svdms
   7.123 -    
   7.124 -    # generate valid (not already existing SDVM name). necessary for creating a new VM
   7.125 -    def generateSDVMName(self):
   7.126 -        vms = self.listVM()
   7.127 -        for i in range(0,999):
   7.128 -            if(not self.vmRootName+str(i) in vms):
   7.129 -                return self.vmRootName+str(i)
   7.130 -        return ''
   7.131 -    
   7.132 -    # check if the device is mass storage type
   7.133 -    @staticmethod
   7.134 -    def isMassStorageDevice(device):
   7.135 -        keyname = 'SYSTEM\CurrentControlSet\Enum\USB' + '\VID_' + device.vendorid+'&'+'PID_'+ device.productid
   7.136 -        key = _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE, keyname)
   7.137 -        #subkeys = _winreg.QueryInfoKey(key)[0]
   7.138 -        #for i in range(0, subkeys):
   7.139 -        #    print _winreg.EnumKey(key, i)     
   7.140 -        devinfokeyname = _winreg.EnumKey(key, 0)
   7.141 -        _winreg.CloseKey(key)
   7.142 -
   7.143 -        devinfokey = _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE, keyname+'\\'+devinfokeyname)
   7.144 -        value = _winreg.QueryValueEx(devinfokey, 'SERVICE')[0]
   7.145 -        _winreg.CloseKey(devinfokey)
   7.146 -        
   7.147 -        return 'USBSTOR' in value
   7.148 -    
   7.149 -    # return the RSDs connected to the host
   7.150 -    @staticmethod
   7.151 -    def getConnectedRSDS():
   7.152 -        results = checkResult(Cygwin.vboxExecute('list usbhost'))[1]
   7.153 -        results = results.split('Host USB Devices:')[1].strip()
   7.154 -        
   7.155 -        items = list( "UUID:"+result for result in results.split('UUID:') if result != '')
   7.156 -        rsds = dict()   
   7.157 -        for item in items:
   7.158 -            props = dict()
   7.159 -            for line in item.splitlines():
   7.160 -                if line != "":         
   7.161 -                    k,v = line[:line.index(':')].strip(), line[line.index(':')+1:].strip()
   7.162 -                    props[k] = v
   7.163 -            
   7.164 -            #if 'Product' in props.keys() and props['Product'] == 'Mass Storage':
   7.165 -            
   7.166 -            usb_filter = USBFilter( re.search(r"\((?P<vid>[0-9A-Fa-f]+)\)", props['VendorId']).groupdict()['vid'], 
   7.167 -                                    re.search(r"\((?P<pid>[0-9A-Fa-f]+)\)", props['ProductId']).groupdict()['pid'],
   7.168 -                                    re.search(r"\((?P<rev>[0-9A-Fa-f]+)\)", props['Revision']).groupdict()['rev'] )
   7.169 -            if VMManager.isMassStorageDevice(usb_filter):
   7.170 -                rsds[props['UUID']] = usb_filter;
   7.171 -                logger.debug(usb_filter)
   7.172 -        return rsds
   7.173 -    
   7.174 -    # return the RSDs attached to all existing SDVMs
   7.175 -    def getAttachedRSDs(self):
   7.176 -        vms = self.listSDVM()
   7.177 -        attached_devices = dict()
   7.178 -        for vm in vms:
   7.179 -            rsd_filter = self.getUSBFilter(vm)
   7.180 -            if rsd_filter != None:
   7.181 -                attached_devices[vm] = rsd_filter
   7.182 -        return attached_devices
   7.183 -    
   7.184 -    # configures hostonly networking and DHCP server. requires admin rights
   7.185 -    def configureHostNetworking(self):
   7.186 -        #cmd = 'vboxmanage list hostonlyifs'
   7.187 -        #Cygwin.vboxExecute(cmd)
   7.188 -        #cmd = 'vboxmanage hostonlyif remove \"VirtualBox Host-Only Ethernet Adapter\"'
   7.189 -        #Cygwin.vboxExecute(cmd)
   7.190 -        #cmd = 'vboxmanage hostonlyif create'
   7.191 -        #Cygwin.vboxExecute(cmd)
   7.192 -        checkResult(Cygwin.vboxExecute('hostonlyif ipconfig \"VirtualBox Host-Only Ethernet Adapter\" --ip 192.168.56.1 --netmask 255.255.255.0'))
   7.193 -        #cmd = 'vboxmanage dhcpserver add'
   7.194 -        #Cygwin.vboxExecute(cmd)
   7.195 -        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'))
   7.196 -    
   7.197 -    #create new virtual machine instance based on template vm named SecurityDVM (\SecurityDVM\SecurityDVM.vmdk)
   7.198 -    def createVM(self, vm_name):
   7.199 -        hostonly_if = self.getHostOnlyIFs()
   7.200 -        checkResult(Cygwin.vboxExecute('createvm --name ' + vm_name + ' --ostype Debian --register'))
   7.201 -        checkResult(Cygwin.vboxExecute('modifyvm ' + vm_name + ' --memory 512 --vram 10 --cpus 1 --usb on --usbehci on --nic1 hostonly --hostonlyadapter1 \"' + hostonly_if['Name'] + '\" --nic2 nat'))
   7.202 -        checkResult(Cygwin.vboxExecute('storagectl ' + vm_name + ' --name SATA --add sata --portcount 2'))
   7.203 -        return
   7.204 -    
   7.205 -    # attach storage image to controller
   7.206 -    def storageAttach(self, vm_name):
   7.207 -        if self.isStorageAttached(vm_name):
   7.208 -            self.storageDetach(vm_name)
   7.209 -        checkResult(Cygwin.vboxExecute('storageattach ' + vm_name + ' --storagectl SATA --port 0 --device 0 --type hdd --medium \"'+ self.machineFolder + '\SecurityDVM\SecurityDVM.vmdk\"'))
   7.210 -    
   7.211 -    # return true if storage is attached 
   7.212 -    def isStorageAttached(self, vm_name):
   7.213 -        info = self.getVMInfo(vm_name)
   7.214 -        return (info['SATA-0-0']!='none')
   7.215 -    
   7.216 -    # detach storage from controller
   7.217 -    def storageDetach(self, vm_name):
   7.218 -        if self.isStorageAttached(vm_name):
   7.219 -            checkResult(Cygwin.vboxExecute('storageattach ' + vm_name + ' --storagectl SATA --port 0 --device 0 --type hdd --medium none'))
   7.220 -    
   7.221 -    def changeStorageType(self, filename, storage_type):
   7.222 -        checkResult(Cygwin.vboxExecute('modifyhd \"' + filename + '\" --type ' + storage_type))
   7.223 -    
   7.224 -    # list storage snaphots for VM
   7.225 -    def updateTemplate(self):
   7.226 -        self.cleanup()
   7.227 -        self.poweroffVM('SecurityDVM')
   7.228 -        self.waitShutdown('SecurityDVM')
   7.229 -        
   7.230 -        # check for updates
   7.231 -        self.genCertificateISO('SecurityDVM')
   7.232 -        self.attachCertificateISO('SecurityDVM')
   7.233 -        
   7.234 -        self.storageDetach('SecurityDVM')
   7.235 -        results = checkResult(Cygwin.vboxExecute('list hdds'))[1]
   7.236 -        results = results.replace('Parent UUID', 'Parent')
   7.237 -        items = list( "UUID:"+result for result in results.split('UUID:') if result != '')
   7.238 -        
   7.239 -        snaps = dict()   
   7.240 -        for item in items:
   7.241 -            props = dict()
   7.242 -            for line in item.splitlines():
   7.243 -                if line != "":         
   7.244 -                    k,v = line[:line.index(':')].strip(), line[line.index(':')+1:].strip()
   7.245 -                    props[k] = v;
   7.246 -            snaps[props['UUID']] = props
   7.247 -        
   7.248 -        
   7.249 -        template_storage = self.machineFolder + '\SecurityDVM\SecurityDVM.vmdk'
   7.250 -        
   7.251 -        # find template uuid
   7.252 -        template_uuid = ''
   7.253 -        for hdd in snaps.values():
   7.254 -            if hdd['Location'] == template_storage:
   7.255 -                template_uuid = hdd['UUID']
   7.256 -        logger.debug('found parent uuid ' + template_uuid)
   7.257 -        
   7.258 -        # remove snapshots 
   7.259 -        for hdd in snaps.values():
   7.260 -            if hdd['Parent'] == template_uuid:
   7.261 -                #template_uuid = hdd['UUID']
   7.262 -                logger.debug('removing snapshot ' + hdd['UUID'])
   7.263 -                checkResult(Cygwin.vboxExecute('closemedium disk {' + hdd['UUID'] + '} --delete'))#[1]
   7.264 -                # parse result 0%...10%...20%...30%...40%...50%...60%...70%...80%...90%...100%
   7.265 -        
   7.266 -        self.changeStorageType(template_storage,'normal')
   7.267 -        self.storageAttach('SecurityDVM')
   7.268 -        self.startVM('SecurityDVM')
   7.269 -        self.waitStartup('SecurityDVM')
   7.270 -        checkResult(Cygwin.sshExecute('"sudo apt-get -y update"', VMManager.getHostOnlyIP('SecurityDVM'), 'osecuser', Cygwin.cygPath(self.machineFolder) + '/' + 'SecurityDVM' + '/dvm_key'))
   7.271 -        checkResult(Cygwin.sshExecute('"sudo apt-get -y upgrade"', VMManager.getHostOnlyIP('SecurityDVM'), 'osecuser', Cygwin.cygPath(self.machineFolder) + '/' + 'SecurityDVM' + '/dvm_key'))
   7.272 -        #self.stopVM('SecurityDVM')
   7.273 -        self.hibernateVM('SecurityDVM')
   7.274 -        self.waitShutdown('SecurityDVM')
   7.275 -        self.storageDetach('SecurityDVM')
   7.276 -        self.changeStorageType(template_storage,'immutable')
   7.277 -        self.storageAttach('SecurityDVM')
   7.278 -        self.rsdHandler = DeviceHandler(self)
   7.279 -        self.rsdHandler.start()
   7.280 -    
   7.281 -    #remove VM from the system. should be used on VMs returned by listSDVMs    
   7.282 -    def removeVM(self, vm_name):
   7.283 -        logger.info('Removing ' + vm_name)
   7.284 -        checkResult(Cygwin.vboxExecute('unregistervm ' + vm_name + ' --delete'))
   7.285 -        machineFolder = Cygwin.cygPath(self.machineFolder)
   7.286 -        checkResult(Cygwin.bashExecute('"/usr/bin/rm -rf ' + machineFolder + '/' + vm_name + '"'))
   7.287 -    
   7.288 -    # start VM
   7.289 -    def startVM(self, vm_name):
   7.290 -        logger.info('Starting ' +  vm_name)
   7.291 -        result = checkResult(Cygwin.vboxExecute('startvm ' + vm_name + ' --type headless' ))
   7.292 -        while 'successfully started' not in result[1]:
   7.293 -            logger.error("Failed to start SDVM: " + vm_name + " retrying")
   7.294 -            time.sleep(1)
   7.295 -            result = checkResult(Cygwin.vboxExecute('startvm ' + vm_name + ' --type headless'))
   7.296 -        return result[0]
   7.297 -    
   7.298 -    # return wether VM is running or not
   7.299 -    def isVMRunning(self, vm_name):
   7.300 -        return vm_name in self.listRunningVMS()    
   7.301 -    
   7.302 -    # stop VM
   7.303 -    def stopVM(self, vm_name):
   7.304 -        logger.info('Sending shutdown signal to ' + vm_name)
   7.305 -        checkResult(Cygwin.sshExecute( '"sudo shutdown -h now"', VMManager.getHostOnlyIP(vm_name), 'osecuser', Cygwin.cygPath(self.machineFolder) + '/' + vm_name + '/dvm_key' ))
   7.306 -    
   7.307 -    # stop VM
   7.308 -    def hibernateVM(self, vm_name):
   7.309 -        logger.info('Sending shutdown signal to ' + vm_name)
   7.310 -        checkResult(Cygwin.sshExecute( '"sudo hibernate-disk&"', VMManager.getHostOnlyIP(vm_name), 'osecuser', Cygwin.cygPath(self.machineFolder) + '/' + vm_name + '/dvm_key', wait_return=False))
   7.311 -            
   7.312 -    # poweroff VM
   7.313 -    def poweroffVM(self, vm_name):
   7.314 -        if not self.isVMRunning(vm_name):
   7.315 -            return
   7.316 -        logger.info('Powering off ' + vm_name)
   7.317 -        return checkResult(Cygwin.vboxExecute('controlvm ' + vm_name + ' poweroff'))
   7.318 -    
   7.319 -    #list the hostonly IFs exposed by the VBox host
   7.320 -    @staticmethod    
   7.321 -    def getHostOnlyIFs():
   7.322 -        result = Cygwin.vboxExecute('list hostonlyifs')[1]
   7.323 -        if result=='':
   7.324 -            return None
   7.325 -        props = dict((k.strip(),v.strip().strip('"')) for k,v in (line.split(':', 1) for line in result.strip().splitlines()))
   7.326 -        return props
   7.327 -    
   7.328 -    # return the hostOnly IP for a running guest or the host
   7.329 -    @staticmethod    
   7.330 -    def getHostOnlyIP(vm_name):
   7.331 -        if vm_name == None:
   7.332 -            logger.info('Gettting hostOnly IP address for Host')
   7.333 -            return VMManager.getHostOnlyIFs()['IPAddress']
   7.334 -        else:
   7.335 -            logger.info('Gettting hostOnly IP address ' + vm_name)
   7.336 -            result = checkResult(Cygwin.vboxExecute('guestproperty get ' + vm_name + ' /VirtualBox/GuestInfo/Net/0/V4/IP'))
   7.337 -            if result=='':
   7.338 -                return None
   7.339 -            result = result[1]
   7.340 -            if result.startswith('No value set!'):
   7.341 -                return None
   7.342 -            return result[result.index(':')+1:].strip()
   7.343 -            
   7.344 -    # attach removable storage device to VM by provision of filter
   7.345 -    def attachRSD(self, vm_name, rsd_filter):
   7.346 -        return checkResult(Cygwin.vboxExecute('usbfilter add 0 --target ' + vm_name + ' --name OpenSecurityRSD --vendorid ' + rsd_filter.vendorid + ' --productid ' + rsd_filter.productid + ' --revision ' + rsd_filter.revision))
   7.347 -    
   7.348 -    # detach removable storage from VM by 
   7.349 -    def detachRSD(self, vm_name):
   7.350 -        return checkResult(Cygwin.vboxExecute('usbfilter remove 0 --target ' + vm_name))
   7.351 -        
   7.352 -    # return the description set for an existing VM
   7.353 -    def getVMInfo(self, vm_name):
   7.354 -        results = checkResult(Cygwin.vboxExecute('showvminfo ' + vm_name + ' --machinereadable'))[1]
   7.355 -        props = dict((k.strip().strip('"'),v.strip().strip('"')) for k,v in (line.split('=', 1) for line in results.splitlines()))
   7.356 -        return props
   7.357 -    
   7.358 -    # return the configured USB filter for an existing VM 
   7.359 -    def getUSBFilter(self, vm_name):
   7.360 -        props = self.getVMInfo(vm_name)
   7.361 -        keys = set(['USBFilterVendorId1', 'USBFilterProductId1', 'USBFilterRevision1'])
   7.362 -        keyset = set(props.keys())
   7.363 -        usb_filter = None
   7.364 -        if keyset.issuperset(keys):
   7.365 -            usb_filter = USBFilter(props['USBFilterVendorId1'], props['USBFilterProductId1'], props['USBFilterRevision1'])
   7.366 -        return usb_filter
   7.367 -    
   7.368 -    #generates ISO containing authorized_keys for use with guest VM
   7.369 -    def genCertificateISO(self, vm_name):
   7.370 -        machineFolder = Cygwin.cygPath(self.machineFolder)
   7.371 -        # remove .ssh folder if exists
   7.372 -        checkResult(Cygwin.bashExecute('\"/usr/bin/rm -rf \\\"' + machineFolder + '/' + vm_name + '/.ssh\\\"\"'))
   7.373 -        # remove .ssh folder if exists
   7.374 -        checkResult(Cygwin.bashExecute('\"/usr/bin/rm -rf \\\"' + machineFolder + '/' + vm_name + '/dvm_key\\\"\"'))
   7.375 -        # create .ssh folder in vm_name
   7.376 -        checkResult(Cygwin.bashExecute('\"/usr/bin/mkdir -p \\\"' + machineFolder + '/' + vm_name + '/.ssh\\\"\"'))
   7.377 -        # generate dvm_key pair in vm_name / .ssh     
   7.378 -        checkResult(Cygwin.bashExecute('\"/usr/bin/ssh-keygen -q -t rsa -N \\"\\" -C \\\"' + vm_name + '\\\" -f \\\"' + machineFolder + '/' + vm_name + '/.ssh/dvm_key\\\"\"'))
   7.379 -        # move out private key
   7.380 -        checkResult(Cygwin.bashExecute('\"/usr/bin/mv \\\"' + machineFolder + '/' + vm_name + '/.ssh/dvm_key\\\" \\\"' + machineFolder + '/' + vm_name + '\\\"'))
   7.381 -        # set permissions for private key
   7.382 -        checkResult(Cygwin.bashExecute('\"/usr/bin/chmod 500 \\\"' + machineFolder + '/' + vm_name + '/dvm_key\\\"\"'))
   7.383 -        # rename public key to authorized_keys
   7.384 -        checkResult(Cygwin.bashExecute('\"/usr/bin/mv \\\"' + machineFolder + '/' + vm_name + '/.ssh/dvm_key.pub\\\" \\\"' + machineFolder + '/' + vm_name + '/.ssh/authorized_keys\\\"'))
   7.385 -        # set permissions for authorized_keys
   7.386 -        checkResult(Cygwin.bashExecute('\"/usr/bin/chmod 500 \\\"' + machineFolder + '/' + vm_name + '/.ssh/authorized_keys\\\"\"'))
   7.387 -        # generate iso image with .ssh/authorized keys
   7.388 -        checkResult(Cygwin.bashExecute('\"/usr/bin/genisoimage -J -R -o \\\"' + machineFolder + '/' + vm_name + '/'+ vm_name + '.iso\\\" \\\"' + machineFolder + '/' + vm_name + '/.ssh\\\"\"'))
   7.389 -    
   7.390 -    # attaches generated ssh public cert to guest vm
   7.391 -    def attachCertificateISO(self, vm_name):
   7.392 -        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\"'))
   7.393 -        return result
   7.394 -    
   7.395 -    # wait for machine to come up
   7.396 -    def waitStartup(self, vm_name, timeout_ms = 30000):
   7.397 -        checkResult(Cygwin.vboxExecute('guestproperty wait ' + vm_name + ' SDVMStarted --timeout ' + str(timeout_ms) + ' --fail-on-timeout'))
   7.398 -        return VMManager.getHostOnlyIP(vm_name)
   7.399 -    
   7.400 -    # wait for machine to shutdown
   7.401 -    def waitShutdown(self, vm_name):
   7.402 -        while vm_name in self.listRunningVMS():
   7.403 -            time.sleep(1)
   7.404 -        return
   7.405 -        
   7.406 -    # handles browsing request    
   7.407 -    def handleBrowsingRequest(self):
   7.408 -        handler = BrowsingHandler(self)
   7.409 -        handler.start()
   7.410 -        return 'ok'
   7.411 -    
   7.412 -    #Small function to check the availability of network resource.
   7.413 -    #def isAvailable(self, path):
   7.414 -        #return os.path.exists(path)
   7.415 -        #result = Cygwin.cmdExecute('IF EXIST "' + path + '" echo YES')
   7.416 -        #return string.find(result[1], 'YES',)
   7.417 -    
   7.418 -    #Small function to check if the mention location is a directory
   7.419 -    def isDirectory(self, path):
   7.420 -        result = checkResult(Cygwin.cmdExecute('dir ' + path + ' | FIND ".."'))
   7.421 -        return string.find(result[1], 'DIR',)
   7.422 -
   7.423 -    def mapNetworkDrive(self, drive, networkPath, user, password):
   7.424 -        self.unmapNetworkDrive(drive)
   7.425 -        #Check for drive availability
   7.426 -        if os.path.exists(drive):
   7.427 -            logger.error("Drive letter is already in use: " + drive)
   7.428 -            return -1
   7.429 -        #Check for network resource availability
   7.430 -        retry = 5
   7.431 -        while not os.path.exists(networkPath):
   7.432 -            time.sleep(1)
   7.433 -            if retry == 0:
   7.434 -                return -1
   7.435 -            logger.info("Path not accessible: " + networkPath + " retrying")
   7.436 -            retry-=1
   7.437 -            #return -1
   7.438 -    
   7.439 -        command = 'USE ' + drive + ' ' + networkPath + ' /PERSISTENT:NO'
   7.440 -        if user != None:
   7.441 -            command += ' ' + password + ' /User' + user
   7.442 -    
   7.443 -        #TODO: Execute 'NET USE' command with authentication
   7.444 -        result = checkResult(Cygwin.execute('C:\\Windows\\system32\\net.exe', command))
   7.445 -        if string.find(result[1], 'successfully',) == -1:
   7.446 -            logger.error("Failed: NET " + command)
   7.447 -            return -1
   7.448 -        return 1
   7.449 -    
   7.450 -    def unmapNetworkDrive(self, drive):
   7.451 -        drives = self.getNetworkDrives()
   7.452 -        if drive not in drives.keys():
   7.453 -            return 1 
   7.454 -        result = checkResult(Cygwin.execute('C:\\Windows\\system32\\net.exe', 'USE ' + drive + ' /DELETE /YES'))
   7.455 -        if string.find(str(result[1]), 'successfully',) == -1:
   7.456 -            logger.error(result[2])
   7.457 -            return -1
   7.458 -        return 1
   7.459 -    
   7.460 -    def getNetworkDrives(self):
   7.461 -        ip = VMManager.getHostOnlyIP(None)
   7.462 -        ip = ip[:ip.rindex('.')]
   7.463 -        drives = dict()    
   7.464 -        result = checkResult(Cygwin.execute('C:\\Windows\\system32\\net.exe', 'USE'))
   7.465 -        for line in result[1].splitlines():
   7.466 -            if ip in line:
   7.467 -                parts = line.split()
   7.468 -                drives[parts[1]] = parts[2]
   7.469 -        return drives
   7.470 -            
   7.471 -    def genNetworkDrive(self):
   7.472 -        network_drives = self.getNetworkDrives()
   7.473 -        logical_drives = VMManager.getLogicalDrives()
   7.474 -        drives = list(map(chr, range(68, 91)))  
   7.475 -        for drive in drives:
   7.476 -            if drive+':' not in network_drives and drive not in logical_drives:
   7.477 -                return drive+':'
   7.478 -
   7.479 -    def getNetworkDrive(self, vm_name):
   7.480 -        ip = self.getHostOnlyIP(vm_name)
   7.481 -        result = checkResult(Cygwin.execute('C:\\Windows\\system32\\net.exe', 'USE'))
   7.482 -        for line in result[1].splitlines():
   7.483 -            if line != None and ip in line:
   7.484 -                parts = line.split()
   7.485 -                return parts[0]
   7.486 -    @staticmethod
   7.487 -    def getLogicalDrives():
   7.488 -        drive_bitmask = ctypes.cdll.kernel32.GetLogicalDrives()
   7.489 -        return list(itertools.compress(string.ascii_uppercase,  map(lambda x:ord(x) - ord('0'), bin(drive_bitmask)[:1:-1])))
   7.490 -    
   7.491 -    @staticmethod
   7.492 -    def getDriveType(drive):
   7.493 -        return ctypes.cdll.kernel32.GetDriveTypeW(u"%s:\\"%drive)
   7.494 -    
   7.495 -    @staticmethod
   7.496 -    def getVolumeInfo(drive):
   7.497 -        volumeNameBuffer = ctypes.create_unicode_buffer(1024)
   7.498 -        fileSystemNameBuffer = ctypes.create_unicode_buffer(1024)
   7.499 -        serial_number = None
   7.500 -        max_component_length = None
   7.501 -        file_system_flags = None
   7.502 -        
   7.503 -        rc = ctypes.cdll.kernel32.GetVolumeInformationW(
   7.504 -            #ctypes.c_wchar_p("F:\\"),
   7.505 -            u"%s:\\"%drive,
   7.506 -            volumeNameBuffer,
   7.507 -            ctypes.sizeof(volumeNameBuffer),
   7.508 -            serial_number,
   7.509 -            max_component_length,
   7.510 -            file_system_flags,
   7.511 -            fileSystemNameBuffer,
   7.512 -            ctypes.sizeof(fileSystemNameBuffer)
   7.513 -        )
   7.514 -        
   7.515 -        return volumeNameBuffer.value, fileSystemNameBuffer.value
   7.516 -
   7.517 -def checkResult(result):
   7.518 -    if result[0] != 0:
   7.519 -        logger.error('Command failed:' + ''.join(result[2]))
   7.520 -        raise OpenSecurityException('Command failed:' + ''.join(result[2]))
   7.521 -    return result
   7.522 -
   7.523 -# handles browsing request                    
   7.524 -class BrowsingHandler(threading.Thread):
   7.525 -    vmm = None
   7.526 -    def __init__(self, vmmanager):
   7.527 -        threading.Thread.__init__(self)
   7.528 -        self.vmm = vmmanager
   7.529 -     
   7.530 -    def run(self):
   7.531 -        try:
   7.532 -            new_sdvm = self.vmm.generateSDVMName()
   7.533 -            self.vmm.createVM(new_sdvm)
   7.534 -            self.vmm.storageAttach(new_sdvm)
   7.535 -            self.vmm.genCertificateISO(new_sdvm)
   7.536 -            self.vmm.attachCertificateISO(new_sdvm)
   7.537 -            self.vmm.startVM(new_sdvm)
   7.538 -            new_ip = self.vmm.waitStartup(new_sdvm)
   7.539 -            drive = self.vmm.genNetworkDrive()
   7.540 -            if new_ip != None:
   7.541 -                self.vmm.mapNetworkDrive(drive, '\\\\' + new_ip + '\\Download', None, None)
   7.542 -            result = checkResult(Cygwin.sshExecuteX11('/usr/bin/iceweasel', new_ip, 'osecuser', Cygwin.cygPath(self.vmm.getMachineFolder()) + '/' + new_sdvm + '/dvm_key'))
   7.543 -        except:
   7.544 -            logger.error("BrowsingHandler failed. Cleaning up")
   7.545 -            
   7.546 -        self.vmm.unmapNetworkDrive(drive)
   7.547 -        self.vmm.poweroffVM(new_sdvm)
   7.548 -        self.vmm.removeVM(new_sdvm)
   7.549 -                
   7.550 -class DeviceHandler(threading.Thread): 
   7.551 -    vmm = None
   7.552 -    #handleDeviceChangeLock = threading.Lock()
   7.553 -    attachedRSDs = None  
   7.554 -    connectedRSDs = None
   7.555 -    running = True
   7.556 -    def __init__(self, vmmanger): 
   7.557 -        threading.Thread.__init__(self)
   7.558 -        self.vmm = vmmanger
   7.559 - 
   7.560 -    def stop(self):
   7.561 -        self.running = False
   7.562 -        
   7.563 -    def run(self):
   7.564 -        self.connectedRSDs = dict()
   7.565 -        self.attachedRSDs = self.vmm.getAttachedRSDs()
   7.566 -        while self.running:
   7.567 -            tmp_rsds = self.vmm.getConnectedRSDS()
   7.568 -            if tmp_rsds.keys() == self.connectedRSDs.keys():
   7.569 -                logger.debug("Nothing's changed. sleep(3)")
   7.570 -                time.sleep(3)
   7.571 -                continue
   7.572 -            
   7.573 -            logger.info("Something's changed")          
   7.574 -            self.connectedRSDs = tmp_rsds
   7.575 -            self.attachedRSDs = self.vmm.getAttachedRSDs()
   7.576 -            
   7.577 -            for vm_name in self.attachedRSDs.keys():
   7.578 -                if self.attachedRSDs[vm_name] not in self.connectedRSDs.values():
   7.579 -                    drive = self.vmm.getNetworkDrive(vm_name)
   7.580 -                    self.vmm.unmapNetworkDrive(drive)
   7.581 -                    #self.stopVM(vm_name)
   7.582 -                    self.vmm.detachRSD(vm_name)
   7.583 -                    self.vmm.poweroffVM(vm_name)
   7.584 -                    self.vmm.removeVM(vm_name)
   7.585 -            #create new vm for attached device if any
   7.586 -            self.attachedRSDs = self.vmm.getAttachedRSDs()
   7.587 -            self.connectedRSDs = self.vmm.getConnectedRSDS()
   7.588 -            
   7.589 -            new_ip = None
   7.590 -            for connected_device in self.connectedRSDs.values():
   7.591 -                if (self.attachedRSDs and False) or (connected_device not in self.attachedRSDs.values()):
   7.592 -                    new_sdvm = self.vmm.generateSDVMName()
   7.593 -                    self.vmm.createVM(new_sdvm)
   7.594 -                    self.vmm.storageAttach(new_sdvm)
   7.595 -                    self.vmm.attachRSD(new_sdvm, connected_device)
   7.596 -                    self.vmm.startVM(new_sdvm)
   7.597 -                    new_ip = self.vmm.waitStartup(new_sdvm)
   7.598 -                    drive = self.vmm.genNetworkDrive()
   7.599 -                    if new_ip != None:
   7.600 -                        self.vmm.mapNetworkDrive(drive, '\\\\' + new_ip + '\\USB', None, None)
   7.601 -
   7.602 -if __name__ == '__main__':
   7.603 -    #man = VMManager.getInstance()
   7.604 -    #man.listVM()
   7.605 -    #print man.getConnectedRSDs()
   7.606 -    #print man.getNetworkDrives()
   7.607 -    #man.genNetworkDrive()
   7.608 -    #drive_bitmask = ctypes.cdll.kernel32.GetLogicalDrives()
   7.609 -    #print list(itertools.compress(string.ascii_uppercase,  map(lambda x:ord(x) - ord('0'), bin(drive_bitmask)[:1:-1])))
   7.610 -    #print list(map(chr, range(68, 91))) 
   7.611 -    #print Cygwin.getRegEntry('SYSTEM\CurrentControlSet\Enum\USB', 'VID_1058&PID_0704')[0]
   7.612 -    #devices = VMManager.getConnectedRSDS()
   7.613 -    #print devices
   7.614 -    
   7.615 -    drives = VMManager.getLogicalDrives()
   7.616 -    print drives
   7.617 -    print VMManager.getDriveType("E")
   7.618 -    print VMManager.getVolumeInfo("E")
   7.619 -    #for device in devices.values():
   7.620 -    #    #print device
   7.621 -    #    if VMManager.isMassStorageDevice(device):
   7.622 -    #        print device
   7.623 -        
   7.624 -    
   7.625 -    
   7.626 -    #time.sleep(-1)
   7.627 -    #man.listVM()
   7.628 -    #man.listVM()
   7.629 -    #man.listVM()
   7.630 -    #man.listVM()
   7.631 -    #man.genCertificateISO('SecurityDVM0')
   7.632 -    #man.guestExecute('SecurityDVM0', '/bin/ls -la')
   7.633 -    #logger = setupLogger('VMManager')
   7.634 -    #c = Cygwin()
   7.635 -    
   7.636 -    #man.sshExecute('/bin/ls -la', 'SecurityDVM0')
   7.637 -    #man.sshExecuteX11('/usr/bin/iceweasel', 'SecurityDVM0')
   7.638 -    #man.removeVM('SecurityDVM0')
   7.639 -    #man.netUse('192.168.56.134', 'USB\\')
   7.640 -    #ip = '192.168.56.139'
   7.641 -    
   7.642 -    #man.cygwin_path = 'c:\\cygwin64\\bin\\'
   7.643 -    #man.handleDeviceChange()
   7.644 -    #print man.listSDVM()
   7.645 -    #man.configureHostNetworking()
   7.646 -    #new_vm = man.generateSDVMName()
   7.647 -    #man.createVM(new_vm)
   7.648 -    
   7.649 -    #print Cygwin.cmd()
   7.650 -    #man.isAvailable('c:')
   7.651 -    #ip = man.getHostOnlyIP('SecurityDVM0')
   7.652 -    #man.mapNetworkDrive('h:', '\\\\' + ip + '\Download', None, None)
   7.653 -    
   7.654 -    #man.genCertificateISO(new_vm)
   7.655 -    #man.attachCertificateISO(new_vm)
   7.656 -    
   7.657 -    #man.attachCertificateISO(vm_name)
   7.658 -    #man.guestExecute(vm_name, "ls")
   7.659 -    #man.sshGuestX11Execute('SecurityDVM1', '/usr/bin/iceweasel')
   7.660 -    #time.sleep(60)
   7.661 -    #print man.cygwinPath("C:\Users\BarthaM\VirtualBox VMs\SecurityDVM\.ssh\*")
   7.662 -    #man.genCertificateISO('SecurityDVM')
   7.663 -    #man.attachCertificateISO('SecurityDVM')
   7.664 -    #man.isStorageAttached('SecurityDVM')
   7.665 -    #man.guestExecute('SecurityDVM', 'sudo apt-get -y update')
   7.666 -    #man.guestExecute('SecurityDVM', 'sudo apt-get -y upgrade' )
   7.667 -    
   7.668 -    #man.stopVM('SecurityDVM')
   7.669 -    #man.storageDetach('SecurityDVM')
   7.670 -    #man.changeStorageType('C:\Users\BarthaM\VirtualBox VMs\SecurityDVM\SecurityDVM.vmdk','immutable')
   7.671 -    #man.storageAttach('SecurityDVM')
   7.672 -    
   7.673 -    
   7.674 -    #cmd = "c:\\cygwin64\\bin\\bash.exe --login -c \"/bin/ls\""
   7.675 -    #man.execute(cmd)
   7.676 +'''
   7.677 +Created on Nov 19, 2013
   7.678 +
   7.679 +@author: BarthaM
   7.680 +'''
   7.681 +import os
   7.682 +import os.path
   7.683 +from subprocess import Popen, PIPE, call, STARTUPINFO, _subprocess
   7.684 +import sys
   7.685 +import re
   7.686 +
   7.687 +from cygwin import Cygwin
   7.688 +from environment import Environment
   7.689 +import threading
   7.690 +import time
   7.691 +import string
   7.692 +
   7.693 +import shutil
   7.694 +import stat
   7.695 +import tempfile
   7.696 +from opensecurity_util import logger, setupLogger, OpenSecurityException
   7.697 +import ctypes
   7.698 +import itertools
   7.699 +import _winreg
   7.700 +DEBUG = True
   7.701 +
   7.702 +class VMManagerException(Exception):
   7.703 +    def __init__(self, value):
   7.704 +        self.value = value
   7.705 +    def __str__(self):
   7.706 +        return repr(self.value)
   7.707 +
   7.708 +class USBFilter:
   7.709 +    vendorid = ""
   7.710 +    productid = ""
   7.711 +    revision = ""
   7.712 +    
   7.713 +    def __init__(self, vendorid, productid, revision):
   7.714 +        self.vendorid = vendorid.lower()
   7.715 +        self.productid = productid.lower()
   7.716 +        self.revision = revision.lower()
   7.717 +        return
   7.718 +    
   7.719 +    def __eq__(self, other):
   7.720 +        return self.vendorid == other.vendorid and self.productid == other.productid and self.revision == other.revision
   7.721 +    
   7.722 +    def __hash__(self):
   7.723 +        return hash(self.vendorid) ^ hash(self.productid) ^ hash(self.revision)
   7.724 +    
   7.725 +    def __repr__(self):
   7.726 +        return "VendorId = \'" + str(self.vendorid) + "\' ProductId = \'" + str(self.productid) + "\' Revision = \'" + str(self.revision) + "\'"
   7.727 +    
   7.728 +    #def __getitem__(self, item):
   7.729 +    #    return self.coords[item]
   7.730 + 
   7.731 +class VMManager(object):
   7.732 +    vmRootName = "SecurityDVM"
   7.733 +    systemProperties = None
   7.734 +    _instance = None
   7.735 +    machineFolder = ''
   7.736 +    rsdHandler = None
   7.737 +    _running = True
   7.738 +    
   7.739 +    def __init__(self):
   7.740 +        self._running = True
   7.741 +        self.systemProperties = self.getSystemProperties()
   7.742 +        self.machineFolder = self.systemProperties["Default machine folder"]
   7.743 +        self.cleanup()
   7.744 +        self.rsdHandler = DeviceHandler(self)
   7.745 +        self.rsdHandler.start()
   7.746 +        return
   7.747 +    
   7.748 +    @staticmethod
   7.749 +    def getInstance():
   7.750 +        if VMManager._instance == None:
   7.751 +            VMManager._instance = VMManager()
   7.752 +        return VMManager._instance
   7.753 +    
   7.754 +    def cleanup(self):
   7.755 +        if self.rsdHandler != None:
   7.756 +            self.rsdHandler.stop()
   7.757 +            self.rsdHandler.join()
   7.758 +        drives = self.getNetworkDrives()
   7.759 +        for drive in drives.keys():
   7.760 +            self.unmapNetworkDrive(drive)
   7.761 +        for vm in self.listSDVM():
   7.762 +            self.poweroffVM(vm)
   7.763 +            self.removeVM(vm)
   7.764 +        
   7.765 +    # return hosty system properties
   7.766 +    def getSystemProperties(self):
   7.767 +        result = checkResult(Cygwin.vboxExecute('list systemproperties'))
   7.768 +        if result[1]=='':
   7.769 +            return None
   7.770 +        props = dict((k.strip(),v.strip().strip('"')) for k,v in (line.split(':', 1) for line in result[1].strip().splitlines()))
   7.771 +        return props
   7.772 +    
   7.773 +    # return the folder containing the guest VMs     
   7.774 +    def getMachineFolder(self):
   7.775 +        return self.machineFolder
   7.776 +
   7.777 +    # list all existing VMs registered with VBox
   7.778 +    def listVM(self):
   7.779 +        result = checkResult(Cygwin.vboxExecute('list vms'))[1]
   7.780 +        vms = list(k.strip().strip('"') for k,_ in (line.split(' ') for line in result.splitlines()))
   7.781 +        return vms
   7.782 +    
   7.783 +    # list running VMs
   7.784 +    def listRunningVMS(self):
   7.785 +        result = checkResult(Cygwin.vboxExecute('list runningvms'))[1]
   7.786 +        vms = list(k.strip().strip('"') for k,_ in (line.split(' ') for line in result.splitlines()))
   7.787 +        return vms
   7.788 +    
   7.789 +    # list existing SDVMs
   7.790 +    def listSDVM(self):
   7.791 +        vms = self.listVM()
   7.792 +        svdms = []
   7.793 +        for vm in vms:
   7.794 +            if vm.startswith(self.vmRootName) and vm != self.vmRootName:
   7.795 +                svdms.append(vm)
   7.796 +        return svdms
   7.797 +    
   7.798 +    # generate valid (not already existing SDVM name). necessary for creating a new VM
   7.799 +    def generateSDVMName(self):
   7.800 +        vms = self.listVM()
   7.801 +        for i in range(0,999):
   7.802 +            if(not self.vmRootName+str(i) in vms):
   7.803 +                return self.vmRootName+str(i)
   7.804 +        return ''
   7.805 +    
   7.806 +    # check if the device is mass storage type
   7.807 +    @staticmethod
   7.808 +    def isMassStorageDevice(device):
   7.809 +        keyname = 'SYSTEM\CurrentControlSet\Enum\USB' + '\VID_' + device.vendorid+'&'+'PID_'+ device.productid
   7.810 +        key = _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE, keyname)
   7.811 +        #subkeys = _winreg.QueryInfoKey(key)[0]
   7.812 +        #for i in range(0, subkeys):
   7.813 +        #    print _winreg.EnumKey(key, i)     
   7.814 +        devinfokeyname = _winreg.EnumKey(key, 0)
   7.815 +        _winreg.CloseKey(key)
   7.816 +
   7.817 +        devinfokey = _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE, keyname+'\\'+devinfokeyname)
   7.818 +        value = _winreg.QueryValueEx(devinfokey, 'SERVICE')[0]
   7.819 +        _winreg.CloseKey(devinfokey)
   7.820 +        
   7.821 +        return 'USBSTOR' in value
   7.822 +    
   7.823 +    # return the RSDs connected to the host
   7.824 +    @staticmethod
   7.825 +    def getConnectedRSDS():
   7.826 +        results = checkResult(Cygwin.vboxExecute('list usbhost'))[1]
   7.827 +        results = results.split('Host USB Devices:')[1].strip()
   7.828 +        
   7.829 +        items = list( "UUID:"+result for result in results.split('UUID:') if result != '')
   7.830 +        rsds = dict()   
   7.831 +        for item in items:
   7.832 +            props = dict()
   7.833 +            for line in item.splitlines():
   7.834 +                if line != "":         
   7.835 +                    k,v = line[:line.index(':')].strip(), line[line.index(':')+1:].strip()
   7.836 +                    props[k] = v
   7.837 +            
   7.838 +            #if 'Product' in props.keys() and props['Product'] == 'Mass Storage':
   7.839 +            
   7.840 +            usb_filter = USBFilter( re.search(r"\((?P<vid>[0-9A-Fa-f]+)\)", props['VendorId']).groupdict()['vid'], 
   7.841 +                                    re.search(r"\((?P<pid>[0-9A-Fa-f]+)\)", props['ProductId']).groupdict()['pid'],
   7.842 +                                    re.search(r"\((?P<rev>[0-9A-Fa-f]+)\)", props['Revision']).groupdict()['rev'] )
   7.843 +            if VMManager.isMassStorageDevice(usb_filter):
   7.844 +                rsds[props['UUID']] = usb_filter;
   7.845 +                logger.debug(usb_filter)
   7.846 +        return rsds
   7.847 +    
   7.848 +    # return the RSDs attached to all existing SDVMs
   7.849 +    def getAttachedRSDs(self):
   7.850 +        vms = self.listSDVM()
   7.851 +        attached_devices = dict()
   7.852 +        for vm in vms:
   7.853 +            rsd_filter = self.getUSBFilter(vm)
   7.854 +            if rsd_filter != None:
   7.855 +                attached_devices[vm] = rsd_filter
   7.856 +        return attached_devices
   7.857 +    
   7.858 +    # configures hostonly networking and DHCP server. requires admin rights
   7.859 +    def configureHostNetworking(self):
   7.860 +        #cmd = 'vboxmanage list hostonlyifs'
   7.861 +        #Cygwin.vboxExecute(cmd)
   7.862 +        #cmd = 'vboxmanage hostonlyif remove \"VirtualBox Host-Only Ethernet Adapter\"'
   7.863 +        #Cygwin.vboxExecute(cmd)
   7.864 +        #cmd = 'vboxmanage hostonlyif create'
   7.865 +        #Cygwin.vboxExecute(cmd)
   7.866 +        checkResult(Cygwin.vboxExecute('hostonlyif ipconfig \"VirtualBox Host-Only Ethernet Adapter\" --ip 192.168.56.1 --netmask 255.255.255.0'))
   7.867 +        #cmd = 'vboxmanage dhcpserver add'
   7.868 +        #Cygwin.vboxExecute(cmd)
   7.869 +        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'))
   7.870 +    
   7.871 +    #create new virtual machine instance based on template vm named SecurityDVM (\SecurityDVM\SecurityDVM.vmdk)
   7.872 +    def createVM(self, vm_name):
   7.873 +        hostonly_if = self.getHostOnlyIFs()
   7.874 +        checkResult(Cygwin.vboxExecute('createvm --name ' + vm_name + ' --ostype Debian --register'))
   7.875 +        checkResult(Cygwin.vboxExecute('modifyvm ' + vm_name + ' --memory 512 --vram 10 --cpus 1 --usb on --usbehci on --nic1 hostonly --hostonlyadapter1 \"' + hostonly_if['Name'] + '\" --nic2 nat'))
   7.876 +        checkResult(Cygwin.vboxExecute('storagectl ' + vm_name + ' --name SATA --add sata --portcount 2'))
   7.877 +        return
   7.878 +    
   7.879 +    # attach storage image to controller
   7.880 +    def storageAttach(self, vm_name):
   7.881 +        if self.isStorageAttached(vm_name):
   7.882 +            self.storageDetach(vm_name)
   7.883 +        checkResult(Cygwin.vboxExecute('storageattach ' + vm_name + ' --storagectl SATA --port 0 --device 0 --type hdd --medium \"'+ self.machineFolder + '\SecurityDVM\SecurityDVM.vmdk\"'))
   7.884 +    
   7.885 +    # return true if storage is attached 
   7.886 +    def isStorageAttached(self, vm_name):
   7.887 +        info = self.getVMInfo(vm_name)
   7.888 +        return (info['SATA-0-0']!='none')
   7.889 +    
   7.890 +    # detach storage from controller
   7.891 +    def storageDetach(self, vm_name):
   7.892 +        if self.isStorageAttached(vm_name):
   7.893 +            checkResult(Cygwin.vboxExecute('storageattach ' + vm_name + ' --storagectl SATA --port 0 --device 0 --type hdd --medium none'))
   7.894 +    
   7.895 +    def changeStorageType(self, filename, storage_type):
   7.896 +        checkResult(Cygwin.vboxExecute('modifyhd \"' + filename + '\" --type ' + storage_type))
   7.897 +    
   7.898 +    # list storage snaphots for VM
   7.899 +    def updateTemplate(self):
   7.900 +        self.cleanup()
   7.901 +        self.poweroffVM('SecurityDVM')
   7.902 +        self.waitShutdown('SecurityDVM')
   7.903 +        
   7.904 +        # check for updates
   7.905 +        self.genCertificateISO('SecurityDVM')
   7.906 +        self.attachCertificateISO('SecurityDVM')
   7.907 +        
   7.908 +        self.storageDetach('SecurityDVM')
   7.909 +        results = checkResult(Cygwin.vboxExecute('list hdds'))[1]
   7.910 +        results = results.replace('Parent UUID', 'Parent')
   7.911 +        items = list( "UUID:"+result for result in results.split('UUID:') if result != '')
   7.912 +        
   7.913 +        snaps = dict()   
   7.914 +        for item in items:
   7.915 +            props = dict()
   7.916 +            for line in item.splitlines():
   7.917 +                if line != "":         
   7.918 +                    k,v = line[:line.index(':')].strip(), line[line.index(':')+1:].strip()
   7.919 +                    props[k] = v;
   7.920 +            snaps[props['UUID']] = props
   7.921 +        
   7.922 +        
   7.923 +        template_storage = self.machineFolder + '\SecurityDVM\SecurityDVM.vmdk'
   7.924 +        
   7.925 +        # find template uuid
   7.926 +        template_uuid = ''
   7.927 +        for hdd in snaps.values():
   7.928 +            if hdd['Location'] == template_storage:
   7.929 +                template_uuid = hdd['UUID']
   7.930 +        logger.debug('found parent uuid ' + template_uuid)
   7.931 +        
   7.932 +        # remove snapshots 
   7.933 +        for hdd in snaps.values():
   7.934 +            if hdd['Parent'] == template_uuid:
   7.935 +                #template_uuid = hdd['UUID']
   7.936 +                logger.debug('removing snapshot ' + hdd['UUID'])
   7.937 +                checkResult(Cygwin.vboxExecute('closemedium disk {' + hdd['UUID'] + '} --delete'))#[1]
   7.938 +                # parse result 0%...10%...20%...30%...40%...50%...60%...70%...80%...90%...100%
   7.939 +        
   7.940 +        self.changeStorageType(template_storage,'normal')
   7.941 +        self.storageAttach('SecurityDVM')
   7.942 +        self.startVM('SecurityDVM')
   7.943 +        self.waitStartup('SecurityDVM')
   7.944 +        checkResult(Cygwin.sshExecute('"sudo apt-get -y update"', VMManager.getHostOnlyIP('SecurityDVM'), 'osecuser', Cygwin.cygPath(self.machineFolder) + '/' + 'SecurityDVM' + '/dvm_key'))
   7.945 +        checkResult(Cygwin.sshExecute('"sudo apt-get -y upgrade"', VMManager.getHostOnlyIP('SecurityDVM'), 'osecuser', Cygwin.cygPath(self.machineFolder) + '/' + 'SecurityDVM' + '/dvm_key'))
   7.946 +        #self.stopVM('SecurityDVM')
   7.947 +        self.hibernateVM('SecurityDVM')
   7.948 +        self.waitShutdown('SecurityDVM')
   7.949 +        self.storageDetach('SecurityDVM')
   7.950 +        self.changeStorageType(template_storage,'immutable')
   7.951 +        self.storageAttach('SecurityDVM')
   7.952 +        self.rsdHandler = DeviceHandler(self)
   7.953 +        self.rsdHandler.start()
   7.954 +    
   7.955 +    #remove VM from the system. should be used on VMs returned by listSDVMs    
   7.956 +    def removeVM(self, vm_name):
   7.957 +        logger.info('Removing ' + vm_name)
   7.958 +        checkResult(Cygwin.vboxExecute('unregistervm ' + vm_name + ' --delete'))
   7.959 +        vm_file = Cygwin.cygPath(self.machineFolder + '\\' + vm_name)
   7.960 +        checkResult(Cygwin.bashExecute('rm -rf \'' + vm_file + '\''))
   7.961 +    
   7.962 +    # start VM
   7.963 +    def startVM(self, vm_name):
   7.964 +        logger.info('Starting ' +  vm_name)
   7.965 +        result = checkResult(Cygwin.vboxExecute('startvm ' + vm_name + ' --type headless' ))
   7.966 +        while 'successfully started' not in result[1] and _running:
   7.967 +            logger.error("Failed to start SDVM: " + vm_name + " retrying")
   7.968 +            time.sleep(1)
   7.969 +            result = checkResult(Cygwin.vboxExecute('startvm ' + vm_name + ' --type headless'))
   7.970 +        return result[0]
   7.971 +    
   7.972 +    # return wether VM is running or not
   7.973 +    def isVMRunning(self, vm_name):
   7.974 +        return vm_name in self.listRunningVMS()    
   7.975 +    
   7.976 +    # stop VM
   7.977 +    def stopVM(self, vm_name):
   7.978 +        logger.info('Sending shutdown signal to ' + vm_name)
   7.979 +        checkResult(Cygwin.sshExecute( '"sudo shutdown -h now"', VMManager.getHostOnlyIP(vm_name), 'osecuser', Cygwin.cygPath(self.machineFolder) + '/' + vm_name + '/dvm_key' ))
   7.980 +    
   7.981 +    # stop VM
   7.982 +    def hibernateVM(self, vm_name):
   7.983 +        logger.info('Sending shutdown signal to ' + vm_name)
   7.984 +        checkResult(Cygwin.sshExecute( '"sudo hibernate-disk&"', VMManager.getHostOnlyIP(vm_name), 'osecuser', Cygwin.cygPath(self.machineFolder) + '/' + vm_name + '/dvm_key', wait_return=False))
   7.985 +            
   7.986 +    # poweroff VM
   7.987 +    def poweroffVM(self, vm_name):
   7.988 +        if not self.isVMRunning(vm_name):
   7.989 +            return
   7.990 +        logger.info('Powering off ' + vm_name)
   7.991 +        return checkResult(Cygwin.vboxExecute('controlvm ' + vm_name + ' poweroff'))
   7.992 +    
   7.993 +    #list the hostonly IFs exposed by the VBox host
   7.994 +    @staticmethod    
   7.995 +    def getHostOnlyIFs():
   7.996 +        result = Cygwin.vboxExecute('list hostonlyifs')[1]
   7.997 +        if result=='':
   7.998 +            return None
   7.999 +        props = dict((k.strip(),v.strip().strip('"')) for k,v in (line.split(':', 1) for line in result.strip().splitlines()))
  7.1000 +        return props
  7.1001 +    
  7.1002 +    # return the hostOnly IP for a running guest or the host
  7.1003 +    @staticmethod    
  7.1004 +    def getHostOnlyIP(vm_name):
  7.1005 +        if vm_name == None:
  7.1006 +            logger.info('Gettting hostOnly IP address for Host')
  7.1007 +            return VMManager.getHostOnlyIFs()['IPAddress']
  7.1008 +        else:
  7.1009 +            logger.info('Gettting hostOnly IP address ' + vm_name)
  7.1010 +            result = checkResult(Cygwin.vboxExecute('guestproperty get ' + vm_name + ' /VirtualBox/GuestInfo/Net/0/V4/IP'))
  7.1011 +            if result=='':
  7.1012 +                return None
  7.1013 +            result = result[1]
  7.1014 +            if result.startswith('No value set!'):
  7.1015 +                return None
  7.1016 +            return result[result.index(':')+1:].strip()
  7.1017 +            
  7.1018 +    # attach removable storage device to VM by provision of filter
  7.1019 +    def attachRSD(self, vm_name, rsd_filter):
  7.1020 +        return checkResult(Cygwin.vboxExecute('usbfilter add 0 --target ' + vm_name + ' --name OpenSecurityRSD --vendorid ' + rsd_filter.vendorid + ' --productid ' + rsd_filter.productid + ' --revision ' + rsd_filter.revision))
  7.1021 +    
  7.1022 +    # detach removable storage from VM by 
  7.1023 +    def detachRSD(self, vm_name):
  7.1024 +        return checkResult(Cygwin.vboxExecute('usbfilter remove 0 --target ' + vm_name))
  7.1025 +        
  7.1026 +    # return the description set for an existing VM
  7.1027 +    def getVMInfo(self, vm_name):
  7.1028 +        results = checkResult(Cygwin.vboxExecute('showvminfo ' + vm_name + ' --machinereadable'))[1]
  7.1029 +        props = dict((k.strip().strip('"'),v.strip().strip('"')) for k,v in (line.split('=', 1) for line in results.splitlines()))
  7.1030 +        return props
  7.1031 +    
  7.1032 +    # return the configured USB filter for an existing VM 
  7.1033 +    def getUSBFilter(self, vm_name):
  7.1034 +        props = self.getVMInfo(vm_name)
  7.1035 +        keys = set(['USBFilterVendorId1', 'USBFilterProductId1', 'USBFilterRevision1'])
  7.1036 +        keyset = set(props.keys())
  7.1037 +        usb_filter = None
  7.1038 +        if keyset.issuperset(keys):
  7.1039 +            usb_filter = USBFilter(props['USBFilterVendorId1'], props['USBFilterProductId1'], props['USBFilterRevision1'])
  7.1040 +        return usb_filter
  7.1041 +    
  7.1042 +    #generates ISO containing authorized_keys for use with guest VM
  7.1043 +    def genCertificateISO(self, vm_name):
  7.1044 +        machineFolder = Cygwin.cygPath(self.machineFolder)
  7.1045 +        # remove .ssh folder if exists
  7.1046 +        checkResult(Cygwin.bashExecute('\"/usr/bin/rm -rf \\\"' + machineFolder + '/' + vm_name + '/.ssh\\\"\"'))
  7.1047 +        # remove .ssh folder if exists
  7.1048 +        checkResult(Cygwin.bashExecute('\"/usr/bin/rm -rf \\\"' + machineFolder + '/' + vm_name + '/dvm_key\\\"\"'))
  7.1049 +        # create .ssh folder in vm_name
  7.1050 +        checkResult(Cygwin.bashExecute('\"/usr/bin/mkdir -p \\\"' + machineFolder + '/' + vm_name + '/.ssh\\\"\"'))
  7.1051 +        # generate dvm_key pair in vm_name / .ssh     
  7.1052 +        checkResult(Cygwin.bashExecute('\"/usr/bin/ssh-keygen -q -t rsa -N \\"\\" -C \\\"' + vm_name + '\\\" -f \\\"' + machineFolder + '/' + vm_name + '/.ssh/dvm_key\\\"\"'))
  7.1053 +        # move out private key
  7.1054 +        checkResult(Cygwin.bashExecute('\"/usr/bin/mv \\\"' + machineFolder + '/' + vm_name + '/.ssh/dvm_key\\\" \\\"' + machineFolder + '/' + vm_name + '\\\"'))
  7.1055 +        # set permissions for private key
  7.1056 +        checkResult(Cygwin.bashExecute('\"/usr/bin/chmod 500 \\\"' + machineFolder + '/' + vm_name + '/dvm_key\\\"\"'))
  7.1057 +        # rename public key to authorized_keys
  7.1058 +        checkResult(Cygwin.bashExecute('\"/usr/bin/mv \\\"' + machineFolder + '/' + vm_name + '/.ssh/dvm_key.pub\\\" \\\"' + machineFolder + '/' + vm_name + '/.ssh/authorized_keys\\\"'))
  7.1059 +        # set permissions for authorized_keys
  7.1060 +        checkResult(Cygwin.bashExecute('\"/usr/bin/chmod 500 \\\"' + machineFolder + '/' + vm_name + '/.ssh/authorized_keys\\\"\"'))
  7.1061 +        # generate iso image with .ssh/authorized keys
  7.1062 +        checkResult(Cygwin.bashExecute('\"/usr/bin/genisoimage -J -R -o \\\"' + machineFolder + '/' + vm_name + '/'+ vm_name + '.iso\\\" \\\"' + machineFolder + '/' + vm_name + '/.ssh\\\"\"'))
  7.1063 +    
  7.1064 +    # attaches generated ssh public cert to guest vm
  7.1065 +    def attachCertificateISO(self, vm_name):
  7.1066 +        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\"'))
  7.1067 +        return result
  7.1068 +    
  7.1069 +    # wait for machine to come up
  7.1070 +    def waitStartup(self, vm_name, timeout_ms = 30000):
  7.1071 +        checkResult(Cygwin.vboxExecute('guestproperty wait ' + vm_name + ' SDVMStarted --timeout ' + str(timeout_ms) + ' --fail-on-timeout'))
  7.1072 +        return VMManager.getHostOnlyIP(vm_name)
  7.1073 +    
  7.1074 +    # wait for machine to shutdown
  7.1075 +    def waitShutdown(self, vm_name):
  7.1076 +        while vm_name in self.listRunningVMS() and _running:
  7.1077 +            time.sleep(1)
  7.1078 +        return
  7.1079 +        
  7.1080 +    # handles browsing request    
  7.1081 +    def handleBrowsingRequest(self):
  7.1082 +        handler = BrowsingHandler(self)
  7.1083 +        handler.start()
  7.1084 +        return 'ok'
  7.1085 +    
  7.1086 +    #Small function to check the availability of network resource.
  7.1087 +    #def isAvailable(self, path):
  7.1088 +        #return os.path.exists(path)
  7.1089 +        #result = Cygwin.cmdExecute('IF EXIST "' + path + '" echo YES')
  7.1090 +        #return string.find(result[1], 'YES',)
  7.1091 +    
  7.1092 +    #Small function to check if the mention location is a directory
  7.1093 +    def isDirectory(self, path):
  7.1094 +        result = checkResult(Cygwin.cmdExecute('dir ' + path + ' | FIND ".."'))
  7.1095 +        return string.find(result[1], 'DIR',)
  7.1096 +
  7.1097 +    def mapNetworkDrive(self, drive, networkPath, user, password):
  7.1098 +        self.unmapNetworkDrive(drive)
  7.1099 +        #Check for drive availability
  7.1100 +        if os.path.exists(drive):
  7.1101 +            logger.error("Drive letter is already in use: " + drive)
  7.1102 +            return -1
  7.1103 +        #Check for network resource availability
  7.1104 +        retry = 5
  7.1105 +        while not os.path.exists(networkPath):
  7.1106 +            time.sleep(1)
  7.1107 +            if retry == 0:
  7.1108 +                return -1
  7.1109 +            logger.info("Path not accessible: " + networkPath + " retrying")
  7.1110 +            retry-=1
  7.1111 +            #return -1
  7.1112 +    
  7.1113 +        command = 'USE ' + drive + ' ' + networkPath + ' /PERSISTENT:NO'
  7.1114 +        if user != None:
  7.1115 +            command += ' ' + password + ' /User' + user
  7.1116 +    
  7.1117 +        #TODO: Execute 'NET USE' command with authentication
  7.1118 +        result = checkResult(Cygwin.execute('C:\\Windows\\system32\\net.exe', command))
  7.1119 +        if string.find(result[1], 'successfully',) == -1:
  7.1120 +            logger.error("Failed: NET " + command)
  7.1121 +            return -1
  7.1122 +        return 1
  7.1123 +    
  7.1124 +    def unmapNetworkDrive(self, drive):
  7.1125 +        drives = self.getNetworkDrives()
  7.1126 +        if drive not in drives.keys():
  7.1127 +            return 1 
  7.1128 +        result = checkResult(Cygwin.execute('C:\\Windows\\system32\\net.exe', 'USE ' + drive + ' /DELETE /YES'))
  7.1129 +        if string.find(str(result[1]), 'successfully',) == -1:
  7.1130 +            logger.error(result[2])
  7.1131 +            return -1
  7.1132 +        return 1
  7.1133 +    
  7.1134 +    def getNetworkDrives(self):
  7.1135 +        ip = VMManager.getHostOnlyIP(None)
  7.1136 +        ip = ip[:ip.rindex('.')]
  7.1137 +        drives = dict()    
  7.1138 +        result = checkResult(Cygwin.execute('C:\\Windows\\system32\\net.exe', 'USE'))
  7.1139 +        for line in result[1].splitlines():
  7.1140 +            if ip in line:
  7.1141 +                parts = line.split()
  7.1142 +                drives[parts[1]] = parts[2]
  7.1143 +        return drives
  7.1144 +            
  7.1145 +    def genNetworkDrive(self):
  7.1146 +        network_drives = self.getNetworkDrives()
  7.1147 +        logical_drives = VMManager.getLogicalDrives()
  7.1148 +        drives = list(map(chr, range(68, 91)))  
  7.1149 +        for drive in drives:
  7.1150 +            if drive+':' not in network_drives and drive not in logical_drives:
  7.1151 +                return drive+':'
  7.1152 +
  7.1153 +    def getNetworkDrive(self, vm_name):
  7.1154 +        ip = self.getHostOnlyIP(vm_name)
  7.1155 +        result = checkResult(Cygwin.execute('C:\\Windows\\system32\\net.exe', 'USE'))
  7.1156 +        for line in result[1].splitlines():
  7.1157 +            if line != None and ip in line:
  7.1158 +                parts = line.split()
  7.1159 +                return parts[0]
  7.1160 +    @staticmethod
  7.1161 +    def getLogicalDrives():
  7.1162 +        drive_bitmask = ctypes.cdll.kernel32.GetLogicalDrives()
  7.1163 +        return list(itertools.compress(string.ascii_uppercase,  map(lambda x:ord(x) - ord('0'), bin(drive_bitmask)[:1:-1])))
  7.1164 +    
  7.1165 +    @staticmethod
  7.1166 +    def getDriveType(drive):
  7.1167 +        return ctypes.cdll.kernel32.GetDriveTypeW(u"%s:\\"%drive)
  7.1168 +    
  7.1169 +    @staticmethod
  7.1170 +    def getVolumeInfo(drive):
  7.1171 +        volumeNameBuffer = ctypes.create_unicode_buffer(1024)
  7.1172 +        fileSystemNameBuffer = ctypes.create_unicode_buffer(1024)
  7.1173 +        serial_number = None
  7.1174 +        max_component_length = None
  7.1175 +        file_system_flags = None
  7.1176 +        
  7.1177 +        rc = ctypes.cdll.kernel32.GetVolumeInformationW(
  7.1178 +            #ctypes.c_wchar_p("F:\\"),
  7.1179 +            u"%s:\\"%drive,
  7.1180 +            volumeNameBuffer,
  7.1181 +            ctypes.sizeof(volumeNameBuffer),
  7.1182 +            serial_number,
  7.1183 +            max_component_length,
  7.1184 +            file_system_flags,
  7.1185 +            fileSystemNameBuffer,
  7.1186 +            ctypes.sizeof(fileSystemNameBuffer)
  7.1187 +        )
  7.1188 +        
  7.1189 +        return volumeNameBuffer.value, fileSystemNameBuffer.value
  7.1190 +
  7.1191 +    @staticmethod
  7.1192 +    def stop():
  7.1193 +        """stop all running infinite loops now --> needed for gracefull shutdown"""
  7.1194 +        _running = False
  7.1195 +
  7.1196 +
  7.1197 +
  7.1198 +def checkResult(result):
  7.1199 +    if result[0] != 0:
  7.1200 +        logger.error('Command failed:' + ''.join(result[2]))
  7.1201 +        raise OpenSecurityException('Command failed:' + ''.join(result[2]))
  7.1202 +    return result
  7.1203 +
  7.1204 +# handles browsing request                    
  7.1205 +class BrowsingHandler(threading.Thread):
  7.1206 +    vmm = None
  7.1207 +    def __init__(self, vmmanager):
  7.1208 +        threading.Thread.__init__(self)
  7.1209 +        self.vmm = vmmanager
  7.1210 +     
  7.1211 +    def run(self):
  7.1212 +        try:
  7.1213 +            new_sdvm = self.vmm.generateSDVMName()
  7.1214 +            self.vmm.createVM(new_sdvm)
  7.1215 +            self.vmm.storageAttach(new_sdvm)
  7.1216 +            self.vmm.genCertificateISO(new_sdvm)
  7.1217 +            self.vmm.attachCertificateISO(new_sdvm)
  7.1218 +            self.vmm.startVM(new_sdvm)
  7.1219 +            new_ip = self.vmm.waitStartup(new_sdvm)
  7.1220 +            drive = self.vmm.genNetworkDrive()
  7.1221 +            if new_ip != None:
  7.1222 +                self.vmm.mapNetworkDrive(drive, '\\\\' + new_ip + '\\Download', None, None)
  7.1223 +            result = checkResult(Cygwin.sshExecuteX11('/usr/bin/iceweasel', new_ip, 'osecuser', Cygwin.cygPath(self.vmm.getMachineFolder()) + '/' + new_sdvm + '/dvm_key'))
  7.1224 +        except:
  7.1225 +            logger.error("BrowsingHandler failed. Cleaning up")
  7.1226 +            
  7.1227 +        self.vmm.unmapNetworkDrive(drive)
  7.1228 +        self.vmm.poweroffVM(new_sdvm)
  7.1229 +        self.vmm.removeVM(new_sdvm)
  7.1230 +                
  7.1231 +class DeviceHandler(threading.Thread): 
  7.1232 +    vmm = None
  7.1233 +    #handleDeviceChangeLock = threading.Lock()
  7.1234 +    attachedRSDs = None  
  7.1235 +    connectedRSDs = None
  7.1236 +    running = True
  7.1237 +    def __init__(self, vmmanger): 
  7.1238 +        threading.Thread.__init__(self)
  7.1239 +        self.vmm = vmmanger
  7.1240 + 
  7.1241 +    def stop(self):
  7.1242 +        self.running = False
  7.1243 +        
  7.1244 +    def run(self):
  7.1245 +        self.connectedRSDs = dict()
  7.1246 +        self.attachedRSDs = self.vmm.getAttachedRSDs()
  7.1247 +        while self.running:
  7.1248 +            tmp_rsds = self.vmm.getConnectedRSDS()
  7.1249 +            if tmp_rsds.keys() == self.connectedRSDs.keys():
  7.1250 +                logger.debug("Nothing's changed. sleep(3)")
  7.1251 +                time.sleep(3)
  7.1252 +                continue
  7.1253 +            
  7.1254 +            logger.info("Something's changed")          
  7.1255 +            self.connectedRSDs = tmp_rsds
  7.1256 +            self.attachedRSDs = self.vmm.getAttachedRSDs()
  7.1257 +            
  7.1258 +            for vm_name in self.attachedRSDs.keys():
  7.1259 +                if self.attachedRSDs[vm_name] not in self.connectedRSDs.values():
  7.1260 +                    drive = self.vmm.getNetworkDrive(vm_name)
  7.1261 +                    self.vmm.unmapNetworkDrive(drive)
  7.1262 +                    #self.stopVM(vm_name)
  7.1263 +                    self.vmm.detachRSD(vm_name)
  7.1264 +                    self.vmm.poweroffVM(vm_name)
  7.1265 +                    self.vmm.removeVM(vm_name)
  7.1266 +            #create new vm for attached device if any
  7.1267 +            self.attachedRSDs = self.vmm.getAttachedRSDs()
  7.1268 +            self.connectedRSDs = self.vmm.getConnectedRSDS()
  7.1269 +            
  7.1270 +            new_ip = None
  7.1271 +            for connected_device in self.connectedRSDs.values():
  7.1272 +                if (self.attachedRSDs and False) or (connected_device not in self.attachedRSDs.values()):
  7.1273 +                    new_sdvm = self.vmm.generateSDVMName()
  7.1274 +                    self.vmm.createVM(new_sdvm)
  7.1275 +                    self.vmm.storageAttach(new_sdvm)
  7.1276 +                    self.vmm.attachRSD(new_sdvm, connected_device)
  7.1277 +                    self.vmm.startVM(new_sdvm)
  7.1278 +                    new_ip = self.vmm.waitStartup(new_sdvm)
  7.1279 +                    drive = self.vmm.genNetworkDrive()
  7.1280 +                    if new_ip != None:
  7.1281 +                        self.vmm.mapNetworkDrive(drive, '\\\\' + new_ip + '\\USB', None, None)
  7.1282 +
  7.1283 +if __name__ == '__main__':
  7.1284 +    #man = VMManager.getInstance()
  7.1285 +    #man.listVM()
  7.1286 +    #print man.getConnectedRSDs()
  7.1287 +    #print man.getNetworkDrives()
  7.1288 +    #man.genNetworkDrive()
  7.1289 +    #drive_bitmask = ctypes.cdll.kernel32.GetLogicalDrives()
  7.1290 +    #print list(itertools.compress(string.ascii_uppercase,  map(lambda x:ord(x) - ord('0'), bin(drive_bitmask)[:1:-1])))
  7.1291 +    #print list(map(chr, range(68, 91))) 
  7.1292 +    #print Cygwin.getRegEntry('SYSTEM\CurrentControlSet\Enum\USB', 'VID_1058&PID_0704')[0]
  7.1293 +    #devices = VMManager.getConnectedRSDS()
  7.1294 +    #print devices
  7.1295 +    
  7.1296 +    drives = VMManager.getLogicalDrives()
  7.1297 +    print drives
  7.1298 +    print VMManager.getDriveType("E")
  7.1299 +    print VMManager.getVolumeInfo("E")
  7.1300 +    #for device in devices.values():
  7.1301 +    #    #print device
  7.1302 +    #    if VMManager.isMassStorageDevice(device):
  7.1303 +    #        print device
  7.1304 +        
  7.1305 +    
  7.1306 +    
  7.1307 +    #time.sleep(-1)
  7.1308 +    #man.listVM()
  7.1309 +    #man.listVM()
  7.1310 +    #man.listVM()
  7.1311 +    #man.listVM()
  7.1312 +    #man.genCertificateISO('SecurityDVM0')
  7.1313 +    #man.guestExecute('SecurityDVM0', '/bin/ls -la')
  7.1314 +    #logger = setupLogger('VMManager')
  7.1315 +    #c = Cygwin()
  7.1316 +    
  7.1317 +    #man.sshExecute('/bin/ls -la', 'SecurityDVM0')
  7.1318 +    #man.sshExecuteX11('/usr/bin/iceweasel', 'SecurityDVM0')
  7.1319 +    #man.removeVM('SecurityDVM0')
  7.1320 +    #man.netUse('192.168.56.134', 'USB\\')
  7.1321 +    #ip = '192.168.56.139'
  7.1322 +    
  7.1323 +    #man.cygwin_path = 'c:\\cygwin64\\bin\\'
  7.1324 +    #man.handleDeviceChange()
  7.1325 +    #print man.listSDVM()
  7.1326 +    #man.configureHostNetworking()
  7.1327 +    #new_vm = man.generateSDVMName()
  7.1328 +    #man.createVM(new_vm)
  7.1329 +    
  7.1330 +    #print Cygwin.cmd()
  7.1331 +    #man.isAvailable('c:')
  7.1332 +    #ip = man.getHostOnlyIP('SecurityDVM0')
  7.1333 +    #man.mapNetworkDrive('h:', '\\\\' + ip + '\Download', None, None)
  7.1334 +    
  7.1335 +    #man.genCertificateISO(new_vm)
  7.1336 +    #man.attachCertificateISO(new_vm)
  7.1337 +    
  7.1338 +    #man.attachCertificateISO(vm_name)
  7.1339 +    #man.guestExecute(vm_name, "ls")
  7.1340 +    #man.sshGuestX11Execute('SecurityDVM1', '/usr/bin/iceweasel')
  7.1341 +    #time.sleep(60)
  7.1342 +    #print man.cygwinPath("C:\Users\BarthaM\VirtualBox VMs\SecurityDVM\.ssh\*")
  7.1343 +    #man.genCertificateISO('SecurityDVM')
  7.1344 +    #man.attachCertificateISO('SecurityDVM')
  7.1345 +    #man.isStorageAttached('SecurityDVM')
  7.1346 +    #man.guestExecute('SecurityDVM', 'sudo apt-get -y update')
  7.1347 +    #man.guestExecute('SecurityDVM', 'sudo apt-get -y upgrade' )
  7.1348 +    
  7.1349 +    #man.stopVM('SecurityDVM')
  7.1350 +    #man.storageDetach('SecurityDVM')
  7.1351 +    #man.changeStorageType('C:\Users\BarthaM\VirtualBox VMs\SecurityDVM\SecurityDVM.vmdk','immutable')
  7.1352 +    #man.storageAttach('SecurityDVM')
  7.1353 +    
  7.1354 +    
  7.1355 +    #cmd = "c:\\cygwin64\\bin\\bash.exe --login -c \"/bin/ls\""
  7.1356 +    #man.execute(cmd)