#!/usr/share/ucs-test/runner python3
## desc: Check if ldap auth is denied for expired passwords
## roles: [domaincontroller_master]
## exposure: dangerous
## packages: [univention-directory-manager-tools]
## bugs: [35088]

from __future__ import print_function
import univention.admin.uldap
import univention.admin.modules as udm_modules
import univention.testing.udm as udm_test
import univention.testing.utils as utils
import univention.testing.ucr as ucr_test
import subprocess
import time


def main():
	UCR = ucr_test.UCSTestConfigRegistry()
	UCR.load()
	if not UCR.is_true('ldap/shadowbind', True):
		utils.fail('UCR variable ldap/shadowbind is disabled (%s), test will not work' % UCR['ldap/shadowbind'])
	print(time.ctime())
	with udm_test.UCSTestUDM() as udm:
		udm_modules.update()
		lo, position = univention.admin.uldap.getAdminConnection()
		udm_modules.init(lo, position, udm_modules.get('users/user'))
		today = int(time.time() / 24 / 3600)
		for delta, disabled, expected in [
			[-9, '0', 1],
			[-8, '0', 1],
			[-7, '0', 1],
			[-6, '0', 1],
			[-5, '0', 1],
			[-4, '0', 1],
			[-3, '0', 1],
			[-2, '0', 1],
			[-1, '0', 1],
			[1, '0', 0],
			[2, '0', 0],
			[-4, '1', 1],
			[2, '1', 1],
			[3, '1', 1],
		]:
			dn, username = udm.create_user(disabled=disabled)
			oldattr = lo.get(dn)
			shadowMax = 7
			planned_expiry_day = today + delta
			shadowLastChange = planned_expiry_day - shadowMax
			print("testing: shadow password expiry in delta=%s days and account disabled=%s" % (delta, disabled))
			print("shadowLastChange: %s, today: %s, expires: %s" % (shadowLastChange, today, planned_expiry_day))
			lo.modify(dn, [
				['shadowMax', oldattr.get('shadowMax', []), [str(shadowMax).encode()]],
				['shadowLastChange', oldattr.get('shadowLastChange', []), [str(shadowLastChange).encode()]],
			])
			cmd = ['univention-ldapsearch', '-LLL', '-D', dn, '-x', '-w', 'univention', 'uid=dummy']
			print("Running: " " ".join(cmd))
			p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, close_fds=True)
			stdout, stderr = p.communicate()
			print("expecting: %s" % ("failure" if expected else "success"))
			print("result   : %s" % ("failure" if p.returncode else "success"))
			print(stdout.decode('utf-8', 'replace'))
			if expected == 0 and p.returncode != 0:
				utils.fail('Login for account %s is expected to pass, but failed' % dn)
			if expected != 0 and p.returncode == 0:
				utils.fail('Login for account %s is expected to fail, but passed' % dn)


if __name__ == '__main__':
	main()
