summaryrefslogtreecommitdiff
path: root/source3/smbd
diff options
context:
space:
mode:
Diffstat (limited to 'source3/smbd')
-rw-r--r--source3/smbd/smb2_ioctl_network_fs.c44
1 files changed, 34 insertions, 10 deletions
diff --git a/source3/smbd/smb2_ioctl_network_fs.c b/source3/smbd/smb2_ioctl_network_fs.c
index 1e1e3e5e94..a1d67f80a9 100644
--- a/source3/smbd/smb2_ioctl_network_fs.c
+++ b/source3/smbd/smb2_ioctl_network_fs.c
@@ -80,29 +80,37 @@ struct fsctl_srv_copychunk_state {
};
static void fsctl_srv_copychunk_vfs_done(struct tevent_req *subreq);
-static NTSTATUS copychunk_check_handles(struct files_struct *src_fsp,
+static NTSTATUS copychunk_check_handles(uint32_t ctl_code,
+ struct files_struct *src_fsp,
struct files_struct *dst_fsp,
struct smb_request *smb1req)
{
/*
* [MS-SMB2] 3.3.5.15.6 Handling a Server-Side Data Copy Request
- * If Open.GrantedAccess of the destination file does not
- * include FILE_WRITE_DATA, then the request MUST be failed with
- * STATUS_ACCESS_DENIED. If Open.GrantedAccess of the
- * destination file does not include FILE_READ_DATA access and
- * the CtlCode is FSCTL_SRV_COPYCHUNK, then the request MUST be
- * failed with STATUS_ACCESS_DENIED.
+ * The server MUST fail the request with STATUS_ACCESS_DENIED if any of
+ * the following are true:
+ * - The Open.GrantedAccess of the destination file does not include
+ * FILE_WRITE_DATA or FILE_APPEND_DATA.
*/
if (!CHECK_WRITE(dst_fsp)) {
DEBUG(5, ("copy chunk no write on dest handle (%s).\n",
smb_fname_str_dbg(dst_fsp->fsp_name) ));
return NT_STATUS_ACCESS_DENIED;
}
- if (!CHECK_READ(dst_fsp, smb1req)) {
+ /*
+ * - The Open.GrantedAccess of the destination file does not include
+ * FILE_READ_DATA, and the CtlCode is FSCTL_SRV_COPYCHUNK.
+ */
+ if ((ctl_code == FSCTL_SRV_COPYCHUNK)
+ && !CHECK_READ(dst_fsp, smb1req)) {
DEBUG(5, ("copy chunk no read on dest handle (%s).\n",
smb_fname_str_dbg(dst_fsp->fsp_name) ));
return NT_STATUS_ACCESS_DENIED;
}
+ /*
+ * - The Open.GrantedAccess of the source file does not include
+ * FILE_READ_DATA access.
+ */
if (!CHECK_READ(src_fsp, smb1req)) {
DEBUG(5, ("copy chunk no read on src handle (%s).\n",
smb_fname_str_dbg(src_fsp->fsp_name) ));
@@ -136,6 +144,7 @@ static NTSTATUS copychunk_check_handles(struct files_struct *src_fsp,
static struct tevent_req *fsctl_srv_copychunk_send(TALLOC_CTX *mem_ctx,
struct tevent_context *ev,
+ uint32_t ctl_code,
struct files_struct *dst_fsp,
DATA_BLOB *in_input,
size_t in_max_output,
@@ -150,6 +159,10 @@ static struct tevent_req *fsctl_srv_copychunk_send(TALLOC_CTX *mem_ctx,
struct srv_copychunk *chunk;
struct fsctl_srv_copychunk_state *state;
+ /* handler for both copy-chunk variants */
+ SMB_ASSERT((ctl_code == FSCTL_SRV_COPYCHUNK)
+ || (ctl_code == FSCTL_SRV_COPYCHUNK_WRITE));
+
req = tevent_req_create(mem_ctx, &state,
struct fsctl_srv_copychunk_state);
if (req == NULL) {
@@ -188,7 +201,8 @@ static struct tevent_req *fsctl_srv_copychunk_send(TALLOC_CTX *mem_ctx,
state->dst_fsp = dst_fsp;
- state->status = copychunk_check_handles(state->src_fsp,
+ state->status = copychunk_check_handles(ctl_code,
+ state->src_fsp,
state->dst_fsp,
smb2req->smb1req);
if (!NT_STATUS_IS_OK(state->status)) {
@@ -446,8 +460,18 @@ struct tevent_req *smb2_ioctl_network_fs(uint32_t ctl_code,
NTSTATUS status;
switch (ctl_code) {
+ /*
+ * [MS-SMB2] 2.2.31
+ * FSCTL_SRV_COPYCHUNK is issued when a handle has
+ * FILE_READ_DATA and FILE_WRITE_DATA access to the file;
+ * FSCTL_SRV_COPYCHUNK_WRITE is issued when a handle only has
+ * FILE_WRITE_DATA access.
+ */
+ case FSCTL_SRV_COPYCHUNK_WRITE: /* FALL THROUGH */
case FSCTL_SRV_COPYCHUNK:
- subreq = fsctl_srv_copychunk_send(state, ev, state->fsp,
+ subreq = fsctl_srv_copychunk_send(state, ev,
+ ctl_code,
+ state->fsp,
&state->in_input,
state->in_max_output,
state->smb2req);