This commit is contained in:
adator
2024-08-29 01:13:55 +02:00
parent 9cd089ee6e
commit 01dcc90d63
7 changed files with 179 additions and 47 deletions

View File

@@ -315,7 +315,7 @@ class Channel:
for user in newChan.uids: for user in newChan.uids:
record.uids.append(user) record.uids.append(user)
# Supprimer les doublons # Supprimer les doublons
del_duplicates = list(set(record.uids)) del_duplicates = list(set(record.uids))
record.uids = del_duplicates record.uids = del_duplicates
self.log.debug(f'Updating a new UID to the channel {record}') self.log.debug(f'Updating a new UID to the channel {record}')
@@ -402,3 +402,97 @@ class Channel:
self.log.debug(f'Search {name} -- result = {Channel}') self.log.debug(f'Search {name} -- result = {Channel}')
return Channel return Channel
class Clones:
@dataclass
class CloneModel:
alive: bool
nickname: str
username: str
UID_CLONE_DB: list[CloneModel] = []
def __init__(self, Base: Base) -> None:
self.log = Base.logs
def insert(self, newCloneObject: CloneModel) -> bool:
"""Create new Clone object
Args:
newCloneObject (CloneModel): New CloneModel object
Returns:
bool: True if inserted
"""
result = False
exist = False
for record in self.UID_CLONE_DB:
if record.nickname == newCloneObject.nickname:
# If the user exist then return False and do not go further
exist = True
self.log.debug(f'{record.nickname} already exist')
return result
if not exist:
self.UID_CLONE_DB.append(newCloneObject)
result = True
self.log.debug(f'New Clone Object Created: ({newCloneObject})')
if not result:
self.log.critical(f'The Clone Object was not inserted {newCloneObject}')
return result
def delete(self, nickname: str) -> bool:
"""Delete the Clone Object starting from the nickname
Args:
nickname (str): nickname of the clone
Returns:
bool: True if deleted
"""
result = False
for record in self.UID_CLONE_DB:
if record.nickname == nickname:
# If the user exist then remove and return True and do not go further
self.UID_CLONE_DB.remove(record)
result = True
self.log.debug(f'The clone ({record.nickname}) has been deleted')
return result
if not result:
self.log.critical(f'The UID {nickname} was not deleted')
return result
def exists(self, nickname: str) -> bool:
"""Check if the nickname exist
Args:
nickname (str): Nickname of the clone
Returns:
bool: True if the nickname exist
"""
response = False
for cloneObject in self.UID_CLONE_DB:
if cloneObject.nickname == nickname:
response = True
return response
def kill(self, nickname:str) -> bool:
response = False
for cloneObject in self.UID_CLONE_DB:
if cloneObject.nickname == nickname:
cloneObject.alive = False # Kill the clone
response = True
return response

View File

@@ -1,20 +1,26 @@
import socket, ssl, time import socket, ssl, time
from ssl import SSLSocket from ssl import SSLSocket
from core.loadConf import Config from core.loadConf import Config
from core.Model import Clones
from core.base import Base from core.base import Base
from typing import Union from typing import Union
class Connection: class Connection:
def __init__(self, server_port: int, nickname: str, username: str, channels:list[str], ssl:bool = False) -> None: def __init__(self, server_port: int, nickname: str, username: str, channels:list[str], CloneObject: Clones, ssl:bool = False) -> None:
self.Config = Config().ConfigObject self.Config = Config().ConfigObject
self.Base = Base(self.Config) self.Base = Base(self.Config)
self.IrcSocket: Union[socket.socket, SSLSocket] = None self.IrcSocket: Union[socket.socket, SSLSocket] = None
self.signal: bool = True
self.nickname = nickname self.nickname = nickname
self.username = username self.username = username
self.channels:list[str] = channels self.channels:list[str] = channels
self.CHARSET = ['utf-8', 'iso-8859-1'] self.CHARSET = ['utf-8', 'iso-8859-1']
self.Clones = CloneObject
self.signal: bool = True
for clone in self.Clones.UID_CLONE_DB:
if clone.nickname == nickname:
self.currentCloneObject = clone
self.create_socket(self.Config.SERVEUR_IP, self.Config.SERVEUR_HOSTNAME, server_port, ssl) self.create_socket(self.Config.SERVEUR_IP, self.Config.SERVEUR_HOSTNAME, server_port, ssl)
self.send_connection_information_to_server(self.IrcSocket) self.send_connection_information_to_server(self.IrcSocket)
@@ -126,7 +132,6 @@ class Connection:
break break
self.parser(data) self.parser(data)
except ssl.SSLEOFError as soe: except ssl.SSLEOFError as soe:
self.Base.logs.error(f"SSLEOFError __connect_to_irc: {soe} - {data}") self.Base.logs.error(f"SSLEOFError __connect_to_irc: {soe} - {data}")
self.signal = False self.signal = False
@@ -156,6 +161,7 @@ class Connection:
try: try:
for data in cmd: for data in cmd:
response = data.decode(self.CHARSET[0]).split() response = data.decode(self.CHARSET[0]).split()
self.signal = self.currentCloneObject.alive
# print(response) # print(response)
match response[0]: match response[0]:
@@ -174,13 +180,15 @@ class Connection:
self.send2socket(f"JOIN {channel}") self.send2socket(f"JOIN {channel}")
return None return None
case 'PRIVMSG': case 'PRIVMSG':
self.Base.logs.debug(response)
self.Base.logs.debug(f'{self.currentCloneObject.nickname} - {self.currentCloneObject.alive}')
fullname = str(response[0]).replace(':', '') fullname = str(response[0]).replace(':', '')
nickname = fullname.split('!')[0].replace(':','') nickname = fullname.split('!')[0].replace(':','')
if nickname == self.Config.SERVICE_NICKNAME: if nickname == self.Config.SERVICE_NICKNAME:
command = str(response[3]).replace(':','') command = str(response[3]).replace(':','')
if command == 'KILL': if command == 'KILL':
self.send2socket(f'QUIT :Thanks and goodbye') self.send2socket(f'QUIT :Thanks and goodbye')
self.signal = False self.signal = self.currentCloneObject.alive
if command == 'JOIN': if command == 'JOIN':
channel_to_join = str(response[4]) channel_to_join = str(response[4])
self.send2socket(f"JOIN {channel_to_join}") self.send2socket(f"JOIN {channel_to_join}")
@@ -193,7 +201,6 @@ class Connection:
response = data.decode(self.CHARSET[1],'replace').split() response = data.decode(self.CHARSET[1],'replace').split()
except AssertionError as ae: except AssertionError as ae:
self.Base.logs.error(f"Assertion error : {ae}") self.Base.logs.error(f"Assertion error : {ae}")
pass
def __ssl_context(self) -> ssl.SSLContext: def __ssl_context(self) -> ssl.SSLContext:
ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT) ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)

View File

@@ -27,6 +27,9 @@ class Install:
def __init__(self) -> None: def __init__(self) -> None:
self.set_configuration() self.set_configuration()
if self.skip_install:
return None
if not self.check_python_version(): if not self.check_python_version():
# Tester si c'est la bonne version de python # Tester si c'est la bonne version de python
@@ -45,6 +48,13 @@ class Install:
def set_configuration(self): def set_configuration(self):
self.skip_install = False
# Exclude Windows OS
if os.name == 'nt':
#print('/!\\ Skip installation /!\\')
self.skip_install = True
return False
defender_install_folder = os.getcwd() defender_install_folder = os.getcwd()
venv_folder = '.pyenv' venv_folder = '.pyenv'
unix_user_home_directory = os.path.expanduser("~") unix_user_home_directory = os.path.expanduser("~")

View File

@@ -3,7 +3,7 @@ from ssl import SSLSocket
from datetime import datetime, timedelta from datetime import datetime, timedelta
from typing import Union from typing import Union
from core.loadConf import Config from core.loadConf import Config
from core.Model import User, Admin, Channel from core.Model import User, Admin, Channel, Clones
from core.base import Base from core.base import Base
class Irc: class Irc:
@@ -30,7 +30,7 @@ class Irc:
0: ['help', 'auth', 'copyright', 'uptime'], 0: ['help', 'auth', 'copyright', 'uptime'],
1: ['load','reload','unload', 'deauth', 'checkversion'], 1: ['load','reload','unload', 'deauth', 'checkversion'],
2: ['show_modules', 'show_timers', 'show_threads', 'show_channels', 'show_users', 'show_admins'], 2: ['show_modules', 'show_timers', 'show_threads', 'show_channels', 'show_users', 'show_admins'],
3: ['quit', 'restart','addaccess','editaccess', 'delaccess','umode'] 3: ['quit', 'restart','addaccess','editaccess', 'delaccess']
} }
# l'ensemble des commandes. # l'ensemble des commandes.
@@ -43,6 +43,7 @@ class Irc:
self.User = User(self.Base) self.User = User(self.Base)
self.Admin = Admin(self.Base) self.Admin = Admin(self.Base)
self.Channel = Channel(self.Base) self.Channel = Channel(self.Base)
self.Clones = Clones(self.Base)
self.__create_table() self.__create_table()
self.Base.create_thread(func=self.heartbeat, func_args=(self.beat, )) self.Base.create_thread(func=self.heartbeat, func_args=(self.beat, ))
@@ -1341,15 +1342,5 @@ class Irc:
(fromuser, ) (fromuser, )
) )
case 'umode':
try:
# .umode nickname +mode
nickname = str(cmd[1])
umode = str(cmd[2])
self.send2socket(f':{dnickname} SVSMODE {nickname} {umode}')
except KeyError as ke:
self.Base.logs.error(ke)
case _: case _:
pass pass

View File

@@ -9,7 +9,6 @@ class Clone():
@dataclass @dataclass
class ModConfModel: class ModConfModel:
clone_count: int
clone_nicknames: list[str] clone_nicknames: list[str]
def __init__(self, ircInstance:Irc) -> None: def __init__(self, ircInstance:Irc) -> None:
@@ -35,6 +34,8 @@ class Clone():
# Add Channel object to the module (Mandatory) # Add Channel object to the module (Mandatory)
self.Channel = ircInstance.Channel self.Channel = ircInstance.Channel
self.Clone = ircInstance.Clones
# Créer les nouvelles commandes du module # Créer les nouvelles commandes du module
self.commands_level = { self.commands_level = {
1: ['clone_connect', 'clone_join', 'clone_kill', 'clone_list'] 1: ['clone_connect', 'clone_join', 'clone_kill', 'clone_list']
@@ -97,15 +98,13 @@ class Clone():
"""### Load Module Configuration """### Load Module Configuration
""" """
try: try:
# Variable qui va contenir les options de configuration du module Defender
# Variable qui va contenir les options de configuration du module Defender # Variable qui va contenir les options de configuration du module Defender
self.ModConfig = self.ModConfModel( self.ModConfig = self.ModConfModel(
clone_count=0,
clone_nicknames=[] clone_nicknames=[]
) )
# Sync the configuration with core configuration (Mandatory) # Sync the configuration with core configuration (Mandatory)
self.Base.db_sync_core_config(self.module_name, self.ModConfig) # self.Base.db_sync_core_config(self.module_name, self.ModConfig)
return None return None
@@ -123,22 +122,23 @@ class Clone():
return None return None
def thread_create_clones(self, nickname: str, username: str, channels:list, server_port:int, ssl:bool) -> None: def thread_create_clones(self, nickname: str, username: str, channels: list, server_port: int, ssl: bool) -> None:
Connection(server_port=server_port, nickname=nickname, username=username, channels=channels, ssl=ssl) Connection(server_port=server_port, nickname=nickname, username=username, channels=channels, CloneObject=self.Clone, ssl=ssl)
return None return None
def thread_join_channels(self, channel_name: str, wait: float, clone_name:str = None): def thread_join_channels(self, channel_name: str, wait: float, clone_name:str = None):
if clone_name is None: if clone_name is None:
for clone in self.ModConfig.clone_nicknames: for clone in self.Clone.UID_CLONE_DB:
self.Irc.send2socket(f':{self.Config.SERVICE_NICKNAME} PRIVMSG {clone} :JOIN {channel_name}') self.Irc.send2socket(f':{self.Config.SERVICE_NICKNAME} PRIVMSG {clone.nickname} :JOIN {channel_name}')
time.sleep(wait) time.sleep(wait)
else: else:
for clone in self.ModConfig.clone_nicknames: for clone in self.Clone.UID_CLONE_DB:
if clone_name == clone: if clone_name == clone.nickname:
self.Irc.send2socket(f':{self.Config.SERVICE_NICKNAME} PRIVMSG {clone} :JOIN {channel_name}') self.Irc.send2socket(f':{self.Config.SERVICE_NICKNAME} PRIVMSG {clone.nickname} :JOIN {channel_name}')
time.sleep(wait)
def generate_names(self) -> tuple[str, str]: def generate_names(self) -> tuple[str, str]:
try: try:
@@ -146,13 +146,25 @@ class Clone():
nickname = fake.first_name() nickname = fake.first_name()
username = fake.last_name() username = fake.last_name()
if not nickname in self.ModConfig.clone_nicknames: if self.Clone.exists(nickname=nickname):
self.ModConfig.clone_nicknames.append(nickname)
else:
caracteres = '0123456789' caracteres = '0123456789'
randomize = ''.join(random.choice(caracteres) for _ in range(2)) randomize = ''.join(random.choice(caracteres) for _ in range(2))
nickname = nickname + str(randomize) nickname = nickname + str(randomize)
self.ModConfig.clone_nicknames.append(nickname) self.Clone.insert(
self.Clone.CloneModel(alive=True, nickname=nickname, username=username)
)
else:
self.Clone.insert(
self.Clone.CloneModel(alive=True, nickname=nickname, username=username)
)
# if not nickname in self.ModConfig.clone_nicknames:
# self.ModConfig.clone_nicknames.append(nickname)
# else:
# caracteres = '0123456789'
# randomize = ''.join(random.choice(caracteres) for _ in range(2))
# nickname = nickname + str(randomize)
# self.ModConfig.clone_nicknames.append(nickname)
return (nickname, username) return (nickname, username)
@@ -204,16 +216,24 @@ class Clone():
case 'clone_kill': case 'clone_kill':
try: try:
clone_name = str(cmd[1]) clone_name = str(cmd[1])
clone_to_kill: list[str] = []
if clone_name.lower() == 'all': if clone_name.lower() == 'all':
for clone in self.ModConfig.clone_nicknames: for clone in self.Clone.UID_CLONE_DB:
self.Irc.send2socket(f':{dnickname} PRIVMSG {clone} :KILL') self.Irc.send2socket(f':{dnickname} PRIVMSG {clone.nickname} :KILL')
self.ModConfig.clone_nicknames.remove(clone) clone_to_kill.append(clone.nickname)
clone.alive = False
for clone_nickname in clone_to_kill:
self.Clone.delete(clone_nickname)
del clone_to_kill
else: else:
for clone in self.ModConfig.clone_nicknames: if self.Clone.exists(clone_name):
if clone_name == clone: self.Irc.send2socket(f':{dnickname} PRIVMSG {clone_name} :KILL')
self.Irc.send2socket(f':{dnickname} PRIVMSG {clone} :KILL') self.Clone.kill(clone_name)
self.ModConfig.clone_nicknames.remove(clone) self.Clone.delete(clone_name)
except Exception as err: except Exception as err:
self.Logs.error(f'{err}') self.Logs.error(f'{err}')
@@ -227,9 +247,9 @@ class Clone():
clone_channel_to_join = cmd[2] clone_channel_to_join = cmd[2]
if clone_name.lower() == 'all': if clone_name.lower() == 'all':
self.Base.create_thread(self.thread_join_channels, (clone_channel_to_join, 4)) self.Base.create_thread(self.thread_join_channels, (clone_channel_to_join, 2))
else: else:
self.Base.create_thread(self.thread_join_channels, (clone_channel_to_join, 4, clone_name)) self.Base.create_thread(self.thread_join_channels, (clone_channel_to_join, 2, clone_name))
except Exception as err: except Exception as err:
self.Logs.error(f'{err}') self.Logs.error(f'{err}')
@@ -238,5 +258,5 @@ class Clone():
case 'clone_list': case 'clone_list':
for clone_name in self.ModConfig.clone_nicknames: for clone_name in self.Clone.UID_CLONE_DB:
self.Irc.send2socket(f':{dnickname} NOTICE {fromuser} :>> {clone_name}') self.Irc.send2socket(f':{dnickname} NOTICE {fromuser} :>> {clone_name.nickname} | {clone_name.username}')

View File

@@ -35,7 +35,7 @@ class Command():
# Create module commands (Mandatory) # Create module commands (Mandatory)
self.commands_level = { self.commands_level = {
1: ['join', 'part'], 1: ['join', 'part'],
2: ['owner', 'deowner', 'op', 'deop', 'halfop', 'dehalfop', 'voice', 'devoice', 'ban', 'unban','kick', 'kickban'] 2: ['owner', 'deowner', 'op', 'deop', 'halfop', 'dehalfop', 'voice', 'devoice', 'ban', 'unban','kick', 'kickban', 'umode']
} }
# Init the module # Init the module
@@ -481,3 +481,13 @@ class Command():
except IndexError as ie: except IndexError as ie:
self.Logs.error(f'{ie}') self.Logs.error(f'{ie}')
case 'umode':
try:
# .umode nickname +mode
nickname = str(cmd[1])
umode = str(cmd[2])
self.send2socket(f':{dnickname} SVSMODE {nickname} {umode}')
except KeyError as ke:
self.Base.logs.error(ke)

View File

@@ -272,14 +272,14 @@ class Defender():
return False return False
def reputation_insert(self, reputationModel: ReputationModel) -> bool: def reputation_insert(self, reputationModel: ReputationModel) -> bool:
response = False response = False
# Check if the user already exist # Check if the user already exist
for reputation in self.UID_REPUTATION_DB: for reputation in self.UID_REPUTATION_DB:
if reputation.uid == reputationModel.uid: if reputation.uid == reputationModel.uid:
return response return response
self.UID_REPUTATION_DB.append(reputationModel) self.UID_REPUTATION_DB.append(reputationModel)
self.Logs.debug(f'Reputation inserted: {reputationModel}') self.Logs.debug(f'Reputation inserted: {reputationModel}')
response = True response = True