[PATCH 12/18] gpo: Added the cases where GPO is deleted from OU or altogether, modularized, and fine tuned hierarchy order

David Mulder dmulder at suse.com
Thu Feb 23 20:22:04 UTC 2017


From: Luke Morrison <luc785 at hotmail.com>

Signed-off-by: Garming Sam <garming at catalyst.net.nz>
Signed-off-by: Luke Morrison <luke at hubtrek.com>
---
 python/samba/gpclass.py               | 38 +++++++++++++++++++++----
 source4/scripting/bin/samba_gpoupdate | 52 ++++++++++++++++++++++-------------
 2 files changed, 65 insertions(+), 25 deletions(-)

diff --git a/python/samba/gpclass.py b/python/samba/gpclass.py
index adebcb5..0b2159b 100755
--- a/python/samba/gpclass.py
+++ b/python/samba/gpclass.py
@@ -118,10 +118,11 @@ class gp_sec_ext(gp_ext):
                                   "PasswordComplexity": ("pwdProperties", inf_to_ldb),
                                  }
                }
-#FIXME. EACH gpo should have a parser, and a creater. Essentially a gpo is just a file. Possibly a method and class to link it to organization unit (if that already does not exist) so that GPO's can be created arithmetically, possibly with a hashtable for certain GPO, then linked if desired. Also could store a backup folder of gpo's and then configure them without necessarily deploying it.
 
     def read_inf(self, path, conn, attr_log):
+        ret = False
         inftable = self.populate_inf()
+
         try:
             policy = conn.loadfile(path).decode('utf-16')
         except:
@@ -129,6 +130,13 @@ class gp_sec_ext(gp_ext):
         current_section = None
         LOG = open(attr_log, "a")
         LOG.write(str(path.split('/')[2]) + '\n')
+
+        # So here we would declare a boolean,
+        # that would get changed to TRUE.
+        #
+        # If at any point in time a GPO was applied,
+        # then we return that boolean at the end.
+
         for line in policy.splitlines():
             line = line.strip()
             if line[0] == '[':
@@ -144,10 +152,9 @@ class gp_sec_ext(gp_ext):
                 if current_section.get(key):
                     (att, setter) = current_section.get(key)
                     value = value.encode('ascii', 'ignore')
-                    # so value is the value that it contains, and the att is the attribute
-                    LOG.write(att + ' ' + value + '\n')
-                    # copy and paste this logic to backwalk deleted GPO
+                    ret = True
                     setter(self.ldb, self.dn, att, value).update_samba()
+        return ret
 
     def parse(self, afile, ldb, conn, attr_log):
         self.ldb = ldb
@@ -165,6 +172,23 @@ def scan_log(sysvol_path):
         data[guid] = int(version)
     return data
 
+
+def Reset_Defaults(test_ldb):
+    test_ldb.set_minPwdAge(str(-25920000000000))
+    test_ldb.set_maxPwdAge(str(-38016000000000))
+    test_ldb.set_minPwdLength(str(7))
+    test_ldb.set_pwdProperties(str(1))
+
+
+def check_deleted(guid_list, backloggpo):
+    if backloggpo is None:
+        return False
+    for guid in backloggpo:
+        if guid not in guid_list:
+            return True
+    return False
+
+
 # The hierarchy is as per MS http://msdn.microsoft.com/en-us/library/windows/desktop/aa374155%28v=vs.85%29.aspx
 #
 # It does not care about local GPO, because GPO and snap-ins are not made in Linux yet.
@@ -265,8 +289,9 @@ def establish_hierarchy(SamDB, GUID_LIST, DC_OU, global_dn):
     unapplied_gpo = []
     # Sorted by container
     sorted_gpo_list = []
-    '''Since the unapplied GPO are put at the front of the list, just once again append them to the linked container sorted list'''
-    while count < indexed_places[0]:
+
+    # Unapplied GPO live at start of list, append them to final list
+    while final_list[0][1] == False:
         unapplied_gpo.append(final_list[count])
         count += 1
     count = 0
@@ -274,6 +299,7 @@ def establish_hierarchy(SamDB, GUID_LIST, DC_OU, global_dn):
 
     # A single container call gets the linked order for all GPO in container.
     # So we need one call per container - > index of the Original list
+    indexed_places.insert(0, 0)
     while count < (len(indexed_places)-1):
         sorted_gpo_list += (sort_linked(SamDB, final_list, indexed_places[count], indexed_places[count+1]))
         count += 1
diff --git a/source4/scripting/bin/samba_gpoupdate b/source4/scripting/bin/samba_gpoupdate
index 1388bf7..e0337f4 100755
--- a/source4/scripting/bin/samba_gpoupdate
+++ b/source4/scripting/bin/samba_gpoupdate
@@ -24,6 +24,7 @@ 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):
 
@@ -32,6 +33,7 @@ def gp_path_list(path):
         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:
@@ -41,9 +43,14 @@ def gpo_parser(GPO_LIST, ldb, conn, attr_log):
     no return except a newly updated Samba
     '''
 
+    ret = False
     for entry in GPO_LIST:
         (ext, thefile) = entry
-        ext.parse(thefile, ldb, conn, attr_log)
+        if ret == False:
+            ret = ext.parse(thefile, ldb, conn, attr_log)
+        else:
+            temp = ext.parse(thefile, ldb, conn, attr_log)
+    return ret
 
 
 class GPOServiceSetup:
@@ -152,6 +159,8 @@ 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")
 
 
@@ -173,38 +182,43 @@ 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')
 
-#Power through the Microsoft Hierarchy with Linking Order included
-#FIXME could be SO much more efficient if we get the dn if the DC, then use that to get all its containers
-#Then use the acquired containers of DC dn, to get all GPO in a convenient linking order with linking order already taken into account
 hierarchy_gpos = establish_hierarchy(test_ldb, guid_list, DC_OU, global_dn)
-
-#At this point we have a list of hierarchically applied GPOS
-#Say for example a GPO was deleted, we can either
-#1)Reset ALL Defaults and then call script to apply all GPO
-#2)Find which attribute, fall back on previous attribute. THat way when we call this script, it only still applies the GPO that has changed
-#2 is more favorable because we are minimally changing Samba
+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 an important GPO parse it. Will not parse if it has not changed, is empty, or is not in the right container'''
+    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
-            #We need to rewrite
-            if (version != BackLoggedGPO.get(guid)) and (version != 0):
-                print ('GPO %s has changed' % guid)
-                #Apply to Samba
-                gpo_parser(gpolist, test_ldb, conn, attr_log)
+            # 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))
 
-- 
2.10.2




More information about the samba-technical mailing list