From 42279bbcfa2e1db68e9fe30e0001d487699cae95 Mon Sep 17 00:00:00 2001 From: Christoph Loesch Date: Sun, 11 Apr 2021 05:16:42 +0200 Subject: [PATCH] rewrite index.py to work with ldap --- index.py | 82 ++++++++++++++++++++++++++++++++------------------------ 1 file changed, 47 insertions(+), 35 deletions(-) diff --git a/index.py b/index.py index 5131ee5..1a7f8b2 100755 --- a/index.py +++ b/index.py @@ -2,12 +2,15 @@ import cgi, cgitb import re import sys, os -from subprocess import check_output, Popen, PIPE, STDOUT, CalledProcessError -from os.path import expanduser +import ldap + +ldap_proto = 'ldap://' +ldap_server = 'localhost' +ldap_basedn = 'dc=ldap,dc=freiesnetz,dc=at' +ldap_userdn = 'ou=Users' +','+ ldap_basedn + +cgitb.enable(display=0, logdir='logs/') -cgitb.enable() -home_dir = expanduser("~") -os.environ['HOME'] = home_dir def check_form(formvars, form): for varname in formvars: @@ -18,6 +21,7 @@ def check_form(formvars, form): return None return True + def read_template_file(filename, **vars): with open('tpl/' + filename, mode='r', encoding='utf-8') as f: template = f.read() @@ -25,38 +29,30 @@ def read_template_file(filename, **vars): template = template.replace('{$' + key + '}', vars[key]) return template + def check_oldpw(accountname, oldpass): try: - dumpvuserargs = ['dumpvuser', accountname] - userdump = check_output(dumpvuserargs).strip().decode('utf-8') - m = re.search('Encrypted-Password: (\$([^\$]+)\$([^\$]+)\$([^\$\n]+))', userdump) - if None == m: - return False - oldhash = m.group(1) - hashtype = m.group(2) - salt = m.group(3) - except CalledProcessError: - return False - - opensslargs = ['openssl', 'passwd', '-' + hashtype, '-salt', salt, '-stdin'] - p = Popen(opensslargs, stdin=PIPE, stdout=PIPE, stderr=STDOUT) - p.stdin.write(oldpass.encode('utf-8') + b'\n') - p.stdin.close() - if p.wait() == 0: - newhash = p.stdout.readline().strip().decode('utf-8'); - - if newhash == oldhash: + conn = ldap.initialize(ldap_proto+ldap_server) + conn.set_option(ldap.OPT_REFERRALS, 0) + conn.set_option(ldap.OPT_PROTOCOL_VERSION, 3) + if conn.simple_bind("uid="+accountname+","+ldap_userdn, oldpass) == True: return True + except ldap.INVALID_CREDENTIALS: + conn.unbind() + return False return False + def generate_headers(): return "Content-Type: text/html; charset=utf-8\n" + def main(): main_content = '' form = cgi.FieldStorage() + debug_content = str(form) if 'submit' in form.keys(): formvars = ['accountname', 'oldpass', 'newpass', 'newpass2'] form_ok = check_form(formvars, form) @@ -68,16 +64,30 @@ def main(): newpass2 = form['newpass2'].value if newpass == newpass2: if check_oldpw(accountname, oldpass): - vpasswdargs = ['vpasswd', accountname] - p = Popen(vpasswdargs, stdin=PIPE, stdout=PIPE, stderr=STDOUT) - p.stdin.write(newpass.encode('utf-8') + b'\n') - p.stdin.write(newpass2.encode('utf-8') + b'\n') - p.stdin.close() - if p.wait() == 0: + conn = ldap.initialize(ldap_proto+ldap_server) + conn.set_option(ldap.OPT_REFERRALS, 0) + conn.set_option(ldap.OPT_PROTOCOL_VERSION, 3) + conn.simple_bind(accountname, oldpass) + results = conn.search_s(ldap_basedn, ldap.SCOPE_SUBTREE, "(uid="+accountname+")", ["dn"]) + conn.unbind() + for dn in results: + conn = ldap.initialize(ldap_proto+ldap_server) + conn.set_option(ldap.OPT_REFERRALS, 0) + conn.set_option(ldap.OPT_PROTOCOL_VERSION, 3) + # do a synchronous ldap bind + conn.simple_bind_s(dn[0], oldpass) + conn.passwd_s(dn[0], oldpass, newpass) + conn.unbind_s() + conn = ldap.initialize(ldap_proto+ldap_server) + conn.set_option(ldap.OPT_REFERRALS, 0) + conn.set_option(ldap.OPT_PROTOCOL_VERSION, 3) + if conn.simple_bind(accountname, newpass) == True: # We did it + conn.unbind() main_content = read_template_file('success.tpl') else: - main_content = read_template_file('fail.tpl', message=cgi.escape(p.stdout.read())) + conn.unbind() + main_content = read_template_file('fail.tpl', message=cgi.escape(ldap.LDAPError)) else: main_content = read_template_file('fail.tpl', message='User not found or wrong password entered.') else: @@ -87,15 +97,17 @@ def main(): else: main_content = read_template_file('fail.tpl', message='Invalid data type supplied.') else: - # Submit button not pressed, show form formaction = cgi.escape("https://" + os.environ["HTTP_HOST"] + os.environ["REQUEST_URI"]) - form = read_template_file('form.tpl', formaction=formaction) + #accountname = os.environ.get('REMOTE_USER') + accountname = os.environ.get('AUTHENTICATE_UID') + http_host = os.environ.get('HTTP_HOST') + form = read_template_file('form.tpl', formaction=formaction, accountname=accountname, http_host=http_host) main_content = form response = generate_headers() + "\n" - response += read_template_file('main.tpl', main_content=main_content) + response += read_template_file('main.tpl', main_content=main_content, debug_content=debug_content) sys.stdout.buffer.write(response.encode('utf-8')) + if __name__ == "__main__": main() -