diff options
-rw-r--r-- | source3/include/smb.h | 1 | ||||
-rw-r--r-- | source3/lib/util_sock.c | 51 | ||||
-rw-r--r-- | source3/smbd/oplock.c | 4 | ||||
-rw-r--r-- | source3/smbd/process.c | 6 | ||||
-rw-r--r-- | source3/smbd/reply.c | 5 |
5 files changed, 36 insertions, 31 deletions
diff --git a/source3/include/smb.h b/source3/include/smb.h index 616b75dded..d810e11340 100644 --- a/source3/include/smb.h +++ b/source3/include/smb.h @@ -27,6 +27,7 @@ #define BUFFER_SIZE (0xFFFF) #define SAFETY_MARGIN 1024 +#define LARGE_WRITEX_HDR_SIZE 65 #define NMB_PORT 137 #define DGRAM_PORT 138 diff --git a/source3/lib/util_sock.c b/source3/lib/util_sock.c index 3269042117..b59debe929 100644 --- a/source3/lib/util_sock.c +++ b/source3/lib/util_sock.c @@ -642,35 +642,38 @@ ssize_t read_smb_length(int fd,char *inbuf,unsigned int timeout) BOOL receive_smb(int fd,char *buffer, unsigned int timeout) { - ssize_t len,ret; + ssize_t len,ret; - smb_read_error = 0; + smb_read_error = 0; - memset(buffer,'\0',smb_size + 100); + memset(buffer,'\0',smb_size + 100); - len = read_smb_length_return_keepalive(fd,buffer,timeout); - if (len < 0) - { - DEBUG(10,("receive_smb: length < 0!\n")); - return(False); - } + len = read_smb_length_return_keepalive(fd,buffer,timeout); + if (len < 0) { + DEBUG(10,("receive_smb: length < 0!\n")); + return(False); + } - if (len > BUFFER_SIZE) { - DEBUG(0,("Invalid packet length! (%d bytes).\n",len)); - if (len > BUFFER_SIZE + (SAFETY_MARGIN/2)) - { - exit(1); - } - } + /* + * A WRITEX with CAP_LARGE_WRITEX can be 64k worth of data plus 65 bytes + * of header. Don't print the error if this fits.... JRA. + */ - if(len > 0) { - ret = read_socket_data(fd,buffer+4,len); - if (ret != len) { - smb_read_error = READ_ERROR; - return False; - } - } - return(True); + if (len > (BUFFER_SIZE + LARGE_WRITEX_HDR_SIZE)) { + DEBUG(0,("Invalid packet length! (%d bytes).\n",len)); + if (len > BUFFER_SIZE + (SAFETY_MARGIN/2)) + exit(1); + } + + if(len > 0) { + ret = read_socket_data(fd,buffer+4,len); + if (ret != len) { + smb_read_error = READ_ERROR; + return False; + } + } + + return(True); } /**************************************************************************** diff --git a/source3/smbd/oplock.c b/source3/smbd/oplock.c index e0b494017a..ac0836324b 100644 --- a/source3/smbd/oplock.c +++ b/source3/smbd/oplock.c @@ -676,13 +676,13 @@ static BOOL oplock_break(SMB_DEV_T dev, SMB_INO_T inode, struct timeval *tval, B messages crossing on the wire. */ - if((inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN))==NULL) + if((inbuf = (char *)malloc(BUFFER_SIZE + LARGE_WRITEX_HDR_SIZE + SAFETY_MARGIN))==NULL) { DEBUG(0,("oplock_break: malloc fail for input buffer.\n")); return False; } - if((outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN))==NULL) + if((outbuf = (char *)malloc(BUFFER_SIZE + LARGE_WRITEX_HDR_SIZE + SAFETY_MARGIN))==NULL) { DEBUG(0,("oplock_break: malloc fail for output buffer.\n")); free(inbuf); diff --git a/source3/smbd/process.c b/source3/smbd/process.c index ac5454c48c..74c0cbc96f 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -1184,8 +1184,8 @@ void smbd_process(void) time_t last_timeout_processing_time = time(NULL); unsigned int num_smbs = 0; - InBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN); - OutBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN); + InBuffer = (char *)malloc(BUFFER_SIZE + LARGE_WRITEX_HDR_SIZE + SAFETY_MARGIN); + OutBuffer = (char *)malloc(BUFFER_SIZE + LARGE_WRITEX_HDR_SIZE + SAFETY_MARGIN); if ((InBuffer == NULL) || (OutBuffer == NULL)) return; @@ -1208,7 +1208,7 @@ void smbd_process(void) lp_talloc_free(); main_loop_talloc_free(); - while (!receive_message_or_smb(InBuffer,BUFFER_SIZE,select_timeout)) { + while (!receive_message_or_smb(InBuffer,BUFFER_SIZE+LARGE_WRITEX_HDR_SIZE,select_timeout)) { if(!timeout_processing( deadtime, &select_timeout, &last_timeout_processing_time)) return; num_smbs = 0; /* Reset smb counter. */ diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index b43512329e..914f1801d2 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -2665,10 +2665,11 @@ int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int leng { files_struct *fsp = file_fsp(inbuf,smb_vwv2); SMB_OFF_T startpos = IVAL(inbuf,smb_vwv3); - size_t numtowrite = SVAL(inbuf,smb_vwv10); + size_t numtowrite = SVAL(inbuf,smb_vwv10)|(((size_t)SVAL(inbuf,smb_vwv9))<<16); BOOL write_through = BITSETW(inbuf+smb_vwv7,0); ssize_t nwritten = -1; unsigned int smb_doff = SVAL(inbuf,smb_vwv11); + unsigned int smblen = smb_len(inbuf); char *data; START_PROFILE(SMBwriteX); @@ -2682,7 +2683,7 @@ int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int leng CHECK_WRITE(fsp); CHECK_ERROR(fsp); - if(smb_doff > smb_len(inbuf)) { + if(smb_doff > smblen || (smb_doff + numtowrite > smblen)) { END_PROFILE(SMBwriteX); return(ERROR(ERRDOS,ERRbadmem)); } |