python:tests: Store keys as bytes rather than as lists of ints
[samba.git] / python / samba / tests / smbconf.py
1 # Unix SMB/CIFS implementation.
2 # Copyright (C) Jelmer Vernooij <jelmer@samba.org> 2007
3 # Copyright (C) John Mulligan <phlogistonjohn@asynchrono.us> 2022
4 #
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.
9 #
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.
14 #
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/>.
17 #
18
19 """
20 Tests for samba.smbconf module
21 """
22
23 from samba.samba3 import param as s3param
24 import samba.tests
25
26
27 class SMBConfTests(samba.tests.TestCase):
28     _smbconf = None
29     _s3smbconf = None
30
31     @property
32     def smbconf(self):
33         """Property to access module under test without
34         importing it at test module load-time.
35         """
36         if self._smbconf is not None:
37             return self._smbconf
38
39         import samba.smbconf
40
41         self._smbconf = samba.smbconf
42         return self._smbconf
43
44     @property
45     def s3smbconf(self):
46         if self._s3smbconf is not None:
47             return self._s3smbconf
48
49         import samba.samba3.smbconf
50
51         self._s3smbconf = samba.samba3.smbconf
52         return self._s3smbconf
53
54     @property
55     def example_conf_default(self):
56         return "./testdata/samba3/smb.conf"
57
58     def setUp(self):
59         super().setUp()
60         # fetch the configuration in the same style as other test suites
61         self.lp_ctx = samba.tests.env_loadparm()
62         # apply the configuration to the samba3 configuration
63         # (because there are two... and they're independent!)
64         # this is needed to make use of the registry
65         s3_lp = s3param.get_context()
66         s3_lp.load(self.lp_ctx.configfile)
67
68     def test_uninitalized_smbconf(self):
69         sconf = self.smbconf.SMBConf()
70         self.assertRaises(RuntimeError, sconf.requires_messaging)
71         self.assertRaises(RuntimeError, sconf.is_writeable)
72         self.assertRaises(RuntimeError, sconf.share_names)
73         self.assertRaises(RuntimeError, sconf.get_share, "foo")
74
75     def test_txt_backend_properties(self):
76         sconf = self.smbconf.init_txt(self.example_conf_default)
77         self.assertFalse(sconf.requires_messaging())
78         self.assertFalse(sconf.is_writeable())
79
80     def test_share_names(self):
81         sconf = self.smbconf.init_txt(self.example_conf_default)
82         names = sconf.share_names()
83         self.assertEqual(names, ["global", "cd1", "cd2", "media", "tmp"])
84
85     def test_get_share_cd1(self):
86         sconf = self.smbconf.init_txt(self.example_conf_default)
87         s1 = sconf.get_share("cd1")
88         self.assertEqual(s1, ("cd1", [("path", "/mnt/cd1"), ("public", "yes")]))
89
90     def test_get_share_cd2(self):
91         sconf = self.smbconf.init_txt(self.example_conf_default)
92         s1 = sconf.get_share("cd2")
93         self.assertEqual(s1, ("cd2", [("path", "/mnt/cd2"), ("public", "yes")]))
94
95     def test_get_config(self):
96         sconf = self.smbconf.init_txt(self.example_conf_default)
97         services = sconf.get_config()
98         self.assertEqual(len(services), 5)
99         self.assertEqual(
100             services[0],
101             (
102                 "global",
103                 [
104                     ("workgroup", "SAMBA"),
105                     ("security", "user"),
106                     (
107                         "passdb backend",
108                         "smbpasswd:../testdata/samba3/smbpasswd "
109                         "tdbsam:../testdata/samba3/passdb.tdb ldapsam:tdb://samba3.ldb",
110                     ),
111                     ("debug level", "5"),
112                     ("netbios name", "BEDWYR"),
113                 ],
114             ),
115         )
116         self.assertEqual(
117             services[1], ("cd1", [("path", "/mnt/cd1"), ("public", "yes")])
118         )
119
120     def test_init_reg(self):
121         sconf = self.s3smbconf.init_reg(None)
122         self.assertTrue(sconf.is_writeable())
123
124     def test_init_str_reg(self):
125         sconf = self.s3smbconf.init("registry:")
126         self.assertTrue(sconf.is_writeable())
127
128     def test_init_str_file(self):
129         sconf = self.s3smbconf.init(f"file:{self.example_conf_default}")
130         self.assertFalse(sconf.is_writeable())
131
132     def test_create_share(self):
133         sconf = self.s3smbconf.init_reg(None)
134         sconf.drop()
135         sconf.create_share("alice")
136         sconf.create_share("bob")
137         names = sconf.share_names()
138         self.assertEqual(names, ["alice", "bob"])
139         self.assertRaises(
140             self.smbconf.SMBConfError, sconf.create_share, "alice"
141         )
142
143     def test_create_share(self):
144         sconf = self.s3smbconf.init_reg(None)
145         sconf.drop()
146         sconf.create_share("alice")
147         sconf.drop()
148         names = sconf.share_names()
149         self.assertEqual(names, [])
150
151     def test_set_parameter(self):
152         sconf = self.s3smbconf.init_reg(None)
153         sconf.drop()
154         sconf.create_share("foobar")
155         sconf.set_parameter("foobar", "path", "/mnt/foobar")
156         sconf.set_parameter("foobar", "browseable", "no")
157
158         s1 = sconf.get_share("foobar")
159         self.assertEqual(
160             s1, ("foobar", [("path", "/mnt/foobar"), ("browseable", "no")])
161         )
162
163     def test_set_global_parameter(self):
164         sconf = self.s3smbconf.init_reg(None)
165         sconf.drop()
166         sconf.set_global_parameter("workgroup", "EXAMPLE")
167         sconf.set_global_parameter("x:custom", "fake")
168
169         s1 = sconf.get_share("global")
170         self.assertEqual(
171             s1, ("global", [("workgroup", "EXAMPLE"), ("x:custom", "fake")])
172         )
173
174     def test_delete_share(self):
175         sconf = self.s3smbconf.init_reg(None)
176         sconf.drop()
177
178         sconf.create_share("alice")
179         sconf.create_share("bob")
180         names = sconf.share_names()
181         self.assertEqual(names, ["alice", "bob"])
182
183         sconf.delete_share("alice")
184         names = sconf.share_names()
185         self.assertEqual(names, ["bob"])
186
187     def test_create_set_share(self):
188         sconf = self.s3smbconf.init_reg(None)
189         sconf.drop()
190
191         params = [
192             ("path", "/mnt/baz"),
193             ("browseable", "yes"),
194             ("read only", "no"),
195         ]
196         sconf.create_set_share("baz", params)
197         self.assertEqual(sconf.get_share("baz"), ("baz", params))
198
199         self.assertRaises(
200             self.smbconf.SMBConfError, sconf.create_set_share, "baz", params
201         )
202         self.assertRaises(TypeError, sconf.create_set_share, "baz", None)
203         self.assertRaises(
204             ValueError, sconf.create_set_share, "baz", [None, None]
205         )
206         self.assertRaises(
207             TypeError, sconf.create_set_share, "baz", [("hi", None)]
208         )
209         self.assertRaises(
210             ValueError, sconf.create_set_share, "baz", [("a", "b", "c")]
211         )
212
213     def test_delete_parameter(self):
214         sconf = self.s3smbconf.init_reg(None)
215         sconf.drop()
216
217         params = [
218             ("path", "/mnt/baz"),
219             ("browseable", "yes"),
220             ("read only", "no"),
221         ]
222         sconf.create_set_share("baz", params)
223         self.assertEqual(sconf.get_share("baz"), ("baz", params))
224
225         sconf.delete_parameter("baz", "browseable")
226         self.assertEqual(
227             sconf.get_share("baz"),
228             (
229                 "baz",
230                 [
231                     ("path", "/mnt/baz"),
232                     ("read only", "no"),
233                 ],
234             ),
235         )
236
237     def test_delete_global_parameter(self):
238         sconf = self.s3smbconf.init_reg(None)
239         sconf.drop()
240         sconf.set_global_parameter("workgroup", "EXAMPLE")
241         sconf.set_global_parameter("client min protocol", "NT1")
242         sconf.set_global_parameter("server min protocol", "SMB2")
243
244         s1 = sconf.get_share("global")
245         self.assertEqual(
246             s1,
247             (
248                 "global",
249                 [
250                     ("workgroup", "EXAMPLE"),
251                     ("client min protocol", "NT1"),
252                     ("server min protocol", "SMB2"),
253                 ],
254             ),
255         )
256
257         sconf.delete_global_parameter("server min protocol")
258         sconf.delete_global_parameter("client min protocol")
259         s1 = sconf.get_share("global")
260         self.assertEqual(s1, ("global", [("workgroup", "EXAMPLE")]))
261
262     def test_transaction_direct(self):
263         sconf = self.s3smbconf.init_reg(None)
264         sconf.drop()
265         sconf.set_global_parameter("workgroup", "EXAMPLE")
266
267         sconf.transaction_start()
268         sconf.set_global_parameter("client min protocol", "NT1")
269         sconf.set_global_parameter("server min protocol", "SMB2")
270         sconf.transaction_cancel()
271
272         s1 = sconf.get_share("global")
273         self.assertEqual(s1, ("global", [("workgroup", "EXAMPLE")]))
274
275         sconf.transaction_start()
276         sconf.set_global_parameter("client min protocol", "NT1")
277         sconf.set_global_parameter("server min protocol", "SMB2")
278         sconf.transaction_commit()
279
280         s1 = sconf.get_share("global")
281         self.assertEqual(
282             s1,
283             (
284                 "global",
285                 [
286                     ("workgroup", "EXAMPLE"),
287                     ("client min protocol", "NT1"),
288                     ("server min protocol", "SMB2"),
289                 ],
290             ),
291         )
292
293     def test_transaction_tryexc(self):
294         sconf = self.s3smbconf.init_reg(None)
295         sconf.drop()
296
297         def _mkshares(shares):
298             sconf.transaction_start()
299             try:
300                 for name, params in shares:
301                     sconf.create_set_share(name, params)
302                 sconf.transaction_commit()
303             except Exception:
304                 sconf.transaction_cancel()
305                 raise
306
307         _mkshares(
308             [
309                 ("hello", [("path", "/srv/world")]),
310                 ("goodnight", [("path", "/srv/moon")]),
311             ]
312         )
313         # this call to _mkshares will fail the whole transaction because
314         # share name "goodnight" already exists
315         self.assertRaises(
316             self.smbconf.SMBConfError,
317             _mkshares,
318             [
319                 ("mars", [("path", "/srv/mars")]),
320                 ("goodnight", [("path", "/srv/phobos")]),
321             ],
322         )
323
324         names = sconf.share_names()
325         self.assertEqual(names, ["hello", "goodnight"])
326
327     def test_error_badfile(self):
328         with self.assertRaises(self.smbconf.SMBConfError) as raised:
329             self.smbconf.init_txt("/foo/bar/baz/_I-dont/.exist/-ok-")
330         self.assertEqual(
331             self.smbconf.SBC_ERR_BADFILE, raised.exception.error_code)
332
333     def test_error_not_supported(self):
334         sconf = self.smbconf.init_txt(self.example_conf_default)
335         with self.assertRaises(self.smbconf.SMBConfError) as raised:
336             sconf.set_global_parameter("client min protocol", "NT1")
337         self.assertEqual(
338             self.smbconf.SBC_ERR_NOT_SUPPORTED, raised.exception.error_code)
339
340     def test_error_no_such_service(self):
341         sconf = self.smbconf.init_txt(self.example_conf_default)
342         with self.assertRaises(self.smbconf.SMBConfError) as raised:
343             sconf.get_share("zilch"),
344         self.assertEqual(
345             self.smbconf.SBC_ERR_NO_SUCH_SERVICE, raised.exception.error_code)
346
347
348
349 if __name__ == "__main__":
350     import unittest
351
352     unittest.main()