Final fix for #7331 - Compound async SMB 2 requests don't work right.
authorJeremy Allison <jra@samba.org>
Mon, 19 Apr 2010 03:23:54 +0000 (20:23 -0700)
committerJeremy Allison <jra@samba.org>
Mon, 19 Apr 2010 03:23:54 +0000 (20:23 -0700)
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.

source3/smbd/smb2_notify.c
source3/smbd/smb2_server.c

index 3d60ffb39c5537b61dfc817f13613d77981123ae..460e6293f595b19f0152242d9cd8e4bc536fbc35 100644 (file)
@@ -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;
        }
 
index b697cb924b2cb668d5447601fc10e25af71c4055..0b3222e6ab0036909e9d34c9d606cf8f5cf27678 100644 (file)
@@ -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;
        }
 
        /*