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