passwordreceiver.py
author ft
Mon, 10 Nov 2014 14:45:01 +0100
changeset 1 f7b8f096b359
parent 0 28b7682d5476
permissions -rw-r--r--
upaded package with latest source
ft@0
     1
#!/usr/bin/python
ft@0
     2
ft@0
     3
# ------------------------------------------------------------
ft@0
     4
# opensecurity package file
ft@0
     5
#
ft@0
     6
# Autor: X-Net Services GmbH <office@x-net.at>
ft@0
     7
#
ft@0
     8
# Copyright 2013-2014 X-Net and AIT Austrian Institute of Technology
ft@0
     9
#
ft@0
    10
#
ft@0
    11
#     X-Net Technologies GmbH
ft@0
    12
#     Elisabethstrasse 1
ft@0
    13
#     4020 Linz
ft@0
    14
#     AUSTRIA
ft@0
    15
#     https://www.x-net.at
ft@0
    16
#
ft@0
    17
#     AIT Austrian Institute of Technology
ft@0
    18
#     Donau City Strasse 1
ft@0
    19
#     1220 Wien
ft@0
    20
#     AUSTRIA
ft@0
    21
#     http://www.ait.ac.at
ft@0
    22
#
ft@0
    23
#
ft@0
    24
# Licensed under the Apache License, Version 2.0 (the "License");
ft@0
    25
# you may not use this file except in compliance with the License.
ft@0
    26
# You may obtain a copy of the License at
ft@0
    27
#
ft@0
    28
#    http://www.apache.org/licenses/LICENSE-2.0
ft@0
    29
#
ft@0
    30
# Unless required by applicable law or agreed to in writing, software
ft@0
    31
# distributed under the License is distributed on an "AS IS" BASIS,
ft@0
    32
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
ft@0
    33
# See the License for the specific language governing permissions and
ft@0
    34
# limitations under the License.
ft@0
    35
# ------------------------------------------------------------
ft@0
    36
ft@0
    37
ft@0
    38
import subprocess
ft@0
    39
import web
ft@0
    40
import netifaces
ft@0
    41
import os
ft@0
    42
import sys
ft@0
    43
import base64
ft@1
    44
import thread
ft@1
    45
import urllib3
ft@1
    46
import netaddr
ft@0
    47
ft@0
    48
opensecurity_urls = (
ft@0
    49
    '/password',                'os_password',
ft@0
    50
    '/init',                    'os_init'
ft@0
    51
)
ft@0
    52
ft@1
    53
STATUS_CODE_OK = 200
ft@1
    54
ft@1
    55
ft@1
    56
def sendDataToRest (urlpath, data):
ft@1
    57
    netifaces.ifaddresses("eth0")[2][0]["addr"]
ft@1
    58
    
ft@1
    59
    # Get first address in network (0 = network ip -> 192.168.0.0)
ft@1
    60
    remote_ip = netaddr.IPNetwork("%s/%s" %(netifaces.ifaddresses("eth0")[2][0]["addr"], netifaces.ifaddresses("eth0")[2][0]["netmask"]))[1]
ft@1
    61
    
ft@1
    62
    url = ("http://%s:8090//%s" %(remote_ip, urlpath))
ft@1
    63
    
ft@1
    64
    try:
ft@1
    65
        response = httpPool.request_encode_body("POST", url, fields=data, retries=0)
ft@1
    66
    except Exception, e:
ft@1
    67
        return
ft@1
    68
    
ft@1
    69
    if response.status == STATUS_CODE_OK:
ft@1
    70
        return True
ft@1
    71
    else:
ft@1
    72
        return False
ft@1
    73
    
ft@1
    74
ft@1
    75
def sendNotification (type, message):
ft@1
    76
    data = {"msgtype" : type, "text" : message}
ft@1
    77
    
ft@1
    78
    if (type == "information"):
ft@1
    79
        sendDataToRest ("message", data)
ft@1
    80
    else:
ft@1
    81
        sendDataToRest ("notification", data)
ft@1
    82
ft@1
    83
def sendInitialisationFailedError():
ft@1
    84
    sendNotification("critical", "Initialisation of the stick failed.")
ft@1
    85
ft@1
    86
ft@1
    87
ft@1
    88
ft@1
    89
ft@1
    90
ft@0
    91
ft@0
    92
class os_password:
ft@0
    93
    
ft@0
    94
    # delete the key file in a secure way (will not working on ssd's :/ ,but ram only vm -> should be ok)
ft@0
    95
    def deleteKeyfile(self, keyfilepath):
ft@0
    96
        filesize = os.path.getsize(keyfilepath)
ft@0
    97
        keyfile = open (keyfilepath, "w+")
ft@0
    98
        for i in range (0, 10):
ft@0
    99
            keyfile.seek(0)
ft@0
   100
            keyfile.write(os.urandom(filesize))
ft@0
   101
            keyfile.flush()
ft@0
   102
        keyfile.close()
ft@0
   103
        os.remove(keyfilepath)
ft@0
   104
    
ft@0
   105
    
ft@0
   106
    def GET(self, settings):
ft@0
   107
        return self.POST(settings)
ft@0
   108
    
ft@0
   109
    def POST(self, settings):
ft@0
   110
        
ft@0
   111
        # pick the arguments
ft@0
   112
        args = web.input()
ft@0
   113
                      
ft@0
   114
        if not "password" in args:
ft@0
   115
            raise web.badrequest()
ft@0
   116
ft@0
   117
        if "keyfile" in args:
ft@0
   118
            keyfile = open (settings["keyfilepath"], "w+")
ft@0
   119
            keyfile.write(base64.b64decode(args["keyfile"]))
ft@0
   120
            keyfile.close()
ft@0
   121
            command = [settings["script"], settings["device"], settings["mountpoint"], args["password"], settings["keyfilepath"]]
ft@0
   122
        else:
ft@0
   123
            command = [settings["script"], settings["device"], settings["mountpoint"], args["password"]]
ft@0
   124
            
ft@0
   125
        process = subprocess.Popen( command, stdout=subprocess.PIPE, stderr=subprocess.PIPE )
ft@0
   126
        retval = process.wait()
ft@0
   127
        ( stdout, stderr ) = process.communicate()
ft@0
   128
        
ft@0
   129
        if "keyfile" in args:
ft@0
   130
            self.deleteKeyfile(settings["keyfilepath"])
ft@0
   131
        
ft@0
   132
        if (retval != 0):
ft@0
   133
            raise web.badrequest(stderr)
ft@0
   134
        
ft@0
   135
        return "Success: Encrypted Stick is mounted"
ft@0
   136
ft@0
   137
class os_init:
ft@0
   138
    # delete the key file in a secure way (will not working on ssd's :/ ,but ram only vm -> should be ok)
ft@0
   139
    def deleteKeyfile(self, keyfilepath):
ft@0
   140
        filesize = os.path.getsize(keyfilepath)
ft@0
   141
        keyfile = open (keyfilepath, "w+")
ft@0
   142
        for i in range (0, 10):
ft@0
   143
            keyfile.seek(0)
ft@0
   144
            keyfile.write(os.urandom(filesize))
ft@0
   145
            keyfile.flush()
ft@0
   146
        keyfile.close()
ft@0
   147
        os.remove(keyfilepath)
ft@0
   148
    
ft@0
   149
    def runPreInitScript(self, preinitscript, device):
ft@0
   150
        
ft@0
   151
        command = [preinitscript, device]
ft@0
   152
        process = subprocess.Popen( command, stdout=subprocess.PIPE, stderr=subprocess.PIPE )
ft@0
   153
        retval = process.wait()
ft@0
   154
        ( stdout, stderr ) = process.communicate()
ft@0
   155
        
ft@0
   156
        if (retval != 0):
ft@0
   157
            raise web.badrequest(stderr)
ft@0
   158
    
ft@0
   159
    def runPostInitScript(self, postinitscript):
ft@0
   160
        command = [postinitscript]
ft@0
   161
        process = subprocess.Popen( command, stdout=subprocess.PIPE, stderr=subprocess.PIPE )
ft@0
   162
        retval = process.wait()
ft@0
   163
        ( stdout, stderr ) = process.communicate()
ft@0
   164
        
ft@0
   165
        if (retval != 0):
ft@1
   166
            return False
ft@1
   167
        else:
ft@1
   168
            return True
ft@0
   169
    
ft@0
   170
    def GET(self, settings):
ft@0
   171
        return self.POST(settings)
ft@0
   172
    
ft@0
   173
    def POST(self, settings):
ft@0
   174
        
ft@0
   175
        # pick the arguments
ft@0
   176
        args = web.input()
ft@0
   177
                      
ft@0
   178
        if not "password" in args:
ft@0
   179
            raise web.badrequest()
ft@0
   180
        
ft@0
   181
        # Do the preinit stuff
ft@0
   182
        self.runPreInitScript(settings["preinitscript"], settings["device"])
ft@0
   183
ft@0
   184
        if "keyfile" in args:
ft@0
   185
            keyfile = open (settings["keyfilepath"], "w+")
ft@0
   186
            keyfile.write(base64.b64decode(args["keyfile"]))
ft@0
   187
            keyfile.close()
ft@0
   188
            command = [settings["script"], settings["device"], settings["mountpoint"], args["password"], settings["keyfilepath"]]
ft@0
   189
        else:
ft@0
   190
            command = [settings["script"], settings["device"], settings["mountpoint"], args["password"]]
ft@0
   191
        
ft@1
   192
        thread.start_new_thread(self.initStick, (command,settings,args,))
ft@1
   193
        
ft@1
   194
        return "Success: Init started"
ft@1
   195
ft@1
   196
    def initStick(self, command, settings, args):
ft@0
   197
        process = subprocess.Popen( command, stdout=subprocess.PIPE, stderr=subprocess.PIPE )
ft@0
   198
        retval = process.wait()
ft@0
   199
        ( stdout, stderr ) = process.communicate()
ft@0
   200
        
ft@0
   201
        if "keyfile" in args:
ft@0
   202
            self.deleteKeyfile(settings["keyfilepath"])
ft@0
   203
        
ft@0
   204
        if (retval != 0):
ft@1
   205
            sendInitialisationFailedError();
ft@0
   206
        
ft@0
   207
        # Do the postinit stuff
ft@1
   208
        if (self.runPostInitScript(settings["postinitscript"]) != True):
ft@1
   209
            sendInitialisationFailedError();
ft@0
   210
ft@0
   211
class MyRestListener(web.application):
ft@0
   212
    def __init__(self, mapping=(), fvars={}, autoreload=None, script=None, device=None, mountpoint=None, tries=None, keyfilepath=None, preinitscript=None, postinitscript=None):
ft@0
   213
        web.application.__init__(self, mapping, fvars, autoreload)
ft@0
   214
        self.device = device
ft@0
   215
        self.mountpoint = mountpoint
ft@0
   216
        self.script = script
ft@0
   217
        self.tries = tries
ft@0
   218
        self.keyfilepath = keyfilepath
ft@0
   219
        self.preinitscript = preinitscript
ft@0
   220
        self.postinitscript = postinitscript
ft@0
   221
        
ft@0
   222
    def run(self, interface, port, *middleware):
ft@0
   223
        func = self.wsgifunc(*middleware)
ft@0
   224
        ifaceip = netifaces.ifaddresses(interface)[2][0]["addr"]
ft@0
   225
        return web.httpserver.runsimple(func, (ifaceip, port))
ft@0
   226
    
ft@0
   227
    def handle(self):
ft@0
   228
        fn, args = self._match(self.mapping, web.ctx.path)
ft@0
   229
        args.append({"script": self.script, "device": self.device, "mountpoint": self.mountpoint, "tries": self.tries, "keyfilepath": self.keyfilepath, "preinitscript": self.preinitscript, "postinitscript": self.postinitscript})
ft@0
   230
        return self._delegate(fn, self.fvars, args)