summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source3/include/smb.h3
-rw-r--r--source3/lib/util.c19
-rw-r--r--source3/smbd/ipc.c11
-rw-r--r--source3/smbd/password.c5
-rw-r--r--source3/smbd/reply.c2
-rw-r--r--source3/smbd/server.c21
-rw-r--r--source3/smbd/trans2.c6
7 files changed, 43 insertions, 24 deletions
diff --git a/source3/include/smb.h b/source3/include/smb.h
index 5fd2e0846b..b9dd13a802 100644
--- a/source3/include/smb.h
+++ b/source3/include/smb.h
@@ -99,6 +99,9 @@ typedef unsigned int uint32;
#define DEFAULT_PIPE_TIMEOUT 10000000 /* Ten seconds */
#endif
+/* how long to wait for secondary SMB packets (seconds) */
+#define SMB_SECONDARY_WAIT 30
+
/* debugging code */
#ifndef SYSLOG
#define DEBUG(level,body) ((DEBUGLEVEL>=(level))?(Debug1 body):0)
diff --git a/source3/lib/util.c b/source3/lib/util.c
index fc47313b57..ee4fca3ed3 100644
--- a/source3/lib/util.c
+++ b/source3/lib/util.c
@@ -2079,7 +2079,7 @@ int read_smb_length(int fd,char *inbuf,int timeout)
if (msg_type == 0x85)
{
- DEBUG(5,( "Got keepalive packet\n"));
+ DEBUG(5,("Got keepalive packet\n"));
ok = False;
}
}
@@ -2097,8 +2097,7 @@ The timeout is in milli seconds
****************************************************************************/
BOOL receive_smb(int fd,char *buffer,int timeout)
{
- int len;
- BOOL ok;
+ int len,ret;
bzero(buffer,smb_size + 100);
@@ -2107,18 +2106,16 @@ BOOL receive_smb(int fd,char *buffer,int timeout)
return(False);
if (len > BUFFER_SIZE) {
- DEBUG(0,("Invalid packet length! (%d bytes)\n",len));
+ DEBUG(0,("Invalid packet length! (%d bytes).\n",len));
if (len > BUFFER_SIZE + (SAFETY_MARGIN/2))
exit(1);
}
- ok = (read_data(fd,buffer+4,len) == len);
-
- if (!ok)
- {
- close_sockets();
- exit(1);
- }
+ ret = read_data(fd,buffer+4,len);
+ if (ret != len) {
+ DEBUG(0,("ERROR: Invalid SMB length. Expected %d got %d\n",len,ret));
+ return False;
+ }
return(True);
}
diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c
index 594e067ddd..415c939bf3 100644
--- a/source3/smbd/ipc.c
+++ b/source3/smbd/ipc.c
@@ -2790,12 +2790,9 @@ int reply_trans(char *inbuf,char *outbuf)
while (pscnt < tpscnt || dscnt < tdscnt)
{
int pcnt,poff,dcnt,doff,pdisp,ddisp;
-
- receive_smb(Client,inbuf, 0);
- show_msg(inbuf);
-
- /* Ensure this is still a trans packet (sanity check) */
- if(CVAL(inbuf, smb_com) != SMBtrans)
+
+ if (!receive_smb(Client,inbuf, SMB_SECONDARY_WAIT*1000) ||
+ CVAL(inbuf, smb_com) != SMBtrans)
{
DEBUG(2,("Invalid secondary trans2 packet\n"));
if (params) free(params);
@@ -2803,6 +2800,8 @@ int reply_trans(char *inbuf,char *outbuf)
if (setup) free(setup);
return(ERROR(ERRSRV,ERRerror));
}
+
+ show_msg(inbuf);
tpscnt = SVAL(inbuf,smb_vwv0);
tdscnt = SVAL(inbuf,smb_vwv1);
diff --git a/source3/smbd/password.c b/source3/smbd/password.c
index ae548b8266..a5f597682f 100644
--- a/source3/smbd/password.c
+++ b/source3/smbd/password.c
@@ -1318,9 +1318,10 @@ BOOL server_cryptkey(char *buf)
CVAL(outbuf,0) = 0x81;
send_smb(password_client,outbuf);
- receive_smb(password_client,inbuf,5000);
+
- if (CVAL(inbuf,0) != 0x82) {
+ if (!receive_smb(password_client,inbuf,5000) ||
+ CVAL(inbuf,0) != 0x82) {
DEBUG(1,("%s rejected the session\n",pserver));
close(password_client); password_client = -1;
return(False);
diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c
index 43703982ec..4cfa001ec2 100644
--- a/source3/smbd/reply.c
+++ b/source3/smbd/reply.c
@@ -1590,7 +1590,7 @@ int reply_writebraw(char *inbuf,char *outbuf)
send_smb(Client,outbuf);
/* Now read the raw data into the buffer and write it */
- if(read_smb_length(Client,inbuf,0) == -1) {
+ if (read_smb_length(Client,inbuf,SMB_SECONDARY_WAIT) == -1) {
exit_server("secondary writebraw failed");
}
diff --git a/source3/smbd/server.c b/source3/smbd/server.c
index ecc8e4ce9c..3ececed393 100644
--- a/source3/smbd/server.c
+++ b/source3/smbd/server.c
@@ -3445,6 +3445,27 @@ static void process(void)
t = time(NULL);
+ {
+ /* the following bit of code was added to combat smbd
+ looping chewing lots of CPU time. It should never
+ actually be needed, but it seems that some systems
+ don't set error correctly, which is used to distinguish
+ a select() timeout from a read error
+
+ we exit if receive_smb() returns false 3 times in one second.
+ */
+ static int error_count=0;
+ static time_t error_time=0;
+ if (error_count==0) {
+ error_time = t;
+ } else if (error_time != t) {
+ error_count = 0;
+ } else if (error_count++ > 2) {
+ exit_server("looping in process()\n");
+ }
+ }
+
+
/* become root again if waiting */
unbecome_user();
diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c
index 0b113a2ed0..321dabc72c 100644
--- a/source3/smbd/trans2.c
+++ b/source3/smbd/trans2.c
@@ -1554,10 +1554,8 @@ int reply_trans2(char *inbuf,char *outbuf,int length,int bufsize)
while( num_data_sofar < total_data || num_params_sofar < total_params)
{
- receive_smb(Client,inbuf, 0);
-
- /* Ensure this is still a trans2 packet (sanity check) */
- if(CVAL(inbuf, smb_com) != SMBtranss2)
+ if(!receive_smb(Client,inbuf, SMB_SECONDARY_WAIT*1000) ||
+ CVAL(inbuf, smb_com) != SMBtranss2)
{
outsize = set_message(outbuf,0,0,True);
DEBUG(2,("Invalid secondary trans2 packet\n"));