#! /usr/bin/python import os import sys import kerberos import cgi import time import exceptions company_name="Example" krb5_domain='EXAMPLE.COM' krb5_tgt='krbtgt/%s@%s' % (krb5_domain, krb5_domain) max_retries=3 admin_accounts = ['admin', 'user1' ] password_expired=False debug=False ############################################################################################## ### ### please don't change under this block unless you are also a dumbass system administrator :) ### ############################################################################################### username='' old_password='' new_password='' retry_counts=0 if debug: import cgitb cgitb.enable() def output_password_reset_page( error_messages=[] ): print "Content-Type: text/html\n\n" print "" print " Password Reset page " print "" print "

Password Reset for %s Linux/Unix users

" % company_name print '
' print '' if username: print '' % username else: print '' print '' print '' print '' print '' if error_messages: lines = len(error_messages) print '' % lines for error_message in error_messages: print '' % error_message print '' print '
User Name:
User Name:
Old Password:
New Password:
New Password (again):
ERRORS%s
' print '' % retry_counts print '

Good Password Rules in Short

' print '' print '' print '' print '' print '' print '' print '' print '
Password must be at least 8 characters long (new security guidelines set this to 12).
Password must have one or more upper case letters.
Password must have one or more lower case letters.
Password must have one or more digits letters.
Password must have one or more special letters like "@", "_", "$", "%", etc.
Password must be updated in no more than 90 days.
' print '' print '' sys.exit(0) def output_page_and_exit( messages=[] ): print "Content-Type: text/html\n\n" print "" print " Password Reset Results " print "" print "

Password Reset Results

" if messages: for message in messages: print message print '' print '' sys.exit(0) def validateInput(): global username, old_password, new_password global retry_counts form = cgi.FieldStorage() submit = form.getvalue('submit') if not submit: ## initial, no html form at all output_password_reset_page() sys.exit(0) retry_counts = form.getvalue('retry_counts') try: #print retry_counts retry_counts = int(retry_counts) except: #retry_counts = max_retries retry_counts = 0 else: if retry_counts <= 0: retry_counts = 0 elif retry_counts >= max_retries: retry_counts = max_retries else: pass if retry_counts >= max_retries: error_message = "Max times of attempts reached." output_page_and_exit( [ error_message ] ) retry_counts += 1 username = form.getvalue('username') old_password = form.getvalue('old_password') new_password_1 = form.getvalue('new_password_1') new_password_2 = form.getvalue('new_password_2') if not username or not old_password or not new_password_1 or not new_password_2: error_message = "username, old password, and new password can not be empty." output_password_reset_page( [ error_message ] ) elif new_password_1 != new_password_2: error_message = "new password mismatch." output_password_reset_page( [ error_message ] ) else: new_password = new_password_1 if username in admin_accounts: error_message = "admin user '%s' can not reset password through web UI." % username output_password_reset_page( [ error_message ] ) def changePasswd(): ## check whether the userID exist, etc. try: kerberos.checkPassword(username, old_password, krb5_tgt, krb5_domain) except kerberos.BasicAuthError as inst: errmsg, errcode = inst if errcode == -1765328378: #'Cannot find KDC for requested realm' if errmsg.find('Client not found in Kerberos database' ) != -1: error_message = "User '%s' doesn't exist." % username output_password_reset_page( [ error_message ] ) elif errmsg.find('Cannot find KDC') != -1: error_message = "oops. Cannot find KDC for requested realm. Please file a bug for techOps." output_password_reset_page( [ error_message ] ) else: error_message = "unknown error '%s'." % errmsg output_password_reset_page( [ error_message ] ) elif errcode == -1765328353: error_message = "old password is wrong." output_password_reset_page( [ error_message ] ) elif errcode == -1765328361: global password_expired info_message = "old password is expired." password_expired = True else: error_message_1 = "unknown error in checking user/password." error_message_2 = "BasicAuthError: %s " % str(inst.args) output_password_reset_page( [ error_message_1, error_message_2 ] ) except exceptions.BaseException as inst: error_message = "1: unknown error message '%s', please file a GUS ticket to TechOps." % str(inst.args) output_password_reset_page( [ error_message ] ) ## change password now try: kerberos.changePassword(username, old_password, new_password) except kerberos.PwdChangeError as inst: #raise if len(inst.args) == 2: errmsg, errcode = inst ## kerberos.PwdChangeError: ('Preauthentication failed', -1765328360) else: errmsg, errcode = inst[0] if errcode == -1765328360: ## 'Preauthentication failed' error_message = "oops. Cloud be empty password in database. Please file a bug for TechOps." output_password_reset_page( [ error_message ] ) if errcode == -1765328361: error_message = "PwdChangeError: %s " % str(inst.args) output_password_reset_page( [ error_message ] ) if errcode == -1765328353: ##PwdChangeError: ('Decrypt integrity check failed', -1765328353) error_message = "old password is wrong." #error_message = "PwdChangeError: %s " % str(inst.args) output_password_reset_page( [ error_message ] ) elif errcode == -1765328366: ##kerberos.PwdChangeError: ('Clients credentials have been revoked', -1765328366) error_message = "User account is locked." output_password_reset_page( [ error_message ] ) elif errcode == 4: ## password too simple ## 'Password change rejected: Password change failed Err5: Password too simple.' if errmsg.find('Password too simple') != -1 : error_message = "Password too simple." #raise output_password_reset_page( [ error_message ] ) ## 'Password change rejected: Password change failed Err7: Too soon to change password.'` elif errmsg.find('Too soon to change password') != -1: error_message = "Too soon to change password" output_password_reset_page( [ error_message ] ) else: error_message = "2: unknown error message '%s', please file a GUS ticket to TechOps." % str(inst.args) output_password_reset_page( [ error_message ] ) else: error_message_1 = "3: unknown error message '%s', please file a GUS ticket to TechOps." % str(inst.args) error_message_2 = str(inst) output_password_reset_page( [ error_message_1, error_message_2 ] ) except exceptions.BaseException as inst: error_message_1 = "4: unknown error message '%s', please file a GUS ticket to TechOps." % str(inst.args) error_message_2 = "4: %s " % str(inst.args) output_password_reset_page( [ error_message_1, error_message_2 ] ) else: if password_expired: info_message = "your expired password is reset successfully." else: info_message = "your password is reset successfully." output_page_and_exit( [ info_message ] ) sys.exit(0) ## it should not come here error_message = "5: unknown Error. Please copy this message screen and file a ticket to TechOps." output_password_reset_page( [ error_message ] ) def main(): global retry_counts validateInput() changePasswd() if __name__ == '__main__': main()