OpenSecurity/bin/opensecurity_client_restful_server.py
author mb
Thu, 09 Jan 2014 10:44:42 +0100
changeset 46 f659d8fb57a8
parent 31 d95fe93d7a83
child 90 bfd41c38d156
permissions -rwxr-xr-x
latest changes from december 2013
om@13
     1
#!/bin/env python
om@13
     2
# -*- coding: utf-8 -*-
om@13
     3
om@13
     4
# ------------------------------------------------------------
om@13
     5
# opensecurity_client_restful_server
om@13
     6
# 
om@13
     7
# the OpenSecurity client RESTful server
om@13
     8
#
om@13
     9
# Autor: Oliver Maurhart, <oliver.maurhart@ait.ac.at>
om@13
    10
#
om@13
    11
# Copyright (C) 2013 AIT Austrian Institute of Technology
om@13
    12
# AIT Austrian Institute of Technology GmbH
om@13
    13
# Donau-City-Strasse 1 | 1220 Vienna | Austria
om@13
    14
# http://www.ait.ac.at
om@13
    15
#
om@13
    16
# This program is free software; you can redistribute it and/or
om@13
    17
# modify it under the terms of the GNU General Public License
om@13
    18
# as published by the Free Software Foundation version 2.
om@13
    19
# 
om@13
    20
# This program is distributed in the hope that it will be useful,
om@13
    21
# but WITHOUT ANY WARRANTY; without even the implied warranty of
om@13
    22
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
om@13
    23
# GNU General Public License for more details.
om@13
    24
# 
om@13
    25
# You should have received a copy of the GNU General Public License
om@13
    26
# along with this program; if not, write to the Free Software
om@13
    27
# Foundation, Inc., 51 Franklin Street, Fifth Floor, 
om@13
    28
# Boston, MA  02110-1301, USA.
om@13
    29
# ------------------------------------------------------------
om@13
    30
om@13
    31
om@13
    32
# ------------------------------------------------------------
om@13
    33
# imports
om@13
    34
om@13
    35
import os
om@13
    36
import os.path
om@13
    37
import subprocess
om@13
    38
import sys
om@29
    39
import urllib
om@29
    40
import urllib2
om@13
    41
import web
om@13
    42
om@13
    43
# local
om@13
    44
from environment import Environment
om@29
    45
from notification import Notification
om@13
    46
om@13
    47
om@13
    48
# ------------------------------------------------------------
om@13
    49
# const
om@13
    50
om@13
    51
om@31
    52
__version__ = "0.2"
om@13
    53
om@13
    54
om@13
    55
"""All the URLs we know mapping to class handler"""
om@13
    56
opensecurity_urls = (
om@31
    57
    #'/application',             'os_application',
om@13
    58
    '/credentials',             'os_credentials',
om@29
    59
    '/notification',            'os_notification',
om@13
    60
    '/password',                'os_password',
om@13
    61
    '/',                        'os_root'
om@13
    62
)
om@13
    63
om@13
    64
om@13
    65
# ------------------------------------------------------------
om@13
    66
# code
om@13
    67
om@13
    68
om@31
    69
# class os_application:
om@31
    70
#
om@31
    71
# PRESUMLY DEAD CODE
om@31
    72
#
om@31
    73
    # """OpenSecurity '/application' handler.
om@13
    74
    
om@31
    75
    # This is called on GET /application?vm=VM-ID&app=APP-ID
om@31
    76
    # This tries to access the vm identified with the label VM-ID
om@31
    77
    # and launched the application identified APP-ID
om@31
    78
    # """
om@13
    79
    
om@31
    80
    # def GET(self):
om@13
    81
        
om@31
    82
        # # pick the arguments
om@31
    83
        # args = web.input()
om@13
    84
        
om@31
    85
        # # we _need_ a vm
om@31
    86
        # if not "vm" in args:
om@31
    87
            # raise web.badrequest('no vm given')
om@13
    88
        
om@31
    89
        # # we _need_ a app
om@31
    90
        # if not "command" in args:
om@31
    91
            # raise web.badrequest('no app given')
om@13
    92
        
om@31
    93
        # # check if we do have valid vm
om@31
    94
        # v = [v for v in vms if v['name'] == args.vm]
om@31
    95
        # if len(v) == 0:
om@31
    96
            # raise web.notfound('vm not found')
om@31
    97
        # v = v[0]
om@13
    98
        
om@31
    99
        # # check if we do have a valid app
om@31
   100
        # a = [a for a in apps if a['name'] == args.app]
om@31
   101
        # if len(a) == 0:
om@31
   102
            # raise web.notfound('app not found')
om@31
   103
        # a = a[0]
om@13
   104
        
om@31
   105
        # # invoke launch with 
om@31
   106
        # res = "starting: launch " + v['user'] + " " + v['ip'] + " " + a['command']
om@31
   107
om@31
   108
        # launch_image = os.path.join(sys.path[0], 'launch.py')
om@31
   109
        # process_command = [sys.executable, launch_image, v['user'], v['ip'], a['command']]
om@31
   110
        # process = subprocess.Popen(process_command, shell = False, stdout = subprocess.PIPE)
om@31
   111
        # result = process.communicate()[0]
om@31
   112
        # if process.returncode != 0:
om@31
   113
            # return 'Launch of application aborted.'
om@13
   114
        
om@31
   115
        # return result
om@13
   116
        
om@13
   117
om@13
   118
class os_credentials:
om@13
   119
    """OpenSecurity '/credentials' handler.
om@13
   120
    
om@13
   121
    This is called on GET /credentials?text=TEXT.
om@13
   122
    Ideally this should pop up a user dialog to insert his
om@13
   123
    credentials based the given TEXT.
om@13
   124
    """
om@13
   125
    
om@13
   126
    def GET(self):
om@13
   127
        
om@13
   128
        # pick the arguments
om@13
   129
        args = web.input()
om@13
   130
        
om@29
   131
        # we _need_ a text
om@13
   132
        if not "text" in args:
om@29
   133
            raise web.badrequest('no text given')
om@13
   134
        
om@13
   135
        # invoke the user dialog as a subprocess
om@29
   136
        dlg_image = os.path.join(sys.path[0], 'opensecurity_dialog.py')
om@29
   137
        process_command = [sys.executable, dlg_image, 'credentials', args.text]
om@13
   138
        process = subprocess.Popen(process_command, shell = False, stdout = subprocess.PIPE)
om@13
   139
        result = process.communicate()[0]
om@13
   140
        if process.returncode != 0:
om@13
   141
            return 'Credentials request has been aborted.'
om@13
   142
        
om@13
   143
        return result
om@13
   144
om@13
   145
om@29
   146
class os_notification:
om@29
   147
    """OpenSecurity '/notification' handler.
om@29
   148
    
om@29
   149
    This is called on GET /notification?msgtype=TYPE&text=TEXT.
om@29
   150
    This will pop up an OpenSecurity notifcation window
om@29
   151
    """
om@29
   152
    
om@29
   153
    def GET(self):
om@29
   154
        
om@29
   155
        # pick the arguments
om@29
   156
        args = web.input()
om@29
   157
        
om@29
   158
        # we _need_ a type
om@29
   159
        if not "msgtype" in args:
om@29
   160
            raise web.badrequest('no msgtype given')
om@29
   161
            
om@29
   162
        if not args.msgtype in Notification.TYPES:
om@29
   163
            raise web.badrequest('Unknown value for msgtype')
om@29
   164
            
om@29
   165
        # we _need_ a text
om@29
   166
        if not "text" in args:
om@29
   167
            raise web.badrequest('no text given')
om@29
   168
            
om@29
   169
        # invoke the user dialog as a subprocess
om@29
   170
        dlg_image = os.path.join(sys.path[0], 'opensecurity_dialog.py')
om@29
   171
        process_command = [sys.executable, dlg_image, 'notification-' + args.msgtype, args.text]
om@29
   172
        process = subprocess.Popen(process_command, shell = False, stdout = subprocess.PIPE)
om@29
   173
        return "Ok"
om@29
   174
om@29
   175
om@13
   176
class os_password:
om@13
   177
    """OpenSecurity '/password' handler.
om@13
   178
    
om@13
   179
    This is called on GET /password?text=TEXT.
om@13
   180
    Ideally this should pop up a user dialog to insert his
om@13
   181
    password based device name.
om@13
   182
    """
om@13
   183
    
om@13
   184
    def GET(self):
om@13
   185
        
om@13
   186
        # pick the arguments
om@13
   187
        args = web.input()
om@13
   188
        
om@29
   189
        # we _need_ a text
om@13
   190
        if not "text" in args:
om@29
   191
            raise web.badrequest('no text given')
om@13
   192
            
om@29
   193
        # remember remote ip
om@29
   194
        remote_ip = web.ctx.environ['REMOTE_ADDR']
om@29
   195
        
om@13
   196
        # invoke the user dialog as a subprocess
om@29
   197
        dlg_image = os.path.join(sys.path[0], 'opensecurity_dialog.py')
om@29
   198
        process_command = [sys.executable, dlg_image, 'password', args.text]
om@13
   199
        process = subprocess.Popen(process_command, shell = False, stdout = subprocess.PIPE)
om@13
   200
        result = process.communicate()[0]
om@13
   201
        if process.returncode != 0:
om@13
   202
            return 'password request has been aborted.'
om@13
   203
        
om@29
   204
        # all ok, tell send request back appropriate destination
om@29
   205
        
om@29
   206
        # the returned value of the dialog is a jason object like
om@29
   207
        # "{ 'password': 'THE_PASSWORD' }"
om@29
   208
        # so we _could_ call eval(...) on this.
om@29
   209
        #
om@29
   210
        # However, anyone malicious enough _could_ encode a certain
om@29
   211
        # "password" making some nasty things within that eval code. :(
om@29
   212
        #
om@29
   213
        # So this is plain old-school string hacking then ...
om@29
   214
        try:
om@29
   215
            password = result.split(':')[1].split("'")[1]
om@29
   216
        except:
om@29
   217
            raise web.internalerror('error in password parsing')
om@29
   218
        
om@29
   219
        url_addr = 'http://' + remote_ip + ':58080/password'
om@29
   220
        url_data = urllib.urlencode({ 'password': password})
om@29
   221
        req = urllib2.Request(url = url_addr + '?' + url_data)
om@29
   222
        try:
om@29
   223
            res = urllib2.urlopen(req)
om@29
   224
        except:
om@29
   225
            raise web.internalerror('failed to contact: ' + url_addr)
om@29
   226
        
om@29
   227
        return 'password told'
om@13
   228
om@13
   229
om@13
   230
class os_root:
om@13
   231
    """OpenSecurity '/' handler"""
om@13
   232
    
om@13
   233
    def GET(self):
om@13
   234
    
om@13
   235
        res = "OpenSecurity-Client RESTFul Server { \"version\": \"%s\" }" % __version__
om@13
   236
        
om@13
   237
        # add some sample links
om@13
   238
        res = res + """
om@13
   239
        
om@13
   240
USAGE EXAMPLES:
om@13
   241
        
om@13
   242
Request a password: 
om@13
   243
    (copy paste this into your browser's address field after the host:port)
om@13
   244
    
om@13
   245
    /password?text=Give+me+a+password+for+device+%22My+USB+Drive%22+(ID%3A+32090-AAA-X0)
om@13
   246
    
om@13
   247
    (eg.: http://127.0.0.1:8090/password?text=Give+me+a+password+for+device+%22My+USB+Drive%22+(ID%3A+32090-AAA-X0))
om@13
   248
    NOTE: check yout taskbar, the dialog window may not pop up in front of your browser window.
om@13
   249
    
om@13
   250
    
om@13
   251
Request a combination of user and password:
om@13
   252
    (copy paste this into your browser's address field after the host:port)
om@13
   253
    
om@13
   254
    /credentials?text=Tell+the+NSA+which+credentials+to+use+in+order+to+avoid+hacking+noise+on+wire.
om@13
   255
    
om@13
   256
    (eg.: http://127.0.0.1:8090/credentials?text=Tell+the+NSA+which+credentials+to+use+in+order+to+avoid+hacking+noise+on+wire.)
om@13
   257
    NOTE: check yout taskbar, the dialog window may not pop up in front of your browser window.
om@13
   258
    
om@13
   259
om@13
   260
Start a Browser:
om@13
   261
    (copy paste this into your browser's address field after the host:port)
om@13
   262
om@13
   263
    /application?vm=Debian+7&app=Browser
om@13
   264
om@13
   265
    (e.g. http://127.0.0.1:8090/application?vm=Debian+7&app=Browser)
om@13
   266
        """
om@13
   267
    
om@13
   268
        return res
om@13
   269
om@13
   270
om@13
   271
# start
om@13
   272
if __name__ == "__main__":
om@13
   273
    server = web.application(opensecurity_urls, globals())
om@13
   274
    server.run()