[SCM] Samba Shared Repository - branch master updated

Jeremy Allison jra at samba.org
Mon Mar 4 19:12:02 UTC 2019


The branch, master has been updated
       via  4a9f7d24569 tests: add a simple test for smbcacls -x
       via  ec8984f8dd1 smbcacls: add -x argument, prints maximum access
       via  52e1171e21b s3:libsmb: add cli_query_mxac()
       via  c8c6da2c298 s3:libsmb: add cli_smb2_query_mxac()
       via  128e195e039 s4:torture: add a test with additional bits in SEC_FLAG_MAXIMUM_ALLOWED
       via  8d355dd9769 libcli/security: fix handling of deny type ACEs in access_check_max_allowed()
       via  b205d695d76 s4:torture: Add test_deny1().
       via  0ebd8c99aed s4:torture: Add test_owner_rights_deny1().
       via  9722f75757c libcli/security: correct access check and maximum access calculation for Owner Rights ACEs
       via  fadc4c1bc5f s4:torture: Add test_owner_rights_deny().
       via  2e181e34c48 s4:torture: Fix the test_owner_rights() test to show permissions are additive.
       via  9fc1a09baee vfs: drop lseek stat-open checks
      from  7798bc14fbd CI: don't use swap

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


- Log -----------------------------------------------------------------
commit 4a9f7d2456952ef79584f5a01f09462f2ffeb990
Author: Ralph Boehme <slow at samba.org>
Date:   Sat Mar 2 15:37:38 2019 +0100

    tests: add a simple test for smbcacls -x
    
    Signed-off-by: Ralph Boehme <slow at samba.org>
    Reviewed-by: Jeremy Allison <jra at samba.org>
    
    Autobuild-User(master): Jeremy Allison <jra at samba.org>
    Autobuild-Date(master): Mon Mar  4 19:11:06 UTC 2019 on sn-devel-144

commit ec8984f8dd1f8c00a489a5aaf5e51a85f0bfd3ad
Author: Ralph Boehme <slow at samba.org>
Date:   Wed Feb 27 16:45:07 2019 +0100

    smbcacls: add -x argument, prints maximum access
    
    Signed-off-by: Ralph Boehme <slow at samba.org>

commit 52e1171e21b56880f75b3e8f0be9c8fdf1503934
Author: Ralph Boehme <slow at samba.org>
Date:   Fri Mar 1 09:49:17 2019 +0100

    s3:libsmb: add cli_query_mxac()
    
    Works only for SMB2.
    
    Signed-off-by: Ralph Boehme <slow at samba.org>
    Reviewed-by: Jeremy Allison <jra at samba.org>

commit c8c6da2c2986096feef37d125eb05ccdb00bffd3
Author: Ralph Boehme <slow at samba.org>
Date:   Fri Mar 1 09:48:25 2019 +0100

    s3:libsmb: add cli_smb2_query_mxac()
    
    Signed-off-by: Ralph Boehme <slow at samba.org>
    Reviewed-by: Jeremy Allison <jra at samba.org>

commit 128e195e039e381d8f691103324033ef916e35cb
Author: Ralph Boehme <slow at samba.org>
Date:   Fri Mar 1 18:06:48 2019 +0100

    s4:torture: add a test with additional bits in SEC_FLAG_MAXIMUM_ALLOWED
    
    When access_mask contains SEC_FLAG_MAXIMUM_ALLOWED, the server must still
    proces other bits from access_mask. Eg if access_mask contains a right that
    the requester doesn't have, the function must validate that against the
    effective permissions.
    
    Signed-off-by: Ralph Boehme <slow at samba.org>
    Reviewed-by: Jeremy Allison <jra at samba.org>

commit 8d355dd9769e8990ce998b4c9f28977669b43616
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>

commit b205d695d769e910a91bec87451dec189ec33740
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>

commit 0ebd8c99aed28a0ba43a22c429837f66f7e94409
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>

commit 9722f75757c0e38c7f42c7cc310d56aa6eaf6392
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>

commit fadc4c1bc5fcc3b2d9daea44ef8daf8a8ae0fbe2
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>

commit 2e181e34c48c879235c5dc64bd7ab2b59781810c
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>

commit 9fc1a09baee4e1339c0fe20e47e24b6ea6c293ae
Author: David Disseldorp <ddiss at samba.org>
Date:   Mon Mar 4 11:35:45 2019 +0100

    vfs: drop lseek stat-open checks
    
    b9e91d2a8e41a43d7ebb7d7eed807a7d8de9b329 added fd==-1 checks to the
    lseek() path to handle "stat opens". Current reply.c and
    smb2_ioctl_filesys.c callers do not invoke SMB_VFS_LSEEK() with
    stat-open fsp structs, so the fd==-1 checks can be removed from the
    VFS.
    
    Signed-off-by: David Disseldorp <ddiss at samba.org>
    Reviewed-by: Jeremy Allison <jra at samba.org>

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

Summary of changes:
 docs-xml/manpages/smbcacls.1.xml       |   9 +
 libcli/security/access_check.c         | 142 +++++----
 source3/libsmb/cli_smb2_fnum.c         | 190 ++++++++++++
 source3/libsmb/cli_smb2_fnum.h         |   9 +
 source3/libsmb/clisecdesc.c            |  12 +
 source3/libsmb/proto.h                 |   4 +
 source3/modules/vfs_ceph.c             |   5 +-
 source3/modules/vfs_default.c          |   5 +-
 source3/script/tests/test_acl_xattr.sh |  17 +
 source3/utils/smbcacls.c               |  40 +++
 source4/torture/smb2/acls.c            | 552 ++++++++++++++++++++++++++++++++-
 11 files changed, 905 insertions(+), 80 deletions(-)


Changeset truncated at 500 lines:

diff --git a/docs-xml/manpages/smbcacls.1.xml b/docs-xml/manpages/smbcacls.1.xml
index 6071047682d..7f87da80329 100644
--- a/docs-xml/manpages/smbcacls.1.xml
+++ b/docs-xml/manpages/smbcacls.1.xml
@@ -38,6 +38,7 @@
 		<arg choice="opt">--set-security-info FLAGS</arg>
 		<arg choice="opt">--sddl</arg>
 		<arg choice="opt">--domain-sid SID</arg>
+		<arg choice="opt">-x|--maximum-access</arg>
 	</cmdsynopsis>
 </refsynopsisdiv>
 
@@ -189,6 +190,14 @@
 		</para></listitem>
 		</varlistentry>
 
+		<varlistentry>
+		<term>-x|--maximum-access</term>
+		<listitem><para>When displaying an ACL additionally query
+		the server for effective maximum permissions. Note that this
+		is only supported with SMB protocol version 2 or higher.
+		</para></listitem>
+		</varlistentry>
+
 		&stdarg.server.debug;
 		&popt.common.samba;
 		&popt.common.credentials;
diff --git a/libcli/security/access_check.c b/libcli/security/access_check.c
index 5d49b718f0c..322f4fdb0c6 100644
--- a/libcli/security/access_check.c
+++ b/libcli/security/access_check.c
@@ -109,10 +109,9 @@ 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;
-	uint32_t owner_rights_allowed = 0;
-	uint32_t owner_rights_denied = 0;
-	bool owner_rights_default = true;
 
 	if (sd->dacl == NULL) {
 		if (security_token_has_sid(token, sd->owner_sid)) {
@@ -121,26 +120,50 @@ static uint32_t access_check_max_allowed(const struct security_descriptor *sd,
 		return granted;
 	}
 
+	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) {
+		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 (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 |= (owner_rights_allowed &
-							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;
 		}
 
@@ -150,22 +173,13 @@ 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;
 		}
 	}
 
-	if (security_token_has_sid(token, sd->owner_sid)) {
-		if (owner_rights_default) {
-			granted |= SEC_STD_WRITE_DAC | SEC_STD_READ_CONTROL;
-		} else {
-			granted |= owner_rights_allowed;
-			granted &= ~owner_rights_denied;
-		}
-	}
-
 	return granted & ~denied;
 }
 
@@ -182,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;
@@ -221,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;
 		}
 
@@ -269,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/source3/libsmb/cli_smb2_fnum.c b/source3/libsmb/cli_smb2_fnum.c
index 4352e504cfc..349d99b8eee 100644
--- a/source3/libsmb/cli_smb2_fnum.c
+++ b/source3/libsmb/cli_smb2_fnum.c
@@ -2774,6 +2774,196 @@ NTSTATUS cli_smb2_set_security_descriptor(struct cli_state *cli,
 	return status;
 }
 
+/***************************************************************
+ Wrapper that allows SMB2 to query a security descriptor.
+ Synchronous only.
+
+***************************************************************/
+
+struct cli_smb2_mxac_state {
+	struct tevent_context *ev;
+	struct cli_state *cli;
+	const char *fname;
+	struct smb2_create_blobs in_cblobs;
+	uint16_t fnum;
+	NTSTATUS status;
+	uint32_t mxac;
+};
+
+static void cli_smb2_mxac_opened(struct tevent_req *subreq);
+static void cli_smb2_mxac_closed(struct tevent_req *subreq);
+
+struct tevent_req *cli_smb2_query_mxac_send(TALLOC_CTX *mem_ctx,
+					    struct tevent_context *ev,
+					    struct cli_state *cli,
+					    const char *fname)
+{
+	struct tevent_req *req = NULL, *subreq = NULL;
+	struct cli_smb2_mxac_state *state = NULL;
+	NTSTATUS status;
+
+	req = tevent_req_create(mem_ctx, &state, struct cli_smb2_mxac_state);
+	if (req == NULL) {
+		return NULL;
+	}
+	*state = (struct cli_smb2_mxac_state) {
+		state->ev = ev,
+		state->cli = cli,
+		state->fname = fname,
+	};
+
+	if (smbXcli_conn_protocol(cli->conn) < PROTOCOL_SMB2_02) {
+		tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
+		return tevent_req_post(req, ev);
+	}
+
+	status = smb2_create_blob_add(state,
+				      &state->in_cblobs,
+				      SMB2_CREATE_TAG_MXAC,
+				      data_blob(NULL, 0));
+	if (tevent_req_nterror(req, status)) {
+		return tevent_req_post(req, ev);
+	}
+
+	subreq = cli_smb2_create_fnum_send(
+		state,
+		state->ev,
+		state->cli,
+		state->fname,
+		0,			/* create_flags */
+		SMB2_IMPERSONATION_IMPERSONATION,
+		FILE_READ_ATTRIBUTES,
+		0,			/* file attributes */
+		FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
+		FILE_OPEN,
+		0,			/* create_options */
+		&state->in_cblobs);
+	if (tevent_req_nomem(subreq, req)) {
+		return tevent_req_post(req, ev);
+	}
+	tevent_req_set_callback(subreq, cli_smb2_mxac_opened, req);
+	return req;
+}
+
+static void cli_smb2_mxac_opened(struct tevent_req *subreq)
+{
+	struct tevent_req *req = tevent_req_callback_data(
+		subreq, struct tevent_req);
+	struct cli_smb2_mxac_state *state = tevent_req_data(
+		req, struct cli_smb2_mxac_state);
+	struct smb2_create_blobs out_cblobs = {0};
+	DATA_BLOB *mxac_blob = NULL;
+	NTSTATUS status;
+	int i;
+
+	status = cli_smb2_create_fnum_recv(
+		subreq, &state->fnum, NULL, state, &out_cblobs);
+	TALLOC_FREE(subreq);
+
+	if (tevent_req_nterror(req, status)) {
+		return;
+	}
+
+	for (i = 0; i < out_cblobs.num_blobs; i++) {
+		if (strcmp(out_cblobs.blobs[i].tag, SMB2_CREATE_TAG_MXAC) != 0) {
+			continue;
+		}
+		mxac_blob = &out_cblobs.blobs[i].data;
+		break;
+	}
+	if (mxac_blob == NULL) {
+		state->status = NT_STATUS_INVALID_NETWORK_RESPONSE;
+		goto close;
+	}
+	if (mxac_blob->length != 8) {
+		state->status = NT_STATUS_INVALID_NETWORK_RESPONSE;
+		goto close;
+	}
+
+	state->status = NT_STATUS(IVAL(mxac_blob->data, 0));
+	state->mxac = IVAL(mxac_blob->data, 4);
+
+close:
+	subreq = cli_smb2_close_fnum_send(
+		state, state->ev, state->cli, state->fnum);
+	if (tevent_req_nomem(subreq, req)) {
+		return;
+	}
+	tevent_req_set_callback(subreq, cli_smb2_mxac_closed, req);
+
+	return;
+}
+
+static void cli_smb2_mxac_closed(struct tevent_req *subreq)
+{
+	struct tevent_req *req = tevent_req_callback_data(
+		subreq, struct tevent_req);
+	NTSTATUS status;
+
+	status = cli_smb2_close_fnum_recv(subreq);
+	if (tevent_req_nterror(req, status)) {
+		return;
+	}
+
+	tevent_req_done(req);
+}
+
+NTSTATUS cli_smb2_query_mxac_recv(struct tevent_req *req, uint32_t *mxac)
+{
+	struct cli_smb2_mxac_state *state = tevent_req_data(
+		req, struct cli_smb2_mxac_state);
+	NTSTATUS status;
+
+	if (tevent_req_is_nterror(req, &status)) {
+		return status;
+	}
+
+	if (!NT_STATUS_IS_OK(state->status)) {
+		return state->status;
+	}
+
+	*mxac = state->mxac;
+	return NT_STATUS_OK;
+}
+
+NTSTATUS cli_smb2_query_mxac(struct cli_state *cli,
+			     const char *fname,
+			     uint32_t *_mxac)
+{
+	TALLOC_CTX *frame = talloc_stackframe();
+	struct tevent_context *ev = NULL;
+	struct tevent_req *req = NULL;
+	NTSTATUS status = NT_STATUS_INTERNAL_ERROR;
+	bool ok;
+
+	if (smbXcli_conn_has_async_calls(cli->conn)) {
+		/*
+		 * Can't use sync call while an async call is in flight
+		 */
+		status = NT_STATUS_INVALID_PARAMETER;
+		goto fail;
+	}
+
+	ev = samba_tevent_context_init(frame);
+	if (ev == NULL) {
+		goto fail;
+	}
+	req = cli_smb2_query_mxac_send(frame, ev, cli, fname);
+	if (req == NULL) {
+		goto fail;
+	}
+	ok = tevent_req_poll_ntstatus(req, ev, &status);
+	if (!ok) {
+		goto fail;
+	}
+	status = cli_smb2_query_mxac_recv(req, _mxac);
+
+fail:
+	cli->raw_status = status;
+	TALLOC_FREE(frame);
+	return status;
+}
+
 /***************************************************************
  Wrapper that allows SMB2 to rename a file.
  Synchronous only.
diff --git a/source3/libsmb/cli_smb2_fnum.h b/source3/libsmb/cli_smb2_fnum.h
index 62ae093862f..c4ca069ee96 100644
--- a/source3/libsmb/cli_smb2_fnum.h
+++ b/source3/libsmb/cli_smb2_fnum.h
@@ -173,6 +173,15 @@ NTSTATUS cli_smb2_set_security_descriptor(struct cli_state *cli,
 			uint16_t fnum,
 			uint32_t sec_info,
 			const struct security_descriptor *sd);
+struct tevent_req *cli_smb2_query_mxac_send(TALLOC_CTX *mem_ctx,
+					    struct tevent_context *ev,
+					    struct cli_state *cli,
+					    const char *fname);
+NTSTATUS cli_smb2_query_mxac_recv(struct tevent_req *req,
+				  uint32_t *mxac);
+NTSTATUS cli_smb2_query_mxac(struct cli_state *cli,
+			     const char *fname,
+			     uint32_t *mxac);
 NTSTATUS cli_smb2_rename(struct cli_state *cli,
 			 const char *fname_src,
 			 const char *fname_dst,
diff --git a/source3/libsmb/clisecdesc.c b/source3/libsmb/clisecdesc.c
index c11e4b322ef..f9a7a057ed6 100644
--- a/source3/libsmb/clisecdesc.c
+++ b/source3/libsmb/clisecdesc.c
@@ -91,6 +91,18 @@ NTSTATUS cli_query_secdesc(struct cli_state *cli, uint16_t fnum,
 	return cli_query_security_descriptor(cli, fnum, sec_info, mem_ctx, sd);
 }
 
+NTSTATUS cli_query_mxac(struct cli_state *cli,
+			const char *filename,
+			uint32_t *mxac)
+{
+	if (smbXcli_conn_protocol(cli->conn) < PROTOCOL_SMB2_02) {
+		return NT_STATUS_NOT_SUPPORTED;
+	}
+
+	return cli_smb2_query_mxac(cli, filename, mxac);
+}
+
+
 /****************************************************************************
   set the security descriptor for a open file
  ****************************************************************************/
diff --git a/source3/libsmb/proto.h b/source3/libsmb/proto.h
index b0cfcb5aa90..e1a54ef75f9 100644
--- a/source3/libsmb/proto.h
+++ b/source3/libsmb/proto.h
@@ -927,6 +927,10 @@ NTSTATUS cli_set_security_descriptor(struct cli_state *cli,
 NTSTATUS cli_set_secdesc(struct cli_state *cli, uint16_t fnum,
 			 const struct security_descriptor *sd);
 
+NTSTATUS cli_query_mxac(struct cli_state *cli,
+			const char *filename,
+			uint32_t *mxac);
+
 /* The following definitions come from libsmb/clistr.c  */
 
 size_t clistr_pull_talloc(TALLOC_CTX *ctx,


-- 
Samba Shared Repository



More information about the samba-cvs mailing list