diff options
-rw-r--r-- | source3/include/smb.h | 3 | ||||
-rw-r--r-- | source3/lib/util.c | 19 | ||||
-rw-r--r-- | source3/smbd/ipc.c | 11 | ||||
-rw-r--r-- | source3/smbd/password.c | 5 | ||||
-rw-r--r-- | source3/smbd/reply.c | 2 | ||||
-rw-r--r-- | source3/smbd/server.c | 21 | ||||
-rw-r--r-- | source3/smbd/trans2.c | 6 |
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")); |