summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJeremy Allison <jra@samba.org>2010-04-18 20:23:54 -0700
committerJeremy Allison <jra@samba.org>2010-04-18 20:23:54 -0700
commit59fa1e1890e0a007f56776d9539bf3f1ce074a34 (patch)
treed0a19706135a161f4a195ef08159a58b0f6d71e6
parent058d4a21afa843241c6a91a251fb46a327037194 (diff)
downloadsamba-59fa1e1890e0a007f56776d9539bf3f1ce074a34.tar.gz
samba-59fa1e1890e0a007f56776d9539bf3f1ce074a34.tar.xz
samba-59fa1e1890e0a007f56776d9539bf3f1ce074a34.zip
Final fix for #7331 - Compound async SMB 2 requests don't work right.
Don't free the cancelled SMB2 req early, let the cancelation function take care of it. Return a NT_STATUS_CANCELLED when we find and cancel a request. Fix our SMB2 error returns to correctly set the structuresize to 9, and add the expected zero byte (see section 2.2.2 in the SMB2 spec.). This causes Samba to pass the test program in this bug report that W2K8R2 fails (heh heh :-). This is because we always cause compound requests to get to a cancelation point before dealing with a cancel request. Jeremy.
-rw-r--r--source3/smbd/smb2_notify.c7
-rw-r--r--source3/smbd/smb2_server.c17
2 files changed, 20 insertions, 4 deletions
diff --git a/source3/smbd/smb2_notify.c b/source3/smbd/smb2_notify.c
index 3d60ffb39c..460e6293f5 100644
--- a/source3/smbd/smb2_notify.c
+++ b/source3/smbd/smb2_notify.c
@@ -113,6 +113,13 @@ static void smbd_smb2_request_notify_done(struct tevent_req *subreq)
uint64_t mid = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
DEBUG(10,("smbd_smb2_request_notify_done: cancelled mid %llu\n",
(unsigned long long)mid ));
+ error = smbd_smb2_request_error(req, NT_STATUS_CANCELLED);
+ if (!NT_STATUS_IS_OK(error)) {
+ smbd_server_connection_terminate(req->sconn,
+ nt_errstr(error));
+ return;
+ }
+ TALLOC_FREE(subreq);
return;
}
diff --git a/source3/smbd/smb2_server.c b/source3/smbd/smb2_server.c
index b697cb924b..0b3222e6ab 100644
--- a/source3/smbd/smb2_server.c
+++ b/source3/smbd/smb2_server.c
@@ -682,6 +682,12 @@ NTSTATUS smbd_smb2_request_pending_queue(struct smbd_smb2_request *req,
message_id = BVAL(reqhdr, SMB2_HDR_MESSAGE_ID);
async_id = message_id; /* keep it simple for now... */
+ /*
+ * What we send is identical to a smbd_smb2_request_error
+ * packet with an error status of STATUS_PENDING. Make use
+ * of this fact sometime when refactoring. JRA.
+ */
+
state = talloc_zero(req->sconn, struct smbd_smb2_request_pending_state);
if (state == NULL) {
return NT_STATUS_NO_MEMORY;
@@ -886,8 +892,6 @@ static NTSTATUS smbd_smb2_request_process_cancel(struct smbd_smb2_request *req)
smb2_opcode_name((uint16_t)IVAL(inhdr, SMB2_HDR_OPCODE)),
(unsigned long long)found_id ));
tevent_req_cancel(cur->subreq);
- TALLOC_FREE(cur->subreq);
- TALLOC_FREE(cur);
}
return NT_STATUS_OK;
@@ -1246,6 +1250,7 @@ NTSTATUS smbd_smb2_request_error_ex(struct smbd_smb2_request *req,
SIVAL(outhdr, SMB2_HDR_STATUS, NT_STATUS_V(status));
outbody = outhdr + SMB2_HDR_BODY;
+ SSVAL(outbody, 0, 9);
req->out.vector[i+1].iov_base = (void *)outbody;
req->out.vector[i+1].iov_len = 8;
@@ -1255,8 +1260,12 @@ NTSTATUS smbd_smb2_request_error_ex(struct smbd_smb2_request *req,
req->out.vector[i+2].iov_base = (void *)info->data;
req->out.vector[i+2].iov_len = info->length;
} else {
- req->out.vector[i+2].iov_base = NULL;
- req->out.vector[i+2].iov_len = 0;
+ req->out.vector[i+2].iov_base = talloc_array(req, uint8_t, 1);
+ if (!req->out.vector[i+2].iov_base) {
+ return NT_STATUS_NO_MEMORY;
+ }
+ SCVAL(req->out.vector[i+2].iov_base, 0, 0);
+ req->out.vector[i+2].iov_len = 1;
}
/*