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

Karolin Seeger kseeger at samba.org
Mon Mar 11 12:26:03 UTC 2019


The branch, v4-9-test has been updated
       via  43957ab96e7 libcli/security: fix handling of deny type ACEs in access_check_max_allowed()
       via  4fe9eff4dd6 s4:torture: Add test_deny1().
       via  824a058aa92 s4:torture: Add test_owner_rights_deny1().
       via  b4289aa34ae libcli/security: correct access check and maximum access calculation for Owner Rights ACEs
       via  f801b824815 s4:torture: Add test_owner_rights_deny().
       via  b1ce4d436a1 s4:torture: Fix the test_owner_rights() test to show permissions are additive.
       via  8f9858671fd libcli/security: add "Owner Rights" calculation to access_check_max_allowed()
       via  2a7e1bb9c03 s4:torture: add a Maximum Access check with an Owner Rights ACE
       via  953039c7a78 s4:libcli: remember return code from maximum access
       via  9dc374fee03 sambaundoguididx: use the right escaped oder unescaped sam ldb files
       via  f8748b8bfc2 s4-server: Open and close a transaction on sam.ldb at startup
      from  47fb4ba84f3 vfs_ceph: remove ceph_fallocate/ceph_ftruncate fallback

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


- Log -----------------------------------------------------------------
commit 43957ab96e7f62c83fe3e46e7467b974ea44f99b
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-9-test): Karolin Seeger <kseeger at samba.org>
    Autobuild-Date(v4-9-test): Mon Mar 11 12:25:05 UTC 2019 on sn-devel-144

commit 4fe9eff4dd63cd7aca4caa63057e27399cc3b929
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 824a058aa92a379fb4c0078e8f4594724419d1ae
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 b4289aa34ae88c28a4b68214e33c57abc98e2f7a
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 f801b824815ca310731dd9243ab091af3a2d9802
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 b1ce4d436a122e0fc15bc41219839fd74941b87c
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 8f9858671fd720f9fe67754eb4b39f786840b824
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 2a7e1bb9c0344d71de1ab4bb841046b764bedc17
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 953039c7a78ffdd1f4f66492b89f10f19aeaee9e
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 9dc374fee03a2468912c9eabdfa1637c0cea6bf3
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)

commit f8748b8bfc20ab67bc53a8324495fa7b4f49a794
Author: Andrew Bartlett <abartlet at samba.org>
Date:   Tue Mar 5 01:38:41 2019 +0000

    s4-server: Open and close a transaction on sam.ldb at startup
    
    This fixes upgrading from 4.7 and earlier releases, and makes the DB
    reindexing more transparent. It should also make it easier to handle
    future normalisation rule changes, e.g. if we change the pack-format
    of integer indexes in a future release.
    
    Without this change, the  should have still handled reindexing the
    database. We don't know why exactly this wasn't happening correctly,
    but opening a transaction early in the samba process startup should
    now guarantee that the DB is correctly reindexed by the time the main
    samba code runs.
    
    An alternative fix would have been to open a transaction in the the
    DSDB module stack every time we connect to the database. However, this
    would add an extra write lock every time we open the DB, whereas
    starting samba happens much more infrequently.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=13760
    
    Signed-off-by: Andrew Bartlett <abartlet at samba.org>
    Reviewed-by: Tim Beale <timbeale at catalyst.net.nz>
    Reviewed-by: Gary Lockyer <gary at catalyst.net.nz>
    
    Autobuild-User(master): Andrew Bartlett <abartlet at samba.org>
    Autobuild-Date(master): Thu Mar  7 04:58:42 UTC 2019 on sn-devel-144
    
    (cherry picked from commit 8b18da27cf261b0283fe66d2b827cab542488ac7)

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

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/smbd/server.c                  |  42 +++
 source4/torture/smb2/acls.c            | 558 +++++++++++++++++++++++++++++++++
 6 files changed, 682 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/smbd/server.c b/source4/smbd/server.c
index db570710ca9..e0255523824 100644
--- a/source4/smbd/server.c
+++ b/source4/smbd/server.c
@@ -230,6 +230,41 @@ _NORETURN_ static void max_runtime_handler(struct tevent_context *ev,
 	exit(0);
 }
 
+/*
+ * When doing an in-place upgrade of Samba, the database format may have
+ * changed between versions. E.g. between 4.7 and 4.8 the DB changed from
+ * DN-based indexes to GUID-based indexes, so we have to re-index the DB after
+ * upgrading.
+ * This function handles migrating an older samba DB to a new Samba release.
+ * Note that we have to maintain DB compatibility between *all* older versions
+ * of Samba, not just the ones still under maintenance support.
+ */
+static int handle_inplace_db_upgrade(struct ldb_context *ldb_ctx)
+{
+	int ret;
+
+	/*
+	 * The DSDB stack will handle reindexing the DB (if needed) upon the first
+	 * DB write. Open and close a transaction on the DB now to trigger a
+	 * reindex if required, rather than waiting for the first write.
+	 * We do this here to guarantee that the DB will have been re-indexed by
+	 * the time the main samba code runs.
+	 * Refer to dsdb_schema_set_indices_and_attributes() for the actual reindexing
+	 * code, called from
+	 * source4/dsdb/samdb/ldb_modules/schema_load.c:schema_load_start_transaction()
+	 */
+	ret = ldb_transaction_start(ldb_ctx);
+	if (ret != LDB_SUCCESS) {
+		return ret;
+	}
+
+	ret = ldb_transaction_commit(ldb_ctx);
+	if (ret != LDB_SUCCESS) {
+		return ret;
+	}
+	return LDB_SUCCESS;
+}
+
 /*
   pre-open the key databases. This saves a lot of time in child
   processes
@@ -262,6 +297,13 @@ static int prime_ldb_databases(struct tevent_context *event_ctx, bool *am_backup
 		talloc_free(db_context);
 		return LDB_ERR_OPERATIONS_ERROR;
 	}
+
+	ret = handle_inplace_db_upgrade(ldb_ctx);
+	if (ret != LDB_SUCCESS) {
+		talloc_free(db_context);
+		return ret;
+	}
+
 	pdb = privilege_connect(db_context, cmdline_lp_ctx);
 	if (pdb == NULL) {
 		talloc_free(db_context);
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.
+	 *


-- 
Samba Shared Repository



More information about the samba-cvs mailing list