diff --git a/README.md b/README.md index 350e742..24984e1 100644 --- a/README.md +++ b/README.md @@ -26,6 +26,7 @@ Lancement de Defender : # VERSION 1 [02.01.2024] + - Rajout de l'activation de la commande flood - Les deux variables RESTART et INIT ont été déplacées vers le module Irc - Nouvelle class Install: - Le programme va vérifier si les 3 librairies sont installées (SQLAlchemy & requests & psutil) diff --git a/core/irc.py b/core/irc.py index 9bb11aa..5d69a15 100644 --- a/core/irc.py +++ b/core/irc.py @@ -603,8 +603,9 @@ def logs(self, log_msg:str) -> None: return None def cmd(self, data:list) -> None: - try: - cmd = data + try: + cmd_to_send:list[str] = data.copy() + cmd = data.copy() if len(cmd) == 0 or len(cmd) == 1: return False @@ -811,7 +812,7 @@ def cmd(self, data:list) -> None: # Envoyer la commande aux classes dynamiquement chargées for classe_name, classe_object in self.loaded_classes.items(): - classe_object.cmd(cmd) + classe_object.cmd(cmd_to_send) except IndexError as ie: self.debug(f"IRC CMD -> IndexError : {ie} - {cmd} - length {str(len(cmd))}") diff --git a/mods/mod_defender.py b/mods/mod_defender.py index 66b0620..cf38645 100644 --- a/mods/mod_defender.py +++ b/mods/mod_defender.py @@ -26,7 +26,7 @@ def __init__(self, ircInstance:Irc) -> None: 0: ['code'], 1: ['join','part', 'info'], 2: ['q', 'dq', 'o', 'do', 'h', 'dh', 'v', 'dv', 'b', 'ub','k', 'kb'], - 3: ['reputation','proxy_scan', 'status', 'timer','show_reputation', 'show_users'] + 3: ['reputation','proxy_scan', 'flood', 'status', 'timer','show_reputation', 'show_users'] } self.__set_commands(self.commands_level) # Enrigstrer les nouvelles commandes dans le code @@ -300,7 +300,6 @@ def insert_db_trusted(self, uid: str, nickname:str) -> None: exec_query = self.Base.db_execute_query(q_insert, mes_donnees) pass - def join_saved_channels(self) -> None: result = self.Base.db_execute_query("SELECT id, channel FROM def_channels") @@ -470,13 +469,13 @@ def _execute_flood_action(self, action:str, channel:str) -> None: return None def flood(self, detected_user:str, channel:str) -> None: - + if self.defConfig['flood'] == 0: return None - + if not '#' in channel: return None - + flood_time = self.defConfig['flood_time'] flood_message = self.defConfig['flood_message'] flood_timer = self.defConfig['flood_timer'] @@ -621,7 +620,7 @@ def abuseipdb_scan(self, remote_ip:str) -> dict[str, any] | None: def cmd(self, data:list) -> None: service_id = self.Config.SERVICE_ID # Defender serveur id - cmd = data + cmd = list(data).copy() if len(cmd) < 2: return None @@ -656,29 +655,6 @@ def cmd(self, data:list) -> None: find_nickname = self.Irc.get_nickname(user_trigger) self.flood(find_nickname, channel) - case 'SJOIN': - # ['@msgid=F9B7JeHL5pj9nN57cJ5pEr;time=2023-12-28T20:47:24.305Z', ':001', 'SJOIN', '1702138958', '#welcome', ':0015L1AHL'] - try: - cmd.pop(0) - parsed_chan = cmd[3] - self.Irc.insert_db_chan(parsed_chan) - - if self.defConfig['reputation'] == 1: - parsed_UID = cmd[4] - pattern = fr'^:[@|%|\+|~|\*]*' - parsed_UID = re.sub(pattern, '', parsed_UID) - if parsed_UID in self.db_reputation: - # print(f"====> {str(self.db_reputation)}") - isWebirc = self.db_reputation[parsed_UID]['isWebirc'] - if self.defConfig['reputation_ban_all_chan'] == 1 and not isWebirc: - if parsed_chan != self.Config.SALON_JAIL: - self.Irc.send2socket(f":{service_id} MODE {parsed_chan} +b {self.db_reputation[parsed_UID]['nickname']}!*@*") - self.Irc.send2socket(f":{service_id} KICK {parsed_chan} {self.db_reputation[parsed_UID]['nickname']}") - - self.Irc.debug(f'SJOIN parsed_uid : {parsed_UID}') - except KeyError as ke: - self.Irc.debug(f"key error SJOIN : {ke}") - case 'UID': if self.Irc.INIT == 1: @@ -723,6 +699,29 @@ def cmd(self, data:list) -> None: self.system_reputation(uid) self.Irc.debug('Démarrer le systeme de reputation') + case 'SJOIN': + # ['@msgid=F9B7JeHL5pj9nN57cJ5pEr;time=2023-12-28T20:47:24.305Z', ':001', 'SJOIN', '1702138958', '#welcome', ':0015L1AHL'] + try: + cmd.pop(0) + parsed_chan = cmd[3] + self.Irc.insert_db_chan(parsed_chan) + + if self.defConfig['reputation'] == 1: + parsed_UID = cmd[4] + pattern = fr'^:[@|%|\+|~|\*]*' + parsed_UID = re.sub(pattern, '', parsed_UID) + if parsed_UID in self.db_reputation: + # print(f"====> {str(self.db_reputation)}") + isWebirc = self.db_reputation[parsed_UID]['isWebirc'] + if self.defConfig['reputation_ban_all_chan'] == 1 and not isWebirc: + if parsed_chan != self.Config.SALON_JAIL: + self.Irc.send2socket(f":{service_id} MODE {parsed_chan} +b {self.db_reputation[parsed_UID]['nickname']}!*@*") + self.Irc.send2socket(f":{service_id} KICK {parsed_chan} {self.db_reputation[parsed_UID]['nickname']}") + + self.Irc.debug(f'SJOIN parsed_uid : {parsed_UID}') + except KeyError as ke: + self.Irc.debug(f"key error SJOIN : {ke}") + case 'SLOG': # self.Base.scan_ports(cmd[7]) cmd.pop(0) @@ -1019,6 +1018,63 @@ def _hcmds(self, user:str, cmd: list) -> None: self.Irc.send2socket(f':{dnickname} NOTICE {fromuser} : Right command : /msg {dnickname} proxy_scan set psutil_scan [ON/OFF]') self.Irc.send2socket(f':{dnickname} NOTICE {fromuser} : Right command : /msg {dnickname} proxy_scan set abuseipdb_scan [ON/OFF]') + case 'flood': + # .flood on/off + # .flood set flood_message 5 + # .flood set flood_time 1 + # .flood set flood_timer 20 + try: + len_cmd = len(cmd) + + if len_cmd == 2: + activation = str(cmd[1]).lower() + key = 'flood' + if activation == 'on': + if self.defConfig[key] == 1: + self.Irc.send2socket(f":{dnickname} PRIVMSG {dchanlog} :[ {self.Config.CONFIG_COLOR['verte']}FLOOD{self.Config.CONFIG_COLOR['noire']} ] : Already activated") + return False + + self.update_db_configuration(key, 1) + self.Irc.send2socket(f":{dnickname} PRIVMSG {dchanlog} :[ {self.Config.CONFIG_COLOR['verte']}FLOOD{self.Config.CONFIG_COLOR['noire']} ] : Activated by {fromuser}") + + if activation == 'off': + if self.defConfig[key] == 0: + self.Irc.send2socket(f":{dnickname} PRIVMSG {dchanlog} :[ {self.Config.CONFIG_COLOR['rouge']}FLOOD{self.Config.CONFIG_COLOR['noire']} ] : Already Deactivated") + return False + + self.update_db_configuration(key, 0) + self.Irc.send2socket(f":{dnickname} PRIVMSG {dchanlog} :[ {self.Config.CONFIG_COLOR['verte']}FLOOD{self.Config.CONFIG_COLOR['noire']} ] : Deactivated by {fromuser}") + + if len_cmd == 4: + set_key = str(cmd[2]).lower() + + if str(cmd[1]).lower() == 'set': + match set_key: + case 'flood_message': + key = 'flood_message' + set_value = int(cmd[3]) + print(f"{str(set_value)} - {set_key}") + self.update_db_configuration(key, set_value) + self.Irc.send2socket(f":{dnickname} PRIVMSG {dchanlog} :[ {self.Config.CONFIG_COLOR['verte']}FLOOD{self.Config.CONFIG_COLOR['noire']} ] : Flood message set to {set_value} by {fromuser}") + + case 'flood_time': + key = 'flood_time' + set_value = int(cmd[3]) + self.update_db_configuration(key, set_value) + self.Irc.send2socket(f":{dnickname} PRIVMSG {dchanlog} :[ {self.Config.CONFIG_COLOR['verte']}FLOOD{self.Config.CONFIG_COLOR['noire']} ] : Flood time set to {set_value} by {fromuser}") + + case 'flood_timer': + key = 'flood_timer' + set_value = int(cmd[3]) + self.update_db_configuration(key, set_value) + self.Irc.send2socket(f":{dnickname} PRIVMSG {dchanlog} :[ {self.Config.CONFIG_COLOR['verte']}FLOOD{self.Config.CONFIG_COLOR['noire']} ] : Flood timer set to {set_value} by {fromuser}") + + case _: + pass + + except ValueError as ve: + self.Irc.debug(f"{self.__class__.__name__} Value Error : {ve}") + case 'status': try: self.Irc.send2socket(f':{dnickname} NOTICE {fromuser} : Reputation ==> {self.defConfig["reputation"]}')