[SCM] Samba Shared Repository - branch master updated

David Mulder dmulder at samba.org
Tue Jun 23 17:54:02 UTC 2020


The branch, master has been updated
       via  ab50d348d93 gpo: Test samba-tool gpo admxload
       via  2c1ebd07b18 samba-tool: add command for installing gpo samba admx
       via  e32f4602ed3 Add python binding for DATADIR build path
       via  97a8f999461 gpo: Test gpo scripts apply
       via  a9d1ccc5699 gpo: Run Group Policy Scripts
       via  cd52a280913 Create Registry.pol group policy extension parser
      from  1a6b714605a nsswitch: silence openpam error messages about unexpected responses

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


- Log -----------------------------------------------------------------
commit ab50d348d9357dcf18863161992cdf49038c954a
Author: David Mulder <dmulder at suse.com>
Date:   Thu Jun 18 12:06:28 2020 -0600

    gpo: Test samba-tool gpo admxload
    
    Signed-off-by: David Mulder <dmulder at suse.com>
    Reviewed-by: Alexander Bokovoy <ab at samba.org>
    
    Autobuild-User(master): David Mulder <dmulder at samba.org>
    Autobuild-Date(master): Tue Jun 23 17:53:22 UTC 2020 on sn-devel-184

commit 2c1ebd07b18cdd64df444b8c356e9044c87008c3
Author: David Mulder <dmulder at suse.com>
Date:   Tue Oct 16 03:36:09 2018 -0600

    samba-tool: add command for installing gpo samba admx
    
    Signed-off-by: David Mulder <dmulder at suse.com>
    Reviewed-by: Alexander Bokovoy <ab at samba.org>

commit e32f4602ed3827530fd63bf31693fb12ede013b9
Author: David Mulder <dmulder at suse.com>
Date:   Tue Oct 16 03:23:34 2018 -0600

    Add python binding for DATADIR build path
    
    Signed-off-by: David Mulder <dmulder at suse.com>
    Reviewed-by: Alexander Bokovoy <ab at samba.org>

commit 97a8f999461f8ca9c24824734131700745310605
Author: David Mulder <dmulder at suse.com>
Date:   Tue Jun 16 15:29:40 2020 -0600

    gpo: Test gpo scripts apply
    
    Signed-off-by: David Mulder <dmulder at suse.com>
    Reviewed-by: Alexander Bokovoy <ab at samba.org>

commit a9d1ccc5699a4e8c66012f769cec8fba6ce84a59
Author: David Mulder <dmulder at suse.com>
Date:   Mon Apr 27 16:02:55 2020 -0600

    gpo: Run Group Policy Scripts
    
    Signed-off-by: David Mulder <dmulder at suse.com>
    Reviewed-by: Alexander Bokovoy <ab at samba.org>

commit cd52a280913a6536b4923da7214977c762f664ed
Author: David Mulder <dmulder at suse.com>
Date:   Thu Aug 9 09:47:38 2018 -0600

    Create Registry.pol group policy extension parser
    
    Create a parent class for parsing Registry.pol
    files by group policy extensions.
    
    Signed-off-by: David Mulder <dmulder at suse.com>
    Reviewed-by: Alexander Bokovoy <ab at samba.org>

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

Summary of changes:
 libgpo/admx/en-US/samba.adml         | 19 ++++++++++
 libgpo/admx/samba.admx               | 23 ++++++++++++
 libgpo/admx/wscript_build            |  3 ++
 libgpo/wscript_build                 |  2 +
 python/samba/gp_scripts_ext.py       | 53 ++++++++++++++++++++++++++
 python/samba/gpclass.py              | 14 ++++++-
 python/samba/netcmd/gpo.py           | 72 ++++++++++++++++++++++++++++++++++++
 python/samba/tests/gpo.py            | 48 +++++++++++++++++++++++-
 python/samba/tests/samba_tool/gpo.py | 25 +++++++++++++
 source4/param/pyparam.c              |  7 ++++
 source4/scripting/bin/samba-gpupdate |  2 +
 11 files changed, 265 insertions(+), 3 deletions(-)
 create mode 100755 libgpo/admx/en-US/samba.adml
 create mode 100755 libgpo/admx/samba.admx
 create mode 100644 libgpo/admx/wscript_build
 create mode 100644 python/samba/gp_scripts_ext.py


Changeset truncated at 500 lines:

diff --git a/libgpo/admx/en-US/samba.adml b/libgpo/admx/en-US/samba.adml
new file mode 100755
index 00000000000..b5fc5098638
--- /dev/null
+++ b/libgpo/admx/en-US/samba.adml
@@ -0,0 +1,19 @@
+<policyDefinitionResources revision="1.0" schemaVersion="1.0">
+  <displayName>
+  </displayName>
+  <description>
+  </description>
+  <resources>
+    <stringTable>
+      <string id="CAT_3338C1DD_8A00_4273_8547_158D8B8C19E9">Samba</string>
+      <string id="CAT_7D8D7DC8_5A9D_4BE1_8227_F09CDD5AFFC6">Unix Settings</string>
+      <string id="POL_9320E11F_AC80_4A7D_A5C8_1C0F3F727061">Daily Scripts</string>
+      <string id="POL_9320E11F_AC80_4A7D_A5C8_1C0F3F727061_Help">This policy setting allows you to execute commands, either local or on remote storage, daily.</string>
+    </stringTable>
+    <presentationTable>
+      <presentation id="POL_9320E11F_AC80_4A7D_A5C8_1C0F3F727061">
+        <listBox refId="LST_2E9A4684_3C0E_415B_8FD6_D4AF68BC8AC6">Script and arguments</listBox>
+      </presentation>
+    </presentationTable>
+  </resources>
+</policyDefinitionResources>
diff --git a/libgpo/admx/samba.admx b/libgpo/admx/samba.admx
new file mode 100755
index 00000000000..f2921ff1885
--- /dev/null
+++ b/libgpo/admx/samba.admx
@@ -0,0 +1,23 @@
+<policyDefinitions revision="1.0" schemaVersion="1.0">
+  <policyNamespaces>
+    <target prefix="fullarmor" namespace="FullArmor.Policies.98BB16AF_01EE_4D17_870D_A3311A44D6C2" />
+    <using prefix="windows" namespace="Microsoft.Policies.Windows" />
+  </policyNamespaces>
+  <supersededAdm fileName="" />
+  <resources minRequiredRevision="1.0" />
+  <categories>
+    <category name="CAT_3338C1DD_8A00_4273_8547_158D8B8C19E9" displayName="$(string.CAT_3338C1DD_8A00_4273_8547_158D8B8C19E9)" />
+    <category name="CAT_7D8D7DC8_5A9D_4BE1_8227_F09CDD5AFFC6" displayName="$(string.CAT_7D8D7DC8_5A9D_4BE1_8227_F09CDD5AFFC6)">
+      <parentCategory ref="CAT_3338C1DD_8A00_4273_8547_158D8B8C19E9" />
+    </category>
+  </categories>
+  <policies>
+    <policy name="POL_9320E11F_AC80_4A7D_A5C8_1C0F3F727061" class="Machine" displayName="$(string.POL_9320E11F_AC80_4A7D_A5C8_1C0F3F727061)" explainText="$(string.POL_9320E11F_AC80_4A7D_A5C8_1C0F3F727061_Help)" presentation="$(presentation.POL_9320E11F_AC80_4A7D_A5C8_1C0F3F727061)" key="Software\Policies\Samba\Unix Settings">
+      <parentCategory ref="CAT_7D8D7DC8_5A9D_4BE1_8227_F09CDD5AFFC6" />
+      <supportedOn ref="windows:SUPPORTED_WindowsVista" />
+      <elements>
+        <list id="LST_2E9A4684_3C0E_415B_8FD6_D4AF68BC8AC6" key="Software\Policies\Samba\Unix Settings\Daily Scripts" valueName="Daily Scripts" />
+      </elements>
+    </policy>
+  </policies>
+</policyDefinitions>
diff --git a/libgpo/admx/wscript_build b/libgpo/admx/wscript_build
new file mode 100644
index 00000000000..cb1cadbf782
--- /dev/null
+++ b/libgpo/admx/wscript_build
@@ -0,0 +1,3 @@
+#!/usr/bin/env python
+
+bld.INSTALL_FILES('${DATADIR}/samba/admx', ['samba.admx', 'en-US/samba.adml'])
diff --git a/libgpo/wscript_build b/libgpo/wscript_build
index f36ccf2c701..e6e54fe359a 100644
--- a/libgpo/wscript_build
+++ b/libgpo/wscript_build
@@ -19,3 +19,5 @@ pyrpc_util = bld.pyembed_libname('pyrpc_util')
 bld.SAMBA3_PYTHON('python_samba_libgpo', 'pygpo.c',
                   deps='%s gpext talloc ads TOKEN_UTIL auth %s' % (pyparam_util, pyrpc_util),
                   realname='samba/gpo.so')
+
+bld.RECURSE('admx')
diff --git a/python/samba/gp_scripts_ext.py b/python/samba/gp_scripts_ext.py
new file mode 100644
index 00000000000..f83f367a5d7
--- /dev/null
+++ b/python/samba/gp_scripts_ext.py
@@ -0,0 +1,53 @@
+# gp_scripts_ext samba gpo policy
+# Copyright (C) David Mulder <dmulder at suse.com> 2020
+#
+# 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
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+import os, re
+from samba.gpclass import gp_pol_ext
+from base64 import b64encode
+from tempfile import NamedTemporaryFile
+
+class gp_scripts_ext(gp_pol_ext):
+    def __str__(self):
+        return 'Unix Settings/Daily Scripts'
+
+    def process_group_policy(self, deleted_gpo_list, changed_gpo_list, cdir='/etc/cron.daily'):
+        for gpo in deleted_gpo_list:
+            self.gp_db.set_guid(gpo[0])
+            if str(self) in gpo[1]:
+                for attribute, script in gpo[1][str(self)].items():
+                    os.unlink(script)
+                    self.gp_db.delete(str(self), attribute)
+            self.gp_db.commit()
+
+        for gpo in changed_gpo_list:
+            if gpo.file_sys_path:
+                section_name = 'Software\\Policies\\Samba\\Unix Settings\\Daily Scripts'
+                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
+                for e in pol_conf.entries:
+                    if e.keyname == section_name and e.data.strip():
+                        attribute = b64encode(e.data.encode()).decode()
+                        old_val = self.gp_db.retrieve(str(self), attribute)
+                        if not old_val:
+                            with NamedTemporaryFile(mode="w+", delete=False, dir=cdir) as f:
+                                f.write('#!/bin/sh\n%s' % e.data)
+                                os.chmod(f.name, 0o700)
+                                self.gp_db.store(str(self), attribute, f.name)
+                        self.gp_db.commit()
diff --git a/python/samba/gpclass.py b/python/samba/gpclass.py
index 0040f235e6e..cc574e12a42 100644
--- a/python/samba/gpclass.py
+++ b/python/samba/gpclass.py
@@ -35,6 +35,9 @@ import samba.gpo as gpo
 from samba.param import LoadParm
 from uuid import UUID
 from tempfile import NamedTemporaryFile
+from samba.dcerpc import preg
+from samba.dcerpc import misc
+from samba.ndr import ndr_pack, ndr_unpack
 
 try:
     from enum import Enum
@@ -307,7 +310,7 @@ class gp_ext(object):
         local_path = self.lp.cache_path('gpo_cache')
         data_file = os.path.join(local_path, check_safe_path(afile).upper())
         if os.path.exists(data_file):
-            return self.read(open(data_file, 'r').read())
+            return self.read(data_file)
         return None
 
     @abstractmethod
@@ -347,7 +350,8 @@ class gp_ext_setter(object):
 
 
 class gp_inf_ext(gp_ext):
-    def read(self, policy):
+    def read(self, data_file):
+        policy = open(data_file, 'r').read()
         inf_conf = ConfigParser()
         inf_conf.optionxform = str
         try:
@@ -357,6 +361,12 @@ class gp_inf_ext(gp_ext):
         return inf_conf
 
 
+class gp_pol_ext(gp_ext):
+    def read(self, data_file):
+        raw = open(data_file, 'rb').read()
+        return ndr_unpack(preg.file, raw)
+
+
 ''' Fetch the hostname of a writable DC '''
 
 
diff --git a/python/samba/netcmd/gpo.py b/python/samba/netcmd/gpo.py
index 4b08c62d773..1e2c2918ebe 100644
--- a/python/samba/netcmd/gpo.py
+++ b/python/samba/netcmd/gpo.py
@@ -61,6 +61,7 @@ from samba.gp_parse.gp_ini import (
 from samba.gp_parse.gp_csv import GPAuditCsvParser
 from samba.gp_parse.gp_inf import GptTmplInfParser
 from samba.gp_parse.gp_aas import GPAasParser
+from samba import param
 
 
 def attr_default(msg, attrname, default):
@@ -1593,6 +1594,76 @@ class cmd_aclcheck(GPOCommand):
             if (fs_sd.as_sddl(domain_sid) != expected_fs_sddl):
                 raise CommandError("Invalid GPO ACL %s on path (%s), should be %s" % (fs_sd.as_sddl(domain_sid), sharepath, expected_fs_sddl))
 
+class cmd_admxload(Command):
+    """Loads samba admx files to sysvol"""
+
+    synopsis = "%prog [options]"
+
+    takes_optiongroups = {
+        "sambaopts": options.SambaOptions,
+        "versionopts": options.VersionOptions,
+        "credopts": options.CredentialsOptions,
+    }
+
+    takes_options = [
+        Option("-H", "--URL", help="LDB URL for database or target server", type=str,
+                metavar="URL", dest="H"),
+        Option("--admx-dir", help="Directory where admx templates are stored",
+                type=str, default=os.path.join(param.data_dir(), 'samba/admx'))
+    ]
+
+    def run(self, H=None, sambaopts=None, credopts=None, versionopts=None,
+            admx_dir=None):
+        self.lp = sambaopts.get_loadparm()
+        self.creds = credopts.get_credentials(self.lp, fallback_machine=True)
+
+        # We need to know writable DC to setup SMB connection
+        if H and H.startswith('ldap://'):
+            dc_hostname = H[7:]
+            self.url = H
+        else:
+            dc_hostname = netcmd_finddc(self.lp, self.creds)
+            self.url = dc_url(self.lp, self.creds, dc=dc_hostname)
+
+        # SMB connect to DC
+        conn = smb_connection(dc_hostname,
+                              'sysvol',
+                              lp=self.lp,
+                              creds=self.creds,
+                              sign=True)
+
+        smb_dir = '\\'.join([self.lp.get('realm').lower(),
+                             'Policies', 'PolicyDefinitions'])
+        try:
+            conn.mkdir(smb_dir)
+        except NTSTATUSError as e:
+            if e.args[0] == 0xC0000022: # STATUS_ACCESS_DENIED
+                raise CommandError("The authenticated user does "
+                                   "not have sufficient privileges")
+            elif e.args[0] != 0xC0000035: # STATUS_OBJECT_NAME_COLLISION
+                raise
+
+        for dirname, dirs, files in os.walk(admx_dir):
+            for fname in files:
+                path_in_admx = dirname.replace(admx_dir, '')
+                full_path = os.path.join(dirname, fname)
+                sub_dir = '\\'.join([smb_dir, path_in_admx]).replace('/', '\\')
+                smb_path = '\\'.join([sub_dir, fname])
+                try:
+                    conn.mkdir(sub_dir)
+                except NTSTATUSError as e:
+                    if e.args[0] == 0xC0000022: # STATUS_ACCESS_DENIED
+                        raise CommandError("The authenticated user does "
+                                           "not have sufficient privileges")
+                    elif e.args[0] != 0xC0000035: # STATUS_OBJECT_NAME_COLLISION
+                        raise
+                with open(full_path, 'rb') as f:
+                    try:
+                        conn.savefile(smb_path, f.read())
+                    except NTSTATUSError as e:
+                        if e.args[0] == 0xC0000022: # STATUS_ACCESS_DENIED
+                            raise CommandError("The authenticated user does "
+                                               "not have sufficient privileges")
 
 class cmd_gpo(SuperCommand):
     """Group Policy Object (GPO) management."""
@@ -1613,3 +1684,4 @@ class cmd_gpo(SuperCommand):
     subcommands["aclcheck"] = cmd_aclcheck()
     subcommands["backup"] = cmd_backup()
     subcommands["restore"] = cmd_restore()
+    subcommands["admxload"] = cmd_admxload()
diff --git a/python/samba/tests/gpo.py b/python/samba/tests/gpo.py
index dce00bd8f86..02ff6d97121 100644
--- a/python/samba/tests/gpo.py
+++ b/python/samba/tests/gpo.py
@@ -23,11 +23,14 @@ from samba.param import LoadParm
 from samba.gpclass import check_refresh_gpo_list, check_safe_path, \
     check_guid, parse_gpext_conf, atomic_write_conf, get_deleted_gpos_list
 from subprocess import Popen, PIPE
-from tempfile import NamedTemporaryFile
+from tempfile import NamedTemporaryFile, TemporaryDirectory
 from samba.gp_sec_ext import gp_sec_ext
+from samba.gp_scripts_ext import gp_scripts_ext
 import logging
 from samba.credentials import Credentials
 from samba.compat import get_bytes
+from samba.dcerpc import preg
+from samba.ndr import ndr_pack
 
 realm = os.environ.get('REALM')
 policies = realm + '/POLICIES'
@@ -316,3 +319,46 @@ class GPOTests(tests.TestCase):
         for guid in guids:
             gpttmpl = gpofile % (local_path, guid)
             unstage_file(gpttmpl)
+
+    def test_gp_daily_scripts(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')
+        logger = logging.getLogger('gpo_tests')
+        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_scripts_ext(logger, self.lp, machine_creds, 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\\Samba\\Unix Settings\\Daily Scripts'
+        e.valuename = b'Software\\Policies\\Samba\\Unix Settings'
+        e.type = 1
+        e.data = b'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)
+            scripts = os.listdir(dname)
+            self.assertEquals(len(scripts), 1, 'The daily script was not created')
+            out, _ = Popen([os.path.join(dname, scripts[0])], stdout=PIPE).communicate()
+            self.assertIn(b'hello world', out, 'Daily script execution failed')
+
+        # Unstage the Registry.pol file
+        unstage_file(reg_pol)
diff --git a/python/samba/tests/samba_tool/gpo.py b/python/samba/tests/samba_tool/gpo.py
index 5cf68f808d4..3e6d4e8fd27 100644
--- a/python/samba/tests/samba_tool/gpo.py
+++ b/python/samba/tests/samba_tool/gpo.py
@@ -24,7 +24,9 @@ import samba
 from samba.tests.samba_tool.base import SambaToolCmdTest
 import shutil
 from samba.netcmd.gpo import get_gpo_dn, get_gpo_info
+from samba.param import LoadParm
 
+source_path = os.path.abspath(os.path.join(os.path.dirname(__file__), "../../../../.."))
 
 def has_difference(path1, path2, binary=True, xml=True, sortlines=False):
     """Use this function to determine if the GPO backup differs from another.
@@ -517,6 +519,29 @@ class GpoCmdTestCase(SambaToolCmdTest):
             shutil.rmtree(os.path.join(self.tempdir, "policy"))
             shutil.rmtree(os.path.join(self.tempdir, 'temp'))
 
+    def test_admx_load(self):
+        lp = LoadParm()
+        lp.load(os.environ['SERVERCONFFILE'])
+        local_path = lp.get('path', 'sysvol')
+        admx_path = os.path.join(local_path, os.environ['REALM'].lower(),
+                                 'Policies', 'PolicyDefinitions')
+        (result, out, err) = self.runsubcmd("gpo", "admxload",
+                                            "-H", "ldap://%s" %
+                                            os.environ["SERVER"],
+                                            "--admx-dir=%s" %
+                                            os.path.join(source_path,
+                                                         'libgpo/admx'),
+                                            "-U%s%%%s" %
+                                            (os.environ["USERNAME"],
+                                            os.environ["PASSWORD"]))
+        self.assertCmdSuccess(result, out, err,
+                              'Filling PolicyDefinitions failed')
+        self.assertTrue(os.path.exists(admx_path),
+                        'PolicyDefinitions was not created')
+        self.assertTrue(os.path.exists(os.path.join(admx_path, 'samba.admx')),
+                        'Filling PolicyDefinitions failed')
+        shutil.rmtree(admx_path)
+
     def setUp(self):
         """set up a temporary GPO to work with"""
         super(GpoCmdTestCase, self).setUp()
diff --git a/source4/param/pyparam.c b/source4/param/pyparam.c
index 5e5e1d370cd..4023fac4dd6 100644
--- a/source4/param/pyparam.c
+++ b/source4/param/pyparam.c
@@ -614,6 +614,11 @@ PyTypeObject PyLoadparmService = {
 	.tp_flags = Py_TPFLAGS_DEFAULT,
 };
 
+static PyObject *py_data_dir(PyObject *self)
+{
+        return PyUnicode_FromString(dyn_DATADIR);
+}
+
 static PyObject *py_default_path(PyObject *self, PyObject *Py_UNUSED(ignored))
 {
 	return PyUnicode_FromString(lp_default_path());
@@ -640,6 +645,8 @@ static PyObject *py_sbin_dir(PyObject *self, PyObject *Py_UNUSED(ignored))
 }
 
 static PyMethodDef pyparam_methods[] = {
+	{ "data_dir", (PyCFunction)py_data_dir, METH_NOARGS,
+		"Returns the compiled in location of data directory." },
 	{ "default_path", (PyCFunction)py_default_path, METH_NOARGS,
 		"Returns the default smb.conf path." },
 	{ "setup_dir", (PyCFunction)py_setup_dir, METH_NOARGS,
diff --git a/source4/scripting/bin/samba-gpupdate b/source4/scripting/bin/samba-gpupdate
index 528019c7478..68dfad1ed87 100755
--- a/source4/scripting/bin/samba-gpupdate
+++ b/source4/scripting/bin/samba-gpupdate
@@ -32,6 +32,7 @@ from samba import getopt as options
 from samba.gpclass import apply_gp, unapply_gp, GPOStorage
 from samba.gp_sec_ext import gp_sec_ext
 from samba.gp_ext_loader import get_gp_client_side_extensions
+from samba.gp_scripts_ext import gp_scripts_ext
 import logging
 
 if __name__ == "__main__":
@@ -80,6 +81,7 @@ if __name__ == "__main__":
     gp_extensions = []
     if opts.target == 'Computer':
         gp_extensions.append(gp_sec_ext(logger, lp, creds, store))
+        gp_extensions.append(gp_scripts_ext(logger, lp, creds, store))
         for ext in machine_exts:
             gp_extensions.append(ext(logger, lp, creds, store))
     elif opts.target == 'User':


-- 
Samba Shared Repository



More information about the samba-cvs mailing list