gpo: Add GPO unapply
[metze/samba/wip.git] / source4 / scripting / bin / samba_gpoupdate
index bba5398571a9b335fca21a17ada489141515129c..721d6071bd10ecc70150989d08a6ec4f1fc30f57 100755 (executable)
@@ -50,6 +50,55 @@ def get_gpo_list(dc_hostname, creds, lp):
         gpos = ads.get_gpo_list(creds.get_username())
     return gpos
 
+def apply_gp(lp, creds, test_ldb, logger, store, gp_extensions):
+    gp_db = store.get_gplog(creds.get_username())
+    dc_hostname = get_dc_hostname()
+    try:
+        conn =  smb.SMB(dc_hostname, 'sysvol', lp=lp, creds=creds)
+    except:
+        logger.error('Error connecting to \'%s\' using SMB' % dc_hostname)
+        raise
+    gpos = get_gpo_list(dc_hostname, creds, lp)
+
+    for gpo_obj in gpos:
+        guid = gpo_obj.name
+        if guid == 'Local Policy':
+            continue
+        local_path = os.path.join(lp.get('realm').lower(), 'Policies', guid)
+        version = int(gpo.gpo_get_sysvol_gpt_version(os.path.join(lp.get("path", "sysvol"), local_path))[1])
+        if version != store.get_int(guid):
+            logger.info('GPO %s has changed' % guid)
+            gp_db.set_guid(guid)
+            store.start()
+            try:
+                for ext in gp_extensions:
+                    ext.parse(ext.list(local_path), test_ldb, conn, gp_db, lp)
+            except:
+                logger.error('Failed to parse gpo %s' % guid)
+                store.cancel()
+                continue
+            store.store(guid, '%i' % version)
+        store.commit()
+
+def unapply_log(gp_db):
+    while True:
+        item = gp_db.apply_log_pop()
+        if item:
+            yield item
+        else:
+            break
+
+def unapply_gp(lp, creds, test_ldb, logger, store, gp_extensions):
+    gp_db = store.get_gplog(creds.get_username())
+    for gpo_guid in unapply_log(gp_db):
+        gp_db.set_guid(gpo_guid)
+        unapply_attributes = gp_db.list(gp_extensions)
+        for attr in unapply_attributes:
+            attr_obj = attr[-1](logger, test_ldb, gp_db, lp, attr[0], attr[1])
+            attr_obj.mapper()[attr[0]][0](attr[1]) # Set the old value
+            gp_db.delete(str(attr_obj), attr[0])
+        gp_db.commit()
+
 if __name__ == "__main__":
     parser = optparse.OptionParser('samba_gpoupdate [options]')
     sambaopts = options.SambaOptions(parser)
@@ -59,6 +108,7 @@ if __name__ == "__main__":
     parser.add_option_group(options.VersionOptions(parser))
     credopts = options.CredentialsOptions(parser)
     parser.add_option('-H', '--url', dest='url', help='URL for the samdb')
+    parser.add_option('-X', '--unapply', help='Unapply Group Policy', action='store_true')
     parser.add_option_group(credopts)
 
     # Set the options and the arguments
@@ -89,38 +139,16 @@ if __name__ == "__main__":
     elif log_level >= 4:
         logger.setLevel(logging.DEBUG)
 
-    '''Return a live instance of Samba'''
-    test_ldb = SamDB(url, session_info=session, credentials=creds, lp=lp)
-
-    # Read the readable backLog into a hashmap
-    # then open writable backLog in same location
-    sysvol_log = os.path.join(lp.get('cache directory'), 'gpo.tdb')
+    cache_dir = lp.get('cache directory')
+    store = GPOStorage(os.path.join(cache_dir, 'gpo.tdb'))
 
-    backlog = Backlog(sysvol_log)
+    gp_extensions = [gp_sec_ext(logger)]
 
-    dc_hostname = get_dc_hostname()
-    try:
-        conn =  smb.SMB(dc_hostname, 'sysvol', lp=lp, creds=creds)
-    except:
-        logger.error('Error connecting to \'%s\' using SMB' % dc_hostname)
-        raise
-    gpos = get_gpo_list(dc_hostname, creds, lp)
+    # Get a live instance of Samba
+    test_ldb = SamDB(url, session_info=session, credentials=creds, lp=lp)
 
-    for gpo_obj in gpos:
-        guid = gpo_obj.name
-        if guid == 'Local Policy':
-            continue
-        gp_extensions = [gp_sec_ext(logger)]
-        local_path = os.path.join(lp.get('realm').lower(), 'Policies', guid)
-        version = int(gpo.gpo_get_sysvol_gpt_version(os.path.join(lp.get("path", "sysvol"), local_path))[1])
-        if version != backlog.version(guid):
-            logger.info('GPO %s has changed' % guid)
-            try:
-                for ext in gp_extensions:
-                    ext.parse(ext.list(local_path), test_ldb, conn, lp)
-            except:
-                logger.error('Failed to parse gpo %s' % guid)
-                continue
-        backlog.store(guid, version)
-    backlog.commit()
+    if not opts.unapply:
+        apply_gp(lp, creds, test_ldb, logger, store, gp_extensions)
+    else:
+        unapply_gp(lp, creds, test_ldb, logger, store, gp_extensions)