[SCM] Samba Shared Repository - branch v4-8-test updated

Karolin Seeger kseeger at samba.org
Mon Mar 11 13:05:03 UTC 2019


The branch, v4-8-test has been updated
       via  29984beafc9 libcli/security: fix handling of deny type ACEs in access_check_max_allowed()
       via  05a54f9c0ef s4:torture: Add test_deny1().
       via  8f77ba1b7c7 s4:torture: Add test_owner_rights_deny1().
       via  ebee56db540 libcli/security: correct access check and maximum access calculation for Owner Rights ACEs
       via  b079f59768d s4:torture: Add test_owner_rights_deny().
       via  72bab8d08b0 s4:torture: Fix the test_owner_rights() test to show permissions are additive.
       via  2fd618413db libcli/security: add "Owner Rights" calculation to access_check_max_allowed()
       via  7ab6b04558c s4:torture: add a Maximum Access check with an Owner Rights ACE
       via  021321f5a89 s4:libcli: remember return code from maximum access
       via  66a0bb5575d sambaundoguididx: use the right escaped oder unescaped sam ldb files
      from  7c476487867 vfs_ceph: remove ceph_fallocate/ceph_ftruncate fallback

https://git.samba.org/?p=samba.git;a=shortlog;h=v4-8-test


- Log -----------------------------------------------------------------
commit 29984beafc91ef6f45884adc3a0bd4617acbc0a0
Author: Ralph Boehme <slow at samba.org>
Date:   Fri Mar 1 18:57:23 2019 +0100

    libcli/security: fix handling of deny type ACEs in access_check_max_allowed()
    
    Deny ACEs must always be evaluated against explicitly granted rights
    from previous ACEs.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=13812
    
    Signed-off-by: Ralph Boehme <slow at samba.org>
    Reviewed-by: Jeremy Allison <jra at samba.org>
    (cherry picked from commit 8d355dd9769e8990ce998b4c9f28977669b43616)
    
    Autobuild-User(v4-8-test): Karolin Seeger <kseeger at samba.org>
    Autobuild-Date(v4-8-test): Mon Mar 11 13:04:13 UTC 2019 on sn-devel-144

commit 05a54f9c0efa7cd1f1e66cec2dc26658d0cce1f2
Author: Ralph Boehme <slow at samba.org>
Date:   Sun Mar 3 08:33:51 2019 +0100

    s4:torture: Add test_deny1().
    
    Creates a 2-element ALLOW + DENY ACE showing that when calculating
    effective permissions and maximum access already seen allow bits are not
    removed.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=13812
    
    Signed-off-by: Ralph Boehme <slow at samba.org>
    Reviewed-by: Jeremy Allison <jra at samba.org>
    (cherry picked from commit b205d695d769e910a91bec87451dec189ec33740)

commit 8f77ba1b7c7620910f9735681f8e357e4ed053e4
Author: Jeremy Allison <jra at samba.org>
Date:   Thu Feb 28 14:59:01 2019 -0800

    s4:torture: Add test_owner_rights_deny1().
    
    Creates a 3-element ALLOW + ALLOW + DENY ACE showing that when
    calculating maximum access already seen allow bits are not removed.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=13812
    
    Signed-off-by: Jeremy Allison <jra at samba.org>
    Reviewed-by: Ralph Boehme <slow at samba.org>
    (cherry picked from commit 0ebd8c99aed28a0ba43a22c429837f66f7e94409)

commit ebee56db540dbc7504bebc96d1b77e1252a536a1
Author: Ralph Boehme <slow at samba.org>
Date:   Fri Mar 1 18:20:35 2019 +0100

    libcli/security: correct access check and maximum access calculation for Owner Rights ACEs
    
    We basically must process the Owner Rights ACEs as any other ACE wrt to the
    order of adding granted permissions and checking denied permissions. According
    to MS-DTYP 2.5.3.2 Owner Rights ACEs must be evaluated in the main loop over
    the ACEs in an ACL and the corresponding access_mask must be directly applied
    to bits_remaining. We currently defer this to after the loop over the ACEs in
    ACL, this is wrong.
    
    We just have to do some initial magic to determine if an ACL contains and
    Owner Rights ACEs, and in case it doesn't we grant SEC_STD_WRITE_DAC |
    SEC_STD_READ_CONTROL at the *beginning*. MS-DTYP:
    
    -- the owner of an object is always granted READ_CONTROL and WRITE_DAC.
    CALL SidInToken(Token, SecurityDescriptor.Owner, PrincipalSelfSubst)
    IF SidInToken returns True THEN
       IF DACL does not contain ACEs from object owner THEN
           Remove READ_CONTROL and WRITE_DAC from RemainingAccess
           Set GrantedAccess to GrantedAccess or READ_CONTROL or WRITE_OWNER
       END IF
    END IF
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=13812
    
    Signed-off-by: Ralph Boehme <slow at samba.org>
    Reviewed-by: Jeremy Allison <jra at samba.org>
    (cherry picked from commit 9722f75757c0e38c7f42c7cc310d56aa6eaf6392)

commit b079f59768dadbca25c74c73dce442dd66171ea1
Author: Jeremy Allison <jra at samba.org>
Date:   Thu Feb 28 14:37:09 2019 -0800

    s4:torture: Add test_owner_rights_deny().
    
    Shows that owner and SID_OWNER_RIGHTS ACE
    entries interact in max permissions requests.
    
    Tested against Windows.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=13812
    
    Signed-off-by: Jeremy Allison <jra at samba.org>
    Reviewed-by: Ralph Boehme <slow at samba.org>
    (cherry picked from commit fadc4c1bc5fcc3b2d9daea44ef8daf8a8ae0fbe2)

commit 72bab8d08b0847dd99e7822099af4075ad23fa87
Author: Jeremy Allison <jra at samba.org>
Date:   Thu Feb 28 13:55:31 2019 -0800

    s4:torture: Fix the test_owner_rights() test to show permissions are additive.
    
    Tested against Windows.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=13812
    
    Signed-off-by: Jeremy Allison <jra at samba.org>
    Reviewed-by: Ralph Boehme <slow at samba.org>
    (cherry picked from commit 2e181e34c48c879235c5dc64bd7ab2b59781810c)

commit 2fd618413dbf3cb47391518b3bee180a2b76aada
Author: Ralph Boehme <slow at samba.org>
Date:   Wed Feb 27 18:07:03 2019 +0100

    libcli/security: add "Owner Rights" calculation to access_check_max_allowed()
    
    This was missing in 44590c1b70c0a24f853c02d5fcdb3c609401e2ca.
    
    Bug: https://bugzilla.samba.org/show_bug.cgi?id=13812
    
    Signed-off-by: Ralph Boehme <slow at samba.org>
    Reviewed-by: David Disseldorp <ddiss at samba.org>
    
    Autobuild-User(master): David Disseldorp <ddiss at samba.org>
    Autobuild-Date(master): Thu Feb 28 19:18:16 UTC 2019 on sn-devel-144
    
    (cherry picked from commit 5cf0764bc4b65dbc59d8626760dbe946a2234833)

commit 7ab6b04558c426f31a110e82b4db449fdb282cc8
Author: Ralph Boehme <slow at samba.org>
Date:   Thu Feb 28 14:48:02 2019 +0100

    s4:torture: add a Maximum Access check with an Owner Rights ACE
    
    Bug: https://bugzilla.samba.org/show_bug.cgi?id=13812
    
    Signed-off-by: Ralph Boehme <slow at samba.org>
    Reviewed-by: David Disseldorp <ddiss at samba.org>
    (cherry picked from commit 3ca38d2cd1189a5040e13ddab016063280be2b4d)

commit 021321f5a89e72027b89a0a47553115ab859aff6
Author: Ralph Boehme <slow at samba.org>
Date:   Thu Feb 28 14:47:18 2019 +0100

    s4:libcli: remember return code from maximum access
    
    Bug: https://bugzilla.samba.org/show_bug.cgi?id=13812
    
    Signed-off-by: Ralph Boehme <slow at samba.org>
    Reviewed-by: David Disseldorp <ddiss at samba.org>
    (cherry picked from commit 9f4ee05295827c9a607e1f63694a17906f777176)

commit 66a0bb5575db194d54a1b88410adf321f5f624b5
Author: Björn Jacke <bj at sernet.de>
Date:   Wed Jan 23 14:01:26 2019 +0100

    sambaundoguididx: use the right escaped oder unescaped sam ldb files
    
    the correct filename is taken from the partition database before, we should not
    unescape that because this can result in a new unescaped ldb file being created
    and the script not to work at all.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=13759
    
    Signed-off-by: Bjoern Jacke <bjacke at samba.org>
    Reviewed-by: Andreas Schneider <asn at samba.org>
    (cherry picked from commit cd1ac3668cd164bd5f7cadf7b59df9541aaef83e)

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

Summary of changes:
 libcli/security/access_check.c         | 127 +++++---
 source4/libcli/raw/interfaces.h        |   1 +
 source4/libcli/smb2/create.c           |   4 +-
 source4/scripting/bin/sambaundoguididx |   3 +-
 source4/torture/smb2/acls.c            | 558 +++++++++++++++++++++++++++++++++
 5 files changed, 640 insertions(+), 53 deletions(-)


Changeset truncated at 500 lines:

diff --git a/libcli/security/access_check.c b/libcli/security/access_check.c
index 03a7dca4adf..322f4fdb0c6 100644
--- a/libcli/security/access_check.c
+++ b/libcli/security/access_check.c
@@ -109,24 +109,61 @@ static uint32_t access_check_max_allowed(const struct security_descriptor *sd,
 					const struct security_token *token)
 {
 	uint32_t denied = 0, granted = 0;
+	bool am_owner = false;
+	bool have_owner_rights_ace = false;
 	unsigned i;
 
+	if (sd->dacl == NULL) {
+		if (security_token_has_sid(token, sd->owner_sid)) {
+			granted |= SEC_STD_WRITE_DAC | SEC_STD_READ_CONTROL;
+		}
+		return granted;
+	}
+
 	if (security_token_has_sid(token, sd->owner_sid)) {
-		granted |= SEC_STD_WRITE_DAC | SEC_STD_READ_CONTROL;
+		/*
+		 * Check for explicit owner rights: if there are none, we remove
+		 * the default owner right SEC_STD_WRITE_DAC|SEC_STD_READ_CONTROL
+		 * from remaining_access. Otherwise we just process the
+		 * explicitly granted rights when processing the ACEs.
+		 */
+		am_owner = true;
+
+		for (i=0; i < sd->dacl->num_aces; i++) {
+			struct security_ace *ace = &sd->dacl->aces[i];
+
+			if (ace->flags & SEC_ACE_FLAG_INHERIT_ONLY) {
+				continue;
+			}
+
+			have_owner_rights_ace = dom_sid_equal(
+				&ace->trustee, &global_sid_Owner_Rights);
+			if (have_owner_rights_ace) {
+				break;
+			}
+		}
 	}
 
-	if (sd->dacl == NULL) {
-		return granted & ~denied;
+	if (am_owner && !have_owner_rights_ace) {
+		granted |= SEC_STD_WRITE_DAC|SEC_STD_READ_CONTROL;
 	}
 
 	for (i = 0;i<sd->dacl->num_aces; i++) {
 		struct security_ace *ace = &sd->dacl->aces[i];
+		bool is_owner_rights_ace = false;
 
 		if (ace->flags & SEC_ACE_FLAG_INHERIT_ONLY) {
 			continue;
 		}
 
-		if (!security_token_has_sid(token, &ace->trustee)) {
+		if (am_owner) {
+			is_owner_rights_ace = dom_sid_equal(
+				&ace->trustee, &global_sid_Owner_Rights);
+		}
+
+		if (!is_owner_rights_ace &&
+		    !security_token_has_sid(token, &ace->trustee))
+		{
 			continue;
 		}
 
@@ -136,7 +173,7 @@ static uint32_t access_check_max_allowed(const struct security_descriptor *sd,
 			break;
 		case SEC_ACE_TYPE_ACCESS_DENIED:
 		case SEC_ACE_TYPE_ACCESS_DENIED_OBJECT:
-			denied |= ace->access_mask;
+			denied |= ~granted & ace->access_mask;
 			break;
 		default:	/* Other ACE types not handled/supported */
 			break;
@@ -159,16 +196,8 @@ NTSTATUS se_access_check(const struct security_descriptor *sd,
 	uint32_t i;
 	uint32_t bits_remaining;
 	uint32_t explicitly_denied_bits = 0;
-	/*
-	 * Up until Windows Server 2008, owner always had these rights. Now
-	 * we have to use Owner Rights perms if they are on the file.
-	 *
-	 * In addition we have to accumulate these bits and apply them
-	 * correctly. See bug #8795
-	 */
-	uint32_t owner_rights_allowed = 0;
-	uint32_t owner_rights_denied = 0;
-	bool owner_rights_default = true;
+	bool am_owner = false;
+	bool have_owner_rights_ace = false;
 
 	*access_granted = access_desired;
 	bits_remaining = access_desired;
@@ -198,35 +227,50 @@ NTSTATUS se_access_check(const struct security_descriptor *sd,
 		goto done;
 	}
 
+	if (security_token_has_sid(token, sd->owner_sid)) {
+		/*
+		 * Check for explicit owner rights: if there are none, we remove
+		 * the default owner right SEC_STD_WRITE_DAC|SEC_STD_READ_CONTROL
+		 * from remaining_access. Otherwise we just process the
+		 * explicitly granted rights when processing the ACEs.
+		 */
+		am_owner = true;
+
+		for (i=0; i < sd->dacl->num_aces; i++) {
+			struct security_ace *ace = &sd->dacl->aces[i];
+
+			if (ace->flags & SEC_ACE_FLAG_INHERIT_ONLY) {
+				continue;
+			}
+
+			have_owner_rights_ace = dom_sid_equal(
+				&ace->trustee, &global_sid_Owner_Rights);
+			if (have_owner_rights_ace) {
+				break;
+			}
+		}
+	}
+	if (am_owner && !have_owner_rights_ace) {
+		bits_remaining &= ~(SEC_STD_WRITE_DAC | SEC_STD_READ_CONTROL);
+	}
+
 	/* check each ace in turn. */
 	for (i=0; bits_remaining && i < sd->dacl->num_aces; i++) {
 		struct security_ace *ace = &sd->dacl->aces[i];
+		bool is_owner_rights_ace = false;
 
 		if (ace->flags & SEC_ACE_FLAG_INHERIT_ONLY) {
 			continue;
 		}
 
-		/*
-		 * We need the Owner Rights permissions to ensure we
-		 * give or deny the correct permissions to the owner. Replace
-		 * owner_rights with the perms here if it is present.
-		 *
-		 * We don't care if we are not the owner because that is taken
-		 * care of below when we check if our token has the owner SID.
-		 *
-		 */
-		if (dom_sid_equal(&ace->trustee, &global_sid_Owner_Rights)) {
-			if (ace->type == SEC_ACE_TYPE_ACCESS_ALLOWED) {
-				owner_rights_allowed |= ace->access_mask;
-				owner_rights_default = false;
-			} else if (ace->type == SEC_ACE_TYPE_ACCESS_DENIED) {
-				owner_rights_denied |= (bits_remaining & ace->access_mask);
-				owner_rights_default = false;
-			}
-			continue;
+		if (am_owner) {
+			is_owner_rights_ace = dom_sid_equal(
+				&ace->trustee, &global_sid_Owner_Rights);
 		}
 
-		if (!security_token_has_sid(token, &ace->trustee)) {
+		if (!is_owner_rights_ace &&
+		    !security_token_has_sid(token, &ace->trustee))
+		{
 			continue;
 		}
 
@@ -246,21 +290,6 @@ NTSTATUS se_access_check(const struct security_descriptor *sd,
 	/* Explicitly denied bits always override */
 	bits_remaining |= explicitly_denied_bits;
 
-	/* The owner always gets owner rights as defined above. */
-	if (security_token_has_sid(token, sd->owner_sid)) {
-		if (owner_rights_default) {
-			/*
-			 * Just remove them, no need to check if they are
-			 * there.
-			 */
-			bits_remaining &= ~(SEC_STD_WRITE_DAC |
-						SEC_STD_READ_CONTROL);
-		} else {
-			bits_remaining &= ~owner_rights_allowed;
-			bits_remaining |= owner_rights_denied;
-		}
-	}
-
 	/*
 	 * We check privileges here because they override even DENY entries.
 	 */
diff --git a/source4/libcli/raw/interfaces.h b/source4/libcli/raw/interfaces.h
index 732ba1512dc..43a53f834df 100644
--- a/source4/libcli/raw/interfaces.h
+++ b/source4/libcli/raw/interfaces.h
@@ -1779,6 +1779,7 @@ union smb_open {
 			/* uint32_t blob_size; */
 
 			/* optional return values matching tagged values in the call */
+			uint32_t maximal_access_status;
 			uint32_t maximal_access;
 			uint8_t on_disk_id[32];
 			struct smb2_lease lease_response;
diff --git a/source4/libcli/smb2/create.c b/source4/libcli/smb2/create.c
index 550069a6cea..eb0f6a421cd 100644
--- a/source4/libcli/smb2/create.c
+++ b/source4/libcli/smb2/create.c
@@ -360,12 +360,12 @@ NTSTATUS smb2_create_recv(struct smb2_request *req, TALLOC_CTX *mem_ctx, struct
 	/* pull out the parsed blobs */
 	for (i=0;i<io->out.blobs.num_blobs;i++) {
 		if (strcmp(io->out.blobs.blobs[i].tag, SMB2_CREATE_TAG_MXAC) == 0) {
-			/* TODO: this also contains a status field in
-			   first 4 bytes */
 			if (io->out.blobs.blobs[i].data.length != 8) {
 				smb2_request_destroy(req);
 				return NT_STATUS_INVALID_NETWORK_RESPONSE;
 			}
+			io->out.maximal_access_status =
+				IVAL(io->out.blobs.blobs[i].data.data, 0);
 			io->out.maximal_access = IVAL(io->out.blobs.blobs[i].data.data, 4);
 		}
 		if (strcmp(io->out.blobs.blobs[i].tag, SMB2_CREATE_TAG_QFID) == 0) {
diff --git a/source4/scripting/bin/sambaundoguididx b/source4/scripting/bin/sambaundoguididx
index 24a95e20d7f..41d2030e075 100755
--- a/source4/scripting/bin/sambaundoguididx
+++ b/source4/scripting/bin/sambaundoguididx
@@ -57,8 +57,7 @@ privatedir = os.path.dirname(url)
 
 dbs = []
 for part in partitions[0]['partition']:
-    file_quoted = part.split(":")[1]
-    tdbname = urllib.unquote(file_quoted)
+    tdbname = part.split(":")[1]
     tdbpath = os.path.join(privatedir, tdbname)
 
     db = ldb.Ldb(url=tdbpath, options=["modules:"])
diff --git a/source4/torture/smb2/acls.c b/source4/torture/smb2/acls.c
index 6178e211034..7bccce803f0 100644
--- a/source4/torture/smb2/acls.c
+++ b/source4/torture/smb2/acls.c
@@ -2363,6 +2363,557 @@ done:
 	return ret;
 }
 
+/*
+ * test Owner Rights, S-1-3-4
+ */
+static bool test_owner_rights(struct torture_context *tctx,
+			      struct smb2_tree *tree)
+{
+	const char *fname = BASEDIR "\\owner_right.txt";
+	struct smb2_create cr;
+	struct smb2_handle handle = {{0}};
+	union smb_fileinfo gi;
+	union smb_setfileinfo si;
+	struct security_descriptor *sd_orig = NULL;
+	struct security_descriptor *sd = NULL;
+	const char *owner_sid = NULL;
+	NTSTATUS mxac_status;
+	NTSTATUS status;
+	bool ret = true;
+
+	smb2_deltree(tree, BASEDIR);
+
+	ret = smb2_util_setup_dir(tctx, tree, BASEDIR);
+	torture_assert_goto(tctx, ret, ret, done,
+			    "smb2_util_setup_dir failed\n");
+
+	torture_comment(tctx, "TESTING OWNER RIGHTS\n");
+
+	cr = (struct smb2_create) {
+		.in.desired_access = SEC_STD_READ_CONTROL |
+			SEC_STD_WRITE_DAC |SEC_STD_WRITE_OWNER,
+		.in.file_attributes = FILE_ATTRIBUTE_NORMAL,
+		.in.share_access = NTCREATEX_SHARE_ACCESS_MASK,
+		.in.create_disposition = NTCREATEX_DISP_OPEN_IF,
+		.in.impersonation_level = NTCREATEX_IMPERSONATION_ANONYMOUS,
+		.in.fname = fname,
+	};
+
+	status = smb2_create(tree, tctx, &cr);
+	torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+					"smb2_create failed\n");
+	handle = cr.out.file.handle;
+
+	torture_comment(tctx, "get the original sd\n");
+
+	gi = (union smb_fileinfo) {
+		.query_secdesc.level = RAW_FILEINFO_SEC_DESC,
+		.query_secdesc.in.file.handle = handle,
+		.query_secdesc.in.secinfo_flags = SECINFO_DACL|SECINFO_OWNER,
+	};
+
+	status = smb2_getinfo_file(tree, tctx, &gi);
+	torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+					"smb2_getinfo_file failed\n");
+
+	sd_orig = gi.query_secdesc.out.sd;
+	owner_sid = dom_sid_string(tctx, sd_orig->owner_sid);
+
+	/*
+	 * Add a 2 element ACL
+	 * SEC_RIGHTS_FILE_READ for the owner,
+	 * SEC_FILE_WRITE_DATA for SID_OWNER_RIGHTS.
+	 *
+	 * Proves that the owner and SID_OWNER_RIGHTS
+	 * ACE entries are additive.
+	 */
+	sd = security_descriptor_dacl_create(tctx, 0, NULL, NULL,
+					     owner_sid,
+					     SEC_ACE_TYPE_ACCESS_ALLOWED,
+					     SEC_RIGHTS_FILE_READ,
+					     0,
+					     SID_OWNER_RIGHTS,
+					     SEC_ACE_TYPE_ACCESS_ALLOWED,
+					     SEC_FILE_WRITE_DATA,
+					     0,
+					     NULL);
+	torture_assert_not_null_goto(tctx, sd, ret, done,
+				     "SD create failed\n");
+
+	si = (union smb_setfileinfo) {
+		.set_secdesc.level = RAW_SFILEINFO_SEC_DESC,
+		.set_secdesc.in.file.handle = handle,
+		.set_secdesc.in.secinfo_flags = SECINFO_DACL,
+		.set_secdesc.in.sd = sd,
+	};
+
+	status = smb2_setinfo_file(tree, &si);
+	torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+					"smb2_setinfo_file failed\n");
+
+	status = smb2_util_close(tree, handle);
+	torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+					"smb2_util_close failed\n");
+	ZERO_STRUCT(handle);
+
+	cr = (struct smb2_create) {
+		.in.desired_access = SEC_STD_READ_CONTROL,
+		.in.file_attributes = FILE_ATTRIBUTE_NORMAL,
+		.in.share_access = NTCREATEX_SHARE_ACCESS_MASK,
+		.in.create_disposition = NTCREATEX_DISP_OPEN_IF,
+		.in.impersonation_level = NTCREATEX_IMPERSONATION_ANONYMOUS,
+		.in.query_maximal_access = true,
+		.in.fname = fname,
+	};
+
+	status = smb2_create(tree, tctx, &cr);
+	torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+					"smb2_setinfo_file failed\n");
+	handle = cr.out.file.handle;
+
+	mxac_status = NT_STATUS(cr.out.maximal_access_status);
+	torture_assert_ntstatus_ok_goto(tctx, mxac_status, ret, done,
+					"smb2_setinfo_file failed\n");
+
+	/*
+	 * For some reasons Windows 2016 doesn't set SEC_STD_DELETE but we
+	 * do. Mask it out so the test passes against Samba and Windows.
+	 */
+	torture_assert_int_equal_goto(tctx,
+				      cr.out.maximal_access & ~SEC_STD_DELETE,
+				      SEC_RIGHTS_FILE_READ |
+				      SEC_FILE_WRITE_DATA,
+				      ret, done,
+				      "Wrong maximum access\n");
+
+	status = smb2_util_close(tree, handle);
+	torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+					"smb2_util_close failed\n");
+	ZERO_STRUCT(handle);
+
+done:
+	if (!smb2_util_handle_empty(handle)) {
+		smb2_util_close(tree, handle);
+	}
+	smb2_deltree(tree, BASEDIR);
+	return ret;
+}
+
+/*
+ * test Owner Rights with a leading DENY ACE, S-1-3-4
+ */
+static bool test_owner_rights_deny(struct torture_context *tctx,
+				struct smb2_tree *tree)
+{
+	const char *fname = BASEDIR "\\owner_right_deny.txt";
+	struct smb2_create cr;
+	struct smb2_handle handle = {{0}};
+	union smb_fileinfo gi;
+	union smb_setfileinfo si;
+	struct security_descriptor *sd_orig = NULL;
+	struct security_descriptor *sd = NULL;
+	const char *owner_sid = NULL;
+	NTSTATUS mxac_status;
+	NTSTATUS status;
+	bool ret = true;
+
+	smb2_deltree(tree, BASEDIR);
+
+	ret = smb2_util_setup_dir(tctx, tree, BASEDIR);
+	torture_assert_goto(tctx, ret, ret, done,
+			"smb2_util_setup_dir failed\n");
+
+	torture_comment(tctx, "TESTING OWNER RIGHTS DENY\n");
+
+	cr = (struct smb2_create) {
+		.in.desired_access = SEC_STD_READ_CONTROL |
+			SEC_STD_WRITE_DAC |SEC_STD_WRITE_OWNER,
+		.in.file_attributes = FILE_ATTRIBUTE_NORMAL,
+		.in.share_access = NTCREATEX_SHARE_ACCESS_MASK,
+		.in.create_disposition = NTCREATEX_DISP_OPEN_IF,
+		.in.impersonation_level = NTCREATEX_IMPERSONATION_ANONYMOUS,
+		.in.fname = fname,
+	};
+
+	status = smb2_create(tree, tctx, &cr);
+	torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+					"smb2_create failed\n");
+	handle = cr.out.file.handle;
+
+	torture_comment(tctx, "get the original sd\n");
+
+	gi = (union smb_fileinfo) {
+		.query_secdesc.level = RAW_FILEINFO_SEC_DESC,
+		.query_secdesc.in.file.handle = handle,
+		.query_secdesc.in.secinfo_flags = SECINFO_DACL|SECINFO_OWNER,
+	};
+
+	status = smb2_getinfo_file(tree, tctx, &gi);
+	torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+				"smb2_getinfo_file failed\n");
+
+	sd_orig = gi.query_secdesc.out.sd;
+	owner_sid = dom_sid_string(tctx, sd_orig->owner_sid);
+
+	/*
+	 * Add a 2 element ACL
+	 * DENY SEC_FILE_DATA_READ for SID_OWNER_RIGHTS
+	 * SEC_FILE_READ_DATA for the owner.
+	 *
+	 * Proves that the owner and SID_OWNER_RIGHTS
+	 * ACE entries are additive.
+	 */
+	sd = security_descriptor_dacl_create(tctx, 0, NULL, NULL,
+					SID_OWNER_RIGHTS,
+					SEC_ACE_TYPE_ACCESS_DENIED,
+					SEC_FILE_READ_DATA,
+					0,
+					owner_sid,
+					SEC_ACE_TYPE_ACCESS_ALLOWED,
+					SEC_RIGHTS_FILE_READ,
+					0,
+					NULL);
+	torture_assert_not_null_goto(tctx, sd, ret, done,
+					"SD create failed\n");
+
+	si = (union smb_setfileinfo) {
+		.set_secdesc.level = RAW_SFILEINFO_SEC_DESC,
+		.set_secdesc.in.file.handle = handle,
+		.set_secdesc.in.secinfo_flags = SECINFO_DACL,
+		.set_secdesc.in.sd = sd,
+	};
+
+	status = smb2_setinfo_file(tree, &si);
+	torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+					"smb2_setinfo_file failed\n");
+
+	status = smb2_util_close(tree, handle);
+	torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+					"smb2_util_close failed\n");
+	ZERO_STRUCT(handle);
+
+	cr = (struct smb2_create) {
+		.in.desired_access = SEC_STD_READ_CONTROL,
+		.in.file_attributes = FILE_ATTRIBUTE_NORMAL,
+		.in.share_access = NTCREATEX_SHARE_ACCESS_MASK,
+		.in.create_disposition = NTCREATEX_DISP_OPEN_IF,
+		.in.impersonation_level = NTCREATEX_IMPERSONATION_ANONYMOUS,
+		.in.query_maximal_access = true,
+		.in.fname = fname,
+	};
+
+	status = smb2_create(tree, tctx, &cr);
+	torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
+					"smb2_setinfo_file failed\n");
+	handle = cr.out.file.handle;
+
+	mxac_status = NT_STATUS(cr.out.maximal_access_status);
+	torture_assert_ntstatus_ok_goto(tctx, mxac_status, ret, done,
+					"smb2_setinfo_file failed\n");
+
+	/*
+	 * For some reasons Windows 2016 doesn't set SEC_STD_DELETE but we
+	 * do. Mask it out so the test passes against Samba and Windows.
+	 */
+	torture_assert_int_equal_goto(tctx,
+				      cr.out.maximal_access & ~SEC_STD_DELETE,
+				      SEC_RIGHTS_FILE_READ & ~SEC_FILE_READ_DATA,
+				      ret, done,
+				      "Wrong maximum access\n");


-- 
Samba Shared Repository



More information about the samba-cvs mailing list