Bug fixes and login additions
This commit is contained in:
@@ -1,17 +1,60 @@
|
|||||||
import time
|
import time
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
import hashlib
|
||||||
|
import os
|
||||||
|
|
||||||
# Setup paths
|
# Setup paths
|
||||||
base_path = Path(__file__).parent
|
base_path = Path(__file__).parent
|
||||||
|
|
||||||
req_path = base_path / "requests"
|
req_path = base_path / "requests"
|
||||||
user_path = base_path / "users"
|
user_path = base_path / "users"
|
||||||
chat_path = base_path / "single_chats"
|
chat_path = base_path / "single_chats"
|
||||||
|
status_path = base_path / "requests" / "status"
|
||||||
|
|
||||||
|
|
||||||
req_path.mkdir(exist_ok=True)
|
req_path.mkdir(exist_ok=True)
|
||||||
|
|
||||||
print("Server online. Monitoring requests...")
|
print("Server online. Monitoring requests...")
|
||||||
|
|
||||||
|
def hash_password(password: str) -> str:
|
||||||
|
# Generate a random 16-byte salt
|
||||||
|
salt = os.urandom(16)
|
||||||
|
|
||||||
|
# Hash the password using scrypt
|
||||||
|
# n=16384 (CPU/Memory cost), r=8 (Block size), p=1 (Parallelization)
|
||||||
|
password_hash = hashlib.scrypt(
|
||||||
|
password.encode(),
|
||||||
|
salt=salt,
|
||||||
|
n=16384,
|
||||||
|
r=8,
|
||||||
|
p=1
|
||||||
|
)
|
||||||
|
|
||||||
|
# Store the salt and hash together as hex strings so they can be saved in a file
|
||||||
|
return f"{salt.hex()}:{password_hash.hex()}"
|
||||||
|
|
||||||
|
def verify_password(stored_full_hash: str, provided_password: str) -> bool:
|
||||||
|
try:
|
||||||
|
# Split the stored string back into the salt and the hash
|
||||||
|
salt_hex, original_hash_hex = stored_full_hash.split(":")
|
||||||
|
salt = bytes.fromhex(salt_hex)
|
||||||
|
original_hash = bytes.fromhex(original_hash_hex)
|
||||||
|
|
||||||
|
# Hash the provided password using the same salt and parameters
|
||||||
|
new_hash = hashlib.scrypt(
|
||||||
|
provided_password.encode(),
|
||||||
|
salt=salt,
|
||||||
|
n=16384,
|
||||||
|
r=8,
|
||||||
|
p=1
|
||||||
|
)
|
||||||
|
|
||||||
|
# Use hmac.compare_digest to prevent "timing attacks"
|
||||||
|
import hmac
|
||||||
|
return hmac.compare_digest(new_hash, original_hash)
|
||||||
|
except Exception:
|
||||||
|
return False
|
||||||
|
|
||||||
while True:
|
while True:
|
||||||
# 1. Grab everything in the folder
|
# 1. Grab everything in the folder
|
||||||
# .iterdir() is efficient for scanning
|
# .iterdir() is efficient for scanning
|
||||||
@@ -39,27 +82,35 @@ while True:
|
|||||||
parts = content.split(":", 2)
|
parts = content.split(":", 2)
|
||||||
|
|
||||||
# FAILSAFE 3: Check if we have enough parts (Command:User:Pass)
|
# FAILSAFE 3: Check if we have enough parts (Command:User:Pass)
|
||||||
if len(parts) < 3:
|
if len(parts) != 3:
|
||||||
print(f"Incomplete data in {file_path.name}, Deleting.")
|
print(f"Corrupted data in {file_path.name}, Deleting.")
|
||||||
# TODO Make failed request file
|
file_path.rename(status_path / f"fail_{file_path.name}")
|
||||||
file_path.unlink()
|
|
||||||
continue
|
continue
|
||||||
|
|
||||||
command, user, data = parts
|
command, user, data = parts
|
||||||
|
|
||||||
|
# Validity check for one last time
|
||||||
if not command.isalnum() or not user.isalnum() or not data.isalnum():
|
if not command.isalnum() or not user.isalnum() or not data.isalnum():
|
||||||
print(f"Invalid parameters in {file_path.name}, Deleting.")
|
print(f"Invalid parameters in {file_path.name}, Deleting.")
|
||||||
# TODO Make failed request file
|
file_path.rename(status_path / f"fail_{file_path.name}")
|
||||||
continue
|
continue
|
||||||
print(f"Processing {command} for {user}...")
|
print(f"Processing {command} for {user}...")
|
||||||
|
|
||||||
if command == "LOGIN":
|
if command == "LOGIN":
|
||||||
|
username_path = user_path / f"{user}"
|
||||||
# TODO
|
# TODO
|
||||||
#1. check if user exists as a folder
|
if username_path.is_dir():
|
||||||
#2. hash password and check against user hash.txt if exist
|
with open(username_path / "pass.txt", "r") as f:
|
||||||
#3. Make success request file
|
password = f.readline().strip()
|
||||||
#4. Fail file as try/except
|
|
||||||
pass
|
# Now password is the entire sequence
|
||||||
if command == "CREATEUSER":
|
if verify_password(password, data):
|
||||||
|
file_path.rename(status_path / f"success_{file_path.name}")
|
||||||
|
# move and rename to success_filename.txt in status
|
||||||
|
else:
|
||||||
|
file_path.rename(status_path / f"fail_{file_path.name}")
|
||||||
|
|
||||||
|
elif command == "CREATEUSER":
|
||||||
# TODO
|
# TODO
|
||||||
#1. Make a new folder with the name
|
#1. Make a new folder with the name
|
||||||
#2. Hash password and store in hash.txt
|
#2. Hash password and store in hash.txt
|
||||||
@@ -68,8 +119,8 @@ while True:
|
|||||||
#5. Fail file as try/except
|
#5. Fail file as try/except
|
||||||
pass
|
pass
|
||||||
|
|
||||||
# 4. Clean up: Delete the request after successful processing
|
elif file_path.is_file():
|
||||||
file_path.unlink()
|
file_path.unlink()
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
# FAILSAFE 4: Catch-all for weird errors (like file being locked)
|
# FAILSAFE 4: Catch-all for weird errors (like file being locked)
|
||||||
|
|||||||
Reference in New Issue
Block a user