diff options
Diffstat (limited to 'source4/dsdb/tests/python/login_basics.py')
-rwxr-xr-x | source4/dsdb/tests/python/login_basics.py | 194 |
1 files changed, 194 insertions, 0 deletions
diff --git a/source4/dsdb/tests/python/login_basics.py b/source4/dsdb/tests/python/login_basics.py new file mode 100755 index 0000000..19cdf3e --- /dev/null +++ b/source4/dsdb/tests/python/login_basics.py @@ -0,0 +1,194 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +# +# Basic sanity-checks of user login. This sanity-checks that a user can login +# over both NTLM and Kerberos, that incorrect passwords are rejected, and that +# the user can change their password successfully. +# +# Copyright Andrew Bartlett 2018 +# +import optparse +import sys +from samba.tests.subunitrun import TestProgram, SubunitOptions +import samba.getopt as options +from samba.auth import system_session +from samba.credentials import MUST_USE_KERBEROS +from samba.dsdb import UF_NORMAL_ACCOUNT +from samba.samdb import SamDB +from password_lockout_base import BasePasswordTestCase + +sys.path.insert(0, "bin/python") + +parser = optparse.OptionParser("login_basics.py [options] <host>") +sambaopts = options.SambaOptions(parser) +parser.add_option_group(sambaopts) +parser.add_option_group(options.VersionOptions(parser)) +# use command line creds if available +credopts = options.CredentialsOptions(parser) +parser.add_option_group(credopts) +subunitopts = SubunitOptions(parser) +parser.add_option_group(subunitopts) +opts, args = parser.parse_args() + +if len(args) < 1: + parser.print_usage() + sys.exit(1) + +host = args[0] + +lp = sambaopts.get_loadparm() +global_creds = credopts.get_credentials(lp) + + +# +# Tests start here +# +class BasicUserAuthTests(BasePasswordTestCase): + + def setUp(self): + self.host = host + self.host_url = "ldap://%s" % host + self.host_url_ldaps = "ldaps://%s" % host + self.lp = lp + self.global_creds = global_creds + self.ldb = SamDB(url=self.host_url, credentials=self.global_creds, + session_info=system_session(self.lp), lp=self.lp) + super(BasicUserAuthTests, self).setUp() + + def _test_login_basics(self, creds, simple=False): + username = creds.get_username() + userpass = creds.get_password() + userdn = "cn=%s,cn=users,%s" % (username, self.base_dn) + if creds.get_kerberos_state() == MUST_USE_KERBEROS: + logoncount_relation = 'greater' + lastlogon_relation = 'greater' + ldap_url = self.host_url + print("Performs a lockout attempt against LDAP using Kerberos") + elif simple: + logoncount_relation = 'equal' + lastlogon_relation = 'equal' + ldap_url = self.host_url_ldaps + print("Performs a lockout attempt against LDAP using Simple") + else: + logoncount_relation = 'equal' + lastlogon_relation = 'equal' + ldap_url = self.host_url + print("Performs a lockout attempt against LDAP using NTLM") + + # get the initial logon values for this user + res = self._check_account(userdn, + badPwdCount=0, + badPasswordTime=("greater", 0), + logonCount=(logoncount_relation, 0), + lastLogon=("greater", 0), + lastLogonTimestamp=("greater", 0), + userAccountControl=UF_NORMAL_ACCOUNT, + msDSUserAccountControlComputed=0, + msg='Initial test setup...') + badPasswordTime = int(res[0]["badPasswordTime"][0]) + logonCount = int(res[0]["logonCount"][0]) + lastLogon = int(res[0]["lastLogon"][0]) + lastLogonTimestamp = int(res[0]["lastLogonTimestamp"][0]) + + test_creds = self.insta_creds(creds) + + # check logging in with the wrong password fails + test_creds.set_password("thatsAcomplPASS1xBAD") + self.assertLoginFailure(ldap_url, test_creds, self.lp) + res = self._check_account(userdn, + badPwdCount=1, + badPasswordTime=("greater", badPasswordTime), + logonCount=logonCount, + lastLogon=lastLogon, + lastLogonTimestamp=lastLogonTimestamp, + userAccountControl=UF_NORMAL_ACCOUNT, + msDSUserAccountControlComputed=0, + msg='Test login with wrong password') + badPasswordTime = int(res[0]["badPasswordTime"][0]) + + # check logging in with the correct password succeeds + test_creds.set_password(userpass) + user_ldb = self.assertLoginSuccess(ldap_url, test_creds, self.lp) + res = self._check_account(userdn, + badPwdCount=0, + badPasswordTime=badPasswordTime, + logonCount=(logoncount_relation, logonCount), + lastLogon=('greater', lastLogon), + lastLogonTimestamp=lastLogonTimestamp, + userAccountControl=UF_NORMAL_ACCOUNT, + msDSUserAccountControlComputed=0, + msg='Test login with correct password') + logonCount = int(res[0]["logonCount"][0]) + lastLogon = int(res[0]["lastLogon"][0]) + + # check that the user can change its password + new_password = "thatsAcomplPASS2" + user_ldb.modify_ldif(""" +dn: %s +changetype: modify +delete: userPassword +userPassword: %s +add: userPassword +userPassword: %s +""" % (userdn, userpass, new_password)) + + # discard the old creds (i.e. get rid of our valid Kerberos ticket) + del test_creds + test_creds = self.insta_creds(creds) + test_creds.set_password(userpass) + + # for Kerberos, logging in with the old password fails + if creds.get_kerberos_state() == MUST_USE_KERBEROS: + self.assertLoginFailure(ldap_url, test_creds, self.lp) + info_msg = 'Test Kerberos login with old password fails' + expectBadPwdTime = ("greater", badPasswordTime) + res = self._check_account(userdn, + badPwdCount=1, + badPasswordTime=expectBadPwdTime, + logonCount=logonCount, + lastLogon=lastLogon, + lastLogonTimestamp=lastLogonTimestamp, + userAccountControl=UF_NORMAL_ACCOUNT, + msDSUserAccountControlComputed=0, + msg=info_msg) + badPasswordTime = int(res[0]["badPasswordTime"][0]) + else: + # for NTLM, logging in with the old password succeeds + user_ldb = self.assertLoginSuccess(ldap_url, test_creds, self.lp) + if simple: + info_msg = 'Test simple-bind login with old password succeeds' + else: + info_msg = 'Test NTLM login with old password succeeds' + res = self._check_account(userdn, + badPwdCount=0, + badPasswordTime=badPasswordTime, + logonCount=logonCount, + lastLogon=lastLogon, + lastLogonTimestamp=lastLogonTimestamp, + userAccountControl=UF_NORMAL_ACCOUNT, + msDSUserAccountControlComputed=0, + msg=info_msg) + + # check logging in with the new password succeeds + test_creds.set_password(new_password) + user_ldb = self.assertLoginSuccess(ldap_url, test_creds, self.lp) + res = self._check_account(userdn, + badPwdCount=0, + badPasswordTime=badPasswordTime, + logonCount=(logoncount_relation, logonCount), + lastLogon=(lastlogon_relation, lastLogon), + lastLogonTimestamp=lastLogonTimestamp, + userAccountControl=UF_NORMAL_ACCOUNT, + msDSUserAccountControlComputed=0, + msg='Test login with new password succeeds') + + def test_login_basics_krb5(self): + self._test_login_basics(self.lockout1krb5_creds) + + def test_login_basics_ntlm(self): + self._test_login_basics(self.lockout1ntlm_creds) + + def test_login_basics_simple(self): + self._test_login_basics(self.lockout1simple_creds, simple=True) + +TestProgram(module=__name__, opts=subunitopts) |