diff options
-rw-r--r-- | source3/include/proto.h | 1 | ||||
-rw-r--r-- | source3/smbd/pipes.c | 8 | ||||
-rw-r--r-- | source3/smbd/process.c | 19 | ||||
-rw-r--r-- | source3/smbd/reply.c | 17 |
4 files changed, 37 insertions, 8 deletions
diff --git a/source3/include/proto.h b/source3/include/proto.h index 5d82ef090d..d644b09a6a 100644 --- a/source3/include/proto.h +++ b/source3/include/proto.h @@ -7120,6 +7120,7 @@ const char *smb_fn_name(int type); void add_to_common_flags2(uint32 v); void remove_from_common_flags2(uint32 v); void construct_reply_common_req(struct smb_request *req, char *outbuf); +size_t req_wct_ofs(struct smb_request *req); void chain_reply(struct smb_request *req); void check_reload(time_t t); void smbd_process(void); diff --git a/source3/smbd/pipes.c b/source3/smbd/pipes.c index faabdd795b..4841882cc3 100644 --- a/source3/smbd/pipes.c +++ b/source3/smbd/pipes.c @@ -278,8 +278,12 @@ void reply_pipe_read_and_X(struct smb_request *req) srv_set_message((char *)req->outbuf, 12, nread, False); SSVAL(req->outbuf,smb_vwv5,nread); - SSVAL(req->outbuf,smb_vwv6,smb_offset(data,req->outbuf)); - SSVAL(smb_buf(req->outbuf),-2,nread); + SSVAL(req->outbuf,smb_vwv6, + req_wct_ofs(req) + + 1 /* the wct field */ + + 12 * sizeof(uint16_t) /* vwv */ + + 2); /* the buflen field */ + SSVAL(req->outbuf,smb_vwv11,smb_maxcnt); DEBUG(3,("readX-IPC pnum=%04x min=%d max=%d nread=%d\n", fsp->fnum, smb_mincnt, smb_maxcnt, (int)nread)); diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 3547bfcc3a..1701cd33da 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -1823,6 +1823,25 @@ void chain_reply(struct smb_request *req) #else /* + * How many bytes have we already accumulated up to the current wct field + * offset? + */ + +size_t req_wct_ofs(struct smb_request *req) +{ + size_t buf_size; + + if (req->chain_outbuf == NULL) { + return smb_wct - 4; + } + buf_size = talloc_get_size(req->chain_outbuf); + if ((buf_size % 4) != 0) { + buf_size += (4 - (buf_size % 4)); + } + return buf_size - 4; +} + +/* * Hack around reply_nterror & friends not being aware of chained requests, * generating illegal (i.e. wct==0) chain replies. */ diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index d7704965f8..28836144c2 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -3169,7 +3169,8 @@ Returning short read of maximum allowed for compatibility with Windows 2000.\n", Setup readX header. ****************************************************************************/ -static int setup_readX_header(char *outbuf, size_t smb_maxcnt) +static int setup_readX_header(struct smb_request *req, char *outbuf, + size_t smb_maxcnt) { int outsize; char *data; @@ -3182,9 +3183,13 @@ static int setup_readX_header(char *outbuf, size_t smb_maxcnt) SCVAL(outbuf,smb_vwv0,0xFF); SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */ SSVAL(outbuf,smb_vwv5,smb_maxcnt); - SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf)); + SSVAL(outbuf,smb_vwv6, + req_wct_ofs(req) + + 1 /* the wct field */ + + 12 * sizeof(uint16_t) /* vwv */ + + 2); /* the buflen field */ SSVAL(outbuf,smb_vwv7,(smb_maxcnt >> 16)); - SSVAL(smb_buf(outbuf),-2,smb_maxcnt); + SSVAL(outbuf,smb_vwv11,smb_maxcnt); /* Reset the outgoing length, set_message truncates at 0x1FFFF. */ _smb_setlen_large(outbuf,(smb_size + 12*2 + smb_maxcnt - 4)); return outsize; @@ -3238,7 +3243,7 @@ static void send_file_readX(connection_struct *conn, struct smb_request *req, header = data_blob_const(headerbuf, sizeof(headerbuf)); construct_reply_common_req(req, (char *)headerbuf); - setup_readX_header((char *)headerbuf, smb_maxcnt); + setup_readX_header(req, (char *)headerbuf, smb_maxcnt); if ((nread = SMB_VFS_SENDFILE(smbd_server_fd(), fsp, &header, startpos, smb_maxcnt)) == -1) { /* Returning ENOSYS means no data at all was sent. @@ -3296,7 +3301,7 @@ normal_read: uint8 headerbuf[smb_size + 2*12]; construct_reply_common_req(req, (char *)headerbuf); - setup_readX_header((char *)headerbuf, smb_maxcnt); + setup_readX_header(req, (char *)headerbuf, smb_maxcnt); /* Send out the header. */ if (write_data(smbd_server_fd(), (char *)headerbuf, @@ -3323,7 +3328,7 @@ normal_read: return; } - setup_readX_header((char *)req->outbuf, nread); + setup_readX_header(req, (char *)req->outbuf, nread); DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n", fsp->fnum, (int)smb_maxcnt, (int)nread ) ); |