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
.gp
.gpclass
import gp_inf_ext
20 from samba
.auth
import system_session
21 from samba
.common
import get_string
23 from ldb
import LdbError
24 from samba
.samdb
import SamDB
27 from samba
.gp
.util
.logging
import log
29 def mins_to_hours(val
):
30 return '%d' % (int(val
) / 60)
32 def days_to_hours(val
):
33 return '%d' % (int(val
) * 24)
35 def days2rel_nttime(val
):
41 return str(-(val
* seconds
* minutes
* hours
* sam_add
))
43 class gp_krb_ext(gp_inf_ext
):
44 apply_map
= { 'MaxTicketAge': 'kdc:user_ticket_lifetime',
45 'MaxServiceAge': 'kdc:service_ticket_lifetime',
46 'MaxRenewAge': 'kdc:renewal_lifetime' }
47 def process_group_policy(self
, deleted_gpo_list
, changed_gpo_list
):
48 if self
.lp
.get('server role') != 'active directory domain controller':
50 inf_file
= 'MACHINE/Microsoft/Windows NT/SecEdit/GptTmpl.inf'
51 for guid
, settings
in deleted_gpo_list
:
52 self
.gp_db
.set_guid(guid
)
53 for section
in settings
.keys():
54 if section
== str(self
):
55 for att
, value
in settings
[section
].items():
56 self
.set_kdc_tdb(att
, value
)
57 self
.gp_db
.delete(section
, att
)
60 for gpo
in changed_gpo_list
:
62 self
.gp_db
.set_guid(gpo
.name
)
63 path
= os
.path
.join(gpo
.file_sys_path
, inf_file
)
64 inf_conf
= self
.parse(path
)
67 for section
in inf_conf
.sections():
68 if section
== str(self
):
69 for key
, value
in inf_conf
.items(section
):
70 if key
not in gp_krb_ext
.apply_map
:
72 att
= gp_krb_ext
.apply_map
[key
]
73 value_func
= self
.mapper().get(att
)
74 self
.set_kdc_tdb(att
, value_func(value
))
77 def set_kdc_tdb(self
, attribute
, val
):
78 old_val
= self
.gp_db
.gpostore
.get(attribute
)
79 log
.info('%s was changed from %s to %s' % (attribute
, old_val
, val
))
81 self
.gp_db
.gpostore
.store(attribute
, get_string(val
))
82 self
.gp_db
.store(str(self
), attribute
, get_string(old_val
)
85 self
.gp_db
.gpostore
.delete(attribute
)
86 self
.gp_db
.delete(str(self
), attribute
)
89 return {'kdc:user_ticket_lifetime': lambda val
: val
,
90 'kdc:service_ticket_lifetime': mins_to_hours
,
91 'kdc:renewal_lifetime': days_to_hours
,
95 return 'Kerberos Policy'
99 if self
.lp
.get('server role') != 'active directory domain controller':
101 inf_file
= 'MACHINE/Microsoft/Windows NT/SecEdit/GptTmpl.inf'
102 if gpo
.file_sys_path
:
103 path
= os
.path
.join(gpo
.file_sys_path
, inf_file
)
104 inf_conf
= self
.parse(path
)
107 if str(self
) in inf_conf
.sections():
109 output
[section
] = {k
: v
for k
, v
in inf_conf
.items(section
)
110 if gp_krb_ext
.apply_map
.get(k
)}
114 class gp_access_ext(gp_inf_ext
):
115 """This class takes the .inf file parameter (essentially a GPO file mapped
116 to a GUID), hashmaps it to the Samba parameter, which then uses an ldb
117 object to update the parameter to Samba4. Not registry oriented whatsoever.
122 self
.ldb
= SamDB(self
.lp
.samdb_url(),
123 session_info
=system_session(),
124 credentials
=self
.creds
,
126 except (NameError, LdbError
):
127 raise Exception('Failed to load SamDB for assigning Group Policy')
129 apply_map
= { 'MinimumPasswordAge': 'minPwdAge',
130 'MaximumPasswordAge': 'maxPwdAge',
131 'MinimumPasswordLength': 'minPwdLength',
132 'PasswordComplexity': 'pwdProperties' }
133 def process_group_policy(self
, deleted_gpo_list
, changed_gpo_list
):
134 if self
.lp
.get('server role') != 'active directory domain controller':
137 inf_file
= 'MACHINE/Microsoft/Windows NT/SecEdit/GptTmpl.inf'
138 for guid
, settings
in deleted_gpo_list
:
139 self
.gp_db
.set_guid(guid
)
140 for section
in settings
.keys():
141 if section
== str(self
):
142 for att
, value
in settings
[section
].items():
143 update_samba
, _
= self
.mapper().get(att
)
144 update_samba(att
, value
)
145 self
.gp_db
.delete(section
, att
)
148 for gpo
in changed_gpo_list
:
149 if gpo
.file_sys_path
:
150 self
.gp_db
.set_guid(gpo
.name
)
151 path
= os
.path
.join(gpo
.file_sys_path
, inf_file
)
152 inf_conf
= self
.parse(path
)
155 for section
in inf_conf
.sections():
156 if section
== str(self
):
157 for key
, value
in inf_conf
.items(section
):
158 if key
not in gp_access_ext
.apply_map
:
160 att
= gp_access_ext
.apply_map
[key
]
161 (update_samba
, value_func
) = self
.mapper().get(att
)
162 update_samba(att
, value_func(value
))
165 def ch_minPwdAge(self
, attribute
, val
):
166 old_val
= self
.ldb
.get_minPwdAge()
167 log
.info('KDC Minimum Password age was changed from %s to %s'
169 self
.gp_db
.store(str(self
), attribute
, str(old_val
))
170 self
.ldb
.set_minPwdAge(val
)
172 def ch_maxPwdAge(self
, attribute
, val
):
173 old_val
= self
.ldb
.get_maxPwdAge()
174 log
.info('KDC Maximum Password age was changed from %s to %s'
176 self
.gp_db
.store(str(self
), attribute
, str(old_val
))
177 self
.ldb
.set_maxPwdAge(val
)
179 def ch_minPwdLength(self
, attribute
, val
):
180 old_val
= self
.ldb
.get_minPwdLength()
181 log
.info('KDC Minimum Password length was changed from %s to %s'
183 self
.gp_db
.store(str(self
), attribute
, str(old_val
))
184 self
.ldb
.set_minPwdLength(val
)
186 def ch_pwdProperties(self
, attribute
, val
):
187 old_val
= self
.ldb
.get_pwdProperties()
188 log
.info('KDC Password Properties were changed from %s to %s'
190 self
.gp_db
.store(str(self
), attribute
, str(old_val
))
191 self
.ldb
.set_pwdProperties(val
)
194 """ldap value : samba setter"""
195 return {"minPwdAge": (self
.ch_minPwdAge
, days2rel_nttime
),
196 "maxPwdAge": (self
.ch_maxPwdAge
, days2rel_nttime
),
197 # Could be none, but I like the method assignment in
199 "minPwdLength": (self
.ch_minPwdLength
, lambda val
: val
),
200 "pwdProperties": (self
.ch_pwdProperties
, lambda val
: val
),
205 return 'System Access'
209 if self
.lp
.get('server role') != 'active directory domain controller':
211 inf_file
= 'MACHINE/Microsoft/Windows NT/SecEdit/GptTmpl.inf'
212 if gpo
.file_sys_path
:
213 path
= os
.path
.join(gpo
.file_sys_path
, inf_file
)
214 inf_conf
= self
.parse(path
)
217 if str(self
) in inf_conf
.sections():
219 output
[section
] = {k
: v
for k
, v
in inf_conf
.items(section
)
220 if gp_access_ext
.apply_map
.get(k
)}