adopted server code and merged client into "bin"
authorom
Fri, 06 Dec 2013 10:51:15 +0100
changeset 134457d7071a23
parent 11 27aa3b16eebb
child 16 e16d64b5e008
adopted server code and merged client into "bin"
OpenSecurity/bin/about.py
OpenSecurity/bin/credentials.py
OpenSecurity/bin/cygwin.py
OpenSecurity/bin/environment.py
OpenSecurity/bin/launch.py
OpenSecurity/bin/opensecurity_client_restful_server.py
OpenSecurity/bin/opensecurity_dialog.py
OpenSecurity/bin/opensecurity_server.py
OpenSecurity/bin/opensecurity_tray.py
OpenSecurity/bin/opensecurityd.py
OpenSecurity/bin/password.py
OpenSecurity/bin/vmmanager/PKG-INFO
OpenSecurity/bin/vmmanager/__init__.py
OpenSecurity/bin/vmmanager/vmmanager.py
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/OpenSecurity/bin/about.py	Fri Dec 06 10:51:15 2013 +0100
     1.3 @@ -0,0 +1,126 @@
     1.4 +#!/bin/env python
     1.5 +# -*- coding: utf-8 -*-
     1.6 +
     1.7 +# ------------------------------------------------------------
     1.8 +# about-dialog
     1.9 +# 
    1.10 +# tell the user about the project
    1.11 +#
    1.12 +# Autor: Oliver Maurhart, <oliver.maurhart@ait.ac.at>
    1.13 +#
    1.14 +# Copyright (C) 2013 AIT Austrian Institute of Technology
    1.15 +# AIT Austrian Institute of Technology GmbH
    1.16 +# Donau-City-Strasse 1 | 1220 Vienna | Austria
    1.17 +# http://www.ait.ac.at
    1.18 +#
    1.19 +# This program is free software; you can redistribute it and/or
    1.20 +# modify it under the terms of the GNU General Public License
    1.21 +# as published by the Free Software Foundation version 2.
    1.22 +# 
    1.23 +# This program is distributed in the hope that it will be useful,
    1.24 +# but WITHOUT ANY WARRANTY; without even the implied warranty of
    1.25 +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    1.26 +# GNU General Public License for more details.
    1.27 +# 
    1.28 +# You should have received a copy of the GNU General Public License
    1.29 +# along with this program; if not, write to the Free Software
    1.30 +# Foundation, Inc., 51 Franklin Street, Fifth Floor, 
    1.31 +# Boston, MA  02110-1301, USA.
    1.32 +# ------------------------------------------------------------
    1.33 +
    1.34 +
    1.35 +# ------------------------------------------------------------
    1.36 +# imports
    1.37 +
    1.38 +import os
    1.39 +
    1.40 +from PyQt4 import QtCore
    1.41 +from PyQt4 import QtGui
    1.42 +
    1.43 +# local
    1.44 +from environment import Environment
    1.45 +
    1.46 +# ------------------------------------------------------------
    1.47 +# vars
    1.48 +
    1.49 +
    1.50 +ABOUT_TEXT = """
    1.51 +<html>
    1.52 +<body bgcolor="#FFFFFF">
    1.53 +
    1.54 +<div align="center">
    1.55 +<p/>
    1.56 +<img src="image:ait_logo_no_claim.png"/>
    1.57 +<p/>
    1.58 +<h1>OpenSecurity</h1>
    1.59 +<p/>
    1.60 +</div>
    1.61 +<p/>
    1.62 +Blah ...<br/>
    1.63 +
    1.64 +<p>
    1.65 +Copyright (C) 2013, AIT Austrian Institute of Technology<br/>
    1.66 +AIT Austrian Institute of Technology GmbH<br/>
    1.67 +Donau-City-Strasse 1 | 1220 Vienna | Austria<br/>
    1.68 +<a href="http://www.ait.ac.at">http://www.ait.ac.at</a>
    1.69 +</p>
    1.70 +</div>
    1.71 +
    1.72 +</body>
    1.73 +</html>
    1.74 +""";
    1.75 +
    1.76 +
    1.77 +# ------------------------------------------------------------
    1.78 +# code
    1.79 +
    1.80 +
    1.81 +class About(QtGui.QDialog):
    1.82 +    
    1.83 +    """Show some about stuff."""
    1.84 +    
    1.85 +    def __init__(self, parent = None, flags = QtCore.Qt.WindowFlags(0)):
    1.86 +        
    1.87 +        # super call and widget init
    1.88 +        super(About, self).__init__(parent, flags)
    1.89 +        
    1.90 +        # setup image search path
    1.91 +        QtCore.QDir.setSearchPaths("image", QtCore.QStringList(os.path.join(Environment('opensecurity').data_path, '..', 'gfx')));
    1.92 +        
    1.93 +        self.setWindowTitle('About OpenSecuirty ...')
    1.94 +        self.setup_ui()
    1.95 +        
    1.96 +
    1.97 +    def setup_ui(self):
    1.98 +        
    1.99 +        """Create the widgets."""
   1.100 +        
   1.101 +        lyMain = QtGui.QVBoxLayout(self)
   1.102 +        lyMain.setContentsMargins(8, 8, 8, 8)
   1.103 +        
   1.104 +        lbAbout = QtGui.QLabel()
   1.105 +        lbAbout.setStyleSheet("QWidget { background: white; color: black; };")
   1.106 +        lbAbout.setText(ABOUT_TEXT)
   1.107 +        lbAbout.setContentsMargins(12, 12, 12, 12)
   1.108 +        
   1.109 +        scAbout = QtGui.QScrollArea()
   1.110 +        scAbout.setWidget(lbAbout)
   1.111 +        scAbout.viewport().setStyleSheet("QWidget { background: white; color: black; };")
   1.112 +        lyMain.addWidget(scAbout)
   1.113 +        
   1.114 +        # buttons
   1.115 +        lyButton = QtGui.QHBoxLayout()
   1.116 +        lyMain.addLayout(lyButton)
   1.117 +        
   1.118 +        lyButton.addStretch(1)
   1.119 +        btnOk = QtGui.QPushButton('&Ok', self)
   1.120 +        btnOk.setMinimumWidth(100)
   1.121 +        lyButton.addWidget(btnOk)
   1.122 +        
   1.123 +        # connectors
   1.124 +        btnOk.clicked.connect(self.accept)
   1.125 +        
   1.126 +        # reduce to the max
   1.127 +        self.setMinimumSize(400, 200)
   1.128 +        self.resize(lyMain.minimumSize())
   1.129 +
     2.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.2 +++ b/OpenSecurity/bin/credentials.py	Fri Dec 06 10:51:15 2013 +0100
     2.3 @@ -0,0 +1,160 @@
     2.4 +#!/bin/env python
     2.5 +# -*- coding: utf-8 -*-
     2.6 +
     2.7 +# ------------------------------------------------------------
     2.8 +# credentials-dialog
     2.9 +# 
    2.10 +# ask the user credentials
    2.11 +#
    2.12 +# Autor: Oliver Maurhart, <oliver.maurhart@ait.ac.at>
    2.13 +#
    2.14 +# Copyright (C) 2013 AIT Austrian Institute of Technology
    2.15 +# AIT Austrian Institute of Technology GmbH
    2.16 +# Donau-City-Strasse 1 | 1220 Vienna | Austria
    2.17 +# http://www.ait.ac.at
    2.18 +#
    2.19 +# This program is free software; you can redistribute it and/or
    2.20 +# modify it under the terms of the GNU General Public License
    2.21 +# as published by the Free Software Foundation version 2.
    2.22 +# 
    2.23 +# This program is distributed in the hope that it will be useful,
    2.24 +# but WITHOUT ANY WARRANTY; without even the implied warranty of
    2.25 +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    2.26 +# GNU General Public License for more details.
    2.27 +# 
    2.28 +# You should have received a copy of the GNU General Public License
    2.29 +# along with this program; if not, write to the Free Software
    2.30 +# Foundation, Inc., 51 Franklin Street, Fifth Floor, 
    2.31 +# Boston, MA  02110-1301, USA.
    2.32 +# ------------------------------------------------------------
    2.33 +
    2.34 +
    2.35 +# ------------------------------------------------------------
    2.36 +# imports
    2.37 +
    2.38 +import sys
    2.39 +
    2.40 +from PyQt4 import QtCore
    2.41 +from PyQt4 import QtGui
    2.42 +
    2.43 +# local
    2.44 +from about import About
    2.45 +
    2.46 +# ------------------------------------------------------------
    2.47 +# code
    2.48 +
    2.49 +
    2.50 +class Credentials(QtGui.QDialog):
    2.51 +    
    2.52 +    """Ask the user for credentials."""
    2.53 +    
    2.54 +    def __init__(self, text, parent = None, flags = QtCore.Qt.WindowFlags(0)):
    2.55 +        
    2.56 +        super(Credentials, self).__init__(parent, flags)
    2.57 +        self.setWindowTitle('OpenSecuirty Credentials Request')
    2.58 +        self.setup_ui()
    2.59 +        
    2.60 +        # positionate ourself central
    2.61 +        screen = QtGui.QDesktopWidget().screenGeometry()
    2.62 +        self.resize(self.geometry().width() * 1.25, self.geometry().height())
    2.63 +        size = self.geometry()
    2.64 +        self.move((screen.width() - size.width()) / 2, (screen.height() - size.height()) / 2)
    2.65 +        
    2.66 +        # fix up text
    2.67 +        self.lbText.setText(text)
    2.68 +        
    2.69 +
    2.70 +    def clicked_about(self):
    2.71 +        """clicked the about button"""
    2.72 +        dlgAbout = About()
    2.73 +        dlgAbout.exec_()
    2.74 +    
    2.75 +
    2.76 +    def clicked_cancel(self):
    2.77 +        """clicked the cancel button"""
    2.78 +        self.reject()
    2.79 +    
    2.80 +
    2.81 +    def clicked_ok(self):
    2.82 +        """clicked the ok button"""
    2.83 +        sys.stdout.write('{ ')
    2.84 +        sys.stdout.write('\'user\': \'')
    2.85 +        sys.stdout.write(self.edUser.text())
    2.86 +        sys.stdout.write('\', ')
    2.87 +        sys.stdout.write('\'password\': \'')
    2.88 +        sys.stdout.write(self.edPassword.text())
    2.89 +        sys.stdout.write('\' ')
    2.90 +        sys.stdout.write('}\n')
    2.91 +        self.accept()
    2.92 +    
    2.93 +
    2.94 +    def setup_ui(self):
    2.95 +        
    2.96 +        """Create the widgets."""
    2.97 +        
    2.98 +        lyMain = QtGui.QVBoxLayout(self)
    2.99 +        lyMain.setContentsMargins(8, 8, 8, 8)
   2.100 +        
   2.101 +        # content area: left pixmap, right text
   2.102 +        lyContent = QtGui.QHBoxLayout()
   2.103 +        lyMain.addLayout(lyContent)
   2.104 +        
   2.105 +        # pixmap
   2.106 +        lbPix = QtGui.QLabel()
   2.107 +        lbPix.setPixmap(QtGui.QPixmapCache.find('opensecurity_icon_64'))
   2.108 +        lyContent.addWidget(lbPix, 0, QtCore.Qt.Alignment(QtCore.Qt.AlignTop + QtCore.Qt.AlignHCenter))
   2.109 +        lyContent.addSpacing(16)
   2.110 +        
   2.111 +        # text ...
   2.112 +        lyText = QtGui.QGridLayout()
   2.113 +        lyContent.addLayout(lyText)
   2.114 +        self.lbText = QtGui.QLabel()
   2.115 +        lyText.addWidget(self.lbText, 0, 0, 1, 2)
   2.116 +        
   2.117 +        lbUser = QtGui.QLabel('&User:')
   2.118 +        lyText.addWidget(lbUser, 1, 0)
   2.119 +        self.edUser = QtGui.QLineEdit()
   2.120 +        lyText.addWidget(self.edUser, 1, 1)
   2.121 +        lbUser.setBuddy(self.edUser)
   2.122 +        
   2.123 +        lbPassword = QtGui.QLabel('&Password:')
   2.124 +        lyText.addWidget(lbPassword, 2, 0)
   2.125 +        self.edPassword = QtGui.QLineEdit()
   2.126 +        self.edPassword.setEchoMode(QtGui.QLineEdit.Password)
   2.127 +        lyText.addWidget(self.edPassword, 2, 1)
   2.128 +        lbPassword.setBuddy(self.edPassword)
   2.129 +        
   2.130 +        lyText.addWidget(QtGui.QWidget(), 3, 0, 1, 2)
   2.131 +        lyText.setColumnStretch(1, 1)
   2.132 +        lyText.setRowStretch(3, 1)
   2.133 +        
   2.134 +        lyMain.addStretch(1)
   2.135 +        
   2.136 +        # buttons
   2.137 +        lyButton = QtGui.QHBoxLayout()
   2.138 +        lyMain.addLayout(lyButton)
   2.139 +        
   2.140 +        lyButton.addStretch(1)
   2.141 +        btnOk = QtGui.QPushButton('&Ok', self)
   2.142 +        btnOk.setDefault(True)
   2.143 +        btnOk.setMinimumWidth(100)
   2.144 +        lyButton.addWidget(btnOk)
   2.145 +        btnCancel = QtGui.QPushButton('&Cancel', self)
   2.146 +        btnCancel.setMinimumWidth(100)
   2.147 +        lyButton.addWidget(btnCancel)
   2.148 +        btnAbout = QtGui.QPushButton('&About', self)
   2.149 +        btnAbout.setMinimumWidth(100)
   2.150 +        lyButton.addWidget(btnAbout)
   2.151 +        
   2.152 +        button_width = max(btnOk.width(), btnCancel.width(), btnAbout.width())
   2.153 +        btnOk.setMinimumWidth(button_width)
   2.154 +        btnCancel.setMinimumWidth(button_width)
   2.155 +        btnAbout.setMinimumWidth(button_width)
   2.156 +        
   2.157 +        # reduce to the max
   2.158 +        self.resize(lyMain.minimumSize())
   2.159 +        
   2.160 +        # connectors
   2.161 +        btnOk.clicked.connect(self.clicked_ok)
   2.162 +        btnCancel.clicked.connect(self.clicked_cancel)
   2.163 +        btnAbout.clicked.connect(self.clicked_about)
     3.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/OpenSecurity/bin/cygwin.py	Fri Dec 06 10:51:15 2013 +0100
     3.3 @@ -0,0 +1,105 @@
     3.4 +#!/bin/env python
     3.5 +# -*- coding: utf-8 -*-
     3.6 +
     3.7 +# ------------------------------------------------------------
     3.8 +# cygwin command
     3.9 +# 
    3.10 +# executes a cygwin command inside the opensecurity project
    3.11 +#
    3.12 +# Autor: Oliver Maurhart, <oliver.maurhart@ait.ac.at>
    3.13 +#
    3.14 +# Copyright (C) 2013 AIT Austrian Institute of Technology
    3.15 +# AIT Austrian Institute of Technology GmbH
    3.16 +# Donau-City-Strasse 1 | 1220 Vienna | Austria
    3.17 +# http://www.ait.ac.at
    3.18 +#
    3.19 +# This program is free software; you can redistribute it and/or
    3.20 +# modify it under the terms of the GNU General Public License
    3.21 +# as published by the Free Software Foundation version 2.
    3.22 +# 
    3.23 +# This program is distributed in the hope that it will be useful,
    3.24 +# but WITHOUT ANY WARRANTY; without even the implied warranty of
    3.25 +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    3.26 +# GNU General Public License for more details.
    3.27 +# 
    3.28 +# You should have received a copy of the GNU General Public License
    3.29 +# along with this program; if not, write to the Free Software
    3.30 +# Foundation, Inc., 51 Franklin Street, Fifth Floor, 
    3.31 +# Boston, MA  02110-1301, USA.
    3.32 +# ------------------------------------------------------------
    3.33 +
    3.34 +
    3.35 +# ------------------------------------------------------------
    3.36 +# imports
    3.37 +
    3.38 +import os
    3.39 +import subprocess
    3.40 +import sys
    3.41 +
    3.42 +# local
    3.43 +from environment import Environment
    3.44 +
    3.45 +
    3.46 +# ------------------------------------------------------------
    3.47 +# code
    3.48 +
    3.49 +
    3.50 +class Cygwin(object):
    3.51 +
    3.52 +    """Some nifty methods working with Cygwin"""
    3.53 +    
    3.54 +    def __call__(self, command, stdin = subprocess.PIPE, stdout = subprocess.PIPE, stderr = subprocess.PIPE):
    3.55 +        """make an instance of this object act as a function"""
    3.56 +        return self.execute(command, stdin, stdout, stderr)
    3.57 +
    3.58 +        
    3.59 +    @staticmethod
    3.60 +    def root():
    3.61 +        """get the path to our local cygwin installment"""
    3.62 +        return os.path.join(Environment('OpenSecurity').prefix_path, '..', 'cygwin')
    3.63 +
    3.64 +
    3.65 +    def execute(self, command, stdin = subprocess.PIPE, stdout = subprocess.PIPE, stderr = subprocess.PIPE):
    3.66 +        """execute a cygwin shell command
    3.67 +        
    3.68 +        command is list of arguments like ['/bin/ls', '-al', '-h']
    3.69 +        
    3.70 +        a Popen object is returned"""
    3.71 +        command_path = Cygwin.root() + os.sep.join(command[0].split('/'))
    3.72 +        command = [command_path] + command[1:]
    3.73 +        
    3.74 +        return subprocess.Popen(command, shell = False, stdin = stdin, stdout = stdout, stderr = stderr)
    3.75 +        
    3.76 +        
    3.77 +    @staticmethod
    3.78 +    def is_X11_running():
    3.79 +        """check if we can connect to a X11 running instance"""
    3.80 +        p = Cygwin()(['/bin/bash', '-c', 'DISPLAY=:0 /usr/bin/xset -q'])
    3.81 +        stdout, stderr = p.communicate()
    3.82 +        return p.returncode == 0
    3.83 +        
    3.84 +        
    3.85 +    @staticmethod
    3.86 +    def start_X11():
    3.87 +        """start X11 in the background (if not already running) on DISPLAY=:0"""
    3.88 +        
    3.89 +        # do not start if already running
    3.90 +        if Cygwin.is_X11_running():
    3.91 +            return
    3.92 +            
    3.93 +        # launch X11 (forget output and return immediately)
    3.94 +        p = Cygwin()(['/bin/bash', '--login', '-i', '-c', ' X :0 -multiwindow'], stdin = None, stdout = None, stderr = None)
    3.95 +        
    3.96 +    
    3.97 +# start
    3.98 +if __name__ == "__main__":
    3.99 +
   3.100 +    # execute what is given on the command line
   3.101 +    c = Cygwin()
   3.102 +    p = c(sys.argv[1:])
   3.103 +    
   3.104 +    # wait until the process finished and grab the output
   3.105 +    stdout, stderr = p.communicate()
   3.106 +    print('=== call result on stdout: ===\n' + stdout)
   3.107 +    print('=== call result on stderr: ===\n' + stderr)
   3.108 +    
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/OpenSecurity/bin/environment.py	Fri Dec 06 10:51:15 2013 +0100
     4.3 @@ -0,0 +1,103 @@
     4.4 +#!/bin/env python
     4.5 +# -*- coding: utf-8 -*-
     4.6 +
     4.7 +# ------------------------------------------------------------
     4.8 +# environment.py
     4.9 +# 
    4.10 +# pick some current environment infos
    4.11 +#
    4.12 +# Autor: Oliver Maurhart, <oliver.maurhart@ait.ac.at>
    4.13 +#
    4.14 +# Copyright (C) 2013 AIT Austrian Institute of Technology
    4.15 +# AIT Austrian Institute of Technology GmbH
    4.16 +# Donau-City-Strasse 1 | 1220 Vienna | Austria
    4.17 +# http://www.ait.ac.at
    4.18 +#
    4.19 +# This program is free software; you can redistribute it and/or
    4.20 +# modify it under the terms of the GNU General Public License
    4.21 +# as published by the Free Software Foundation version 2.
    4.22 +# 
    4.23 +# This program is distributed in the hope that it will be useful,
    4.24 +# but WITHOUT ANY WARRANTY; without even the implied warranty of
    4.25 +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    4.26 +# GNU General Public License for more details.
    4.27 +# 
    4.28 +# You should have received a copy of the GNU General Public License
    4.29 +# along with this program; if not, write to the Free Software
    4.30 +# Foundation, Inc., 51 Franklin Street, Fifth Floor, 
    4.31 +# Boston, MA  02110-1301, USA.
    4.32 +# ------------------------------------------------------------
    4.33 +
    4.34 +
    4.35 +# ------------------------------------------------------------
    4.36 +# imports
    4.37 +
    4.38 +import os
    4.39 +import os.path
    4.40 +import sys
    4.41 +
    4.42 +
    4.43 +# ------------------------------------------------------------
    4.44 +# code
    4.45 +
    4.46 +
    4.47 +class Environment(object):
    4.48 +    
    4.49 +    """Hold some nifty environment stuff in a dedicated class."""
    4.50 +    
    4.51 +    def __init__(self, application = None):
    4.52 +        
    4.53 +        # if we ain't got a path to start from, all is valid/lost
    4.54 +        if len(sys.path[0]) == 0:
    4.55 +            self._prefix_path = ''
    4.56 +            self._data_path = ''
    4.57 +            return
    4.58 +        
    4.59 +        # the prefix path
    4.60 +        #
    4.61 +        # - on Linux: this is ../../ to the current executable
    4.62 +        #   e.g. "/usr/bin/myprogram" --> "/usr"
    4.63 +        #
    4.64 +        # - on Windows (inkl. Cygwin): this is the installation folder
    4.65 +        #   e.g. "C:/Program Files/MyProgram/myprogam" --> "C:/Program Files/MyProgram"
    4.66 +        #
    4.67 +        if sys.platform == 'linux2':
    4.68 +            self._prefix_path = os.path.split(sys.path[0])[0]
    4.69 +        elif sys.platform == 'win32' or sys.platform == 'cygwin':
    4.70 +            self._prefix_path = sys.path[0]
    4.71 +            
    4.72 +        # the data path where all data files are stored
    4.73 +        if sys.platform == 'linux2':
    4.74 +            if not application is None:
    4.75 +                self._data_path = os.path.join(self._prefix_path, os.path.join('share', application))
    4.76 +            else:
    4.77 +                self._data_path = os.path.join(self._prefix_path, 'share')
    4.78 +        elif sys.platform == 'win32' or sys.platform == 'cygwin':
    4.79 +            self._data_path = self._prefix_path
    4.80 +
    4.81 +            
    4.82 +    def data_path_get(self):
    4.83 +        """dat_path get"""
    4.84 +        return self._data_path
    4.85 +        
    4.86 +    data_path = property(data_path_get)
    4.87 +            
    4.88 +            
    4.89 +    def prefix_path_get(self):
    4.90 +        """prefix_path get"""
    4.91 +        return self._prefix_path
    4.92 +        
    4.93 +    prefix_path = property(prefix_path_get)
    4.94 +            
    4.95 +# test method			
    4.96 +def test():
    4.97 +
    4.98 +	"""Test: class Environment"""
    4.99 +	e = Environment('My Application')
   4.100 +	print('prefix_path: "{0}"'.format(e.prefix_path))
   4.101 +	print('  data_path: "{0}"'.format(e.data_path))
   4.102 +			
   4.103 +			
   4.104 +# test the module			
   4.105 +if __name__ == '__main__':
   4.106 +	test()
     5.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.2 +++ b/OpenSecurity/bin/launch.py	Fri Dec 06 10:51:15 2013 +0100
     5.3 @@ -0,0 +1,287 @@
     5.4 +#!/bin/env python
     5.5 +# -*- coding: utf-8 -*-
     5.6 +
     5.7 +# ------------------------------------------------------------
     5.8 +# opensecurity-launcher
     5.9 +# 
    5.10 +# launches an application inside a VM
    5.11 +#
    5.12 +# Autor: Oliver Maurhart, <oliver.maurhart@ait.ac.at>
    5.13 +#
    5.14 +# Copyright (C) 2013 AIT Austrian Institute of Technology
    5.15 +# AIT Austrian Institute of Technology GmbH
    5.16 +# Donau-City-Strasse 1 | 1220 Vienna | Austria
    5.17 +# http://www.ait.ac.at
    5.18 +#
    5.19 +# This program is free software; you can redistribute it and/or
    5.20 +# modify it under the terms of the GNU General Public License
    5.21 +# as published by the Free Software Foundation version 2.
    5.22 +# 
    5.23 +# This program is distributed in the hope that it will be useful,
    5.24 +# but WITHOUT ANY WARRANTY; without even the implied warranty of
    5.25 +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    5.26 +# GNU General Public License for more details.
    5.27 +# 
    5.28 +# You should have received a copy of the GNU General Public License
    5.29 +# along with this program; if not, write to the Free Software
    5.30 +# Foundation, Inc., 51 Franklin Street, Fifth Floor, 
    5.31 +# Boston, MA  02110-1301, USA.
    5.32 +# ------------------------------------------------------------
    5.33 +
    5.34 +
    5.35 +# ------------------------------------------------------------
    5.36 +# imports
    5.37 +
    5.38 +import argparse
    5.39 +import os
    5.40 +import subprocess
    5.41 +import sys
    5.42 +
    5.43 +from PyQt4 import QtCore
    5.44 +from PyQt4 import QtGui
    5.45 +
    5.46 +# local
    5.47 +from about import About
    5.48 +from cygwin import Cygwin
    5.49 +from environment import Environment
    5.50 +import opensecurity_server
    5.51 +
    5.52 +
    5.53 +# ------------------------------------------------------------
    5.54 +# code
    5.55 +
    5.56 +
    5.57 +class Chooser(QtGui.QDialog, object):
    5.58 +    
    5.59 +    """Ask the user what to launch."""
    5.60 +    
    5.61 +    def __init__(self, parent = None, flags = QtCore.Qt.WindowFlags(0)):
    5.62 +    
    5.63 +        super(Chooser, self).__init__(parent, flags)
    5.64 +        self.setWindowTitle('OpenSecuirty Launch Application')
    5.65 +        self.setup_ui()
    5.66 +        
    5.67 +        # known vms and applications
    5.68 +        self._apps, self_vms = [], []
    5.69 +        
    5.70 +        # positionate ourself central
    5.71 +        screen = QtGui.QDesktopWidget().screenGeometry()
    5.72 +        self.resize(self.geometry().width() * 1.25, self.geometry().height())
    5.73 +        size = self.geometry()
    5.74 +        self.move((screen.width() - size.width()) / 2, (screen.height() - size.height()) / 2)
    5.75 +        
    5.76 +        # refresh vm and command input
    5.77 +        self.refresh()
    5.78 +        
    5.79 +        
    5.80 +    def app_get(self):
    5.81 +        """The application of the user."""
    5.82 +        a = str(self._cbApplication.currentText())
    5.83 +        for app in self._apps:
    5.84 +            if a == app['name']:
    5.85 +                return app['command']
    5.86 +        return a
    5.87 +        
    5.88 +    app = property(app_get)
    5.89 +        
    5.90 +
    5.91 +    def clicked_about(self):
    5.92 +        """clicked the about button"""
    5.93 +        dlgAbout = About()
    5.94 +        dlgAbout.exec_()
    5.95 +
    5.96 +
    5.97 +    def clicked_cancel(self):
    5.98 +        """clicked the cancel button"""
    5.99 +        self.reject()
   5.100 +    
   5.101 +
   5.102 +    def clicked_ok(self):
   5.103 +        """clicked the ok button"""
   5.104 +        self.accept()
   5.105 +    
   5.106 +    
   5.107 +    def refresh(self):
   5.108 +        """load the known vms and commands and adjust input fields"""
   5.109 +        
   5.110 +        self._apps = opensecurity_server.query_apps()
   5.111 +        self._vms = opensecurity_server.query_vms()
   5.112 +        
   5.113 +        # add the VMs we know
   5.114 +        self._cbApplication.clear()
   5.115 +        for app in self._apps:
   5.116 +            self._cbApplication.addItem(app['name'])
   5.117 +        
   5.118 +        # add the commands we know
   5.119 +        self._cbVM.clear()
   5.120 +        for vm in self._vms:
   5.121 +            self._cbVM.addItem(vm['name'])
   5.122 +        
   5.123 +        
   5.124 +    def setup_ui(self):
   5.125 +        """Create the widgets."""
   5.126 +        
   5.127 +        lyMain = QtGui.QVBoxLayout(self)
   5.128 +        lyMain.setContentsMargins(8, 8, 8, 8)
   5.129 +        
   5.130 +        # content area: left pixmap, right text
   5.131 +        lyContent = QtGui.QHBoxLayout()
   5.132 +        lyMain.addLayout(lyContent)
   5.133 +        
   5.134 +        # pixmap
   5.135 +        lbPix = QtGui.QLabel()
   5.136 +        lbPix.setPixmap(QtGui.QPixmapCache.find('opensecurity_icon_64'))
   5.137 +        lyContent.addWidget(lbPix, 0, QtCore.Qt.Alignment(QtCore.Qt.AlignTop + QtCore.Qt.AlignHCenter))
   5.138 +        lyContent.addSpacing(16)
   5.139 +        
   5.140 +        # launch ...
   5.141 +        lyLaunch = QtGui.QGridLayout()
   5.142 +        lyContent.addLayout(lyLaunch)
   5.143 +        lbTitle = QtGui.QLabel('Specify details for application to launch.')
   5.144 +        lyLaunch.addWidget(lbTitle, 0, 0, 1, 2)
   5.145 +        
   5.146 +        lbVM = QtGui.QLabel('&VM-ID:')
   5.147 +        lyLaunch.addWidget(lbVM, 1, 0)
   5.148 +        self._cbVM = QtGui.QComboBox()
   5.149 +        self._cbVM.setEditable(True)
   5.150 +        self._cbVM.setInsertPolicy(QtGui.QComboBox.InsertAlphabetically)
   5.151 +        lyLaunch.addWidget(self._cbVM, 1, 1)
   5.152 +        lbVM.setBuddy(self._cbVM)
   5.153 +        
   5.154 +        lbApplication = QtGui.QLabel('&Application:')
   5.155 +        lyLaunch.addWidget(lbApplication, 2, 0)
   5.156 +        self._cbApplication = QtGui.QComboBox()
   5.157 +        self._cbApplication.setEditable(True)
   5.158 +        self._cbApplication.setInsertPolicy(QtGui.QComboBox.InsertAlphabetically)
   5.159 +        lyLaunch.addWidget(self._cbApplication, 2, 1)
   5.160 +        lbApplication.setBuddy(self._cbApplication)
   5.161 +        
   5.162 +        lyLaunch.addWidget(QtGui.QWidget(), 3, 0, 1, 2)
   5.163 +        lyLaunch.setColumnStretch(1, 1)
   5.164 +        lyLaunch.setRowStretch(3, 1)
   5.165 +        
   5.166 +        lyMain.addStretch(1)
   5.167 +        
   5.168 +        # buttons
   5.169 +        lyButton = QtGui.QHBoxLayout()
   5.170 +        lyMain.addLayout(lyButton)
   5.171 +        
   5.172 +        lyButton.addStretch(1)
   5.173 +        btnOk = QtGui.QPushButton('&Ok', self)
   5.174 +        btnOk.setDefault(True)
   5.175 +        btnOk.setMinimumWidth(100)
   5.176 +        lyButton.addWidget(btnOk)
   5.177 +        btnCancel = QtGui.QPushButton('&Cancel', self)
   5.178 +        btnCancel.setMinimumWidth(100)
   5.179 +        lyButton.addWidget(btnCancel)
   5.180 +        btnAbout = QtGui.QPushButton('&About', self)
   5.181 +        btnAbout.setMinimumWidth(100)
   5.182 +        lyButton.addWidget(btnAbout)
   5.183 +        
   5.184 +        button_width = max(btnOk.width(), btnCancel.width(), btnAbout.width())
   5.185 +        btnOk.setMinimumWidth(button_width)
   5.186 +        btnCancel.setMinimumWidth(button_width)
   5.187 +        btnAbout.setMinimumWidth(button_width)
   5.188 +        
   5.189 +        # reduce to the max
   5.190 +        self.resize(lyMain.minimumSize())
   5.191 +        
   5.192 +        # connectors
   5.193 +        btnOk.clicked.connect(self.clicked_ok)
   5.194 +        btnCancel.clicked.connect(self.clicked_cancel)
   5.195 +        btnAbout.clicked.connect(self.clicked_about)
   5.196 +
   5.197 +        
   5.198 +    def user_get(self):
   5.199 +        """The user of the vm of choice."""
   5.200 +        v = str(self._cbVM.currentText())
   5.201 +        for vm in self._vms:
   5.202 +            if v == vm['name']:
   5.203 +                return vm['user']
   5.204 +        return v
   5.205 +        
   5.206 +    user = property(user_get)
   5.207 +    
   5.208 +    
   5.209 +    def vm_get(self):
   5.210 +        """The vm of choice."""
   5.211 +        v = str(self._cbVM.currentText())
   5.212 +        for vm in self._vms:
   5.213 +            if v == vm['name']:
   5.214 +                return vm['ip']
   5.215 +        return v
   5.216 +        
   5.217 +    vm = property(vm_get)
   5.218 +        
   5.219 +        
   5.220 +def ask_user():
   5.221 +    """ask the user for VM and app to start"""
   5.222 +    
   5.223 +    # launch Qt
   5.224 +    app = QtGui.QApplication(sys.argv)
   5.225 +    
   5.226 +    # prebuild the pixmap cache: fetch all jpg, png and jpeg images and load them
   5.227 +    image_path = os.path.join(Environment("OpenSecurity").data_path, '..', 'gfx')
   5.228 +    for file in os.listdir(image_path):
   5.229 +        if file.lower().rpartition('.')[2] in ('jpg', 'png', 'jpeg'):
   5.230 +            QtGui.QPixmapCache.insert(file.lower().rpartition('.')[0], QtGui.QPixmap(os.path.join(image_path, file)))
   5.231 +            
   5.232 +    # we should have now our application icon
   5.233 +    app.setWindowIcon(QtGui.QIcon(QtGui.QPixmapCache.find('opensecurity_icon_64')))
   5.234 +    
   5.235 +    # pop up the dialog
   5.236 +    dlg = Chooser()
   5.237 +    dlg.show()
   5.238 +    app.exec_()
   5.239 +    
   5.240 +    if dlg.result() == QtGui.QDialog.Accepted:
   5.241 +        return dlg.user, dlg.vm, dlg.app
   5.242 +
   5.243 +    return '', '', ''
   5.244 +    
   5.245 +
   5.246 +def main():
   5.247 +    """entry point"""
   5.248 +    
   5.249 +    # parse command line
   5.250 +    parser = argparse.ArgumentParser(description = 'OpenSecurity Launcher: run application in VM')
   5.251 +    parser.add_argument('user', metavar='USER', help='USER on Virtual Machine', nargs='?', type=str, default='')
   5.252 +    parser.add_argument('ip', metavar='IP', help='IP of Virtual Machine', nargs='?', type=str, default='')
   5.253 +    parser.add_argument('command', metavar='COMMAND', help='Full path of command and arguments to start inside VM', nargs='?', type=str, default='')
   5.254 +    args = parser.parse_args()
   5.255 +    
   5.256 +    # we must have at least all or none set
   5.257 +    set_user = args.user != ''
   5.258 +    set_ip = args.ip != ''
   5.259 +    set_command = args.command != ''
   5.260 +    set_ALL = set_user and set_ip and set_command
   5.261 +    set_NONE = (not set_user) and (not set_ip) and (not set_command)
   5.262 +    if (not set_ALL) and (not set_NONE):
   5.263 +        sys.stderr.write("Please specify user, ip and command or none.\n")
   5.264 +        sys.stderr.write("Type '--help' for help.\n")
   5.265 +        sys.exit(1)
   5.266 +        
   5.267 +    # check if we need to ask the user
   5.268 +    if set_NONE:
   5.269 +        args.user, args.ip, args.command = ask_user()
   5.270 +        
   5.271 +    # still no IP? --> no chance, over and out!
   5.272 +    if args.ip == '':
   5.273 +        sys.exit(0)
   5.274 +        
   5.275 +    # ensure we have our X11 running
   5.276 +    Cygwin.start_X11()
   5.277 +    
   5.278 +    # the SSH command
   5.279 +    user_at_guest = args.user + '@' + args.ip
   5.280 +    ssh = 'DISPLAY=:0 /usr/bin/ssh -Y ' + user_at_guest + ' ' + args.command
   5.281 +    print(ssh)
   5.282 +    
   5.283 +    # off we go!
   5.284 +    Cygwin()(['/bin/bash', '--login', '-i', '-c', ssh], None, None, None)
   5.285 +
   5.286 +    
   5.287 +# start
   5.288 +if __name__ == "__main__":
   5.289 +    main()
   5.290 +
     6.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.2 +++ b/OpenSecurity/bin/opensecurity_client_restful_server.py	Fri Dec 06 10:51:15 2013 +0100
     6.3 @@ -0,0 +1,215 @@
     6.4 +#!/bin/env python
     6.5 +# -*- coding: utf-8 -*-
     6.6 +
     6.7 +# ------------------------------------------------------------
     6.8 +# opensecurity_client_restful_server
     6.9 +# 
    6.10 +# the OpenSecurity client RESTful server
    6.11 +#
    6.12 +# Autor: Oliver Maurhart, <oliver.maurhart@ait.ac.at>
    6.13 +#
    6.14 +# Copyright (C) 2013 AIT Austrian Institute of Technology
    6.15 +# AIT Austrian Institute of Technology GmbH
    6.16 +# Donau-City-Strasse 1 | 1220 Vienna | Austria
    6.17 +# http://www.ait.ac.at
    6.18 +#
    6.19 +# This program is free software; you can redistribute it and/or
    6.20 +# modify it under the terms of the GNU General Public License
    6.21 +# as published by the Free Software Foundation version 2.
    6.22 +# 
    6.23 +# This program is distributed in the hope that it will be useful,
    6.24 +# but WITHOUT ANY WARRANTY; without even the implied warranty of
    6.25 +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    6.26 +# GNU General Public License for more details.
    6.27 +# 
    6.28 +# You should have received a copy of the GNU General Public License
    6.29 +# along with this program; if not, write to the Free Software
    6.30 +# Foundation, Inc., 51 Franklin Street, Fifth Floor, 
    6.31 +# Boston, MA  02110-1301, USA.
    6.32 +# ------------------------------------------------------------
    6.33 +
    6.34 +
    6.35 +# ------------------------------------------------------------
    6.36 +# imports
    6.37 +
    6.38 +import os
    6.39 +import os.path
    6.40 +import subprocess
    6.41 +import sys
    6.42 +import web
    6.43 +
    6.44 +# local
    6.45 +from environment import Environment
    6.46 +import opensecurity_server
    6.47 +
    6.48 +
    6.49 +# ------------------------------------------------------------
    6.50 +# const
    6.51 +
    6.52 +
    6.53 +__version__ = "0.1"
    6.54 +
    6.55 +
    6.56 +"""All the URLs we know mapping to class handler"""
    6.57 +opensecurity_urls = (
    6.58 +    '/application',             'os_application',
    6.59 +    '/credentials',             'os_credentials',
    6.60 +    '/password',                'os_password',
    6.61 +    '/',                        'os_root'
    6.62 +)
    6.63 +
    6.64 +
    6.65 +# ------------------------------------------------------------
    6.66 +# code
    6.67 +
    6.68 +
    6.69 +class os_application:
    6.70 +    """OpenSecurity '/application' handler.
    6.71 +    
    6.72 +    This is called on GET /application?vm=VM-ID&app=APP-ID
    6.73 +    This tries to access the vm identified with the label VM-ID
    6.74 +    and launched the application identified APP-ID
    6.75 +    """
    6.76 +    
    6.77 +    def GET(self):
    6.78 +        
    6.79 +        # pick the arguments
    6.80 +        args = web.input()
    6.81 +        
    6.82 +        # we _need_ a vm
    6.83 +        if not "vm" in args:
    6.84 +            raise web.badrequest()
    6.85 +        
    6.86 +        # we _need_ a app
    6.87 +        if not "app" in args:
    6.88 +            raise web.badrequest()
    6.89 +        
    6.90 +        apps = opensecurity_server.query_apps()
    6.91 +        vms = opensecurity_server.query_vms()
    6.92 +        
    6.93 +        # check if we do have valid vm
    6.94 +        v = [v for v in vms if v['name'] == args.vm]
    6.95 +        if len(v) == 0:
    6.96 +            raise web.notfound('vm not found')
    6.97 +        v = v[0]
    6.98 +        
    6.99 +        # check if we do have a valid app
   6.100 +        a = [a for a in apps if a['name'] == args.app]
   6.101 +        if len(a) == 0:
   6.102 +            raise web.notfound('app not found')
   6.103 +        a = a[0]
   6.104 +        
   6.105 +        # invoke launch with 
   6.106 +        res = "starting: launch " + v['user'] + " " + v['ip'] + " " + a['command']
   6.107 +
   6.108 +        launch_image = os.path.join(sys.path[0], 'launch.py')
   6.109 +        process_command = [sys.executable, launch_image, v['user'], v['ip'], a['command']]
   6.110 +        process = subprocess.Popen(process_command, shell = False, stdout = subprocess.PIPE)
   6.111 +        result = process.communicate()[0]
   6.112 +        if process.returncode != 0:
   6.113 +            return 'Launch of application aborted.'
   6.114 +        
   6.115 +        return result
   6.116 +        
   6.117 +
   6.118 +class os_credentials:
   6.119 +    """OpenSecurity '/credentials' handler.
   6.120 +    
   6.121 +    This is called on GET /credentials?text=TEXT.
   6.122 +    Ideally this should pop up a user dialog to insert his
   6.123 +    credentials based the given TEXT.
   6.124 +    """
   6.125 +    
   6.126 +    def GET(self):
   6.127 +        
   6.128 +        # pick the arguments
   6.129 +        args = web.input()
   6.130 +        
   6.131 +        # we _need_ a device id
   6.132 +        if not "text" in args:
   6.133 +            raise web.badrequest()
   6.134 +        
   6.135 +        # invoke the user dialog as a subprocess
   6.136 +        dlg_credentials_image = os.path.join(sys.path[0], 'opensecurity_dialog.py')
   6.137 +        process_command = [sys.executable, dlg_credentials_image, 'credentials', args.text]
   6.138 +        process = subprocess.Popen(process_command, shell = False, stdout = subprocess.PIPE)
   6.139 +        result = process.communicate()[0]
   6.140 +        if process.returncode != 0:
   6.141 +            return 'Credentials request has been aborted.'
   6.142 +        
   6.143 +        return result
   6.144 +
   6.145 +
   6.146 +class os_password:
   6.147 +    """OpenSecurity '/password' handler.
   6.148 +    
   6.149 +    This is called on GET /password?text=TEXT.
   6.150 +    Ideally this should pop up a user dialog to insert his
   6.151 +    password based device name.
   6.152 +    """
   6.153 +    
   6.154 +    def GET(self):
   6.155 +        
   6.156 +        # pick the arguments
   6.157 +        args = web.input()
   6.158 +        
   6.159 +        # we _need_ a device id
   6.160 +        if not "text" in args:
   6.161 +            raise web.badrequest()
   6.162 +            
   6.163 +        # invoke the user dialog as a subprocess
   6.164 +        dlg_credentials_image = os.path.join(sys.path[0], 'opensecurity_dialog.py')
   6.165 +        process_command = [sys.executable, dlg_credentials_image, 'password', args.text]
   6.166 +        process = subprocess.Popen(process_command, shell = False, stdout = subprocess.PIPE)
   6.167 +        result = process.communicate()[0]
   6.168 +        if process.returncode != 0:
   6.169 +            return 'password request has been aborted.'
   6.170 +        
   6.171 +        return result
   6.172 +
   6.173 +
   6.174 +class os_root:
   6.175 +    """OpenSecurity '/' handler"""
   6.176 +    
   6.177 +    def GET(self):
   6.178 +    
   6.179 +        res = "OpenSecurity-Client RESTFul Server { \"version\": \"%s\" }" % __version__
   6.180 +        
   6.181 +        # add some sample links
   6.182 +        res = res + """
   6.183 +        
   6.184 +USAGE EXAMPLES:
   6.185 +        
   6.186 +Request a password: 
   6.187 +    (copy paste this into your browser's address field after the host:port)
   6.188 +    
   6.189 +    /password?text=Give+me+a+password+for+device+%22My+USB+Drive%22+(ID%3A+32090-AAA-X0)
   6.190 +    
   6.191 +    (eg.: http://127.0.0.1:8090/password?text=Give+me+a+password+for+device+%22My+USB+Drive%22+(ID%3A+32090-AAA-X0))
   6.192 +    NOTE: check yout taskbar, the dialog window may not pop up in front of your browser window.
   6.193 +    
   6.194 +    
   6.195 +Request a combination of user and password:
   6.196 +    (copy paste this into your browser's address field after the host:port)
   6.197 +    
   6.198 +    /credentials?text=Tell+the+NSA+which+credentials+to+use+in+order+to+avoid+hacking+noise+on+wire.
   6.199 +    
   6.200 +    (eg.: http://127.0.0.1:8090/credentials?text=Tell+the+NSA+which+credentials+to+use+in+order+to+avoid+hacking+noise+on+wire.)
   6.201 +    NOTE: check yout taskbar, the dialog window may not pop up in front of your browser window.
   6.202 +    
   6.203 +
   6.204 +Start a Browser:
   6.205 +    (copy paste this into your browser's address field after the host:port)
   6.206 +
   6.207 +    /application?vm=Debian+7&app=Browser
   6.208 +
   6.209 +    (e.g. http://127.0.0.1:8090/application?vm=Debian+7&app=Browser)
   6.210 +        """
   6.211 +    
   6.212 +        return res
   6.213 +
   6.214 +
   6.215 +# start
   6.216 +if __name__ == "__main__":
   6.217 +    server = web.application(opensecurity_urls, globals())
   6.218 +    server.run()
     7.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     7.2 +++ b/OpenSecurity/bin/opensecurity_dialog.py	Fri Dec 06 10:51:15 2013 +0100
     7.3 @@ -0,0 +1,93 @@
     7.4 +#!/bin/env python
     7.5 +# -*- coding: utf-8 -*-
     7.6 +
     7.7 +# ------------------------------------------------------------
     7.8 +# opensecurity-dialog
     7.9 +# 
    7.10 +# an opensecurity dialog
    7.11 +#
    7.12 +# Autor: Oliver Maurhart, <oliver.maurhart@ait.ac.at>
    7.13 +#
    7.14 +# Copyright (C) 2013 AIT Austrian Institute of Technology
    7.15 +# AIT Austrian Institute of Technology GmbH
    7.16 +# Donau-City-Strasse 1 | 1220 Vienna | Austria
    7.17 +# http://www.ait.ac.at
    7.18 +#
    7.19 +# This program is free software; you can redistribute it and/or
    7.20 +# modify it under the terms of the GNU General Public License
    7.21 +# as published by the Free Software Foundation version 2.
    7.22 +# 
    7.23 +# This program is distributed in the hope that it will be useful,
    7.24 +# but WITHOUT ANY WARRANTY; without even the implied warranty of
    7.25 +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    7.26 +# GNU General Public License for more details.
    7.27 +# 
    7.28 +# You should have received a copy of the GNU General Public License
    7.29 +# along with this program; if not, write to the Free Software
    7.30 +# Foundation, Inc., 51 Franklin Street, Fifth Floor, 
    7.31 +# Boston, MA  02110-1301, USA.
    7.32 +# ------------------------------------------------------------
    7.33 +
    7.34 +
    7.35 +# ------------------------------------------------------------
    7.36 +# imports
    7.37 +
    7.38 +import argparse
    7.39 +import os
    7.40 +import sys
    7.41 +
    7.42 +from PyQt4 import QtCore
    7.43 +from PyQt4 import QtGui
    7.44 +
    7.45 +# local
    7.46 +from credentials import Credentials
    7.47 +from environment import Environment
    7.48 +from password import Password
    7.49 +
    7.50 +
    7.51 +# ------------------------------------------------------------
    7.52 +# code
    7.53 +
    7.54 +
    7.55 +def main():
    7.56 +    
    7.57 +    # parse command line
    7.58 +    parser = argparse.ArgumentParser(description = 'OpenSecurity Dialog.')
    7.59 +    parser.add_argument('mode', metavar='MODE', help='dialog mode: \'password\' or \'credentials\'')
    7.60 +    parser.add_argument('text', metavar='TEXT', help='text to show')
    7.61 +    args = parser.parse_args()
    7.62 +    
    7.63 +    app = QtGui.QApplication(sys.argv)
    7.64 +    
    7.65 +    # prebuild the pixmap cache: fetch all jpg, png and jpeg images and load them
    7.66 +    data_path = Environment("OpenSecurity").data_path
    7.67 +    image_path = os.path.join(data_path, '..', 'gfx')
    7.68 +    for file in os.listdir(image_path):
    7.69 +        if file.lower().rpartition('.')[2] in ('jpg', 'png', 'jpeg'):
    7.70 +            QtGui.QPixmapCache.insert(file.lower().rpartition('.')[0], QtGui.QPixmap(os.path.join(image_path, file)))
    7.71 +            
    7.72 +    # we should have now our application icon
    7.73 +    app.setWindowIcon(QtGui.QIcon(QtGui.QPixmapCache.find('opensecurity_icon_64')))
    7.74 +    
    7.75 +    if args.mode == 'password':
    7.76 +        dlg = Password(args.text)
    7.77 +    
    7.78 +    if args.mode == 'credentials':
    7.79 +        dlg = Credentials(args.text)
    7.80 +    
    7.81 +    # pop up the dialog
    7.82 +    dlg.show()
    7.83 +    app.exec_()
    7.84 +    
    7.85 +    # give proper result code
    7.86 +    if dlg.result() == QtGui.QDialog.Accepted:
    7.87 +        res = 0
    7.88 +    else:
    7.89 +        res = 1
    7.90 +    sys.exit(res)
    7.91 +    
    7.92 +
    7.93 +# start
    7.94 +if __name__ == "__main__":
    7.95 +    main()
    7.96 +
     8.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     8.2 +++ b/OpenSecurity/bin/opensecurity_server.py	Fri Dec 06 10:51:15 2013 +0100
     8.3 @@ -0,0 +1,70 @@
     8.4 +#!/bin/env python
     8.5 +# -*- coding: utf-8 -*-
     8.6 +
     8.7 +# ------------------------------------------------------------
     8.8 +# opensecurity-server
     8.9 +# 
    8.10 +# talk to the opensecurity server
    8.11 +#
    8.12 +# Autor: Oliver Maurhart, <oliver.maurhart@ait.ac.at>
    8.13 +#
    8.14 +# Copyright (C) 2013 AIT Austrian Institute of Technology
    8.15 +# AIT Austrian Institute of Technology GmbH
    8.16 +# Donau-City-Strasse 1 | 1220 Vienna | Austria
    8.17 +# http://www.ait.ac.at
    8.18 +#
    8.19 +# This program is free software; you can redistribute it and/or
    8.20 +# modify it under the terms of the GNU General Public License
    8.21 +# as published by the Free Software Foundation version 2.
    8.22 +# 
    8.23 +# This program is distributed in the hope that it will be useful,
    8.24 +# but WITHOUT ANY WARRANTY; without even the implied warranty of
    8.25 +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    8.26 +# GNU General Public License for more details.
    8.27 +# 
    8.28 +# You should have received a copy of the GNU General Public License
    8.29 +# along with this program; if not, write to the Free Software
    8.30 +# Foundation, Inc., 51 Franklin Street, Fifth Floor, 
    8.31 +# Boston, MA  02110-1301, USA.
    8.32 +# ------------------------------------------------------------
    8.33 +
    8.34 +# ------------------------------------------------------------
    8.35 +# import
    8.36 +
    8.37 +from pprint import PrettyPrinter
    8.38 +
    8.39 +
    8.40 +# ------------------------------------------------------------
    8.41 +# code
    8.42 +
    8.43 +def query_apps():
    8.44 +    """get the list of known apps"""
    8.45 +    
    8.46 +    # TODO: REPLACE THIS HARDCODED STUFF WITH REAL CODE TO THE OS SERVER
    8.47 +    apps = [ 
    8.48 +        { 'vm': '', 'name': 'Browser', 'command': '/usr/bin/iceweasel'}, 
    8.49 +    ]
    8.50 +    
    8.51 +    return apps
    8.52 +    
    8.53 +
    8.54 +def query_vms():
    8.55 +    """get the list of registered vms, their ip and the prefered user"""
    8.56 +    
    8.57 +    # TODO: REPLACE THIS HARDCODED STUFF WITH REAL CODE TO THE OS SERVER
    8.58 +    vms = [ 
    8.59 +        { 'user': 'opensec', 'name': 'Debian 7', 'ip': '192.168.56.101'}, 
    8.60 +        { 'user': 'opensec', 'name': 'Anit-Virus VM', 'ip': '192.168.56.101'}
    8.61 +    ]
    8.62 +    
    8.63 +    return vms
    8.64 +
    8.65 +    
    8.66 +# start
    8.67 +if __name__ == "__main__":
    8.68 +    print("known apps: ")
    8.69 +    PrettyPrinter().pprint(query_apps())
    8.70 +    print("known vms: ")
    8.71 +    PrettyPrinter().pprint(query_vms())
    8.72 +    
    8.73 +
     9.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     9.2 +++ b/OpenSecurity/bin/opensecurity_tray.py	Fri Dec 06 10:51:15 2013 +0100
     9.3 @@ -0,0 +1,131 @@
     9.4 +#!/bin/env python
     9.5 +# -*- coding: utf-8 -*-
     9.6 +
     9.7 +# ------------------------------------------------------------
     9.8 +# opensecurity-dialog
     9.9 +# 
    9.10 +# an opensecurity dialog
    9.11 +#
    9.12 +# Autor: Oliver Maurhart, <oliver.maurhart@ait.ac.at>
    9.13 +#
    9.14 +# Copyright (C) 2013 AIT Austrian Institute of Technology
    9.15 +# AIT Austrian Institute of Technology GmbH
    9.16 +# Donau-City-Strasse 1 | 1220 Vienna | Austria
    9.17 +# http://www.ait.ac.at
    9.18 +#
    9.19 +# This program is free software; you can redistribute it and/or
    9.20 +# modify it under the terms of the GNU General Public License
    9.21 +# as published by the Free Software Foundation version 2.
    9.22 +# 
    9.23 +# This program is distributed in the hope that it will be useful,
    9.24 +# but WITHOUT ANY WARRANTY; without even the implied warranty of
    9.25 +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    9.26 +# GNU General Public License for more details.
    9.27 +# 
    9.28 +# You should have received a copy of the GNU General Public License
    9.29 +# along with this program; if not, write to the Free Software
    9.30 +# Foundation, Inc., 51 Franklin Street, Fifth Floor, 
    9.31 +# Boston, MA  02110-1301, USA.
    9.32 +# ------------------------------------------------------------
    9.33 +
    9.34 +
    9.35 +# ------------------------------------------------------------
    9.36 +# imports
    9.37 +
    9.38 +import argparse
    9.39 +import os
    9.40 +import subprocess
    9.41 +import sys
    9.42 +
    9.43 +from PyQt4 import QtCore
    9.44 +from PyQt4 import QtGui
    9.45 +
    9.46 +# local
    9.47 +from about import About
    9.48 +from environment import Environment
    9.49 +
    9.50 +
    9.51 +# ------------------------------------------------------------
    9.52 +# code
    9.53 +
    9.54 +
    9.55 +class OpenSecurityTrayIcon(QtGui.QSystemTrayIcon):
    9.56 +    
    9.57 +    """This is the OpenSecuirty Tray Icon"""
    9.58 +
    9.59 +    def __init__(self, icon, parent=None):
    9.60 +        
    9.61 +        super(OpenSecurityTrayIcon, self).__init__(icon, parent)
    9.62 +        self.setup_ui()
    9.63 +        
    9.64 +        
    9.65 +    def clicked_about(self):
    9.66 +        """clicked about"""
    9.67 +        dlgAbout = About()
    9.68 +        dlgAbout.exec_()
    9.69 +    
    9.70 +
    9.71 +    def clicked_exit(self):
    9.72 +        """clicked exit"""
    9.73 +        sys.exit(0)
    9.74 +    
    9.75 +
    9.76 +    def clicked_launch_application(self):
    9.77 +        """clicked the launch an application"""
    9.78 +        dlg_launch_image = os.path.join(sys.path[0], 'launch.pyw')
    9.79 +        process_command = [sys.executable, dlg_launch_image]
    9.80 +        print(process_command)
    9.81 +        process = subprocess.Popen(process_command, shell = False)
    9.82 +        process.communicate()
    9.83 +            
    9.84 +            
    9.85 +    def clicked_refresh(self):
    9.86 +        """clicked refresh"""
    9.87 +        self.setup_ui()
    9.88 +
    9.89 +    
    9.90 +    def setup_ui(self):
    9.91 +        """create the user interface
    9.92 +        As for the system tray this is 'just' the context menu.
    9.93 +        """
    9.94 +    
    9.95 +        # define the tray icon menu
    9.96 +        menu = QtGui.QMenu(self.parent())
    9.97 +        self.setContextMenu(menu)
    9.98 +        
    9.99 +        # add known apps
   9.100 +        
   9.101 +        # add standard menu items
   9.102 +        cAcLaunch = menu.addAction(QtGui.QIcon(QtGui.QPixmapCache.find('opensecurity_icon_64')), 'Lauch Application')
   9.103 +        menu.addSeparator()
   9.104 +        cAcRefresh = menu.addAction('Refresh')
   9.105 +        cAcAbout = menu.addAction("About")
   9.106 +        cAcExit = menu.addAction("Exit")
   9.107 +        
   9.108 +        cAcLaunch.triggered.connect(self.clicked_launch_application)
   9.109 +        cAcRefresh.triggered.connect(self.clicked_refresh)
   9.110 +        cAcAbout.triggered.connect(self.clicked_about)
   9.111 +        cAcExit.triggered.connect(self.clicked_exit)
   9.112 +        
   9.113 +        
   9.114 +def main():
   9.115 +    
   9.116 +    app = QtGui.QApplication(sys.argv)
   9.117 +
   9.118 +    # prebuild the pixmap cache: fetch all jpg, png and jpeg images and load them
   9.119 +    image_path = os.path.join(Environment("OpenSecurity").data_path, '..', 'gfx')
   9.120 +    for file in os.listdir(image_path):
   9.121 +        if file.lower().rpartition('.')[2] in ('jpg', 'png', 'jpeg'):
   9.122 +            QtGui.QPixmapCache.insert(file.lower().rpartition('.')[0], QtGui.QPixmap(os.path.join(image_path, file)))
   9.123 +
   9.124 +    w = QtGui.QWidget()
   9.125 +    trayIcon = OpenSecurityTrayIcon(QtGui.QIcon(QtGui.QPixmapCache.find('opensecurity_icon_64')), w)
   9.126 +
   9.127 +    trayIcon.show()
   9.128 +    sys.exit(app.exec_())
   9.129 +   
   9.130 +
   9.131 +# start
   9.132 +if __name__ == "__main__":
   9.133 +    main()
   9.134 +
    10.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    10.2 +++ b/OpenSecurity/bin/opensecurityd.py	Fri Dec 06 10:51:15 2013 +0100
    10.3 @@ -0,0 +1,119 @@
    10.4 +#!/bin/env python
    10.5 +# -*- coding: utf-8 -*-
    10.6 +
    10.7 +# ------------------------------------------------------------
    10.8 +# opensecurityd
    10.9 +# 
   10.10 +# the opensecurityd as RESTful server
   10.11 +#
   10.12 +# Autor: Oliver Maurhart, <oliver.maurhart@ait.ac.at>
   10.13 +#
   10.14 +# Copyright (C) 2013 AIT Austrian Institute of Technology
   10.15 +# AIT Austrian Institute of Technology GmbH
   10.16 +# Donau-City-Strasse 1 | 1220 Vienna | Austria
   10.17 +# http://www.ait.ac.at
   10.18 +#
   10.19 +# This program is free software; you can redistribute it and/or
   10.20 +# modify it under the terms of the GNU General Public License
   10.21 +# as published by the Free Software Foundation version 2.
   10.22 +# 
   10.23 +# This program is distributed in the hope that it will be useful,
   10.24 +# but WITHOUT ANY WARRANTY; without even the implied warranty of
   10.25 +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   10.26 +# GNU General Public License for more details.
   10.27 +# 
   10.28 +# You should have received a copy of the GNU General Public License
   10.29 +# along with this program; if not, write to the Free Software
   10.30 +# Foundation, Inc., 51 Franklin Street, Fifth Floor, 
   10.31 +# Boston, MA  02110-1301, USA.
   10.32 +# ------------------------------------------------------------
   10.33 +
   10.34 +
   10.35 +# ------------------------------------------------------------
   10.36 +# imports
   10.37 +
   10.38 +import os
   10.39 +import os.path
   10.40 +import subprocess
   10.41 +import sys
   10.42 +import web
   10.43 +from vmmanager.vmmanager import VMManager
   10.44 +
   10.45 +# local
   10.46 +from environment import Environment
   10.47 +
   10.48 +
   10.49 +# ------------------------------------------------------------
   10.50 +# const
   10.51 +
   10.52 +__version__ = "0.1"
   10.53 +
   10.54 +
   10.55 +"""All the URLs we know mapping to class handler"""
   10.56 +opensecurity_urls = (
   10.57 +    '/device_change',           'os_device_change',
   10.58 +    '/sdvms',                   'os_sdvms',
   10.59 +    '/vms',                     'os_vms',
   10.60 +    '/vms/(.*)',                'os_vm',
   10.61 +    '/',                        'os_root'
   10.62 +)
   10.63 +
   10.64 +
   10.65 +# ------------------------------------------------------------
   10.66 +# vars
   10.67 +
   10.68 +# Global VMManager instance
   10.69 +gvm_mgr = VMManager()
   10.70 +
   10.71 +
   10.72 +# ------------------------------------------------------------
   10.73 +# code
   10.74 +
   10.75 +
   10.76 +class os_device_change:
   10.77 +    """OpenSecurity '/device_change' handler"""
   10.78 +    
   10.79 +    def GET(self):
   10.80 +        #gvm_mgr.configureHostNetworking()
   10.81 +        print 'received device_change'
   10.82 +        return "os_device_change"
   10.83 +
   10.84 +
   10.85 +class os_sdvms:
   10.86 +    """OpenSecurity '/sdvms' handler"""
   10.87 +    
   10.88 +    def GET(self):
   10.89 +        return gvm_mgr.listSDVM() 
   10.90 +            
   10.91 +
   10.92 +class os_vm:
   10.93 +    """OpenSecurity '/vms/VM' handler"""
   10.94 +    
   10.95 +    def GET(self, name):
   10.96 +        return gvm_mgr.getVMInfo(name)
   10.97 +            
   10.98 +
   10.99 +class os_vms:
  10.100 +    """OpenSecurity '/vms' handler"""
  10.101 +    
  10.102 +    def GET(self):
  10.103 +        return gvm_mgr.listVM() 
  10.104 +            
  10.105 +
  10.106 +class os_root:
  10.107 +    """OpenSecurity '/' handler"""
  10.108 +    
  10.109 +    def GET(self):
  10.110 +        res = "'os_server': { "
  10.111 +        res += "'version': '" + __version__ + "', "
  10.112 +        res += "'virtualbox_path': '" + gvm_mgr.vBoxPath + "', "
  10.113 +        res += "'machine_folder': '" + gvm_mgr.getDefaultMachineFolder() + "' "
  10.114 +        res += "}"
  10.115 +        return res
  10.116 +
  10.117 +
  10.118 +# start
  10.119 +if __name__ == "__main__":
  10.120 +    server = web.application(opensecurity_urls, globals())
  10.121 +    server.run()
  10.122 +
    11.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    11.2 +++ b/OpenSecurity/bin/password.py	Fri Dec 06 10:51:15 2013 +0100
    11.3 @@ -0,0 +1,150 @@
    11.4 +#!/bin/env python
    11.5 +# -*- coding: utf-8 -*-
    11.6 +
    11.7 +# ------------------------------------------------------------
    11.8 +# password-dialog
    11.9 +# 
   11.10 +# ask the user a password
   11.11 +#
   11.12 +# Autor: Oliver Maurhart, <oliver.maurhart@ait.ac.at>
   11.13 +#
   11.14 +# Copyright (C) 2013 AIT Austrian Institute of Technology
   11.15 +# AIT Austrian Institute of Technology GmbH
   11.16 +# Donau-City-Strasse 1 | 1220 Vienna | Austria
   11.17 +# http://www.ait.ac.at
   11.18 +#
   11.19 +# This program is free software; you can redistribute it and/or
   11.20 +# modify it under the terms of the GNU General Public License
   11.21 +# as published by the Free Software Foundation version 2.
   11.22 +# 
   11.23 +# This program is distributed in the hope that it will be useful,
   11.24 +# but WITHOUT ANY WARRANTY; without even the implied warranty of
   11.25 +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   11.26 +# GNU General Public License for more details.
   11.27 +# 
   11.28 +# You should have received a copy of the GNU General Public License
   11.29 +# along with this program; if not, write to the Free Software
   11.30 +# Foundation, Inc., 51 Franklin Street, Fifth Floor, 
   11.31 +# Boston, MA  02110-1301, USA.
   11.32 +# ------------------------------------------------------------
   11.33 +
   11.34 +
   11.35 +# ------------------------------------------------------------
   11.36 +# imports
   11.37 +
   11.38 +import sys
   11.39 +
   11.40 +from PyQt4 import QtCore
   11.41 +from PyQt4 import QtGui
   11.42 +
   11.43 +# local
   11.44 +from about import About
   11.45 +
   11.46 +# ------------------------------------------------------------
   11.47 +# code
   11.48 +
   11.49 +
   11.50 +class Password(QtGui.QDialog):
   11.51 +    
   11.52 +    """Ask the user for a password."""
   11.53 +    
   11.54 +    def __init__(self, text, parent = None, flags = QtCore.Qt.WindowFlags(0)):
   11.55 +        
   11.56 +        # super call and widget init
   11.57 +        super(Password, self).__init__(parent, flags)
   11.58 +        self.setWindowTitle('OpenSecuirty Password Request')
   11.59 +        self.setup_ui()
   11.60 +        
   11.61 +        # positionate ourself central
   11.62 +        screen = QtGui.QDesktopWidget().screenGeometry()
   11.63 +        self.resize(self.geometry().width() * 1.25, self.geometry().height())
   11.64 +        size = self.geometry()
   11.65 +        self.move((screen.width() - size.width()) / 2, (screen.height() - size.height()) / 2)
   11.66 +        
   11.67 +        # fix up text
   11.68 +        self.lbText.setText(text)
   11.69 +        
   11.70 +
   11.71 +    def clicked_about(self):
   11.72 +        """clicked the about button"""
   11.73 +        dlgAbout = About()
   11.74 +        dlgAbout.exec_()
   11.75 +    
   11.76 +
   11.77 +    def clicked_cancel(self):
   11.78 +        """clicked the cancel button"""
   11.79 +        self.reject()
   11.80 +    
   11.81 +
   11.82 +    def clicked_ok(self):
   11.83 +        """clicked the ok button"""
   11.84 +        sys.stdout.write('{ ')
   11.85 +        sys.stdout.write('\'password\': \'')
   11.86 +        sys.stdout.write(self.edPassword.text())
   11.87 +        sys.stdout.write('\' ')
   11.88 +        sys.stdout.write('}\n')
   11.89 +        self.accept()
   11.90 +    
   11.91 +
   11.92 +    def setup_ui(self):
   11.93 +        
   11.94 +        """Create the widgets."""
   11.95 +        
   11.96 +        lyMain = QtGui.QVBoxLayout(self)
   11.97 +        lyMain.setContentsMargins(8, 8, 8, 8)
   11.98 +        
   11.99 +        # content area: left pixmap, right text
  11.100 +        lyContent = QtGui.QHBoxLayout()
  11.101 +        lyMain.addLayout(lyContent)
  11.102 +        
  11.103 +        # pixmap
  11.104 +        lbPix = QtGui.QLabel()
  11.105 +        lbPix.setPixmap(QtGui.QPixmapCache.find('opensecurity_icon_64'))
  11.106 +        lyContent.addWidget(lbPix, 0, QtCore.Qt.Alignment(QtCore.Qt.AlignTop + QtCore.Qt.AlignHCenter))
  11.107 +        lyContent.addSpacing(16)
  11.108 +        
  11.109 +        # text ...
  11.110 +        lyText = QtGui.QVBoxLayout()
  11.111 +        lyContent.addLayout(lyText)
  11.112 +        self.lbText = QtGui.QLabel()
  11.113 +        lyText.addWidget(self.lbText)
  11.114 +        lyPassword = QtGui.QHBoxLayout()
  11.115 +        lyText.addLayout(lyPassword)
  11.116 +        lbPassword = QtGui.QLabel('&Password:')
  11.117 +        lyPassword.addWidget(lbPassword)
  11.118 +        self.edPassword = QtGui.QLineEdit()
  11.119 +        self.edPassword.setEchoMode(QtGui.QLineEdit.Password)
  11.120 +        lyPassword.addWidget(self.edPassword)
  11.121 +        lbPassword.setBuddy(self.edPassword)
  11.122 +        lyText.addStretch(1)
  11.123 +        
  11.124 +        lyMain.addStretch(1)
  11.125 +        
  11.126 +        # buttons
  11.127 +        lyButton = QtGui.QHBoxLayout()
  11.128 +        lyMain.addLayout(lyButton)
  11.129 +        
  11.130 +        lyButton.addStretch(1)
  11.131 +        btnOk = QtGui.QPushButton('&Ok', self)
  11.132 +        btnOk.setDefault(True)
  11.133 +        btnOk.setMinimumWidth(100)
  11.134 +        lyButton.addWidget(btnOk)
  11.135 +        btnCancel = QtGui.QPushButton('&Cancel', self)
  11.136 +        btnCancel.setMinimumWidth(100)
  11.137 +        lyButton.addWidget(btnCancel)
  11.138 +        btnAbout = QtGui.QPushButton('&About', self)
  11.139 +        btnAbout.setMinimumWidth(100)
  11.140 +        lyButton.addWidget(btnAbout)
  11.141 +        
  11.142 +        button_width = max(btnOk.width(), btnCancel.width(), btnAbout.width())
  11.143 +        btnOk.setMinimumWidth(button_width)
  11.144 +        btnCancel.setMinimumWidth(button_width)
  11.145 +        btnAbout.setMinimumWidth(button_width)
  11.146 +        
  11.147 +        # reduce to the max
  11.148 +        self.resize(lyMain.minimumSize())
  11.149 +        
  11.150 +        # connectors
  11.151 +        btnOk.clicked.connect(self.clicked_ok)
  11.152 +        btnCancel.clicked.connect(self.clicked_cancel)
  11.153 +        btnAbout.clicked.connect(self.clicked_about)
    12.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    12.2 +++ b/OpenSecurity/bin/vmmanager/PKG-INFO	Fri Dec 06 10:51:15 2013 +0100
    12.3 @@ -0,0 +1,10 @@
    12.4 +Metadata-Version: 1.0
    12.5 +Name: vmmanager.py
    12.6 +Version: 0.1
    12.7 +Summary: vmmanager.py: manages GustVM's
    12.8 +Home-page:  http://webpy.org/
    12.9 +Author: Mihai Bartha
   12.10 +Author-email: mihai.bartha@ait.ac.at
   12.11 +License: Public domain
   12.12 +Description: Module to manage virtualbox guests and host
   12.13 +Platform: any
    13.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    13.2 +++ b/OpenSecurity/bin/vmmanager/__init__.py	Fri Dec 06 10:51:15 2013 +0100
    13.3 @@ -0,0 +1,6 @@
    13.4 +__version__ = "0.1"
    13.5 +__author__ = [
    13.6 +    "Mihai Bartha <mihai.bartha@ait.ac.at>"
    13.7 +]
    13.8 +__license__ = "public domain"
    13.9 +__contributors__ = "OpenSecurity Consortium"
   13.10 \ No newline at end of file
    14.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    14.2 +++ b/OpenSecurity/bin/vmmanager/vmmanager.py	Fri Dec 06 10:51:15 2013 +0100
    14.3 @@ -0,0 +1,342 @@
    14.4 +'''
    14.5 +Created on Nov 19, 2013
    14.6 +
    14.7 +@author: BarthaM
    14.8 +'''
    14.9 +import os
   14.10 +import os.path
   14.11 +from subprocess import Popen, PIPE, call
   14.12 +import subprocess
   14.13 +import sys
   14.14 +import re
   14.15 +from cygwin import Cygwin
   14.16 +import _winreg
   14.17 +
   14.18 +DEBUG = True
   14.19 +
   14.20 +class USBFilter:
   14.21 +    vendorid = ""
   14.22 +    productid = ""
   14.23 +    revision = ""
   14.24 +    
   14.25 +    def __init__(self, vendorid, productid, revision):
   14.26 +        self.vendorid = vendorid.lower()
   14.27 +        self.productid = productid.lower()
   14.28 +        self.revision = revision.lower()
   14.29 +        return
   14.30 +    
   14.31 +    def __eq__(self, other):
   14.32 +        return self.vendorid == other.vendorid and self.productid == other.productid and self.revision == other.revision
   14.33 +    
   14.34 +    def __hash__(self):
   14.35 +        return hash(self.vendorid) ^ hash(self.productid) ^ hash(self.revision)
   14.36 +    
   14.37 +    def __repr__(self):
   14.38 +        return "VendorId = \'" + str(self.vendorid) + "\' ProductId = \'" + str(self.productid) + "\' Revision = \'" + str(self.revision) + "\'"
   14.39 +        
   14.40 +
   14.41 +class VMManager(object):
   14.42 +    """Manage Virtual Machines"""
   14.43 +
   14.44 +    vmRootName = "SecurityDVM"
   14.45 +    
   14.46 +    def __init__(self):
   14.47 +        self.vBoxPath = self.getVBoxManagePath()
   14.48 +        self.vBoxManage = os.path.join(self.vBoxPath, 'VBoxManage.exe')
   14.49 +        self.systemProperties = self.getSystemProperties()
   14.50 +        self.cygwin_path = Cygwin.root()
   14.51 +        return
   14.52 +         
   14.53 +    def execute(self, cmd):
   14.54 +        """execute a command"""
   14.55 +    
   14.56 +        # we can handle strings and lists as input
   14.57 +        c = cmd
   14.58 +        if type(cmd) == list:
   14.59 +            c = ' '.join(cmd)
   14.60 +    
   14.61 +        if DEBUG:
   14.62 +            sys.stderr.write('trying to launch: ' + c + '\n')
   14.63 +        process = Popen(cmd, stdout=PIPE, stderr=PIPE)
   14.64 +        if DEBUG:
   14.65 +            sys.stderr.write('launched: ' + c + '\n')
   14.66 +            
   14.67 +        result = process.wait()
   14.68 +        res_stdout = process.stdout.read();
   14.69 +        res_stderr = process.stderr.read();
   14.70 +        if DEBUG:
   14.71 +            if res_stdout != "":
   14.72 +                print res_stdout
   14.73 +            if res_stderr != "":
   14.74 +                print res_stderr
   14.75 +        return result, res_stdout, res_stderr
   14.76 +    
   14.77 +    
   14.78 +    def getVBoxManagePath(self):
   14.79 +        """get the path to the VirtualBox installation on this system"""
   14.80 +        p = None
   14.81 +        try:
   14.82 +            k = _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE, 'SOFTWARE\Oracle\VirtualBox')
   14.83 +            p = _winreg.QueryValueEx(k, 'InstallDir')[0]
   14.84 +            _winreg.CloseKey(k)
   14.85 +        except:
   14.86 +            pass
   14.87 +        return p
   14.88 +    
   14.89 +    # return host system properties
   14.90 +    def getSystemProperties(self):
   14.91 +        cmd = [self.vBoxManage, 'list', 'systemproperties']
   14.92 +        result = self.execute(cmd)
   14.93 +        if result[1]=='':
   14.94 +            return None
   14.95 +        props = dict((k.strip(),v.strip().strip('"')) for k,v in (line.split(':', 1) for line in result[1].strip().splitlines()))
   14.96 +        return props
   14.97 +    
   14.98 +    # return the folder containing the guest VMs     
   14.99 +    def getDefaultMachineFolder(self):
  14.100 +        return self.systemProperties["Default machine folder"]
  14.101 +    
  14.102 +    #list the hostonly IFs exposed by the VBox host
  14.103 +    def getHostOnlyIFs(self):
  14.104 +        cmd = [self.vBoxManage, 'list', 'hostonlyifs']
  14.105 +        result = self.execute(cmd)[1]
  14.106 +        if result=='':
  14.107 +            return None
  14.108 +        props = dict((k.strip(),v.strip().strip('"')) for k,v in (line.split(':', 1) for line in result.strip().splitlines()))
  14.109 +        return props
  14.110 +        
  14.111 +    def listRSDS(self):
  14.112 +        cmd = [self.vBoxManage, 'list', 'usbhost']
  14.113 +        results = self.execute(cmd)
  14.114 +        results = results.split('Host USB Devices:')[1].strip()
  14.115 +        
  14.116 +        items = list( "UUID:" + result for result in results.split('UUID:') if result != '')
  14.117 +        rsds = dict()   
  14.118 +        for item in items:
  14.119 +            props = dict()
  14.120 +            for line in item.splitlines():
  14.121 +                if line != "":         
  14.122 +                    k,v = line[:line.index(':')].strip(), line[line.index(':')+1:].strip()
  14.123 +                    props[k] = v;
  14.124 +            
  14.125 +            if 'Product' in props.keys() and props['Product'] == 'Mass Storage':
  14.126 +                usb_filter = USBFilter( re.search(r"\((?P<vid>[0-9A-Fa-f]+)\)", props['VendorId']).groupdict()['vid'], 
  14.127 +                                        re.search(r"\((?P<pid>[0-9A-Fa-f]+)\)", props['ProductId']).groupdict()['pid'],
  14.128 +                                        re.search(r"\((?P<rev>[0-9A-Fa-f]+)\)", props['Revision']).groupdict()['rev'] )
  14.129 +                rsds[props['UUID']] = usb_filter;
  14.130 +                if DEBUG:
  14.131 +                    print filter
  14.132 +        return rsds
  14.133 +
  14.134 +    # list all existing VMs registered with VBox
  14.135 +    def listVM(self):
  14.136 +        cmd = [self.vBoxManage, 'list', 'vms']
  14.137 +        result = self.execute(cmd)[1]
  14.138 +        vms = list(k.strip().strip('"') for k,_ in (line.split(' ') for line in result.splitlines()))
  14.139 +        return vms
  14.140 +    
  14.141 +    # list existing SDVMs
  14.142 +    def listSDVM(self):
  14.143 +        vms = self.listVM()
  14.144 +        svdms = []
  14.145 +        for vm in vms:
  14.146 +            if vm.startswith(self.vmRootName) and vm != self.vmRootName:
  14.147 +                svdms.append(vm)
  14.148 +        return svdms
  14.149 +    
  14.150 +    # generate valid (not already existing SDVM name). necessary for creating a new VM
  14.151 +    def generateSDVMName(self):
  14.152 +        vms = self.listVM()
  14.153 +        for i in range(0,999):
  14.154 +            if(not self.vmRootName+str(i) in vms):
  14.155 +                return self.vmRootName+str(i)
  14.156 +        return ''
  14.157 +    
  14.158 +    # return the RSDs attached to all existing SDVMs
  14.159 +    def getAttachedRSDs(self):
  14.160 +        vms = self.listSDVM()
  14.161 +        attached_devices = dict()
  14.162 +        for vm in vms:
  14.163 +            rsd_filter = self.getUSBFilter(vm)
  14.164 +            if filter != None:
  14.165 +                attached_devices[vm] = rsd_filter
  14.166 +        return attached_devices
  14.167 +    
  14.168 +    # configures hostonly networking and DHCP server. requires admin rights
  14.169 +    def configureHostNetworking(self):
  14.170 +        #cmd = 'vboxmanage list hostonlyifs'
  14.171 +        #self.execute(cmd)
  14.172 +        #cmd = 'vboxmanage hostonlyif remove \"VirtualBox Host-Only Ethernet Adapter\"'
  14.173 +        #self.execute(cmd)
  14.174 +        #cmd = 'vboxmanage hostonlyif create'
  14.175 +        #self.execute(cmd)
  14.176 +        cmd = self.vBoxManage + ' hostonlyif ipconfig \"VirtualBox Host-Only Ethernet Adapter\" --ip 192.168.56.1 --netmask 255.255.255.0'
  14.177 +        self.execute(cmd)
  14.178 +        #cmd = 'vboxmanage dhcpserver add'
  14.179 +        #self.execute(cmd)
  14.180 +        cmd = self.vBoxManage + ' dhcpserver modify --ifname \"VirtualBox Host-Only Ethernet Adapter\" --ip 192.168.56.1 --netmask 255.255.255.0 --lowerip 192.168.56.100 --upperip 192.168.56.255'
  14.181 +        self.execute(cmd)
  14.182 +    
  14.183 +    #create new virtual machine instance based on template vm named SecurityDVM (\SecurityDVM\SecurityDVM.vmdk)
  14.184 +    def createVM(self, vm_name):
  14.185 +        hostonly_if = self.getHostOnlyIFs()
  14.186 +        machineFolder = self.getDefaultMachineFolder()
  14.187 +        cmd = self.vBoxManage + ' createvm --name ' + vm_name + ' --ostype Debian --register'
  14.188 +        self.execute(cmd)
  14.189 +        cmd = self.vBoxManage + ' modifyvm ' + vm_name + ' --memory 512 --vram 10 --cpus 1 --usb on --usbehci on --nic1 hostonly --hostonlyadapter1 \"' + hostonly_if['Name'] + '\" --nic2 nat' 
  14.190 +        self.execute(cmd)
  14.191 +        cmd = self.vBoxManage + ' storagectl ' + vm_name + ' --name contr1 --add sata --portcount 2'
  14.192 +        self.execute(cmd)
  14.193 +        cmd = self.vBoxManage + ' storageattach ' + vm_name + ' --storagectl contr1 --port 0 --device 0 --type hdd --mtype normal --medium \"'+ machineFolder + '\SecurityDVM\SecurityDVM.vmdk\"'
  14.194 +        self.execute(cmd)
  14.195 +        return
  14.196 +    
  14.197 +    #remove VM from the system. should be used on VMs returned by listSDVMs    
  14.198 +    def removeVM(self, vm_name):
  14.199 +        print('removing ' + vm_name)
  14.200 +        cmd = self.vBoxManage + ' unregistervm', vm_name, '--delete'
  14.201 +        print self.execute(cmd)
  14.202 +        machineFolder = self.getDefaultMachineFolder()
  14.203 +        cmd = self.cygwin_path+'bash.exe --login -c \"rm -rf ' + machineFolder + '\\' + vm_name + '*\"'
  14.204 +        print self.execute(cmd)
  14.205 +    
  14.206 +    # start VM
  14.207 +    def startVM(self, vm_name):
  14.208 +        print('starting ' +  vm_name)
  14.209 +        cmd = self.vBoxManage + ' startvm ' + vm_name + ' --type headless'
  14.210 +        print self.execute(cmd)
  14.211 +        
  14.212 +    # stop VM    
  14.213 +    def stopVM(self, vm_name):
  14.214 +        print('stopping ' + vm_name)
  14.215 +        cmd = self.vBoxManage + ' controlvm ' + vm_name + ' poweroff'
  14.216 +        print self.execute(cmd)
  14.217 +    
  14.218 +    # return the hostOnly IP for a running guest    
  14.219 +    def getHostOnlyIP(self, vm_name):
  14.220 +        print('gettting hostOnly IP address ' + vm_name)
  14.221 +        cmd = self.vBoxManage + ' guestproperty get ' + vm_name + ' /VirtualBox/GuestInfo/Net/0/V4/IP'
  14.222 +        result = self.execute(cmd)
  14.223 +        if result=='':
  14.224 +            return None
  14.225 +        result = result[1]
  14.226 +        return result[result.index(':')+1:].strip()
  14.227 +    
  14.228 +    # attach removable storage device to VM by provision of filter
  14.229 +    def attachRSD(self, vm_name, rsd_filter):
  14.230 +        cmd = self.vBoxManage + ' usbfilter add 0 --target ' + vm_name + ' --name OpenSecurityRSD --vendorid ' + rsd_filter.vendorid + ' --productid ' + rsd_filter.productid + ' --revision ' + rsd_filter.revision
  14.231 +        print self.execute(cmd)
  14.232 +        
  14.233 +    
  14.234 +    # return the description set for an existing VM
  14.235 +    def getVMInfo(self, vm_name):
  14.236 +        cmd = self.vBoxManage + ' showvminfo ' + vm_name + ' --machinereadable'
  14.237 +        r, o, e = self.execute(cmd)
  14.238 +        props = dict((k.strip(),v.strip().strip('"')) for k, v in (line.split('=', 1) for line in o.splitlines()))
  14.239 +        return props
  14.240 +    
  14.241 +    # return the configured USB filter for an existing VM 
  14.242 +    def getUSBFilter(self, vm_name):
  14.243 +        props = self.getVMInfo(vm_name)
  14.244 +        keys = set(['USBFilterVendorId1', 'USBFilterProductId1', 'USBFilterRevision1'])
  14.245 +        keyset = set(props.keys())
  14.246 +        usb_filter = None
  14.247 +        if keyset.issuperset(keys):
  14.248 +            usb_filter = USBFilter(props['USBFilterVendorId1'], props['USBFilterProductId1'], props['USBFilterRevision1'])
  14.249 +        return usb_filter
  14.250 +    
  14.251 +    #generates ISO containing authorized_keys for use with guest VM
  14.252 +    def genCertificateISO(self, vm_name):
  14.253 +        machineFolder = self.getDefaultMachineFolder()
  14.254 +        # create .ssh folder in vm_name
  14.255 +        cmd = self.cygwin_path+'bash.exe --login -c \"mkdir -p \\\"' + machineFolder + '\\' + vm_name + '\\.ssh\\\"\"'
  14.256 +        result = self.execute(cmd)
  14.257 +        # generate dvm_key pair in vm_name / .ssh     
  14.258 +        cmd = self.cygwin_path+'bash.exe --login -c \"ssh-keygen -q -t rsa -N \\"\\" -C \\\"' + vm_name + '\\\" -f \\\"' + machineFolder + '\\' + vm_name + '\\.ssh\\dvm_key\\\"\"'   #'echo -e "y\\n" |',
  14.259 +        result = self.execute(cmd)
  14.260 +        # set permissions for keys
  14.261 +        #TODO: test without chmod
  14.262 +        cmd = self.cygwin_path+'bash.exe --login -c \"chmod 500 \\\"' + machineFolder + '\\' + vm_name + '\\.ssh\\*\\\"\"'
  14.263 +        result = self.execute(cmd)
  14.264 +        # move out private key
  14.265 +        cmd = self.cygwin_path+'bash.exe --login -c \"mv \\\"' + machineFolder + '\\' + vm_name + '\\.ssh\\dvm_key\\\" \\\"' + machineFolder + '\\' + vm_name + '\\\"'
  14.266 +        result = self.execute(cmd)
  14.267 +        # rename public key to authorized_keys
  14.268 +        cmd = self.cygwin_path+'bash.exe --login -c \"mv \\\"' + machineFolder + '\\' + vm_name + '\\.ssh\\dvm_key.pub\\\" \\\"' + machineFolder + '\\' + vm_name + '\\.ssh\\authorized_keys\\\"'
  14.269 +        result = self.execute(cmd)
  14.270 +        # generate iso image with .ssh/authorized keys
  14.271 +        cmd = self.cygwin_path+'bash.exe --login -c \"/usr/bin/genisoimage -J -R -o \\\"' + machineFolder + '\\' + vm_name + '\\'+ vm_name + '.iso\\\" \\\"' + machineFolder + '\\' + vm_name + '\\.ssh\\\"\"'
  14.272 +        result = self.execute(cmd)
  14.273 +    
  14.274 +    # attaches generated ssh public cert to guest vm
  14.275 +    def attachCertificateISO(self, vm_name):
  14.276 +        machineFolder = self.getDefaultMachineFolder()
  14.277 +        cmd = self.vBoxManage + ' storageattach ' + vm_name + ' --storagectl contr1 --port 1 --device 0 --type dvddrive --mtype readonly --medium \"' + machineFolder + '\\' + vm_name + '\\'+ vm_name + '.iso\"'
  14.278 +        result = self.execute(cmd)
  14.279 +        return result
  14.280 +    
  14.281 +    # handles device change events
  14.282 +    def handleDeviceChange(self):
  14.283 +        attached_devices = self.getAttachedRSDs()
  14.284 +        connected_devices = self.listRSDS()
  14.285 +        for vm_name in attached_devices.keys():
  14.286 +            if attached_devices[vm_name] not in connected_devices.values():
  14.287 +                self.stopVM(vm_name)
  14.288 +                self.removeVM(vm_name)
  14.289 +        
  14.290 +        attached_devices = self.getAttachedRSDs()
  14.291 +        for connected_device in connected_devices.values():
  14.292 +            if connected_device not in attached_devices.values():
  14.293 +                new_sdvm = self.generateSDVMName()
  14.294 +                self.createVM(new_sdvm)
  14.295 +                self.genCertificateISO(new_sdvm)
  14.296 +                self.attachCertificateISO(new_sdvm)
  14.297 +                self.attachRSD(new_sdvm, connected_device)
  14.298 +                self.startVM(new_sdvm)
  14.299 +    
  14.300 +    # executes command over ssh on guest vm
  14.301 +    def sshGuestExecute(self, vm_name, prog, user_name='opensec'):
  14.302 +        # get vm ip
  14.303 +        address = self.getHostOnlyIP(vm_name)
  14.304 +        machineFolder = self.getDefaultMachineFolder()
  14.305 +        # run command
  14.306 +        cmd = self.cygwin_path+'bash.exe --login -c \"ssh -i \\\"' + machineFolder + '\\' + vm_name + '\\dvm_key\\\"  ' + user_name + '@' + address + ' ' + prog + '\"'
  14.307 +        return self.execute(cmd)
  14.308 +    
  14.309 +    # executes command over ssh on guest vm with X forwarding
  14.310 +    def sshGuestX11Execute(self, vm_name, prog, user_name='opensec'):
  14.311 +        #TODO: verify if X server is running on user account 
  14.312 +        #TODO: set DISPLAY accordingly
  14.313 +        address = self.getHostOnlyIP(vm_name)
  14.314 +        machineFolder = self.getDefaultMachineFolder()
  14.315 +        # run command
  14.316 +        cmd = self.cygwin_path+'bash.exe --login -c \"DISPLAY=:0 ssh -Y -i \\\"' + machineFolder + '\\' + vm_name + '\\dvm_key\\\"  '  + user_name + '@' + address + ' ' + prog + '\"'
  14.317 +        return self.execute(cmd)    
  14.318 +        
  14.319 +    # executes NET USE and connects to samba share on guestos 
  14.320 +    def netUse(self, vm_name):
  14.321 +        ip = self.getHostOnlyIP(vm_name)
  14.322 +        cmd = 'net use H: \\' + ip + '\RSD_Device'
  14.323 +        return self.execute(cmd)
  14.324 +        
  14.325 +    
  14.326 +if __name__ == '__main__':
  14.327 +    man = VMManager()
  14.328 +    man.cygwin_path = 'c:\\cygwin64\\bin\\'
  14.329 +    #man.handleDeviceChange()
  14.330 +    #print man.listSDVM()
  14.331 +    #man.configureHostNetworking()
  14.332 +    new_vm = man.generateSDVMName()
  14.333 +    man.createVM(new_vm)
  14.334 +    man.genCertificateISO(new_vm)
  14.335 +    man.attachCertificateISO(new_vm)
  14.336 +    
  14.337 +    #man.attachCertificateISO(vm_name)
  14.338 +    #man.sshGuestExecute(vm_name, "ls")
  14.339 +    #man.sshGuestX11Execute(vm_name, "iceweasel")
  14.340 +    #cmd = "c:\\cygwin64\\bin\\bash.exe --login -c \"/bin/ls\""
  14.341 +    #man.execute(cmd)
  14.342 +    
  14.343 +    
  14.344 +
  14.345 +