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:
record.uids.append(user)
# Supprimer les doublons
# Supprimer les doublons
del_duplicates = list(set(record.uids))
record.uids = del_duplicates
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}')
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
from ssl import SSLSocket
from core.loadConf import Config
from core.Model import Clones
from core.base import Base
from typing import Union
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.Base = Base(self.Config)
self.IrcSocket: Union[socket.socket, SSLSocket] = None
self.signal: bool = True
self.nickname = nickname
self.username = username
self.channels:list[str] = channels
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.send_connection_information_to_server(self.IrcSocket)
@@ -126,7 +132,6 @@ class Connection:
break
self.parser(data)
except ssl.SSLEOFError as soe:
self.Base.logs.error(f"SSLEOFError __connect_to_irc: {soe} - {data}")
self.signal = False
@@ -156,6 +161,7 @@ class Connection:
try:
for data in cmd:
response = data.decode(self.CHARSET[0]).split()
self.signal = self.currentCloneObject.alive
# print(response)
match response[0]:
@@ -174,13 +180,15 @@ class Connection:
self.send2socket(f"JOIN {channel}")
return None
case 'PRIVMSG':
self.Base.logs.debug(response)
self.Base.logs.debug(f'{self.currentCloneObject.nickname} - {self.currentCloneObject.alive}')
fullname = str(response[0]).replace(':', '')
nickname = fullname.split('!')[0].replace(':','')
if nickname == self.Config.SERVICE_NICKNAME:
command = str(response[3]).replace(':','')
if command == 'KILL':
self.send2socket(f'QUIT :Thanks and goodbye')
self.signal = False
self.signal = self.currentCloneObject.alive
if command == 'JOIN':
channel_to_join = str(response[4])
self.send2socket(f"JOIN {channel_to_join}")
@@ -193,7 +201,6 @@ class Connection:
response = data.decode(self.CHARSET[1],'replace').split()
except AssertionError as ae:
self.Base.logs.error(f"Assertion error : {ae}")
pass
def __ssl_context(self) -> ssl.SSLContext:
ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)

View File

@@ -27,6 +27,9 @@ class Install:
def __init__(self) -> None:
self.set_configuration()
if self.skip_install:
return None
if not self.check_python_version():
# Tester si c'est la bonne version de python
@@ -45,6 +48,13 @@ class Install:
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()
venv_folder = '.pyenv'
unix_user_home_directory = os.path.expanduser("~")

View File

@@ -3,7 +3,7 @@ from ssl import SSLSocket
from datetime import datetime, timedelta
from typing import Union
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
class Irc:
@@ -30,7 +30,7 @@ class Irc:
0: ['help', 'auth', 'copyright', 'uptime'],
1: ['load','reload','unload', 'deauth', 'checkversion'],
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.
@@ -43,6 +43,7 @@ class Irc:
self.User = User(self.Base)
self.Admin = Admin(self.Base)
self.Channel = Channel(self.Base)
self.Clones = Clones(self.Base)
self.__create_table()
self.Base.create_thread(func=self.heartbeat, func_args=(self.beat, ))
@@ -1341,15 +1342,5 @@ class Irc:
(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 _:
pass

View File

@@ -9,7 +9,6 @@ class Clone():
@dataclass
class ModConfModel:
clone_count: int
clone_nicknames: list[str]
def __init__(self, ircInstance:Irc) -> None:
@@ -35,6 +34,8 @@ class Clone():
# Add Channel object to the module (Mandatory)
self.Channel = ircInstance.Channel
self.Clone = ircInstance.Clones
# Créer les nouvelles commandes du module
self.commands_level = {
1: ['clone_connect', 'clone_join', 'clone_kill', 'clone_list']
@@ -97,15 +98,13 @@ class Clone():
"""### Load Module Configuration
"""
try:
# 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(
clone_count=0,
clone_nicknames=[]
)
# 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
@@ -123,22 +122,23 @@ class Clone():
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
def thread_join_channels(self, channel_name: str, wait: float, clone_name:str = None):
if clone_name is None:
for clone in self.ModConfig.clone_nicknames:
self.Irc.send2socket(f':{self.Config.SERVICE_NICKNAME} PRIVMSG {clone} :JOIN {channel_name}')
for clone in self.Clone.UID_CLONE_DB:
self.Irc.send2socket(f':{self.Config.SERVICE_NICKNAME} PRIVMSG {clone.nickname} :JOIN {channel_name}')
time.sleep(wait)
else:
for clone in self.ModConfig.clone_nicknames:
if clone_name == clone:
self.Irc.send2socket(f':{self.Config.SERVICE_NICKNAME} PRIVMSG {clone} :JOIN {channel_name}')
for clone in self.Clone.UID_CLONE_DB:
if clone_name == clone.nickname:
self.Irc.send2socket(f':{self.Config.SERVICE_NICKNAME} PRIVMSG {clone.nickname} :JOIN {channel_name}')
time.sleep(wait)
def generate_names(self) -> tuple[str, str]:
try:
@@ -146,13 +146,25 @@ class Clone():
nickname = fake.first_name()
username = fake.last_name()
if not nickname in self.ModConfig.clone_nicknames:
self.ModConfig.clone_nicknames.append(nickname)
else:
if self.Clone.exists(nickname=nickname):
caracteres = '0123456789'
randomize = ''.join(random.choice(caracteres) for _ in range(2))
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)
@@ -204,16 +216,24 @@ class Clone():
case 'clone_kill':
try:
clone_name = str(cmd[1])
clone_to_kill: list[str] = []
if clone_name.lower() == 'all':
for clone in self.ModConfig.clone_nicknames:
self.Irc.send2socket(f':{dnickname} PRIVMSG {clone} :KILL')
self.ModConfig.clone_nicknames.remove(clone)
for clone in self.Clone.UID_CLONE_DB:
self.Irc.send2socket(f':{dnickname} PRIVMSG {clone.nickname} :KILL')
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:
for clone in self.ModConfig.clone_nicknames:
if clone_name == clone:
self.Irc.send2socket(f':{dnickname} PRIVMSG {clone} :KILL')
self.ModConfig.clone_nicknames.remove(clone)
if self.Clone.exists(clone_name):
self.Irc.send2socket(f':{dnickname} PRIVMSG {clone_name} :KILL')
self.Clone.kill(clone_name)
self.Clone.delete(clone_name)
except Exception as err:
self.Logs.error(f'{err}')
@@ -227,9 +247,9 @@ class Clone():
clone_channel_to_join = cmd[2]
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:
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:
self.Logs.error(f'{err}')
@@ -238,5 +258,5 @@ class Clone():
case 'clone_list':
for clone_name in self.ModConfig.clone_nicknames:
self.Irc.send2socket(f':{dnickname} NOTICE {fromuser} :>> {clone_name}')
for clone_name in self.Clone.UID_CLONE_DB:
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)
self.commands_level = {
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
@@ -481,3 +481,13 @@ class Command():
except IndexError as 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
def reputation_insert(self, reputationModel: ReputationModel) -> bool:
response = False
# Check if the user already exist
for reputation in self.UID_REPUTATION_DB:
if reputation.uid == reputationModel.uid:
return response
self.UID_REPUTATION_DB.append(reputationModel)
self.Logs.debug(f'Reputation inserted: {reputationModel}')
response = True