god i am done with this program
This commit is contained in:
Binary file not shown.
Binary file not shown.
@@ -2,7 +2,7 @@ from flask import Flask, request, render_template, redirect, url_for, session, s
|
||||
from flask_talisman import Talisman
|
||||
from functools import wraps
|
||||
import os
|
||||
from security import validate_user
|
||||
from security import validate_user, is_ip_locked
|
||||
from data_handler import save_link, save_file, retrieve_uploads, handle_download, get_file_path
|
||||
from datetime import datetime
|
||||
from zipfile import ZipFile
|
||||
@@ -36,11 +36,21 @@ def login_required(f):
|
||||
|
||||
@app.before_request
|
||||
def ensure_login():
|
||||
if 'username' not in session and request.endpoint not in ('login', 'static'):
|
||||
ip_address = request.remote_addr
|
||||
|
||||
# Check if the IP is locked and redirect to lockout if it is
|
||||
if is_ip_locked(ip_address) and request.endpoint != 'lockout':
|
||||
return redirect(url_for('lockout'))
|
||||
|
||||
if 'username' not in session and request.endpoint not in ('login', 'static', 'lockout'):
|
||||
return redirect(url_for('login'))
|
||||
elif request.endpoint == 'login' and 'username' in session:
|
||||
session.clear()
|
||||
|
||||
@app.route('/lockout')
|
||||
def lockout():
|
||||
return render_template("lockout.html")
|
||||
|
||||
@app.route('/')
|
||||
@login_required
|
||||
def index():
|
||||
@@ -48,6 +58,12 @@ def index():
|
||||
|
||||
@app.route('/login', methods=['GET', 'POST'])
|
||||
def login():
|
||||
ip_address = request.remote_addr
|
||||
|
||||
# Check if the IP is locked out
|
||||
if is_ip_locked(ip_address):
|
||||
return redirect(url_for('lockout'))
|
||||
|
||||
if request.method == 'POST':
|
||||
username = request.form['username']
|
||||
password = request.form['password']
|
||||
@@ -77,14 +93,18 @@ def upload_link():
|
||||
@app.route('/upload/files', methods=['POST'])
|
||||
@login_required
|
||||
def upload_files():
|
||||
if 'files' not in request.files:
|
||||
# Check if the field name 'files[]' is present in the request
|
||||
if 'files[]' not in request.files:
|
||||
return redirect(url_for('index'))
|
||||
|
||||
files = request.files.getlist('files')
|
||||
# Retrieve the list of files with 'files[]'
|
||||
files = request.files.getlist('files[]')
|
||||
uploader = session['username']
|
||||
|
||||
# Save each file
|
||||
for file in files:
|
||||
save_file(uploader, file)
|
||||
if file: # Check if a file was actually selected
|
||||
save_file(uploader, file)
|
||||
|
||||
return redirect(url_for('index'))
|
||||
|
||||
|
||||
@@ -99,8 +99,14 @@ def reset_login_attempts(username):
|
||||
|
||||
def increment_login_attempts(username):
|
||||
with closing(sqlite3.connect(DATABASE)) as conn, conn, closing(conn.cursor()) as c:
|
||||
c.execute('UPDATE users SET login_attempts = login_attempts + 1 WHERE username = ?', (username,))
|
||||
conn.commit()
|
||||
if username:
|
||||
c.execute('UPDATE users SET login_attempts = login_attempts + 1 WHERE username = ?', (username,))
|
||||
c.execute('SELECT login_attempts FROM users WHERE username = ?', (username,))
|
||||
login_attempts = c.fetchone()[0]
|
||||
conn.commit()
|
||||
return login_attempts
|
||||
else:
|
||||
return None
|
||||
|
||||
def add_upload(uploader, file_type, content):
|
||||
with closing(sqlite3.connect(DATABASE)) as conn, conn, closing(conn.cursor()) as c:
|
||||
|
||||
39
server/security.add.py
Normal file
39
server/security.add.py
Normal file
@@ -0,0 +1,39 @@
|
||||
def validate_user(username, password):
|
||||
ip_address = request.remote_addr
|
||||
|
||||
# Check if the IP is locked
|
||||
if is_ip_locked(ip_address):
|
||||
return False, "You have been locked out."
|
||||
|
||||
user_data = get_user(username)
|
||||
if not user_data:
|
||||
increment_login_attempts(None) # Increment failed attempts for any non-existent username attempt
|
||||
|
||||
# Check if IP should be locked
|
||||
attempts = increment_login_attempts(None)
|
||||
if attempts >= MAX_ATTEMPTS:
|
||||
lock_ip(ip_address)
|
||||
return False, "Maximum login attempts exceeded. You have been locked out."
|
||||
|
||||
remaining_attempts = MAX_ATTEMPTS - attempts
|
||||
return False, f"User does not exist. {remaining_attempts} attempt(s) remaining."
|
||||
|
||||
stored_password, salt, login_attempts = user_data
|
||||
|
||||
# Check if the maximum login attempts have been reached
|
||||
if login_attempts >= MAX_ATTEMPTS:
|
||||
lock_ip(ip_address)
|
||||
return False, "Maximum login attempts exceeded. You have been locked out."
|
||||
|
||||
hashed_password = hash_password(password, salt)
|
||||
if hashed_password == stored_password:
|
||||
reset_login_attempts(username)
|
||||
return True, "Login successful."
|
||||
else:
|
||||
increment_login_attempts(username)
|
||||
if login_attempts + 1 >= MAX_ATTEMPTS:
|
||||
lock_ip(ip_address)
|
||||
return False, "Maximum login attempts exceeded. You have been locked out."
|
||||
|
||||
remaining_attempts = MAX_ATTEMPTS - login_attempts - 1
|
||||
return False, f"Invalid credentials. {remaining_attempts} attempt(s) remaining."
|
||||
@@ -1,9 +1,16 @@
|
||||
import os # Import for generating random salts
|
||||
import os
|
||||
import hashlib
|
||||
from flask import request
|
||||
from db_setup import get_user, increment_login_attempts, reset_login_attempts
|
||||
|
||||
MAX_ATTEMPTS = 3
|
||||
LOCKOUT_FILE = "locked_ips.txt"
|
||||
FAILED_ATTEMPTS = {}
|
||||
|
||||
# Ensure the locked_ips.txt file exists
|
||||
if not os.path.exists(LOCKOUT_FILE):
|
||||
with open(LOCKOUT_FILE, 'w') as f:
|
||||
pass
|
||||
|
||||
def generate_salt():
|
||||
"""
|
||||
@@ -12,39 +19,68 @@ def generate_salt():
|
||||
return os.urandom(16)
|
||||
|
||||
def hash_password(password, salt):
|
||||
"""
|
||||
Hashes the password with the provided salt using SHA-256.
|
||||
"""
|
||||
# Convert the salt to bytes if it's a string
|
||||
if isinstance(salt, str):
|
||||
salt = salt.encode()
|
||||
return hashlib.sha256(salt + password.encode()).hexdigest()
|
||||
|
||||
def is_ip_locked(ip):
|
||||
"""
|
||||
Checks if the IP address is in the lockout list.
|
||||
"""
|
||||
if os.path.exists(LOCKOUT_FILE):
|
||||
with open(LOCKOUT_FILE, 'r') as f:
|
||||
locked_ips = f.read().splitlines()
|
||||
return ip in locked_ips
|
||||
return False
|
||||
|
||||
def lock_ip(ip):
|
||||
"""
|
||||
Adds an IP address to the lockout list.
|
||||
"""
|
||||
with open(LOCKOUT_FILE, 'a') as f:
|
||||
f.write(ip + "\n")
|
||||
|
||||
def validate_user(username, password):
|
||||
"""
|
||||
Validates the user's credentials against stored data.
|
||||
"""
|
||||
ip_address = request.remote_addr
|
||||
|
||||
# Check if the IP is locked
|
||||
if is_ip_locked(ip_address):
|
||||
return False, "You have been locked out."
|
||||
|
||||
# Check or increment failed attempts for this IP address
|
||||
if ip_address not in FAILED_ATTEMPTS:
|
||||
FAILED_ATTEMPTS[ip_address] = 0
|
||||
|
||||
user_data = get_user(username)
|
||||
if not user_data:
|
||||
print(f"User '{username}' does not exist.")
|
||||
return False, "User does not exist."
|
||||
FAILED_ATTEMPTS[ip_address] += 1
|
||||
|
||||
if FAILED_ATTEMPTS[ip_address] >= MAX_ATTEMPTS:
|
||||
lock_ip(ip_address)
|
||||
return False, "Maximum login attempts exceeded. You have been locked out."
|
||||
|
||||
remaining_attempts = MAX_ATTEMPTS - FAILED_ATTEMPTS[ip_address]
|
||||
return False, f"User does not exist. {remaining_attempts} attempt(s) remaining."
|
||||
|
||||
stored_password, salt, login_attempts = user_data
|
||||
|
||||
# Check if the maximum login attempts have been reached
|
||||
if login_attempts >= MAX_ATTEMPTS:
|
||||
print(f"User '{username}' has exceeded max login attempts.")
|
||||
return False, "Maximum login attempts exceeded. Please contact the administrator."
|
||||
|
||||
# Hash the provided password with the salt
|
||||
hashed_password = hash_password(password, salt)
|
||||
print(f"Provided hash: {hashed_password}, Stored hash: {stored_password}")
|
||||
|
||||
if hashed_password == stored_password:
|
||||
reset_login_attempts(username)
|
||||
print(f"User '{username}' logged in successfully.")
|
||||
# Clear failed attempts for this IP on a successful login
|
||||
FAILED_ATTEMPTS.pop(ip_address, None)
|
||||
return True, "Login successful."
|
||||
else:
|
||||
increment_login_attempts(username)
|
||||
remaining_attempts = MAX_ATTEMPTS - login_attempts - 1
|
||||
print(f"Invalid credentials for '{username}'. {remaining_attempts} attempt(s) remaining.")
|
||||
FAILED_ATTEMPTS[ip_address] += 1
|
||||
if FAILED_ATTEMPTS[ip_address] >= MAX_ATTEMPTS:
|
||||
lock_ip(ip_address)
|
||||
return False, "Maximum login attempts exceeded. You have been locked out."
|
||||
|
||||
remaining_attempts = MAX_ATTEMPTS - FAILED_ATTEMPTS[ip_address]
|
||||
return False, f"Invalid credentials. {remaining_attempts} attempt(s) remaining."
|
||||
|
||||
def identify_uploader():
|
||||
|
||||
79
server/security.py.bak
Normal file
79
server/security.py.bak
Normal file
@@ -0,0 +1,79 @@
|
||||
import os # Import for generating random salts
|
||||
import hashlib
|
||||
from flask import request
|
||||
from db_setup import get_user, increment_login_attempts, reset_login_attempts
|
||||
|
||||
MAX_ATTEMPTS = 3
|
||||
|
||||
def generate_salt():
|
||||
"""
|
||||
Generates a 16-byte random salt.
|
||||
"""
|
||||
return os.urandom(16)
|
||||
|
||||
def hash_password(password, salt):
|
||||
# Convert the salt to bytes if it's a string
|
||||
if isinstance(salt, str):
|
||||
salt = salt.encode()
|
||||
return hashlib.sha256(salt + password.encode()).hexdigest()
|
||||
|
||||
def validate_user(username, password):
|
||||
"""
|
||||
Validates the user's credentials against stored data.
|
||||
"""
|
||||
user_data = get_user(username)
|
||||
if not user_data:
|
||||
print(f"User '{username}' does not exist.")
|
||||
return False, "User does not exist."
|
||||
|
||||
stored_password, salt, login_attempts = user_data
|
||||
|
||||
# Check if the maximum login attempts have been reached
|
||||
if login_attempts >= MAX_ATTEMPTS:
|
||||
print(f"User '{username}' has exceeded max login attempts.")
|
||||
return False, "Maximum login attempts exceeded. Please contact the administrator."
|
||||
|
||||
# Hash the provided password with the salt
|
||||
hashed_password = hash_password(password, salt)
|
||||
print(f"Provided hash: {hashed_password}, Stored hash: {stored_password}")
|
||||
|
||||
if hashed_password == stored_password:
|
||||
reset_login_attempts(username)
|
||||
print(f"User '{username}' logged in successfully.")
|
||||
return True, "Login successful."
|
||||
else:
|
||||
increment_login_attempts(username)
|
||||
remaining_attempts = MAX_ATTEMPTS - login_attempts - 1
|
||||
print(f"Invalid credentials for '{username}'. {remaining_attempts} attempt(s) remaining.")
|
||||
return False, f"Invalid credentials. {remaining_attempts} attempt(s) remaining."
|
||||
|
||||
def identify_uploader():
|
||||
"""
|
||||
Identifies the uploader's device information from the request headers.
|
||||
"""
|
||||
device_info = get_device_info()
|
||||
user_agent = device_info['user_agent']
|
||||
|
||||
if "iPhone" in user_agent:
|
||||
device_type = "iPhone"
|
||||
elif "Android" in user_agent:
|
||||
device_type = "Android"
|
||||
elif "Windows" in user_agent:
|
||||
device_type = "Windows PC"
|
||||
elif "Mac" in user_agent:
|
||||
device_type = "Mac"
|
||||
elif "Linux" in user_agent:
|
||||
device_type = "Linux Machine"
|
||||
else:
|
||||
device_type = "Unknown Device"
|
||||
|
||||
return f"Uploaded by {device_type} (IP: {device_info['ip']})"
|
||||
|
||||
def get_device_info():
|
||||
"""
|
||||
Extracts device information from the request.
|
||||
"""
|
||||
return {
|
||||
"ip": request.remote_addr or "Unknown IP",
|
||||
"user_agent": request.headers.get('User-Agent', 'Unknown'),
|
||||
}
|
||||
Reference in New Issue
Block a user