Compare commits

..

No commits in common. 'b2395105276b40290efa6c4a8e64b9c647d15b7a' and '406438b2be2baaa3e5626c38bfbfb46a0b230d83' have entirely different histories.

@ -6,11 +6,6 @@ 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 = "",""
@ -120,5 +115,11 @@ 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)

@ -2,64 +2,44 @@ 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]))
# 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.
if verifRegle(co):
co.commit()
else:
print("A rule has been violated. The system is endangered. The database hasn't been updated.")
# 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()
co.rollback()
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()

@ -1,22 +1,15 @@
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=[]
@ -25,10 +18,5 @@ 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.

Loading…
Cancel
Save