smbd: Add padding byte to readx response
authorChristof Schmitt <cs@samba.org>
Fri, 15 Aug 2014 05:04:33 +0000 (22:04 -0700)
committerJeremy Allison <jra@samba.org>
Fri, 29 Aug 2014 22:27:13 +0000 (00:27 +0200)
MS-CIFS 2.2.4.42.2 states: "Pad (1 byte): This field is optional. When
using the NT LAN Manager dialect, this field can be used to align the
Data field to a 16-bit boundary relative to the start of the SMB Header.
If Unicode strings are being used, this field MUST be present. When
used, this field MUST be one padding byte long."

Always add the padding byte to all readx responses to avoid additional
complexity.

Signed-off-by: Christof Schmitt <cs@samba.org>
Reviewed-by: Jeremy Allison <jra@samba.org>
source3/smbd/aio.c
source3/smbd/pipes.c
source3/smbd/process.c
source3/smbd/reply.c

index 2235c32eefce7b1be2d22927f33d674f7f4cfbe3..f5e4cc6837730dbc0a2c75347b3b0fb672a9933c 100644 (file)
@@ -196,7 +196,7 @@ NTSTATUS schedule_aio_read_and_X(connection_struct *conn,
        /* The following is safe from integer wrap as we've already checked
           smb_maxcnt is 128k or less. Wct is 12 for read replies */
 
-       bufsize = smb_size + 12 * 2 + smb_maxcnt;
+       bufsize = smb_size + 12 * 2 + smb_maxcnt + 1 /* padding byte */;
 
        if ((aio_ex = create_aio_extra(NULL, fsp, bufsize)) == NULL) {
                DEBUG(10,("schedule_aio_read_and_X: malloc fail.\n"));
@@ -206,6 +206,7 @@ NTSTATUS schedule_aio_read_and_X(connection_struct *conn,
        construct_reply_common_req(smbreq, (char *)aio_ex->outbuf.data);
        srv_set_message((char *)aio_ex->outbuf.data, 12, 0, True);
        SCVAL(aio_ex->outbuf.data,smb_vwv0,0xFF); /* Never a chained reply. */
+       SCVAL(smb_buf(aio_ex->outbuf.data), 0, 0); /* padding byte */
 
        init_strict_lock_struct(fsp, (uint64_t)smbreq->smbpid,
                (uint64_t)startpos, (uint64_t)smb_maxcnt, READ_LOCK,
@@ -221,7 +222,8 @@ NTSTATUS schedule_aio_read_and_X(connection_struct *conn,
        aio_ex->offset = startpos;
 
        req = SMB_VFS_PREAD_SEND(aio_ex, fsp->conn->sconn->ev_ctx,
-                                fsp, smb_buf(aio_ex->outbuf.data),
+                                fsp,
+                                smb_buf(aio_ex->outbuf.data) + 1 /* pad */,
                                 smb_maxcnt, startpos);
        if (req == NULL) {
                DEBUG(0,("schedule_aio_read_and_X: aio_read failed. "
@@ -256,7 +258,7 @@ static void aio_pread_smb1_done(struct tevent_req *req)
        files_struct *fsp = aio_ex->fsp;
        int outsize;
        char *outbuf = (char *)aio_ex->outbuf.data;
-       char *data = smb_buf(outbuf);
+       char *data = smb_buf(outbuf) + 1 /* padding byte */;
        ssize_t nread;
        int err;
 
@@ -285,7 +287,8 @@ static void aio_pread_smb1_done(struct tevent_req *req)
                ERROR_NT(map_nt_error_from_unix(err));
                outsize = srv_set_message(outbuf,0,0,true);
        } else {
-               outsize = srv_set_message(outbuf, 12, nread, False);
+               outsize = srv_set_message(outbuf, 12,
+                                         nread + 1 /* padding byte */, false);
                SSVAL(outbuf,smb_vwv2, 0xFFFF); /* Remaining - must be * -1. */
                SSVAL(outbuf,smb_vwv5, nread);
                SSVAL(outbuf,smb_vwv6, smb_offset(data,outbuf));
index f1f61bbc5b81c595c690e191e2b79cf7518f9aea..110951ca67cb4186d28c596033a00f5e690986be 100644 (file)
@@ -422,11 +422,12 @@ void reply_pipe_read_and_X(struct smb_request *req)
        state->smb_maxcnt = SVAL(req->vwv+5, 0);
        state->smb_mincnt = SVAL(req->vwv+6, 0);
 
-       reply_outbuf(req, 12, state->smb_maxcnt);
+       reply_outbuf(req, 12, state->smb_maxcnt + 1 /* padding byte */);
        SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
        SSVAL(req->outbuf, smb_vwv1, 0);    /* no andx offset */
+       SCVAL(smb_buf(req->outbuf), 0, 0); /* padding byte */
 
-       data = (uint8_t *)smb_buf(req->outbuf);
+       data = (uint8_t *)smb_buf(req->outbuf) + 1 /* padding byte */;
 
        /*
         * We have to tell the upper layers that we're async.
@@ -467,7 +468,8 @@ static void pipe_read_andx_done(struct tevent_req *subreq)
        req->outbuf = state->outbuf;
        state->outbuf = NULL;
 
-       srv_set_message((char *)req->outbuf, 12, nread, False);
+       srv_set_message((char *)req->outbuf, 12, nread + 1 /* padding byte */,
+                       false);
 
 #if 0
        /*
@@ -488,7 +490,8 @@ static void pipe_read_andx_done(struct tevent_req *subreq)
              (smb_wct - 4)     /* offset from smb header to wct */
              + 1               /* the wct field */
              + 12 * sizeof(uint16_t) /* vwv */
-             + 2);             /* the buflen field */
+             + 2               /* the buflen field */
+             + 1);             /* padding byte */
        SSVAL(req->outbuf,smb_vwv11,state->smb_maxcnt);
 
        DEBUG(3,("readX-IPC min=%d max=%d nread=%d\n",
index 7148462d716eddc470c6d7f22a278e49902ce4f8..207a4dd996803947c5c3216bc6001ccea5414242 100644 (file)
@@ -2144,7 +2144,8 @@ static bool smb_splice_chain(uint8_t **poutbuf, const uint8_t *andx_buf)
 
                bytes_addr = outbuf + ofs        /* vwv start */
                        + sizeof(uint16_t) * wct /* vwv array */
-                       + sizeof(uint16_t);      /* bcc */
+                       + sizeof(uint16_t)       /* bcc */
+                       + 1;                     /* padding byte */
 
                SSVAL(outbuf + ofs, 6 * sizeof(uint16_t),
                      bytes_addr - outbuf - 4);
index 4cb446fb23e6aa24418018ccdaadd530ffff9d12..2cc174fce420bf279c71faf61a2e972a9437620d 100644 (file)
@@ -3682,7 +3682,8 @@ static int setup_readX_header(struct smb_request *req, char *outbuf,
 {
        int outsize;
 
-       outsize = srv_set_message(outbuf,12,smb_maxcnt,False);
+       outsize = srv_set_message(outbuf,12,smb_maxcnt + 1 /* padding byte */,
+                                 False);
 
        memset(outbuf+smb_vwv0,'\0',24); /* valgrind init. */
 
@@ -3693,11 +3694,14 @@ static int setup_readX_header(struct smb_request *req, char *outbuf,
              (smb_wct - 4)     /* offset from smb header to wct */
              + 1               /* the wct field */
              + 12 * sizeof(uint16_t) /* vwv */
-             + 2);             /* the buflen field */
+             + 2               /* the buflen field */
+             + 1);             /* padding byte */
        SSVAL(outbuf,smb_vwv7,(smb_maxcnt >> 16));
        SSVAL(outbuf,smb_vwv11,smb_maxcnt);
+       SCVAL(smb_buf(outbuf), 0, 0); /* padding byte */
        /* Reset the outgoing length, set_message truncates at 0x1FFFF. */
-       _smb_setlen_large(outbuf,(smb_size + 12*2 + smb_maxcnt - 4));
+       _smb_setlen_large(outbuf,
+                         smb_size + 12*2 + smb_maxcnt - 4 + 1 /* pad */);
        return outsize;
 }
 
@@ -3734,7 +3738,7 @@ static void send_file_readX(connection_struct *conn, struct smb_request *req,
            (fsp->base_fsp == NULL) &&
            (fsp->wcp == NULL) &&
            lp_use_sendfile(SNUM(conn), xconn->smb1.signing_state) ) {
-               uint8 headerbuf[smb_size + 12 * 2];
+               uint8 headerbuf[smb_size + 12 * 2 + 1 /* padding byte */];
                DATA_BLOB header;
 
                if(fsp_stat(fsp) == -1) {
@@ -3848,7 +3852,7 @@ static void send_file_readX(connection_struct *conn, struct smb_request *req,
 normal_read:
 
        if ((smb_maxcnt & 0xFF0000) > 0x10000) {
-               uint8 headerbuf[smb_size + 2*12];
+               uint8 headerbuf[smb_size + 2*12 + 1 /* padding byte */];
                ssize_t ret;
 
                construct_reply_common_req(req, (char *)headerbuf);
@@ -3887,11 +3891,12 @@ normal_read:
 
 nosendfile_read:
 
-       reply_outbuf(req, 12, smb_maxcnt);
+       reply_outbuf(req, 12, smb_maxcnt + 1 /* padding byte */);
        SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
        SSVAL(req->outbuf, smb_vwv1, 0);    /* no andx offset */
 
-       nread = read_file(fsp, smb_buf(req->outbuf), startpos, smb_maxcnt);
+       nread = read_file(fsp, smb_buf(req->outbuf) + 1 /* padding byte */,
+                         startpos, smb_maxcnt);
        saved_errno = errno;
 
        SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
@@ -3969,7 +3974,7 @@ static size_t calc_read_size(const struct smb_request *req,
        size_t max_pdu = calc_max_read_pdu(req);
        size_t total_size = 0;
        size_t hdr_len = MIN_SMB_SIZE + VWV(12);
-       size_t max_len = max_pdu - hdr_len;
+       size_t max_len = max_pdu - hdr_len - 1 /* padding byte */;
 
        /*
         * Windows explicitly ignores upper size of 0xFFFF.