The branch, master has been updated via 94b70d1ed92 gp: Don't hide managed/recommended directories via 0a1778cde01 gp: Ensure rsop is tested for every CSE via c435c105c51 gp: Fix rsop when final value isn't a str via 74598eeef72 gp: Enable gpupdate output when testing via 6710c50f540 gp: Ensure policy changes don't leave files behind via e6156b13502 gp: Re-create files if manually removed via d170d8cfbb4 gp: Test that files are re-created if manually removed via 5037d402a54 gp: Modify Chromium CSE to use new files applier via f36542b50c7 gp: Modify Cert Auto Enroll CSE to use new applier via acdc7fbe898 gp: Modify Centrify Crontab compatible CSE to use new files applier via f20ca1a7db2 gp: Modify Startup Scripts CSE to use new files applier via fb512e06803 gp: Modify GNOME Settings CSE to use new files applier via f3e24a325ea gp: Modify Machine Scripts CSE to use new files applier via 64f4930dc0d gp: Modify Files CSE to use new files applier via 2953329ba07 gp: Modify Sudoers CSEs to use new files applier via 81dbcae9dfb gp: Modify OpenSSH CSE to use new files applier via 50f4c3d44e1 gp: Modify PAM Access CSE to use new files applier via 3f7105894c1 gp: Modify Symlink CSE to use new files applier via 5715281918f gp: Implement appliers for monitoring policy changes from 5b19288949e s3:params:lp_do_section - protect against NULL deref
https://git.samba.org/?p=samba.git;a=shortlog;h=master - Log ----------------------------------------------------------------- commit 94b70d1ed92a6fac4a679ccc959c63c49d918349 Author: David Mulder <dmul...@samba.org> Date: Mon Dec 12 10:05:16 2022 -0700 gp: Don't hide managed/recommended directories Making these variables hidden prevents the parent class gp_chromium_ext from reading them when subclassed in gp_chrome_ext. This caused the chrome policies to be installed in the chromium directories. Signed-off-by: David Mulder <dmul...@samba.org> Reviewed-by: Jeremy Allison <j...@samba.org> Autobuild-User(master): Jeremy Allison <j...@samba.org> Autobuild-Date(master): Wed Dec 21 03:05:46 UTC 2022 on sn-devel-184 commit 0a1778cde011fecb000f5b7e6f43920f5ab59da0 Author: David Mulder <dmul...@samba.org> Date: Fri Dec 9 10:31:49 2022 -0700 gp: Ensure rsop is tested for every CSE A bug cropped up in the rsop that was causing a crash because this wasn't being tested. Signed-off-by: David Mulder <dmul...@samba.org> Reviewed-by: Jeremy Allison <j...@samba.org> commit c435c105c511bd984b6d1bda3964100ad5ec2c31 Author: David Mulder <dmul...@samba.org> Date: Fri Dec 9 09:40:34 2022 -0700 gp: Fix rsop when final value isn't a str The output must be a string value, or it will crash. Chromium policies output integers, which was causing the parser to crash. Signed-off-by: David Mulder <dmul...@samba.org> Reviewed-by: Jeremy Allison <j...@samba.org> commit 74598eeef72e6b260393df7451c957d7fde1f59a Author: David Mulder <dmul...@samba.org> Date: Thu Dec 8 15:15:15 2022 -0700 gp: Enable gpupdate output when testing Signed-off-by: David Mulder <dmul...@samba.org> Reviewed-by: Jeremy Allison <j...@samba.org> commit 6710c50f54025d8174aacd17515d58ff50e6d28a Author: David Mulder <dmul...@samba.org> Date: Wed Dec 7 10:17:38 2022 -0700 gp: Ensure policy changes don't leave files behind This test exercises the gp_file_applier and ensures that when a policy is modified, no old policy is left behind. Signed-off-by: David Mulder <dmul...@samba.org> Reviewed-by: Jeremy Allison <j...@samba.org> commit e6156b135021db5a6335bb8779acefff2f6a0bd3 Author: David Mulder <dmul...@samba.org> Date: Wed Dec 7 09:51:12 2022 -0700 gp: Re-create files if manually removed Signed-off-by: David Mulder <dmul...@samba.org> Reviewed-by: Jeremy Allison <j...@samba.org> commit d170d8cfbb4571af8b66f1dcd7355a598b0abd1f Author: David Mulder <dmul...@samba.org> Date: Wed Dec 7 09:49:53 2022 -0700 gp: Test that files are re-created if manually removed Currently applied files which are manually removed do not get re-applied. Signed-off-by: David Mulder <dmul...@samba.org> Reviewed-by: Jeremy Allison <j...@samba.org> commit 5037d402a54a0010382cc7825e6fba4322ba18b4 Author: David Mulder <dmul...@samba.org> Date: Tue Dec 6 11:12:34 2022 -0700 gp: Modify Chromium CSE to use new files applier Signed-off-by: David Mulder <dmul...@samba.org> Reviewed-by: Jeremy Allison <j...@samba.org> commit f36542b50c70de74144b9e2e94e91944e8536421 Author: David Mulder <dmul...@samba.org> Date: Tue Dec 6 08:56:24 2022 -0700 gp: Modify Cert Auto Enroll CSE to use new applier Signed-off-by: David Mulder <dmul...@samba.org> Reviewed-by: Jeremy Allison <j...@samba.org> commit acdc7fbe8985a16d41075b72f54a96f217c3f884 Author: David Mulder <dmul...@samba.org> Date: Mon Dec 5 10:41:27 2022 -0700 gp: Modify Centrify Crontab compatible CSE to use new files applier Signed-off-by: David Mulder <dmul...@samba.org> Reviewed-by: Jeremy Allison <j...@samba.org> commit f20ca1a7db29ec2ccf3ef5de58a578aa7dfc4964 Author: David Mulder <dmul...@samba.org> Date: Fri Dec 2 15:42:58 2022 -0700 gp: Modify Startup Scripts CSE to use new files applier Signed-off-by: David Mulder <dmul...@samba.org> Reviewed-by: Jeremy Allison <j...@samba.org> commit fb512e068033b49b7e8bc6baa6040b032d6b99c1 Author: David Mulder <dmul...@samba.org> Date: Fri Dec 2 14:51:27 2022 -0700 gp: Modify GNOME Settings CSE to use new files applier Signed-off-by: David Mulder <dmul...@samba.org> Reviewed-by: Jeremy Allison <j...@samba.org> commit f3e24a325ea6d2d574f42f0e7f9f1e1fb040366c Author: David Mulder <dmul...@samba.org> Date: Tue Nov 29 14:01:13 2022 -0700 gp: Modify Machine Scripts CSE to use new files applier Signed-off-by: David Mulder <dmul...@samba.org> Reviewed-by: Jeremy Allison <j...@samba.org> commit 64f4930dc0d46c21fefd8a798534b58670036faa Author: David Mulder <dmul...@samba.org> Date: Tue Nov 29 08:04:35 2022 -0700 gp: Modify Files CSE to use new files applier Signed-off-by: David Mulder <dmul...@samba.org> Reviewed-by: Jeremy Allison <j...@samba.org> commit 2953329ba07cb7de6c8df1718779b7c9045d3910 Author: David Mulder <dmul...@samba.org> Date: Mon Nov 28 13:37:52 2022 -0700 gp: Modify Sudoers CSEs to use new files applier Signed-off-by: David Mulder <dmul...@samba.org> Reviewed-by: Jeremy Allison <j...@samba.org> commit 81dbcae9dfba2f2dd7b5e7e04f9ababca02ed49b Author: David Mulder <dmul...@samba.org> Date: Fri Nov 18 15:03:41 2022 -0700 gp: Modify OpenSSH CSE to use new files applier Signed-off-by: David Mulder <dmul...@samba.org> Reviewed-by: Jeremy Allison <j...@samba.org> commit 50f4c3d44e1c99210e754c5aeff85f7c9ac9ed2b Author: David Mulder <dmul...@samba.org> Date: Fri Nov 18 14:22:17 2022 -0700 gp: Modify PAM Access CSE to use new files applier Signed-off-by: David Mulder <dmul...@samba.org> Reviewed-by: Jeremy Allison <j...@samba.org> commit 3f7105894c1b65cb4b26702d1111a9fb35bb561c Author: David Mulder <dmul...@samba.org> Date: Fri Nov 18 14:04:13 2022 -0700 gp: Modify Symlink CSE to use new files applier Signed-off-by: David Mulder <dmul...@samba.org> Reviewed-by: Jeremy Allison <j...@samba.org> commit 5715281918fc10a4840f682a9c314e0e0ae84ee3 Author: David Mulder <dmul...@samba.org> Date: Fri Nov 18 13:59:32 2022 -0700 gp: Implement appliers for monitoring policy changes This is currently a significant drawback of Samba Group Policy. CSEs MUST be aware of policy changes such as modification, removal, etc. This is a complex process, and is easy to mess up. Here I add 'appliers' (the first being for files), which handle the complexty transparently to ensure this is done correctly. Signed-off-by: David Mulder <dmul...@samba.org> Reviewed-by: Jeremy Allison <j...@samba.org> ----------------------------------------------------------------------- Summary of changes: python/samba/gp/gp_centrify_crontab_ext.py | 38 +- python/samba/gp/gp_centrify_sudoers_ext.py | 51 +- python/samba/gp/gp_cert_auto_enroll_ext.py | 114 +- python/samba/gp/gp_chromium_ext.py | 132 +- python/samba/gp/gp_gnome_settings_ext.py | 176 +-- python/samba/gp/gp_scripts_ext.py | 54 +- python/samba/gp/gp_sudoers_ext.py | 69 +- python/samba/gp/gpclass.py | 212 ++- python/samba/gp/vgp_access_ext.py | 48 +- python/samba/gp/vgp_files_ext.py | 54 +- python/samba/gp/vgp_openssh_ext.py | 48 +- python/samba/gp/vgp_startup_scripts_ext.py | 53 +- python/samba/gp/vgp_sudoers_ext.py | 51 +- python/samba/gp/vgp_symlink_ext.py | 28 +- python/samba/tests/gpo.py | 2266 ++-------------------------- 15 files changed, 812 insertions(+), 2582 deletions(-) Changeset truncated at 500 lines: diff --git a/python/samba/gp/gp_centrify_crontab_ext.py b/python/samba/gp/gp_centrify_crontab_ext.py index 220feb776a5..414cd90aaf7 100644 --- a/python/samba/gp/gp_centrify_crontab_ext.py +++ b/python/samba/gp/gp_centrify_crontab_ext.py @@ -16,7 +16,7 @@ import os, re from subprocess import Popen, PIPE -from samba.gp.gpclass import gp_pol_ext, drop_privileges +from samba.gp.gpclass import gp_pol_ext, drop_privileges, gp_file_applier from hashlib import blake2b from tempfile import NamedTemporaryFile @@ -34,43 +34,47 @@ end = ''' ### autogenerated by samba ### ''' -class gp_centrify_crontab_ext(gp_pol_ext): +class gp_centrify_crontab_ext(gp_pol_ext, gp_file_applier): def __str__(self): return 'Centrify/CrontabEntries' def process_group_policy(self, deleted_gpo_list, changed_gpo_list, cdir=None): for guid, settings in deleted_gpo_list: - self.gp_db.set_guid(guid) if str(self) in settings: for attribute, script in settings[str(self)].items(): - if os.path.exists(script): - os.unlink(script) - self.gp_db.delete(str(self), attribute) - self.gp_db.commit() + self.unapply(guid, attribute, script) for gpo in changed_gpo_list: if gpo.file_sys_path: section = \ 'Software\\Policies\\Centrify\\UnixSettings\\CrontabEntries' - self.gp_db.set_guid(gpo.name) pol_file = 'MACHINE/Registry.pol' path = os.path.join(gpo.file_sys_path, pol_file) pol_conf = self.parse(path) if not pol_conf: continue + entries = [] for e in pol_conf.entries: if e.keyname == section and e.data.strip(): cron_dir = '/etc/cron.d' if not cdir else cdir - attribute = blake2b(e.data.encode()).hexdigest() - old_val = self.gp_db.retrieve(str(self), attribute) - if not old_val: - with NamedTemporaryFile(prefix='gp_', mode="w+", - delete=False, dir=cron_dir) as f: - contents = '%s\n%s\n%s' % (intro, e.data, end) - f.write(contents) - self.gp_db.store(str(self), attribute, f.name) - self.gp_db.commit() + entries.append(e.data) + def applier_func(entries): + with NamedTemporaryFile(prefix='gp_', mode="w+", + delete=False, dir=cron_dir) as f: + contents = intro + for entry in entries: + contents += '%s\n' % entry + contents += end + f.write(contents) + return [f.name] + attribute = self.generate_attribute(gpo.name) + value_hash = self.generate_value_hash(*entries) + self.apply(gpo.name, attribute, value_hash, applier_func, + entries) + + # Remove scripts for this GPO which are no longer applied + self.clean(gpo.name, keep=attribute) def rsop(self, gpo, target='MACHINE'): output = {} diff --git a/python/samba/gp/gp_centrify_sudoers_ext.py b/python/samba/gp/gp_centrify_sudoers_ext.py index 2d03a4871a4..3de4fb871ea 100644 --- a/python/samba/gp/gp_centrify_sudoers_ext.py +++ b/python/samba/gp/gp_centrify_sudoers_ext.py @@ -15,11 +15,8 @@ # along with this program. If not, see <http://www.gnu.org/licenses/>. import os -from samba.gp.gpclass import gp_pol_ext -from base64 import b64encode -from tempfile import NamedTemporaryFile -from subprocess import Popen, PIPE -from samba.gp.gp_sudoers_ext import visudo, intro +from samba.gp.gpclass import gp_pol_ext, gp_file_applier +from samba.gp.gp_sudoers_ext import sudo_applier_func from samba.gp.util.logging import log def ext_enabled(entries): @@ -29,57 +26,41 @@ def ext_enabled(entries): return e.data == 1 return False -class gp_centrify_sudoers_ext(gp_pol_ext): +class gp_centrify_sudoers_ext(gp_pol_ext, gp_file_applier): def __str__(self): return 'Centrify/Sudo Rights' def process_group_policy(self, deleted_gpo_list, changed_gpo_list, sdir='/etc/sudoers.d'): for guid, settings in deleted_gpo_list: - self.gp_db.set_guid(guid) if str(self) in settings: for attribute, sudoers in settings[str(self)].items(): - if os.path.exists(sudoers): - os.unlink(sudoers) - self.gp_db.delete(str(self), attribute) - self.gp_db.commit() + self.unapply(guid, attribute, sudoers) for gpo in changed_gpo_list: if gpo.file_sys_path: section = 'Software\\Policies\\Centrify\\UnixSettings\\SuDo' - self.gp_db.set_guid(gpo.name) pol_file = 'MACHINE/Registry.pol' path = os.path.join(gpo.file_sys_path, pol_file) pol_conf = self.parse(path) if not pol_conf or not ext_enabled(pol_conf.entries): continue + sudo_entries = [] for e in pol_conf.entries: if e.keyname == section and e.data.strip(): if '**delvals.' in e.valuename: continue - attribute = b64encode(e.data.encode()).decode() - old_val = self.gp_db.retrieve(str(self), attribute) - if not old_val: - contents = intro - contents += '%s\n' % e.data - with NamedTemporaryFile() as f: - with open(f.name, 'w') as w: - w.write(contents) - sudo_validation = \ - Popen([visudo, '-c', '-f', f.name], - stdout=PIPE, stderr=PIPE).wait() - if sudo_validation == 0: - with NamedTemporaryFile(prefix='gp_', - delete=False, - dir=sdir) as f: - with open(f.name, 'w') as w: - w.write(contents) - self.gp_db.store(str(self), - attribute, - f.name) - else: - log.error('Sudoers apply failed', e.data) - self.gp_db.commit() + sudo_entries.append(e.data) + # Each GPO applies only one set of sudoers, in a + # set of files, so the attribute does not need uniqueness. + attribute = self.generate_attribute(gpo.name, *sudo_entries) + # The value hash is generated from the sudo_entries, ensuring + # any changes to this GPO will cause the files to be rewritten. + value_hash = self.generate_value_hash(*sudo_entries) + self.apply(gpo.name, attribute, value_hash, sudo_applier_func, + sdir, sudo_entries) + # Cleanup any old entries that are no longer part of the policy + self.clean(gpo.name, keep=[attribute]) def rsop(self, gpo): output = {} diff --git a/python/samba/gp/gp_cert_auto_enroll_ext.py b/python/samba/gp/gp_cert_auto_enroll_ext.py index f1dcf6bbafb..3be8931bf1e 100644 --- a/python/samba/gp/gp_cert_auto_enroll_ext.py +++ b/python/samba/gp/gp_cert_auto_enroll_ext.py @@ -17,7 +17,7 @@ import os import operator import requests -from samba.gp.gpclass import gp_pol_ext +from samba.gp.gpclass import gp_pol_ext, gp_applier, GPOSTATE from samba import Ldb from ldb import SCOPE_SUBTREE, SCOPE_BASE from samba.auth import system_session @@ -39,6 +39,7 @@ except ModuleNotFoundError: from cryptography.hazmat.primitives.serialization import Encoding from cryptography.x509 import load_der_x509_certificate from cryptography.hazmat.backends import default_backend +from samba.common import get_string cert_wrap = b""" -----BEGIN CERTIFICATE----- @@ -153,9 +154,9 @@ def fetch_certification_authorities(ldb): if len(res) == 0: return result for es in res: - data = { 'name': es['cn'][0], - 'hostname': es['dNSHostName'][0], - 'cACertificate': es['cACertificate'][0] + data = { 'name': get_string(es['cn'][0]), + 'hostname': get_string(es['dNSHostName'][0]), + 'cACertificate': get_string(es['cACertificate'][0]) } result.append(data) return result @@ -171,7 +172,7 @@ def fetch_template_attrs(ldb, name, attrs=['msPKI-Minimal-Key-Size']): return {'msPKI-Minimal-Key-Size': ['2048']} def format_root_cert(cert): - cert = base64.b64encode(cert) + cert = base64.b64encode(cert.encode()) return cert_wrap % re.sub(b"(.{64})", b"\\1\n", cert, 0, re.DOTALL) def find_cepces_submit(): @@ -248,7 +249,7 @@ def getca(ca, url, trust_dir): def cert_enroll(ca, ldb, trust_dir, private_dir, auth='Kerberos'): """Install the root certificate chain.""" - data = {'files': [], 'templates': []} + data = dict({'files': [], 'templates': []}, **ca) url = 'http://%s/CertSrv/mscep/mscep.dll/pkiclient.exe?' % ca['hostname'] root_certs = getca(ca, url, trust_dir) data['files'].extend(root_certs) @@ -311,10 +312,42 @@ def cert_enroll(ca, ldb, trust_dir, private_dir, auth='Kerberos'): 'certificate auto enrollment to work') return json.dumps(data) -class gp_cert_auto_enroll_ext(gp_pol_ext): +class gp_cert_auto_enroll_ext(gp_pol_ext, gp_applier): def __str__(self): return 'Cryptography\AutoEnrollment' + def unapply(self, guid, attribute, value): + ca_cn = base64.b64decode(attribute) + data = json.loads(value) + getcert = which('getcert') + if getcert is not None: + Popen([getcert, 'remove-ca', '-c', ca_cn]).wait() + for nickname in data['templates']: + Popen([getcert, 'stop-tracking', '-i', nickname]).wait() + for f in data['files']: + if os.path.exists(f): + if os.path.exists(f): + os.unlink(f) + self.cache_remove_attribute(guid, attribute) + + def apply(self, guid, ca, applier_func, *args, **kwargs): + attribute = base64.b64encode(ca['name'].encode()).decode() + # If the policy has changed, unapply, then apply new policy + old_val = self.cache_get_attribute_value(guid, attribute) + old_data = json.loads(old_val) if old_val is not None else {} + if all([(ca[k] == old_data[k] if k in old_data else False) \ + for k in ca.keys()]) or \ + self.cache_get_apply_state() == GPOSTATE.ENFORCE: + self.unapply(guid, attribute, old_val) + # If policy is already applied, skip application + if old_val is not None and \ + self.cache_get_apply_state() != GPOSTATE.ENFORCE: + return + + # Apply the policy and log the changes + data = applier_func(*args, **kwargs) + self.cache_add_attribute(guid, attribute, data) + def process_group_policy(self, deleted_gpo_list, changed_gpo_list, trust_dir=None, private_dir=None): if trust_dir is None: @@ -327,27 +360,13 @@ class gp_cert_auto_enroll_ext(gp_pol_ext): os.mkdir(private_dir, mode=0o700) for guid, settings in deleted_gpo_list: - self.gp_db.set_guid(guid) if str(self) in settings: for ca_cn_enc, data in settings[str(self)].items(): - ca_cn = base64.b64decode(ca_cn_enc) - data = json.loads(data) - getcert = which('getcert') - if getcert is not None: - Popen([getcert, 'remove-ca', '-c', ca_cn]).wait() - for nickname in data['templates']: - Popen([getcert, 'stop-tracking', - '-i', nickname]).wait() - for f in data['files']: - if os.path.exists(f): - os.unlink(f) - self.gp_db.delete(str(self), ca_cn_enc) - self.gp_db.commit() + self.unapply(guid, ca_cn_enc, data) for gpo in changed_gpo_list: if gpo.file_sys_path: section = 'Software\Policies\Microsoft\Cryptography\AutoEnrollment' - self.gp_db.set_guid(gpo.name) pol_file = 'MACHINE/Registry.pol' path = os.path.join(gpo.file_sys_path, pol_file) pol_conf = self.parse(path) @@ -362,11 +381,22 @@ class gp_cert_auto_enroll_ext(gp_pol_ext): manage = e.data & 0x2 == 0x2 retrive_pending = e.data & 0x4 == 0x4 if enroll: - self.__enroll(pol_conf.entries, trust_dir, - private_dir) - self.gp_db.commit() + ca_names = self.__enroll(gpo.name, + pol_conf.entries, + trust_dir, private_dir) + + # Cleanup any old CAs that have been removed + ca_attrs = [base64.b64encode(n.encode()).decode() \ + for n in ca_names] + self.clean(gpo.name, keep=ca_attrs) + else: + # If enrollment has been disabled for this GPO, + # remove any existing policy + ca_attrs = \ + self.cache_get_all_attribute_values(gpo.name) + self.clean(gpo.name, remove=ca_attrs) - def __read_cep_data(self, ldb, end_point_information, + def __read_cep_data(self, guid, ldb, end_point_information, trust_dir, private_dir): """Read CEP Data. @@ -414,42 +444,44 @@ class gp_cert_auto_enroll_ext(gp_pol_ext): # For each CertificateEnrollmentPolicyEndPoint instance for that # group: + ca_names = [] for ca in end_point_group: # If EndPoint.URI equals "LDAP": if ca['URL'] == 'LDAP:': # This is a basic configuration. cas = fetch_certification_authorities(ldb) for _ca in cas: - data = cert_enroll(_ca, ldb, trust_dir, private_dir) - self.gp_db.store(str(self), - base64.b64encode(_ca['name']).decode(), - data) + self.apply(guid, _ca, cert_enroll, _ca, ldb, trust_dir, + private_dir) + ca_names.append(_ca['name']) # If EndPoint.URI starts with "HTTPS//": elif ca['URL'].lower().startswith('https://'): - data = cert_enroll(ca, ldb, trust_dir, - private_dir, auth=ca['auth']) - self.gp_db.store(str(self), - base64.b64encode(ca['name'].encode()).decode(), - data) + self.apply(guid, ca, cert_enroll, ca, ldb, trust_dir, + private_dir, auth=ca['auth']) + ca_names.append(ca['name']) else: edata = { 'endpoint': ca['URL'] } log.error('Unrecognized endpoint', edata) + return ca_names - def __enroll(self, entries, trust_dir, private_dir): + def __enroll(self, guid, entries, trust_dir, private_dir): url = 'ldap://%s' % get_dc_hostname(self.creds, self.lp) ldb = Ldb(url=url, session_info=system_session(), lp=self.lp, credentials=self.creds) + ca_names = [] end_point_information = obtain_end_point_information(entries) if len(end_point_information) > 0: - self.__read_cep_data(ldb, end_point_information, - trust_dir, private_dir) + ca_names.extend(self.__read_cep_data(guid, ldb, + end_point_information, + trust_dir, private_dir)) else: cas = fetch_certification_authorities(ldb) for ca in cas: - data = cert_enroll(ca, ldb, trust_dir, private_dir) - self.gp_db.store(str(self), - base64.b64encode(ca['name']).decode(), data) + self.apply(guid, ca, cert_enroll, ca, ldb, trust_dir, + private_dir) + ca_names.append(ca['name']) + return ca_names def rsop(self, gpo): output = {} diff --git a/python/samba/gp/gp_chromium_ext.py b/python/samba/gp/gp_chromium_ext.py index ae4bc8a7a80..5e54f0f469d 100644 --- a/python/samba/gp/gp_chromium_ext.py +++ b/python/samba/gp/gp_chromium_ext.py @@ -16,10 +16,11 @@ import os import json -from samba.gp.gpclass import gp_pol_ext +from samba.gp.gpclass import gp_pol_ext, gp_file_applier from samba.dcerpc import misc from samba.common import get_string from samba.gp.util.logging import log +from tempfile import NamedTemporaryFile def parse_entry_data(name, e): dict_entries = ['VirtualKeyboardFeatures', @@ -365,7 +366,9 @@ def assign_entry(policies, e): name = e.valuename policies[name] = parse_entry_data(name, e) -def convert_pol_to_json(managed, recommended, section, entries): +def convert_pol_to_json(section, entries): + managed = {} + recommended = {} recommended_section = '\\'.join([section, 'Recommended']) for e in entries: if '**delvals.' in e.valuename: @@ -376,98 +379,77 @@ def convert_pol_to_json(managed, recommended, section, entries): assign_entry(managed, e) return managed, recommended -class gp_chromium_ext(gp_pol_ext): - __managed_policies_path = '/etc/chromium/policies/managed' - __recommended_policies_path = '/etc/chromium/policies/recommended' +class gp_chromium_ext(gp_pol_ext, gp_file_applier): + managed_policies_path = '/etc/chromium/policies/managed' + recommended_policies_path = '/etc/chromium/policies/recommended' def __str__(self): return 'Google/Chromium' - def set_managed_machine_policy(self, managed): - try: - managed_policies = os.path.join(self.__managed_policies_path, - 'policies.json') - os.makedirs(self.__managed_policies_path, exist_ok=True) - with open(managed_policies, 'w') as f: - json.dump(managed, f) - log.debug('Wrote Chromium preferences', managed_policies) - except PermissionError: - log.debug('Failed to write Chromium preferences', - managed_policies) - - - def set_recommended_machine_policy(self, recommended): - try: - recommended_policies = os.path.join(self.__recommended_policies_path, - 'policies.json') - os.makedirs(self.__recommended_policies_path, exist_ok=True) - with open(recommended_policies, 'w') as f: - json.dump(recommended, f) - log.debug('Wrote Chromium preferences', recommended_policies) - except PermissionError: - log.debug('Failed to write Chromium preferences', - recommended_policies) - - def get_managed_machine_policy(self): - managed_policies = os.path.join(self.__managed_policies_path, - 'policies.json') - if os.path.exists(managed_policies): - with open(managed_policies, 'r') as r: - managed = json.load(r) - log.debug('Read Chromium preferences', managed_policies) - else: - managed = {} - return managed - - def get_recommended_machine_policy(self): - recommended_policies = os.path.join(self.__recommended_policies_path, - 'policies.json') - if os.path.exists(recommended_policies): - with open(recommended_policies, 'r') as r: - recommended = json.load(r) - log.debug('Read Chromium preferences', recommended_policies) - else: - recommended = {} - return recommended - def process_group_policy(self, deleted_gpo_list, changed_gpo_list, policy_dir=None): if policy_dir is not None: - self.__recommended_policies_path = os.path.join(policy_dir, + self.recommended_policies_path = os.path.join(policy_dir, 'recommended') - self.__managed_policies_path = os.path.join(policy_dir, 'managed') + self.managed_policies_path = os.path.join(policy_dir, 'managed') + # Create the policy directories if necessary + if not os.path.exists(self.recommended_policies_path): + os.makedirs(self.recommended_policies_path, mode=0o755, + exist_ok=True) + if not os.path.exists(self.managed_policies_path): + os.makedirs(self.managed_policies_path, mode=0o755, + exist_ok=True) for guid, settings in deleted_gpo_list: - self.gp_db.set_guid(guid) if str(self) in settings: for attribute, policies in settings[str(self)].items(): - if attribute == 'managed': - self.set_managed_machine_policy(json.loads(policies)) - elif attribute == 'recommended': - self.set_recommended_machine_policy(json.loads(policies)) - self.gp_db.delete(str(self), attribute) - self.gp_db.commit() + try: + json.loads(policies) + except json.decoder.JSONDecodeError: + self.unapply(guid, attribute, policies) + else: + # Policies were previously stored all in one file, but + # the Chromium documentation says this is not -- Samba Shared Repository