From 0bdbbe326f0377080776afeaf9ed6438468928de Mon Sep 17 00:00:00 2001 From: Gary Lockyer Date: Mon, 10 Jul 2017 07:46:26 +1200 Subject: [PATCH 2/3] tests auth_log: Add new tests for NETLOGON Tests for the logging of NETLOGON authentications in the netr_ServerAuthenticate3 message processing BUG: https://bugzilla.samba.org/show_bug.cgi?id=12865 Signed-off-by: Gary Lockyer --- python/samba/tests/auth_log_netlogon.py | 127 ++++++++++++++++++++++ python/samba/tests/auth_log_netlogon_bad_creds.py | 127 ++++++++++++++++++++++ selftest/knownfail.d/auth-logging | 8 ++ source4/selftest/tests.py | 18 +++ 4 files changed, 280 insertions(+) create mode 100644 python/samba/tests/auth_log_netlogon.py create mode 100644 python/samba/tests/auth_log_netlogon_bad_creds.py create mode 100644 selftest/knownfail.d/auth-logging diff --git a/python/samba/tests/auth_log_netlogon.py b/python/samba/tests/auth_log_netlogon.py new file mode 100644 index 0000000..ec707dd --- /dev/null +++ b/python/samba/tests/auth_log_netlogon.py @@ -0,0 +1,127 @@ +# Unix SMB/CIFS implementation. +# Copyright (C) Andrew Bartlett 2017 +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + +""" + Tests that exercise the auth logging for a successful netlogon attempt + + NOTE: As the netlogon authentication is performed once per session, + there is only one test in this routine. If another test is added + only the test executed first will generate the netlogon auth message +""" + +import samba.tests +import os +from samba.samdb import SamDB +import samba.tests.auth_log_base +from samba.credentials import Credentials +from samba.dcerpc import netlogon +from samba.auth import system_session +from samba.tests import delete_force +from samba.dsdb import UF_WORKSTATION_TRUST_ACCOUNT, UF_PASSWD_NOTREQD +from samba.dcerpc.misc import SEC_CHAN_WKSTA + + +class AuthLogTestsNetLogon(samba.tests.auth_log_base.AuthLogTestBase): + + def setUp(self): + super(AuthLogTestsNetLogon, self).setUp() + self.lp = samba.tests.env_loadparm() + self.creds = Credentials() + + self.session = system_session() + self.ldb = SamDB( + session_info=self.session, + credentials=self.creds, + lp=self.lp) + + self.domain = os.environ["DOMAIN"] + self.netbios_name = "NetLogonGood" + self.machinepass = "abcdefghij" + self.remoteAddress = "/root/ncalrpc_as_system" + self.base_dn = self.ldb.domain_dn() + self.dn = ("cn=%s,cn=users,%s" % + (self.netbios_name, self.base_dn)) + + utf16pw = unicode( + '"' + self.machinepass.encode('utf-8') + '"', 'utf-8' + ).encode('utf-16-le') + self.ldb.add({ + "dn": self.dn, + "objectclass": "computer", + "sAMAccountName": "%s$" % self.netbios_name, + "userAccountControl": + str(UF_WORKSTATION_TRUST_ACCOUNT | UF_PASSWD_NOTREQD), + "unicodePwd": utf16pw}) + + def tearDown(self): + super(AuthLogTestsNetLogon, self).tearDown() + delete_force(self.ldb, self.dn) + + def _test_netlogon(self, binding, checkFunction): + + def isLastExpectedMessage(msg): + return ( + msg["type"] == "Authorization" and + msg["Authorization"]["serviceDescription"] == "DCE/RPC" and + msg["Authorization"]["authType"] == "schannel" and + msg["Authorization"]["transportProtection"] == "SEAL") + + if binding: + binding = "[schannel,%s]" % binding + else: + binding = "[schannel]" + + machine_creds = Credentials() + machine_creds.guess(self.get_loadparm()) + machine_creds.set_secure_channel_type(SEC_CHAN_WKSTA) + machine_creds.set_password(self.machinepass) + machine_creds.set_username(self.netbios_name + "$") + + netlogon_conn = netlogon.netlogon("ncalrpc:%s" % binding, + self.get_loadparm(), + machine_creds) + + messages = self.waitForMessages(isLastExpectedMessage, netlogon_conn) + checkFunction(messages) + + def netlogon_check(self, messages): + + expected_messages = 5 + self.assertEquals(expected_messages, + len(messages), + "Did not receive the expected number of messages") + + # Check the first message it should be an Authorization + msg = messages[0] + self.assertEquals("Authorization", msg["type"]) + self.assertEquals("DCE/RPC", + msg["Authorization"]["serviceDescription"]) + self.assertEquals("ncalrpc", msg["Authorization"]["authType"]) + self.assertEquals("NONE", msg["Authorization"]["transportProtection"]) + + # Check the fourth message it should be a NETLOGON Authentication + msg = messages[3] + self.assertEquals("Authentication", msg["type"]) + self.assertEquals("NETLOGON", + msg["Authentication"]["serviceDescription"]) + self.assertEquals("ServerAuthenticate", + msg["Authentication"]["authDescription"]) + self.assertEquals("NT_STATUS_OK", + msg["Authentication"]["status"]) + + def test_netlogon(self): + self._test_netlogon("SEAL", self.netlogon_check) diff --git a/python/samba/tests/auth_log_netlogon_bad_creds.py b/python/samba/tests/auth_log_netlogon_bad_creds.py new file mode 100644 index 0000000..b21106e --- /dev/null +++ b/python/samba/tests/auth_log_netlogon_bad_creds.py @@ -0,0 +1,127 @@ +# Unix SMB/CIFS implementation. +# Copyright (C) Andrew Bartlett 2017 +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + +""" + Tests that exercise auth logging for unsuccessful netlogon attempts. + + NOTE: netlogon is only done once per session, so this file should only + test failed logons. Adding a successful case will potentially break + the other tests, depending on the order of execution. +""" + +import samba.tests +import os +from samba import NTSTATUSError +from samba.samdb import SamDB +import samba.tests.auth_log_base +from samba.credentials import Credentials +from samba.dcerpc import netlogon +from samba.auth import system_session +from samba.tests import delete_force +from samba.dsdb import UF_WORKSTATION_TRUST_ACCOUNT, UF_PASSWD_NOTREQD +from samba.dcerpc.misc import SEC_CHAN_WKSTA + + +class AuthLogTestsNetLogonBadCreds(samba.tests.auth_log_base.AuthLogTestBase): + + def setUp(self): + super(AuthLogTestsNetLogonBadCreds, self).setUp() + self.lp = samba.tests.env_loadparm() + self.creds = Credentials() + + self.session = system_session() + self.ldb = SamDB( + session_info=self.session, + credentials=self.creds, + lp=self.lp) + + self.domain = os.environ["DOMAIN"] + self.netbios_name = "NetLogonBad" + self.machinepass = "abcdefghij" + self.remoteAddress = "/root/ncalrpc_as_system" + self.base_dn = self.ldb.domain_dn() + self.dn = ("cn=%s,cn=users,%s" % + (self.netbios_name, self.base_dn)) + + utf16pw = unicode( + '"' + self.machinepass.encode('utf-8') + '"', 'utf-8' + ).encode('utf-16-le') + self.ldb.add({ + "dn": self.dn, + "objectclass": "computer", + "sAMAccountName": "%s$" % self.netbios_name, + "userAccountControl": + str(UF_WORKSTATION_TRUST_ACCOUNT | UF_PASSWD_NOTREQD), + "unicodePwd": utf16pw}) + + def tearDown(self): + super(AuthLogTestsNetLogonBadCreds, self).tearDown() + delete_force(self.ldb, self.dn) + + def _test_netlogon(self, name, pwd, status, checkFunction): + + def isLastExpectedMessage(msg): + return ( + msg["type"] == "Authentication" and + msg["Authentication"]["serviceDescription"] == "NETLOGON" and + msg["Authentication"]["authDescription"] == + "ServerAuthenticate" and + msg["Authentication"]["status"] == status) + + machine_creds = Credentials() + machine_creds.guess(self.get_loadparm()) + machine_creds.set_secure_channel_type(SEC_CHAN_WKSTA) + machine_creds.set_password(pwd) + machine_creds.set_username(name + "$") + + try: + netlogon.netlogon("ncalrpc:[schannel,SEAL]", + self.get_loadparm(), + machine_creds) + self.fail("NTSTATUSError not raised") + except NTSTATUSError: + pass + + messages = self.waitForMessages(isLastExpectedMessage) + checkFunction(messages) + + def netlogon_check(self, messages): + + expected_messages = 4 + self.assertEquals(expected_messages, + len(messages), + "Did not receive the expected number of messages") + + # Check the first message it should be an Authorization + msg = messages[0] + self.assertEquals("Authorization", msg["type"]) + self.assertEquals("DCE/RPC", + msg["Authorization"]["serviceDescription"]) + self.assertEquals("ncalrpc", msg["Authorization"]["authType"]) + self.assertEquals("NONE", msg["Authorization"]["transportProtection"]) + + def test_netlogon_bad_machine_name(self): + self._test_netlogon("bad_name", + self.machinepass, + "NT_STATUS_NO_TRUST_SAM_ACCOUNT", + self.netlogon_check) + + def test_netlogon_bad_password(self): + self._test_netlogon(self.netbios_name, + "badpass", + "NT_STATUS_ACCESS_DENIED", + self.netlogon_check) diff --git a/selftest/knownfail.d/auth-logging b/selftest/knownfail.d/auth-logging new file mode 100644 index 0000000..e10a69e --- /dev/null +++ b/selftest/knownfail.d/auth-logging @@ -0,0 +1,8 @@ +# NETLOGON authentication logging tests, currently fail as the +# code has not been implemented +^samba.tests.auth_log_netlogon_bad_creds.samba.tests.auth_log_netlogon_bad_creds.AuthLogTestsNetLogonBadCreds.test_netlogon_bad_password\(ad_dc_ntvfs:local\) +^samba.tests.auth_log_netlogon_bad_creds.samba.tests.auth_log_netlogon_bad_creds.AuthLogTestsNetLogonBadCreds.test_netlogon_bad_machine_name\(ad_dc_ntvfs:local\) +^samba.tests.auth_log_netlogon_bad_creds.samba.tests.auth_log_netlogon_bad_creds.AuthLogTestsNetLogonBadCreds.test_netlogon_bad_password\(ad_dc:local\) +^samba.tests.auth_log_netlogon_bad_creds.samba.tests.auth_log_netlogon_bad_creds.AuthLogTestsNetLogonBadCreds.test_netlogon_bad_machine_name\(ad_dc:local\) +^samba.tests.auth_log_netlogon.samba.tests.auth_log_netlogon.AuthLogTestsNetLogon.test_netlogon\(ad_dc_ntvfs:local\) +^samba.tests.auth_log_netlogon.samba.tests.auth_log_netlogon.AuthLogTestsNetLogon.test_netlogon\(ad_dc:local\) diff --git a/source4/selftest/tests.py b/source4/selftest/tests.py index 15037a2..465a15b 100755 --- a/source4/selftest/tests.py +++ b/source4/selftest/tests.py @@ -636,6 +636,24 @@ if have_jansson_support and have_heimdal_support: extra_args=['-U"$USERNAME%$PASSWORD"'], environ={'CLIENT_IP': '127.0.0.11', 'SOCKET_WRAPPER_DEFAULT_IFACE': 11}) + planoldpythontestsuite("ad_dc:local", "samba.tests.auth_log_netlogon", + extra_args=['-U"$USERNAME%$PASSWORD"'], + environ={'CLIENT_IP': '127.0.0.11', + 'SOCKET_WRAPPER_DEFAULT_IFACE': 11}) + planoldpythontestsuite("ad_dc_ntvfs:local", "samba.tests.auth_log_netlogon", + extra_args=['-U"$USERNAME%$PASSWORD"'], + environ={'CLIENT_IP': '127.0.0.11', + 'SOCKET_WRAPPER_DEFAULT_IFACE': 11}) + planoldpythontestsuite("ad_dc:local", + "samba.tests.auth_log_netlogon_bad_creds", + extra_args=['-U"$USERNAME%$PASSWORD"'], + environ={'CLIENT_IP': '127.0.0.11', + 'SOCKET_WRAPPER_DEFAULT_IFACE': 11}) + planoldpythontestsuite("ad_dc_ntvfs:local", + "samba.tests.auth_log_netlogon_bad_creds", + extra_args=['-U"$USERNAME%$PASSWORD"'], + environ={'CLIENT_IP': '127.0.0.11', + 'SOCKET_WRAPPER_DEFAULT_IFACE': 11}) planoldpythontestsuite("ad_dc", "samba.tests.net_join_no_spnego", extra_args=['-U"$USERNAME%$PASSWORD"']) -- 2.7.4