Port to Python 3, get rid of cdb

This commit is contained in:
Janek Bevendorff 2015-10-21 16:05:38 +02:00
parent 8f7ba6a4f0
commit 71c8a4dd5a

View file

@ -1,12 +1,13 @@
#!/usr/bin/env python2.7 #!/usr/bin/env python3
import cgi import cgi, cgitb
import cgitb import re
import pwd, sys, os, cdb, subprocess import sys, os, subprocess
from subprocess import check_output, Popen, PIPE from subprocess import check_output, Popen, PIPE, CalledProcessError
from os.path import expanduser from os.path import expanduser
cgitb.enable() cgitb.enable()
home_dir = expanduser("~") home_dir = expanduser("~")
os.environ['HOME'] = home_dir
def check_form(formvars, form): def check_form(formvars, form):
for varname in formvars: for varname in formvars:
@ -18,32 +19,32 @@ def check_form(formvars, form):
return True return True
def read_template_file(filename, **vars): 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() template = f.read()
for key in vars: for key in vars:
template = template.replace('{$' + key + '}', vars[key]) template = template.replace('{$' + key + '}', vars[key])
return template return template
def check_oldpw(accountname, oldpass): def check_oldpw(accountname, oldpass):
passwd_dbfile = os.path.abspath(home_dir + "/passwd.cdb");
try: try:
db = cdb.init(passwd_dbfile) dumpvuserargs = ['dumpvuser', accountname]
except: userdump = check_output(dumpvuserargs).strip().decode('utf-8')
return 'No user database found.' m = re.search('Encrypted-Password: (\$([^\$]+)\$([^\$]+)\$([^\$\n]+))', userdump)
try: if None == m:
cdb_user_data=db[accountname] return False
except: oldhash = m.group(1)
return 'User not found or password incorrect.' hashtype = m.group(2)
passhash = cdb_user_data[6:40] salt = m.group(3)
# Hash algorithm is given between first two $ of passhash (here only md5 based BSD password is used) except CalledProcessError as e:
hashtype = '1' print(e)
# Salt is given between next two $ return False
salt = passhash[3:11]
opensslargs = ['openssl', 'passwd', '-' + hashtype, '-salt', salt, oldpass]; opensslargs = ['openssl', 'passwd', '-' + hashtype, '-salt', salt, oldpass]
newhash = check_output(opensslargs).strip(); newhash = check_output(opensslargs).strip().decode('utf-8');
if newhash == passhash:
return '' if newhash == oldhash:
return 'User not found or password incorrect.' return True
return False
def generate_headers(): def generate_headers():
return "Content-Type: text/html; charset=utf-8\n" return "Content-Type: text/html; charset=utf-8\n"
@ -62,13 +63,11 @@ def main():
newpass = form['newpass'].value newpass = form['newpass'].value
newpass2 = form['newpass2'].value newpass2 = form['newpass2'].value
if newpass == newpass2: if newpass == newpass2:
if check_oldpw(accountname, oldpass) == '': if check_oldpw(accountname, oldpass):
vpasswdargs = ['vpasswd', accountname] 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 = Popen(vpasswdargs, stdin=PIPE, stdout=PIPE, stderr=subprocess.STDOUT)
p.stdin.write(newpass + '\n') p.stdin.write(newpass.encode('utf-8') + b'\n')
p.stdin.write(newpass2 + '\n') p.stdin.write(newpass2.encode('utf-8') + b'\n')
p.stdin.close() p.stdin.close()
if p.wait() == 0: if p.wait() == 0:
# We did it # We did it
@ -76,7 +75,7 @@ def main():
else: else:
main_content = read_template_file('fail.tpl', message=cgi.escape(p.stdout.read())) main_content = read_template_file('fail.tpl', message=cgi.escape(p.stdout.read()))
else: 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: else:
main_content = read_template_file('fail.tpl', message='Passwords to not match.') main_content = read_template_file('fail.tpl', message='Passwords to not match.')
elif form_ok == False: elif form_ok == False:
@ -91,7 +90,7 @@ def main():
response = generate_headers() + "\n" response = generate_headers() + "\n"
response += read_template_file('main.tpl', main_content=main_content) response += read_template_file('main.tpl', main_content=main_content)
print(response) sys.stdout.buffer.write(response.encode('utf-8'))
if __name__ == "__main__": if __name__ == "__main__":
main() main()