src/encryptionprovider.py
author ft
Tue, 04 Nov 2014 14:23:14 +0100
changeset 27 a8c8d86b8501
parent 17 980ca72ff1f1
permissions -rwxr-xr-x
Added licence things
ft@0
     1
#!/usr/bin/python
ft@0
     2
ft@27
     3
# ------------------------------------------------------------
ft@27
     4
# opensecurity package file
ft@27
     5
#
ft@27
     6
# Autor: X-Net Services GmbH <office@x-net.at>
ft@27
     7
#
ft@27
     8
# Copyright 2013-2014 X-Net and AIT Austrian Institute of Technology
ft@27
     9
#
ft@27
    10
#
ft@27
    11
#     X-Net Technologies GmbH
ft@27
    12
#     Elisabethstrasse 1
ft@27
    13
#     4020 Linz
ft@27
    14
#     AUSTRIA
ft@27
    15
#     https://www.x-net.at
ft@27
    16
#
ft@27
    17
#     AIT Austrian Institute of Technology
ft@27
    18
#     Donau City Strasse 1
ft@27
    19
#     1220 Wien
ft@27
    20
#     AUSTRIA
ft@27
    21
#     http://www.ait.ac.at
ft@27
    22
#
ft@27
    23
#
ft@27
    24
# Licensed under the Apache License, Version 2.0 (the "License");
ft@27
    25
# you may not use this file except in compliance with the License.
ft@27
    26
# You may obtain a copy of the License at
ft@27
    27
#
ft@27
    28
#    http://www.apache.org/licenses/LICENSE-2.0
ft@27
    29
#
ft@27
    30
# Unless required by applicable law or agreed to in writing, software
ft@27
    31
# distributed under the License is distributed on an "AS IS" BASIS,
ft@27
    32
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
ft@27
    33
# See the License for the specific language governing permissions and
ft@27
    34
# limitations under the License.
ft@27
    35
# ------------------------------------------------------------
ft@27
    36
ft@0
    37
import subprocess
ft@0
    38
import web
ft@0
    39
import netifaces
ft@0
    40
import argparse
ft@0
    41
import thread
ft@0
    42
import time
ft@0
    43
import os
ft@0
    44
import sys
ft@0
    45
import ConfigParser
ft@0
    46
import logging
ft@1
    47
from passwordreceiver import *
ft@0
    48
ft@1
    49
MINOPTS = { "Main" : ["LogFile", "LogLevel", "MountScript", "UmountScript", "InitScript", "GetDevicesScript", "Keyfile"]}
ft@0
    50
ft@6
    51
CONFIG_FILE="/etc/encryptionprovider/encryptionprovider.cfg"
ft@0
    52
CONFIG_NOT_READABLE = "Configfile is not readable"
ft@0
    53
CONFIG_WRONG = "Something is wrong with the config"
ft@0
    54
CONFIG_MISSING = "Section: \"%s\" Option: \"%s\" in configfile is missing"
ft@0
    55
ft@0
    56
def checkMinimumOptions (config):
ft@0
    57
    for section, options in MINOPTS.iteritems ():
ft@0
    58
        for option in options:
ft@0
    59
            if (config.has_option(section, option) == False):
ft@0
    60
                print (CONFIG_MISSING % (section, option))
ft@0
    61
                exit (129)
ft@0
    62
    
ft@0
    63
    
ft@0
    64
def loadConfig ():
ft@0
    65
    configfile = CONFIG_FILE
ft@0
    66
    config = ConfigParser.SafeConfigParser ()
ft@0
    67
ft@0
    68
    if ((os.path.exists (configfile) == False) or (os.path.isfile (configfile) == False) or (os.access (configfile, os.R_OK) == False)):
ft@0
    69
        print (CONFIG_NOT_READABLE)
ft@0
    70
        exit (1)
ft@0
    71
ft@0
    72
    try:
ft@0
    73
        config.read (CONFIG_FILE)
ft@0
    74
    except Exception, e:
ft@0
    75
        print (CONFIG_WRONG)
ft@0
    76
        print ("Error: %s" % (e))
ft@0
    77
        exit (1)
ft@0
    78
ft@0
    79
    checkMinimumOptions (config)
ft@0
    80
    return config
ft@0
    81
ft@0
    82
def initLog (config):
ft@0
    83
    global LOG
ft@0
    84
    logfile = config.get("Main", "LogFile")
ft@0
    85
    
ft@0
    86
    numeric_level = getattr(logging, config.get("Main", "LogLevel").upper(), None)
ft@0
    87
    if not isinstance(numeric_level, int):
ft@0
    88
        raise ValueError('Invalid log level: %s' % loglevel)
ft@0
    89
ft@0
    90
    # ToDo move log level and maybe other things to config file
ft@0
    91
    logging.basicConfig(
ft@0
    92
                        level = numeric_level,
ft@0
    93
                        format = "%(asctime)s %(name)-12s %(funcName)-15s %(levelname)-8s %(message)s",
ft@0
    94
                        datefmt = "%Y-%m-%d %H:%M:%S",
ft@0
    95
                        filename = logfile,
ft@0
    96
                        filemode = "a+",
ft@0
    97
    )
ft@17
    98
    LOG = logging.getLogger("encryptionprovicer")
ft@0
    99
    
ft@0
   100
    
ft@0
   101
    
ft@0
   102
    
ft@1
   103
def runExternalScripts (command):
ft@1
   104
    LOG.debug ("Run external Script: %s" %(command,))
ft@0
   105
    
ft@1
   106
    if (os.path.isfile (command[0]) == False):
ft@1
   107
        LOG.error ("File does not exist: %s" %((command[0]),))
ft@1
   108
        sys.stderr.write("File does not exist: %s\n" %((command[0]),))
ft@1
   109
        exit (1)
ft@0
   110
    
ft@1
   111
    process = subprocess.Popen( command, stdout=subprocess.PIPE, stderr=subprocess.PIPE )
ft@1
   112
    retcode = process.wait()
ft@1
   113
    ( stdout, stderr ) = process.communicate()
ft@0
   114
    
ft@1
   115
    return { "retcode" : retcode, "stdout" : stdout, "stderr" : stderr }
ft@1
   116
    
ft@1
   117
    
ft@1
   118
def getDevices (script):
ft@1
   119
    command = [script];
ft@1
   120
    result = runExternalScripts (command);
ft@1
   121
    
ft@1
   122
    if (result["retcode"] != 0):
ft@1
   123
        LOG.error ("Retcode: %s" %(result["retcode"],))
ft@1
   124
        LOG.error ("stdout: %s" %(result["stdout"],))
ft@1
   125
        LOG.error ("stderr: %s" %(result["stderr"],))
ft@1
   126
        sys.stderr.write("%s" %(result["stderr"],))
ft@1
   127
        exit (1)
ft@1
   128
    
ft@1
   129
    #print ("%s" %(result["stdout"],))
ft@1
   130
    # don't use print here, because of the extra newline
ft@1
   131
    sys.stdout.write ("%s" %(result["stdout"],))
ft@1
   132
ft@1
   133
ft@1
   134
def umountDevice (script, device):
ft@1
   135
    command = [script, device];
ft@1
   136
    result = runExternalScripts (command);
ft@1
   137
    
ft@1
   138
    if (result["retcode"] != 0):
ft@1
   139
        LOG.error ("Retcode: %s" %(result["retcode"],))
ft@1
   140
        LOG.error ("stdout: %s" %(result["stdout"],))
ft@1
   141
        LOG.error ("stderr: %s" %(result["stderr"],))
ft@1
   142
        sys.stderr.write("%s" %(result["stderr"],))
ft@1
   143
        exit (1)
ft@1
   144
        
ft@1
   145
    #print ("%s" %(result["stdout"],))
ft@1
   146
    # don't use print here, because of the extra newline
ft@1
   147
    sys.stdout.write ("%s" %(result["stdout"],))
ft@1
   148
    
ft@1
   149
ft@1
   150
def mountDevice (script, interface, port, device, mountpoint, keyfilepath):    
ft@1
   151
    listener = MyRestListener (opensecurity_urls, globals(), script = script, device = device, mountpoint = mountpoint, tries = 3, keyfilepath = keyfilepath)
ft@1
   152
    thread.start_new_thread(listener.run, (interface, port,))
ft@1
   153
    
ft@1
   154
    close = False
ft@1
   155
    while (close == False):
ft@1
   156
        time.sleep(1)
ft@1
   157
        if (os.path.ismount(mountpoint) == True):
ft@1
   158
            close = True
ft@1
   159
            LOG.info ("Stick \"%s\" was mounted sucessfully to \"%s\"" %(device, mountpoint,))
ft@1
   160
            sys.exit(0)
ft@1
   161
            
ft@1
   162
        if (os.path.exists(device) == False):
ft@1
   163
            close = True
ft@1
   164
            LOG.error ("Stick \"%s\" removed -> exit" %(device,))
ft@1
   165
            sys.exit(1)
ft@1
   166
ft@9
   167
def isDeviceMountedAtMountpoint (device, mountpoint):
ft@10
   168
    command = ("/bin/df %s | /usr/bin/tail -1 | awk '{print $1}'" %(mountpoint,))
ft@11
   169
    pipe = os.popen(command)
ft@12
   170
    result = pipe.read().rstrip()
ft@10
   171
    
ft@11
   172
    if (pipe.close() != None):
ft@11
   173
        LOG.error ("error: %s" %(result,))
ft@9
   174
        exit (1)
ft@9
   175
    
ft@11
   176
    if (result == device):
ft@12
   177
        LOG.debug ("Device: %s ### Result: %s ### Return: True" %(device, result,))
ft@9
   178
        return True
ft@9
   179
    else:
ft@12
   180
        LOG.debug ("Device: %s ### Result: %s ### Return: False" %(device, result,))
ft@9
   181
        return False
ft@9
   182
    
ft@9
   183
ft@17
   184
def initDevice (script, interface, port, device, mountpoint, keyfilepath, preinitscript, postinitscript):    
ft@17
   185
    listener = MyRestListener (opensecurity_urls, globals(), script = script, device = device, mountpoint = mountpoint, tries = 3, keyfilepath = keyfilepath, preinitscript = preinitscript, postinitscript = postinitscript)
ft@7
   186
    thread.start_new_thread(listener.run, (interface, port,))
ft@7
   187
    
ft@7
   188
    close = False
ft@7
   189
    while (close == False):
ft@7
   190
        time.sleep(1)
ft@7
   191
        if (os.path.exists(device) == False):
ft@7
   192
            close = True
ft@8
   193
            LOG.info ("Stick \"%s\" removed -> exit" %(device,))
ft@9
   194
            sys.exit(1)
ft@7
   195
ft@0
   196
if __name__ == "__main__":
ft@0
   197
    
ft@0
   198
    parser = argparse.ArgumentParser(epilog='--mount, --umount and --initialize are mutually exclusive')
ft@0
   199
    group = parser.add_mutually_exclusive_group(required=True)
ft@7
   200
    group.add_argument('-m', '--mount', action='store', nargs=4, dest='mount', help='Mounts an encrypted device.', metavar=("interface", "port", "device", "mountpoint"))
ft@7
   201
    group.add_argument('-u', '--umount', action='store', nargs=1, dest='umount', help='Unmounts an encrypted device', metavar="device")
ft@7
   202
    group.add_argument('-i', '--initialize', action='store', nargs=4, dest='initialize', help='Initialize an device.', metavar=("interface", "port", "device", "mountpoint"))
ft@1
   203
    group.add_argument('-g', '--getdevices', action='store_true', dest="getdevices", help='Returns a list of all mounted encrypted devices')
ft@0
   204
    arguments = parser.parse_args()
ft@0
   205
    
ft@0
   206
    
ft@0
   207
    config = loadConfig ()
ft@0
   208
    initLog (config)
ft@0
   209
    
ft@0
   210
    if (arguments.getdevices):
ft@1
   211
        getDevices (config.get ("Main", "GetDevicesScript"))
ft@0
   212
        
ft@0
   213
    if (arguments.umount):
ft@1
   214
        umountDevice (config.get ("Main", "UmountScript"), arguments.umount[0])
ft@0
   215
    
ft@0
   216
    if (arguments.mount):
ft@1
   217
        mountDevice (config.get ("Main", "MountScript"), arguments.mount[0], int(arguments.mount[1]), arguments.mount[2], arguments.mount[3], config.get ("Main", "Keyfile"))
ft@0
   218
    
ft@0
   219
    if (arguments.initialize):
ft@17
   220
        initDevice (config.get ("Main", "InitScript"), arguments.initialize[0], int(arguments.initialize[1]), arguments.initialize[2], arguments.initialize[3], config.get ("Main", "Keyfile"), config.get("Main", "PreInitScript"), config.get("Main", "PostInitScript"))