From 71c8a4dd5a5eb2eaf8971cc1da39203f174af498 Mon Sep 17 00:00:00 2001 From: Janek Bevendorff Date: Wed, 21 Oct 2015 16:05:38 +0200 Subject: [PATCH] Port to Python 3, get rid of cdb --- index.py | 61 ++++++++++++++++++++++++++++---------------------------- 1 file changed, 30 insertions(+), 31 deletions(-) diff --git a/index.py b/index.py index 036856f..662b6c0 100755 --- a/index.py +++ b/index.py @@ -1,12 +1,13 @@ -#!/usr/bin/env python2.7 -import cgi -import cgitb -import pwd, sys, os, cdb, subprocess -from subprocess import check_output, Popen, PIPE +#!/usr/bin/env python3 +import cgi, cgitb +import re +import sys, os, subprocess +from subprocess import check_output, Popen, PIPE, CalledProcessError from os.path import expanduser cgitb.enable() home_dir = expanduser("~") +os.environ['HOME'] = home_dir def check_form(formvars, form): for varname in formvars: @@ -18,32 +19,32 @@ def check_form(formvars, form): return True def read_template_file(filename, **vars): - with open('tpl/' + filename, 'r') as f: + with open('tpl/' + filename, mode='r', encoding='utf-8') as f: template = f.read() for key in vars: template = template.replace('{$' + key + '}', vars[key]) return template def check_oldpw(accountname, oldpass): - passwd_dbfile = os.path.abspath(home_dir + "/passwd.cdb"); try: - db = cdb.init(passwd_dbfile) - except: - return 'No user database found.' - try: - cdb_user_data=db[accountname] - except: - return 'User not found or password incorrect.' - passhash = cdb_user_data[6:40] - # Hash algorithm is given between first two $ of passhash (here only md5 based BSD password is used) - hashtype = '1' - # Salt is given between next two $ - salt = passhash[3:11] - opensslargs = ['openssl', 'passwd', '-' + hashtype, '-salt', salt, oldpass]; - newhash = check_output(opensslargs).strip(); - if newhash == passhash: - return '' - return 'User not found or password incorrect.' + 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 as e: + print(e) + return False + + opensslargs = ['openssl', 'passwd', '-' + hashtype, '-salt', salt, oldpass] + newhash = check_output(opensslargs).strip().decode('utf-8'); + + if newhash == oldhash: + return True + return False def generate_headers(): return "Content-Type: text/html; charset=utf-8\n" @@ -62,13 +63,11 @@ def main(): newpass = form['newpass'].value newpass2 = form['newpass2'].value if newpass == newpass2: - if check_oldpw(accountname, oldpass) == '': + if check_oldpw(accountname, oldpass): vpasswdargs = ['vpasswd', accountname] - # Environmental variable HOME is needed for vpasswd to work - os.environ['HOME'] = home_dir p = Popen(vpasswdargs, stdin=PIPE, stdout=PIPE, stderr=subprocess.STDOUT) - p.stdin.write(newpass + '\n') - p.stdin.write(newpass2 + '\n') + 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: # We did it @@ -76,7 +75,7 @@ def main(): else: main_content = read_template_file('fail.tpl', message=cgi.escape(p.stdout.read())) else: - main_content = read_template_file('fail.tpl', message=cgi.escape( check_oldpw(accountname, oldpass))) + main_content = read_template_file('fail.tpl', message='User not found or wrong password entered.') else: main_content = read_template_file('fail.tpl', message='Passwords to not match.') elif form_ok == False: @@ -91,7 +90,7 @@ def main(): response = generate_headers() + "\n" response += read_template_file('main.tpl', main_content=main_content) - print(response) + sys.stdout.buffer.write(response.encode('utf-8')) if __name__ == "__main__": main()