diff options
author | Luke Morrison <luc785@hotmail.com> | 2014-01-31 13:27:05 +1300 |
---|---|---|
committer | Garming Sam <garming@samba.org> | 2017-11-20 21:41:14 +0100 |
commit | 5194cd4e8d9d0308775042eeba544a5ea0a927a0 (patch) | |
tree | 8abc1401b5b40e447a937e26ce0d3235bfed202a /source4/scripting | |
parent | 148b7ae707f31e221fef79e80ccda2663d5526ee (diff) | |
download | samba-5194cd4e8d9d0308775042eeba544a5ea0a927a0.tar.gz |
gpo: Initial commit for GPO work
Enclosed is my Summer of Code 2013 patch to have vital password GPO always applied to the Samba4 Domain Controller using a GPO update service.
To try it out "make -j" your samba with the patch, apply a security password GPO and see the difference in ~20 seconds. It also takes GPO hierarchy into account.
Split from "Initial commit for GPO work done by Luke Morrison" by David Mulder
Signed-off-by: Garming Sam <garming@catalyst.net.nz>
Signed-off-by: Luke Morrison <luke@hubtrek.com>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
Diffstat (limited to 'source4/scripting')
-rwxr-xr-x | source4/scripting/bin/samba_gpoupdate | 235 |
1 files changed, 235 insertions, 0 deletions
diff --git a/source4/scripting/bin/samba_gpoupdate b/source4/scripting/bin/samba_gpoupdate new file mode 100755 index 00000000000..ba83dcf7e91 --- /dev/null +++ b/source4/scripting/bin/samba_gpoupdate @@ -0,0 +1,235 @@ +#!/usr/bin/env python +# Copyright Luke Morrison <luc785@.hotmail.com> July 2013 +# Co-Edited by Matthieu Pattou July 2013 from original August 2013 +# Edited by Garming Sam Feb. 2014 +# Edited by Luke Morrison April 2014 + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +'''This script reads a log file of previous GPO, gets all GPO from sysvol +and sorts them by container. Then, it applies the ones that haven't been +applied, have changed, or is in the right container''' + +import os +import fcntl +import sys +import tempfile +import subprocess + +sys.path.insert(0, "bin/python") + +import samba +import optparse +from samba import getopt as options +from samba.gpclass import * +from samba.net import Net +from samba.dcerpc import nbt +from samba import smb + + +# Finds all GPO Files ending in inf +def gp_path_list(path): + + GPO_LIST = [] + for ext in gp_extensions: + GPO_LIST.append((ext, ext.list(path))) + return GPO_LIST + + +def gpo_parser(GPO_LIST, ldb, conn, attr_log): + '''The API method to parse the GPO + :param GPO_LIST: + :param ldb: Live instance of an LDB object AKA Samba + :param conn: Live instance of a CIFS connection + :param attr_log: backlog path for GPO and attribute to be written + no return except a newly updated Samba + ''' + + ret = False + for entry in GPO_LIST: + (ext, thefile) = entry + if ret == False: + ret = ext.parse(thefile, ldb, conn, attr_log) + else: + temp = ext.parse(thefile, ldb, conn, attr_log) + return ret + + +class GPOServiceSetup: + def __init__(self): + """Initialize all components necessary to return instances of + a Samba lp context (smb.conf) and Samba LDB context + """ + + self.parser = optparse.OptionParser("samba_gpoupdate [options]") + self.sambaopts = options.SambaOptions(self.parser) + self.credopts = None + self.opts = None + self.args = None + self.lp = None + self.smbconf = None + self.creds = None + self.url = None + + # Setters or Initializers + def init_parser(self): + '''Get the command line options''' + self.parser.add_option_group(self.sambaopts) + self.parser.add_option_group(options.VersionOptions(self.parser)) + self.init_credopts() + self.parser.add_option("-H", dest="url", help="URL for the samdb") + self.parser.add_option_group(self.credopts) + + def init_argsopts(self): + '''Set the options and the arguments''' + (opts, args) = self.parser.parse_args() + + self.opts = opts + self.args = args + + def init_credopts(self): + '''Set Credential operations''' + self.credopts = options.CredentialsOptions(self.parser) + + def init_lp(self): + '''Set the loadparm context''' + self.lp = self.sambaopts.get_loadparm() + self.smbconf = self.lp.configfile + if (not self.opts.url): + self.url = self.lp.samdb_url() + else: + self.url = self.opts.url + + def init_session(self): + '''Initialize the session''' + self.creds = self.credopts.get_credentials(self.lp, + fallback_machine=True) + self.session = system_session() + + def InitializeService(self): + '''Inializer for the thread''' + self.init_parser() + self.init_argsopts() + self.init_lp() + self.init_session() + + # Getters + def Get_LDB(self): + '''Return a live instance of Samba''' + SambaDB = SamDB(self.url, session_info=self.session, + credentials=self.creds, lp=self.lp) + return SambaDB + + def Get_lp_Content(self): + '''Return an instance of a local lp context''' + return self.lp + + def Get_Creds(self): + '''Return an instance of a local creds''' + return self.creds + + +def GetBackLog(sys_log): + """Reads BackLog and makes thread aware of which GPO are unchanged or empty + :param String sys_log: path to backLog + :return Dictionary previous_scanned_version: {Unedited GPO: Version Number} + *NOTE on Version below + """ + previous_scanned_version = {} + if os.path.isfile(sys_log): + previous_scanned_version = scan_log(sys_log) + return previous_scanned_version + else: + return None + +# Set up the GPO service +GPOService = GPOServiceSetup() +GPOService.InitializeService() + +# Get the Samba Instance +test_ldb = GPOService.Get_LDB() + +# Get The lp context +lp = GPOService.Get_lp_Content() + +# Get the CREDS +creds = GPOService.Get_Creds() + +# Read the readable backLog into a hashmap +# then open writable backLog in same location +BackLoggedGPO = None +sys_log = '%s/%s' % (lp.get("path", "sysvol"), 'syslog.txt') +attr_log = '%s/%s' % (lp.get("path", "sysvol"), 'attrlog.txt') +BackLoggedGPO = GetBackLog(sys_log) + + +BackLog = open(sys_log, "w") + + +# We need to know writable DC to setup SMB connection +net = Net(creds=creds, lp=lp) +cldap_ret = net.finddc(domain=lp.get('realm'), flags=(nbt.NBT_SERVER_LDAP | + nbt.NBT_SERVER_DS)) +dc_hostname = cldap_ret.pdc_dns_name + +try: + conn = smb.SMB(dc_hostname, 'sysvol', lp=lp, creds=creds) +except Exception, e: + raise Exception("Error connecting to '%s' using SMB" % dc_hostname, e) + +# Get the dn of the domain, and the dn of readable/writable DC +global_dn = test_ldb.domain_dn() +DC_OU = "OU=Domain Controllers" + ',' + global_dn + +# Set up a List of the GUID for all GPO's +guid_list = [x['name'] for x in conn.list('%s/Policies' % lp.get("realm").lower())] +SYSV_PATH = '%s/%s/%s' % (lp.get("path", "sysvol"), lp.get("realm"), 'Policies') + +hierarchy_gpos = establish_hierarchy(test_ldb, guid_list, DC_OU, global_dn) +change_backlog = False + +# Take a local list of all current GPO list and run it against previous GPO's +# to see if something has changed. If so reset default and re-apply GPO. +Applicable_GPO = [] +for i in hierarchy_gpos: + Applicable_GPO += i + +# Flag gets set when +GPO_Changed = False +GPO_Deleted = check_deleted(Applicable_GPO, BackLoggedGPO) +if (GPO_Deleted): + # Null the backlog + BackLoggedGPO = {} + # Reset defaults then overwrite them + Reset_Defaults(test_ldb) + GPO_Changed = False + +for guid_eval in hierarchy_gpos: + guid = guid_eval[0] + gp_extensions = [gp_sec_ext()] + local_path = '%s/Policies' % lp.get("realm").lower() + '/' + guid + '/' + version = gpo.gpo_get_sysvol_gpt_version(lp.get("path", "sysvol") + '/' + local_path)[1] + gpolist = gp_path_list(local_path) + if(version != BackLoggedGPO.get(guid)): + GPO_Changed = True + # If the GPO has a dn that is applicable to Samba + if guid_eval[1]: + # If it has a GPO file that could apply to Samba + if gpolist[0][1]: + # If it we have not read it before and is not empty + # Rewrite entire logfile here + if (version != 0) and GPO_Changed == True: + change_backlog = gpo_parser(gpolist, test_ldb, conn, attr_log) + + BackLog.write('%s %i\n' % (guid, version)) |