def __init__(self, config: ConfigurationManager, base=BasePlugin): self.base = base self.config = config self.failed = {} self._seen_classes = set() self._plugins = {} self._activated_plugins = set() self._deactivated_plugins = set() self._resolved = False self._overrides = set() self._override_cache = set() self._packet_parser = PacketParser(self.config)
def __init__(self, db, interface, related_interface, sniffer_name, enable_hopping, use_24=True, use_pop5=False): self.db = db self.sniffer_name = sniffer_name self.interface = interface self.enable_hopping = enable_hopping # Check interface existance if not self._iface_exists(interface): print "Exiting: Interface %s doesn't exist" % interface sys.exit(1) if related_interface and not self._iface_exists(related_interface): print "Exiting: Related interface %s doesn't exist" % interface sys.exit(1) # Logging header = 'SNIFF' if sniffer_name: header += '_' + sniffer_name self.log = Log(self.db, use_stdout=True, header=header) # Submodules self.packet_parser = PacketParser(self.log) self.hopper = Hopper(self.log, interface, related_interface) ret = self.hopper.configure(use_24=use_24, use_pop5=use_pop5) if ret is False: sys.exit(1) config.conf.sniff_promisc = 0 self.log.info("Promiscuous mode disabled") self.watchdog = WatchDog(interval=20)
def updateDataStreams(cls, id, packed): data = PacketParser.unpack_packed_bytes(cls.format, packed) result = [] if data != None: for d in cls.datastreams: if 'transform' in d: cval = d['transform'](data[d['dataindex']]) else: cval = data[d['dataindex']] result.append(xively.Datastream(id=id + d['suffix'], current_value=cval)) return result
def handleNewPacket(self, packet): parse_result = PacketParser.byte_encode_ok_packet(packet) if parse_result != None: (id, type, packed) = parse_result node = self.getNode(int(type)) if DEBUG: logging.debug("NODE: id {0}, type {1}".format(id, type)) if int(id) not in self.knownIDs: node.createDataStreams(self.feed, id) self.knownIDs.add(int(id)) if node != None: update = node.updateDataStreams(id, packed) if update != []: self.feed.datastreams = update try: self.feed.update(fields=['datastreams']) if DEBUG: logging.debug("DSTRM_UPDATED:" + id + ", " + type + ", " + repr(update)) except requests.ConnectionError as e: logging.error("XIV_CON_ERR: {0}".format(e))
class PluginManager: def __init__(self, config: ConfigurationManager, base=BasePlugin): self.base = base self.config = config self.failed = {} self._seen_classes = set() self._plugins = {} self._activated_plugins = set() self._deactivated_plugins = set() self._resolved = False self._overrides = set() self._override_cache = set() self._packet_parser = PacketParser(self.config) def list_plugins(self): return self._plugins @asyncio.coroutine def do(self, protocol, action: str, packet: dict): """ Calls an action on all loaded plugins """ try: if ("on_%s" % action) in self._overrides: packet = yield from self._packet_parser.parse(packet) send_flag = True for plugin in self._plugins.values(): p = getattr(plugin, "on_%s" % action) if not (yield from p(packet, protocol)): send_flag = False return send_flag else: return True except Exception: print("Exception encountered in plugin.") traceback.print_exc() return True def load_from_path(self, plugin_path: pathlib.Path): blacklist = ["__init__", "__pycache__"] loaded = set() for file in plugin_path.iterdir(): if file.stem in blacklist: continue if (file.suffix == ".py" or file.is_dir()) and str( file) not in loaded: try: loaded.add(str(file)) self.load_plugin(file) except (SyntaxError, ImportError) as e: self.failed[file.stem] = str(e) print(e) except FileNotFoundError: print("File not found") @staticmethod def _load_module(file_path: pathlib.Path): """ Attempts to load a module, either from a straight python file or from a python package, by appending __init__.py to the end of the path if it is a directory. """ if file_path.is_dir(): file_path /= '__init__.py' if not file_path.exists(): raise FileNotFoundError("{0} doesn't exist.".format(str(file_path))) name = "plugins.%s" % file_path.stem loader = importlib.machinery.SourceFileLoader(name, str(file_path)) module = loader.load_module(name) return module def load_plugin(self, plugin_path: pathlib.Path): module = self._load_module(plugin_path) classes = self.get_classes(module) for candidate in classes: self._seen_classes.add(candidate) def get_classes(self, module: ModuleType): """ Uses the inspect module to find all classes in a given module that are subclassed from `self.base`, but are not actually `self.base`. """ class_list = [] for _, obj in inspect.getmembers(module): if inspect.isclass(obj): if issubclass(obj, self.base) and obj is not self.base: obj.config = self.config class_list.append(obj) return class_list def load_plugins(self, plugins: list): for plugin in plugins: self.load_plugin(plugin) def resolve_dependencies(self): """ Resolves dependencies from self._seen_classes through a very simple topological sort. Raises ImportError if there is an unresolvable dependency, otherwise it instantiates the class and puts it in self._plugins. """ deps = {x.name: set(x.depends) for x in self._seen_classes} classes = {x.name: x for x in self._seen_classes} while len(deps) > 0: ready = [x for x, d in deps.items() if len(d) == 0] for name in ready: self._plugins[name] = classes[name]() del deps[name] for name, depends in deps.items(): to_load = depends & set(self._plugins.keys()) deps[name] = deps[name].difference(set(self._plugins.keys())) for plugin in to_load: classes[name].plugins[plugin] = self._plugins[plugin] if len(ready) == 0: raise ImportError("Unresolved dependencies found.") self._resolved = True @asyncio.coroutine def get_overrides(self): if self._override_cache is self._activated_plugins: return self._overrides else: overrides = set() for plugin in self._activated_plugins: override = yield from detect_overrides(BasePlugin, plugin) overrides.update({x for x in override}) self._overrides = overrides self._override_cache = self._activated_plugins return overrides def activate_all(self): for plugin in self._plugins.values(): print(plugin) plugin.activate() self._activated_plugins.add(plugin) def deactivate_all(self): for plugin in self._plugins.values(): print("Deactivating") plugin.deactivate()
class Sniffer(object): "Channel hopping, packet sniffing, parsing and finally storing" def __init__(self, db, interface, related_interface, sniffer_name, enable_hopping, use_24=True, use_pop5=False): self.db = db self.sniffer_name = sniffer_name self.interface = interface self.enable_hopping = enable_hopping # Check interface existance if not self._iface_exists(interface): print "Exiting: Interface %s doesn't exist" % interface sys.exit(1) if related_interface and not self._iface_exists(related_interface): print "Exiting: Related interface %s doesn't exist" % interface sys.exit(1) # Logging header = 'SNIFF' if sniffer_name: header += '_' + sniffer_name self.log = Log(self.db, use_stdout=True, header=header) # Submodules self.packet_parser = PacketParser(self.log) self.hopper = Hopper(self.log, interface, related_interface) ret = self.hopper.configure(use_24=use_24, use_pop5=use_pop5) if ret is False: sys.exit(1) config.conf.sniff_promisc = 0 self.log.info("Promiscuous mode disabled") self.watchdog = WatchDog(interval=20) def _iface_exists(self, iface_name): "Check if interface exists" path = '/sys/class/net' iface_path = os.path.join(path, iface_name) try: _ = os.stat(iface_path) return True except OSError: return False def run(self): "Sniffer main loop" begin = time() pkts_all = 0 sniff_begin = time() stat_prev = sniff_begin stat_every = 3 # seconds while True: start = time() # This catches KeyboardInterrupt, # TODO: Disable this catching + Probably hop on another thread and use prn argument. # But then - you'd have watchdog problems. pkts = sendrecv.sniff(iface=self.interface, count=20, timeout=0.1) pkts_all += len(pkts) for pkt in pkts: data = self.packet_parser.parse(pkt) if data is None: continue data['ch'] = self.hopper.channel_number data['sniffer'] = self.sniffer_name if ('PROBE_REQ' in data['tags'] or 'PROBE_RESP' in data['tags'] or 'ASSOC_REQ' in data['tags'] or 'DISASS' in data['tags']): # Increase karma when client traffic is detected self.hopper.increase_karma() data['tags'] = list(data['tags']) self.db.frames.add(data) now = time() took = now - start if stat_prev + stat_every < now: took = time() - sniff_begin print "STAT: pkts=%d t_total=%.2fs pps=%.2f swipes=%d avg_swipe_t=%.2f cur_ch=%d" % ( pkts_all, took, pkts_all / took, self.hopper.swipes_total, took / (self.hopper.swipes_total + 0.001), self.hopper.channel_number, ) stat_prev = now if self.enable_hopping: ret = self.hopper.karmic_hop() if ret is False: break self.watchdog.dontkillmeplease()
class Sniffer(object): "Channel hopping, packet sniffing, parsing and finally storing" def __init__(self, db, interface, related_interface, sniffer_name, enable_hopping, use_24=True, use_pop5=False): self.db = db self.sniffer_name = sniffer_name self.interface = interface self.enable_hopping = enable_hopping # Check interface existance if not self._iface_exists(interface): print "Exiting: Interface %s doesn't exist" % interface sys.exit(1) if related_interface and not self._iface_exists(related_interface): print "Exiting: Related interface %s doesn't exist" % interface sys.exit(1) # Logging header = 'SNIFF' if sniffer_name: header += '_' + sniffer_name self.log = Log(self.db, use_stdout=True, header=header) # Submodules self.packet_parser = PacketParser(self.log) self.hopper = Hopper(self.log, interface, related_interface) ret = self.hopper.configure(use_24=use_24, use_pop5=use_pop5) if ret is False: sys.exit(1) config.conf.sniff_promisc = 0 self.log.info("Promiscuous mode disabled") self.watchdog = WatchDog(interval=20) def _iface_exists(self, iface_name): "Check if interface exists" path = '/sys/class/net' iface_path = os.path.join(path, iface_name) try: _ = os.stat(iface_path) return True except OSError: return False def run(self): "Sniffer main loop" begin = time() pkts_all = 0 sniff_begin = time() stat_prev = sniff_begin stat_every = 3 # seconds while True: start = time() # This catches KeyboardInterrupt, # TODO: Disable this catching + Probably hop on another thread and use prn argument. # But then - you'd have watchdog problems. pkts = sendrecv.sniff(iface=self.interface, count=20, timeout=0.1) pkts_all += len(pkts) for pkt in pkts: data = self.packet_parser.parse(pkt) if data is None: continue data['ch'] = self.hopper.channel_number data['sniffer'] = self.sniffer_name if ('PROBE_REQ' in data['tags'] or 'PROBE_RESP' in data['tags'] or 'ASSOC_REQ' in data['tags'] or 'DISASS' in data['tags']): # Increase karma when client traffic is detected self.hopper.increase_karma() data['tags'] = list(data['tags']) self.db.frames.add(data) now = time() took = now - start if stat_prev + stat_every < now: took = time() - sniff_begin print "STAT: pkts=%d t_total=%.2fs pps=%.2f swipes=%d avg_swipe_t=%.2f cur_ch=%d" % ( pkts_all, took, pkts_all / took, self.hopper.swipes_total, took/(self.hopper.swipes_total + 0.001), self.hopper.channel_number, ) stat_prev = now if self.enable_hopping: ret = self.hopper.karmic_hop() if ret is False: break self.watchdog.dontkillmeplease()