OpenSecurity/bin/opensecurity_client_restful_server.py
author mb
Fri, 07 Mar 2014 14:32:12 +0100
changeset 90 bfd41c38d156
parent 46 f659d8fb57a8
child 112 9cd4654c040b
permissions -rwxr-xr-x
new version. many bugfixes and new functionality
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
mb@90
    42
import threading
mb@90
    43
import time
om@13
    44
om@13
    45
# local
om@13
    46
from environment import Environment
om@29
    47
from notification import Notification
om@13
    48
om@13
    49
om@13
    50
# ------------------------------------------------------------
om@13
    51
# const
om@13
    52
om@13
    53
om@31
    54
__version__ = "0.2"
om@13
    55
om@13
    56
om@13
    57
"""All the URLs we know mapping to class handler"""
om@13
    58
opensecurity_urls = (
om@31
    59
    #'/application',             'os_application',
om@13
    60
    '/credentials',             'os_credentials',
om@29
    61
    '/notification',            'os_notification',
om@13
    62
    '/password',                'os_password',
om@13
    63
    '/',                        'os_root'
om@13
    64
)
om@13
    65
om@13
    66
om@13
    67
# ------------------------------------------------------------
om@13
    68
# code
om@13
    69
om@13
    70
om@31
    71
# class os_application:
om@31
    72
#
om@31
    73
# PRESUMLY DEAD CODE
om@31
    74
#
om@31
    75
    # """OpenSecurity '/application' handler.
om@13
    76
    
om@31
    77
    # This is called on GET /application?vm=VM-ID&app=APP-ID
om@31
    78
    # This tries to access the vm identified with the label VM-ID
om@31
    79
    # and launched the application identified APP-ID
om@31
    80
    # """
om@13
    81
    
om@31
    82
    # def GET(self):
om@13
    83
        
om@31
    84
        # # pick the arguments
om@31
    85
        # args = web.input()
om@13
    86
        
om@31
    87
        # # we _need_ a vm
om@31
    88
        # if not "vm" in args:
om@31
    89
            # raise web.badrequest('no vm given')
om@13
    90
        
om@31
    91
        # # we _need_ a app
om@31
    92
        # if not "command" in args:
om@31
    93
            # raise web.badrequest('no app given')
om@13
    94
        
om@31
    95
        # # check if we do have valid vm
om@31
    96
        # v = [v for v in vms if v['name'] == args.vm]
om@31
    97
        # if len(v) == 0:
om@31
    98
            # raise web.notfound('vm not found')
om@31
    99
        # v = v[0]
om@13
   100
        
om@31
   101
        # # check if we do have a valid app
om@31
   102
        # a = [a for a in apps if a['name'] == args.app]
om@31
   103
        # if len(a) == 0:
om@31
   104
            # raise web.notfound('app not found')
om@31
   105
        # a = a[0]
om@13
   106
        
om@31
   107
        # # invoke launch with 
om@31
   108
        # res = "starting: launch " + v['user'] + " " + v['ip'] + " " + a['command']
om@31
   109
om@31
   110
        # launch_image = os.path.join(sys.path[0], 'launch.py')
om@31
   111
        # process_command = [sys.executable, launch_image, v['user'], v['ip'], a['command']]
om@31
   112
        # process = subprocess.Popen(process_command, shell = False, stdout = subprocess.PIPE)
om@31
   113
        # result = process.communicate()[0]
om@31
   114
        # if process.returncode != 0:
om@31
   115
            # return 'Launch of application aborted.'
om@13
   116
        
om@31
   117
        # return result
om@13
   118
        
om@13
   119
om@13
   120
class os_credentials:
om@13
   121
    """OpenSecurity '/credentials' handler.
om@13
   122
    
om@13
   123
    This is called on GET /credentials?text=TEXT.
om@13
   124
    Ideally this should pop up a user dialog to insert his
om@13
   125
    credentials based the given TEXT.
om@13
   126
    """
om@13
   127
    
om@13
   128
    def GET(self):
om@13
   129
        
om@13
   130
        # pick the arguments
om@13
   131
        args = web.input()
om@13
   132
        
om@29
   133
        # we _need_ a text
om@13
   134
        if not "text" in args:
om@29
   135
            raise web.badrequest('no text given')
om@13
   136
        
om@13
   137
        # invoke the user dialog as a subprocess
om@29
   138
        dlg_image = os.path.join(sys.path[0], 'opensecurity_dialog.py')
om@29
   139
        process_command = [sys.executable, dlg_image, 'credentials', args.text]
om@13
   140
        process = subprocess.Popen(process_command, shell = False, stdout = subprocess.PIPE)
om@13
   141
        result = process.communicate()[0]
om@13
   142
        if process.returncode != 0:
om@13
   143
            return 'Credentials request has been aborted.'
om@13
   144
        
om@13
   145
        return result
om@13
   146
om@13
   147
om@29
   148
class os_notification:
om@29
   149
    """OpenSecurity '/notification' handler.
om@29
   150
    
om@29
   151
    This is called on GET /notification?msgtype=TYPE&text=TEXT.
om@29
   152
    This will pop up an OpenSecurity notifcation window
om@29
   153
    """
om@29
   154
    
om@29
   155
    def GET(self):
om@29
   156
        
om@29
   157
        # pick the arguments
om@29
   158
        args = web.input()
om@29
   159
        
mb@90
   160
        if "message" in args:
mb@90
   161
            print args.message
mb@90
   162
        
om@29
   163
        # we _need_ a type
om@29
   164
        if not "msgtype" in args:
om@29
   165
            raise web.badrequest('no msgtype given')
om@29
   166
            
om@29
   167
        if not args.msgtype in Notification.TYPES:
om@29
   168
            raise web.badrequest('Unknown value for msgtype')
om@29
   169
            
om@29
   170
        # we _need_ a text
om@29
   171
        if not "text" in args:
om@29
   172
            raise web.badrequest('no text given')
om@29
   173
            
om@29
   174
        # invoke the user dialog as a subprocess
om@29
   175
        dlg_image = os.path.join(sys.path[0], 'opensecurity_dialog.py')
om@29
   176
        process_command = [sys.executable, dlg_image, 'notification-' + args.msgtype, args.text]
om@29
   177
        process = subprocess.Popen(process_command, shell = False, stdout = subprocess.PIPE)
om@29
   178
        return "Ok"
om@29
   179
mb@90
   180
class PasswordSender(threading.Thread):
mb@90
   181
    remote_ip = None
mb@90
   182
    args = None
mb@90
   183
    def __init__(self, remote_ip, args): 
mb@90
   184
        threading.Thread.__init__(self)
mb@90
   185
        self.args = args
mb@90
   186
        self.remote_ip = remote_ip
mb@90
   187
 
mb@90
   188
    def stop(self):
mb@90
   189
        self.running = False
mb@90
   190
        
mb@90
   191
    def run(self):
mb@90
   192
        # invoke the user dialog as a subprocess
mb@90
   193
        dlg_image = os.path.join(sys.path[0], 'opensecurity_dialog.py')
mb@90
   194
        process_command = [sys.executable, dlg_image, 'password', self.args.text]
mb@90
   195
        process = subprocess.Popen(process_command, shell = False, stdout = subprocess.PIPE)
mb@90
   196
        result = process.communicate()[0]
mb@90
   197
        if process.returncode != 0:
mb@90
   198
            print 'password request has been aborted.'
mb@90
   199
            return
mb@90
   200
        
mb@90
   201
        # all ok, tell send request back appropriate destination
mb@90
   202
        try:
mb@90
   203
            password = result.split(':')[1].split("'")[1]
mb@90
   204
        except:
mb@90
   205
            print 'error in password parsing'
mb@90
   206
            return
mb@90
   207
        
mb@90
   208
        url_addr = 'http://' + self.remote_ip + ':58080/password'
mb@90
   209
        url_data = urllib.urlencode({ 'password': password})
mb@90
   210
        url = url_addr + '?' + url_data
mb@90
   211
        req = urllib2.Request(url)
mb@90
   212
        try:
mb@90
   213
            res = urllib2.urlopen(req)
mb@90
   214
        except:
mb@90
   215
            print 'failed to contact: ' + url_addr
mb@90
   216
            return 
om@29
   217
om@13
   218
class os_password:
om@13
   219
    """OpenSecurity '/password' handler.
om@13
   220
    
om@13
   221
    This is called on GET /password?text=TEXT.
om@13
   222
    Ideally this should pop up a user dialog to insert his
om@13
   223
    password based device name.
om@13
   224
    """
om@13
   225
    
om@13
   226
    def GET(self):
om@13
   227
        
om@13
   228
        # pick the arguments
om@13
   229
        args = web.input()
om@13
   230
        
om@29
   231
        # we _need_ a text
om@13
   232
        if not "text" in args:
om@29
   233
            raise web.badrequest('no text given')
om@13
   234
            
om@29
   235
        # remember remote ip
om@29
   236
        remote_ip = web.ctx.environ['REMOTE_ADDR']
om@29
   237
        
mb@90
   238
        sender = PasswordSender(remote_ip, args)
mb@90
   239
        sender.start()
om@29
   240
        
om@29
   241
        return 'password told'
om@13
   242
om@13
   243
om@13
   244
class os_root:
om@13
   245
    """OpenSecurity '/' handler"""
om@13
   246
    
om@13
   247
    def GET(self):
om@13
   248
    
om@13
   249
        res = "OpenSecurity-Client RESTFul Server { \"version\": \"%s\" }" % __version__
om@13
   250
        
om@13
   251
        # add some sample links
om@13
   252
        res = res + """
om@13
   253
        
om@13
   254
USAGE EXAMPLES:
om@13
   255
        
om@13
   256
Request a password: 
om@13
   257
    (copy paste this into your browser's address field after the host:port)
om@13
   258
    
om@13
   259
    /password?text=Give+me+a+password+for+device+%22My+USB+Drive%22+(ID%3A+32090-AAA-X0)
om@13
   260
    
om@13
   261
    (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
   262
    NOTE: check yout taskbar, the dialog window may not pop up in front of your browser window.
om@13
   263
    
om@13
   264
    
om@13
   265
Request a combination of user and password:
om@13
   266
    (copy paste this into your browser's address field after the host:port)
om@13
   267
    
om@13
   268
    /credentials?text=Tell+the+NSA+which+credentials+to+use+in+order+to+avoid+hacking+noise+on+wire.
om@13
   269
    
om@13
   270
    (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
   271
    NOTE: check yout taskbar, the dialog window may not pop up in front of your browser window.
om@13
   272
    
om@13
   273
om@13
   274
Start a Browser:
om@13
   275
    (copy paste this into your browser's address field after the host:port)
om@13
   276
om@13
   277
    /application?vm=Debian+7&app=Browser
om@13
   278
om@13
   279
    (e.g. http://127.0.0.1:8090/application?vm=Debian+7&app=Browser)
om@13
   280
        """
om@13
   281
    
om@13
   282
        return res
om@13
   283
om@13
   284
om@13
   285
# start
om@13
   286
if __name__ == "__main__":
om@13
   287
    server = web.application(opensecurity_urls, globals())
om@13
   288
    server.run()