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 +