1 # gp_sec_ext kdc gpo policy
2 # Copyright (C) Luke Morrison <luc785@.hotmail.com> 2013
3 # Copyright (C) David Mulder <dmulder@suse.com> 2018
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.
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.
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/>.
19 from samba.gpclass import gp_ext_setter, gp_inf_ext
20 from samba.auth import system_session
21 from samba.compat import get_string
23 from ldb import LdbError
24 from samba.samdb import SamDB
29 class gp_krb_ext(gp_inf_ext):
30 apply_map = { 'MaxTicketAge': 'kdc:user_ticket_lifetime',
31 'MaxServiceAge': 'kdc:service_ticket_lifetime',
32 'MaxRenewAge': 'kdc:renewal_lifetime' }
33 def process_group_policy(self, deleted_gpo_list, changed_gpo_list):
34 if self.lp.get('server role') != 'active directory domain controller':
36 inf_file = 'MACHINE/Microsoft/Windows NT/SecEdit/GptTmpl.inf'
37 for gpo in deleted_gpo_list:
38 self.gp_db.set_guid(gpo[0])
39 for section in gpo[1].keys():
40 if section == str(self):
41 for att, value in gpo[1][section].items():
42 update_samba, _ = self.mapper().get(att)
43 update_samba(att, value)
44 self.gp_db.delete(section, att)
47 for gpo in changed_gpo_list:
49 self.gp_db.set_guid(gpo.name)
50 path = os.path.join(gpo.file_sys_path, inf_file)
51 inf_conf = self.parse(path)
54 for section in inf_conf.sections():
55 if section == str(self):
56 for key, value in inf_conf.items(section):
57 att = gp_krb_ext.apply_map[key]
58 (update_samba, value_func) = self.mapper().get(att)
59 update_samba(att, value_func(value))
62 def mins_to_hours(self, val):
63 return '%d' % (int(val) / 60)
65 def days_to_hours(self, val):
66 return '%d' % (int(val) * 24)
68 def set_kdc_tdb(self, attribute, val):
69 old_val = self.gp_db.gpostore.get(attribute)
70 self.logger.info('%s was changed from %s to %s' % (attribute,
73 self.gp_db.gpostore.store(attribute, get_string(val))
74 self.gp_db.store(str(self), attribute, get_string(old_val) \
77 self.gp_db.gpostore.delete(attribute)
78 self.gp_db.delete(str(self), attribute)
81 return {'kdc:user_ticket_lifetime': (self.set_kdc_tdb,
83 'kdc:service_ticket_lifetime': (self.set_kdc_tdb,
85 'kdc:renewal_lifetime': (self.set_kdc_tdb,
90 return 'Kerberos Policy'
94 inf_file = 'MACHINE/Microsoft/Windows NT/SecEdit/GptTmpl.inf'
96 path = os.path.join(gpo.file_sys_path, inf_file)
97 inf_conf = self.parse(path)
100 for section in inf_conf.sections():
101 output[section] = {k: v for k, v in inf_conf.items(section) \
102 if gp_krb_ext.apply_map.get(k)}
106 class gp_access_ext(gp_inf_ext):
107 '''This class takes the .inf file parameter (essentially a GPO file mapped
108 to a GUID), hashmaps it to the Samba parameter, which then uses an ldb
109 object to update the parameter to Samba4. Not registry oriented whatsoever.
112 def __init__(self, *args):
113 super().__init__(*args)
115 self.ldb = SamDB(self.lp.samdb_url(),
116 session_info=system_session(),
117 credentials=self.creds,
119 except (NameError, LdbError):
120 raise Exception('Failed to load SamDB for assigning Group Policy')
122 apply_map = { 'MinimumPasswordAge': 'minPwdAge',
123 'MaximumPasswordAge': 'maxPwdAge',
124 'MinimumPasswordLength': 'minPwdLength',
125 'PasswordComplexity': 'pwdProperties' }
126 def process_group_policy(self, deleted_gpo_list, changed_gpo_list):
127 if self.lp.get('server role') != 'active directory domain controller':
129 inf_file = 'MACHINE/Microsoft/Windows NT/SecEdit/GptTmpl.inf'
130 for gpo in deleted_gpo_list:
131 self.gp_db.set_guid(gpo[0])
132 for section in gpo[1].keys():
133 if section == str(self):
134 for att, value in gpo[1][section].items():
135 update_samba, _ = self.mapper().get(att)
136 update_samba(att, value)
137 self.gp_db.delete(section, att)
140 for gpo in changed_gpo_list:
141 if gpo.file_sys_path:
142 self.gp_db.set_guid(gpo.name)
143 path = os.path.join(gpo.file_sys_path, inf_file)
144 inf_conf = self.parse(path)
147 for section in inf_conf.sections():
148 if section == str(self):
149 for key, value in inf_conf.items(section):
150 att = gp_access_ext.apply_map[key]
151 (update_samba, value_func) = self.mapper().get(att)
152 update_samba(att, value_func(value))
155 def ch_minPwdAge(self, attribute, val):
156 old_val = self.ldb.get_minPwdAge()
157 self.logger.info('KDC Minimum Password age was changed from %s to %s'
159 self.gp_db.store(str(self), attribute, str(old_val))
160 self.ldb.set_minPwdAge(val)
162 def ch_maxPwdAge(self, attribute, val):
163 old_val = self.ldb.get_maxPwdAge()
164 self.logger.info('KDC Maximum Password age was changed from %s to %s'
166 self.gp_db.store(str(self), attribute, str(old_val))
167 self.ldb.set_maxPwdAge(val)
169 def ch_minPwdLength(self, attribute, val):
170 old_val = self.ldb.get_minPwdLength()
172 'KDC Minimum Password length was changed from %s to %s'
174 self.gp_db.store(str(self), attribute, str(old_val))
175 self.ldb.set_minPwdLength(val)
177 def ch_pwdProperties(self, attribute, val):
178 old_val = self.ldb.get_pwdProperties()
179 self.logger.info('KDC Password Properties were changed from %s to %s'
181 self.gp_db.store(str(self), attribute, str(old_val))
182 self.ldb.set_pwdProperties(val)
184 def days2rel_nttime(self, val):
190 return str(-(val * seconds * minutes * hours * sam_add))
193 '''ldap value : samba setter'''
194 return {"minPwdAge": (self.ch_minPwdAge, self.days2rel_nttime),
195 "maxPwdAge": (self.ch_maxPwdAge, self.days2rel_nttime),
196 # Could be none, but I like the method assignment in
198 "minPwdLength": (self.ch_minPwdLength, lambda val: val),
199 "pwdProperties": (self.ch_pwdProperties, lambda val: val),
204 return 'System Access'
208 inf_file = 'MACHINE/Microsoft/Windows NT/SecEdit/GptTmpl.inf'
209 if gpo.file_sys_path:
210 path = os.path.join(gpo.file_sys_path, inf_file)
211 inf_conf = self.parse(path)
214 for section in inf_conf.sections():
215 output[section] = {k: v for k, v in inf_conf.items(section) \
216 if gp_access_ext.apply_map.get(k)}