# along with this program. If not, see <http://www.gnu.org/licenses/>.
import os.path
-from gpclass import gp_ext_setter, gp_inf_ext
+from samba.gpclass import gp_ext_setter, gp_inf_ext
+from samba.auth import system_session
+from samba.compat import get_string
+try:
+ from ldb import LdbError
+ from samba.samdb import SamDB
+except ImportError:
+ pass
-class inf_to_kdc_tdb(gp_ext_setter):
- def mins_to_hours(self):
- return '%d' % (int(self.val)/60)
- def days_to_hours(self):
- return '%d' % (int(self.val)*24)
+class gp_krb_ext(gp_inf_ext):
+ apply_map = { 'MaxTicketAge': 'kdc:user_ticket_lifetime',
+ 'MaxServiceAge': 'kdc:service_ticket_lifetime',
+ 'MaxRenewAge': 'kdc:renewal_lifetime' }
+ def process_group_policy(self, deleted_gpo_list, changed_gpo_list):
+ if self.lp.get('server role') != 'active directory domain controller':
+ return
+ inf_file = 'MACHINE/Microsoft/Windows NT/SecEdit/GptTmpl.inf'
+ for gpo in deleted_gpo_list:
+ self.gp_db.set_guid(gpo[0])
+ for section in gpo[1].keys():
+ if section == str(self):
+ for att, value in gpo[1][section].items():
+ update_samba, _ = self.mapper().get(att)
+ update_samba(att, value)
+ self.gp_db.delete(section, att)
+ self.gp_db.commit()
- def set_kdc_tdb(self, val):
- old_val = self.gp_db.gpostore.get(self.attribute)
- self.logger.info('%s was changed from %s to %s' % (self.attribute,
+ for gpo in changed_gpo_list:
+ if gpo.file_sys_path:
+ self.gp_db.set_guid(gpo.name)
+ path = os.path.join(gpo.file_sys_path, inf_file)
+ inf_conf = self.parse(path)
+ if not inf_conf:
+ continue
+ for section in inf_conf.sections():
+ if section == str(self):
+ for key, value in inf_conf.items(section):
+ att = gp_krb_ext.apply_map[key]
+ (update_samba, value_func) = self.mapper().get(att)
+ update_samba(att, value_func(value))
+ self.gp_db.commit()
+
+ def mins_to_hours(self, val):
+ return '%d' % (int(val) / 60)
+
+ def days_to_hours(self, val):
+ return '%d' % (int(val) * 24)
+
+ def set_kdc_tdb(self, attribute, val):
+ old_val = self.gp_db.gpostore.get(attribute)
+ self.logger.info('%s was changed from %s to %s' % (attribute,
old_val, val))
if val is not None:
- self.gp_db.gpostore.store(self.attribute, val)
- self.gp_db.store(str(self), self.attribute, old_val)
+ self.gp_db.gpostore.store(attribute, get_string(val))
+ self.gp_db.store(str(self), attribute, get_string(old_val) \
+ if old_val else None)
else:
- self.gp_db.gpostore.delete(self.attribute)
- self.gp_db.delete(str(self), self.attribute)
+ self.gp_db.gpostore.delete(attribute)
+ self.gp_db.delete(str(self), attribute)
def mapper(self):
- return { 'kdc:user_ticket_lifetime': (self.set_kdc_tdb, self.explicit),
- 'kdc:service_ticket_lifetime': (self.set_kdc_tdb,
- self.mins_to_hours),
- 'kdc:renewal_lifetime': (self.set_kdc_tdb,
- self.days_to_hours),
- }
+ return {'kdc:user_ticket_lifetime': (self.set_kdc_tdb,
+ lambda val: val),
+ 'kdc:service_ticket_lifetime': (self.set_kdc_tdb,
+ self.mins_to_hours),
+ 'kdc:renewal_lifetime': (self.set_kdc_tdb,
+ self.days_to_hours),
+ }
def __str__(self):
return 'Kerberos Policy'
+ def rsop(self, gpo):
+ output = {}
+ inf_file = 'MACHINE/Microsoft/Windows NT/SecEdit/GptTmpl.inf'
+ if gpo.file_sys_path:
+ path = os.path.join(gpo.file_sys_path, inf_file)
+ inf_conf = self.parse(path)
+ if not inf_conf:
+ return output
+ for section in inf_conf.sections():
+ output[section] = {k: v for k, v in inf_conf.items(section) \
+ if gp_krb_ext.apply_map.get(k)}
+ return output
+
+
class inf_to_ldb(gp_ext_setter):
'''This class takes the .inf file parameter (essentially a GPO file mapped
to a GUID), hashmaps it to the Samba parameter, which then uses an ldb
object to update the parameter to Samba4. Not registry oriented whatsoever.
'''
+ def __init__(self, logger, gp_db, lp, creds, key, value):
+ super(inf_to_ldb, self).__init__(logger, gp_db, lp, creds, key, value)
+ try:
+ self.ldb = SamDB(self.lp.samdb_url(),
+ session_info=system_session(),
+ credentials=self.creds,
+ lp=self.lp)
+ except (NameError, LdbError):
+ raise Exception('Failed to load SamDB for assigning Group Policy')
+
def ch_minPwdAge(self, val):
old_val = self.ldb.get_minPwdAge()
- self.logger.info('KDC Minimum Password age was changed from %s to %s' \
+ self.logger.info('KDC Minimum Password age was changed from %s to %s'
% (old_val, val))
- self.gp_db.store(str(self), self.attribute, old_val)
+ self.gp_db.store(str(self), self.attribute, str(old_val))
self.ldb.set_minPwdAge(val)
def ch_maxPwdAge(self, val):
old_val = self.ldb.get_maxPwdAge()
- self.logger.info('KDC Maximum Password age was changed from %s to %s' \
+ self.logger.info('KDC Maximum Password age was changed from %s to %s'
% (old_val, val))
- self.gp_db.store(str(self), self.attribute, old_val)
+ self.gp_db.store(str(self), self.attribute, str(old_val))
self.ldb.set_maxPwdAge(val)
def ch_minPwdLength(self, val):
old_val = self.ldb.get_minPwdLength()
self.logger.info(
- 'KDC Minimum Password length was changed from %s to %s' \
- % (old_val, val))
- self.gp_db.store(str(self), self.attribute, old_val)
+ 'KDC Minimum Password length was changed from %s to %s'
+ % (old_val, val))
+ self.gp_db.store(str(self), self.attribute, str(old_val))
self.ldb.set_minPwdLength(val)
def ch_pwdProperties(self, val):
old_val = self.ldb.get_pwdProperties()
- self.logger.info('KDC Password Properties were changed from %s to %s' \
+ self.logger.info('KDC Password Properties were changed from %s to %s'
% (old_val, val))
- self.gp_db.store(str(self), self.attribute, old_val)
+ self.gp_db.store(str(self), self.attribute, str(old_val))
self.ldb.set_pwdProperties(val)
def days2rel_nttime(self):
sam_add = 10000000
val = (self.val)
val = int(val)
- return str(-(val * seconds * minutes * hours * sam_add))
+ return str(-(val * seconds * minutes * hours * sam_add))
def mapper(self):
'''ldap value : samba setter'''
- return { "minPwdAge" : (self.ch_minPwdAge, self.days2rel_nttime),
- "maxPwdAge" : (self.ch_maxPwdAge, self.days2rel_nttime),
- # Could be none, but I like the method assignment in
- # update_samba
- "minPwdLength" : (self.ch_minPwdLength, self.explicit),
- "pwdProperties" : (self.ch_pwdProperties, self.explicit),
+ return {"minPwdAge": (self.ch_minPwdAge, self.days2rel_nttime),
+ "maxPwdAge": (self.ch_maxPwdAge, self.days2rel_nttime),
+ # Could be none, but I like the method assignment in
+ # update_samba
+ "minPwdLength": (self.ch_minPwdLength, self.explicit),
+ "pwdProperties": (self.ch_pwdProperties, self.explicit),
- }
+ }
def __str__(self):
return 'System Access'
+
class gp_sec_ext(gp_inf_ext):
'''This class does the following two things:
1) Identifies the GPO if it has a certain kind of filepath,
def __str__(self):
return "Security GPO extension"
- def list(self, rootpath):
- return os.path.join(rootpath,
- "MACHINE/Microsoft/Windows NT/SecEdit/GptTmpl.inf")
-
- def listmachpol(self, rootpath):
- return os.path.join(rootpath, "Machine/Registry.pol")
-
- def listuserpol(self, rootpath):
- return os.path.join(rootpath, "User/Registry.pol")
-
def apply_map(self):
return {"System Access": {"MinimumPasswordAge": ("minPwdAge",
inf_to_ldb),
inf_to_ldb),
"PasswordComplexity": ("pwdProperties",
inf_to_ldb),
- },
- "Kerberos Policy": {"MaxTicketAge": (
- "kdc:user_ticket_lifetime",
- inf_to_kdc_tdb
- ),
- "MaxServiceAge": (
- "kdc:service_ticket_lifetime",
- inf_to_kdc_tdb
- ),
- "MaxRenewAge": (
- "kdc:renewal_lifetime",
- inf_to_kdc_tdb
- ),
- }
- }
+ },
+ }
+
+ def process_group_policy(self, deleted_gpo_list, changed_gpo_list):
+ if self.lp.get('server role') != 'active directory domain controller':
+ return
+ inf_file = 'MACHINE/Microsoft/Windows NT/SecEdit/GptTmpl.inf'
+ apply_map = self.apply_map()
+ for gpo in deleted_gpo_list:
+ self.gp_db.set_guid(gpo[0])
+ for section in gpo[1].keys():
+ current_section = apply_map.get(section)
+ if not current_section:
+ continue
+ for key, value in gpo[1][section].items():
+ setter = None
+ for _, tup in current_section.items():
+ if tup[0] == key:
+ setter = tup[1]
+ if setter:
+ value = value.encode('ascii', 'ignore') \
+ if value else value
+ setter(self.logger, self.gp_db, self.lp, self.creds,
+ key, value).delete()
+ self.gp_db.delete(section, key)
+ self.gp_db.commit()
+
+ for gpo in changed_gpo_list:
+ if gpo.file_sys_path:
+ self.gp_db.set_guid(gpo.name)
+ path = os.path.join(gpo.file_sys_path, inf_file)
+ inf_conf = self.parse(path)
+ if not inf_conf:
+ continue
+ for section in inf_conf.sections():
+ current_section = apply_map.get(section)
+ if not current_section:
+ continue
+ for key, value in inf_conf.items(section):
+ if current_section.get(key):
+ (att, setter) = current_section.get(key)
+ value = value.encode('ascii', 'ignore')
+ setter(self.logger, self.gp_db, self.lp,
+ self.creds, att, value).update_samba()
+ self.gp_db.commit()
+ def rsop(self, gpo):
+ output = {}
+ inf_file = 'MACHINE/Microsoft/Windows NT/SecEdit/GptTmpl.inf'
+ apply_map = self.apply_map()
+ if gpo.file_sys_path:
+ path = os.path.join(gpo.file_sys_path, inf_file)
+ inf_conf = self.parse(path)
+ if not inf_conf:
+ return output
+ for section in inf_conf.sections():
+ current_section = apply_map.get(section)
+ if not current_section:
+ continue
+ output[section] = {k: v for k, v in inf_conf.items(section) \
+ if current_section.get(k)}
+ return output