hectamail-website/account/account.py

184 lines
6.2 KiB
Python
Raw Normal View History

2023-11-19 21:54:36 +00:00
from flask import Flask, render_template, request, redirect, url_for, make_response
2023-11-19 13:48:33 +00:00
import bcrypt
import sqlite3
import configparser
2023-11-20 00:56:42 +00:00
import subprocess
2023-11-20 17:55:25 +00:00
import os
2023-11-19 13:48:33 +00:00
from waitress import serve
# Load from config.ini
config = configparser.ConfigParser()
2023-11-19 13:51:30 +00:00
config.read("../config.ini")
2023-11-19 23:47:22 +00:00
database = config.get("Account", "database")
runport = config.get("Account", "port")
2023-11-19 13:48:33 +00:00
# Status report
2023-11-19 23:47:22 +00:00
print("HectaMail Account Service is starting up...")
2023-11-19 13:48:33 +00:00
print("Your database is located at:", database)
2023-11-20 17:55:25 +00:00
def is_valid_input(input_string):
return re.match(allowed_pattern, input_string) is not None
2023-11-19 13:48:33 +00:00
app = Flask(__name__)
2023-11-20 17:55:25 +00:00
def change_email_password(username, password):
if password and is_valid_input(username):
try:
# Create a temporary file to escape the password
with open("../tmp/chnpassword.tmp", "w") as file:
file.write(password)
# Pass the file through a shell command
cmd = ["cat", "../tmp/chnpassword.tmp", "|", "maddy", "creds", "password", f"{username}@hectabit.org"]
# Run and determine the result of the shell command
result = subprocess.run(" ".join(cmd), shell=True, check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
# Delete the temporary file
os.remove("../tmp/chnpassword.tmp")
# Check if command executed correctly
if result.returncode == 0:
# Command executed successfully
return True
else:
# Handle errors, log them, and return False
error_message = result.stderr.decode("utf-8")
print(f"Error creating email account: {error_message}")
return False
except Exception as e:
# Handle exceptions and return False
print(f"Error creating email account: {str(e)}")
return False
else:
# Something went very wrong if this function triggers
print(f"Injection Bypass! Very bad!")
return False
2023-11-19 13:48:33 +00:00
def fetch_hash_from_database(key):
conn = sqlite3.connect(database)
cursor = conn.cursor()
cursor.execute("SELECT value FROM passwords WHERE key = ?", (key,))
result = cursor.fetchone()
conn.close()
if result:
return result[0][7:] # Remove the first 7 characters
else:
return None
def verify_bcrypt(passphrase, hashed_password):
return bcrypt.checkpw(passphrase.encode('utf-8'), hashed_password.encode('utf-8'))
@app.route('/')
def index():
2023-11-20 17:32:17 +00:00
email = request.cookies.get('email')
2023-11-20 01:05:00 +00:00
if 'passwordhash' in request.cookies and request.cookies.get('passwordhash'):
2023-11-20 17:32:17 +00:00
return render_template('dashboard.html', user_email=email)
2023-11-20 01:05:00 +00:00
else:
return render_template('index.html')
2023-11-19 13:48:33 +00:00
2023-11-20 00:19:47 +00:00
@app.route('/loginapi', methods=['POST'])
2023-11-19 13:48:33 +00:00
def login():
key_to_fetch = request.form['email']
password_to_check = request.form['password']
2023-11-19 21:54:36 +00:00
passwordhash = fetch_hash_from_database(key_to_fetch)
2023-11-19 13:48:33 +00:00
2023-11-19 21:54:36 +00:00
if passwordhash:
is_password_valid = verify_bcrypt(password_to_check, passwordhash)
2023-11-19 13:48:33 +00:00
if is_password_valid:
2023-11-20 17:24:58 +00:00
response = make_response(redirect('/account'))
2023-11-19 21:54:36 +00:00
response.set_cookie('passwordhash', passwordhash)
2023-11-20 00:05:07 +00:00
response.set_cookie('email', request.form['email'])
2023-11-19 21:54:36 +00:00
return response
2023-11-19 13:48:33 +00:00
else:
2023-11-20 17:24:58 +00:00
return render_template('wrong.html')
2023-11-19 13:48:33 +00:00
else:
2023-11-20 17:24:58 +00:00
return render_template('wrong.html')
2023-11-19 13:48:33 +00:00
2023-11-20 00:19:47 +00:00
@app.route('/deleteapi', methods=['POST'])
def delete():
key_to_fetch = request.form['email']
verify_hash = request.form['hash']
passwordhash = fetch_hash_from_database(key_to_fetch)
if passwordhash:
if verify_hash == passwordhash:
2023-11-20 01:04:01 +00:00
cmd = ["echo", "y", "|", "maddy", "creds", "remove", key_to_fetch]
2023-11-20 00:51:01 +00:00
result = subprocess.run(" ".join(cmd), shell=True, check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
if result.returncode == 0:
# Command executed successfully
2023-11-20 17:24:58 +00:00
response = make_response(redirect('/'))
2023-11-20 01:04:01 +00:00
response.set_cookie('passwordhash', '', expires=0)
response.set_cookie('email', '', expires=0)
return response
2023-11-20 00:51:01 +00:00
else:
# Handle errors, log them, and return False
error_message = result.stderr.decode("utf-8")
print(f"Error deleting email account: {error_message}")
2023-11-20 17:24:58 +00:00
return render_template('err.html')
2023-11-20 00:51:01 +00:00
2023-11-20 00:19:47 +00:00
else:
2023-11-20 17:24:58 +00:00
return render_template('wrong.html')
2023-11-19 21:54:36 +00:00
else:
2023-11-20 17:24:58 +00:00
return render_template('wrong.html')
2023-11-19 21:54:36 +00:00
2023-11-20 00:05:07 +00:00
@app.route('/deleteacct')
def deleteacct():
2023-11-20 01:04:01 +00:00
email = request.cookies.get('email')
passwordhash = request.cookies.get('passwordhash')
2023-11-20 00:05:07 +00:00
if 'passwordhash' in request.cookies and request.cookies.get('passwordhash'):
2023-11-20 01:04:01 +00:00
return render_template('confirm.html', user_email=email, password_hash=passwordhash)
2023-11-20 00:05:07 +00:00
else:
2023-11-20 17:55:25 +00:00
return redirect('/account')
2023-11-20 00:05:07 +00:00
2023-11-20 17:32:17 +00:00
@app.route('/logout')
2023-11-20 17:33:00 +00:00
def logout():
2023-11-20 17:32:17 +00:00
response = make_response(redirect('/'))
response.set_cookie('passwordhash', '', expires=0)
response.set_cookie('email', '', expires=0)
return response
2023-11-20 17:55:25 +00:00
@app.route('/changepass')
def changepass():
email = request.cookies.get('email')
passwordhash = request.cookies.get('passwordhash')
if 'passwordhash' in request.cookies and request.cookies.get('passwordhash'):
return render_template('changepass.html', user_email=email, password_hash=passwordhash)
else:
return redirect('/account')
@app.route('/changeapi', methods=['POST'])
def register():
# Get the form data
username = request.form.get('username')
2023-11-20 18:17:33 +00:00
verifyhash = request.form.get('passwordhash')
2023-11-20 17:57:28 +00:00
password = request.form.get('password')
2023-11-20 17:55:25 +00:00
2023-11-20 18:18:52 +00:00
passwordhash = fetch_hash_from_database(username)
2023-11-20 18:17:33 +00:00
if password == passwordhash:
# Attempt to change the password
if change_email_password(username, password):
# Password changed
response.set_cookie('passwordhash', '', expires=0)
response.set_cookie('email', '', expires=0)
return redirect('/account')
2023-11-20 17:55:25 +00:00
else:
2023-11-20 18:17:33 +00:00
# Backend error, potentially maddy
return render_template('err.html'), 500
2023-11-20 17:55:25 +00:00
else:
return render_template('wrong.html'), 400
2023-11-19 13:48:33 +00:00
if __name__ == '__main__':
serve(app, host='0.0.0.0', port=runport)