keyfile query and dialog handling reworked
authorOliver Maurhart <oliver.maurhart@ait.ac.at>
Tue, 29 Apr 2014 13:00:46 +0200
changeset 134f1c1c06c947d
parent 133 6649faffb63c
child 135 c9499f5166c7
keyfile query and dialog handling reworked
OpenSecurity/bin/opensecurity_client_restful_server.py
OpenSecurity/bin/opensecurity_dialog.pyw
OpenSecurity/bin/ui/KeyfileDialog.ui
OpenSecurity/bin/ui/Makefile
OpenSecurity/bin/ui/__init__.py
OpenSecurity/bin/ui/credentials_dialog.py
OpenSecurity/bin/ui/keyfile_dialog.py
OpenSecurity/bin/ui/password_dialog.py
OpenSecurity/bin/ui/ui_KeyfileDialog.py
     1.1 --- a/OpenSecurity/bin/opensecurity_client_restful_server.py	Fri Apr 25 13:23:20 2014 +0200
     1.2 +++ b/OpenSecurity/bin/opensecurity_client_restful_server.py	Tue Apr 29 13:00:46 2014 +0200
     1.3 @@ -32,6 +32,7 @@
     1.4  # ------------------------------------------------------------
     1.5  # imports
     1.6  
     1.7 +import json
     1.8  import os
     1.9  import os.path
    1.10  import subprocess
    1.11 @@ -44,7 +45,6 @@
    1.12  
    1.13  # local
    1.14  from environment import Environment
    1.15 -from notification import Notification
    1.16  
    1.17  
    1.18  # ------------------------------------------------------------
    1.19 @@ -56,8 +56,8 @@
    1.20  
    1.21  """All the URLs we know mapping to class handler"""
    1.22  opensecurity_urls = (
    1.23 -    #'/application',             'os_application',
    1.24      '/credentials',             'os_credentials',
    1.25 +    '/keyfile',                 'os_keyfile',
    1.26      '/notification',            'os_notification',
    1.27      '/password',                'os_password',
    1.28      '/',                        'os_root'
    1.29 @@ -68,56 +68,8 @@
    1.30  # code
    1.31  
    1.32  
    1.33 -# class os_application:
    1.34 -#
    1.35 -# PRESUMLY DEAD CODE
    1.36 -#
    1.37 -    # """OpenSecurity '/application' handler.
    1.38 -    
    1.39 -    # This is called on GET /application?vm=VM-ID&app=APP-ID
    1.40 -    # This tries to access the vm identified with the label VM-ID
    1.41 -    # and launched the application identified APP-ID
    1.42 -    # """
    1.43 -    
    1.44 -    # def GET(self):
    1.45 -        
    1.46 -        # # pick the arguments
    1.47 -        # args = web.input()
    1.48 -        
    1.49 -        # # we _need_ a vm
    1.50 -        # if not "vm" in args:
    1.51 -            # raise web.badrequest('no vm given')
    1.52 -        
    1.53 -        # # we _need_ a app
    1.54 -        # if not "command" in args:
    1.55 -            # raise web.badrequest('no app given')
    1.56 -        
    1.57 -        # # check if we do have valid vm
    1.58 -        # v = [v for v in vms if v['name'] == args.vm]
    1.59 -        # if len(v) == 0:
    1.60 -            # raise web.notfound('vm not found')
    1.61 -        # v = v[0]
    1.62 -        
    1.63 -        # # check if we do have a valid app
    1.64 -        # a = [a for a in apps if a['name'] == args.app]
    1.65 -        # if len(a) == 0:
    1.66 -            # raise web.notfound('app not found')
    1.67 -        # a = a[0]
    1.68 -        
    1.69 -        # # invoke launch with 
    1.70 -        # res = "starting: launch " + v['user'] + " " + v['ip'] + " " + a['command']
    1.71 +class os_credentials:
    1.72  
    1.73 -        # launch_image = os.path.join(sys.path[0], 'launch.py')
    1.74 -        # process_command = [sys.executable, launch_image, v['user'], v['ip'], a['command']]
    1.75 -        # process = subprocess.Popen(process_command, shell = False, stdout = subprocess.PIPE)
    1.76 -        # result = process.communicate()[0]
    1.77 -        # if process.returncode != 0:
    1.78 -            # return 'Launch of application aborted.'
    1.79 -        
    1.80 -        # return result
    1.81 -        
    1.82 -
    1.83 -class os_credentials:
    1.84      """OpenSecurity '/credentials' handler.
    1.85      
    1.86      This is called on GET /credentials?text=TEXT.
    1.87 @@ -134,18 +86,56 @@
    1.88          if not "text" in args:
    1.89              raise web.badrequest('no text given')
    1.90          
    1.91 -        # invoke the user dialog as a subprocess
    1.92 -        dlg_image = os.path.join(sys.path[0], 'opensecurity_dialog.py')
    1.93 +        # remember remote ip
    1.94 +        remote_ip = web.ctx.environ['REMOTE_ADDR']
    1.95 +
    1.96 +        # create the process which queries the user
    1.97 +        dlg_image = os.path.join(sys.path[0], 'opensecurity_dialog.pyw')
    1.98          process_command = [sys.executable, dlg_image, 'credentials', args.text]
    1.99 -        process = subprocess.Popen(process_command, shell = False, stdout = subprocess.PIPE)
   1.100 -        result = process.communicate()[0]
   1.101 -        if process.returncode != 0:
   1.102 -            return 'Credentials request has been aborted.'
   1.103 +        process = subprocess.Popen(process_command, shell = False, stdout = subprocess.PIPE)        
   1.104          
   1.105 -        return result
   1.106 +        # run process result handling in seprate thread (not to block main one)
   1.107 +        bouncer = UserResultBouncer(process, remote_ip, '/credentials')
   1.108 +        bouncer.start()
   1.109 +         
   1.110 +        return 'user queried for credentials'
   1.111 +
   1.112 +
   1.113 +class os_keyfile:
   1.114 +
   1.115 +    """OpenSecurity '/keyfile' handler.
   1.116 +    
   1.117 +    This is called on GET /keyfile?text=TEXT.
   1.118 +    Ideally this should pop up a user dialog to insert his
   1.119 +    password along with a keyfile.
   1.120 +    """
   1.121 +    
   1.122 +    def GET(self):
   1.123 +        
   1.124 +        # pick the arguments
   1.125 +        args = web.input()
   1.126 +        
   1.127 +        # we _need_ a text
   1.128 +        if not "text" in args:
   1.129 +            raise web.badrequest('no text given')
   1.130 +            
   1.131 +        # remember remote ip
   1.132 +        remote_ip = web.ctx.environ['REMOTE_ADDR']
   1.133 +        
   1.134 +        # create the process which queries the user
   1.135 +        dlg_image = os.path.join(sys.path[0], 'opensecurity_dialog.pyw')
   1.136 +        process_command = [sys.executable, dlg_image, 'keyfile', args.text]
   1.137 +        process = subprocess.Popen(process_command, shell = False, stdout = subprocess.PIPE)        
   1.138 +        
   1.139 +        # run process result handling in seprate thread (not to block main one)
   1.140 +        bouncer = UserResultBouncer(process, remote_ip, '/keyfile')
   1.141 +        bouncer.start()
   1.142 +         
   1.143 +        return 'user queried for password and keyfile'
   1.144  
   1.145  
   1.146  class os_notification:
   1.147 +
   1.148      """OpenSecurity '/notification' handler.
   1.149      
   1.150      This is called on GET /notification?msgtype=TYPE&text=TEXT.
   1.151 @@ -157,14 +147,11 @@
   1.152          # pick the arguments
   1.153          args = web.input()
   1.154          
   1.155 -        if "message" in args:
   1.156 -            print args.message
   1.157 -        
   1.158          # we _need_ a type
   1.159          if not "msgtype" in args:
   1.160              raise web.badrequest('no msgtype given')
   1.161              
   1.162 -        if not args.msgtype in Notification.TYPES:
   1.163 +        if not args.msgtype in ['information', 'warning', 'critical']:
   1.164              raise web.badrequest('Unknown value for msgtype')
   1.165              
   1.166          # we _need_ a text
   1.167 @@ -175,47 +162,12 @@
   1.168          dlg_image = os.path.join(sys.path[0], 'opensecurity_dialog.py')
   1.169          process_command = [sys.executable, dlg_image, 'notification-' + args.msgtype, args.text]
   1.170          process = subprocess.Popen(process_command, shell = False, stdout = subprocess.PIPE)
   1.171 +
   1.172          return "Ok"
   1.173  
   1.174 -class PasswordSender(threading.Thread):
   1.175 -    remote_ip = None
   1.176 -    args = None
   1.177 -    def __init__(self, remote_ip, args): 
   1.178 -        threading.Thread.__init__(self)
   1.179 -        self.args = args
   1.180 -        self.remote_ip = remote_ip
   1.181 - 
   1.182 -    def stop(self):
   1.183 -        self.running = False
   1.184 -        
   1.185 -    def run(self):
   1.186 -        # invoke the user dialog as a subprocess
   1.187 -        dlg_image = os.path.join(sys.path[0], 'opensecurity_dialog.py')
   1.188 -        process_command = [sys.executable, dlg_image, 'password', self.args.text]
   1.189 -        process = subprocess.Popen(process_command, shell = False, stdout = subprocess.PIPE)
   1.190 -        result = process.communicate()[0]
   1.191 -        if process.returncode != 0:
   1.192 -            print 'password request has been aborted.'
   1.193 -            return
   1.194 -        
   1.195 -        # all ok, tell send request back appropriate destination
   1.196 -        try:
   1.197 -            password = result.split(':')[1].split("'")[1]
   1.198 -        except:
   1.199 -            print 'error in password parsing'
   1.200 -            return
   1.201 -        
   1.202 -        url_addr = 'http://' + self.remote_ip + ':58080/password'
   1.203 -        url_data = urllib.urlencode({ 'password': password})
   1.204 -        url = url_addr + '?' + url_data
   1.205 -        req = urllib2.Request(url)
   1.206 -        try:
   1.207 -            res = urllib2.urlopen(req)
   1.208 -        except:
   1.209 -            print 'failed to contact: ' + url_addr
   1.210 -            return 
   1.211  
   1.212  class os_password:
   1.213 +
   1.214      """OpenSecurity '/password' handler.
   1.215      
   1.216      This is called on GET /password?text=TEXT.
   1.217 @@ -235,13 +187,20 @@
   1.218          # remember remote ip
   1.219          remote_ip = web.ctx.environ['REMOTE_ADDR']
   1.220          
   1.221 -        sender = PasswordSender(remote_ip, args)
   1.222 -        sender.start()
   1.223 +        # create the process which queries the user
   1.224 +        dlg_image = os.path.join(sys.path[0], 'opensecurity_dialog.pyw')
   1.225 +        process_command = [sys.executable, dlg_image, 'password', args.text]
   1.226 +        process = subprocess.Popen(process_command, shell = False, stdout = subprocess.PIPE)        
   1.227          
   1.228 -        return 'password told'
   1.229 +        # run process result handling in seprate thread (not to block main one)
   1.230 +        bouncer = UserResultBouncer(process, remote_ip, '/password')
   1.231 +        bouncer.start()
   1.232 +        
   1.233 +        return 'user queried for password'
   1.234  
   1.235  
   1.236  class os_root:
   1.237 +
   1.238      """OpenSecurity '/' handler"""
   1.239      
   1.240      def GET(self):
   1.241 @@ -271,6 +230,15 @@
   1.242      NOTE: check yout taskbar, the dialog window may not pop up in front of your browser window.
   1.243      
   1.244  
   1.245 +Request a combination of password and keyfile:
   1.246 +    (copy paste this into your browser's address field after the host:port)
   1.247 +    
   1.248 +    /keyfile?text=Your%20private%20RSA%20Keyfile%3A
   1.249 +    
   1.250 +    (eg.: http://127.0.0.1:8090//keyfile?text=Your%20private%20RSA%20Keyfile%3A)
   1.251 +    NOTE: check yout taskbar, the dialog window may not pop up in front of your browser window.
   1.252 +    
   1.253 +
   1.254  Start a Browser:
   1.255      (copy paste this into your browser's address field after the host:port)
   1.256  
   1.257 @@ -282,7 +250,57 @@
   1.258          return res
   1.259  
   1.260  
   1.261 +class UserResultBouncer(threading.Thread):
   1.262 +
   1.263 +    """A class to spawn off user I/O waiting and push the data back to the requesting services."""
   1.264 +
   1.265 +    def __init__(self, process, remote_ip, resource): 
   1.266 +
   1.267 +        """ctor"""
   1.268 +
   1.269 +        threading.Thread.__init__(self)
   1.270 +        self._process = process
   1.271 +        self._remote_ip = remote_ip
   1.272 +        self._resource = resource
   1.273 + 
   1.274 +    
   1.275 +    def stop(self):
   1.276 +
   1.277 +        """stop thread"""
   1.278 +        self.running = False
   1.279 +        
   1.280 +    
   1.281 +    def run(self):
   1.282 +
   1.283 +        """run the thread"""
   1.284 +
   1.285 +        # invoke the user dialog as a subprocess
   1.286 +        result = self._process.communicate()[0]
   1.287 +        if self._process.returncode != 0:
   1.288 +            print 'user request has been aborted.'
   1.289 +            return
   1.290 +        
   1.291 +        # all ok, tell send request back appropriate destination
   1.292 +        try:
   1.293 +            j = json.loads(result)
   1.294 +        except:
   1.295 +            print 'error in password parsing'
   1.296 +            return
   1.297 +        
   1.298 +        # TODO: it would be WAY easier and secure if we just 
   1.299 +        #       add the result json to a HTTP-POST here.
   1.300 +        url_addr = 'http://' + self._remote_ip + ':58080' + self._resource
   1.301 +        url = url_addr + '?' + urllib.urlencode(j)
   1.302 +        req = urllib2.Request(url)
   1.303 +        try:
   1.304 +            res = urllib2.urlopen(req)
   1.305 +        except:
   1.306 +            print 'failed to contact: ' + url_addr
   1.307 +            return 
   1.308 +
   1.309 +
   1.310  # start
   1.311  if __name__ == "__main__":
   1.312      server = web.application(opensecurity_urls, globals())
   1.313      server.run()
   1.314 +
     2.1 --- a/OpenSecurity/bin/opensecurity_dialog.pyw	Fri Apr 25 13:23:20 2014 +0200
     2.2 +++ b/OpenSecurity/bin/opensecurity_dialog.pyw	Tue Apr 29 13:00:46 2014 +0200
     2.3 @@ -51,7 +51,7 @@
     2.4      
     2.5      # parse command line
     2.6      parser = argparse.ArgumentParser(description = 'OpenSecurity Dialog.')
     2.7 -    parser.add_argument('mode', metavar='MODE', help='dialog mode: \'password\', \'credentials\', \'notification-information\', \'notification-warning\' or \'notification-critical\'')
     2.8 +    parser.add_argument('mode', metavar='MODE', help='dialog mode: \'password\', \'credentials\', \'keyfile\', \'notification-information\', \'notification-warning\' or \'notification-critical\'')
     2.9      parser.add_argument('text', metavar='TEXT', help='text to show')
    2.10      args = parser.parse_args()
    2.11      
    2.12 @@ -63,6 +63,9 @@
    2.13      if args.mode == 'credentials':
    2.14          d = CredentialsDialog(args.text)
    2.15      
    2.16 +    if args.mode == 'keyfile':
    2.17 +        d = KeyfileDialog(args.text)
    2.18 +    
    2.19      if args.mode == 'notification-information':
    2.20          d = NotificationDialog('OpenSecurity Information', args.text)
    2.21      
    2.22 @@ -70,7 +73,7 @@
    2.23          d = NotificationDialog('OpenSecurity Warning', args.text)
    2.24      
    2.25      if args.mode == 'notification-critical':
    2.26 -        d = NotificationDialog('OpenSecurity Criticali Message', args.text)
    2.27 +        d = NotificationDialog('OpenSecurity Critical Message', args.text)
    2.28          
    2.29      if not 'd' in locals():
    2.30          sys.stderr.write('unknown mode. type --help for help\n')
     3.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/OpenSecurity/bin/ui/KeyfileDialog.ui	Tue Apr 29 13:00:46 2014 +0200
     3.3 @@ -0,0 +1,174 @@
     3.4 +<?xml version="1.0" encoding="UTF-8"?>
     3.5 +<ui version="4.0">
     3.6 + <class>KeyfileDialog</class>
     3.7 + <widget class="QDialog" name="KeyfileDialog">
     3.8 +  <property name="geometry">
     3.9 +   <rect>
    3.10 +    <x>0</x>
    3.11 +    <y>0</y>
    3.12 +    <width>420</width>
    3.13 +    <height>120</height>
    3.14 +   </rect>
    3.15 +  </property>
    3.16 +  <property name="sizePolicy">
    3.17 +   <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
    3.18 +    <horstretch>0</horstretch>
    3.19 +    <verstretch>0</verstretch>
    3.20 +   </sizepolicy>
    3.21 +  </property>
    3.22 +  <property name="windowTitle">
    3.23 +   <string>OpenSecuirty Keyfile Request</string>
    3.24 +  </property>
    3.25 +  <property name="windowIcon">
    3.26 +   <iconset resource="opensecurity.qrc">
    3.27 +    <normaloff>:/opensecurity/gfx/opensecurity_icon_64.png</normaloff>:/opensecurity/gfx/opensecurity_icon_64.png</iconset>
    3.28 +  </property>
    3.29 +  <layout class="QVBoxLayout" name="lyMain">
    3.30 +   <item>
    3.31 +    <layout class="QHBoxLayout" name="lyContent">
    3.32 +     <property name="spacing">
    3.33 +      <number>16</number>
    3.34 +     </property>
    3.35 +     <item>
    3.36 +      <widget class="QLabel" name="lblIcon">
    3.37 +       <property name="text">
    3.38 +        <string/>
    3.39 +       </property>
    3.40 +       <property name="pixmap">
    3.41 +        <pixmap resource="opensecurity.qrc">:/opensecurity/gfx/opensecurity_icon_64.png</pixmap>
    3.42 +       </property>
    3.43 +       <property name="alignment">
    3.44 +        <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
    3.45 +       </property>
    3.46 +      </widget>
    3.47 +     </item>
    3.48 +     <item>
    3.49 +      <layout class="QGridLayout" name="lyCredentials" rowstretch="0,0,0,0" columnstretch="0,0,0">
    3.50 +       <property name="spacing">
    3.51 +        <number>4</number>
    3.52 +       </property>
    3.53 +       <item row="0" column="0" colspan="2">
    3.54 +        <widget class="QLabel" name="lblText">
    3.55 +         <property name="text">
    3.56 +          <string>TextLabel</string>
    3.57 +         </property>
    3.58 +        </widget>
    3.59 +       </item>
    3.60 +       <item row="3" column="0" colspan="2">
    3.61 +        <widget class="QWidget" name="wdCredentialsSpacer" native="true"/>
    3.62 +       </item>
    3.63 +       <item row="1" column="0">
    3.64 +        <widget class="QLabel" name="lblPassword">
    3.65 +         <property name="text">
    3.66 +          <string>&amp;Password:</string>
    3.67 +         </property>
    3.68 +         <property name="buddy">
    3.69 +          <cstring>edtPassword</cstring>
    3.70 +         </property>
    3.71 +        </widget>
    3.72 +       </item>
    3.73 +       <item row="2" column="0">
    3.74 +        <widget class="QLabel" name="lblKeyfile">
    3.75 +         <property name="text">
    3.76 +          <string>&amp;Keyfile:</string>
    3.77 +         </property>
    3.78 +         <property name="buddy">
    3.79 +          <cstring>edtKeyfile</cstring>
    3.80 +         </property>
    3.81 +        </widget>
    3.82 +       </item>
    3.83 +       <item row="2" column="1">
    3.84 +        <widget class="QLineEdit" name="edtKeyfile"/>
    3.85 +       </item>
    3.86 +       <item row="2" column="2">
    3.87 +        <widget class="QToolButton" name="btnBrowse">
    3.88 +         <property name="text">
    3.89 +          <string>...</string>
    3.90 +         </property>
    3.91 +        </widget>
    3.92 +       </item>
    3.93 +       <item row="1" column="1" colspan="2">
    3.94 +        <widget class="QLineEdit" name="edtPassword">
    3.95 +         <property name="echoMode">
    3.96 +          <enum>QLineEdit::Password</enum>
    3.97 +         </property>
    3.98 +        </widget>
    3.99 +       </item>
   3.100 +      </layout>
   3.101 +     </item>
   3.102 +    </layout>
   3.103 +   </item>
   3.104 +   <item>
   3.105 +    <layout class="QHBoxLayout" name="lyButtons">
   3.106 +     <item>
   3.107 +      <spacer name="spButtons">
   3.108 +       <property name="orientation">
   3.109 +        <enum>Qt::Horizontal</enum>
   3.110 +       </property>
   3.111 +       <property name="sizeHint" stdset="0">
   3.112 +        <size>
   3.113 +         <width>40</width>
   3.114 +         <height>20</height>
   3.115 +        </size>
   3.116 +       </property>
   3.117 +      </spacer>
   3.118 +     </item>
   3.119 +     <item>
   3.120 +      <widget class="QPushButton" name="btnAbout">
   3.121 +       <property name="minimumSize">
   3.122 +        <size>
   3.123 +         <width>100</width>
   3.124 +         <height>0</height>
   3.125 +        </size>
   3.126 +       </property>
   3.127 +       <property name="text">
   3.128 +        <string>&amp;About</string>
   3.129 +       </property>
   3.130 +      </widget>
   3.131 +     </item>
   3.132 +     <item>
   3.133 +      <widget class="QPushButton" name="btnCancel">
   3.134 +       <property name="minimumSize">
   3.135 +        <size>
   3.136 +         <width>100</width>
   3.137 +         <height>0</height>
   3.138 +        </size>
   3.139 +       </property>
   3.140 +       <property name="text">
   3.141 +        <string>&amp;Cancel</string>
   3.142 +       </property>
   3.143 +      </widget>
   3.144 +     </item>
   3.145 +     <item>
   3.146 +      <widget class="QPushButton" name="btnOk">
   3.147 +       <property name="minimumSize">
   3.148 +        <size>
   3.149 +         <width>100</width>
   3.150 +         <height>0</height>
   3.151 +        </size>
   3.152 +       </property>
   3.153 +       <property name="text">
   3.154 +        <string>&amp;Ok</string>
   3.155 +       </property>
   3.156 +       <property name="default">
   3.157 +        <bool>true</bool>
   3.158 +       </property>
   3.159 +      </widget>
   3.160 +     </item>
   3.161 +    </layout>
   3.162 +   </item>
   3.163 +  </layout>
   3.164 + </widget>
   3.165 + <tabstops>
   3.166 +  <tabstop>edtPassword</tabstop>
   3.167 +  <tabstop>edtKeyfile</tabstop>
   3.168 +  <tabstop>btnBrowse</tabstop>
   3.169 +  <tabstop>btnAbout</tabstop>
   3.170 +  <tabstop>btnCancel</tabstop>
   3.171 +  <tabstop>btnOk</tabstop>
   3.172 + </tabstops>
   3.173 + <resources>
   3.174 +  <include location="opensecurity.qrc"/>
   3.175 + </resources>
   3.176 + <connections/>
   3.177 +</ui>
     4.1 --- a/OpenSecurity/bin/ui/Makefile	Fri Apr 25 13:23:20 2014 +0200
     4.2 +++ b/OpenSecurity/bin/ui/Makefile	Tue Apr 29 13:00:46 2014 +0200
     4.3 @@ -5,6 +5,7 @@
     4.4  	ui_ConfigureDialog.py \
     4.5  	ui_CredentialsDialog.py \
     4.6  	ui_LaunchDialog.py \
     4.7 +	ui_KeyfileDialog.py \
     4.8  	ui_NotificationDialog.py \
     4.9  	ui_PasswordDialog.py 
    4.10  
     5.1 --- a/OpenSecurity/bin/ui/__init__.py	Fri Apr 25 13:23:20 2014 +0200
     5.2 +++ b/OpenSecurity/bin/ui/__init__.py	Tue Apr 29 13:00:46 2014 +0200
     5.3 @@ -35,6 +35,7 @@
     5.4  from about_dialog import AboutDialog
     5.5  from configure_dialog import ConfigureDialog
     5.6  from credentials_dialog import CredentialsDialog
     5.7 +from keyfile_dialog import KeyfileDialog
     5.8  from launch_dialog import LaunchDialog
     5.9  from notification_dialog import NotificationDialog
    5.10  from password_dialog import  PasswordDialog
    5.11 @@ -45,6 +46,7 @@
    5.12      'AboutDialog',
    5.13      'ConfigureDialog',
    5.14      'CredentialsDialog',
    5.15 +    'KeyfileDialog',
    5.16      'LaunchDialog',
    5.17      'NotificationDialog',
    5.18      'PasswordDialog'
     6.1 --- a/OpenSecurity/bin/ui/credentials_dialog.py	Fri Apr 25 13:23:20 2014 +0200
     6.2 +++ b/OpenSecurity/bin/ui/credentials_dialog.py	Tue Apr 29 13:00:46 2014 +0200
     6.3 @@ -82,12 +82,12 @@
     6.4          
     6.5          """Ok button has been clicked."""
     6.6          sys.stdout.write('{ ')
     6.7 -        sys.stdout.write('\'user\': \'')
     6.8 +        sys.stdout.write('"user": "')
     6.9          sys.stdout.write(self.ui.edtUser.text())
    6.10 -        sys.stdout.write('\', ')
    6.11 -        sys.stdout.write('\'password\': \'')
    6.12 +        sys.stdout.write('", ')
    6.13 +        sys.stdout.write('"password": "')
    6.14          sys.stdout.write(self.ui.edtPassword.text())
    6.15 -        sys.stdout.write('\' ')
    6.16 +        sys.stdout.write('" ')
    6.17          sys.stdout.write('}\n')
    6.18          self.accept()
    6.19  
     7.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     7.2 +++ b/OpenSecurity/bin/ui/keyfile_dialog.py	Tue Apr 29 13:00:46 2014 +0200
     7.3 @@ -0,0 +1,132 @@
     7.4 +#!/bin/env python
     7.5 +# -*- coding: utf-8 -*-
     7.6 +
     7.7 +# ------------------------------------------------------------
     7.8 +# keyfile_dialog.pyw
     7.9 +# 
    7.10 +# the user should give us a keyfile
    7.11 +#
    7.12 +# Autor: Oliver Maurhart, <oliver.maurhart@ait.ac.at>
    7.13 +#
    7.14 +# Copyright (C) 2014 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 base64
    7.39 +import sys
    7.40 +
    7.41 +from PyQt4 import QtCore
    7.42 +from PyQt4 import QtGui
    7.43 +
    7.44 +from ui_KeyfileDialog import Ui_KeyfileDialog 
    7.45 +from about_dialog import AboutDialog
    7.46 +
    7.47 +
    7.48 +# ------------------------------------------------------------
    7.49 +# code
    7.50 +
    7.51 +
    7.52 +class KeyfileDialog(QtGui.QDialog):
    7.53 +
    7.54 +    """A dialog for letting the user pass on a password/keyfile combo"""
    7.55 +
    7.56 +    def __init__(self, user_text = 'Please provide an approbitate password and keyfile to proceed:'):
    7.57 +
    7.58 +        QtGui.QDialog.__init__(self)
    7.59 +
    7.60 +        # setup the user interface
    7.61 +        self.ui = Ui_KeyfileDialog()
    7.62 +        self.ui.setupUi(self)
    7.63 +    
    7.64 +        # local members
    7.65 +        self._about_dialog = AboutDialog()
    7.66 +        self._open_file_dialog = QtGui.QFileDialog(self, 'Open Keyfile', QtCore.QDir.homePath(), 'All Files (*.*);;')
    7.67 +        self._open_file_dialog.setAcceptMode(QtGui.QFileDialog.AcceptOpen)
    7.68 +        self._open_file_dialog.setFileMode(QtGui.QFileDialog.ExistingFile)
    7.69 +
    7.70 +        # connectors
    7.71 +        self.ui.lblText.setText(user_text)
    7.72 +        self.ui.btnAbout.clicked.connect(self.clicked_about)
    7.73 +        self.ui.btnCancel.clicked.connect(self.reject)
    7.74 +        self.ui.btnOk.clicked.connect(self.clicked_ok)
    7.75 +        self.ui.btnBrowse.clicked.connect(self.clicked_browse)
    7.76 +
    7.77 +        # positionate ourself central
    7.78 +        screen = QtGui.QDesktopWidget().screenGeometry()
    7.79 +        size = self.geometry()
    7.80 +        self.move((screen.width() - size.width()) / 2, (screen.height() - size.height()) / 2)
    7.81 + 
    7.82 +
    7.83 +    def clicked_about(self):
    7.84 +
    7.85 +        """About button has been clicked."""
    7.86 +        self._about_dialog.show()
    7.87 +
    7.88 +
    7.89 +    def clicked_browse(self):
    7.90 +
    7.91 +        """Browse button has been clicked."""
    7.92 +        if self._open_file_dialog.exec_() == QtGui.QDialog.Accepted:
    7.93 +            self.ui.edtKeyfile.setText(self._open_file_dialog.selectedFiles()[0])
    7.94 +
    7.95 +
    7.96 +    def clicked_ok(self):
    7.97 +        
    7.98 +        """Ok button has been clicked."""
    7.99 +
   7.100 +        # read the content of the keyfile
   7.101 +        keyfile_content = ''
   7.102 +        try:
   7.103 +            keyfile = open(self.ui.edtKeyfile.text(), 'r')
   7.104 +            keyfile_content = keyfile.read()
   7.105 +        except Exception as e:
   7.106 +            sys.stderr.write('failed to read keyfile content:\n' + str(e) + '\n')
   7.107 +            QtGui.QMessageBox.critical(self, 'Failed to read keyfile', str(e))
   7.108 +            return
   7.109 +
   7.110 +        # turn into Base64
   7.111 +        keyfile_content_base64 = base64.b64encode(keyfile_content)
   7.112 +
   7.113 +        sys.stdout.write('{ ')
   7.114 +        sys.stdout.write('"password": "')
   7.115 +        sys.stdout.write(self.ui.edtPassword.text())
   7.116 +        sys.stdout.write('", ')
   7.117 +        sys.stdout.write('"keyfile": "')
   7.118 +        sys.stdout.write(keyfile_content_base64)
   7.119 +        sys.stdout.write('" ')
   7.120 +        sys.stdout.write('}\n')
   7.121 +        self.accept()
   7.122 +
   7.123 +
   7.124 +    def set_user_text(user_text):
   7.125 +
   7.126 +        """Set a text to explain which password we need."""
   7.127 +        self.ui.lblText.setText(user_text)
   7.128 +
   7.129 +
   7.130 +if __name__ == "__main__":
   7.131 +    a = QtGui.QApplication(sys.argv)
   7.132 +    d = KeyfileDialog()
   7.133 +    d.show()
   7.134 +    sys.exit(a.exec_())     
   7.135 +
     8.1 --- a/OpenSecurity/bin/ui/password_dialog.py	Fri Apr 25 13:23:20 2014 +0200
     8.2 +++ b/OpenSecurity/bin/ui/password_dialog.py	Tue Apr 29 13:00:46 2014 +0200
     8.3 @@ -47,7 +47,7 @@
     8.4  
     8.5  class PasswordDialog(QtGui.QDialog):
     8.6  
     8.7 -    """A dialog for letting the user pass on a user/password combo"""
     8.8 +    """A dialog for letting the user type in a password"""
     8.9  
    8.10      def __init__(self, user_text = 'Please provide an approbitate password to proceed:'):
    8.11  
    8.12 @@ -82,9 +82,9 @@
    8.13          
    8.14          """Ok button has been clicked."""
    8.15          sys.stdout.write('{ ')
    8.16 -        sys.stdout.write('\'password\': \'')
    8.17 +        sys.stdout.write('"password": "')
    8.18          sys.stdout.write(self.ui.edtPassword.text())
    8.19 -        sys.stdout.write('\' ')
    8.20 +        sys.stdout.write('" ')
    8.21          sys.stdout.write('}\n')
    8.22          self.accept()
    8.23  
     9.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     9.2 +++ b/OpenSecurity/bin/ui/ui_KeyfileDialog.py	Tue Apr 29 13:00:46 2014 +0200
     9.3 @@ -0,0 +1,115 @@
     9.4 +# -*- coding: utf-8 -*-
     9.5 +
     9.6 +# Form implementation generated from reading ui file 'KeyfileDialog.ui'
     9.7 +#
     9.8 +# Created: Tue Apr 29 10:47:26 2014
     9.9 +#      by: PyQt4 UI code generator 4.10.3
    9.10 +#
    9.11 +# WARNING! All changes made in this file will be lost!
    9.12 +
    9.13 +from PyQt4 import QtCore, QtGui
    9.14 +
    9.15 +try:
    9.16 +    _fromUtf8 = QtCore.QString.fromUtf8
    9.17 +except AttributeError:
    9.18 +    def _fromUtf8(s):
    9.19 +        return s
    9.20 +
    9.21 +try:
    9.22 +    _encoding = QtGui.QApplication.UnicodeUTF8
    9.23 +    def _translate(context, text, disambig):
    9.24 +        return QtGui.QApplication.translate(context, text, disambig, _encoding)
    9.25 +except AttributeError:
    9.26 +    def _translate(context, text, disambig):
    9.27 +        return QtGui.QApplication.translate(context, text, disambig)
    9.28 +
    9.29 +class Ui_KeyfileDialog(object):
    9.30 +    def setupUi(self, KeyfileDialog):
    9.31 +        KeyfileDialog.setObjectName(_fromUtf8("KeyfileDialog"))
    9.32 +        KeyfileDialog.resize(420, 120)
    9.33 +        sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Preferred, QtGui.QSizePolicy.Preferred)
    9.34 +        sizePolicy.setHorizontalStretch(0)
    9.35 +        sizePolicy.setVerticalStretch(0)
    9.36 +        sizePolicy.setHeightForWidth(KeyfileDialog.sizePolicy().hasHeightForWidth())
    9.37 +        KeyfileDialog.setSizePolicy(sizePolicy)
    9.38 +        icon = QtGui.QIcon()
    9.39 +        icon.addPixmap(QtGui.QPixmap(_fromUtf8(":/opensecurity/gfx/opensecurity_icon_64.png")), QtGui.QIcon.Normal, QtGui.QIcon.Off)
    9.40 +        KeyfileDialog.setWindowIcon(icon)
    9.41 +        self.lyMain = QtGui.QVBoxLayout(KeyfileDialog)
    9.42 +        self.lyMain.setObjectName(_fromUtf8("lyMain"))
    9.43 +        self.lyContent = QtGui.QHBoxLayout()
    9.44 +        self.lyContent.setSpacing(16)
    9.45 +        self.lyContent.setObjectName(_fromUtf8("lyContent"))
    9.46 +        self.lblIcon = QtGui.QLabel(KeyfileDialog)
    9.47 +        self.lblIcon.setText(_fromUtf8(""))
    9.48 +        self.lblIcon.setPixmap(QtGui.QPixmap(_fromUtf8(":/opensecurity/gfx/opensecurity_icon_64.png")))
    9.49 +        self.lblIcon.setAlignment(QtCore.Qt.AlignLeading|QtCore.Qt.AlignLeft|QtCore.Qt.AlignTop)
    9.50 +        self.lblIcon.setObjectName(_fromUtf8("lblIcon"))
    9.51 +        self.lyContent.addWidget(self.lblIcon)
    9.52 +        self.lyCredentials = QtGui.QGridLayout()
    9.53 +        self.lyCredentials.setSpacing(4)
    9.54 +        self.lyCredentials.setObjectName(_fromUtf8("lyCredentials"))
    9.55 +        self.lblText = QtGui.QLabel(KeyfileDialog)
    9.56 +        self.lblText.setObjectName(_fromUtf8("lblText"))
    9.57 +        self.lyCredentials.addWidget(self.lblText, 0, 0, 1, 2)
    9.58 +        self.wdCredentialsSpacer = QtGui.QWidget(KeyfileDialog)
    9.59 +        self.wdCredentialsSpacer.setObjectName(_fromUtf8("wdCredentialsSpacer"))
    9.60 +        self.lyCredentials.addWidget(self.wdCredentialsSpacer, 3, 0, 1, 2)
    9.61 +        self.lblPassword = QtGui.QLabel(KeyfileDialog)
    9.62 +        self.lblPassword.setObjectName(_fromUtf8("lblPassword"))
    9.63 +        self.lyCredentials.addWidget(self.lblPassword, 1, 0, 1, 1)
    9.64 +        self.lblKeyfile = QtGui.QLabel(KeyfileDialog)
    9.65 +        self.lblKeyfile.setObjectName(_fromUtf8("lblKeyfile"))
    9.66 +        self.lyCredentials.addWidget(self.lblKeyfile, 2, 0, 1, 1)
    9.67 +        self.edtKeyfile = QtGui.QLineEdit(KeyfileDialog)
    9.68 +        self.edtKeyfile.setObjectName(_fromUtf8("edtKeyfile"))
    9.69 +        self.lyCredentials.addWidget(self.edtKeyfile, 2, 1, 1, 1)
    9.70 +        self.btnBrowse = QtGui.QToolButton(KeyfileDialog)
    9.71 +        self.btnBrowse.setObjectName(_fromUtf8("btnBrowse"))
    9.72 +        self.lyCredentials.addWidget(self.btnBrowse, 2, 2, 1, 1)
    9.73 +        self.edtPassword = QtGui.QLineEdit(KeyfileDialog)
    9.74 +        self.edtPassword.setEchoMode(QtGui.QLineEdit.Password)
    9.75 +        self.edtPassword.setObjectName(_fromUtf8("edtPassword"))
    9.76 +        self.lyCredentials.addWidget(self.edtPassword, 1, 1, 1, 2)
    9.77 +        self.lyContent.addLayout(self.lyCredentials)
    9.78 +        self.lyMain.addLayout(self.lyContent)
    9.79 +        self.lyButtons = QtGui.QHBoxLayout()
    9.80 +        self.lyButtons.setObjectName(_fromUtf8("lyButtons"))
    9.81 +        spacerItem = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum)
    9.82 +        self.lyButtons.addItem(spacerItem)
    9.83 +        self.btnAbout = QtGui.QPushButton(KeyfileDialog)
    9.84 +        self.btnAbout.setMinimumSize(QtCore.QSize(100, 0))
    9.85 +        self.btnAbout.setObjectName(_fromUtf8("btnAbout"))
    9.86 +        self.lyButtons.addWidget(self.btnAbout)
    9.87 +        self.btnCancel = QtGui.QPushButton(KeyfileDialog)
    9.88 +        self.btnCancel.setMinimumSize(QtCore.QSize(100, 0))
    9.89 +        self.btnCancel.setObjectName(_fromUtf8("btnCancel"))
    9.90 +        self.lyButtons.addWidget(self.btnCancel)
    9.91 +        self.btnOk = QtGui.QPushButton(KeyfileDialog)
    9.92 +        self.btnOk.setMinimumSize(QtCore.QSize(100, 0))
    9.93 +        self.btnOk.setDefault(True)
    9.94 +        self.btnOk.setObjectName(_fromUtf8("btnOk"))
    9.95 +        self.lyButtons.addWidget(self.btnOk)
    9.96 +        self.lyMain.addLayout(self.lyButtons)
    9.97 +        self.lblPassword.setBuddy(self.edtPassword)
    9.98 +        self.lblKeyfile.setBuddy(self.edtKeyfile)
    9.99 +
   9.100 +        self.retranslateUi(KeyfileDialog)
   9.101 +        QtCore.QMetaObject.connectSlotsByName(KeyfileDialog)
   9.102 +        KeyfileDialog.setTabOrder(self.edtPassword, self.edtKeyfile)
   9.103 +        KeyfileDialog.setTabOrder(self.edtKeyfile, self.btnBrowse)
   9.104 +        KeyfileDialog.setTabOrder(self.btnBrowse, self.btnAbout)
   9.105 +        KeyfileDialog.setTabOrder(self.btnAbout, self.btnCancel)
   9.106 +        KeyfileDialog.setTabOrder(self.btnCancel, self.btnOk)
   9.107 +
   9.108 +    def retranslateUi(self, KeyfileDialog):
   9.109 +        KeyfileDialog.setWindowTitle(_translate("KeyfileDialog", "OpenSecuirty Keyfile Request", None))
   9.110 +        self.lblText.setText(_translate("KeyfileDialog", "TextLabel", None))
   9.111 +        self.lblPassword.setText(_translate("KeyfileDialog", "&Password:", None))
   9.112 +        self.lblKeyfile.setText(_translate("KeyfileDialog", "&Keyfile:", None))
   9.113 +        self.btnBrowse.setText(_translate("KeyfileDialog", "...", None))
   9.114 +        self.btnAbout.setText(_translate("KeyfileDialog", "&About", None))
   9.115 +        self.btnCancel.setText(_translate("KeyfileDialog", "&Cancel", None))
   9.116 +        self.btnOk.setText(_translate("KeyfileDialog", "&Ok", None))
   9.117 +
   9.118 +import opensecurity_rc