The branch, master has been updated via d4b72821dc3 selftest: add tests for samba-tool ntacl changedomsid via 6554cfa87e0 samba-tool: add ntacl changedomsid command via 0eee621cf17 samba-tool ntacl: consolidate code for getting the local domain sid via 670a12df52d python/ntacls: use correct "state directory" smb.conf option instead of "state dir" via 1b0184a9562 selftest: add test for samba-tool ntacl get/set --use-ntvfs --xattr-backend=tdb from 80f648b1695 smbd: Deprecate "blocking locks" parameter
https://git.samba.org/?p=samba.git;a=shortlog;h=master - Log ----------------------------------------------------------------- commit d4b72821dc3484d29f459c954061e737cb1f5b5e Author: Björn Baumbach <b...@sernet.de> Date: Wed Jun 12 21:02:43 2019 +0200 selftest: add tests for samba-tool ntacl changedomsid Signed-off-by: Björn Baumbach <b...@samba.org> Reviewed-by: Stefan Metzmacher <me...@samba.org> Autobuild-User(master): Björn Baumbach <b...@sernet.de> Autobuild-Date(master): Tue Jun 18 16:54:22 UTC 2019 on sn-devel-184 commit 6554cfa87e01bc606cb6ff9566e7e96808d02e91 Author: Björn Baumbach <b...@sernet.de> Date: Tue Jun 11 15:11:20 2019 +0200 samba-tool: add ntacl changedomsid command This tool is meant to locally change all entries in acl_xattr when the machine's SID has accidentially changed or the data set has been copied to another box either via backup/restore or rsync. Signed-off-by: Björn Baumbach <b...@samba.org> Reviewed-by: Stefan Metzmacher <me...@samba.org> commit 0eee621cf1781e9c5ec68fd1a7c7cf5eab4e74b6 Author: Björn Baumbach <b...@sernet.de> Date: Mon Jun 17 14:20:56 2019 +0200 samba-tool ntacl: consolidate code for getting the local domain sid Signed-off-by: Björn Baumbach <b...@samba.org> Reviewed-by: Stefan Metzmacher <me...@samba.org> commit 670a12df52df63a067b638d37bec71341bf18bdd Author: Björn Baumbach <b...@sernet.de> Date: Wed Jun 12 21:16:25 2019 +0200 python/ntacls: use correct "state directory" smb.conf option instead of "state dir" samba-tool ntacl get testfile --xattr-backend=tdb --use-ntvfs Fixes: Unknown parameter encountered: "state dir" Signed-off-by: Björn Baumbach <b...@samba.org> Reviewed-by: Stefan Metzmacher <me...@samba.org> commit 1b0184a9562689a658e75a0cfc69bdd23277cff6 Author: Björn Baumbach <b...@sernet.de> Date: Wed Jun 12 21:00:01 2019 +0200 selftest: add test for samba-tool ntacl get/set --use-ntvfs --xattr-backend=tdb Signed-off-by: Björn Baumbach <b...@samba.org> Reviewed-by: Stefan Metzmacher <me...@samba.org> ----------------------------------------------------------------------- Summary of changes: python/samba/netcmd/ntacl.py | 249 ++++++++++++++++++++++------ python/samba/ntacls.py | 4 +- python/samba/tests/samba_tool/ntacl.py | 87 ++++++++++ source4/selftest/tests.py | 2 +- testprogs/blackbox/test_samba-tool_ntacl.sh | 66 ++++++++ 5 files changed, 353 insertions(+), 55 deletions(-) Changeset truncated at 500 lines: diff --git a/python/samba/netcmd/ntacl.py b/python/samba/netcmd/ntacl.py index b5dbc1fcf54..4cc7737ae77 100644 --- a/python/samba/netcmd/ntacl.py +++ b/python/samba/netcmd/ntacl.py @@ -25,6 +25,7 @@ from samba.ndr import ndr_unpack, ndr_print from samba.samdb import SamDB from samba.samba3 import param as s3param, passdb, smbd from samba import provision +import os from samba.auth import ( system_session, @@ -46,6 +47,36 @@ def system_session_unix(): return session_info_unix +def get_local_domain_sid(lp): + is_ad_dc = False + server_role = lp.server_role() + if server_role == "ROLE_ACTIVE_DIRECTORY_DC": + is_ad_dc = True + + s3conf = s3param.get_context() + s3conf.load(lp.configfile) + + if is_ad_dc: + try: + samdb = SamDB(session_info=system_session(), + lp=lp) + except Exception as e: + raise CommandError("Unable to open samdb:", e) + # ensure we are using the right samba_dsdb passdb backend, no + # matter what + s3conf.set("passdb backend", "samba_dsdb:%s" % samdb.url) + + try: + if is_ad_dc: + domain_sid = security.dom_sid(samdb.domain_sid) + else: + domain_sid = passdb.get_domain_sid() + except: + raise CommandError("Unable to read domain SID from configuration " + "files") + return domain_sid + + class cmd_ntacl_set(Command): """Set ACLs on a file.""" @@ -75,39 +106,13 @@ class cmd_ntacl_set(Command): service=None): logger = self.get_logger() lp = sambaopts.get_loadparm() - - is_ad_dc = False - server_role = lp.server_role() - if server_role == "ROLE_ACTIVE_DIRECTORY_DC": - is_ad_dc = True + domain_sid = get_local_domain_sid(lp) if not use_ntvfs and not use_s3fs: use_ntvfs = "smb" in lp.get("server services") elif use_s3fs: use_ntvfs = False - s3conf = s3param.get_context() - s3conf.load(lp.configfile) - - if is_ad_dc: - try: - samdb = SamDB(session_info=system_session(), - lp=lp) - except Exception as e: - raise CommandError("Unable to open samdb:", e) - # ensure we are using the right samba_dsdb passdb backend, no - # matter what - s3conf.set("passdb backend", "samba_dsdb:%s" % samdb.url) - - try: - if is_ad_dc: - domain_sid = security.dom_sid(samdb.domain_sid) - else: - domain_sid = passdb.get_domain_sid() - except: - raise CommandError("Unable to read domain SID from configuration " - "files") - setntacl(lp, file, acl, @@ -171,30 +176,13 @@ class cmd_ntacl_get(Command): credopts=None, sambaopts=None, versionopts=None, service=None): lp = sambaopts.get_loadparm() - - is_ad_dc = False - server_role = lp.server_role() - if server_role == "ROLE_ACTIVE_DIRECTORY_DC": - is_ad_dc = True + domain_sid = get_local_domain_sid(lp) if not use_ntvfs and not use_s3fs: use_ntvfs = "smb" in lp.get("server services") elif use_s3fs: use_ntvfs = False - s3conf = s3param.get_context() - s3conf.load(lp.configfile) - if is_ad_dc: - try: - samdb = SamDB(session_info=system_session(), - lp=lp) - except Exception as e: - raise CommandError("Unable to open samdb:", e) - - # ensure we are using the right samba_dsdb passdb backend, no - # matter what - s3conf.set("passdb backend", "samba_dsdb:%s" % samdb.url) - acl = getntacl(lp, file, xattr_backend, @@ -203,19 +191,173 @@ class cmd_ntacl_get(Command): service=service, session_info=system_session_unix()) if as_sddl: - try: - if is_ad_dc: - domain_sid = security.dom_sid(samdb.domain_sid) - else: - domain_sid = passdb.get_domain_sid() - except: - raise CommandError("Unable to read domain SID from " - "configuration files") self.outf.write(acl.as_sddl(domain_sid) + "\n") else: self.outf.write(ndr_print(acl)) +class cmd_ntacl_changedomsid(Command): + """Change the domain SID for ACLs""" + synopsis = "%prog <Orig-Domain-SID> <New-Domain-SID> <file> [options]" + + takes_optiongroups = { + "sambaopts": options.SambaOptions, + } + + takes_options = [ + Option( + "--service", + help="Name of the smb.conf service to use", + type="string"), + Option( + "--use-ntvfs", + help=("Set the ACLs directly to the TDB or xattr for use with the " + "ntvfs file server"), + action="store_true"), + Option( + "--use-s3fs", + help=("Set the ACLs for use with the default s3fs file server via " + "the VFS layer"), + action="store_true"), + Option( + "--eadb-file", + help="Name of the tdb file where attributes are stored", + type="string"), + Option( + "--xattr-backend", + type="choice", + help="xattr backend type (native fs or tdb)", + choices=["native", "tdb"]), + Option( + "-r", + "--recursive", + help="Set the ACLs for directories and their contents recursively", + action="store_true"), + Option( + "--follow-symlinks", + help="Follow symlinks", + action="store_true"), + Option( + "-v", + "--verbose", + help="Be verbose", + action="store_true"), + ] + + takes_args = ["old_domain_sid", "new_domain_sid", "file"] + + def run(self, + old_domain_sid_str, + new_domain_sid_str, + file, + use_ntvfs=False, + use_s3fs=False, + service=None, + xattr_backend=None, + eadb_file=None, + sambaopts=None, + recursive=False, + follow_symlinks=False, + verbose=False): + logger = self.get_logger() + lp = sambaopts.get_loadparm() + domain_sid = get_local_domain_sid(lp) + + if not use_ntvfs and not use_s3fs: + use_ntvfs = "smb" in lp.get("server services") + elif use_s3fs: + use_ntvfs = False + + if not use_ntvfs and not service: + raise CommandError( + "Must provide a share name with --service=<share>") + + try: + old_domain_sid = security.dom_sid(old_domain_sid_str) + except Exception as e: + raise CommandError("Could not parse old sid %s: %s" % + (old_domain_sid_str, e)) + + try: + new_domain_sid = security.dom_sid(new_domain_sid_str) + except Exception as e: + raise CommandError("Could not parse old sid %s: %s" % + (new_domain_sid_str, e)) + + def changedom_sids(file): + if verbose: + self.outf.write("file: %s\n" % file) + + try: + acl = getntacl(lp, + file, + xattr_backend, + eadb_file, + direct_db_access=use_ntvfs, + service=service, + session_info=system_session_unix()) + except Exception as e: + raise CommandError("Could not get acl for %s: %s" % (file, e)) + + orig_sddl = acl.as_sddl(domain_sid) + if verbose: + self.outf.write("before:\n%s\n" % orig_sddl) + + def replace_domain_sid(sid): + (dom, rid) = sid.split() + if dom == old_domain_sid: + return security.dom_sid("%s-%i" % (new_domain_sid, rid)) + return sid + + acl.owner_sid = replace_domain_sid(acl.owner_sid) + acl.group_sid = replace_domain_sid(acl.group_sid) + + if acl.sacl: + for ace in acl.sacl.aces: + ace.trustee = replace_domain_sid(ace.trustee) + if acl.dacl: + for ace in acl.dacl.aces: + ace.trustee = replace_domain_sid(ace.trustee) + + new_sddl = acl.as_sddl(domain_sid) + if verbose: + self.outf.write("after:\n%s\n" % new_sddl) + + if orig_sddl == new_sddl: + if verbose: + self.outf.write("nothing to do\n") + return True + + try: + setntacl(lp, + file, + acl, + new_domain_sid, + xattr_backend, + eadb_file, + use_ntvfs=use_ntvfs, + service=service, + session_info=system_session_unix()) + except Exception as e: + raise CommandError("Could not set acl for %s: %s" % (file, e)) + + def recursive_changedom_sids(file): + for root, dirs, files in os.walk(file, followlinks=follow_symlinks): + for f in files: + changedom_sids(os.path.join(root, f)) + + for d in dirs: + changedom_sids(os.path.join(root, d)) + + changedom_sids(file) + if recursive and os.path.isdir(file): + recursive_changedom_sids(file) + + if use_ntvfs: + logger.warning("Please note that POSIX permissions have NOT been " + "changed, only the stored NT ACL.") + + class cmd_ntacl_sysvolreset(Command): """Reset sysvol ACLs to defaults (including correct ACLs on GPOs).""" synopsis = "%prog <file> [options]" @@ -320,6 +462,7 @@ class cmd_ntacl(SuperCommand): subcommands = {} subcommands["set"] = cmd_ntacl_set() subcommands["get"] = cmd_ntacl_get() + subcommands["changedomsid"] = cmd_ntacl_changedomsid() subcommands["sysvolreset"] = cmd_ntacl_sysvolreset() subcommands["sysvolcheck"] = cmd_ntacl_sysvolcheck() subcommands["getdosinfo"] = cmd_dosinfo_get() diff --git a/python/samba/ntacls.py b/python/samba/ntacls.py index 82d950fbbc9..cc40b32a538 100644 --- a/python/samba/ntacls.py +++ b/python/samba/ntacls.py @@ -77,7 +77,9 @@ def checkset_backend(lp, backend, eadbfile): if eadbfile is not None: return (samba.xattr_tdb, eadbfile) else: - return (samba.xattr_tdb, os.path.abspath(os.path.join(lp.get("state dir"), "xattr.tdb"))) + state_dir = lp.get("state directory") + db_path = os.path.abspath(os.path.join(state_dir, "xattr.tdb")) + return (samba.xattr_tdb, db_path) else: raise XattrBackendError("Invalid xattr backend choice %s" % backend) diff --git a/python/samba/tests/samba_tool/ntacl.py b/python/samba/tests/samba_tool/ntacl.py index e8fee852651..ee166764b6a 100644 --- a/python/samba/tests/samba_tool/ntacl.py +++ b/python/samba/tests/samba_tool/ntacl.py @@ -133,3 +133,90 @@ class NtACLCmdGetSetTestCase(SambaToolCmdTest): self.assertCmdSuccess(result, out, err) self.assertEquals(err, "", "Shouldn't be any error messages") self.assertEquals(self.acl + "\n", out, "Output should be the ACL") + +class NtACLCmdChangedomsidTestCase(SambaToolCmdTest): + """Tests for samba-tool ntacl changedomsid subcommand""" + + acl = "O:DAG:DUD:P(A;OICI;0x001f01ff;;;DA)(A;OICI;0x001f01ff;;;EA)(A;OICIIO;0x001f01ff;;;CO)(A;OICI;0x001f01ff;;;DA)(A;OICI;0x001f01ff;;;SY)(A;OICI;0x001200a9;;;AU)(A;OICI;0x001200a9;;;ED)S:AI(OU;CIIDSA;WP;f30e3bbe-9ff0-11d1-b603-0000f80367c1;bf967aa5-0de6-11d0-a285-00aa003049e2;WD)(OU;CIIDSA;WP;f30e3bbf-9ff0-11d1-b603-0000f80367c1;bf967aa5-0de6-11d0-a285-00aa003049e2;WD)" + new_acl="O:S-1-5-21-2212615479-2695158682-2101375468-512G:S-1-5-21-2212615479-2695158682-2101375468-513D:P(A;OICI;0x001f01ff;;;S-1-5-21-2212615479-2695158682-2101375468-512)(A;OICI;0x001f01ff;;;S-1-5-21-2212615479-2695158682-2101375468-519)(A;OICIIO;0x001f01ff;;;CO)(A;OICI;0x001f01ff;;;S-1-5-21-2212615479-2695158682-2101375468-512)(A;OICI;0x001f01ff;;;SY)(A;OICI;0x001200a9;;;AU)(A;OICI;0x001200a9;;;ED)S:AI(OU;CIIDSA;WP;f30e3bbe-9ff0-11d1-b603-0000f80367c1;bf967aa5-0de6-11d0-a285-00aa003049e2;WD)(OU;CIIDSA;WP;f30e3bbf-9ff0-11d1-b603-0000f80367c1;bf967aa5-0de6-11d0-a285-00aa003049e2;WD)" + domain_sid=os.environ['DOMSID'] + new_domain_sid="S-1-5-21-2212615479-2695158682-2101375468" + + def test_ntvfs_check(self): + path = os.environ['SELFTEST_PREFIX'] + tempf = os.path.join( + path, "pytests" + str(int(100000 * random.random()))) + open(tempf, 'w').write("empty") + + print("DOMSID: %s", self.domain_sid) + + (result, out, err) = self.runsubcmd("ntacl", + "set", + self.acl, + tempf, + "--use-ntvfs") + self.assertCmdSuccess(result, out, err) + self.assertEquals(out, "", "Shouldn't be any output messages") + self.assertIn("Please note that POSIX permissions have NOT been " + "changed, only the stored NT ACL", err) + + (result, out, err) = self.runsubcmd("ntacl", + "changedomsid", + self.domain_sid, + self.new_domain_sid, + tempf, + "--use-ntvfs") + self.assertCmdSuccess(result, out, err) + self.assertEquals(out, "", "Shouldn't be any output messages") + self.assertIn("Please note that POSIX permissions have NOT been " + "changed, only the stored NT ACL.", err) + + # Now check they were set correctly + (result, out, err) = self.runsubcmd("ntacl", + "get", + tempf, + "--use-ntvfs", + "--as-sddl") + self.assertCmdSuccess(result, out, err) + self.assertEquals(err, "", "Shouldn't be any error messages") + self.assertEquals(self.new_acl + "\n", out, "Output should be the ACL") + + def test_s3fs_check(self): + path = os.environ['SELFTEST_PREFIX'] + tempf = os.path.join( + path, "pytests" + str(int(100000 * random.random()))) + open(tempf, 'w').write("empty") + + print("DOMSID: %s" % self.domain_sid) + + (result, out, err) = self.runsubcmd("ntacl", + "set", + self.acl, + tempf, + "--use-s3fs", + "--service=sysvol") + self.assertCmdSuccess(result, out, err) + self.assertEquals(out, "", "Shouldn't be any output messages") + self.assertEquals(err, "", "Shouldn't be any error messages") + + (result, out, err) = self.runsubcmd("ntacl", + "changedomsid", + self.domain_sid, + self.new_domain_sid, + tempf, + "--use-s3fs", + "--service=sysvol") + self.assertCmdSuccess(result, out, err) + self.assertEquals(out, "", "Shouldn't be any output messages") + self.assertEquals(err, "", "Shouldn't be any error messages") + + # Now check they were set correctly + (result, out, err) = self.runsubcmd("ntacl", + "get", + tempf, + "--use-s3fs", + "--as-sddl", + "--service=sysvol") + self.assertCmdSuccess(result, out, err) + self.assertEquals(err, "", "Shouldn't be any error messages") + self.assertEquals(self.new_acl + "\n", out, "Output should be the ACL") diff --git a/source4/selftest/tests.py b/source4/selftest/tests.py index 156bd200372..0e2138a007c 100755 --- a/source4/selftest/tests.py +++ b/source4/selftest/tests.py @@ -488,7 +488,7 @@ plantestsuite("samba4.blackbox.client_etypes_all(ad_dc:client)", "ad_dc:client", plantestsuite("samba4.blackbox.client_etypes_legacy(ad_dc:client)", "ad_dc:client", [os.path.join(bbdir, "test_client_etypes.sh"), '$DC_SERVER', '$DC_USERNAME', '$DC_PASSWORD', '$PREFIX_ABS', 'legacy', '23']) plantestsuite("samba4.blackbox.client_etypes_strong(ad_dc:client)", "ad_dc:client", [os.path.join(bbdir, "test_client_etypes.sh"), '$DC_SERVER', '$DC_USERNAME', '$DC_PASSWORD', '$PREFIX_ABS', 'strong', '17_18']) plantestsuite("samba4.blackbox.net_ads_dns(ad_member:local)", "ad_member:local", [os.path.join(bbdir, "test_net_ads_dns.sh"), '$DC_SERVER', '$DC_USERNAME', '$DC_PASSWORD', '$REALM', '$USERNAME', '$PASSWORD']) -plantestsuite("samba4.blackbox.samba-tool_ntacl(ad_member:local)", "ad_member:local", [os.path.join(bbdir, "test_samba-tool_ntacl.sh"), '$PREFIX']) +plantestsuite("samba4.blackbox.samba-tool_ntacl(ad_member:local)", "ad_member:local", [os.path.join(bbdir, "test_samba-tool_ntacl.sh"), '$PREFIX', '$DOMSID']) plantestsuite_loadlist("samba4.rpc.echo against NetBIOS alias", "ad_dc_ntvfs", [valgrindify(smbtorture4), "$LISTOPT", "$LOADLIST", 'ncacn_np:$NETBIOSALIAS', '-U$DOMAIN/$USERNAME%$PASSWORD', 'rpc.echo']) # json tests hook into ``chgdcpass'' to make them run in contributor CI on # gitlab diff --git a/testprogs/blackbox/test_samba-tool_ntacl.sh b/testprogs/blackbox/test_samba-tool_ntacl.sh index b00d4f29ac2..6991165cc63 100755 --- a/testprogs/blackbox/test_samba-tool_ntacl.sh +++ b/testprogs/blackbox/test_samba-tool_ntacl.sh @@ -10,6 +10,7 @@ exit 1; fi PREFIX=$1 +domain_sid=$2 failed=0 @@ -20,6 +21,8 @@ testfile="$PREFIX/ntacl_testfile" # acl from samba_tool/ntacl.py tests acl="O:DAG:DUD:P(A;OICI;0x001f01ff;;;DA)(A;OICI;0x001f01ff;;;EA)(A;OICIIO;0x001f01ff;;;CO)(A;OICI;0x001f01ff;;;DA)(A;OICI;0x001f01ff;;;SY)(A;OICI;0x001200a9;;;AU)(A;OICI;0x001200a9;;;ED)S:AI(OU;CIIDSA;WP;f30e3bbe-9ff0-11d1-b603-0000f80367c1;bf967aa5-0de6-11d0-a285-00aa003049e2;WD)(OU;CIIDSA;WP;f30e3bbf-9ff0-11d1-b603-0000f80367c1;bf967aa5-0de6-11d0-a285-00aa003049e2;WD)" +new_acl="O:S-1-5-21-2212615479-2695158682-2101375468-512G:S-1-5-21-2212615479-2695158682-2101375468-513D:P(A;OICI;0x001f01ff;;;S-1-5-21-2212615479-2695158682-2101375468-512)(A;OICI;0x001f01ff;;;S-1-5-21-2212615479-2695158682-2101375468-519)(A;OICIIO;0x001f01ff;;;CO)(A;OICI;0x001f01ff;;;S-1-5-21-2212615479-2695158682-2101375468-512)(A;OICI;0x001f01ff;;;SY)(A;OICI;0x001200a9;;;AU)(A;OICI;0x001200a9;;;ED)S:AI(OU;CIIDSA;WP;f30e3bbe-9ff0-11d1-b603-0000f80367c1;bf967aa5-0de6-11d0-a285-00aa003049e2;WD)(OU;CIIDSA;WP;f30e3bbf-9ff0-11d1-b603-0000f80367c1;bf967aa5-0de6-11d0-a285-00aa003049e2;WD)" +new_domain_sid="S-1-5-21-2212615479-2695158682-2101375468" . `dirname $0`/subunit.sh @@ -44,6 +47,62 @@ test_set_acl() $PYTHON $samba_tool ntacl set "$acl" "$testfile" } +test_get_acl_ntvfs() +{ + testfile="$1" + exptextedacl="$2" + + retacl=$($PYTHON $samba_tool ntacl get "$testfile" --as-sddl --use-ntvfs --xattr-backend=tdb -s $PREFIX/ad_member/lib/server.conf) || return $? + + test "$retacl" = "$exptextedacl" +} + +test_set_acl_ntvfs() +{ + testfile="$1" + acl="$2" + + $PYTHON $samba_tool ntacl set "$acl" "$testfile" --use-ntvfs --xattr-backend=tdb -s $PREFIX/ad_member/lib/server.conf +} + +test_changedomsid() +{ + testfile="$1" + + $PYTHON $samba_tool ntacl changedomsid \ + "$domain_sid" "$new_domain_sid" "$testfile" \ + --service=tmp \ + -s $PREFIX/ad_member/lib/server.conf + + retacl=$($PYTHON $samba_tool ntacl get \ + "$testfile" \ + --as-sddl \ + --service=tmp \ + -s $PREFIX/ad_member/lib/server.conf) || return $? + + test "$retacl" = "$new_acl" +} + +test_changedomsid_ntvfs() +{ + testfile="$1" + -- Samba Shared Repository