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 inf_to_kdc_tdb(gp_ext_setter
):
30 def mins_to_hours(self
):
31 return '%d' % (int(self
.val
) / 60)
33 def days_to_hours(self
):
34 return '%d' % (int(self
.val
) * 24)
36 def set_kdc_tdb(self
, val
):
37 old_val
= self
.gp_db
.gpostore
.get(self
.attribute
)
38 self
.logger
.info('%s was changed from %s to %s' % (self
.attribute
,
41 self
.gp_db
.gpostore
.store(self
.attribute
, get_string(val
))
42 self
.gp_db
.store(str(self
), self
.attribute
, get_string(old_val
) if old_val
else None)
44 self
.gp_db
.gpostore
.delete(self
.attribute
)
45 self
.gp_db
.delete(str(self
), self
.attribute
)
48 return {'kdc:user_ticket_lifetime': (self
.set_kdc_tdb
, self
.explicit
),
49 'kdc:service_ticket_lifetime': (self
.set_kdc_tdb
,
51 'kdc:renewal_lifetime': (self
.set_kdc_tdb
,
56 return 'Kerberos Policy'
59 class inf_to_ldb(gp_ext_setter
):
60 '''This class takes the .inf file parameter (essentially a GPO file mapped
61 to a GUID), hashmaps it to the Samba parameter, which then uses an ldb
62 object to update the parameter to Samba4. Not registry oriented whatsoever.
65 def __init__(self
, logger
, gp_db
, lp
, creds
, key
, value
):
66 super(inf_to_ldb
, self
).__init
__(logger
, gp_db
, lp
, creds
, key
, value
)
68 self
.ldb
= SamDB(self
.lp
.samdb_url(),
69 session_info
=system_session(),
70 credentials
=self
.creds
,
72 except (NameError, LdbError
):
73 raise Exception('Failed to load SamDB for assigning Group Policy')
75 def ch_minPwdAge(self
, val
):
76 old_val
= self
.ldb
.get_minPwdAge()
77 self
.logger
.info('KDC Minimum Password age was changed from %s to %s'
79 self
.gp_db
.store(str(self
), self
.attribute
, str(old_val
))
80 self
.ldb
.set_minPwdAge(val
)
82 def ch_maxPwdAge(self
, val
):
83 old_val
= self
.ldb
.get_maxPwdAge()
84 self
.logger
.info('KDC Maximum Password age was changed from %s to %s'
86 self
.gp_db
.store(str(self
), self
.attribute
, str(old_val
))
87 self
.ldb
.set_maxPwdAge(val
)
89 def ch_minPwdLength(self
, val
):
90 old_val
= self
.ldb
.get_minPwdLength()
92 'KDC Minimum Password length was changed from %s to %s'
94 self
.gp_db
.store(str(self
), self
.attribute
, str(old_val
))
95 self
.ldb
.set_minPwdLength(val
)
97 def ch_pwdProperties(self
, val
):
98 old_val
= self
.ldb
.get_pwdProperties()
99 self
.logger
.info('KDC Password Properties were changed from %s to %s'
101 self
.gp_db
.store(str(self
), self
.attribute
, str(old_val
))
102 self
.ldb
.set_pwdProperties(val
)
104 def days2rel_nttime(self
):
111 return str(-(val
* seconds
* minutes
* hours
* sam_add
))
114 '''ldap value : samba setter'''
115 return {"minPwdAge": (self
.ch_minPwdAge
, self
.days2rel_nttime
),
116 "maxPwdAge": (self
.ch_maxPwdAge
, self
.days2rel_nttime
),
117 # Could be none, but I like the method assignment in
119 "minPwdLength": (self
.ch_minPwdLength
, self
.explicit
),
120 "pwdProperties": (self
.ch_pwdProperties
, self
.explicit
),
125 return 'System Access'
128 class gp_sec_ext(gp_inf_ext
):
129 '''This class does the following two things:
130 1) Identifies the GPO if it has a certain kind of filepath,
131 2) Finally parses it.
137 return "Security GPO extension"
140 return {"System Access": {"MinimumPasswordAge": ("minPwdAge",
142 "MaximumPasswordAge": ("maxPwdAge",
144 "MinimumPasswordLength": ("minPwdLength",
146 "PasswordComplexity": ("pwdProperties",
149 "Kerberos Policy": {"MaxTicketAge": (
150 "kdc:user_ticket_lifetime",
154 "kdc:service_ticket_lifetime",
158 "kdc:renewal_lifetime",
164 def process_group_policy(self
, deleted_gpo_list
, changed_gpo_list
):
165 if self
.lp
.get('server role') != 'active directory domain controller':
167 inf_file
= 'MACHINE/Microsoft/Windows NT/SecEdit/GptTmpl.inf'
168 apply_map
= self
.apply_map()
169 for gpo
in deleted_gpo_list
:
170 self
.gp_db
.set_guid(gpo
[0])
171 for section
in gpo
[1].keys():
172 current_section
= apply_map
.get(section
)
173 if not current_section
:
175 for key
, value
in gpo
[1][section
].items():
177 for _
, tup
in current_section
.items():
181 value
= value
.encode('ascii', 'ignore') \
183 setter(self
.logger
, self
.gp_db
, self
.lp
, self
.creds
,
185 self
.gp_db
.delete(section
, key
)
188 for gpo
in changed_gpo_list
:
189 if gpo
.file_sys_path
:
190 self
.gp_db
.set_guid(gpo
.name
)
191 path
= os
.path
.join(gpo
.file_sys_path
, inf_file
)
192 inf_conf
= self
.parse(path
)
195 for section
in inf_conf
.sections():
196 current_section
= apply_map
.get(section
)
197 if not current_section
:
199 for key
, value
in inf_conf
.items(section
):
200 if current_section
.get(key
):
201 (att
, setter
) = current_section
.get(key
)
202 value
= value
.encode('ascii', 'ignore')
203 setter(self
.logger
, self
.gp_db
, self
.lp
,
204 self
.creds
, att
, value
).update_samba()