From 46d4e201df2b6c434358365db1ef1f5ab94a738e Mon Sep 17 00:00:00 2001 From: Paul SQUIZZATO Date: Wed, 29 Mar 2023 10:36:12 +0200 Subject: [PATCH] Commentaires + docu sur les .py --- src/decoderOutdated.py | 11 +++++------ src/ecritureBDD.py | 28 ++++++++++++++++++++++++---- src/triPacket.py | 12 ++++++++++++ 3 files changed, 41 insertions(+), 10 deletions(-) diff --git a/src/decoderOutdated.py b/src/decoderOutdated.py index d0797cf..abfe35f 100644 --- a/src/decoderOutdated.py +++ b/src/decoderOutdated.py @@ -6,6 +6,11 @@ import scapy.contrib.modbus as mb from triPacket import triPacket import getpass +# ======================================================================================== +# This decoder is outdated, as it uses a string parser on the packets given by scapy. +# Instead of this script, please use decoderMain.py. +# ======================================================================================== + def decode(pkt): prt=0 addr,value = "","" @@ -115,11 +120,5 @@ if not db_user: db_password = getpass.getpass('user password : ') connec=[db_host,db_name,db_user,db_password] -# si register 5 = 55 et coil 3 = 1 et coil 12 = 0 : -# ecriture sur le registre 8 à 72 ou coil 9 à 1 impossibles -# if ['r',5,55] and ['c',3,1] and ['c',12,0] and ecriture ['r',8,72]: - #bloquer ecriture -# ecrire registre 5 72,4,4,55,4 - scapy.sniff(iface="lo", prn=decode) diff --git a/src/ecritureBDD.py b/src/ecritureBDD.py index 943a278..2074d1e 100644 --- a/src/ecritureBDD.py +++ b/src/ecritureBDD.py @@ -2,44 +2,64 @@ import psycopg2 as psy import regles def verifRegle(co): + ''' verifRegle takes a connection to a database, from which it'll go through the data in the current transaction + to see if the data correlate to a possible rule violation. + ''' cur=co.cursor() cur.execute('''SELECT type,addresse,valeur FROM Status ORDER BY type,addresse;''') res=cur.fetchall() + # res contains all the data from the current transaction. The entirety of the status table is loaded. dataState={} for row in res: dataState[(row[0],int(row[1]))]=int(row[2]) + # the dictionnary dataState is a litteral representation of the database, with the key being a tuple of the address and the type of data, + # dataState's values are the values of the statuses. listRules=regles.getRegles() + # listRules contains all the rules created in regles.py, and getRegles is called to get a copy of the rules' list. for rule in listRules: + # we check each rule one by one, to see if they aren't violated ruleWarning=0 condition=len(rule[0]) for i in rule[0]: if (i[0],i[1]) in dataState: if dataState[(i[0],i[1])]==i[2]: ruleWarning+=1 + # we first verify if the conditions aren't violated. if ruleWarning>=condition: + # if all the conditions of the rule are matched, we check to see if the request tries to update the forbidden value. if (rule[1][0],rule[1][1]) in dataState: if dataState[(rule[1][0],rule[1][1])]==rule[1][2]: return False + # The boolean False is returned in the case where one rule is violated. return True + # If True is returned, it's because there's no rule that is violated, so the request isn't problematic for the system. def ecritureBDD(lStatus,connec): + ''' ecritureBDD is the function that is called to upsert (insert or update) the values of the status given in lStatus + connec contains the information needed to create a connection to the database + ''' co = None try: co = psy.connect(host=connec[0],database=connec[1],user=connec[2],password=connec[3]) + # the connection to the database is now created in co. cur = co.cursor() + # cur is a cursor on the connection to the database, it lets us perform actions on co's transaction. for i in lStatus: cur.execute("INSERT INTO Status VALUES (%s,%s,%s ) ON CONFLICT (addresse,type) DO UPDATE SET valeur=%s;",(i[1],i[0],i[2],i[2])) - if verifRegle(co): - co.commit() - else: + # each statuses in lStatus is now upserted in the database on the current transaction, until commited, they aren't actually inside the database. + if verifRegle(co)!=True: + # verifRegle is executed with the current connection, so it has access to the transaction in order to verify if rules are violated. print("A rule has been violated. The system is endangered. The database hasn't been updated.") - co.rollback() + # A message is shown to the user to make him aware of the rule that is violated. + # a co.rollback() would be called if we managed to block the client request in order to prevent the server to be updated. + co.commit() cur.close() except(Exception,psy.DatabaseError) as error: print(error) + # In case of an exception, like the failure of the creation of the connection, details are shown to tell the user about it. finally: if co is not None: co.close() diff --git a/src/triPacket.py b/src/triPacket.py index f84d815..5f8a7e1 100644 --- a/src/triPacket.py +++ b/src/triPacket.py @@ -1,15 +1,22 @@ from ecritureBDD import ecritureBDD def decoupePacket(lPkt): + ''' decoupePacket is a recursive function that takes a list as an argument. + Its purpose is to create lists that shows the updated statuses from the modbus client's requests following the database format. + ''' if type(lPkt)!=list: + # If the list of statuses isn't a list, nothing should be put inside the database. print('pas liste') return if len(lPkt)==0: + # If the list is empty, nothing should be put inside the database as well. print('liste vide') return if len(lPkt)==1: + # If the list has only one element, it is probably another list inside, that's why we call decoupePacket again. return decoupePacket(lPkt[0]) if len(lPkt)==3 and type(lPkt[0])==str: + # If the list has a size of 3, and it's first element is a string type, we probably have the status we need to use. return [[lPkt[0],int(lPkt[1]),int(lPkt[2])]] else: l=[] @@ -18,5 +25,10 @@ def decoupePacket(lPkt): return l def triPacket(lPkt,connec): + ''' + triPacket takes the list of statuses obtained from the client's request and the information needed to connect to the database. + ''' lNettoyee=decoupePacket(lPkt) + # decoupePacket is called in order to create a better structured list of statuses. ecritureBDD(lNettoyee,connec) + # ecritureBDD is now called to update the values inside the database.