ed5f8702b99545ee1fe4ef12194711459e7f9ebc
[samba.git] / python / samba / tests / gpo.py
1 # Unix SMB/CIFS implementation. Tests for smb manipulation
2 # Copyright (C) David Mulder <dmulder@suse.com> 2018
3 #
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.
8 #
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.
13 #
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/>.
16
17 import os
18 from samba import gpo, tests
19 from samba.gpclass import register_gp_extension, list_gp_extensions, \
20     unregister_gp_extension
21 from samba.param import LoadParm
22 from samba.gpclass import check_refresh_gpo_list, check_safe_path, \
23     check_guid, parse_gpext_conf, atomic_write_conf
24
25 poldir = r'\\addom.samba.example.com\sysvol\addom.samba.example.com\Policies'
26 dspath = 'CN=Policies,CN=System,DC=addom,DC=samba,DC=example,DC=com'
27 gpt_data = '[General]\nVersion=%d'
28
29 class GPOTests(tests.TestCase):
30     def setUp(self):
31         super(GPOTests, self).setUp()
32         self.server = os.environ["SERVER"]
33         self.lp = LoadParm()
34         self.lp.load_default()
35         self.creds = self.insta_creds(template=self.get_credentials())
36
37     def tearDown(self):
38         super(GPOTests, self).tearDown()
39
40     def test_gpo_list(self):
41         global poldir, dspath
42         ads = gpo.ADS_STRUCT(self.server, self.lp, self.creds)
43         if ads.connect():
44             gpos = ads.get_gpo_list(self.creds.get_username())
45         guid = '{31B2F340-016D-11D2-945F-00C04FB984F9}'
46         names = ['Local Policy', guid]
47         file_sys_paths = [None, '%s\\%s' % (poldir, guid)]
48         ds_paths = [None, 'CN=%s,%s' % (guid, dspath)]
49         for i in range(0, len(gpos)):
50             self.assertEquals(gpos[i].name, names[i],
51                               'The gpo name did not match expected name %s' % gpos[i].name)
52             self.assertEquals(gpos[i].file_sys_path, file_sys_paths[i],
53                               'file_sys_path did not match expected %s' % gpos[i].file_sys_path)
54             self.assertEquals(gpos[i].ds_path, ds_paths[i],
55                               'ds_path did not match expected %s' % gpos[i].ds_path)
56
57
58     def test_gpo_ads_does_not_segfault(self):
59         try:
60             ads = gpo.ADS_STRUCT(self.server, 42, self.creds)
61         except:
62             pass
63
64     def test_gpt_version(self):
65         global gpt_data
66         local_path = self.lp.cache_path('gpo_cache')
67         policies = 'ADDOM.SAMBA.EXAMPLE.COM/POLICIES'
68         guid = '{31B2F340-016D-11D2-945F-00C04FB984F9}'
69         gpo_path = os.path.join(local_path, policies, guid)
70         old_vers = gpo.gpo_get_sysvol_gpt_version(gpo_path)[1]
71
72         with open(os.path.join(gpo_path, 'GPT.INI'), 'w') as gpt:
73             gpt.write(gpt_data % 42)
74         self.assertEquals(gpo.gpo_get_sysvol_gpt_version(gpo_path)[1], 42,
75                           'gpo_get_sysvol_gpt_version() did not return the expected version')
76
77         with open(os.path.join(gpo_path, 'GPT.INI'), 'w') as gpt:
78             gpt.write(gpt_data % old_vers)
79         self.assertEquals(gpo.gpo_get_sysvol_gpt_version(gpo_path)[1], old_vers,
80                           'gpo_get_sysvol_gpt_version() did not return the expected version')
81
82     def test_check_refresh_gpo_list(self):
83         cache = self.lp.cache_path('gpo_cache')
84         ads = gpo.ADS_STRUCT(self.server, self.lp, self.creds)
85         if ads.connect():
86             gpos = ads.get_gpo_list(self.creds.get_username())
87         check_refresh_gpo_list(self.server, self.lp, self.creds, gpos)
88
89         self.assertTrue(os.path.exists(cache),
90                         'GPO cache %s was not created' % cache)
91
92         guid = '{31B2F340-016D-11D2-945F-00C04FB984F9}'
93         gpt_ini = os.path.join(cache, 'ADDOM.SAMBA.EXAMPLE.COM/POLICIES',
94                                guid, 'GPT.INI')
95         self.assertTrue(os.path.exists(gpt_ini),
96                         'GPT.INI was not cached for %s' % guid)
97
98     def test_check_refresh_gpo_list_malicious_paths(self):
99         # the path cannot contain ..
100         path = '/usr/local/samba/var/locks/sysvol/../../../../../../root/'
101         self.assertRaises(OSError, check_safe_path, path)
102
103         self.assertEqual(check_safe_path('/etc/passwd'), 'etc/passwd')
104         self.assertEqual(check_safe_path('\\\\etc/\\passwd'), 'etc/passwd')
105
106         # there should be no backslashes used to delineate paths
107         before = 'sysvol/addom.samba.example.com\\Policies/' \
108             '{31B2F340-016D-11D2-945F-00C04FB984F9}\\GPT.INI'
109         after = 'addom.samba.example.com/Policies/' \
110             '{31B2F340-016D-11D2-945F-00C04FB984F9}/GPT.INI'
111         result = check_safe_path(before)
112         self.assertEquals(result, after, 'check_safe_path() didn\'t' \
113                           ' correctly convert \\ to /')
114
115     def test_gpt_ext_register(self):
116         this_path = os.path.dirname(os.path.realpath(__file__))
117         samba_path = os.path.realpath(os.path.join(this_path, '../../../'))
118         ext_path = os.path.join(samba_path, 'python/samba/gp_sec_ext.py')
119         ext_guid = '{827D319E-6EAC-11D2-A4EA-00C04F79F83A}'
120         ret = register_gp_extension(ext_guid, 'gp_sec_ext', ext_path,
121                                     smb_conf=self.lp.configfile,
122                                     machine=True, user=False)
123         self.assertTrue(ret, 'Failed to register a gp ext')
124         gp_exts = list_gp_extensions(self.lp.configfile)
125         self.assertTrue(ext_guid in gp_exts.keys(),
126                         'Failed to list gp exts')
127         self.assertEquals(gp_exts[ext_guid]['DllName'], ext_path,
128                           'Failed to list gp exts')
129
130         unregister_gp_extension(ext_guid)
131         gp_exts = list_gp_extensions(self.lp.configfile)
132         self.assertTrue(ext_guid not in gp_exts.keys(),
133                         'Failed to unregister gp exts')
134
135         self.assertTrue(check_guid(ext_guid), 'Failed to parse valid guid')
136         self.assertFalse(check_guid('AAAAAABBBBBBBCCC'), 'Parsed invalid guid')
137
138         lp, parser = parse_gpext_conf(self.lp.configfile)
139         self.assertTrue(lp and parser, 'parse_gpext_conf() invalid return')
140         parser.add_section('test_section')
141         parser.set('test_section', 'test_var', ext_guid)
142         atomic_write_conf(lp, parser)
143
144         lp, parser = parse_gpext_conf(self.lp.configfile)
145         self.assertTrue('test_section' in parser.sections(),
146                         'test_section not found in gpext.conf')
147         self.assertEquals(parser.get('test_section', 'test_var'), ext_guid,
148                           'Failed to find test variable in gpext.conf')
149         parser.remove_section('test_section')
150         atomic_write_conf(lp, parser)
151