summaryrefslogtreecommitdiff
path: root/source4/scripting
diff options
context:
space:
mode:
authorLuke Morrison <luc785@hotmail.com>2014-01-31 13:27:05 +1300
committerGarming Sam <garming@samba.org>2017-11-20 21:41:14 +0100
commit5194cd4e8d9d0308775042eeba544a5ea0a927a0 (patch)
tree8abc1401b5b40e447a937e26ce0d3235bfed202a /source4/scripting
parent148b7ae707f31e221fef79e80ccda2663d5526ee (diff)
downloadsamba-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-xsource4/scripting/bin/samba_gpoupdate235
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))