[SCM] Samba Shared Repository - branch master updated

Jeremy Allison jra at samba.org
Tue May 10 20:06:01 UTC 2022


The branch, master has been updated
       via  17ba8120ed6 gpo: Add Centrify Compatible Crontab Extensions
       via  fe0aa82b621 gpo: Test Centrify Compatible Crontab Extensions
       via  d68270eb4b7 gpo: Add Centrify Compatible Sudoers Extension
       via  c28e4396de2 gpo: Test Centrify Compatible Sudoers Extension
      from  4580fd10468 winbind: send "debug traceid" from winbindd parent to child

https://git.samba.org/?p=samba.git;a=shortlog;h=master


- Log -----------------------------------------------------------------
commit 17ba8120ed61f58d927164d67408399becac27bb
Author: David Mulder <dmulder at suse.com>
Date:   Fri Apr 29 15:21:33 2022 -0600

    gpo: Add Centrify Compatible Crontab Extensions
    
    Signed-off-by: David Mulder <dmulder at suse.com>
    Reviewed-by: Jeremy Allison <jra at samba.org>
    
    Autobuild-User(master): Jeremy Allison <jra at samba.org>
    Autobuild-Date(master): Tue May 10 20:05:48 UTC 2022 on sn-devel-184

commit fe0aa82b621bf01bbd81186a5ebbae10559facc1
Author: David Mulder <dmulder at suse.com>
Date:   Fri Apr 29 14:40:41 2022 -0600

    gpo: Test Centrify Compatible Crontab Extensions
    
    Signed-off-by: David Mulder <dmulder at suse.com>
    Reviewed-by: Jeremy Allison <jra at samba.org>

commit d68270eb4b7418327c4f06b46f3686d955831e66
Author: David Mulder <dmulder at suse.com>
Date:   Fri Apr 29 10:29:01 2022 -0600

    gpo: Add Centrify Compatible Sudoers Extension
    
    Signed-off-by: David Mulder <dmulder at suse.com>
    Reviewed-by: Jeremy Allison <jra at samba.org>

commit c28e4396de27be05c5ba8f96eb9b1e86d01f58ec
Author: David Mulder <dmulder at suse.com>
Date:   Fri Apr 29 09:14:10 2022 -0600

    gpo: Test Centrify Compatible Sudoers Extension
    
    Signed-off-by: David Mulder <dmulder at suse.com>
    Reviewed-by: Jeremy Allison <jra at samba.org>

-----------------------------------------------------------------------

Summary of changes:
 ...p_scripts_ext.py => gp_centrify_crontab_ext.py} |  68 ++++-----
 ...p_sudoers_ext.py => gp_centrify_sudoers_ext.py} |  53 +++----
 python/samba/tests/gpo.py                          | 166 +++++++++++++++++++++
 source4/scripting/bin/samba-gpupdate               |   6 +
 4 files changed, 222 insertions(+), 71 deletions(-)
 copy python/samba/{gp_scripts_ext.py => gp_centrify_crontab_ext.py} (69%)
 copy python/samba/{gp_sudoers_ext.py => gp_centrify_sudoers_ext.py} (75%)


Changeset truncated at 500 lines:

diff --git a/python/samba/gp_scripts_ext.py b/python/samba/gp_centrify_crontab_ext.py
similarity index 69%
copy from python/samba/gp_scripts_ext.py
copy to python/samba/gp_centrify_crontab_ext.py
index 33049ff6dc0..eace6a973cd 100644
--- a/python/samba/gp_scripts_ext.py
+++ b/python/samba/gp_centrify_crontab_ext.py
@@ -1,5 +1,5 @@
-# gp_scripts_ext samba gpo policy
-# Copyright (C) David Mulder <dmulder at suse.com> 2020
+# gp_centrify_crontab_ext samba gpo policy
+# Copyright (C) David Mulder <dmulder at suse.com> 2022
 #
 # 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
@@ -17,14 +17,13 @@
 import os, re
 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 = '''
 ### autogenerated by samba
 #
-# This file is generated by the gp_scripts_ext Group Policy
+# This file is generated by the gp_centrify_crontab_ext Group Policy
 # Client Side Extension. To modify the contents of this file,
 # modify the appropriate Group Policy objects which apply
 # to this machine. DO NOT MODIFY THIS FILE DIRECTLY.
@@ -35,11 +34,12 @@ end = '''
 ### autogenerated by samba ###
 '''
 
-class gp_scripts_ext(gp_pol_ext):
+class gp_centrify_crontab_ext(gp_pol_ext):
     def __str__(self):
-        return 'Unix Settings/Scripts'
+        return 'Centrify/CrontabEntries'
 
-    def process_group_policy(self, deleted_gpo_list, changed_gpo_list, cdir=None):
+    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:
@@ -51,11 +51,8 @@ class gp_scripts_ext(gp_pol_ext):
 
         for gpo in changed_gpo_list:
             if gpo.file_sys_path:
-                reg_key = 'Software\\Policies\\Samba\\Unix Settings'
-                sections = { '%s\\Daily Scripts' % reg_key : '/etc/cron.daily',
-                             '%s\\Monthly Scripts' % reg_key : '/etc/cron.monthly',
-                             '%s\\Weekly Scripts' % reg_key : '/etc/cron.weekly',
-                             '%s\\Hourly Scripts' % reg_key : '/etc/cron.hourly' }
+                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)
@@ -63,23 +60,21 @@ class gp_scripts_ext(gp_pol_ext):
                 if not pol_conf:
                     continue
                 for e in pol_conf.entries:
-                    if e.keyname in sections.keys() and e.data.strip():
-                        cron_dir = sections[e.keyname] if not cdir else cdir
-                        attribute = '%s:%s' % (e.keyname,
-                                b64encode(e.data.encode()).decode())
+                    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 = '#!/bin/sh\n%s' % intro
-                                contents += '%s\n' % e.data
+                                contents = '%s\n%s\n%s' % (intro, e.data, end)
                                 f.write(contents)
-                                os.chmod(f.name, 0o700)
                                 self.gp_db.store(str(self), attribute, f.name)
                         self.gp_db.commit()
 
     def rsop(self, gpo, target='MACHINE'):
         output = {}
+        section = 'Software\\Policies\\Centrify\\UnixSettings\\CrontabEntries'
         pol_file = '%s/Registry.pol' % target
         if gpo.file_sys_path:
             path = os.path.join(gpo.file_sys_path, pol_file)
@@ -87,11 +82,10 @@ class gp_scripts_ext(gp_pol_ext):
             if not pol_conf:
                 return output
             for e in pol_conf.entries:
-                key = e.keyname.split('\\')[-1]
-                if key.endswith('Scripts') and e.data.strip():
-                    if key not in output.keys():
-                        output[key] = []
-                    output[key].append(e.data)
+                if e.keyname == section and e.data.strip():
+                    if str(self) not in output.keys():
+                        output[str(self)] = []
+                    output[str(self)].append(e.data)
         return output
 
 def fetch_crontab(username):
@@ -117,7 +111,7 @@ def install_crontab(fname, username):
     if p.returncode != 0:
         raise RuntimeError('Failed to install crontab: %s' % err)
 
-class gp_user_scripts_ext(gp_scripts_ext):
+class gp_user_centrify_crontab_ext(gp_centrify_crontab_ext):
     def process_group_policy(self, deleted_gpo_list, changed_gpo_list):
         for guid, settings in deleted_gpo_list:
             self.gp_db.set_guid(guid)
@@ -130,7 +124,7 @@ class gp_user_scripts_ext(gp_scripts_ext):
                 with NamedTemporaryFile() as f:
                     if len(entries) > 0:
                         f.write('\n'.join([others, intro,
-                                   '\n'.join(entries), end]).encode())
+                                '\n'.join(entries), end]).encode())
                     else:
                         f.write(others.encode())
                     f.flush()
@@ -139,11 +133,8 @@ class gp_user_scripts_ext(gp_scripts_ext):
 
         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' }
+                section = \
+                    'Software\\Policies\\Centrify\\UnixSettings\\CrontabEntries'
                 self.gp_db.set_guid(gpo.name)
                 pol_file = 'USER/Registry.pol'
                 path = os.path.join(gpo.file_sys_path, pol_file)
@@ -151,21 +142,18 @@ class gp_user_scripts_ext(gp_scripts_ext):
                 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())
+                    if e.keyname == section and e.data.strip():
+                        attribute = 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)
+                        if not old_val or e.data not in entries:
+                            entries.append(e.data)
                             with NamedTemporaryFile() as f:
                                 f.write('\n'.join([others, intro,
-                                           '\n'.join(entries), end]).encode())
+                                        '\n'.join(entries), end]).encode())
                                 f.flush()
                                 install_crontab(f.name, self.username)
-                            self.gp_db.store(str(self), attribute, entry)
+                            self.gp_db.store(str(self), attribute, e.data)
                         self.gp_db.commit()
 
     def rsop(self, gpo):
diff --git a/python/samba/gp_sudoers_ext.py b/python/samba/gp_centrify_sudoers_ext.py
similarity index 75%
copy from python/samba/gp_sudoers_ext.py
copy to python/samba/gp_centrify_sudoers_ext.py
index 47e8778d68d..4af51406050 100644
--- a/python/samba/gp_sudoers_ext.py
+++ b/python/samba/gp_centrify_sudoers_ext.py
@@ -1,5 +1,5 @@
-# gp_sudoers_ext samba gpo policy
-# Copyright (C) David Mulder <dmulder at suse.com> 2020
+# gp_centrify_sudoers_ext samba gpo policy
+# Copyright (C) David Mulder <dmulder at suse.com> 2022
 #
 # 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
@@ -19,32 +19,19 @@ from samba.gpclass import gp_pol_ext
 from base64 import b64encode
 from tempfile import NamedTemporaryFile
 from subprocess import Popen, PIPE
+from samba.gp_sudoers_ext import visudo, intro
 from samba.gp.util.logging import log
 
-def find_executable(executable, path):
-    paths = path.split(os.pathsep)
-    for p in paths:
-        f = os.path.join(p, executable)
-        if os.path.isfile(f):
-            return f
-    return None
+def ext_enabled(entries):
+    section = 'Software\\Policies\\Centrify\\UnixSettings'
+    for e in entries:
+        if e.keyname == section and e.valuename == 'sudo.enabled':
+            return e.data == 1
+    return False
 
-intro = '''
-### autogenerated by samba
-#
-# This file is generated by the gp_sudoers_ext Group Policy
-# Client Side Extension. To modify the contents of this file,
-# modify the appropriate Group Policy objects which apply
-# to this machine. DO NOT MODIFY THIS FILE DIRECTLY.
-#
-
-'''
-visudo = find_executable('visudo',
-        path='%s:%s' % (os.environ['PATH'], '/usr/sbin'))
-
-class gp_sudoers_ext(gp_pol_ext):
+class gp_centrify_sudoers_ext(gp_pol_ext):
     def __str__(self):
-        return 'Unix Settings/Sudo Rights'
+        return 'Centrify/Sudo Rights'
 
     def process_group_policy(self, deleted_gpo_list, changed_gpo_list,
             sdir='/etc/sudoers.d'):
@@ -59,15 +46,17 @@ class gp_sudoers_ext(gp_pol_ext):
 
         for gpo in changed_gpo_list:
             if gpo.file_sys_path:
-                section = 'Software\\Policies\\Samba\\Unix Settings\\Sudo Rights'
+                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:
+                if not pol_conf or not ext_enabled(pol_conf.entries):
                     continue
                 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:
@@ -94,6 +83,7 @@ class gp_sudoers_ext(gp_pol_ext):
 
     def rsop(self, gpo):
         output = {}
+        section = 'Software\\Policies\\Centrify\\UnixSettings\\SuDo'
         pol_file = 'MACHINE/Registry.pol'
         if gpo.file_sys_path:
             path = os.path.join(gpo.file_sys_path, pol_file)
@@ -101,9 +91,10 @@ class gp_sudoers_ext(gp_pol_ext):
             if not pol_conf:
                 return output
             for e in pol_conf.entries:
-                key = e.keyname.split('\\')[-1]
-                if key.endswith('Sudo Rights') and e.data.strip():
-                    if key not in output.keys():
-                        output[key] = []
-                    output[key].append(e.data)
+                if e.keyname == section and e.data.strip():
+                    if '**delvals.' in e.valuename:
+                        continue
+                    if str(self) not in output.keys():
+                        output[str(self)] = []
+                    output[str(self)].append(e.data)
         return output
diff --git a/python/samba/tests/gpo.py b/python/samba/tests/gpo.py
index 8d2b3545209..7d3cb878b93 100644
--- a/python/samba/tests/gpo.py
+++ b/python/samba/tests/gpo.py
@@ -48,6 +48,9 @@ from samba.gp_chromium_ext import gp_chromium_ext
 from samba.gp_firewalld_ext import gp_firewalld_ext
 from samba.credentials import Credentials
 from samba.gp_msgs_ext import gp_msgs_ext
+from samba.gp_centrify_sudoers_ext import gp_centrify_sudoers_ext
+from samba.gp_centrify_crontab_ext import gp_centrify_crontab_ext, \
+                                          gp_user_centrify_crontab_ext
 from samba.common import get_bytes
 from samba.dcerpc import preg
 from samba.ndr import ndr_pack
@@ -9163,3 +9166,166 @@ class GPOTests(tests.TestCase):
 
         # Unstage the Registry.pol file
         unstage_file(reg_pol)
+
+    def test_gp_centrify_sudoers_ext(self):
+        local_path = self.lp.cache_path('gpo_cache')
+        guid = '{31B2F340-016D-11D2-945F-00C04FB984F9}'
+        reg_pol = os.path.join(local_path, policies, guid,
+                               'MACHINE/REGISTRY.POL')
+        cache_dir = self.lp.get('cache directory')
+        store = GPOStorage(os.path.join(cache_dir, 'gpo.tdb'))
+
+        machine_creds = Credentials()
+        machine_creds.guess(self.lp)
+        machine_creds.set_machine_account()
+
+        # Initialize the group policy extension
+        ext = gp_centrify_sudoers_ext(self.lp, machine_creds,
+                                      machine_creds.get_username(), store)
+
+        ads = gpo.ADS_STRUCT(self.server, self.lp, machine_creds)
+        if ads.connect():
+            gpos = ads.get_gpo_list(machine_creds.get_username())
+
+        # Stage the Registry.pol file with test data
+        stage = preg.file()
+        e1 = preg.entry()
+        e1.keyname = b'Software\\Policies\\Centrify\\UnixSettings'
+        e1.valuename = b'sudo.enabled'
+        e1.type = 4
+        e1.data = 1
+        e2 = preg.entry()
+        e2.keyname = b'Software\\Policies\\Centrify\\UnixSettings\\SuDo'
+        e2.valuename = b'1'
+        e2.type = 1
+        e2.data = b'fakeu ALL=(ALL) NOPASSWD: ALL'
+        stage.num_entries = 2
+        stage.entries = [e1, e2]
+        ret = stage_file(reg_pol, ndr_pack(stage))
+        self.assertTrue(ret, 'Could not create the target %s' % reg_pol)
+
+        # Process all gpos, with temp output directory
+        with TemporaryDirectory() as dname:
+            ext.process_group_policy([], gpos, dname)
+            sudoers = os.listdir(dname)
+            self.assertEquals(len(sudoers), 1, 'The sudoer file was not created')
+            self.assertIn(e2.data,
+                    open(os.path.join(dname, sudoers[0]), 'r').read(),
+                    'The sudoers entry was not applied')
+
+            # Remove policy
+            gp_db = store.get_gplog(machine_creds.get_username())
+            del_gpos = get_deleted_gpos_list(gp_db, [])
+            ext.process_group_policy(del_gpos, [])
+            self.assertEquals(len(os.listdir(dname)), 0,
+                              'Unapply failed to cleanup scripts')
+
+        # Unstage the Registry.pol file
+        unstage_file(reg_pol)
+
+    def test_gp_centrify_crontab_ext(self):
+        local_path = self.lp.cache_path('gpo_cache')
+        guid = '{31B2F340-016D-11D2-945F-00C04FB984F9}'
+        reg_pol = os.path.join(local_path, policies, guid,
+                               'MACHINE/REGISTRY.POL')
+        cache_dir = self.lp.get('cache directory')
+        store = GPOStorage(os.path.join(cache_dir, 'gpo.tdb'))
+
+        machine_creds = Credentials()
+        machine_creds.guess(self.lp)
+        machine_creds.set_machine_account()
+
+        # Initialize the group policy extension
+        ext = gp_centrify_crontab_ext(self.lp, machine_creds,
+                                      machine_creds.get_username(), store)
+
+        ads = gpo.ADS_STRUCT(self.server, self.lp, machine_creds)
+        if ads.connect():
+            gpos = ads.get_gpo_list(machine_creds.get_username())
+
+        # Stage the Registry.pol file with test data
+        stage = preg.file()
+        e = preg.entry()
+        e.keyname = \
+            b'Software\\Policies\\Centrify\\UnixSettings\\CrontabEntries'
+        e.valuename = b'Command1'
+        e.type = 1
+        e.data = b'17 * * * * root echo hello world'
+        stage.num_entries = 1
+        stage.entries = [e]
+        ret = stage_file(reg_pol, ndr_pack(stage))
+        self.assertTrue(ret, 'Could not create the target %s' % reg_pol)
+
+        # Process all gpos, with temp output directory
+        with TemporaryDirectory() as dname:
+            ext.process_group_policy([], gpos, dname)
+            cron_entries = os.listdir(dname)
+            self.assertEquals(len(cron_entries), 1, 'Cron entry not created')
+            fname = os.path.join(dname, cron_entries[0])
+            data = open(fname, 'rb').read()
+            self.assertIn(get_bytes(e.data), data, 'Cron entry is missing')
+
+            # Remove policy
+            gp_db = store.get_gplog(machine_creds.get_username())
+            del_gpos = get_deleted_gpos_list(gp_db, [])
+            ext.process_group_policy(del_gpos, [])
+            self.assertEquals(len(os.listdir(dname)), 0,
+                              'Unapply failed to cleanup script')
+
+            # Unstage the Registry.pol file
+            unstage_file(reg_pol)
+
+    def test_gp_user_centrify_crontab_ext(self):
+        local_path = self.lp.cache_path('gpo_cache')
+        guid = '{31B2F340-016D-11D2-945F-00C04FB984F9}'
+        reg_pol = os.path.join(local_path, policies, guid,
+                               'USER/REGISTRY.POL')
+        cache_dir = self.lp.get('cache directory')
+        store = GPOStorage(os.path.join(cache_dir, 'gpo.tdb'))
+
+        machine_creds = Credentials()
+        machine_creds.guess(self.lp)
+        machine_creds.set_machine_account()
+
+        # Initialize the group policy extension
+        ext = gp_user_centrify_crontab_ext(self.lp, machine_creds,
+                                           os.environ.get('DC_USERNAME'),
+                                           store)
+
+        ads = gpo.ADS_STRUCT(self.server, self.lp, machine_creds)
+        if ads.connect():
+            gpos = ads.get_gpo_list(machine_creds.get_username())
+
+        # Stage the Registry.pol file with test data
+        stage = preg.file()
+        e = preg.entry()
+        e.keyname = \
+            b'Software\\Policies\\Centrify\\UnixSettings\\CrontabEntries'
+        e.valuename = b'Command1'
+        e.type = 1
+        e.data = b'17 * * * * echo hello world'
+        stage.num_entries = 1
+        stage.entries = [e]
+        ret = stage_file(reg_pol, ndr_pack(stage))
+        self.assertTrue(ret, 'Could not create the target %s' % reg_pol)
+
+        # Process all gpos, intentionally skipping the privilege drop
+        ext.process_group_policy([], gpos)
+        # Dump the fake crontab setup for testing
+        p = Popen(['crontab', '-l'], stdout=PIPE)
+        crontab, _ = p.communicate()
+        self.assertIn(get_bytes(e.data), crontab,
+            'The crontab entry was not installed')
+
+        # Remove policy
+        gp_db = store.get_gplog(os.environ.get('DC_USERNAME'))
+        del_gpos = get_deleted_gpos_list(gp_db, [])
+        ext.process_group_policy(del_gpos, [])
+        # Dump the fake crontab setup for testing
+        p = Popen(['crontab', '-l'], stdout=PIPE)
+        crontab, _ = p.communicate()
+        self.assertNotIn(get_bytes(e.data), crontab,
+            'Unapply failed to cleanup crontab entry')
+
+        # Unstage the Registry.pol file
+        unstage_file(reg_pol)
diff --git a/source4/scripting/bin/samba-gpupdate b/source4/scripting/bin/samba-gpupdate
index 0d0e9271a14..079ae485f10 100755
--- a/source4/scripting/bin/samba-gpupdate
+++ b/source4/scripting/bin/samba-gpupdate
@@ -49,6 +49,9 @@ from samba.gp_cert_auto_enroll_ext import gp_cert_auto_enroll_ext
 from samba.gp_firefox_ext import gp_firefox_ext
 from samba.gp_chromium_ext import gp_chromium_ext, gp_chrome_ext
 from samba.gp_firewalld_ext import gp_firewalld_ext
+from samba.gp_centrify_sudoers_ext import gp_centrify_sudoers_ext
+from samba.gp_centrify_crontab_ext import gp_centrify_crontab_ext, \
+                                          gp_user_centrify_crontab_ext
 from samba.credentials import Credentials
 from samba.gp.util.logging import logger_init
 
@@ -101,6 +104,8 @@ if __name__ == "__main__":
         gp_extensions.append(gp_scripts_ext)
         gp_extensions.append(gp_sudoers_ext)
         gp_extensions.append(vgp_sudoers_ext)
+        gp_extensions.append(gp_centrify_sudoers_ext)
+        gp_extensions.append(gp_centrify_crontab_ext)
         gp_extensions.append(gp_smb_conf_ext)
         gp_extensions.append(gp_msgs_ext)
         gp_extensions.append(vgp_symlink_ext)
@@ -119,6 +124,7 @@ if __name__ == "__main__":
         gp_extensions.extend(machine_exts)
     elif opts.target == 'User':
         gp_extensions.append(gp_user_scripts_ext)
+        gp_extensions.append(gp_user_centrify_crontab_ext)
         gp_extensions.extend(user_exts)
 
     if opts.rsop:


-- 
Samba Shared Repository



More information about the samba-cvs mailing list