[SCM] Samba Shared Repository - branch master updated

Andrew Bartlett abartlet at samba.org
Mon Jan 30 10:01:01 UTC 2023


The branch, master has been updated
       via  f6712c70986 script:autobuild: Make sure we can send a failure mail
       via  41aa379abb3 python: Replace calls to deprecated methods
       via  a15208f60bb samba-tool: Use ntstatus constants in gpo commands
       via  a4530c153e3 samba-tool: Test gpo show/load handling of utf-16-le strings
       via  3b0d78a3fdc samba-tool: gpo show/load handle utf-16-le strings
       via  e6032703606 samba-tool: gpo load provide option for replace vs merge
       via  6f373603720 samba-tool: gpo load set ntacl with SYSVOL file creation
       via  e7737d6bb27 samba-tool: gpo load add Registry ext by default
       via  a3452147129 samba-tool: gpo load extension names
       via  00e40f9f924 samba-tool: gpo load/remove increment GPT.INI
       via  ea619d704e4 samba-tool: gpo load/remove bytes
       via  dc6725336ad samba-tool: Test gpo load/remove commands
       via  ee37e3cd32e samba-tool: gpo load/remove commands
       via  a0f8d7ca05e samba-tool: Move smb_connection to a common file
       via  d6194600c19 samba-tool: Move create_directory_hier to a common file
       via  e40faf7a750 samba-tool: gpo show command list policies
      from  7e0eb0f31a2 s3:lib: Change file_modtime() to return an error code and a struct timespec.

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


- Log -----------------------------------------------------------------
commit f6712c709868bf87dfd3d92bec1f306d2a98116e
Author: Andreas Schneider <asn at samba.org>
Date:   Wed Jan 25 17:08:58 2023 +0100

    script:autobuild: Make sure we can send a failure mail
    
    We should not run into an exception if the file doesn't exist.
    
    Traceback (most recent call last):
      File "script/autobuild.py", line 1781, in <module>
        email_failure(-1, 'rebase', 'rebase', 'rebase',
      File "script/autobuild.py", line 1677, in email_failure
        f = open("%s/%s.stdout" % (gitroot, failed_tag), 'r')
    FileNotFoundError: [Errno 2] No such file or directory:
      'samba-autobuild/rebase.stdout'
    
    Signed-off-by: Andreas Schneider <asn at samba.org>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>
    
    Autobuild-User(master): Andrew Bartlett <abartlet at samba.org>
    Autobuild-Date(master): Mon Jan 30 10:00:27 UTC 2023 on atb-devel-224

commit 41aa379abb391ffab77238d65ee5ba11b9ab8538
Author: Joseph Sutton <josephsutton at catalyst.net.nz>
Date:   Thu Jan 19 08:37:03 2023 +1300

    python: Replace calls to deprecated methods
    
    These aliases are deprecated and have been removed in Python 3.12.
    
    Signed-off-by: Joseph Sutton <josephsutton at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit a15208f60bbace89d99acbe8e3a8325740f5d6ab
Author: David Mulder <dmulder at samba.org>
Date:   Wed Dec 7 10:56:54 2022 -0700

    samba-tool: Use ntstatus constants in gpo commands
    
    Replace all the hard coded instances of ntstatus
    codes in the samba-tool gpo commands with
    constants from samba.ntstatus.
    
    Signed-off-by: David Mulder <dmulder at samba.org>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit a4530c153e38b205f0ffa7f30e06d2a4469fa58b
Author: David Mulder <dmulder at suse.com>
Date:   Thu Mar 24 11:35:02 2022 -0600

    samba-tool: Test gpo show/load handling of utf-16-le strings
    
    Signed-off-by: David Mulder <dmulder at suse.com>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>
    Tested-by: Kees van Vloten <keesvanvloten at gmail.com>

commit 3b0d78a3fdcd2df1d6ee63f41e2d56688ccd83f1
Author: David Mulder <dmulder at suse.com>
Date:   Thu Mar 24 17:05:13 2022 +0000

    samba-tool: gpo show/load handle utf-16-le strings
    
    Signed-off-by: David Mulder <dmulder at suse.com>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>
    Tested-by: Kees van Vloten <keesvanvloten at gmail.com>

commit e60327036067d1b3141ec40200efeeb057aa93ff
Author: David Mulder <dmulder at suse.com>
Date:   Thu Feb 17 10:38:46 2022 -0700

    samba-tool: gpo load provide option for replace vs merge
    
    Signed-off-by: David Mulder <dmulder at suse.com>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>
    Tested-by: Kees van Vloten <keesvanvloten at gmail.com>

commit 6f3736037203f21b8508f134dde6bd25867f5613
Author: David Mulder <dmulder at suse.com>
Date:   Wed Feb 16 03:11:34 2022 -0700

    samba-tool: gpo load set ntacl with SYSVOL file creation
    
    Signed-off-by: David Mulder <dmulder at suse.com>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>
    Tested-by: Kees van Vloten <keesvanvloten at gmail.com>

commit e7737d6bb27dd4b70782635eafa75f4d01450aa7
Author: David Mulder <dmulder at suse.com>
Date:   Tue Feb 15 14:45:41 2022 -0700

    samba-tool: gpo load add Registry ext by default
    
    Signed-off-by: David Mulder <dmulder at suse.com>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>
    Tested-by: Kees van Vloten <keesvanvloten at gmail.com>

commit a3452147129a0eea6a578c3d57aa828642986d89
Author: David Mulder <dmulder at suse.com>
Date:   Tue Feb 15 11:09:12 2022 -0700

    samba-tool: gpo load extension names
    
    Signed-off-by: David Mulder <dmulder at suse.com>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>
    Tested-by: Kees van Vloten <keesvanvloten at gmail.com>

commit 00e40f9f924f6354e5e8e9e0d0ee7077243a4b26
Author: David Mulder <dmulder at suse.com>
Date:   Mon Feb 14 13:34:39 2022 -0700

    samba-tool: gpo load/remove increment GPT.INI
    
    Signed-off-by: David Mulder <dmulder at suse.com>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>
    Tested-by: Kees van Vloten <keesvanvloten at gmail.com>

commit ea619d704e4d9f498104b20bb1c8a98a1a6df9d6
Author: David Mulder <dmulder at suse.com>
Date:   Mon Jan 24 09:21:47 2022 -0700

    samba-tool: gpo load/remove bytes
    
    Signed-off-by: David Mulder <dmulder at suse.com>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>
    Tested-by: Kees van Vloten <keesvanvloten at gmail.com>

commit dc6725336ad76fe425ef818a83272bd4cf7c937c
Author: David Mulder <dmulder at suse.com>
Date:   Fri Jan 21 11:48:48 2022 -0700

    samba-tool: Test gpo load/remove commands
    
    Signed-off-by: David Mulder <dmulder at suse.com>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>
    Tested-by: Kees van Vloten <keesvanvloten at gmail.com>

commit ee37e3cd32e98088cf3b4faba4cc2a2ce3a70175
Author: David Mulder <dmulder at samba.org>
Date:   Tue Jun 29 19:38:02 2021 +0000

    samba-tool: gpo load/remove commands
    
    These commands allow the setting of various group
    policies on the sysvol.
    
    Signed-off-by: David Mulder <dmulder at samba.org>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>
    Tested-by: Kees van Vloten <keesvanvloten at gmail.com>

commit a0f8d7ca05e0cc65d328864f300ae67098526868
Author: David Mulder <dmulder at samba.org>
Date:   Wed Dec 7 11:32:30 2022 -0700

    samba-tool: Move smb_connection to a common file
    
    This is in preparation for needing it here later.
    
    Signed-off-by: David Mulder <dmulder at samba.org>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit d6194600c19e12a58686199ce65daa45367371f6
Author: David Mulder <dmulder at samba.org>
Date:   Wed Dec 7 11:27:00 2022 -0700

    samba-tool: Move create_directory_hier to a common file
    
    This is in preparation for needing it here later.
    
    Signed-off-by: David Mulder <dmulder at samba.org>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit e40faf7a750c3aeb4298b1a9c6647e372c063151
Author: David Mulder <dmulder at samba.org>
Date:   Thu Jun 3 17:05:42 2021 +0000

    samba-tool: gpo show command list policies
    
    Signed-off-by: David Mulder <dmulder at samba.org>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>
    Tested-by: Kees van Vloten <keesvanvloten at gmail.com>

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

Summary of changes:
 python/samba/netcmd/gpcommon.py                    |  55 ++
 python/samba/netcmd/gpo.py                         | 564 +++++++++++++++------
 python/samba/policies.py                           | 389 ++++++++++++++
 python/samba/tests/audit_log_dsdb.py               |  40 +-
 python/samba/tests/audit_log_pass_change.py        |  28 +-
 python/samba/tests/gpo.py                          |  16 +-
 python/samba/tests/group_audit.py                  |  48 +-
 python/samba/tests/prefork_restart.py              |  18 +-
 python/samba/tests/samba_tool/computer.py          |   6 +-
 python/samba/tests/samba_tool/contact.py           |   6 +-
 .../samba_tool/drs_clone_dc_data_lmdb_size.py      |  10 +-
 python/samba/tests/samba_tool/gpo.py               | 157 ++++++
 python/samba/tests/samba_tool/join_lmdb_size.py    |  10 +-
 python/samba/tests/samba_tool/ou.py                |   6 +-
 python/samba/tests/samba_tool/passwordsettings.py  |   4 +-
 .../samba/tests/samba_tool/promote_dc_lmdb_size.py |  10 +-
 .../samba/tests/samba_tool/provision_lmdb_size.py  |  10 +-
 .../tests/samba_tool/provision_password_check.py   |   4 +-
 python/samba/tests/upgradeprovisionneeddc.py       |   8 +-
 script/autobuild.py                                |  10 +-
 source4/dsdb/tests/python/urgent_replication.py    |  20 +-
 .../torture/drs/python/samba_tool_drs_showrepl.py  |  46 +-
 22 files changed, 1152 insertions(+), 313 deletions(-)
 create mode 100644 python/samba/netcmd/gpcommon.py
 create mode 100644 python/samba/policies.py


Changeset truncated at 500 lines:

diff --git a/python/samba/netcmd/gpcommon.py b/python/samba/netcmd/gpcommon.py
new file mode 100644
index 00000000000..ee5da4dfd13
--- /dev/null
+++ b/python/samba/netcmd/gpcommon.py
@@ -0,0 +1,55 @@
+# Samba common group policy functions
+#
+# Copyright Andrew Tridgell 2010
+# Copyright Amitay Isaacs 2011-2012 <amitay at gmail.com>
+#
+# 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 ldb
+from samba.credentials import SMB_SIGNING_REQUIRED
+from samba.samba3 import param as s3param
+from samba.samba3 import libsmb_samba_internal as libsmb
+from samba.netcmd import CommandError
+
+def get_gpo_dn(samdb, gpo):
+    '''Construct the DN for gpo'''
+
+    dn = samdb.get_default_basedn()
+    dn.add_child(ldb.Dn(samdb, "CN=Policies,CN=System"))
+    dn.add_child(ldb.Dn(samdb, "CN=%s" % gpo))
+    return dn
+
+def create_directory_hier(conn, remotedir):
+    elems = remotedir.replace('/', '\\').split('\\')
+    path = ""
+    for e in elems:
+        path = path + '\\' + e
+        if not conn.chkpath(path):
+            conn.mkdir(path)
+
+def smb_connection(dc_hostname, service, lp, creds):
+    # SMB connect to DC
+    # Force signing for the smb connection
+    saved_signing_state = creds.get_smb_signing()
+    creds.set_smb_signing(SMB_SIGNING_REQUIRED)
+    try:
+        # the SMB bindings rely on having a s3 loadparm
+        s3_lp = s3param.get_context()
+        s3_lp.load(lp.configfile)
+        conn = libsmb.Conn(dc_hostname, service, lp=s3_lp, creds=creds)
+    except Exception:
+        raise CommandError("Error connecting to '%s' using SMB" % dc_hostname)
+    # Reset signing state
+    creds.set_smb_signing(saved_signing_state)
+    return conn
diff --git a/python/samba/netcmd/gpo.py b/python/samba/netcmd/gpo.py
index 9cd08273aaa..bfd3e0f05f7 100644
--- a/python/samba/netcmd/gpo.py
+++ b/python/samba/netcmd/gpo.py
@@ -19,6 +19,7 @@
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 #
 import os
+import sys
 import samba.getopt as options
 import ldb
 import re
@@ -43,7 +44,6 @@ import samba.auth
 from samba.auth import AUTH_SESSION_INFO_DEFAULT_GROUPS, AUTH_SESSION_INFO_AUTHENTICATED, AUTH_SESSION_INFO_SIMPLE_PRIVILEGES
 from samba.netcmd.common import netcmd_finddc
 from samba import policy
-from samba.samba3 import param as s3param
 from samba.samba3 import libsmb_samba_internal as libsmb
 from samba import NTSTATUSError
 import uuid
@@ -62,13 +62,28 @@ 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
-from samba.credentials import SMB_SIGNING_REQUIRED
 from samba.netcmd.common import attr_default
 from samba.common import get_bytes, get_string
 from configparser import ConfigParser
 from io import StringIO, BytesIO
 from samba.gp.vgp_files_ext import calc_mode, stat_from_mode
 import hashlib
+import json
+from samba.registry import str_regtype
+from samba.ntstatus import (
+    NT_STATUS_OBJECT_NAME_INVALID,
+    NT_STATUS_OBJECT_NAME_NOT_FOUND,
+    NT_STATUS_OBJECT_PATH_NOT_FOUND,
+    NT_STATUS_OBJECT_NAME_COLLISION,
+    NT_STATUS_ACCESS_DENIED
+)
+from samba.netcmd.gpcommon import (
+    create_directory_hier,
+    smb_connection,
+    get_gpo_dn
+)
+from samba.policies import RegistryGroupPolicies
+from samba.dcerpc.misc import REG_MULTI_SZ
 
 
 def gpo_flags_string(value):
@@ -129,15 +144,6 @@ def dc_url(lp, creds, url=None, dc=None):
     return url
 
 
-def get_gpo_dn(samdb, gpo):
-    '''Construct the DN for gpo'''
-
-    dn = samdb.get_default_basedn()
-    dn.add_child(ldb.Dn(samdb, "CN=Policies,CN=System"))
-    dn.add_child(ldb.Dn(samdb, "CN=%s" % gpo))
-    return dn
-
-
 def get_gpo_info(samdb, gpo=None, displayname=None, dn=None,
                  sd_flags=(security.SECINFO_OWNER |
                            security.SECINFO_GROUP |
@@ -374,31 +380,6 @@ def copy_directory_local_to_remote(conn, localdir, remotedir,
                 conn.savefile(r_name, data)
 
 
-def create_directory_hier(conn, remotedir):
-    elems = remotedir.replace('/', '\\').split('\\')
-    path = ""
-    for e in elems:
-        path = path + '\\' + e
-        if not conn.chkpath(path):
-            conn.mkdir(path)
-
-def smb_connection(dc_hostname, service, lp, creds):
-    # SMB connect to DC
-    # Force signing for the smb connection
-    saved_signing_state = creds.get_smb_signing()
-    creds.set_smb_signing(SMB_SIGNING_REQUIRED)
-    try:
-        # the SMB bindings rely on having a s3 loadparm
-        s3_lp = s3param.get_context()
-        s3_lp.load(lp.configfile)
-        conn = libsmb.Conn(dc_hostname, service, lp=s3_lp, creds=creds)
-    except Exception:
-        raise CommandError("Error connecting to '%s' using SMB" % dc_hostname)
-    # Reset signing state
-    creds.set_smb_signing(saved_signing_state)
-    return conn
-
-
 class GPOCommand(Command):
     def construct_tmpdir(self, tmpdir, gpo):
         """Ensure that the temporary directory structure used in fetch,
@@ -621,7 +602,13 @@ class cmd_show(GPOCommand):
         self.lp = sambaopts.get_loadparm()
         self.creds = credopts.get_credentials(self.lp, fallback_machine=True)
 
-        self.url = dc_url(self.lp, self.creds, H)
+        # 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)
 
         self.samdb_connect()
 
@@ -640,13 +627,254 @@ class cmd_show(GPOCommand):
         self.outf.write("GPO          : %s\n" % msg['name'][0])
         self.outf.write("display name : %s\n" % msg['displayName'][0])
         self.outf.write("path         : %s\n" % msg['gPCFileSysPath'][0])
+        if 'gPCMachineExtensionNames' in msg:
+            self.outf.write("Machine Exts : %s\n" % msg['gPCMachineExtensionNames'][0])
+        if 'gPCUserExtensionNames' in msg:
+            self.outf.write("User Exts    : %s\n" % msg['gPCUserExtensionNames'][0])
         self.outf.write("dn           : %s\n" % msg.dn)
         self.outf.write("version      : %s\n" % attr_default(msg, 'versionNumber', '0'))
         self.outf.write("flags        : %s\n" % gpo_flags_string(int(attr_default(msg, 'flags', 0))))
         self.outf.write("ACL          : %s\n" % secdesc_sddl)
+
+        # SMB connect to DC
+        conn = smb_connection(dc_hostname,
+                              'sysvol',
+                              lp=self.lp,
+                              creds=self.creds)
+
+        realm = self.lp.get('realm')
+        pol_file = '\\'.join([realm.lower(), 'Policies', gpo,
+                                '%s\\Registry.pol'])
+        policy_defs = []
+        for policy_class in ['MACHINE', 'USER']:
+            try:
+                pol_data = ndr_unpack(preg.file,
+                                      conn.loadfile(pol_file % policy_class))
+            except NTSTATUSError as e:
+                if e.args[0] in [NT_STATUS_OBJECT_NAME_INVALID,
+                                 NT_STATUS_OBJECT_NAME_NOT_FOUND,
+                                 NT_STATUS_OBJECT_PATH_NOT_FOUND]:
+                    continue # The file doesn't exist, so there is nothing to list
+                if e.args[0] == NT_STATUS_ACCESS_DENIED:
+                    raise CommandError("The authenticated user does "
+                                       "not have sufficient privileges")
+                raise
+
+            for entry in pol_data.entries:
+                if entry.valuename == "**delvals.":
+                    continue
+                defs = {}
+                defs['keyname'] = entry.keyname
+                defs['valuename'] = entry.valuename
+                defs['class'] = policy_class
+                defs['type'] = str_regtype(entry.type)
+                defs['data'] = entry.data
+                # Bytes aren't JSON serializable
+                if type(defs['data']) == bytes:
+                    if entry.type == REG_MULTI_SZ:
+                        data = defs['data'].decode('utf-16-le')
+                        defs['data'] = data.rstrip('\x00').split('\x00')
+                    else:
+                        defs['data'] = list(defs['data'])
+                policy_defs.append(defs)
+        self.outf.write("Policies     :\n")
+        json.dump(policy_defs, self.outf, indent=4)
         self.outf.write("\n")
 
 
+class cmd_load(GPOCommand):
+    """Load policies onto a GPO.
+
+    Reads json from standard input until EOF, unless a json formatted
+    file is provided via --content.
+
+    Example json_input:
+    [
+        {
+            "keyname": "Software\\Policies\\Mozilla\\Firefox\\Homepage",
+            "valuename": "StartPage",
+            "class": "USER",
+            "type": "REG_SZ",
+            "data": "homepage"
+        },
+        {
+            "keyname": "Software\\Policies\\Mozilla\\Firefox\\Homepage",
+            "valuename": "URL",
+            "class": "USER",
+            "type": "REG_SZ",
+            "data": "google.com"
+        },
+        {
+            "keyname": "Software\\Microsoft\\Internet Explorer\\Toolbar",
+            "valuename": "IEToolbar",
+            "class": "USER",
+            "type": "REG_BINARY",
+            "data": [0]
+        },
+        {
+            "keyname": "Software\\Policies\\Microsoft\\InputPersonalization",
+            "valuename": "RestrictImplicitTextCollection",
+            "class": "USER",
+            "type": "REG_DWORD",
+            "data": 1
+        }
+    ]
+
+    Valid class attributes: MACHINE|USER|BOTH
+    Data arrays are interpreted as bytes.
+
+    The --machine-ext-name and --user-ext-name options are multi-value inputs
+    which respectively set the gPCMachineExtensionNames and gPCUserExtensionNames
+    ldap attributes on the GPO. These attributes must be set to the correct GUID
+    names for Windows Group Policy to work correctly. These GUIDs represent
+    the client side extensions to apply on the machine. Linux Group Policy does
+    not enforce this constraint.
+    {35378EAC-683F-11D2-A89A-00C04FBBCFA2} is provided by default, which
+    enables most Registry policies.
+    """
+
+    synopsis = "%prog <gpo> [options]"
+
+    takes_optiongroups = {
+        "sambaopts": options.SambaOptions,
+        "versionopts": options.VersionOptions,
+        "credopts": options.CredentialsOptions,
+    }
+
+    takes_args = ['gpo']
+
+    takes_options = [
+        Option("-H", help="LDB URL for database or target server", type=str),
+        Option("--content", help="JSON file of policy inputs", type=str),
+        Option("--machine-ext-name",
+            action="append", dest="machine_exts",
+            default=['{35378EAC-683F-11D2-A89A-00C04FBBCFA2}'],
+            help="A machine extension name to add to gPCMachineExtensionNames"),
+        Option("--user-ext-name",
+            action="append", dest="user_exts",
+            default=['{35378EAC-683F-11D2-A89A-00C04FBBCFA2}'],
+            help="A user extension name to add to gPCUserExtensionNames"),
+        Option("--replace", action='store_true', default=False,
+               help="Replace the existing Group Policies, rather than merging")
+    ]
+
+    def run(self, gpo, H=None, content=None,
+            machine_exts=['{35378EAC-683F-11D2-A89A-00C04FBBCFA2}'],
+            user_exts=['{35378EAC-683F-11D2-A89A-00C04FBBCFA2}'],
+            replace=False, sambaopts=None, credopts=None, versionopts=None):
+        if content is None:
+            policy_defs = json.loads(sys.stdin.read())
+        elif os.path.exists(content):
+            with open(content, 'rb') as r:
+                policy_defs = json.load(r)
+        else:
+            raise CommandError("The JSON content file does not exist")
+
+        self.lp = sambaopts.get_loadparm()
+        self.creds = credopts.get_credentials(self.lp, fallback_machine=True)
+        self.url = dc_url(self.lp, self.creds, H)
+        self.samdb_connect()
+        reg = RegistryGroupPolicies(gpo, self.lp, self.creds, self.samdb, H)
+        for ext_name in machine_exts:
+            reg.register_extension_name(ext_name, 'gPCMachineExtensionNames')
+        for ext_name in user_exts:
+            reg.register_extension_name(ext_name, 'gPCUserExtensionNames')
+        try:
+            if replace:
+                reg.replace_s(policy_defs)
+            else:
+                reg.merge_s(policy_defs)
+        except NTSTATUSError as e:
+            if e.args[0] == NT_STATUS_ACCESS_DENIED:
+                raise CommandError("The authenticated user does "
+                                   "not have sufficient privileges")
+            else:
+                raise
+
+
+class cmd_remove(GPOCommand):
+    """Remove policies from a GPO.
+
+    Reads json from standard input until EOF, unless a json formatted
+    file is provided via --content.
+
+    Example json_input:
+    [
+        {
+            "keyname": "Software\\Policies\\Mozilla\\Firefox\\Homepage",
+            "valuename": "StartPage",
+            "class": "USER",
+        },
+        {
+            "keyname": "Software\\Policies\\Mozilla\\Firefox\\Homepage",
+            "valuename": "URL",
+            "class": "USER",
+        },
+        {
+            "keyname": "Software\\Microsoft\\Internet Explorer\\Toolbar",
+            "valuename": "IEToolbar",
+            "class": "USER"
+        },
+        {
+            "keyname": "Software\\Policies\\Microsoft\\InputPersonalization",
+            "valuename": "RestrictImplicitTextCollection",
+            "class": "USER"
+        }
+    ]
+
+    Valid class attributes: MACHINE|USER|BOTH
+    """
+
+    synopsis = "%prog <gpo> [options]"
+
+    takes_optiongroups = {
+        "sambaopts": options.SambaOptions,
+        "versionopts": options.VersionOptions,
+        "credopts": options.CredentialsOptions,
+    }
+
+    takes_args = ['gpo']
+
+    takes_options = [
+        Option("-H", help="LDB URL for database or target server", type=str),
+        Option("--content", help="JSON file of policy inputs", type=str),
+        Option("--machine-ext-name",
+            action="append", default=[], dest="machine_exts",
+            help="A machine extension name to remove from gPCMachineExtensionNames"),
+        Option("--user-ext-name",
+            action="append", default=[], dest="user_exts",
+            help="A user extension name to remove from gPCUserExtensionNames")
+    ]
+
+    def run(self, gpo, H=None, content=None, machine_exts=[], user_exts=[],
+            sambaopts=None, credopts=None, versionopts=None):
+        if content is None:
+            policy_defs = json.loads(sys.stdin.read())
+        elif os.path.exists(content):
+            with open(content, 'rb') as r:
+                policy_defs = json.load(r)
+        else:
+            raise CommandError("The JSON content file does not exist")
+
+        self.lp = sambaopts.get_loadparm()
+        self.creds = credopts.get_credentials(self.lp, fallback_machine=True)
+        self.url = dc_url(self.lp, self.creds, H)
+        self.samdb_connect()
+        reg = RegistryGroupPolicies(gpo, self.lp, self.creds, self.samdb, H)
+        for ext_name in machine_exts:
+            reg.unregister_extension_name(ext_name, 'gPCMachineExtensionNames')
+        for ext_name in user_exts:
+            reg.unregister_extension_name(ext_name, 'gPCUserExtensionNames')
+        try:
+            reg.remove_s(policy_defs)
+        except NTSTATUSError as e:
+            if e.args[0] == NT_STATUS_ACCESS_DENIED:
+                raise CommandError("The authenticated user does "
+                                   "not have sufficient privileges")
+            else:
+                raise
+
+
 class cmd_getlink(GPOCommand):
     """List GPO Links for a container."""
 
@@ -1645,10 +1873,10 @@ class cmd_admxload(Command):
         try:
             conn.mkdir(smb_dir)
         except NTSTATUSError as e:
-            if e.args[0] == 0xC0000022: # STATUS_ACCESS_DENIED
+            if e.args[0] == NT_STATUS_ACCESS_DENIED:
                 raise CommandError("The authenticated user does "
                                    "not have sufficient privileges")
-            elif e.args[0] != 0xC0000035: # STATUS_OBJECT_NAME_COLLISION
+            elif e.args[0] != NT_STATUS_OBJECT_NAME_COLLISION:
                 raise
 
         for dirname, dirs, files in os.walk(admx_dir):
@@ -1660,16 +1888,16 @@ class cmd_admxload(Command):
                 try:
                     create_directory_hier(conn, sub_dir)
                 except NTSTATUSError as e:
-                    if e.args[0] == 0xC0000022: # STATUS_ACCESS_DENIED
+                    if e.args[0] == NT_STATUS_ACCESS_DENIED:
                         raise CommandError("The authenticated user does "
                                            "not have sufficient privileges")
-                    elif e.args[0] != 0xC0000035: # STATUS_OBJECT_NAME_COLLISION
+                    elif e.args[0] != NT_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
+                        if e.args[0] == NT_STATUS_ACCESS_DENIED:
                             raise CommandError("The authenticated user does "
                                                "not have sufficient privileges")
         self.outf.write('Installing ADMX templates to the Central Store '
@@ -1745,9 +1973,9 @@ fakeu,fakeg% ALL=(ALL) NOPASSWD: ALL
             policysetting = xml_data.getroot().find('policysetting')
             data = policysetting.find('data')
         except NTSTATUSError as e:
-            # STATUS_OBJECT_NAME_INVALID, STATUS_OBJECT_NAME_NOT_FOUND,
-            # STATUS_OBJECT_PATH_NOT_FOUND
-            if e.args[0] in [0xC0000033, 0xC0000034, 0xC000003A]:
+            if e.args[0] in [NT_STATUS_OBJECT_NAME_INVALID,
+                             NT_STATUS_OBJECT_NAME_NOT_FOUND,
+                             NT_STATUS_OBJECT_PATH_NOT_FOUND]:
                 # The file doesn't exist, so create the xml structure
                 xml_data = ET.ElementTree(ET.Element('vgppolicy'))
                 policysetting = ET.SubElement(xml_data.getroot(),
@@ -1763,7 +1991,7 @@ fakeu,fakeg% ALL=(ALL) NOPASSWD: ALL
                 data = ET.SubElement(policysetting, 'data')
                 load_plugin = ET.SubElement(data, 'load_plugin')
                 load_plugin.text = 'true'
-            elif e.args[0] == 0xC0000022: # STATUS_ACCESS_DENIED
+            elif e.args[0] == NT_STATUS_ACCESS_DENIED:
                 raise CommandError("The authenticated user does "
                                    "not have sufficient privileges")
             else:
@@ -1794,7 +2022,7 @@ fakeu,fakeg% ALL=(ALL) NOPASSWD: ALL
             create_directory_hier(conn, vgp_dir)
             conn.savefile(vgp_xml, out.read())
         except NTSTATUSError as e:
-            if e.args[0] == 0xC0000022: # STATUS_ACCESS_DENIED
+            if e.args[0] == NT_STATUS_ACCESS_DENIED:
                 raise CommandError("The authenticated user does "
                                    "not have sufficient privileges")
             raise
@@ -1848,12 +2076,12 @@ samba-tool gpo manage sudoers list {31B2F340-016D-11D2-945F-00C04FB984F9}
         try:
             xml_data = ET.fromstring(conn.loadfile(vgp_xml))
         except NTSTATUSError as e:
-            # STATUS_OBJECT_NAME_INVALID, STATUS_OBJECT_NAME_NOT_FOUND,
-            # STATUS_OBJECT_PATH_NOT_FOUND
-            if e.args[0] in [0xC0000033, 0xC0000034, 0xC000003A]:


-- 
Samba Shared Repository



More information about the samba-cvs mailing list