1 # Unix SMB/CIFS implementation.
2 # Copyright (C) Andrew Bartlett <abartlet@samba.org> 2017
3 # Copyright (C) Catalyst IT Ltd. 2017
5 # This program is free software; you can redistribute it and/or modify
6 # it under the terms of the GNU General Public License as published by
7 # the Free Software Foundation; either version 3 of the License, or
8 # (at your option) any later version.
10 # This program is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 # GNU General Public License for more details.
15 # You should have received a copy of the GNU General Public License
16 # along with this program. If not, see <http://www.gnu.org/licenses/>.
20 Tests that exercise auth logging for unsuccessful netlogon attempts.
22 NOTE: netlogon is only done once per session, so this file should only
23 test failed logons. Adding a successful case will potentially break
24 the other tests, depending on the order of execution.
29 from samba import NTSTATUSError
30 from samba.samdb import SamDB
31 import samba.tests.auth_log_base
32 from samba.credentials import Credentials
33 from samba.dcerpc import netlogon
34 from samba.dcerpc.dcerpc import AS_SYSTEM_MAGIC_PATH_TOKEN
35 from samba.auth import system_session
36 from samba.tests import delete_force
37 from samba.dsdb import UF_WORKSTATION_TRUST_ACCOUNT, UF_PASSWD_NOTREQD
38 from samba.dcerpc.misc import SEC_CHAN_WKSTA
39 from samba.dcerpc.netlogon import NETLOGON_NEG_STRONG_KEYS
40 from samba.compat import get_string
41 from samba.dcerpc.windows_event_ids import (
42 EVT_ID_UNSUCCESSFUL_LOGON,
47 class AuthLogTestsNetLogonBadCreds(samba.tests.auth_log_base.AuthLogTestBase):
50 super(AuthLogTestsNetLogonBadCreds, self).setUp()
51 self.lp = samba.tests.env_loadparm()
52 self.creds = Credentials()
54 self.session = system_session()
56 session_info=self.session,
57 credentials=self.creds,
60 self.domain = os.environ["DOMAIN"]
61 self.netbios_name = "NetLogonBad"
62 self.machinepass = "abcdefghij"
63 self.remoteAddress = AS_SYSTEM_MAGIC_PATH_TOKEN
64 self.base_dn = self.ldb.domain_dn()
65 self.dn = ("cn=%s,cn=users,%s" % (self.netbios_name, self.base_dn))
67 utf16pw = get_string('"' + self.machinepass + '"').encode('utf-16-le')
70 "objectclass": "computer",
71 "sAMAccountName": "%s$" % self.netbios_name,
73 str(UF_WORKSTATION_TRUST_ACCOUNT | UF_PASSWD_NOTREQD),
74 "unicodePwd": utf16pw})
77 super(AuthLogTestsNetLogonBadCreds, self).tearDown()
78 delete_force(self.ldb, self.dn)
80 def _test_netlogon(self, name, pwd, status, checkFunction, event_id):
82 def isLastExpectedMessage(msg):
84 msg["type"] == "Authentication" and
85 msg["Authentication"]["serviceDescription"] == "NETLOGON" and
86 msg["Authentication"]["authDescription"] ==
87 "ServerAuthenticate" and
88 msg["Authentication"]["status"] == status and
89 msg["Authentication"]["eventId"] == event_id and
90 msg["Authentication"]["logonType"] == EVT_LOGON_NETWORK)
92 machine_creds = Credentials()
93 machine_creds.guess(self.get_loadparm())
94 machine_creds.set_secure_channel_type(SEC_CHAN_WKSTA)
95 machine_creds.set_password(pwd)
96 machine_creds.set_username(name + "$")
99 netlogon.netlogon("ncalrpc:[schannel]",
102 self.fail("NTSTATUSError not raised")
103 except NTSTATUSError:
106 messages = self.waitForMessages(isLastExpectedMessage)
107 checkFunction(messages)
109 def netlogon_check(self, messages):
111 expected_messages = 4
112 self.assertEquals(expected_messages,
114 "Did not receive the expected number of messages")
116 # Check the first message it should be an Authorization
118 self.assertEquals("Authorization", msg["type"])
119 self.assertEquals("DCE/RPC",
120 msg["Authorization"]["serviceDescription"])
121 self.assertEquals("ncalrpc", msg["Authorization"]["authType"])
122 self.assertEquals("NONE", msg["Authorization"]["transportProtection"])
123 self.assertTrue(self.is_guid(msg["Authorization"]["sessionId"]))
125 def test_netlogon_bad_machine_name(self):
126 self._test_netlogon("bad_name",
128 "NT_STATUS_NO_TRUST_SAM_ACCOUNT",
130 EVT_ID_UNSUCCESSFUL_LOGON)
132 def test_netlogon_bad_password(self):
133 self._test_netlogon(self.netbios_name,
135 "NT_STATUS_ACCESS_DENIED",
137 EVT_ID_UNSUCCESSFUL_LOGON)
139 def test_netlogon_password_DES(self):
140 """Logon failure that exercises the "DES" passwordType path.
142 def isLastExpectedMessage(msg):
144 msg["type"] == "Authentication" and
145 msg["Authentication"]["serviceDescription"] == "NETLOGON" and
146 msg["Authentication"]["authDescription"] ==
147 "ServerAuthenticate" and
148 msg["Authentication"]["passwordType"] == "DES" and
149 (msg["Authentication"]["eventId"] ==
150 EVT_ID_UNSUCCESSFUL_LOGON) and
151 msg["Authentication"]["logonType"] == EVT_LOGON_NETWORK)
153 c = netlogon.netlogon("ncalrpc:[schannel]", self.get_loadparm())
154 creds = netlogon.netr_Credential()
155 c.netr_ServerReqChallenge(self.server, self.netbios_name, creds)
157 c.netr_ServerAuthenticate3(self.server,
163 except NTSTATUSError:
165 self.waitForMessages(isLastExpectedMessage)
167 def test_netlogon_password_HMAC_MD5(self):
168 """Logon failure that exercises the "HMAC-MD5" passwordType path.
170 def isLastExpectedMessage(msg):
172 msg["type"] == "Authentication" and
173 msg["Authentication"]["serviceDescription"] == "NETLOGON" and
174 msg["Authentication"]["authDescription"] ==
175 "ServerAuthenticate" and
176 msg["Authentication"]["passwordType"] == "HMAC-MD5" and
177 (msg["Authentication"]["eventId"] ==
178 EVT_ID_UNSUCCESSFUL_LOGON) and
179 msg["Authentication"]["logonType"] == EVT_LOGON_NETWORK)
181 c = netlogon.netlogon("ncalrpc:[schannel]", self.get_loadparm())
182 creds = netlogon.netr_Credential()
183 c.netr_ServerReqChallenge(self.server, self.netbios_name, creds)
185 c.netr_ServerAuthenticate3(self.server,
190 NETLOGON_NEG_STRONG_KEYS)
191 except NTSTATUSError:
193 self.waitForMessages(isLastExpectedMessage)