From d2b284983b3aa6f4175e72be3ac60dd239d8d44e Mon Sep 17 00:00:00 2001 From: Garming Sam Date: Wed, 24 Jul 2019 15:18:40 +1200 Subject: [PATCH 1/3] netcmd: Allow drs replicate --local to create partitions Currently, neither the offline (--local) or online (normal replica sync) methods allow partition creation post-join. This overrides the Python default to not create the DB, which allows TDB + MDB to work. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14051 Signed-off-by: Garming Sam Reviewed-by: Andrew Bartlett (cherry picked from commit d90ccce59754bc833027c06683afac25f7a8d474) --- python/samba/netcmd/drs.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/python/samba/netcmd/drs.py b/python/samba/netcmd/drs.py index e6b892c2877..5c20d6be6f3 100644 --- a/python/samba/netcmd/drs.py +++ b/python/samba/netcmd/drs.py @@ -448,8 +448,10 @@ class cmd_drs_replicate(Command): self.server = SOURCE_DC drsuapi_connect(self) + # Override the default flag LDB_FLG_DONT_CREATE_DB self.local_samdb = SamDB(session_info=system_session(), url=None, - credentials=self.creds, lp=self.lp) + credentials=self.creds, lp=self.lp, + flags=0) self.samdb = SamDB(url="ldap://%s" % self.server, session_info=system_session(), -- 2.17.1 From 0fd1807a3522e92e4643d59bc0e9aaf775dbf0bd Mon Sep 17 00:00:00 2001 From: Garming Sam Date: Wed, 24 Jul 2019 15:13:43 +1200 Subject: [PATCH 2/3] tests: Add samba_upgradedns to the list of possible cmds This will be used to test the replication scenario with no DNS partitions BUG: https://bugzilla.samba.org/show_bug.cgi?id=14051 Signed-off-by: Garming Sam Reviewed-by: Andrew Bartlett (cherry picked from commit 7d2875bd70cf727730be8dc705bfd01eacaaaa6f) --- python/samba/tests/__init__.py | 1 + 1 file changed, 1 insertion(+) diff --git a/python/samba/tests/__init__.py b/python/samba/tests/__init__.py index f904499b90b..15824bd410a 100644 --- a/python/samba/tests/__init__.py +++ b/python/samba/tests/__init__.py @@ -402,6 +402,7 @@ class BlackboxTestCase(TestCaseInTempDir): python_cmds = ["samba-tool", "samba_dnsupdate", + "samba_upgradedns", "script/traffic_replay", "script/traffic_learner"] -- 2.17.1 From de3db0f54d47e8e95b21cf867a70e4aefee26fd9 Mon Sep 17 00:00:00 2001 From: Garming Sam Date: Wed, 24 Jul 2019 14:53:33 +1200 Subject: [PATCH 3/3] tests/drs_no_dns: Check dbcheck and ldapcmp pass When joining a DC without DNS partitions, make sure that the alternate flow of creating them afterwards results in a database with everything that is necessary. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14051 RN: Allow a DC join without DNS partitions, to add them later Signed-off-by: Garming Sam Reviewed-by: Andrew Bartlett (cherry picked from commit 35c54007e6183829d9d85a24b3bd95f469739ad3) --- source4/selftest/tests.py | 7 + .../drs/python/samba_tool_drs_no_dns.py | 183 ++++++++++++++++++ 2 files changed, 190 insertions(+) create mode 100644 source4/torture/drs/python/samba_tool_drs_no_dns.py diff --git a/source4/selftest/tests.py b/source4/selftest/tests.py index 30fedd9803e..cb42303ccd0 100755 --- a/source4/selftest/tests.py +++ b/source4/selftest/tests.py @@ -906,6 +906,13 @@ for env in ['backupfromdc', 'offlinebackupdc', 'restoredc', 'renamedc', plantestsuite("samba4.blackbox.join_ldapcmp", env, ["PYTHON=%s" % python, os.path.join(bbdir, "join_ldapcmp.sh")]) +env = 'backupfromdc' +planoldpythontestsuite("%s:local" % env, "samba_tool_drs_no_dns", + extra_path=[os.path.join(samba4srcdir, 'torture/drs/python')], + name="samba4.drs.samba_tool_drs_no_dns.python(%s)" % env, + environ={'DC1': '$DC_SERVER', 'DC2': '$DC_SERVER'}, + extra_args=['-U$DOMAIN/$DC_USERNAME%$DC_PASSWORD']) + plantestsuite_loadlist("samba4.ldap.rodc.python(rodc)", "rodc", [python, os.path.join(samba4srcdir, "dsdb/tests/python/rodc.py"), diff --git a/source4/torture/drs/python/samba_tool_drs_no_dns.py b/source4/torture/drs/python/samba_tool_drs_no_dns.py new file mode 100644 index 00000000000..b9cab49e82b --- /dev/null +++ b/source4/torture/drs/python/samba_tool_drs_no_dns.py @@ -0,0 +1,183 @@ +# Blackbox tests for "samba-tool drs" command +# Copyright (C) Kamen Mazdrashki 2011 +# Copyright (C) Andrew Bartlett 2017 +# Copyright (C) Catalyst.Net Ltd 2019 +# +# 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 . +# + +""" +Blackbox tests for samba-tool drs with no DNS partitions + +Adapted from samba_tool_drs.py +""" + +import samba.tests +import shutil +import os +import ldb +import drs_base + +from samba.tests import BlackboxProcessError +from samba.compat import get_string + + +class SambaToolDrsNoDnsTests(drs_base.DrsBaseTestCase): + """Blackbox test case for samba-tool drs.""" + + def setUp(self): + super(SambaToolDrsNoDnsTests, self).setUp() + + self.dc1 = samba.tests.env_get_var_value("DC1") + + creds = self.get_credentials() + self.cmdline_creds = "-U%s/%s%%%s" % (creds.get_domain(), + creds.get_username(), creds.get_password()) + + def tearDown(self): + self._enable_inbound_repl(self.dnsname_dc1) + + try: + shutil.rmtree(os.path.join(self.tempdir, "private")) + shutil.rmtree(os.path.join(self.tempdir, "etc")) + shutil.rmtree(os.path.join(self.tempdir, "msg.lock")) + os.remove(os.path.join(self.tempdir, "names.tdb")) + shutil.rmtree(os.path.join(self.tempdir, "state")) + shutil.rmtree(os.path.join(self.tempdir, "bind-dns")) + except Exception: + pass + + super(SambaToolDrsNoDnsTests, self).tearDown() + + def _get_rootDSE(self, dc, ldap_only=True): + samdb = samba.tests.connect_samdb(dc, lp=self.get_loadparm(), + credentials=self.get_credentials(), + ldap_only=ldap_only) + return samdb.search(base="", scope=samba.tests.ldb.SCOPE_BASE)[0], samdb + + def test_samba_tool_replicate_local_no_dns_tdb(self): + self.backend = 'tdb' + self._test_samba_tool_replicate_local_no_dns() + + def test_samba_tool_replicate_local_no_dns_mdb(self): + self.backend = 'mdb' + self._test_samba_tool_replicate_local_no_dns() + + def _test_samba_tool_replicate_local_no_dns(self): + """Check we can provision a database without DNS partitions + (and then add them afterwards).""" + + server_rootdse, _ = self._get_rootDSE(self.dc1) + nc_name = server_rootdse["defaultNamingContext"] + server_ldap_service_name = str(server_rootdse["ldapServiceName"][0]) + server_realm = server_ldap_service_name.split(":")[0] + creds = self.get_credentials() + + # We have to give it a different netbiosname every time + # it runs, otherwise the collision causes strange issues + # to happen. This should be different on different environments. + netbiosname = "dns" + self.backend + self.dc1 + if len(netbiosname) > 15: + netbiosname = netbiosname[:15] + + out = self.check_output("samba-tool domain join %s dc --server=%s %s --targetdir=%s --option=netbiosname=%s %s --backend-store=%s" + % (server_realm, self.dc1, self.cmdline_creds, + self.tempdir, netbiosname, + "--dns-backend=NONE", + self.backend)) + + new_dc_config_file = os.path.join(self.tempdir, "etc", "smb.conf") + new_dc_sam = os.path.join(self.tempdir, "private", "sam.ldb") + + forestdns_dn = ldb.binary_encode('DC=ForestDNSZones,' + str(nc_name)) + domaindns_dn = ldb.binary_encode('DC=DomainDNSZones,' + str(nc_name)) + + self.check_output("samba-tool drs replicate --local %s %s %s %s -s %s --full-sync" + % ("invalid", self.dc1, forestdns_dn, + self.cmdline_creds, new_dc_config_file)) + + self.check_output("samba-tool drs replicate --local %s %s %s %s -s %s --full-sync" + % ("invalid", self.dc1, domaindns_dn, + self.cmdline_creds, new_dc_config_file)) + + server_rootdse, samdb = self._get_rootDSE("ldb://" + new_dc_sam, ldap_only=False) + server_ds_name = ldb.binary_encode(server_rootdse["dsServiceName"][0].decode('utf-8')) + + # Show that Has-Master-NCs is fixed by samba_upgradedns + res = samdb.search(base=server_ds_name, + expression="(msds-hasmasterncs=%s)" % forestdns_dn) + self.assertEquals(len(res), 0) + res = samdb.search(base=server_ds_name, + expression="(msds-hasmasterncs=%s)" % domaindns_dn) + self.assertEquals(len(res), 0) + + self.check_output("samba_upgradedns -s %s" % (new_dc_config_file)) + + res = samdb.search(base=server_ds_name, + expression="(msds-hasmasterncs=%s)" % forestdns_dn) + self.assertEquals(len(res), 1) + res = samdb.search(base=server_ds_name, + expression="(msds-hasmasterncs=%s)" % domaindns_dn) + self.assertEquals(len(res), 1) + + # Show that replica locations is fixed by dbcheck + res = samdb.search(controls=["search_options:1:2"], + expression="(&(msds-nc-replica-locations=%s)(ncname=%s))" + % (server_ds_name, forestdns_dn)) + self.assertEquals(len(res), 0) + res = samdb.search(controls=["search_options:1:2"], + expression="(&(msds-nc-replica-locations=%s)(ncname=%s))" + % (server_ds_name, domaindns_dn)) + self.assertEquals(len(res), 0) + + try: + # This fixes any forward-link-backward-link issues with the tools + self.check_output("samba-tool dbcheck -s %s --cross-ncs --fix --yes" % (new_dc_config_file)) + except BlackboxProcessError as e: + self.assertTrue("Checked " in get_string(e.stdout)) + + self.check_output("samba-tool dbcheck -s %s --cross-ncs" % (new_dc_config_file)) + + # Compare the two directories + self.check_output("samba-tool ldapcmp ldap://%s ldb://%s %s --filter=%s" % + (self.dc1, new_dc_sam, self.cmdline_creds, + "msDs-masteredBy,msDS-NC-Replica-Locations,msDS-hasMasterNCs")) + + # Check all ForestDNS connections and backlinks + res = samdb.search(base=server_ds_name, + expression="(msds-hasmasterncs=%s)" % forestdns_dn) + self.assertEquals(len(res), 1) + res = samdb.search(base=forestdns_dn, + expression="(msds-masteredby=%s)" % server_ds_name) + self.assertEquals(len(res), 1) + res = samdb.search(controls=["search_options:1:2"], + expression="(&(msds-nc-replica-locations=%s)(ncname=%s))" + % (server_ds_name, forestdns_dn)) + self.assertEquals(len(res), 1) + + # Check all DomainDNS connections and backlinks + res = samdb.search(base=server_ds_name, + expression="(msds-hasmasterncs=%s)" % domaindns_dn) + self.assertEquals(len(res), 1) + res = samdb.search(base=domaindns_dn, + expression="(msds-masteredby=%s)" % server_ds_name) + self.assertEquals(len(res), 1) + res = samdb.search(controls=["search_options:1:2"], + expression="(&(msds-nc-replica-locations=%s)(ncname=%s))" + % (server_ds_name, domaindns_dn)) + self.assertEquals(len(res), 1) + + # Demote the DC we created in the test + self.check_output("samba-tool domain demote --remove-other-dead-server=%s -H ldap://%s %s -s %s" + % (netbiosname, self.dc1, self.cmdline_creds, new_dc_config_file)) -- 2.17.1