class SnifferProcess(Process):
    '''
    Takes the KillerBee instance which will be used for sniffing and receives
    packets, feeding each into the given pipe to the FilterProcess, until
    the stopevent fires.
    '''
    def __init__(self, pipe, kb, stopevent, drone, parent):
        super(SnifferProcess, self).__init__()
        self.pipe = pipe
        self.kb = kb
        self.stopevent = stopevent
        self.name = '{0}.Sniffer'.format(parent)
        self.logutil = KBLogUtil(drone, self.name)

    def run(self):
        '''
        Start receiving and returning packets until the stopevent
        flag is set.
        '''
        self.logutil.log('Initializing')
        self.logutil.log('Turning on interface: {0}'.format(self.kb.device))
        self.kb.sniffer_on()
        while not self.stopevent.is_set():
            recvpkt = self.kb.pnext()  #nonbocking
            # Check for empty packet (timeout) and valid FCS
            if recvpkt is not None:  # and recvpkt[1]:
                self.logutil.debug("Received Frame")
                self.pipe.send(recvpkt)
        self.logutil.log('Turning off interface: {0}'.format(self.kb.device))
        self.kb.sniffer_off()
        self.logutil.log('Terminating Execution')
class SnifferProcess(Process):
    """
    Takes the KillerBee instance which will be used for sniffing and receives
    packets, feeding each into the given pipe to the FilterProcess, until
    the stopevent fires.
    """

    def __init__(self, pipe, kb, stopevent, drone, parent):
        super(SnifferProcess, self).__init__()
        self.pipe = pipe
        self.kb = kb
        self.stopevent = stopevent
        self.name = "{0}.Sniffer".format(parent)
        self.logutil = KBLogUtil(drone, self.name)

    def run(self):
        """
        Start receiving and returning packets until the stopevent
        flag is set.
        """
        self.logutil.log("Initializing")
        self.logutil.log("Turning on interface: {0}".format(self.kb.device))
        self.kb.sniffer_on()
        while not self.stopevent.is_set():
            recvpkt = self.kb.pnext()  # nonbocking
            # Check for empty packet (timeout) and valid FCS
            if recvpkt is not None:  # and recvpkt[1]:
                self.logutil.debug("Received Frame")
                self.pipe.send(recvpkt)
        self.logutil.log("Turning off interface: {0}".format(self.kb.device))
        self.kb.sniffer_off()
        self.logutil.log("Terminating Execution")
 def __init__(self, pipe, kb, stopevent, drone, parent):
     super(SnifferProcess, self).__init__()
     self.pipe = pipe
     self.kb = kb
     self.stopevent = stopevent
     self.name = '{0}.Sniffer'.format(parent)
     self.logutil = KBLogUtil(drone, self.name)
Esempio n. 4
0
 def __init__(self, name, port):
     signal.signal(signal.SIGINT, self.SIGINT)
     self.port = port
     self.name = name
     self.logutil = KBLogUtil(self.name, 'Daemon', os.getpid())
     self.interfaces = {}
     self.plugins = {}
     self.pid = os.getpid()
Esempio n. 5
0
class BaseDronePlugin(object):
    def __init__(self, interfaces, channel, drone, name):
        #TODO: add interface validation

        self.interfaces = interfaces
        self.name = name
        self.kb = None
        self.channel = channel
        self.drone = drone
        self.childprocesses = []
        self.tasks = {}
        self.done_event = Event()
        self.task_update_event = Event()
        self.timeout = 5
        self.status = True
        self.active = True
        self.desc = None
        self.pid = os.getpid()
        self.logutil = KBLogUtil(self.drone, '{0}.Main'.format(self.name))

    def info(self):
        info = {}
        info['name'] = self.name
        info['pid'] = self.pid
        info['status'] = self.status
        info['active'] = self.active
        info['processes'] = list(({'desc':process.desc, 'pid':process.pid} for process in self.childprocesses))
        info['tasks'] = list(({'uuid': task[0], 'parameters':task[1] } for task in self.tasks.items()))
        return info

    def shutdown(self):
        self.logutil.log('Initiating shutdown')
        self.done_event.set()
        for process in self.childprocesses:
            if process.is_alive():
                process.join(self.timeout)
                if process.is_alive():
                    process.terminate()
                    time.sleep(self.timeout)
                    if process.is_alive():
                        raise Exception("Failed to terminate process")
        self.active = False
        #self.kb.plugin = None
        self.kb.active = False
        self.logutil.log('Successful shutdown')

    def task(self, uuid, data):
        '''
        overwrite this function
        '''
        pass

    def detask(self, uuid):
        '''
        overwrite this function
        '''
        pass
Esempio n. 6
0
    def __init__(self, config):
        Process.__init__(self)
        self.name = 'RuleEngine'
        self.config = config
        self.database = DatabaseHandler(self.config.name)
        self.logutil = KBLogUtil(self.config.name, self.name)
        self.wids = WIDSClient(self.config.server_ip, self.config.server_port)
        self.active = None
        self.rules = []

        #///dev///
        self.rules.append(rule1)
    def __init__(self, pipe, task_queue, stopevent, task_update_event, drone,
                 parent):
        super(FilterProcess, self).__init__()
        self.pipe = pipe
        self.task_queue = task_queue
        self.stopevent = stopevent
        self.taskevent = task_update_event

        self.drone = drone
        self.parent = parent
        self.name = '{0}.Filter'.format(self.parent)
        self.logutil = KBLogUtil(self.drone, self.name, None)
        self.callbacks = 0
Esempio n. 8
0
 def __init__(self, settings, config, shutdown_event, name):
     Process.__init__(self)
     self.name = name
     self.settings = settings
     self.config = config
     self.shutdown_event = shutdown_event
     self.database = DatabaseHandler(self.config.name)
     self.logutil = KBLogUtil(self.config.name, self.name, None)
     self.wids_api = WIDSClient(self.config.server_ip,
                                self.config.server_port)
     self.tasks = {}
     self.active = False
     self.running = False
Esempio n. 9
0
 def __init__(self, parameters=None, config=None):
     signal.signal(signal.SIGINT, self.SIGINT)
     self.config = WIDSConfig(parameters, config)
     self.config.daemon_pid = os.getpid()
     self.logutil = KBLogUtil(self.config.name, 'Daemon')
     self.database = DatabaseHandler(self.config.name)
     self.engine = None
     self.module_store = {}
     self.module_counter = 0
     self.task_store = {}
     self.task_counter = 0
     self.drone_store = {}
     self.drone_counter = 0
 def __init__(self, pipe, kb, stopevent, drone, parent):
     super(SnifferProcess, self).__init__()
     self.pipe = pipe
     self.kb = kb
     self.stopevent = stopevent
     self.name = "{0}.Sniffer".format(parent)
     self.logutil = KBLogUtil(drone, self.name)
Esempio n. 11
0
    def __init__(self, interfaces, channel, drone, name):
        #TODO: add interface validation

        self.interfaces = interfaces
        self.name = name
        self.kb = None
        self.channel = channel
        self.drone = drone
        self.childprocesses = []
        self.tasks = {}
        self.done_event = Event()
        self.task_update_event = Event()
        self.timeout = 5
        self.status = True
        self.active = True
        self.desc = None
        self.pid = os.getpid()
        self.logutil = KBLogUtil(self.drone, '{0}.Main'.format(self.name))
Esempio n. 12
0
 def __init__(self, settings, config, shutdown_event, name):
     Process.__init__(self)
     self.name = name
     self.settings = settings
     self.config = config
     self.shutdown_event = shutdown_event
     self.database = DatabaseHandler(self.config.name)
     self.logutil = KBLogUtil(self.config.name, self.name, None)
     self.wids_api = WIDSClient(self.config.server_ip, self.config.server_port)
     self.tasks = {}
     self.active = False
     self.running = False
    def __init__(self, pipe, task_queue, stopevent, task_update_event, drone, parent):
        super(FilterProcess, self).__init__()
        self.pipe = pipe
        self.task_queue = task_queue
        self.stopevent = stopevent
        self.taskevent = task_update_event

        self.drone = drone
        self.parent = parent
        self.name = '{0}.Filter'.format(self.parent)
        self.logutil = KBLogUtil(self.drone, self.name, None)
        self.callbacks = 0
Esempio n. 14
0
    def __init__(self, config):
        Process.__init__(self)
        self.name = 'RuleEngine'
        self.config = config
        self.database = DatabaseHandler(self.config.name)
        self.logutil = KBLogUtil(self.config.name, self.name)
        self.wids = WIDSClient(self.config.server_ip, self.config.server_port)
        self.active = None
        self.rules = []

        #///dev///
        self.rules.append(rule1)
Esempio n. 15
0
 def __init__(self, parameters=None, config=None):
     signal.signal(signal.SIGINT, self.SIGINT)
     self.config = WIDSConfig(parameters, config)
     self.config.daemon_pid = os.getpid()
     self.logutil = KBLogUtil(self.config.name, 'Daemon')
     self.database = DatabaseHandler(self.config.name)
     self.engine = None
     self.module_store = {}
     self.module_counter = 0
     self.task_store = {}
     self.task_counter = 0
     self.drone_store = {}
     self.drone_counter = 0
Esempio n. 16
0
class RuleEngine(Process):
    def __init__(self, config):
        Process.__init__(self)
        self.name = 'RuleEngine'
        self.config = config
        self.database = DatabaseHandler(self.config.name)
        self.logutil = KBLogUtil(self.config.name, self.name)
        self.wids = WIDSClient(self.config.server_ip, self.config.server_port)
        self.active = None
        self.rules = []

        #///dev///
        self.rules.append(rule1)
        #////////

    def run(self):
        self.logutil.log('Starting Execution')
        self.active = True
        self.start_time = dateToMicro(datetime.utcnow())

        while self.active:

            if DEV_DEBUG:
                self.logutil.debug('Checking for new rules')
                time.sleep(3)

            # check server for new rules: 'GET /rules/updatecheck', if so load new rules
            '''
            if self.wids.checkNewRules():
                new_rules = self.wids.getNewRules()
            '''

            # evaluate each rule serially
            self.logutil.debug('Evaluating rules')
            for RuleObject in self.rules:
                self.evaluateRule(RuleObject)

        self.logutil.log('Terminating Execution')

    # TODO - replace the internal database with a REST call to query database for events
    def evaluateRule(self, RuleObject):
        try:
            self.logutil.dev('Evaluating Rule: {0} (EventIndex: {1})'.format(
                RuleObject.name, RuleObject.event_index))
            for condition in RuleObject.conditions:
                module = condition[0]
                event = condition[1]
                count = condition[2]

                # TODO - replace this direct database query with REST call ????
                query = self.database.session.query(Event).filter(
                    Event.module == module).filter(Event.name == event).filter(
                        Event.datetime > self.start_time).filter(
                            Event.id > RuleObject.event_index)

                results_count = query.limit(count).count()
                self.logutil.dev(
                    'Event: {0} - Found: {1} (Events Needed: {2})'.format(
                        event, results_count, count))
                if not results_count >= count:
                    return False
                last_result = query.order_by(
                    Event.id.desc()).limit(count).first()
                RuleObject.event_index = last_result.id
                self.logutil.log('>>> Rule Conditions Met ({0})'.format(
                    RuleObject.name))
                for action in RuleObject.actions:
                    actionType = action[0]
                    actionParams = action[1]
                    if actionType == 'GenerateAlert':
                        self.action_GenerateAlert(RuleObject.name,
                                                  actionParams)
                    if actionType == 'GenerateLog':
                        self.action_GenerateLog(RuleObject.name, actionParams)
        except Exception:
            traceback.print_exc()

    def action_GenerateLog(self, rule_name, action_parameters):
        self.logutil.log(
            'Execution GenerateLog Action for Rule {0}'.format(rule_name))
        pass

    def action_GenerateAlert(self, rule_name, action_parameters):
        self.logutil.log(
            'Executing GenerateAlert Action for Rule {0}'.format(rule_name))
        self.wids.generateAlert(rule_name)

    def shutdown(self):
        self.active = False
        self.terminate()
Esempio n. 17
0
class WIDSDaemon:

    def __init__(self, parameters=None, config=None):
        signal.signal(signal.SIGINT, self.SIGINT)
        self.config = WIDSConfig(parameters, config)
        self.config.daemon_pid = os.getpid()
        self.logutil = KBLogUtil(self.config.name, 'Daemon')
        self.database = DatabaseHandler(self.config.name)
        self.engine = None
        self.module_store = {}
        self.module_counter = 0
        self.task_store = {}
        self.task_counter = 0
        self.drone_store = {}
        self.drone_counter = 0

    def SIGINT(self, s, f):
        if self.config.daemon_pid == os.getpid():
            self.logutil.log('SIGINT')
            self.stopDaemon()

    def startDaemon(self):
        self.logutil.writePID()
        self.logutil.startlog()
        self.logutil.log('Starting Daemon')
        self.loadDrones()
        self.loadModules()
        self.startServer()

    def stopDaemon(self):
        self.logutil.log('Initiating Shutdown')
        self.unloadModules()
        self.unloadDrones()
        self.logutil.log('Successfull Shutdown')
        self.logutil.cleanup()
        sys.exit()

    def loadDrones(self):
        count = len(self.config.drones)
        self.logutil.log('Loading Drones (Found {0} Drones in the Config)'.format(count))
        for droneConfig in self.config.drones:
            self.loadDrone(droneConfig)

    def loadDrone(self, droneConfigDict):
        try:
            print(droneConfigDict)
            drone_ip = str(droneConfigDict.get('ip', None))
            drone_port = str(droneConfigDict.get('port', None))
            if drone_ip == None or drone_port == None:
                error = 'Error: Missing Parameter: "address"'
                self.logutil.log(error)
                return self.formatResponse(error, None)
            else:
                droneIndex = self.drone_counter
                droneObject = DroneContainer(droneIndex, drone_ip, drone_port)
                self.drone_store[droneIndex] = droneObject
                self.drone_counter += 1
                self.logutil.log('Loading Drone {0} - {1}:{2}'.format(droneIndex, drone_ip, drone_port))
                return self.formatResponse(None, None)
        except:
            self.handleException()

    def unloadDrones(self):
        self.logutil.log('Unloading Drones')
        self.logutil.log('Found {0} Active Drones'.format(len(self.drone_store)))
        for i in range(len(self.drone_store)):
            self.unloadDrone(i)

    def unloadDrone(self, droneIndexInt):
        try:
            droneObject = self.drone_store.get(droneIndexInt, None)
            if droneObject == None:
                error = 'Error: Drone with Index {0} does not exist'.format(droneIndexInt)
                self.logutil.log(error)
                return self.formatResponse(False, error)
            else:
                droneObject.release()
                self.logutil.log('Releasing Drone {0} - {1}:{2}'.format(droneIndexInt, droneObject.address, droneObject.port))
                del(self.drone_store[droneIndexInt])
                del(droneObject)
                return self.formatResponse(True, None)
        except:
            self.handleException()


    def taskDrone(self, taskConfigDict):
        try:
            droneIndexList = taskConfigDict.get('droneIndexList')
            for droneIndexInt in droneIndexList:
                droneObject = self.drone_store.get(droneIndexInt, None)
                task_uuid = taskConfigDict.get('uuid', None)
                task_plugin = taskConfigDict.get('plugin', None)
                task_channel = taskConfigDict.get('channel', None)
                task_parameters = taskConfigDict.get('parameters', None)
                module_index = taskConfigDict.get('module_index', None)
                if droneObject == None:
                    error = ec.ERROR_DRONE_InvalidDroneIndex
                    data = droneIndexInt
                    return (error,data)
                if task_uuid == None:
                    error = ec.ERROR_DRONE_MissingDroneTaskParameter
                    data = 'uuid'
                    return (error, data)
                if task_channel == None:
                    error = ec.ERROR_DRONE_MissingDroneTaskParameter
                    data = 'channel'
                    return (error, data)
                if task_plugin == None:
                    error = ec.ERROR_MissingDroneTaskParameter
                    data = 'plugin'
                    return (error, data)
                if task_parameters == None:
                    error = ec.ERROR_MissingDroneTaskParameter
                    data = 'parameters'
                    return (error, data)
                (data,error) = droneObject.api.task(task_plugin, task_channel, task_uuid, task_parameters) 
                if error == None:
                    self.task_store[self.task_counter] = TaskContainer(self.task_counter, task_uuid, task_plugin, task_channel, task_parameters, droneIndexList, module_index)
                    self.task_counter += 1
                return (data,error)
        except:
            self.handleException()


    def detaskDrone(self, droneIndexList, task_uuid):
        try:
            for int_DroneIndex in droneIndexList:
                droneObject = self.drone_store.get(int_DroneIndex, None)
                droneObject.api.detask(task_uuid)
        except Exception:
            self.handleException()


    def loadModules(self):
        count = len(self.config.modules)
        self.logutil.log('Loading Modules (Found {0} Modules in the Config)'.format(count))
        for moduleConfigDict in self.config.modules:
            self.loadModule(moduleConfigDict)
        pass

    def unloadModules(self):
        self.logutil.log('Unloading Modules')
        self.logutil.log('Found {0} Active Modules'.format(len(self.module_store)))
        for i in range(len(self.module_store)):
            self.unloadModule(i)

    def loadModuleClass(self, module):
        if module == 'BeaconRequestMonitor'       : return BeaconRequestMonitor
        if module == 'DisassociationStormMonitor' : return DisassociationStormMonitor
        if module == 'DosAesCtrMonitor'           : return DosAesCtrMonitor

    def loadModule(self, moduleConfigDict):
        self.logutil.debug('Loading Module: {0}'.format(moduleConfigDict))
        try:
            moduleName = moduleConfigDict.get('name', None)
            moduleSettings = moduleConfigDict.get('settings', None)
            moduleClass = self.loadModuleClass(moduleName)
            if moduleName == None:
                error = ec.ERROR_WIDS_MissingModuleParameter
                data = 'name'
                self.logutil.log('Failed to Load Module - Missing Parameter: "name" in {0}\n'.format(moduleConfigDict))
                return self.formatResponse(error,data)
            elif moduleSettings == None:
                error = ec.ERROR_WIDS_MissingModuleParameter
                data = 'settings'
                self.logutil.log('Failed to Load Module - Missing Parameter: "settings" in {0}\n'.format(moduleConfigDict))
                return self.formatResponse(error,data)
            elif moduleClass == None:
                error = ec.ERROR_WIDS_MissingModuleClass
                data = moduleName
                self.logutil.log('Failed to Load Module - Could not load class: {0}'.format(moduleName))
                return self.formatResponse(error,data)
            else:
                moduleIndex = self.module_counter
                moduleShutdownEvent = Event()
                moduleSettings['module_index'] = moduleIndex
                self.logutil.debug('Found module class: {0}'.format(moduleClass))
                '''
                (error,data) = moduleClass.validate_settings(moduleSettings) 
                if not error == None:
                    return self.formatResponse(error,data)
                '''
                moduleProcess = moduleClass(moduleSettings, self.config, moduleShutdownEvent)
                moduleProcess.start()
                moduleObject = ModuleContainer(moduleIndex, moduleName, moduleSettings, moduleProcess, moduleShutdownEvent)
                self.module_store[moduleIndex] = moduleObject
                self.module_counter += 1
                self.logutil.log('Loading Module {0} - {1}'.format(moduleIndex, moduleObject.name))
                return self.formatResponse(None, None)
        except:
            self.handleException()


    def unloadModule(self, moduleIndexInt):
        try:
            moduleObject = self.module_store.get(moduleIndexInt, None)
            if moduleObject == None:
                error = 'Error: Module with Index {0} does not exist'.format(moduleIndexInt)
                self.logutil.log(error)
                return self.formatResponse(False, error)
            else:
                self.logutil.log('Unloading Module {0} ({1} - {2})'.format(moduleIndexInt, moduleObject.name, moduleObject.process.pid))
                self.logutil.log('Detasking Module Tasks')
                for taskObject in self.task_store.values():
                    if taskObject.module_index == moduleObject.index:
                        drones = taskObject.drones
                        uuid = taskObject.uuid
                        self.logutil.log('Removing Task {0} from Drones {1}'.format(uuid, drones))
                        self.detaskDrone(drones, uuid)
                moduleObject.process.terminate()
                moduleObject.process.join()
                del(self.module_store[moduleIndexInt])
                del(moduleObject)
                return self.formatResponse(True, None)
        except:
            self.handleException()


    def startServer(self):
        self.logutil.log('Starting Server on port {0}'.format(self.config.server_port))
        app = flask.Flask(__name__)
        app.add_url_rule('/active',             None, self.processActiveGetRequest,         methods=['GET'] )
        app.add_url_rule('/status',             None, self.processStatusGetRequest,         methods=['GET'] )
        app.add_url_rule('/data/upload',        None, self.processDataUploadRequest,        methods=['POST'])
        app.add_url_rule('/data/download',      None, self.processDataDownloadRequest,      methods=['POST'])
        app.add_url_rule('/drone/task',         None, self.processDroneTaskRequest,         methods=['POST'])
        app.add_url_rule('/drone/detask',       None, self.processDroneDetaskRequest,       methods=['POST'])
        app.add_url_rule('/drone/add',          None, self.processDroneAddRequest,          methods=['POST'])
        app.add_url_rule('/drone/delete',       None, self.processDroneDeleteRequest,       methods=['POST'])
        app.add_url_rule('/alerts',             None, self.processAlertGetRequest,          methods=['POST'])
        app.add_url_rule('/alerts/generate',    None, self.processAlertGenerateRequest,     methods=['POST'])
        app.add_url_rule('/module/load',        None, self.processModuleLoadRequest,        methods=['POST'])
        app.add_url_rule('/module/unload',      None, self.processModuleUnloadRequest,      methods=['POST'])
        app.run(threaded=True, port=int(self.config.server_port))

    def handleException(self):
        etb = traceback.format_exc()
        self.logutil.trace(etb)
        return self.formatResponse(error=ec.ERROR_GENERAL_UnknownException, data=str(etb))

    def formatResponse(self, error, data):
        return json.dumps({'error':error, 'data':data})

    def processActiveGetRequest(self):
        self.logutil.debug('Processing Active Get Request')
        return self.formatResponse(error=None, data=True)

    def processDataUploadRequest(self):
        self.logutil.debug('Processing Data Upload Request')
        try:
            data = json.loads(flask.request.data)
            packetdata = data.get('pkt')
            self.database.storePacket(packetdata)
            return self.formatResponse(error=None, data=None)
        except Exception:
            return self.handleException()

    def processDataDownloadRequest(self):
        self.logutil.debug('Processing Data Upload Request')
        try:
            return self.formatResponse(error=None, data=None)
        except Exception:
            return self.handleException()

    def processDroneTaskRequest(self):
        self.logutil.debug('Processing Drone Task Request')
        try:
            request_data = json.loads(flask.request.data)
            (error,data) = self.taskDrone(request_data)
            return self.formatResponse(error,data)
        except Exception:
            return self.handleException()

    def processDroneDetaskRequest(self):
        self.logutil.debug('Processing Drone Detask Request')
        try:
            data = json.loads(flask.request.data)
            return self.detaskDrone(data)
        except Exception:
            return self.handleException()

    def processDroneAddRequest(self):
        self.logutil.debug('Processing Drone Add Request')
        try:
            data = json.loads(flask.request.data)
            return self.loadDrone(data)
        except Exception:
            return self.handleException()

    def processDroneDeleteRequest(self):
        self.logutil.debug('Processing Drone Delete Request')
        try:
            data = json.loads(flask.request.data)
            drone_index = int(data.get('drone_index'))
            return self.unloadDrone(drone_index)
        except:
            return self.handleException()

    def processModuleLoadRequest(self):
        self.logutil.debug('Processing Module Load Request')
        try:
            data = json.loads(flask.request.data)
            return self.loadModule(data)
        except:
            return self.handleException()

    def processModuleUnloadRequest(self):
        self.logutil.debug('Processing Module Unload Request')
        try:
            data = json.loads(flask.request.data)
            module_index = int(data.get('module_index'))
            return self.unloadModule(module_index)
        except:
            return self.handleException()

    def processAlertGenerateRequest(self):
        self.logutil.debug('Processing Alert Generate Request')
        try:
            data = json.loads(flask.request.data)
            alert_name = str(data.get('alert_name'))
            self.database.storeAlert(alert_name)
            return self.formatResponse(True, None) 
        except:
            return self.handleException()
        
    def processAlertGetRequest(self):
        #self.logutil.debug('Processing Alert Request')
        try:
            alerts = []
            for alert in self.database.session.query(Alert).all():
                alerts.append('{0} - {1}'.format(microToDate(alert.datetime), alert.name))
            return self.formatResponse(None, alerts)
        except:
            return self.handleException()

    def processStatusGetRequest(self):
        self.logutil.log('Processing Status Request')
        try:
            config = self.config.json()
            modules = list((module.json() for module in self.module_store.values()))
            tasks = list((task.json() for task in self.task_store.values()))
            rules = list((rule.json() for rule in self.rule_store.values()))
            drones = list((drone.json() for drone in self.drone_store.values()))
            status = {'config':config, 'modules':modules, 'tasks':tasks, 'drones':drones, 'rules':rules}
            return json.dumps({'success':True, 'data':status})
        except:
            return self.handleException()
Esempio n. 18
0
class AnalyticModule(Process):
    def __init__(self, settings, config, shutdown_event, name):
        Process.__init__(self)
        self.name = name
        self.settings = settings
        self.config = config
        self.shutdown_event = shutdown_event
        self.database = DatabaseHandler(self.config.name)
        self.logutil = KBLogUtil(self.config.name, self.name, None)
        self.wids_api = WIDSClient(self.config.server_ip,
                                   self.config.server_port)
        self.tasks = {}
        self.active = False
        self.running = False

    def SIGTERM(self, a, b):
        self.logutil.log('SIGTERM')
        self.shutdown()

    def moduleIndex(self):
        return self.settings.get('module_index')

    def waitForWIDS(self):
        while not self.wids_api.isActive():
            sleep(0.1)

    def taskDrone(self, droneIndexList, task_plugin, task_channel,
                  task_parameters, module_index):
        try:
            task_uuid = str((uuid4()))
            (error, data) = self.wids_api.taskDrone(droneIndexList, task_uuid,
                                                    task_plugin, task_channel,
                                                    task_parameters,
                                                    module_index)
            if error == None:
                self.tasks[task_uuid] = {
                    'plugin': task_plugin,
                    'channel': task_channel,
                    'parameters': task_parameters,
                    'drones': droneIndexList,
                    'uuid': task_uuid,
                    'module_index': module_index
                }
                return task_uuid
            else:
                return False
        except Exception:
            etb = traceback.format_exc()
            self.logutil.trace(etb)
            return False

    def detaskDrone(self, droneIndexList, uuid):
        self.logutil.log('Detasking UUID: {0} from Drones: {1}'.format(
            uuid, droneIndexList))
        try:
            self.wids_api.detaskDrone(droneIndexList, uuid)
        except Exception:
            etb = traceback.format_exc()
            self.logutil.trace(etb)

    def detaskAll(self):
        self.logutil.log('Detasking all active tasks ({0} found)'.format(
            len(self.tasks.values())))
        for task in self.tasks.values():
            uuid = task.get('uuid')
            droneIndexList = task.get('drones')
            self.detaskDrone(droneIndexList, uuid)

    def getPackets(self,
                   valueFilterList=[],
                   uuidFilterList=[],
                   new=False,
                   maxcount=0,
                   count=False):
        return self.database.getPackets(valueFilterList, uuidFilterList, new,
                                        maxcount, count)

    def getEvents(self,
                  valueFilterList=[],
                  new=False,
                  maxcount=0,
                  count=False):
        return self.database.getPackets(valueFilterList, new, maxcount, count)

    def registerEvent(self,
                      name,
                      details={},
                      related_packets=[],
                      related_uuids=[]):
        event_data = {
            'module': self.name,
            'name': name,
            'details': details,
            'related_packets': related_packets,
            'related_uuids': related_uuids,
            'datetime': dateToMicro(datetime.utcnow())
        }
        return self.database.storeEvent(event_data)

    def generateAlert(self, alert_name):
        return self.database.storeAlert(alert_name)

    def cleanup(self):
        '''
        This should be overridden by modules which need to do housekeeping 
        before shutdown.
        '''
        pass

    def shutdown(self, detask=True):
        self.logutil.log('Received Shutdown Request')
        self.cleanup()
        self.logutil.log('Module Shutdown Complete')
        sys.exit()
Esempio n. 19
0
class DroneDaemon:

    def __init__(self, name, port):
        signal.signal(signal.SIGINT, self.SIGINT)
        self.port = port
        self.name = name
        self.logutil = KBLogUtil(self.name, 'Daemon', os.getpid())
        self.interfaces = {}
        self.plugins = {}
        self.pid = os.getpid()

    def SIGINT(self, s, f):
        #TODO find a cleaner way to do only handle signals from the parent process ?
        if self.pid == os.getpid():
            self.logutil.log("SIGINT")
            signal.signal(signal.SIGINT, signal.SIG_IGN)
            self.shutdown = True
            self.shutdownDaemon()

    def handleException(self):
        etb = traceback.format_exc()
        print(etb)
        self.logutil.trace(etb)
        return json.dumps({'success':False, 'data':str(etb)})


    def runChecks(self):
        try:
            s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            s.bind(('', self.port))
            s.close()
        except socket.error:
            print("Error Starting Drone:")
            print("Socket TCP {0} already bound".format(self.port))
            sys.exit()

    def startDaemon(self):
        self.runChecks()
        self.logutil.writePID()
        self.logutil.startlog()
        self.logutil.log("Starting DroneDaemon")
        self.enumerateInterfaces()
        self.startRestServer()

    def shutdownDaemon(self):
        self.logutil.log('Initiating shutdown')
        self.stopRunningPlugins()
        self.logutil.log('Completed shutdown')
        self.logutil.cleanup()
        # TODO: verify that all subprocess have been terminated
        sys.exit()

    def startRestServer(self):
        self.logutil.log('Starting REST Server on port {0}'.format(self.port))
        app = flask.Flask(__name__)
        app.add_url_rule('/task',       None, self.processTaskRequest,          methods=['POST'])
        app.add_url_rule('/detask',     None, self.processDetaskRequest,        methods=['POST'])
        app.add_url_rule('/status',     None, self.processStatusGetRequest,     methods=['POST'])
        app.run(port=self.port, threaded=True)

    def handleUnknownException(self):
        etb = traceback.format_exc()
        self.logutil.trace(etb)
        return self.formatResult(error=ec.ERROR_UnknownException, data=str(etb))

    def formatResponse(self, error, data):
        return json.dumps({'error':error, 'data':data})

    def processTaskRequest(self):
        self.logutil.log('Processing Task Request')
        try:
            data = json.loads(flask.request.data)
            uuid = data.get('uuid')
            plugin = data.get('plugin')
            channel = data.get('channel')
            parameters = data.get('parameters')
            self.logutil.log('Processing Task Request: {0} ({1})'.format(uuid, plugin))
            (error,data) = self.taskPlugin(plugin, channel, uuid, parameters)
            return self.formatResponse(error,data)
        except Exception:
            return self.handleUnknownException()

    def processDetaskRequest(self):
        self.logutil.log('Processing Detask Request')
        try:
            data = json.loads(flask.request.data)
            uuid = data.get('uuid')
            (error,data) =  self.detaskPlugin(uuid)
            return self.formatResponse(error,None)
        except Exception:
            return self.handleUnknownException()

    def processStatusGetRequest(self):
        self.logutil.log('Processing Status Get Request')
        try:
            status = {}
            status['config'] = {}
            status['config']['pid'] = self.pid
            status['config']['name'] = self.name
            status['interfaces'] = list((interface.info() for interface in self.interfaces.values()))
            status['plugins'] = list((plugin.info() for plugin in self.plugins.values()))
            return self.formatResponse(None, status)
        except Exception:
            self.handleUnknownException()

    def loadPluginClass(self, plugin):
        if plugin == 'CapturePlugin':
            return CapturePlugin

    def taskPlugin(self, plugin, channel, uuid, parameters):
        self.logutil.debug('Tasking Plugin ({0},{1})'.format(plugin,channel))
        pluginObject = self.plugins.get((plugin,channel), None)
        if pluginObject == None:
            self.logutil.log('No Instance of ({0},{1}) Found - Starting New one'.format(plugin, channel))
            (error,data) = self.startPlugin(plugin,channel)
            if error == None:
                pluginObject = data
            else:
                return (error,data)
        try:
            self.logutil.log('Tasking Plugin: ({0}, ch.{1}) with Task {2}'.format(plugin, channel, uuid))
            success = pluginObject.task(uuid, parameters)
            if success == False:
                error = ec.ERROR_DRONE_UnknownTaskingFailure
            else:
                error = None
            return (error,None)
        except Exception:
            self.handleException()

    def startPlugin(self, plugin, channel):
        self.logutil.debug('Starting Plugin ({0},{1})'.format(plugin,channel))
        try:
            interface = self.getAvailableInterface()
            if interface == None:
                self.logutil.log('Failed to Start Plugin - No Avilable Interfaces')
                error = ec.ERROR_DRONE_UnavailableInterface
                return (error, None)
            pluginClass = self.loadPluginClass(plugin)
            if pluginClass == None:
                self.logutil.log('Failed to Start Plugin - Plugin Module: {0} does not exist'.format(plugin))
                error = ec.ERROR_DroneFailedToLoadPlugin
                return (error,plugin)
            self.logutil.log('Acquired Interface: {0}'.format(interface.device))
            self.logutil.log('Loaded Plugin Class: {0}'.format(pluginClass))
            pluginObject = pluginClass([interface], channel, self.name)
            self.plugins[(plugin,channel)] = pluginObject
            self.logutil.log('Successfully Started Plugin')
            time.sleep(0.5)
            error = None
            data = pluginObject
            return (error,data)
        except Exception:
            self.handleException()

    def detaskPlugin(self, uuid):
        self.logutil.log('Processing Detask Request for {0}'.format(uuid))
        try:
            for pluginKey,pluginObject in self.plugins.items():
                for task_uuid in pluginObject.tasks.keys():
                    if task_uuid == uuid:
                        detask_success = pluginObject.detask(uuid)
                        if detask_success == False:
                            error = ec.ERROR_DroneUnknownDetaskingFailure
                            return (error,None)
                        time.sleep(2)
                        if pluginObject.active == False:
                            del(self.plugins[pluginKey])
                        self.logutil.log('Succesfully detasked {0} from {1}'.format(uuid, str(pluginObject.desc)))
                        return (None,None)
        except Exception:
            return self.handleException()

    def stopRunningPlugins(self):
        self.logutil.log('Stopping Running Plugins')
        for plugin in self.plugins.values():
            if plugin.active == True:
                self.logutil.log("Stopping Plugin: {0}".format(plugin.desc))
                plugin.shutdown()
                if plugin.active:
                    print("had a problem shutting down plugin")
        self.logutil.log('Running plugins have been terminated')

    def getAvailableInterface(self):
        for interface in self.interfaces.values():
            if not interface.active:
                return interface
        return None

    def enumerateInterfaces(self):
        self.logutil.log("Enumerating Interfaces")
        try:
            for interface in kbutils.devlist():
                device = interface[0]
                description = interface[1]
                self.logutil.log("Added new interface: {0}".format(device))
                self.interfaces[device] = KBInterface(device)
        except Exception:
            self.handleUnknownException()
Esempio n. 20
0
class AnalyticModule(Process):

    def __init__(self, settings, config, shutdown_event, name):
        Process.__init__(self)
        self.name = name
        self.settings = settings
        self.config = config
        self.shutdown_event = shutdown_event
        self.database = DatabaseHandler(self.config.name)
        self.logutil = KBLogUtil(self.config.name, self.name, None)
        self.wids_api = WIDSClient(self.config.server_ip, self.config.server_port)
        self.tasks = {}
        self.active = False
        self.running = False

    def SIGTERM(self,a,b):
        self.logutil.log('SIGTERM')
        self.shutdown()

    def moduleIndex(self):
        return self.settings.get('module_index')

    def waitForWIDS(self):
        while not self.wids_api.isActive():
            sleep(0.1)

    def taskDrone(self, droneIndexList, task_plugin, task_channel, task_parameters, module_index):
        try:
            task_uuid = str((uuid4()))
            (error,data) = self.wids_api.taskDrone(droneIndexList, task_uuid, task_plugin, task_channel, task_parameters, module_index)
            if error == None:
                self.tasks[task_uuid] = {'plugin':task_plugin, 'channel':task_channel, 'parameters':task_parameters, 'drones':droneIndexList, 'uuid':task_uuid, 'module_index':module_index}
                return task_uuid 
            else:
                return False
        except Exception:
            etb = traceback.format_exc()
            self.logutil.trace(etb)
            return False

    def detaskDrone(self, droneIndexList, uuid):
        self.logutil.log('Detasking UUID: {0} from Drones: {1}'.format(uuid,droneIndexList))
        try:
            self.wids_api.detaskDrone(droneIndexList, uuid)
        except Exception:
            etb = traceback.format_exc()
            self.logutil.trace(etb)

    def detaskAll(self):
        self.logutil.log('Detasking all active tasks ({0} found)'.format(len(self.tasks.values())))
        for task in self.tasks.values():
            uuid = task.get('uuid')
            droneIndexList = task.get('drones')
            self.detaskDrone(droneIndexList, uuid)

    def getPackets(self, valueFilterList=[], uuidFilterList=[], new=False, maxcount=0, count=False):
        return self.database.getPackets(valueFilterList, uuidFilterList, new, maxcount, count)

    def getEvents(self, valueFilterList=[], new=False, maxcount=0, count=False):
        return self.database.getPackets(valueFilterList, new, maxcount, count)

    def registerEvent(self, name, details={}, related_packets=[], related_uuids=[]):
        event_data = {'module':self.name, 'name':name, 'details':details, 'related_packets':related_packets, 'related_uuids':related_uuids, 'datetime':dateToMicro(datetime.utcnow())}
        return self.database.storeEvent(event_data)

    def generateAlert(self, alert_name):
        return self.database.storeAlert(alert_name)

    def cleanup(self):
        '''
        This should be overridden by modules which need to do housekeeping 
        before shutdown.
        '''
        pass

    def shutdown(self, detask=True):
        self.logutil.log('Received Shutdown Request')
        self.cleanup()
        self.logutil.log('Module Shutdown Complete')
        sys.exit()
class FilterProcess(Process):
    def __init__(self, pipe, task_queue, stopevent, task_update_event, drone, parent):
        super(FilterProcess, self).__init__()
        self.pipe = pipe
        self.task_queue = task_queue
        self.stopevent = stopevent
        self.taskevent = task_update_event

        self.drone = drone
        self.parent = parent
        self.name = '{0}.Filter'.format(self.parent)
        self.logutil = KBLogUtil(self.drone, self.name, None)
        self.callbacks = 0

    def do_callback(self, uuid, cburl, pkt):
        pkt['uuid'] = uuid
        pkt['datetime'] = dateToMicro(pkt['datetime'])
        pkt['bytes'] = base64.b64encode(pkt['bytes'])
        if 0 in pkt: del pkt[0] # Kill KillerBee's backwards compatible keys
        if 1 in pkt: del pkt[1]
        if 2 in pkt: del pkt[2]
        http_headers = {'Content-Type' : 'application/json', 'User-Agent' : 'Drone'}
        post_data_json = json.dumps({'uuid':uuid, 'pkt':pkt})
        post_object = urllib2.Request(cburl, post_data_json, http_headers)
        try:
            response = urllib2.urlopen(post_object)
            self.logutil.debug('Successful Data Upload task {0} data to: {1}'.format(uuid, cburl))
        except(IOError):
            self.logutil.debug('Failed Data Upload task {0} to: {1}'.format(uuid, cburl))
        self.callbacks += 1

    def run(self):
        '''
        This part runs in a separate process as invoked by Multiprocessing.
        It recieves packets from the SnifferProcess via a pipe, and compares
        them against the data currently in the filters Manager.
        '''
        self.logutil.log('Started')
        tasks = []
        while not self.stopevent.is_set():
        
            # check if there are new tasks and update
            while not self.task_queue.empty():
                self.logutil.debug('Detected Tasking Update in Queue')
                tasks = []
                pickleTaskDict = self.task_queue.get_nowait()
                for uuid,data in cPickle.loads(pickleTaskDict).items():
                    tasks.append( (uuid, data['filter'], data['callback']) )
                self.task_queue.task_done()
                self.logutil.log('Tasking Updated ({0} tasks total)'.format(len(tasks)))
           
            # get packet from sniffer and match against tasked filters 
            try:
                pkt = self.pipe.recv()
                self.logutil.debug('Received Packet: {0}'.format(pkt['bytes'].encode('hex')))
                self.logutil.dev('Filtering against {0} tasks ({1})'.format(len(tasks), list((x[0] for x in tasks))))
                # Do the basic filtering, and run the callback function on packets that match
                for (uuid, filt, cb) in tasks:
                    # We check to see if the tasking has each test, and
                    # if it does, we see if it meets the defined condition.
                    # If it does not meet a condition, fail out right away.
                    if 'size' in filt:
                        (minB, maxB) = filt['size']
                        pktB = len(pkt['bytes'])
                        if pktB < minB or pktB > maxB:
                            continue
                    if 'fcf' in filt:
                        (mask, val) = filt['fcf']
                        if (unpack('>H', pkt['bytes'][0:2])[0] & mask) != val:
                            continue
                    if 'byteoffset' in filt:
                        (offset, mask, val) = filt['byteoffset']
                        if offset >= len(pkt['bytes']):
                            continue
                        if (unpack('B', pkt['bytes'][offset])[0] & mask) != val:
                            continue
                    # The cases of:
                    # (a) no conditions, aka send all packets, and
                    # (b) unknown condition we don't have coded for
                    # Both come to here and cause a callback to occur
                    self.logutil.debug('Matched Packet against task: {0}'.format(uuid))
                    self.do_callback(uuid, cb, pkt)
            except Exception as e:
                traceback.print_exc()
                print "Sniffer pipe on the filter end received an IOError, OK at shutdown:", e
Esempio n. 22
0
class RuleEngine(Process):

    def __init__(self, config):
        Process.__init__(self)
        self.name = 'RuleEngine'
        self.config = config
        self.database = DatabaseHandler(self.config.name)
        self.logutil = KBLogUtil(self.config.name, self.name)
        self.wids = WIDSClient(self.config.server_ip, self.config.server_port)
        self.active = None
        self.rules = []

        #///dev///
        self.rules.append(rule1)
        #////////

    def run(self):
        self.logutil.log('Starting Execution')        
        self.active = True
        self.start_time = dateToMicro(datetime.utcnow())

        while self.active:
    
            if DEV_DEBUG:
                self.logutil.debug('Checking for new rules')
                time.sleep(3)

            # check server for new rules: 'GET /rules/updatecheck', if so load new rules
            '''
            if self.wids.checkNewRules():
                new_rules = self.wids.getNewRules()
            '''

            # evaluate each rule serially
            self.logutil.debug('Evaluating rules')
            for RuleObject in self.rules:
                self.evaluateRule(RuleObject)

        self.logutil.log('Terminating Execution')


    # TODO - replace the internal database with a REST call to query database for events
    def evaluateRule(self, RuleObject):
        try:
            self.logutil.dev('Evaluating Rule: {0} (EventIndex: {1})'.format(RuleObject.name, RuleObject.event_index))
            for condition in RuleObject.conditions:
                module = condition[0]
                event  = condition[1]
                count  = condition[2]

                # TODO - replace this direct database query with REST call ????
                query = self.database.session.query(Event).filter(Event.module == module).filter(Event.name == event).filter(Event.datetime > self.start_time).filter(Event.id > RuleObject.event_index)

                results_count = query.limit(count).count()
                self.logutil.dev('Event: {0} - Found: {1} (Events Needed: {2})'.format(event, results_count, count))
                if not results_count >= count:
                    return False
                last_result = query.order_by(Event.id.desc()).limit(count).first()
                RuleObject.event_index = last_result.id
                self.logutil.log('>>> Rule Conditions Met ({0})'.format(RuleObject.name))
                for action in RuleObject.actions:
                    actionType   = action[0]
                    actionParams = action[1]
                    if actionType == 'GenerateAlert':
                        self.action_GenerateAlert(RuleObject.name,  actionParams)
                    if actionType == 'GenerateLog':
                        self.action_GenerateLog(RuleObject.name, actionParams)
        except Exception:
            traceback.print_exc() 
            
    def action_GenerateLog(self, rule_name, action_parameters):
        self.logutil.log('Execution GenerateLog Action for Rule {0}'.format(rule_name))
        pass

    def action_GenerateAlert(self, rule_name, action_parameters):
        self.logutil.log('Executing GenerateAlert Action for Rule {0}'.format(rule_name))
        self.wids.generateAlert(rule_name)

    def shutdown(self):
        self.active = False
        self.terminate()
class FilterProcess(Process):
    def __init__(self, pipe, task_queue, stopevent, task_update_event, drone,
                 parent):
        super(FilterProcess, self).__init__()
        self.pipe = pipe
        self.task_queue = task_queue
        self.stopevent = stopevent
        self.taskevent = task_update_event

        self.drone = drone
        self.parent = parent
        self.name = '{0}.Filter'.format(self.parent)
        self.logutil = KBLogUtil(self.drone, self.name, None)
        self.callbacks = 0

    def do_callback(self, uuid, cburl, pkt):
        pkt['uuid'] = uuid
        pkt['datetime'] = dateToMicro(pkt['datetime'])
        pkt['bytes'] = base64.b64encode(pkt['bytes'])
        if 0 in pkt: del pkt[0]  # Kill KillerBee's backwards compatible keys
        if 1 in pkt: del pkt[1]
        if 2 in pkt: del pkt[2]
        http_headers = {
            'Content-Type': 'application/json',
            'User-Agent': 'Drone'
        }
        post_data_json = json.dumps({'uuid': uuid, 'pkt': pkt})
        post_object = urllib2.Request(cburl, post_data_json, http_headers)
        try:
            response = urllib2.urlopen(post_object)
            self.logutil.debug(
                'Successful Data Upload task {0} data to: {1}'.format(
                    uuid, cburl))
        except (IOError):
            self.logutil.debug('Failed Data Upload task {0} to: {1}'.format(
                uuid, cburl))
        self.callbacks += 1

    def run(self):
        '''
        This part runs in a separate process as invoked by Multiprocessing.
        It recieves packets from the SnifferProcess via a pipe, and compares
        them against the data currently in the filters Manager.
        '''
        self.logutil.log('Started')
        tasks = []
        while not self.stopevent.is_set():

            # check if there are new tasks and update
            while not self.task_queue.empty():
                self.logutil.debug('Detected Tasking Update in Queue')
                tasks = []
                pickleTaskDict = self.task_queue.get_nowait()
                for uuid, data in cPickle.loads(pickleTaskDict).items():
                    tasks.append((uuid, data['filter'], data['callback']))
                self.task_queue.task_done()
                self.logutil.log('Tasking Updated ({0} tasks total)'.format(
                    len(tasks)))

            # get packet from sniffer and match against tasked filters
            try:
                pkt = self.pipe.recv()
                self.logutil.debug('Received Packet: {0}'.format(
                    pkt['bytes'].encode('hex')))
                self.logutil.dev('Filtering against {0} tasks ({1})'.format(
                    len(tasks), list((x[0] for x in tasks))))
                # Do the basic filtering, and run the callback function on packets that match
                for (uuid, filt, cb) in tasks:
                    # We check to see if the tasking has each test, and
                    # if it does, we see if it meets the defined condition.
                    # If it does not meet a condition, fail out right away.
                    if 'size' in filt:
                        (minB, maxB) = filt['size']
                        pktB = len(pkt['bytes'])
                        if pktB < minB or pktB > maxB:
                            continue
                    if 'fcf' in filt:
                        (mask, val) = filt['fcf']
                        if (unpack('>H', pkt['bytes'][0:2])[0] & mask) != val:
                            continue
                    if 'byteoffset' in filt:
                        (offset, mask, val) = filt['byteoffset']
                        if offset >= len(pkt['bytes']):
                            continue
                        if (unpack('B', pkt['bytes'][offset])[0]
                                & mask) != val:
                            continue
                    # The cases of:
                    # (a) no conditions, aka send all packets, and
                    # (b) unknown condition we don't have coded for
                    # Both come to here and cause a callback to occur
                    self.logutil.debug(
                        'Matched Packet against task: {0}'.format(uuid))
                    self.do_callback(uuid, cb, pkt)
            except Exception as e:
                traceback.print_exc()
                print "Sniffer pipe on the filter end received an IOError, OK at shutdown:", e
Esempio n. 24
0
class WIDSDaemon:
    def __init__(self, parameters=None, config=None):
        signal.signal(signal.SIGINT, self.SIGINT)
        self.config = WIDSConfig(parameters, config)
        self.config.daemon_pid = os.getpid()
        self.logutil = KBLogUtil(self.config.name, 'Daemon')
        self.database = DatabaseHandler(self.config.name)
        self.engine = None
        self.module_store = {}
        self.module_counter = 0
        self.task_store = {}
        self.task_counter = 0
        self.drone_store = {}
        self.drone_counter = 0

    def SIGINT(self, s, f):
        if self.config.daemon_pid == os.getpid():
            self.logutil.log('SIGINT')
            self.stopDaemon()

    def startDaemon(self):
        self.logutil.writePID()
        self.logutil.startlog()
        self.logutil.log('Starting Daemon')
        self.loadDrones()
        self.loadModules()
        self.startServer()

    def stopDaemon(self):
        self.logutil.log('Initiating Shutdown')
        self.unloadModules()
        self.unloadDrones()
        self.logutil.log('Successfull Shutdown')
        self.logutil.cleanup()
        sys.exit()

    def loadDrones(self):
        count = len(self.config.drones)
        self.logutil.log(
            'Loading Drones (Found {0} Drones in the Config)'.format(count))
        for droneConfig in self.config.drones:
            self.loadDrone(droneConfig)

    def loadDrone(self, droneConfigDict):
        try:
            print(droneConfigDict)
            drone_ip = str(droneConfigDict.get('ip', None))
            drone_port = str(droneConfigDict.get('port', None))
            if drone_ip == None or drone_port == None:
                error = 'Error: Missing Parameter: "address"'
                self.logutil.log(error)
                return self.formatResponse(error, None)
            else:
                droneIndex = self.drone_counter
                droneObject = DroneContainer(droneIndex, drone_ip, drone_port)
                self.drone_store[droneIndex] = droneObject
                self.drone_counter += 1
                self.logutil.log('Loading Drone {0} - {1}:{2}'.format(
                    droneIndex, drone_ip, drone_port))
                return self.formatResponse(None, None)
        except:
            self.handleException()

    def unloadDrones(self):
        self.logutil.log('Unloading Drones')
        self.logutil.log('Found {0} Active Drones'.format(len(
            self.drone_store)))
        for i in range(len(self.drone_store)):
            self.unloadDrone(i)

    def unloadDrone(self, droneIndexInt):
        try:
            droneObject = self.drone_store.get(droneIndexInt, None)
            if droneObject == None:
                error = 'Error: Drone with Index {0} does not exist'.format(
                    droneIndexInt)
                self.logutil.log(error)
                return self.formatResponse(False, error)
            else:
                droneObject.release()
                self.logutil.log('Releasing Drone {0} - {1}:{2}'.format(
                    droneIndexInt, droneObject.address, droneObject.port))
                del (self.drone_store[droneIndexInt])
                del (droneObject)
                return self.formatResponse(True, None)
        except:
            self.handleException()

    def taskDrone(self, taskConfigDict):
        try:
            droneIndexList = taskConfigDict.get('droneIndexList')
            for droneIndexInt in droneIndexList:
                droneObject = self.drone_store.get(droneIndexInt, None)
                task_uuid = taskConfigDict.get('uuid', None)
                task_plugin = taskConfigDict.get('plugin', None)
                task_channel = taskConfigDict.get('channel', None)
                task_parameters = taskConfigDict.get('parameters', None)
                module_index = taskConfigDict.get('module_index', None)
                if droneObject == None:
                    error = ec.ERROR_DRONE_InvalidDroneIndex
                    data = droneIndexInt
                    return (error, data)
                if task_uuid == None:
                    error = ec.ERROR_DRONE_MissingDroneTaskParameter
                    data = 'uuid'
                    return (error, data)
                if task_channel == None:
                    error = ec.ERROR_DRONE_MissingDroneTaskParameter
                    data = 'channel'
                    return (error, data)
                if task_plugin == None:
                    error = ec.ERROR_MissingDroneTaskParameter
                    data = 'plugin'
                    return (error, data)
                if task_parameters == None:
                    error = ec.ERROR_MissingDroneTaskParameter
                    data = 'parameters'
                    return (error, data)
                (data, error) = droneObject.api.task(task_plugin, task_channel,
                                                     task_uuid,
                                                     task_parameters)
                if error == None:
                    self.task_store[self.task_counter] = TaskContainer(
                        self.task_counter, task_uuid, task_plugin,
                        task_channel, task_parameters, droneIndexList,
                        module_index)
                    self.task_counter += 1
                return (data, error)
        except:
            self.handleException()

    def detaskDrone(self, droneIndexList, task_uuid):
        try:
            for int_DroneIndex in droneIndexList:
                droneObject = self.drone_store.get(int_DroneIndex, None)
                droneObject.api.detask(task_uuid)
        except Exception:
            self.handleException()

    def loadModules(self):
        count = len(self.config.modules)
        self.logutil.log(
            'Loading Modules (Found {0} Modules in the Config)'.format(count))
        for moduleConfigDict in self.config.modules:
            self.loadModule(moduleConfigDict)
        pass

    def unloadModules(self):
        self.logutil.log('Unloading Modules')
        self.logutil.log('Found {0} Active Modules'.format(
            len(self.module_store)))
        for i in range(len(self.module_store)):
            self.unloadModule(i)

    def loadModuleClass(self, module):
        if module == 'BeaconRequestMonitor': return BeaconRequestMonitor
        if module == 'DisassociationStormMonitor':
            return DisassociationStormMonitor
        if module == 'DosAesCtrMonitor': return DosAesCtrMonitor

    def loadModule(self, moduleConfigDict):
        self.logutil.debug('Loading Module: {0}'.format(moduleConfigDict))
        try:
            moduleName = moduleConfigDict.get('name', None)
            moduleSettings = moduleConfigDict.get('settings', None)
            moduleClass = self.loadModuleClass(moduleName)
            if moduleName == None:
                error = ec.ERROR_WIDS_MissingModuleParameter
                data = 'name'
                self.logutil.log(
                    'Failed to Load Module - Missing Parameter: "name" in {0}\n'
                    .format(moduleConfigDict))
                return self.formatResponse(error, data)
            elif moduleSettings == None:
                error = ec.ERROR_WIDS_MissingModuleParameter
                data = 'settings'
                self.logutil.log(
                    'Failed to Load Module - Missing Parameter: "settings" in {0}\n'
                    .format(moduleConfigDict))
                return self.formatResponse(error, data)
            elif moduleClass == None:
                error = ec.ERROR_WIDS_MissingModuleClass
                data = moduleName
                self.logutil.log(
                    'Failed to Load Module - Could not load class: {0}'.format(
                        moduleName))
                return self.formatResponse(error, data)
            else:
                moduleIndex = self.module_counter
                moduleShutdownEvent = Event()
                moduleSettings['module_index'] = moduleIndex
                self.logutil.debug(
                    'Found module class: {0}'.format(moduleClass))
                '''
                (error,data) = moduleClass.validate_settings(moduleSettings) 
                if not error == None:
                    return self.formatResponse(error,data)
                '''
                moduleProcess = moduleClass(moduleSettings, self.config,
                                            moduleShutdownEvent)
                moduleProcess.start()
                moduleObject = ModuleContainer(moduleIndex, moduleName,
                                               moduleSettings, moduleProcess,
                                               moduleShutdownEvent)
                self.module_store[moduleIndex] = moduleObject
                self.module_counter += 1
                self.logutil.log('Loading Module {0} - {1}'.format(
                    moduleIndex, moduleObject.name))
                return self.formatResponse(None, None)
        except:
            self.handleException()

    def unloadModule(self, moduleIndexInt):
        try:
            moduleObject = self.module_store.get(moduleIndexInt, None)
            if moduleObject == None:
                error = 'Error: Module with Index {0} does not exist'.format(
                    moduleIndexInt)
                self.logutil.log(error)
                return self.formatResponse(False, error)
            else:
                self.logutil.log('Unloading Module {0} ({1} - {2})'.format(
                    moduleIndexInt, moduleObject.name,
                    moduleObject.process.pid))
                self.logutil.log('Detasking Module Tasks')
                for taskObject in self.task_store.values():
                    if taskObject.module_index == moduleObject.index:
                        drones = taskObject.drones
                        uuid = taskObject.uuid
                        self.logutil.log(
                            'Removing Task {0} from Drones {1}'.format(
                                uuid, drones))
                        self.detaskDrone(drones, uuid)
                moduleObject.process.terminate()
                moduleObject.process.join()
                del (self.module_store[moduleIndexInt])
                del (moduleObject)
                return self.formatResponse(True, None)
        except:
            self.handleException()

    def startServer(self):
        self.logutil.log('Starting Server on port {0}'.format(
            self.config.server_port))
        app = flask.Flask(__name__)
        app.add_url_rule('/active',
                         None,
                         self.processActiveGetRequest,
                         methods=['GET'])
        app.add_url_rule('/status',
                         None,
                         self.processStatusGetRequest,
                         methods=['GET'])
        app.add_url_rule('/data/upload',
                         None,
                         self.processDataUploadRequest,
                         methods=['POST'])
        app.add_url_rule('/data/download',
                         None,
                         self.processDataDownloadRequest,
                         methods=['POST'])
        app.add_url_rule('/drone/task',
                         None,
                         self.processDroneTaskRequest,
                         methods=['POST'])
        app.add_url_rule('/drone/detask',
                         None,
                         self.processDroneDetaskRequest,
                         methods=['POST'])
        app.add_url_rule('/drone/add',
                         None,
                         self.processDroneAddRequest,
                         methods=['POST'])
        app.add_url_rule('/drone/delete',
                         None,
                         self.processDroneDeleteRequest,
                         methods=['POST'])
        app.add_url_rule('/alerts',
                         None,
                         self.processAlertGetRequest,
                         methods=['POST'])
        app.add_url_rule('/alerts/generate',
                         None,
                         self.processAlertGenerateRequest,
                         methods=['POST'])
        app.add_url_rule('/module/load',
                         None,
                         self.processModuleLoadRequest,
                         methods=['POST'])
        app.add_url_rule('/module/unload',
                         None,
                         self.processModuleUnloadRequest,
                         methods=['POST'])
        app.run(threaded=True, port=int(self.config.server_port))

    def handleException(self):
        etb = traceback.format_exc()
        self.logutil.trace(etb)
        return self.formatResponse(error=ec.ERROR_GENERAL_UnknownException,
                                   data=str(etb))

    def formatResponse(self, error, data):
        return json.dumps({'error': error, 'data': data})

    def processActiveGetRequest(self):
        self.logutil.debug('Processing Active Get Request')
        return self.formatResponse(error=None, data=True)

    def processDataUploadRequest(self):
        self.logutil.debug('Processing Data Upload Request')
        try:
            data = json.loads(flask.request.data)
            packetdata = data.get('pkt')
            self.database.storePacket(packetdata)
            return self.formatResponse(error=None, data=None)
        except Exception:
            return self.handleException()

    def processDataDownloadRequest(self):
        self.logutil.debug('Processing Data Upload Request')
        try:
            return self.formatResponse(error=None, data=None)
        except Exception:
            return self.handleException()

    def processDroneTaskRequest(self):
        self.logutil.debug('Processing Drone Task Request')
        try:
            request_data = json.loads(flask.request.data)
            (error, data) = self.taskDrone(request_data)
            return self.formatResponse(error, data)
        except Exception:
            return self.handleException()

    def processDroneDetaskRequest(self):
        self.logutil.debug('Processing Drone Detask Request')
        try:
            data = json.loads(flask.request.data)
            return self.detaskDrone(data)
        except Exception:
            return self.handleException()

    def processDroneAddRequest(self):
        self.logutil.debug('Processing Drone Add Request')
        try:
            data = json.loads(flask.request.data)
            return self.loadDrone(data)
        except Exception:
            return self.handleException()

    def processDroneDeleteRequest(self):
        self.logutil.debug('Processing Drone Delete Request')
        try:
            data = json.loads(flask.request.data)
            drone_index = int(data.get('drone_index'))
            return self.unloadDrone(drone_index)
        except:
            return self.handleException()

    def processModuleLoadRequest(self):
        self.logutil.debug('Processing Module Load Request')
        try:
            data = json.loads(flask.request.data)
            return self.loadModule(data)
        except:
            return self.handleException()

    def processModuleUnloadRequest(self):
        self.logutil.debug('Processing Module Unload Request')
        try:
            data = json.loads(flask.request.data)
            module_index = int(data.get('module_index'))
            return self.unloadModule(module_index)
        except:
            return self.handleException()

    def processAlertGenerateRequest(self):
        self.logutil.debug('Processing Alert Generate Request')
        try:
            data = json.loads(flask.request.data)
            alert_name = str(data.get('alert_name'))
            self.database.storeAlert(alert_name)
            return self.formatResponse(True, None)
        except:
            return self.handleException()

    def processAlertGetRequest(self):
        #self.logutil.debug('Processing Alert Request')
        try:
            alerts = []
            for alert in self.database.session.query(Alert).all():
                alerts.append('{0} - {1}'.format(microToDate(alert.datetime),
                                                 alert.name))
            return self.formatResponse(None, alerts)
        except:
            return self.handleException()

    def processStatusGetRequest(self):
        self.logutil.log('Processing Status Request')
        try:
            config = self.config.json()
            modules = list(
                (module.json() for module in self.module_store.values()))
            tasks = list((task.json() for task in self.task_store.values()))
            rules = list((rule.json() for rule in self.rule_store.values()))
            drones = list(
                (drone.json() for drone in self.drone_store.values()))
            status = {
                'config': config,
                'modules': modules,
                'tasks': tasks,
                'drones': drones,
                'rules': rules
            }
            return json.dumps({'success': True, 'data': status})
        except:
            return self.handleException()