2 # -*- coding: utf-8 -*-
4 # Basic sanity-checks of user login. This sanity-checks that a user can login
5 # over both NTLM and Kerberos, that incorrect passwords are rejected, and that
6 # the user can change their password successfully.
8 # Copyright Andrew Bartlett 2018
12 from samba
.tests
.subunitrun
import TestProgram
, SubunitOptions
13 import samba
.getopt
as options
14 from samba
.auth
import system_session
15 from samba
.credentials
import MUST_USE_KERBEROS
16 from samba
.dsdb
import UF_NORMAL_ACCOUNT
17 from samba
.samdb
import SamDB
18 from password_lockout_base
import BasePasswordTestCase
20 sys
.path
.insert(0, "bin/python")
22 parser
= optparse
.OptionParser("login_basics.py [options] <host>")
23 sambaopts
= options
.SambaOptions(parser
)
24 parser
.add_option_group(sambaopts
)
25 parser
.add_option_group(options
.VersionOptions(parser
))
26 # use command line creds if available
27 credopts
= options
.CredentialsOptions(parser
)
28 parser
.add_option_group(credopts
)
29 subunitopts
= SubunitOptions(parser
)
30 parser
.add_option_group(subunitopts
)
31 opts
, args
= parser
.parse_args()
39 lp
= sambaopts
.get_loadparm()
40 global_creds
= credopts
.get_credentials(lp
)
46 class BasicUserAuthTests(BasePasswordTestCase
):
50 self
.host_url
= "ldap://%s" % host
51 self
.host_url_ldaps
= "ldaps://%s" % host
53 self
.global_creds
= global_creds
54 self
.ldb
= SamDB(url
=self
.host_url
, credentials
=self
.global_creds
,
55 session_info
=system_session(self
.lp
), lp
=self
.lp
)
56 super(BasicUserAuthTests
, self
).setUp()
58 def _test_login_basics(self
, creds
, simple
=False):
59 username
= creds
.get_username()
60 userpass
= creds
.get_password()
61 userdn
= "cn=%s,cn=users,%s" % (username
, self
.base_dn
)
62 if creds
.get_kerberos_state() == MUST_USE_KERBEROS
:
63 logoncount_relation
= 'greater'
64 lastlogon_relation
= 'greater'
65 ldap_url
= self
.host_url
66 print("Performs a lockout attempt against LDAP using Kerberos")
68 logoncount_relation
= 'equal'
69 lastlogon_relation
= 'equal'
70 ldap_url
= self
.host_url_ldaps
71 print("Performs a lockout attempt against LDAP using Simple")
73 logoncount_relation
= 'equal'
74 lastlogon_relation
= 'equal'
75 ldap_url
= self
.host_url
76 print("Performs a lockout attempt against LDAP using NTLM")
78 # get the initial logon values for this user
79 res
= self
._check
_account
(userdn
,
81 badPasswordTime
=("greater", 0),
82 logonCount
=(logoncount_relation
, 0),
83 lastLogon
=("greater", 0),
84 lastLogonTimestamp
=("greater", 0),
85 userAccountControl
=UF_NORMAL_ACCOUNT
,
86 msDSUserAccountControlComputed
=0,
87 msg
='Initial test setup...')
88 badPasswordTime
= int(res
[0]["badPasswordTime"][0])
89 logonCount
= int(res
[0]["logonCount"][0])
90 lastLogon
= int(res
[0]["lastLogon"][0])
91 lastLogonTimestamp
= int(res
[0]["lastLogonTimestamp"][0])
93 test_creds
= self
.insta_creds(creds
)
95 # check logging in with the wrong password fails
96 test_creds
.set_password("thatsAcomplPASS1xBAD")
97 self
.assertLoginFailure(ldap_url
, test_creds
, self
.lp
)
98 res
= self
._check
_account
(userdn
,
100 badPasswordTime
=("greater", badPasswordTime
),
101 logonCount
=logonCount
,
103 lastLogonTimestamp
=lastLogonTimestamp
,
104 userAccountControl
=UF_NORMAL_ACCOUNT
,
105 msDSUserAccountControlComputed
=0,
106 msg
='Test login with wrong password')
107 badPasswordTime
= int(res
[0]["badPasswordTime"][0])
109 # check logging in with the correct password succeeds
110 test_creds
.set_password(userpass
)
111 user_ldb
= self
.assertLoginSuccess(ldap_url
, test_creds
, self
.lp
)
112 res
= self
._check
_account
(userdn
,
114 badPasswordTime
=badPasswordTime
,
115 logonCount
=(logoncount_relation
, logonCount
),
116 lastLogon
=('greater', lastLogon
),
117 lastLogonTimestamp
=lastLogonTimestamp
,
118 userAccountControl
=UF_NORMAL_ACCOUNT
,
119 msDSUserAccountControlComputed
=0,
120 msg
='Test login with correct password')
121 logonCount
= int(res
[0]["logonCount"][0])
122 lastLogon
= int(res
[0]["lastLogon"][0])
124 # check that the user can change its password
125 new_password
= "thatsAcomplPASS2"
126 user_ldb
.modify_ldif("""
133 """ % (userdn
, userpass
, new_password
))
135 # discard the old creds (i.e. get rid of our valid Kerberos ticket)
137 test_creds
= self
.insta_creds(creds
)
138 test_creds
.set_password(userpass
)
140 # for Kerberos, logging in with the old password fails
141 if creds
.get_kerberos_state() == MUST_USE_KERBEROS
:
142 self
.assertLoginFailure(ldap_url
, test_creds
, self
.lp
)
143 info_msg
= 'Test Kerberos login with old password fails'
144 expectBadPwdTime
= ("greater", badPasswordTime
)
145 res
= self
._check
_account
(userdn
,
147 badPasswordTime
=expectBadPwdTime
,
148 logonCount
=logonCount
,
150 lastLogonTimestamp
=lastLogonTimestamp
,
151 userAccountControl
=UF_NORMAL_ACCOUNT
,
152 msDSUserAccountControlComputed
=0,
154 badPasswordTime
= int(res
[0]["badPasswordTime"][0])
156 # for NTLM, logging in with the old password succeeds
157 user_ldb
= self
.assertLoginSuccess(ldap_url
, test_creds
, self
.lp
)
159 info_msg
= 'Test simple-bind login with old password succeeds'
161 info_msg
= 'Test NTLM login with old password succeeds'
162 res
= self
._check
_account
(userdn
,
164 badPasswordTime
=badPasswordTime
,
165 logonCount
=logonCount
,
167 lastLogonTimestamp
=lastLogonTimestamp
,
168 userAccountControl
=UF_NORMAL_ACCOUNT
,
169 msDSUserAccountControlComputed
=0,
172 # check logging in with the new password succeeds
173 test_creds
.set_password(new_password
)
174 user_ldb
= self
.assertLoginSuccess(ldap_url
, test_creds
, self
.lp
)
175 res
= self
._check
_account
(userdn
,
177 badPasswordTime
=badPasswordTime
,
178 logonCount
=(logoncount_relation
, logonCount
),
179 lastLogon
=(lastlogon_relation
, lastLogon
),
180 lastLogonTimestamp
=lastLogonTimestamp
,
181 userAccountControl
=UF_NORMAL_ACCOUNT
,
182 msDSUserAccountControlComputed
=0,
183 msg
='Test login with new password succeeds')
185 def test_login_basics_krb5(self
):
186 self
._test
_login
_basics
(self
.lockout1krb5_creds
)
188 def test_login_basics_ntlm(self
):
189 self
._test
_login
_basics
(self
.lockout1ntlm_creds
)
191 def test_login_basics_simple(self
):
192 self
._test
_login
_basics
(self
.lockout1simple_creds
, simple
=True)
194 TestProgram(module
=__name__
, opts
=subunitopts
)