OpenSecurity/bin/opensecurity_tray.pyw
author BarthaM@N3SIM1218.D03.arc.local
Wed, 24 Sep 2014 16:40:43 +0100
changeset 223 a4fb6694e6fe
parent 215 9d777587cdab
child 234 216da9017f8f
permissions -rwxr-xr-x
Added WPAD proxy support.
Not fully tested
om@13
     1
# -*- coding: utf-8 -*-
om@13
     2
om@13
     3
# ------------------------------------------------------------
om@13
     4
# opensecurity-dialog
om@13
     5
# 
om@13
     6
# an opensecurity dialog
om@13
     7
#
om@13
     8
# Autor: Oliver Maurhart, <oliver.maurhart@ait.ac.at>
om@13
     9
#
om@13
    10
# Copyright (C) 2013 AIT Austrian Institute of Technology
om@13
    11
# AIT Austrian Institute of Technology GmbH
om@13
    12
# Donau-City-Strasse 1 | 1220 Vienna | Austria
om@13
    13
# http://www.ait.ac.at
om@13
    14
#
om@13
    15
# This program is free software; you can redistribute it and/or
om@13
    16
# modify it under the terms of the GNU General Public License
om@13
    17
# as published by the Free Software Foundation version 2.
om@13
    18
# 
om@13
    19
# This program is distributed in the hope that it will be useful,
om@13
    20
# but WITHOUT ANY WARRANTY; without even the implied warranty of
om@13
    21
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
om@13
    22
# GNU General Public License for more details.
om@13
    23
# 
om@13
    24
# You should have received a copy of the GNU General Public License
om@13
    25
# along with this program; if not, write to the Free Software
om@13
    26
# Foundation, Inc., 51 Franklin Street, Fifth Floor, 
om@13
    27
# Boston, MA  02110-1301, USA.
om@13
    28
# ------------------------------------------------------------
om@13
    29
om@13
    30
om@13
    31
# ------------------------------------------------------------
om@13
    32
# imports
om@13
    33
om@13
    34
import argparse
oliver@165
    35
import json
om@13
    36
import os
om@13
    37
import subprocess
om@13
    38
import sys
oliver@145
    39
import urllib
om@42
    40
import urllib2
oliver@145
    41
import webbrowser
BarthaM@213
    42
import _winreg
BarthaM@213
    43
import re
om@13
    44
om@13
    45
from PyQt4 import QtCore
om@13
    46
from PyQt4 import QtGui
om@13
    47
om@13
    48
# local
oliver@144
    49
import __init__ as opensecurity
oliver@144
    50
oliver@104
    51
if sys.platform == 'win32' or sys.platform == 'cygwin':
oliver@104
    52
    from cygwin import Cygwin
oliver@104
    53
oliver@136
    54
import opensecurity_client_restful_server 
oliver@104
    55
from ui import AboutDialog
oliver@106
    56
from ui import ConfigureDialog
oliver@104
    57
from ui import opensecurity_rc
om@13
    58
oliver@106
    59
om@13
    60
# ------------------------------------------------------------
om@13
    61
# code
om@13
    62
om@13
    63
om@42
    64
class OpenSecurityWait(QtGui.QDialog):
om@42
    65
om@42
    66
    """OpenSecurity: please wait ..."""
om@42
    67
    
om@42
    68
    def __init__(self, parent = None, flags = QtCore.Qt.WindowFlags(0)):
om@42
    69
        super(OpenSecurityWait, self).__init__(parent, flags)
om@42
    70
        self.setWindowTitle('OpenSecurity')
om@42
    71
        self.setup_ui()
om@42
    72
        
om@42
    73
        
om@42
    74
    def setup_ui(self):
om@42
    75
        """Create the widgets."""
om@42
    76
        
om@42
    77
        lyMain = QtGui.QVBoxLayout(self)
om@42
    78
        lyMain.setContentsMargins(8, 8, 8, 8)
om@42
    79
        
om@42
    80
        # content area: left pixmap, right text
om@42
    81
        lbTitle = QtGui.QLabel('Creating secure subsystem. Please stand by ...')
om@42
    82
        lyMain.addWidget(lbTitle)
om@42
    83
        
om@42
    84
        self.setMinimumSize(400, 50)
om@42
    85
        self.resize(lyMain.minimumSize())
om@42
    86
om@42
    87
om@13
    88
class OpenSecurityTrayIcon(QtGui.QSystemTrayIcon):
om@13
    89
    
om@13
    90
    """This is the OpenSecuirty Tray Icon"""
om@13
    91
om@13
    92
    def __init__(self, icon, parent=None):
om@13
    93
        
om@13
    94
        super(OpenSecurityTrayIcon, self).__init__(icon, parent)
om@13
    95
        self.setup_ui()
oliver@207
    96
        self.activated.connect(self.activated_)
oliver@207
    97
       
oliver@207
    98
oliver@207
    99
    def activated_(self, reason):
oliver@207
   100
oliver@207
   101
        """the system tray icon was activated"""
oliver@207
   102
        self.refresh_format_menu()
oliver@207
   103
om@13
   104
        
om@13
   105
    def clicked_about(self):
om@13
   106
        """clicked about"""
oliver@104
   107
        d = AboutDialog()
oliver@104
   108
        d.exec_()
om@13
   109
    
BarthaM@213
   110
    def getProxySettings(self):        
BarthaM@213
   111
        aReg = _winreg.ConnectRegistry(None,_winreg.HKEY_CURRENT_USER)
BarthaM@213
   112
        aKey = _winreg.OpenKey(aReg, r"Software\Microsoft\Windows\CurrentVersion\Internet Settings")
BarthaM@213
   113
        subCount, valueCount, lastModified = _winreg.QueryInfoKey(aKey)
BarthaM@213
   114
        reg_entries = dict()
BarthaM@213
   115
        for i in range(valueCount):                                           
BarthaM@213
   116
            try:
BarthaM@213
   117
                n,v,t = _winreg.EnumValue(aKey,i)
BarthaM@213
   118
                reg_entries[n] = v
BarthaM@213
   119
            except EnvironmentError:                                               
BarthaM@213
   120
                break
BarthaM@213
   121
        _winreg.CloseKey(aKey)
BarthaM@223
   122
        
BarthaM@223
   123
        if 'AutoConfigURL' in reg_entries.keys():
BarthaM@223
   124
            return {'ProxyAutoConfigURL': reg_entries['AutoConfigURL']}
BarthaM@213
   125
BarthaM@213
   126
        if 'ProxyEnable' in reg_entries.keys() and reg_entries['ProxyEnable'] == 1:
BarthaM@213
   127
            proxy_search = re.search(r"(?<=http=)(?P<ProxyServer>.*?)(?=;)", reg_entries['ProxyServer'])
BarthaM@213
   128
            if proxy_search:
BarthaM@213
   129
                proxies = proxy_search.groupdict()
BarthaM@213
   130
                if 'ProxyServer' in proxies.keys(): # found http proxy
BarthaM@213
   131
                    return {'ProxyServer': proxies['ProxyServer']}  
BarthaM@213
   132
            return {'ProxyServer': reg_entries['ProxyServer']}
BarthaM@223
   133
            
BarthaM@213
   134
        return None
om@13
   135
om@37
   136
    def clicked_browser(self):
om@37
   137
        """wish for safe internet browsing"""
om@42
   138
        
oliver@104
   139
        if not (sys.platform == 'win32' or sys.platform == 'cygwin'):
oliver@104
   140
            QtGui.QMessageBox.critical(self.parent(), 'OpenSecurity Error', 'This action is not supported on this platform.\nSorry.')
oliver@104
   141
            return
oliver@193
   142
       
om@42
   143
        try:
om@42
   144
            # get a proper browsing VM
mb@110
   145
            Cygwin.start_X11()
oliver@144
   146
oliver@144
   147
            # TODO: HARDCODED ADDRESS OF OPENSECURITYD
BarthaM@213
   148
            proxy_support = urllib2.ProxyHandler({})
BarthaM@213
   149
            opener = urllib2.build_opener(proxy_support)
BarthaM@213
   150
            urllib2.install_opener(opener)
BarthaM@213
   151
BarthaM@213
   152
            req_data = ""
BarthaM@213
   153
            proxy = self.getProxySettings()
BarthaM@213
   154
            if proxy:
BarthaM@213
   155
                req_data = '?' + urllib.urlencode(proxy) 
BarthaM@213
   156
            req = 'http://127.0.0.1:8080/browsing'+ req_data
BarthaM@213
   157
            browsing_vm = urllib2.urlopen(req).readline()
BarthaM@213
   158
            print('Called '+ req + ' got: ' + str(browsing_vm))
om@42
   159
        except:
om@42
   160
            QtGui.QApplication.instance().processEvents()
om@42
   161
            QtGui.QMessageBox.critical(None, 'Failed to invoke Safe Internet Browsing', 'OpenSecurity Error')
om@42
   162
            
om@42
   163
        QtGui.QApplication.instance().processEvents()
om@37
   164
            
om@37
   165
            
oliver@106
   166
    def clicked_configure(self):
oliver@106
   167
        """clicked configure"""
oliver@106
   168
        d = ConfigureDialog()
oliver@106
   169
        d.exec_()
oliver@106
   170
    
oliver@106
   171
om@13
   172
    def clicked_exit(self):
om@13
   173
        """clicked exit"""
oliver@136
   174
        opensecurity_client_restful_server.stop()
om@13
   175
        sys.exit(0)
om@13
   176
    
om@13
   177
om@13
   178
    def clicked_launch_application(self):
om@13
   179
        """clicked the launch an application"""
oliver@104
   180
        dlg_launch_image = os.path.join(sys.path[0], 'ui', 'launch_dialog.py')
om@13
   181
        process_command = [sys.executable, dlg_launch_image]
oliver@165
   182
        process = subprocess.Popen(process_command, shell = False, stdout = subprocess.PIPE)        
oliver@165
   183
        try:
oliver@165
   184
            stdout = process.communicate()[0]
oliver@165
   185
            j = json.loads(stdout)
oliver@165
   186
        except:
oliver@165
   187
            return
oliver@165
   188
oliver@165
   189
        try:
oliver@165
   190
        
oliver@165
   191
            # get a proper browsing VM
oliver@165
   192
            Cygwin.start_X11()
oliver@165
   193
oliver@165
   194
            # TODO: HARDCODED ADDRESS OF OPENSECURITYD
oliver@165
   195
            url = 'http://127.0.0.1:8080/sdvms/' + j['vm'] + '/application' + j['application']
oliver@165
   196
            result = urllib2.urlopen(url).readline()
oliver@165
   197
            
oliver@165
   198
        except:
oliver@165
   199
            pass 
om@13
   200
            
om@13
   201
            
oliver@144
   202
    def clicked_mail(self):
oliver@145
   203
        
oliver@144
   204
        """clicked mail"""
oliver@145
   205
        address = 'feedback@opensecurity.at'
oliver@145
   206
        subject = 'Feedback zu OpenSecurity V' + opensecurity.__version__
oliver@145
   207
oliver@145
   208
        if sys.platform == 'linux2':
oliver@145
   209
            subprocess.Popen(['xdg-email', '--subject', subject, address])
oliver@145
   210
        elif sys.platform == 'win32' or sys.platform == 'cygwin':
oliver@145
   211
            mail_url = 'mailto:' + urllib.quote(address, '@') + '?' + urllib.quote('subject=' + subject)
oliver@148
   212
            subprocess.Popen(['cmd', '/C', 'start', mail_url])
oliver@207
   213
   
oliver@207
   214
oliver@207
   215
    def format_drive(self):
oliver@207
   216
oliver@207
   217
        """format drive clicked (the sender should a QAction created with refresh_format_menu)"""
oliver@207
   218
        try:
oliver@207
   219
oliver@207
   220
            # fiddle the IP of the VM controlling the VM
oliver@207
   221
            s = self.sender()
oliver@207
   222
            ip = str(s.text().split('\\\\')[1])
oliver@207
   223
oliver@207
   224
            # invoke the format drive dialog
oliver@207
   225
            dlg_format_drive = os.path.join(sys.path[0], 'ui', 'format_drive_dialog.py')
oliver@207
   226
            process_command = [sys.executable, dlg_format_drive, ip]
oliver@207
   227
            process = subprocess.Popen(process_command, shell = False, stdout = subprocess.PIPE)        
oliver@207
   228
oliver@207
   229
            stdout = process.communicate()[0]
oliver@207
   230
oliver@207
   231
        except:
oliver@207
   232
            pass
oliver@207
   233
oliver@207
   234
oliver@207
   235
    def refresh_format_menu(self):
oliver@207
   236
oliver@207
   237
        """create a new list of format 'drives'"""
oliver@207
   238
        self._menu_format.clear()
oliver@207
   239
        a = self._menu_format.addAction('<No Drive given>')
oliver@207
   240
        a.setEnabled(False)
oliver@207
   241
oliver@207
   242
        try:
oliver@207
   243
oliver@207
   244
            # get machines
oliver@207
   245
            machines = json.load(urllib2.urlopen('http://127.0.0.1:8080/sdvms'))
oliver@207
   246
            if len(machines) == 0:
oliver@207
   247
                return
oliver@207
   248
oliver@207
   249
            self._icon_network = QtGui.QIcon()
oliver@207
   250
            self._icon_network.addPixmap(QtGui.QPixmap(":/opensecurity/gfx/network-workgroup.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
oliver@207
   251
oliver@215
   252
            cleared = False
oliver@207
   253
            for m in machines:
oliver@215
   254
oliver@215
   255
                # do not insert Browsing VM
BarthaM@213
   256
                if u'SecurityDVM0' in m:
BarthaM@213
   257
                    continue
oliver@215
   258
oliver@215
   259
                if not cleared:
oliver@215
   260
                    self._menu_format.clear()
oliver@215
   261
                    cleared = True
oliver@215
   262
oliver@207
   263
                a = self._menu_format.addAction(m + '\\\\' + machines[m])
oliver@207
   264
                a.setIcon(self._icon_network)
oliver@207
   265
                a.triggered.connect(self.format_drive)
oliver@207
   266
oliver@207
   267
        except:
oliver@207
   268
            pass
oliver@207
   269
oliver@144
   270
om@13
   271
    def setup_ui(self):
om@13
   272
        """create the user interface
om@13
   273
        As for the system tray this is 'just' the context menu.
om@13
   274
        """
om@13
   275
    
om@13
   276
        # define the tray icon menu
om@13
   277
        menu = QtGui.QMenu(self.parent())
om@13
   278
        self.setContextMenu(menu)
om@13
   279
        
om@13
   280
        # add known apps
oliver@104
   281
        self.acBrowser = QtGui.QAction('Secure Browsing', self.parent())
oliver@104
   282
        icon = QtGui.QIcon()
oliver@106
   283
        icon.addPixmap(QtGui.QPixmap(QtCore.QString.fromUtf8(':/opensecurity/gfx/opensecurity_browsing_64.png')), QtGui.QIcon.Normal, QtGui.QIcon.Off)
oliver@104
   284
        self.acBrowser.setIcon(icon)
oliver@104
   285
        menu.addAction(self.acBrowser)
om@37
   286
        menu.addSeparator()
om@13
   287
        
om@13
   288
        # add standard menu items
oliver@104
   289
        self.acLaunch = QtGui.QAction('Launch Application', self.parent())
oliver@104
   290
        icon = QtGui.QIcon()
oliver@106
   291
        icon.addPixmap(QtGui.QPixmap(QtCore.QString.fromUtf8(':/opensecurity/gfx/opensecurity_launch_64.png')), QtGui.QIcon.Normal, QtGui.QIcon.Off)
oliver@104
   292
        self.acLaunch.setIcon(icon)
oliver@104
   293
        menu.addAction(self.acLaunch)
oliver@106
   294
        self.acConfigure = QtGui.QAction('Configuration', self.parent())
oliver@106
   295
        icon = QtGui.QIcon()
oliver@106
   296
        icon.addPixmap(QtGui.QPixmap(QtCore.QString.fromUtf8(':/opensecurity/gfx/opensecurity_configure_64.png')), QtGui.QIcon.Normal, QtGui.QIcon.Off)
oliver@106
   297
        self.acConfigure.setIcon(icon)
oliver@106
   298
        menu.addAction(self.acConfigure)
om@13
   299
        menu.addSeparator()
oliver@104
   300
oliver@207
   301
        self._menu_format = menu.addMenu('Format')
oliver@207
   302
        menu.addSeparator()
oliver@207
   303
oliver@144
   304
        self.acMail = menu.addAction('Send feedback mail')
oliver@144
   305
        icon = QtGui.QIcon()
oliver@144
   306
        icon.addPixmap(QtGui.QPixmap(QtCore.QString.fromUtf8(':/opensecurity/gfx/opensecurity_mail_64.png')), QtGui.QIcon.Normal, QtGui.QIcon.Off)
oliver@144
   307
        self.acMail.setIcon(icon)
oliver@104
   308
        self.acAbout = menu.addAction('About')
oliver@215
   309
        
oliver@215
   310
        # diabled as of TICKET #11
oliver@215
   311
        # self.acExit = menu.addAction('Exit')
oliver@144
   312
       
oliver@104
   313
        self.acBrowser.triggered.connect(self.clicked_browser)
oliver@104
   314
        self.acLaunch.triggered.connect(self.clicked_launch_application)
oliver@106
   315
        self.acConfigure.triggered.connect(self.clicked_configure)
oliver@104
   316
        self.acAbout.triggered.connect(self.clicked_about)
oliver@215
   317
oliver@215
   318
        # disabled as for TICKET #11
oliver@215
   319
        # self.acExit.triggered.connect(self.clicked_exit)
oliver@144
   320
        self.acMail.triggered.connect(self.clicked_mail)
om@13
   321
        
oliver@136
   322
om@13
   323
def main():
om@13
   324
    
oliver@136
   325
    # parse arguments
oliver@136
   326
    parser = argparse.ArgumentParser(description = 'OpenSecurity Tray Icon.')
oliver@136
   327
    parser.add_argument('-p', '--port', type=int, default=8090, help='port number of the REST API this instance will listen on.')
oliver@136
   328
    args = parser.parse_args()
oliver@136
   329
oliver@136
   330
    # get up Qt
oliver@104
   331
    a = QtGui.QApplication(sys.argv)
om@13
   332
oliver@136
   333
    # enforce singelton process
oliver@136
   334
    if opensecurity_client_restful_server.is_already_running(args.port):
oliver@136
   335
        QtGui.QMessageBox.critical(None, 'OpenSecurity Error', 'OpenSecurity Tray Instance already launched.\nClose previous instance first.')
oliver@136
   336
        sys.exit(1)
oliver@136
   337
oliver@136
   338
    # start serving
oliver@136
   339
    opensecurity_client_restful_server.serve(args.port, True)
oliver@136
   340
oliver@136
   341
    # init tray icon widget
om@13
   342
    w = QtGui.QWidget()
oliver@104
   343
    icon = QtGui.QIcon()
oliver@104
   344
    icon.addPixmap(QtGui.QPixmap(QtCore.QString.fromUtf8(":/opensecurity/gfx/opensecurity_icon_64.png")), QtGui.QIcon.Normal, QtGui.QIcon.Off)
oliver@104
   345
    trayIcon = OpenSecurityTrayIcon(icon)
oliver@193
   346
    opensecurity_client_restful_server.tray_icon = trayIcon
om@13
   347
oliver@136
   348
    # go!
om@13
   349
    trayIcon.show()
oliver@104
   350
    a.setQuitOnLastWindowClosed(False)
oliver@104
   351
    sys.exit(a.exec_())
om@13
   352
   
om@13
   353
om@13
   354
# start
om@13
   355
if __name__ == "__main__":
om@13
   356
    main()
om@13
   357