libcli/smb: correctly handle STATUS_BUFFER_OVERFLOW in smb1cli_readx*
authorStefan Metzmacher <metze@samba.org>
Fri, 27 Nov 2015 18:10:01 +0000 (19:10 +0100)
committerJeremy Allison <jra@samba.org>
Mon, 30 Nov 2015 23:38:23 +0000 (00:38 +0100)
BUG: https://bugzilla.samba.org/show_bug.cgi?id=11623

Signed-off-by: Stefan Metzmacher <metze@samba.org>
Reviewed-by: Jeremy Allison <jra@samba.org>
libcli/smb/smb1cli_read.c

index ab250abf143c9b94b54428fa3cab39b71aa3f897..d7a7f43e66e107cef7301036b58ae6eb7547e917 100644 (file)
@@ -26,9 +26,9 @@
 struct smb1cli_readx_state {
        uint32_t size;
        uint16_t vwv[12];
-       NTSTATUS status;
        uint32_t received;
        uint8_t *buf;
+       bool out_valid;
 };
 
 static void smb1cli_readx_done(struct tevent_req *subreq);
@@ -131,27 +131,36 @@ static void smb1cli_readx_done(struct tevent_req *subreq)
        uint8_t *bytes;
        uint16_t data_offset;
        uint32_t bytes_offset;
+       NTSTATUS status;
        static const struct smb1cli_req_expected_response expected[] = {
        {
                .status = NT_STATUS_OK,
                .wct = 0x0C
        },
+       {
+               .status = STATUS_BUFFER_OVERFLOW,
+               .wct = 0x0C
+       },
        };
 
-       state->status = smb1cli_req_recv(subreq, state,
-                                        &recv_iov,
-                                        NULL, /* phdr */
-                                        &wct,
-                                        &vwv,
-                                        NULL, /* pvwv_offset */
-                                        &num_bytes,
-                                        &bytes,
-                                        &bytes_offset,
-                                        NULL, /* inbuf */
-                                        expected, ARRAY_SIZE(expected));
+       status = smb1cli_req_recv(subreq, state,
+                                 &recv_iov,
+                                 NULL, /* phdr */
+                                 &wct,
+                                 &vwv,
+                                 NULL, /* pvwv_offset */
+                                 &num_bytes,
+                                 &bytes,
+                                 &bytes_offset,
+                                 NULL, /* inbuf */
+                                 expected, ARRAY_SIZE(expected));
        TALLOC_FREE(subreq);
-       if (tevent_req_nterror(req, state->status)) {
-               return;
+       if (NT_STATUS_EQUAL(status, STATUS_BUFFER_OVERFLOW)) {
+               /* no error */
+       } else {
+               if (tevent_req_nterror(req, status)) {
+                       return;
+               }
        }
 
        /* size is the number of bytes the server returned.
@@ -189,6 +198,12 @@ static void smb1cli_readx_done(struct tevent_req *subreq)
 
        state->buf = bytes + (data_offset - bytes_offset);
 
+       state->out_valid = true;
+
+       if (tevent_req_nterror(req, status)) {
+               return;
+       }
+
        tevent_req_done(req);
 }
 
@@ -205,7 +220,7 @@ static void smb1cli_readx_done(struct tevent_req *subreq)
  * @param[out] received The number of bytes received.
  * @param[out] rcvbuf Pointer to the bytes received.
  *
- * @return NT_STATUS_OK on succsess.
+ * @return NT_STATUS_OK or STATUS_BUFFER_OVERFLOW on succsess.
  */
 NTSTATUS smb1cli_readx_recv(struct tevent_req *req,
                            uint32_t *received,
@@ -213,12 +228,14 @@ NTSTATUS smb1cli_readx_recv(struct tevent_req *req,
 {
        struct smb1cli_readx_state *state = tevent_req_data(
                req, struct smb1cli_readx_state);
-       NTSTATUS status;
+       NTSTATUS status = NT_STATUS_OK;
 
-       if (tevent_req_is_nterror(req, &status)) {
+       if (tevent_req_is_nterror(req, &status) && !state->out_valid) {
+               *received = 0;
+               *rcvbuf = NULL;
                return status;
        }
        *received = state->received;
        *rcvbuf = state->buf;
-       return NT_STATUS_OK;
+       return status;
 }