]> git.ipfire.org Git - thirdparty/samba.git/commitdiff
gpo: Apply Group Policy User Scripts
authorDavid Mulder <dmulder@suse.com>
Tue, 20 Jul 2021 17:14:28 +0000 (11:14 -0600)
committerJeremy Allison <jra@samba.org>
Fri, 13 Aug 2021 19:14:30 +0000 (19:14 +0000)
Signed-off-by: David Mulder <dmulder@suse.com>
Reviewed-by: Jeremy Allison <jra@samba.org>
python/samba/gp_scripts_ext.py
selftest/knownfail.d/gpo [deleted file]

index 70e668159a2b2db71d957cc2df763f0127b579aa..33049ff6dc0b25d917ad71c16de0c51f51a4514d 100644 (file)
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
 import os, re
-from samba.gpclass import gp_pol_ext
+from subprocess import Popen, PIPE
+from samba.gpclass import gp_pol_ext, drop_privileges
 from base64 import b64encode
+from hashlib import blake2b
 from tempfile import NamedTemporaryFile
 
 intro = '''
@@ -28,6 +30,9 @@ intro = '''
 # to this machine. DO NOT MODIFY THIS FILE DIRECTLY.
 #
 
+'''
+end = '''
+### autogenerated by samba ###
 '''
 
 class gp_scripts_ext(gp_pol_ext):
@@ -89,9 +94,79 @@ class gp_scripts_ext(gp_pol_ext):
                     output[key].append(e.data)
         return output
 
+def fetch_crontab(username):
+    p = Popen(['crontab', '-l', '-u', username], stdout=PIPE, stderr=PIPE)
+    out, err = p.communicate()
+    if p.returncode != 0:
+        raise RuntimeError('Failed to read the crontab: %s' % err)
+    m = re.findall('%s(.*)%s' % (intro, end), out.decode(), re.DOTALL)
+    if len(m) == 1:
+        entries = m[0].strip().split('\n')
+    else:
+        entries = []
+    m = re.findall('(.*)%s.*%s(.*)' % (intro, end), out.decode(), re.DOTALL)
+    if len(m) == 1:
+        others = '\n'.join([l.strip() for l in m[0]])
+    else:
+        others = out.decode()
+    return others, entries
+
+def install_crontab(fname, username):
+    p = Popen(['crontab', fname, '-u', username], stdout=PIPE, stderr=PIPE)
+    _, err = p.communicate()
+    if p.returncode != 0:
+        raise RuntimeError('Failed to install crontab: %s' % err)
+
 class gp_user_scripts_ext(gp_scripts_ext):
     def process_group_policy(self, deleted_gpo_list, changed_gpo_list):
-        pass
+        for guid, settings in deleted_gpo_list:
+            self.gp_db.set_guid(guid)
+            if str(self) in settings:
+                others, entries = fetch_crontab(self.username)
+                for attribute, entry in settings[str(self)].items():
+                    if entry in entries:
+                        entries.remove(entry)
+                    self.gp_db.delete(str(self), attribute)
+                with NamedTemporaryFile() as f:
+                    if len(entries) > 0:
+                        f.write('\n'.join([others, intro,
+                                   '\n'.join(entries), end]).encode())
+                    else:
+                        f.write(others.encode())
+                    f.flush()
+                    install_crontab(f.name, self.username)
+            self.gp_db.commit()
+
+        for gpo in changed_gpo_list:
+            if gpo.file_sys_path:
+                reg_key = 'Software\\Policies\\Samba\\Unix Settings'
+                sections = { '%s\\Daily Scripts' % reg_key : '@daily',
+                             '%s\\Monthly Scripts' % reg_key : '@monthly',
+                             '%s\\Weekly Scripts' % reg_key : '@weekly',
+                             '%s\\Hourly Scripts' % reg_key : '@hourly' }
+                self.gp_db.set_guid(gpo.name)
+                pol_file = 'USER/Registry.pol'
+                path = os.path.join(gpo.file_sys_path, pol_file)
+                pol_conf = drop_privileges('root', self.parse, path)
+                if not pol_conf:
+                    continue
+                for e in pol_conf.entries:
+                    if e.keyname in sections.keys() and e.data.strip():
+                        cron_freq = sections[e.keyname]
+                        attribute = '%s:%s' % (e.keyname,
+                                blake2b(e.data.encode()).hexdigest())
+                        old_val = self.gp_db.retrieve(str(self), attribute)
+                        entry = '%s %s' % (cron_freq, e.data)
+                        others, entries = fetch_crontab(self.username)
+                        if not old_val or entry not in entries:
+                            entries.append(entry)
+                            with NamedTemporaryFile() as f:
+                                f.write('\n'.join([others, intro,
+                                           '\n'.join(entries), end]).encode())
+                                f.flush()
+                                install_crontab(f.name, self.username)
+                            self.gp_db.store(str(self), attribute, entry)
+                        self.gp_db.commit()
 
     def rsop(self, gpo):
         return super().rsop(gpo, target='USER')
diff --git a/selftest/knownfail.d/gpo b/selftest/knownfail.d/gpo
deleted file mode 100644 (file)
index 138d933..0000000
+++ /dev/null
@@ -1 +0,0 @@
-^samba.tests.gpo.samba.tests.gpo.GPOTests.test_gp_user_scripts_ext