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
.common
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
):
51 self
.lp
= samba
.tests
.env_loadparm()
52 self
.session
= system_session()
54 session_info
=self
.session
,
57 self
.domain
= os
.environ
["DOMAIN"]
58 self
.netbios_name
= "NetLogonBad"
59 self
.machinepass
= "abcdefghij"
60 self
.remoteAddress
= AS_SYSTEM_MAGIC_PATH_TOKEN
61 self
.base_dn
= self
.ldb
.domain_dn()
62 self
.dn
= ("cn=%s,cn=users,%s" % (self
.netbios_name
, self
.base_dn
))
64 utf16pw
= get_string('"' + self
.machinepass
+ '"').encode('utf-16-le')
67 "objectclass": "computer",
68 "sAMAccountName": "%s$" % self
.netbios_name
,
70 str(UF_WORKSTATION_TRUST_ACCOUNT | UF_PASSWD_NOTREQD
),
71 "unicodePwd": utf16pw
})
75 delete_force(self
.ldb
, self
.dn
)
77 def _test_netlogon(self
, name
, pwd
, status
, checkFunction
, event_id
):
79 def isLastExpectedMessage(msg
):
81 msg
["type"] == "Authentication" and
82 msg
["Authentication"]["serviceDescription"] == "NETLOGON" and
83 msg
["Authentication"]["authDescription"] ==
84 "ServerAuthenticate" and
85 msg
["Authentication"]["status"] == status
and
86 msg
["Authentication"]["eventId"] == event_id
and
87 msg
["Authentication"]["logonType"] == EVT_LOGON_NETWORK
)
89 machine_creds
= Credentials()
90 machine_creds
.guess(self
.get_loadparm())
91 machine_creds
.set_secure_channel_type(SEC_CHAN_WKSTA
)
92 machine_creds
.set_password(pwd
)
93 machine_creds
.set_username(name
+ "$")
96 netlogon
.netlogon("ncalrpc:[schannel]",
99 self
.fail("NTSTATUSError not raised")
100 except NTSTATUSError
:
103 messages
= self
.waitForMessages(isLastExpectedMessage
)
104 checkFunction(messages
)
106 def netlogon_check(self
, messages
):
108 expected_messages
= 4
109 self
.assertEqual(expected_messages
,
111 "Did not receive the expected number of messages")
113 # Check the first message it should be an Authorization
115 self
.assertEqual("Authorization", msg
["type"])
116 self
.assertEqual("DCE/RPC",
117 msg
["Authorization"]["serviceDescription"])
118 self
.assertEqual("ncalrpc", msg
["Authorization"]["authType"])
119 self
.assertEqual("NONE", msg
["Authorization"]["transportProtection"])
120 self
.assertTrue(self
.is_guid(msg
["Authorization"]["sessionId"]))
122 def test_netlogon_bad_machine_name(self
):
123 self
._test
_netlogon
("bad_name",
125 "NT_STATUS_NO_TRUST_SAM_ACCOUNT",
127 EVT_ID_UNSUCCESSFUL_LOGON
)
129 def test_netlogon_bad_password(self
):
130 self
._test
_netlogon
(self
.netbios_name
,
132 "NT_STATUS_ACCESS_DENIED",
134 EVT_ID_UNSUCCESSFUL_LOGON
)
136 def test_netlogon_password_DES(self
):
137 """Logon failure that exercises the "DES" passwordType path.
139 def isLastExpectedMessage(msg
):
141 msg
["type"] == "Authentication" and
142 msg
["Authentication"]["serviceDescription"] == "NETLOGON" and
143 msg
["Authentication"]["authDescription"] ==
144 "ServerAuthenticate" and
145 msg
["Authentication"]["passwordType"] == "DES" and
146 (msg
["Authentication"]["eventId"] ==
147 EVT_ID_UNSUCCESSFUL_LOGON
) and
148 msg
["Authentication"]["logonType"] == EVT_LOGON_NETWORK
)
150 c
= netlogon
.netlogon("ncalrpc:[schannel]", self
.get_loadparm())
151 creds
= netlogon
.netr_Credential()
152 c
.netr_ServerReqChallenge(self
.server
, self
.netbios_name
, creds
)
154 c
.netr_ServerAuthenticate3(self
.server
,
160 except NTSTATUSError
:
164 self
.waitForMessages(isLastExpectedMessage
)
166 def test_netlogon_password_HMAC_MD5(self
):
167 """Logon failure that exercises the "HMAC-MD5" passwordType path.
169 def isLastExpectedMessage(msg
):
171 msg
["type"] == "Authentication" and
172 msg
["Authentication"]["serviceDescription"] == "NETLOGON" and
173 msg
["Authentication"]["authDescription"] ==
174 "ServerAuthenticate" and
175 msg
["Authentication"]["passwordType"] == "HMAC-MD5" and
176 (msg
["Authentication"]["eventId"] ==
177 EVT_ID_UNSUCCESSFUL_LOGON
) and
178 msg
["Authentication"]["logonType"] == EVT_LOGON_NETWORK
)
180 c
= netlogon
.netlogon("ncalrpc:[schannel]", self
.get_loadparm())
181 creds
= netlogon
.netr_Credential()
182 c
.netr_ServerReqChallenge(self
.server
, self
.netbios_name
, creds
)
184 c
.netr_ServerAuthenticate3(self
.server
,
189 NETLOGON_NEG_STRONG_KEYS
)
190 except NTSTATUSError
:
194 self
.waitForMessages(isLastExpectedMessage
)