from flask import Flask, render_template, request, redirect, url_for, make_response import bcrypt import sqlite3 import configparser import subprocess import os from waitress import serve # Load from config.ini config = configparser.ConfigParser() config.read("../config.ini") database = config.get("Account", "database") runport = config.get("Account", "port") # Status report print("HectaMail Account Service is starting up...") print("Your database is located at:", database) def is_valid_input(input_string): return re.match(allowed_pattern, input_string) is not None app = Flask(__name__) 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 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(): email = request.cookies.get('email') if 'passwordhash' in request.cookies and request.cookies.get('passwordhash'): return render_template('dashboard.html', user_email=email) else: return render_template('index.html') @app.route('/loginapi', methods=['POST']) def login(): key_to_fetch = request.form['email'] password_to_check = request.form['password'] passwordhash = fetch_hash_from_database(key_to_fetch) if passwordhash: is_password_valid = verify_bcrypt(password_to_check, passwordhash) if is_password_valid: response = make_response(redirect('/account')) response.set_cookie('passwordhash', passwordhash) response.set_cookie('email', request.form['email']) return response else: return render_template('wrong.html') else: return render_template('wrong.html') @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: cmd = ["echo", "y", "|", "maddy", "creds", "remove", key_to_fetch] result = subprocess.run(" ".join(cmd), shell=True, check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) if result.returncode == 0: # Command executed successfully response = make_response(redirect('/')) response.set_cookie('passwordhash', '', expires=0) response.set_cookie('email', '', expires=0) return response else: # Handle errors, log them, and return False error_message = result.stderr.decode("utf-8") print(f"Error deleting email account: {error_message}") return render_template('err.html') else: return render_template('wrong.html') else: return render_template('wrong.html') @app.route('/deleteacct') def deleteacct(): email = request.cookies.get('email') passwordhash = request.cookies.get('passwordhash') if 'passwordhash' in request.cookies and request.cookies.get('passwordhash'): return render_template('confirm.html', user_email=email, password_hash=passwordhash) else: return redirect('/account') @app.route('/logout') def logout(): response = make_response(redirect('/')) response.set_cookie('passwordhash', '', expires=0) response.set_cookie('email', '', expires=0) return response @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') verifyhash = request.form.get('passwordhash') password = request.form.get('password') passwordhash = fetch_hash_from_database(username) if verifyhash == 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') else: # Backend error, potentially maddy return render_template('err.html'), 500 else: return render_template('wrong.html'), 400 if __name__ == '__main__': serve(app, host='0.0.0.0', port=runport)