Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SP-CRA security solutions #331

Merged
merged 20 commits into from
Nov 22, 2023
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
6706600
Added 2_0 folder for MS 2.0
SelinaTII Sep 18, 2023
0525b29
Added 2_0 folder for MS 2.0
SelinaTII Sep 18, 2023
445b80d
Added folder for jamming
SelinaTII Sep 19, 2023
a54694e
Added the script performing Signal Processing assisted Authentication…
anshul-tii Oct 2, 2023
95b6360
Improved script with bug fixes and resolving the issue of infinite ex…
anshul-tii Nov 6, 2023
58f7cca
Functional and regression test cases for the Signal processing assist…
anshul-tii Nov 6, 2023
fceb884
Adding Basic performance test Cases for the SP-CRA Implementation
anshul-tii Nov 6, 2023
8f21dd2
Adding relevant security test cases for SP-CRA Implementation
anshul-tii Nov 6, 2023
02ca7a7
Minor Comments formating
anshul-tii Nov 6, 2023
474b17f
Added following changes: sendall() is used instead of send, fix the …
anshul-tii Nov 8, 2023
d2aba4e
Resolved space issue to maintian uniformity in code pointed by Mika
anshul-tii Nov 8, 2023
2bcd76d
Merge branch 'develop' into PHYSEC_SOLN
anshul-tii Nov 9, 2023
128d1c4
Modified the script to comply with the main script. THe entry point o…
anshul-tii Nov 17, 2023
c394ef1
main.py script acting as an entry point for all securiy features. THe…
anshul-tii Nov 17, 2023
36a7899
updating branch
anshul-tii Nov 17, 2023
0e75f1e
RSS Authentication Scripts
anshul-tii Nov 21, 2023
8fde56c
Modified the RSS_Auth Class implementation to do away with passing s…
anshul-tii Nov 21, 2023
ba1beff
Modified the main.py script and the feature.yaml file to consider RSS…
anshul-tii Nov 21, 2023
1193a9d
Added a debug flag option to control the disply of authentication tab…
anshul-tii Nov 21, 2023
afc25c7
Making all feature disbaled by default in accordance to Sebastien com…
anshul-tii Nov 22, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions modules/sc-mesh-secure-deployment/src/2_0/features.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
PHY: true
IDS: false
jamming: false

Original file line number Diff line number Diff line change
Expand Up @@ -6,23 +6,35 @@
import logging
import numpy as np
import os
import queue
from getmac import get_mac_address
from mat4py import loadmat

class PHYCRA:
def __init__(self):
log_filename = '/tmp/server_log.txt' # Set the log file location to /tmp/

# Clear the server log at the start of each session
# Initialization code
log_filename = '/tmp/server_log.log' # Log file location
txt_log_filename = '/tmp/server_log.txt'
# Clear server log at the start of each session
if os.path.exists(log_filename):
os.remove(log_filename)
if os.path.exists(txt_log_filename):
os.remove(txt_log_filename)


logging.basicConfig(level=logging.INFO, filename=log_filename, filemode='w',
format='%(asctime)s - %(levelname)s - %(message)s')
logging.info("Server initialized")

# Server setup

# Determine the directory in which this script is located
script_dir = os.path.dirname(os.path.realpath(__file__))

# Use the script's directory to construct the path to the .mat file
mat_file_path = os.path.join(script_dir, 'ACF_Table.mat')
try:
DataServer = loadmat('ACF_Table.mat')
DataServer = loadmat(mat_file_path)
self.acf = np.array(DataServer['y_C']).transpose()
self.SERVER = self.get_server_ip()
self.BROADCAST_PORT = 5051
Expand All @@ -35,37 +47,58 @@ def __init__(self):

# Client setup
try:
DataClient = loadmat('ACF_Table.mat')
DataClient = loadmat(mat_file_path)
self.acf_client = np.array(DataClient['y_C']).transpose()
logging.info("Client setup completed successfully")
except Exception as e:
logging.error("Error during client setup: %s", e)
# Create an event to signal when 5 minutes have passed

# Initialize threads but do not start them
self.server_thread = None
self.listen_thread = None
self.broadcast_thread = None
self.results_queue = {'Pass': [], 'Fail': []}
#self.all_attempts = set() # Set to track all unique attempts

# Create an event for graceful shutdown
self.stop_event = threading.Event()

# Start server and client functionalities
def start(self):
"""Starts the server and client functionalities in separate threads."""
try:
self.server_thread = threading.Thread(target=self.server_start)
self.server_thread.start()
logging.info("Server thread started")
time.sleep(2)

self.listen_thread = threading.Thread(target=self.listen_for_broadcast)
self.listen_thread.start()
logging.info("Broadcast listening thread started")
except Exception as e:
logging.error("Error during server/client threads initialization: %s", e)

# Start a timer to stop the server and broadcasting after 5 minutes
timer = threading.Timer(60, self.stop_event.set)
timer.start()
logging.info("Server shutdown timer started")

# SERVER FUNCTIONS
def stop(self):
"""Stops all running threads and closes sockets."""
self.stop_event.set()

if self.server_thread and self.server_thread.is_alive():
self.server_thread.join()
if self.listen_thread and self.listen_thread.is_alive():
self.listen_thread.join()
if self.broadcast_thread and self.broadcast_thread.is_alive():
self.broadcast_thread.join()

if hasattr(self, 'server') and self.server:
self.server.close()
if hasattr(self, 'listen_sock') and self.listen_sock:
self.listen_sock.close()
logging.info("PHYCRA stopped successfully")



def log_authentication(self, node_ip, mac_address, result):
timestamp = time.strftime("%Y-%m-%d %H:%M:%S")
log_entry = f"{timestamp}\t{node_ip}\t{mac_address}\t{result}\n"
with open("server_log.txt", "a") as log_file:
with open("/tmp/server_log.txt", "a") as log_file:
log_file.write(log_entry)


Expand All @@ -74,11 +107,15 @@ def display_table(self):
print("+---------------------+---------------+-------------------+---------------------------+")
print("| Time | Node IP | MAC Address | Authentication Result |")
print("+---------------------+---------------+-------------------+---------------------------+")
anshul-tii marked this conversation as resolved.
Show resolved Hide resolved
with open("server_log.txt", "r") as log_file:
for line in log_file:
timestamp, node_ip, mac_address, result = line.strip().split("\t")
formatted_line = f"| {timestamp:<19} | {node_ip:<12} | {mac_address:<15} | {result:<23} |"
print(formatted_line)
log_file_path = "/tmp/server_log.txt"
if os.path.exists(log_file_path):
with open(log_file_path, "r") as log_file:
for line in log_file:
timestamp, node_ip, mac_address, result = line.strip().split("\t")
formatted_line = f"| {timestamp:<19} | {node_ip:<12} | {mac_address:<15} | {result:<23} |"
print(formatted_line)
else:
print("No entries found.")
print("+---------------------+---------------+-------------------+---------------------------+")


Expand Down Expand Up @@ -109,10 +146,12 @@ def handle_client(self, conn, addr):
print("PASS: Authentication successful")
logging.info("Authentication successful for %s", addr)
self.log_authentication(addr[0], mac_address, "Success")
self.results_queue['Pass'].append((addr[0], mac_address))
else:
print('FAIL: Authentication failed')
logging.warning("Authentication failed for %s", addr)
self.log_authentication(addr[0], mac_address, "Access denied")
self.results_queue['Fail'].append((addr[0], mac_address))

print("\nUpdated Table:")
self.display_table()
Expand All @@ -121,7 +160,15 @@ def handle_client(self, conn, addr):
finally:
conn.close()


def get_result(self):
"""
Retrieve and clear the latest results from the results queue.
"""
current_results = {k: list(v) for k, v in self.results_queue.items()}
self.results_queue = {'Pass': [], 'Fail': []} # Reset for next batch
return current_results


def server_start(self):
try:
self.server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
Expand Down Expand Up @@ -158,7 +205,7 @@ def broadcast_status(self):
while not self.stop_event.is_set(): # Check if the stop event is set
msg = "SERVER_AVAILABLE"
broadcast_sock.sendto(msg.encode(), ('<broadcast>', self.BROADCAST_PORT))
time.sleep(30)
time.sleep(20)
except Exception as e:
logging.error("Error during broadcast: %s", e)
finally:
Expand Down Expand Up @@ -219,7 +266,7 @@ def listen_for_broadcast(self):
finally:
self.listen_sock.close()
logging.info("Stopped listening for broadcasts")


# Common Functions
def get_server_ip(self):
Expand All @@ -233,10 +280,3 @@ def get_server_ip(self):
s.close()
return IP

if __name__ == "__main__":
phycra_instance = PHYCRA()
time.sleep(60)
phycra_instance.stop_event.set()
phycra_instance.server_thread.join()
phycra_instance.listen_thread.join()
phycra_instance.broadcast_thread.join()
92 changes: 92 additions & 0 deletions modules/sc-mesh-secure-deployment/src/2_0/main.py
100644 → 100755
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
import yaml
import threading
import time

# Import classes for features
from features.PHY.PHY_CRA_scripts.SP_CRA_mainDE1 import PHYCRA
# from features.IDS.IDS import IDS
# from features.jamming.jamming import Jamming

def launch_PHY():
# Place holder to launch PHY
phycra = PHYCRA()
phycra.start()
return phycra

def launch_IDS():
# Place holder to launch IDS
# Currently, this function does nothing
pass

def launch_jamming():
# Place holder to launch jamming
# Currently, this function does nothing
pass

def stop_PHY(phycra):
phycra.stop()

def stop_jamming(jamming):
jamming.stop()

def stop_IDS(ids):
ids.stop()

def launch_decision_engine(sensors):
# Place holder to launch decision engine
collected_data = {}
# decision_engine = DecisionEngine(sensors)

# Periodically gets results from security sensors
while True:
print("Executing decision engine with collected data: ")
for sensor_name in sensors:
sensor_data = sensors[sensor_name].get_result()
if sensor_data: # Check if there is new data
collected_data[sensor_name] = sensor_data
else:
collected_data[sensor_name] = {'Pass': [], 'Fail': []} # Default to empty lists if no new data

for sensor_name in collected_data:
print(sensor_name)
print(collected_data)


# Process data with the decision engine
#decisions = decision_engine.make_decision(collected_data)

# Place holder to call quarantine/ MBA if necessary

time.sleep(60) # Period can be adjusted



def readfile():
with open("features.yaml", "r") as stream:
try:
return yaml.safe_load(stream)
except yaml.YAMLError as exc:
print(exc)
return None

def initialize(feature):
if feature == 'PHY':
phycra = launch_PHY()
sensors[feature] = phycra
if feature == 'IDS':
ids = launch_IDS()
sensors[feature] = ids
if feature == 'jamming':
launch_jamming()

if __name__ == "__main__":
features = readfile()
sensors = {} # Stores sensor_name: sensor_object for each sensor/ feature that publishes results for decision engine

# Start features that are true in features.yaml
for feature in features:
if features[feature]:
initialize(feature)

# Call decision engine
launch_decision_engine(sensors)
Loading