ldap-chpw-cgi/index.py

99 lines
3.6 KiB
Python
Raw Normal View History

2015-10-19 18:29:41 +02:00
#!/usr/bin/env python2.7
import cgi
import cgitb
import pwd, sys, os, cdb, subprocess
from subprocess import check_output, Popen, PIPE
from os.path import expanduser
cgitb.enable()
home_dir = expanduser("~")
def check_form(formvars, form):
for varname in formvars:
if varname not in form.keys():
return False
else:
if type(form[varname].value) is not type(''):
return None
return True
def read_template_file(filename, **vars):
with open('tpl/' + filename, 'r') 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.'
def generate_headers():
return "Content-Type: text/html; charset=utf-8\n"
def main():
main_content = ''
form = cgi.FieldStorage()
if 'submit' in form.keys():
formvars = ['accountname', 'oldpass', 'newpass', 'newpass2']
form_ok = check_form(formvars, form)
if form_ok == True:
accountname = form['accountname'].value
accountname = accountname.split("@")[0]
oldpass = form['oldpass'].value
newpass = form['newpass'].value
newpass2 = form['newpass2'].value
if newpass == newpass2:
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.close()
if p.wait() == 0:
# We did it
main_content = read_template_file('success.tpl')
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)))
else:
main_content = read_template_file('fail.tpl', message='Passwords to not match.')
elif form_ok == False:
main_content = read_template_file('fail.tpl', message='All fields are required.')
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)
main_content = form
response = generate_headers() + "\n"
response += read_template_file('main.tpl', main_content=main_content)
print(response)
if __name__ == "__main__":
main()