ctdb-scripts: Improve update and listing code
[samba4-gss.git] / python / samba / tests / auth_log_pass_change.py
blob29a9e38db1d7a7e91ca42c9e9d9ac1b65813455d
1 # Unix SMB/CIFS implementation.
2 # Copyright (C) Andrew Bartlett <abartlet@samba.org> 2017
4 # This program is free software; you can redistribute it and/or modify
5 # it under the terms of the GNU General Public License as published by
6 # the Free Software Foundation; either version 3 of the License, or
7 # (at your option) any later version.
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
14 # You should have received a copy of the GNU General Public License
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
18 """Tests for the Auth and AuthZ logging of password changes.
19 """
21 import samba.tests
22 from samba.samdb import SamDB
23 from samba.auth import system_session
24 import os
25 import samba.tests.auth_log_base
26 from samba.tests import delete_force
27 from samba.net import Net
28 import samba
29 from ldb import LdbError
30 from samba.tests.password_test import PasswordCommon
31 from samba.dcerpc.windows_event_ids import (
32 EVT_ID_SUCCESSFUL_LOGON,
33 EVT_ID_UNSUCCESSFUL_LOGON,
34 EVT_LOGON_NETWORK
37 USER_NAME = "authlogtestuser"
38 USER_PASS = samba.generate_random_password(32, 32)
41 class AuthLogPassChangeTests(samba.tests.auth_log_base.AuthLogTestBase):
43 def setUp(self):
44 super().setUp()
46 self.server_ip = os.environ["SERVER_IP"]
48 host = "ldap://%s" % os.environ["SERVER"]
49 self.ldb = SamDB(url=host,
50 session_info=system_session(),
51 credentials=self.get_credentials(),
52 lp=self.get_loadparm())
54 # permit password changes during this test
55 PasswordCommon.allow_password_changes(self, self.ldb)
57 self.base_dn = self.ldb.domain_dn()
59 # (Re)adds the test user USER_NAME with password USER_PASS
60 delete_force(self.ldb, "cn=" + USER_NAME + ",cn=users," + self.base_dn)
61 self.ldb.add({
62 "dn": "cn=" + USER_NAME + ",cn=users," + self.base_dn,
63 "objectclass": "user",
64 "sAMAccountName": USER_NAME,
65 "userPassword": USER_PASS
68 # discard any auth log messages for the password setup
69 type(self).discardMessages()
71 def _authDescription(self):
72 return "samr_ChangePasswordUser4"
74 def test_admin_change_password(self):
75 def isLastExpectedMessage(msg):
76 return ((msg["type"] == "Authentication") and
77 (msg["Authentication"]["status"] == "NT_STATUS_OK") and
78 (msg["Authentication"]["serviceDescription"] ==
79 "SAMR Password Change") and
80 (msg["Authentication"]["authDescription"] ==
81 self._authDescription()) and
82 (msg["Authentication"]["eventId"] ==
83 EVT_ID_SUCCESSFUL_LOGON) and
84 (msg["Authentication"]["logonType"] ==
85 EVT_LOGON_NETWORK))
87 creds = self.insta_creds(template=self.get_credentials())
89 lp = self.get_loadparm()
90 net = Net(creds, lp, server=self.server_ip)
91 password = "newPassword!!42"
93 net.change_password(newpassword=password,
94 username=USER_NAME,
95 oldpassword=USER_PASS)
96 self.assertTrue(self.waitForMessages(isLastExpectedMessage),
97 "Did not receive the expected message")
99 def test_admin_change_password_new_password_fails_restriction(self):
100 def isLastExpectedMessage(msg):
101 return ((msg["type"] == "Authentication") and
102 (msg["Authentication"]["status"] ==
103 "NT_STATUS_PASSWORD_RESTRICTION") and
104 (msg["Authentication"]["serviceDescription"] ==
105 "SAMR Password Change") and
106 (msg["Authentication"]["authDescription"] ==
107 self._authDescription()) and
108 (msg["Authentication"]["eventId"] ==
109 EVT_ID_UNSUCCESSFUL_LOGON) and
110 (msg["Authentication"]["logonType"] ==
111 EVT_LOGON_NETWORK))
113 creds = self.insta_creds(template=self.get_credentials())
115 lp = self.get_loadparm()
116 net = Net(creds, lp, server=self.server_ip)
117 password = "newPassword"
119 exception_thrown = False
120 try:
121 net.change_password(newpassword=password,
122 oldpassword=USER_PASS,
123 username=USER_NAME)
124 except Exception:
125 exception_thrown = True
126 self.assertEqual(True, exception_thrown,
127 "Expected exception not thrown")
128 self.assertTrue(self.waitForMessages(isLastExpectedMessage),
129 "Did not receive the expected message")
131 def test_admin_change_password_unknown_user(self):
132 def isLastExpectedMessage(msg):
133 return ((msg["type"] == "Authentication") and
134 (msg["Authentication"]["status"] ==
135 "NT_STATUS_NO_SUCH_USER") and
136 (msg["Authentication"]["serviceDescription"] ==
137 "SAMR Password Change") and
138 (msg["Authentication"]["authDescription"] ==
139 self._authDescription()) and
140 (msg["Authentication"]["eventId"] ==
141 EVT_ID_UNSUCCESSFUL_LOGON) and
142 (msg["Authentication"]["logonType"] ==
143 EVT_LOGON_NETWORK))
145 creds = self.insta_creds(template=self.get_credentials())
147 lp = self.get_loadparm()
148 net = Net(creds, lp, server=self.server_ip)
149 password = "newPassword!!42"
151 exception_thrown = False
152 try:
153 net.change_password(newpassword=password,
154 oldpassword=USER_PASS,
155 username="badUser")
156 except Exception:
157 exception_thrown = True
158 self.assertEqual(True, exception_thrown,
159 "Expected exception not thrown")
161 self.assertTrue(self.waitForMessages(isLastExpectedMessage),
162 "Did not receive the expected message")
164 def test_admin_change_password_bad_original_password(self):
165 def isLastExpectedMessage(msg):
166 return ((msg["type"] == "Authentication") and
167 (msg["Authentication"]["status"] ==
168 "NT_STATUS_WRONG_PASSWORD") and
169 (msg["Authentication"]["serviceDescription"] ==
170 "SAMR Password Change") and
171 (msg["Authentication"]["authDescription"] ==
172 self._authDescription()) and
173 (msg["Authentication"]["eventId"] ==
174 EVT_ID_UNSUCCESSFUL_LOGON) and
175 (msg["Authentication"]["logonType"] ==
176 EVT_LOGON_NETWORK))
178 creds = self.insta_creds(template=self.get_credentials())
180 lp = self.get_loadparm()
181 net = Net(creds, lp, server=self.server_ip)
182 password = "newPassword!!42"
184 exception_thrown = False
185 try:
186 net.change_password(newpassword=password,
187 oldpassword="badPassword",
188 username=USER_NAME)
189 except Exception:
190 exception_thrown = True
191 self.assertEqual(True, exception_thrown,
192 "Expected exception not thrown")
194 self.assertTrue(self.waitForMessages(isLastExpectedMessage),
195 "Did not receive the expected message")
197 def test_ldap_change_password(self):
198 def isLastExpectedMessage(msg):
199 return ((msg["type"] == "Authentication") and
200 (msg["Authentication"]["status"] == "NT_STATUS_OK") and
201 (msg["Authentication"]["serviceDescription"] ==
202 "LDAP Password Change") and
203 (msg["Authentication"]["authDescription"] ==
204 "LDAP Modify") and
205 (msg["Authentication"]["eventId"] ==
206 EVT_ID_SUCCESSFUL_LOGON) and
207 (msg["Authentication"]["logonType"] ==
208 EVT_LOGON_NETWORK))
210 new_password = samba.generate_random_password(32, 32)
211 self.ldb.modify_ldif(
212 "dn: cn=" + USER_NAME + ",cn=users," + self.base_dn + "\n" +
213 "changetype: modify\n" +
214 "delete: userPassword\n" +
215 "userPassword: " + USER_PASS + "\n" +
216 "add: userPassword\n" +
217 "userPassword: " + new_password + "\n")
219 self.assertTrue(self.waitForMessages(isLastExpectedMessage),
220 "Did not receive the expected message")
223 # Currently this does not get logged, so we expect to see no messages.
225 def test_ldap_change_password_bad_user(self):
226 def isLastExpectedMessage(msg):
227 msg_type = msg["type"]
229 # Accept any message we receive, except for those produced while
230 # the Administrator authenticates in setUp().
231 return (msg_type != "Authentication" or (
232 "Administrator" not in msg[msg_type]["clientAccount"])) and (
233 msg_type != "Authorization" or (
234 "Administrator" not in msg[msg_type]["account"]))
236 new_password = samba.generate_random_password(32, 32)
237 try:
238 self.ldb.modify_ldif(
239 "dn: cn=" + "badUser" + ",cn=users," + self.base_dn + "\n" +
240 "changetype: modify\n" +
241 "delete: userPassword\n" +
242 "userPassword: " + USER_PASS + "\n" +
243 "add: userPassword\n" +
244 "userPassword: " + new_password + "\n")
245 self.fail()
246 except LdbError as e:
247 (num, msg) = e.args
248 pass
250 self.assertFalse(self.waitForMessages(isLastExpectedMessage),
251 "Received unexpected messages")
253 def test_ldap_change_password_bad_original_password(self):
254 def isLastExpectedMessage(msg):
255 return ((msg["type"] == "Authentication") and
256 (msg["Authentication"]["status"] ==
257 "NT_STATUS_WRONG_PASSWORD") and
258 (msg["Authentication"]["serviceDescription"] ==
259 "LDAP Password Change") and
260 (msg["Authentication"]["authDescription"] ==
261 "LDAP Modify") and
262 (msg["Authentication"]["eventId"] ==
263 EVT_ID_UNSUCCESSFUL_LOGON) and
264 (msg["Authentication"]["logonType"] ==
265 EVT_LOGON_NETWORK))
267 new_password = samba.generate_random_password(32, 32)
268 try:
269 self.ldb.modify_ldif(
270 "dn: cn=" + USER_NAME + ",cn=users," + self.base_dn + "\n" +
271 "changetype: modify\n" +
272 "delete: userPassword\n" +
273 "userPassword: " + "badPassword" + "\n" +
274 "add: userPassword\n" +
275 "userPassword: " + new_password + "\n")
276 self.fail()
277 except LdbError as e1:
278 (num, msg) = e1.args
279 pass
281 self.assertTrue(self.waitForMessages(isLastExpectedMessage),
282 "Did not receive the expected message")