X-Git-Url: https://git.ralfj.de/ansible.git/blobdiff_plain/d8b2db0f1004d3496e6e64aafef506eb4f7e373a..df93ad2b2188c394c421743afc7a7645a2486202:/roles/email/templates/changepw diff --git a/roles/email/templates/changepw b/roles/email/templates/changepw new file mode 100644 index 0000000..96eef60 --- /dev/null +++ b/roles/email/templates/changepw @@ -0,0 +1,102 @@ +#!/usr/bin/env python2 +from __future__ import print_function +import os, cgi, MySQLdb, subprocess, time + +# settings +DB_NAME = 'vmail' +DB_USER = 'vmail' +DB_PW = '{{postfix.dovecot.mysql_password}}' + +# DB stuff +db = MySQLdb.connect(user=DB_USER, passwd=DB_PW, db=DB_NAME, charset='utf8') + +def db_execute(query, args): + cursor = db.cursor(MySQLdb.cursors.DictCursor) + if len(args) == 1 and isinstance(args[0], dict): args = args[0] # einzelnes dict weiterreichen + cursor.execute(query, args) + return cursor + +def db_fetch_one_row(query, *args): + cursor = db_execute(query, args) + result = cursor.fetchone() + if cursor.fetchone() is not None: + raise Exception("Found more than one result, only one was expected") + cursor.close() + return result + +def db_run(query, *args): + cursor = db_execute(query, args) + cursor.close() + +def get_user(name): + return db_fetch_one_row('SELECT * FROM users WHERE username=%s', name) + +def change_user_pw(name, hash): + db_run('UPDATE users SET password=%s WHERE username=%s', hash, name) + +def change_user_active(name, active): + db_run('UPDATE users SET active=%s WHERE username=%s', int(active), name) + +# interaction with dbadm pw +def compare_pw(hash, plain): + try: + subprocess.check_output(["doveadm", "pw", "-t", hash, "-p", plain]) + return True + except subprocess.CalledProcessError: + return False + +def gen_hash(plain): + return subprocess.check_output(["doveadm", "pw", "-s", "SHA512-CRYPT", "-r", str(64*1024), "-p", plain]).decode('utf-8').strip() + +# the core action +def act(user, oldpw, newpw1, newpw2): + if user is None and oldpw is None and newpw1 is None and newpw2 is None: + return + if user is None or oldpw is None or newpw1 is None or newpw2 is None: + return "Error: You have to fill all the fields." + curdata = get_user(user) + if curdata is None: + return "Error: User not found." + if len(newpw1) < 8: + return "Error: Password must be at least 8 characters long." + if newpw1 != newpw2: + return "Error: New passwords do not match." + # slow down brute-force attacks + time.sleep(2.5) + # now go on + if not compare_pw(curdata['password'], oldpw): + return "Error: Old PW is wrong." + new_hash = gen_hash(newpw1) + change_user_pw(user, new_hash) + # potentially enable this user + if curdata['active'] < 0: + change_user_active(user, -curdata['active']) + return "Password successfully changed." + +# print headers +print("Content-Type: text/html") +print() + +# print document header +print("") +print("") +print(" ") +print(" User PW change") +print(" ") +print("") + +# do stuff +form = cgi.FieldStorage() +msg = act(form.getfirst('user'), form.getfirst('oldpw'), form.getfirst('newpw1'), form.getfirst('newpw2')) +if msg is not None: + print("

{}

".format(msg)) + +# print form +print("
") +print(" ") +print(" ") +print(" ") +print(" ") +print(" ") +print("
Username:
Old Password:
New Password:
New Password (confirmation):
") +print("")