s3:ntlm_auth: make logs more consistent with length check
[Samba.git] / python / samba / tests / samba_startup_fl_change.py
blob54fa9f820c64d68dd746c2a63e5a41a66bd538ae
1 # Unix SMB/CIFS implementation. Tests for dsdb
2 # Copyright (C) Andrew Bartlett <abartlet@samba.org> 2023
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 samba.dsdb."""
20 from samba.credentials import Credentials
21 from samba.samdb import SamDB
22 from samba.auth import system_session
23 from samba.param import LoadParm
24 from samba import dsdb, functional_level
25 import ldb
28 from samba.tests.samba_tool.base import SambaToolCmdTest
29 import os
30 import shutil
31 import tempfile
33 class SambaFLStartUpTests(SambaToolCmdTest):
34 """Test the samba binary sets the DC FL on startup for RW DCs"""
36 @classmethod
37 def setUpClass(cls):
38 super().setUpClass()
39 cls.classtempdir = tempfile.mkdtemp()
40 cls.tempsambadir = os.path.join(cls.classtempdir, "samba")
42 command = (
43 "samba-tool " +
44 "domain provision " +
45 "--realm=foo.example.com " +
46 "--domain=FOO " +
47 ("--targetdir=%s " % cls.tempsambadir) +
48 "--use-ntvfs"
51 (result, out, err) = cls.run_command(command)
52 if (result != 0):
53 raise AssertionError
55 @classmethod
56 def tearDownClass(cls):
57 super().tearDownClass()
58 shutil.rmtree(cls.tempsambadir)
60 def setUp(self):
61 super().setUp()
62 path = os.path.join(self.tempsambadir, "etc/smb.conf")
63 self.lp = LoadParm(filename_for_non_global_lp=path)
64 self.creds = Credentials()
65 self.creds.guess(self.lp)
66 self.session = system_session()
67 self.samdb = SamDB(session_info=self.session,
68 credentials=self.creds,
69 lp=self.lp)
72 def test_initial_db_fl_state(self):
73 server_dn = self.samdb.get_dsServiceName()
74 res = self.samdb.search(base=server_dn,
75 scope=ldb.SCOPE_BASE,
76 attrs=["msDS-Behavior-Version"])
77 # This confirms the domain is in FL 2008 R2 by default, this is
78 # important to verify the original state
79 self.assertEqual(int(res[0]["msDS-Behavior-Version"][0]),
80 dsdb.DS_DOMAIN_FUNCTION_2008_R2)
82 def test_initial_rootdse_domain_fl_state(self):
83 res = self.samdb.search(base="",
84 scope=ldb.SCOPE_BASE,
85 attrs=["domainControllerFunctionality"])
86 self.assertEqual(int(res[0]["domainControllerFunctionality"][0]),
87 dsdb.DS_DOMAIN_FUNCTION_2008_R2)
89 def test_initial_rootdse_dc_fl_state(self):
90 res = self.samdb.search(base="",
91 scope=ldb.SCOPE_BASE,
92 attrs=["domainFunctionality"])
93 self.assertEqual(int(res[0]["domainFunctionality"][0]),
94 dsdb.DS_DOMAIN_FUNCTION_2008_R2)
96 def test_initial_lp_fl_state(self):
97 lp_fl = self.lp.get("ad dc functional level")
98 # This confirms the domain is in FL 2008 R2 by default, this is
99 # important to verify the original state
100 self.assertEqual(lp_fl, "2008_R2")
102 def test_initial_lp_fl_state_mapped(self):
103 # Confirm the same via the dc_level_from_lp wrapper
104 self.assertEqual(functional_level.dc_level_from_lp(self.lp),
105 dsdb.DS_DOMAIN_FUNCTION_2008_R2)
107 def fixup_fl(self, dn, fl):
108 msg = ldb.Message()
109 msg.dn = dn
110 msg["msDS-Behavior-Version"] = (
111 ldb.MessageElement(str(fl),
112 ldb.FLAG_MOD_REPLACE,
113 "msDS-Behavior-Version"))
114 self.samdb.modify(msg)
116 def test_change_db_dc_fl(self):
117 server_dn = ldb.Dn(self.samdb, self.samdb.get_dsServiceName())
118 msg = ldb.Message()
119 msg.dn = server_dn
120 msg["msDS-Behavior-Version"] = (
121 ldb.MessageElement(str(dsdb.DS_DOMAIN_FUNCTION_2012_R2),
122 ldb.FLAG_MOD_REPLACE,
123 "msDS-Behavior-Version"))
124 self.samdb.modify(msg)
125 self.addCleanup(self.fixup_fl, msg.dn, dsdb.DS_DOMAIN_FUNCTION_2008_R2)
127 samdb2 = SamDB(session_info=self.session,
128 credentials=self.creds,
129 lp=self.lp)
131 # Check that the DB set to 2012_R2 has got as far as the rootDSE handler on a new connection
132 res = samdb2.search(base="",
133 scope=ldb.SCOPE_BASE,
134 attrs=["domainControllerFunctionality"])
135 self.assertEqual(int(res[0]["domainControllerFunctionality"][0]),
136 dsdb.DS_DOMAIN_FUNCTION_2012_R2)
138 def test_incorrect_db_dc_fl(self):
139 server_dn = ldb.Dn(self.samdb, self.samdb.get_dsServiceName())
140 self.addCleanup(self.fixup_fl, server_dn, dsdb.DS_DOMAIN_FUNCTION_2008_R2)
142 old_lp_fl = self.lp.get("ad dc functional level")
143 self.lp.set("ad dc functional level",
144 "2016")
145 self.addCleanup(self.lp.set, "ad dc functional level", old_lp_fl)
147 dsdb.check_and_update_fl(self.samdb, self.lp)
149 # Check this has been set to 2016 per the smb.conf setting
150 res = self.samdb.search(base="",
151 scope=ldb.SCOPE_BASE,
152 attrs=["domainControllerFunctionality"])
153 self.assertEqual(int(res[0]["domainControllerFunctionality"][0]),
154 dsdb.DS_DOMAIN_FUNCTION_2016)
156 samdb3 = SamDB(session_info=self.session,
157 credentials=self.creds,
158 lp=self.lp)
160 # Check this is still set on re-read (not just the opaque)
161 res = samdb3.search(base="",
162 scope=ldb.SCOPE_BASE,
163 attrs=["domainControllerFunctionality"])
164 self.assertEqual(int(res[0]["domainControllerFunctionality"][0]),
165 dsdb.DS_DOMAIN_FUNCTION_2016)
167 res = self.samdb.search(base=server_dn,
168 scope=ldb.SCOPE_BASE,
169 attrs=["msDS-Behavior-Version"])
170 self.assertEqual(int(res[0]["msDS-Behavior-Version"][0]),
171 dsdb.DS_DOMAIN_FUNCTION_2016)
173 self.assertEqual(functional_level.dc_level_from_lp(self.lp),
174 dsdb.DS_DOMAIN_FUNCTION_2016)
175 self.assertEqual(self.lp.get("ad dc functional level"),
176 "2016")
178 if __name__ == "__main__":
179 import unittest
180 unittest.main()