Hi,
Some weeks ago i implemented TLS capability in my SMTP-Server component.
Every thing works perfekt for the first weeks, but suddenly i noticed
that the server process
use 100% CPU. I restarted the process and it works again for about 2
days, then it goes to 100% again.
After hours of debuging i found out that it was always the same Server
in the Internet which cause the Problem.
In my logs i saw the following SMTP Command sequence:
Receive > EHLO O026.server.lu
Response < 250-OK
Response < 250-STARTTLS
Response < 250-AUTH PLAIN LOGIN
Response < 250 SIZE 104857600
Receive > STARTTLS
Response < 220 Ready to start TLS
Receive > EHLO O026.server.lu
Response < 250-OK
Response < 250-AUTH PLAIN LOGIN
Response < 250 SIZE 104857600
Receive > MAIL FROM:<[email protected]> SIZE=3318
Response < 250 OK smtp ready for [email protected]
Receive > RCPT TO:<[email protected]>
Response < 554 Recipient unknown
Receive > RSET
Response < 250 OK - Reset
After that the CPU utilization goes to 100%. No Disconnect and no Socket
Error !?
Because i could not found anything in my source code, i made a tcpdump
of this connection.
The Server is an active Spammer so it takes only a couple of hours until
it cames again ;-)
After a look into the tcpdump i saw that the server sends a QUIT after
the RSET, but
it shutdown the SSL before it sends the QUIT !!!
Of course, i know that this behavior is not correct. But it cause the
TBlockSocket.RecvTerminated method
to go in an endless loop! So we have a simple process to make a DoS.
I wrote a test client to reproduce this behavior by my self, and made an
fix for this condition.
*I would like to discuss this fix here. Maybe there is a better way to
handle this condition.
Maybe it's better to handle the condition in the RecvBuffer method of
the SSL Plugin.*
(Btw. i use openssl with freepascal and Linux)
-------------------------------------------------------------------------------
function TBlockSocket.RecvPacket(Timeout: Integer): AnsiString; //
Current SVN Version => 009.006.000
var
x: integer;
{$IFDEF CIL}
buf: TMemory;
{$ENDIF}
begin
Result := '';
ResetLastError;
if FBuffer <> '' then
begin
Result := FBuffer;
FBuffer := '';
end
else
begin
{$IFDEF WIN32}
//not drain CPU on large downloads...
Sleep(0);
{$ENDIF}
x := WaitingData;
if x > 0 then
begin
{$IFDEF CIL}
SetLength(Buf, x);
x := RecvBuffer(Buf, x);
if x >= 0 then
begin
SetLength(Buf, x);
Result := StringOf(Buf);
end;
{$ELSE}
SetLength(Result, x);
*// Here is the main problem. After the Client drops SSL
** // **RecvBuffer will return always 0 and not set an Error Code
// also RecvBuffer did not empty the Buffer, so the WaitingData
// method will always see the same Data
// In my case WaitingData always announce 16 Bytes and RecvBuffer
returns 0 => forever!!!
* x := RecvBuffer(Pointer(Result), x);
if x >= 0 then
SetLength(Result, x);
{$ENDIF}
* // Added this to announce an connection error
if x = 0 then
FLastError := WSAECONNRESET;
* end
else
begin
if CanRead(Timeout) then
begin
x := WaitingData;
if x = 0 then
FLastError := WSAECONNRESET;
if x > 0 then
begin
{$IFDEF CIL}
SetLength(Buf, x);
x := RecvBuffer(Buf, x);
if x >= 0 then
begin
SetLength(Buf, x);
result := StringOf(Buf);
end;
{$ELSE}
SetLength(Result, x);
x := RecvBuffer(Pointer(Result), x);
if x >= 0 then
SetLength(Result, x);
{$ENDIF}
* // Added this to announce an connection error
if x = 0 then
FLastError := WSAECONNRESET;
* end;
end
else
FLastError := WSAETIMEDOUT;
end;
end;
if FConvertLineEnd and (Result <> '') then
begin
if FLastCR and (Result[1] = LF) then
Delete(Result, 1, 1);
if FLastLF and (Result[1] = CR) then
Delete(Result, 1, 1);
FLastCR := False;
FLastLF := False;
end;
ExceptCheck;
end;
-------------------------------------------------------------------------------
If you want to reproduce that, the do the following on Client side:
1. Make a normal connection
2. Start TLS with: *Socket.SSLDoConnect;*
3. Send some data. Anything should be ok so far.
4. Shutdown SSL on client side with : *Socket.SSl.Shutdown;
*5. Send some data. Now the Server connection goes in the endless loop.
Alex
------------------------------------------------------------------------------
Enter the BlackBerry Developer Challenge
This is your chance to win up to $100,000 in prizes! For a limited time,
vendors submitting new applications to BlackBerry App World(TM) will have
the opportunity to enter the BlackBerry Developer Challenge. See full prize
details at: http://p.sf.net/sfu/Challenge
_______________________________________________
synalist-public mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/synalist-public