Ensure we correctly calculate reply credits over all returned
authorJeremy Allison <jra@samba.org>
Tue, 15 Nov 2011 19:27:56 +0000 (11:27 -0800)
committerKarolin Seeger <kseeger@samba.org>
Wed, 16 Nov 2011 19:31:35 +0000 (20:31 +0100)
SMB2 replies, and do as Windows does and return the total in the
last SMB2 reply. Fixes an issue found by Christian M Ambach <christian.ambach@de.ibm.com>
(and thanks to Christian for the initial patch this was based on).
(cherry picked from commit 65566dfa8629136eaf0dc1491502dc651d1a4858)

Fix bug #8614 (SMB2: not granting credits for all requests in a compound
request).

source3/smbd/smb2_server.c

index 0e70983263bf5ca9a166cd9ff1cb6c5da693a3d3..8a5d81f87b227a9dc8e09f59bc1233e39d2eb6fe 100644 (file)
@@ -514,13 +514,24 @@ static void smb2_calculate_credits(const struct smbd_smb2_request *inreq,
                                struct smbd_smb2_request *outreq)
 {
        int count, idx;
+       uint16_t total_credits = 0;
 
        count = outreq->out.vector_count;
 
        for (idx=1; idx < count; idx += 3) {
+               uint8_t *outhdr = (uint8_t *)outreq->out.vector[idx].iov_base;
                smb2_set_operation_credit(outreq->sconn,
                        &inreq->in.vector[idx],
                        &outreq->out.vector[idx]);
+               /* To match Windows, count up what we
+                  just granted. */
+               total_credits += SVAL(outhdr, SMB2_HDR_CREDIT);
+               /* Set to zero in all but the last reply. */
+               if (idx + 3 < count) {
+                       SSVAL(outhdr, SMB2_HDR_CREDIT, 0);
+               } else {
+                       SSVAL(outhdr, SMB2_HDR_CREDIT, total_credits);
+               }
        }
 }
 
@@ -1739,11 +1750,9 @@ static NTSTATUS smbd_smb2_request_reply(struct smbd_smb2_request *req)
 
        smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
 
-       /* Set credit for this operation (zero credits if this
+       /* Set credit for these operations (zero credits if this
           is a final reply for an async operation). */
-       smb2_set_operation_credit(req->sconn,
-                       &req->in.vector[i],
-                       &req->out.vector[i]);
+       smb2_calculate_credits(req, req);
 
        if (req->do_signing) {
                NTSTATUS status;