summaryrefslogtreecommitdiff
path: root/source3/smbd/reply.c
diff options
context:
space:
mode:
Diffstat (limited to 'source3/smbd/reply.c')
-rw-r--r--source3/smbd/reply.c95
1 files changed, 81 insertions, 14 deletions
diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c
index 38ce797eeb..4c1ed56d4f 100644
--- a/source3/smbd/reply.c
+++ b/source3/smbd/reply.c
@@ -3494,7 +3494,7 @@ void reply_writebraw(connection_struct *conn, struct smb_request *req)
}
if (numtowrite>0) {
- nwritten = write_file(fsp,data,startpos,numtowrite);
+ nwritten = write_file(req,fsp,data,startpos,numtowrite);
}
DEBUG(3,("reply_writebraw: initial write fnum=%d start=%.0f num=%d "
@@ -3572,7 +3572,7 @@ void reply_writebraw(connection_struct *conn, struct smb_request *req)
exit_server_cleanly("secondary writebraw failed");
}
- nwritten = write_file(fsp,buf+4,startpos+nwritten,numtowrite);
+ nwritten = write_file(req,fsp,buf+4,startpos+nwritten,numtowrite);
if (nwritten == -1) {
TALLOC_FREE(buf);
reply_unixerror(req, ERRHRD, ERRdiskfull);
@@ -3686,7 +3686,7 @@ void reply_writeunlock(connection_struct *conn, struct smb_request *req)
if(numtowrite == 0) {
nwritten = 0;
} else {
- nwritten = write_file(fsp,data,startpos,numtowrite);
+ nwritten = write_file(req,fsp,data,startpos,numtowrite);
}
status = sync_file(conn, fsp, False /* write through */);
@@ -3808,7 +3808,7 @@ void reply_write(connection_struct *conn, struct smb_request *req)
return;
}
} else
- nwritten = write_file(fsp,data,startpos,numtowrite);
+ nwritten = write_file(req,fsp,data,startpos,numtowrite);
status = sync_file(conn, fsp, False);
if (!NT_STATUS_IS_OK(status)) {
@@ -3841,6 +3841,64 @@ void reply_write(connection_struct *conn, struct smb_request *req)
}
/****************************************************************************
+ Ensure a buffer is a valid writeX for recvfile purposes.
+****************************************************************************/
+
+#define STANDARD_WRITE_AND_X_HEADER_SIZE (smb_size - 4 + /* basic header */ \
+ (2*14) + /* word count (including bcc) */ \
+ 1 /* pad byte */)
+
+bool is_valid_writeX_buffer(char *inbuf)
+{
+ size_t numtowrite;
+ connection_struct *conn = NULL;
+ unsigned int doff = 0;
+ size_t len = smb_len(inbuf);
+
+ if (CVAL(inbuf,smb_com) != SMBwriteX ||
+ CVAL(inbuf,smb_vwv0) != 0xFF ||
+ CVAL(inbuf,smb_wct) != 14) {
+ return false;
+ }
+ conn = conn_find(SVAL(inbuf, smb_tid));
+ if (conn == NULL) {
+ return false;
+ }
+ if (IS_IPC(conn)) {
+ return false;
+ }
+ numtowrite = SVAL(inbuf,smb_vwv10);
+ numtowrite |= ((((size_t)SVAL(inbuf,smb_vwv9)) & 1 )<<16);
+ if (numtowrite == 0) {
+ return false;
+ }
+ /* Ensure the sizes match up. */
+ doff = SVAL(inbuf,smb_vwv11);
+
+ if (doff < STANDARD_WRITE_AND_X_HEADER_SIZE) {
+ /* no pad byte...old smbclient :-( */
+ return false;
+ }
+
+ if (len - doff != numtowrite) {
+ DEBUG(10,("is_valid_writeX_buffer: doff mismatch "
+ "len = %u, doff = %u, numtowrite = %u\n",
+ (unsigned int)len,
+ (unsigned int)doff,
+ (unsigned int)numtowrite ));
+ return false;
+ }
+
+ DEBUG(10,("is_valid_writeX_buffer: true "
+ "len = %u, doff = %u, numtowrite = %u\n",
+ (unsigned int)len,
+ (unsigned int)doff,
+ (unsigned int)numtowrite ));
+
+ return true;
+}
+
+/****************************************************************************
Reply to a write and X.
****************************************************************************/
@@ -3875,10 +3933,18 @@ void reply_write_and_X(connection_struct *conn, struct smb_request *req)
numtowrite |= ((((size_t)SVAL(req->inbuf,smb_vwv9)) & 1 )<<16);
}
- if(smb_doff > smblen || (smb_doff + numtowrite > smblen)) {
- reply_doserror(req, ERRDOS, ERRbadmem);
- END_PROFILE(SMBwriteX);
- return;
+ if (req->unread_bytes) {
+ if (numtowrite != req->unread_bytes) {
+ reply_doserror(req, ERRDOS, ERRbadmem);
+ END_PROFILE(SMBwriteX);
+ return;
+ }
+ } else {
+ if (smb_doff > smblen || smb_doff + numtowrite > smblen) {
+ reply_doserror(req, ERRDOS, ERRbadmem);
+ END_PROFILE(SMBwriteX);
+ return;
+ }
}
/* If it's an IPC, pass off the pipe handler. */
@@ -3947,15 +4013,16 @@ void reply_write_and_X(connection_struct *conn, struct smb_request *req)
nwritten = 0;
} else {
- if (schedule_aio_write_and_X(conn, req, fsp, data, startpos,
- numtowrite)) {
+ if (req->unread_bytes == 0 &&
+ schedule_aio_write_and_X(conn, req, fsp, data,
+ startpos, numtowrite)) {
END_PROFILE(SMBwriteX);
return;
}
- nwritten = write_file(fsp,data,startpos,numtowrite);
+ nwritten = write_file(req,fsp,data,startpos,numtowrite);
}
-
+
if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
reply_unixerror(req, ERRHRD, ERRdiskfull);
END_PROFILE(SMBwriteX);
@@ -4264,7 +4331,7 @@ void reply_writeclose(connection_struct *conn, struct smb_request *req)
return;
}
- nwritten = write_file(fsp,data,startpos,numtowrite);
+ nwritten = write_file(req,fsp,data,startpos,numtowrite);
set_filetime(conn, fsp->fsp_name, mtime);
@@ -4726,7 +4793,7 @@ void reply_printwrite(connection_struct *conn, struct smb_request *req)
data = smb_buf(req->inbuf) + 3;
- if (write_file(fsp,data,-1,numtowrite) != numtowrite) {
+ if (write_file(req,fsp,data,-1,numtowrite) != numtowrite) {
reply_unixerror(req, ERRHRD, ERRdiskfull);
END_PROFILE(SMBsplwr);
return;