Re: [twsocket] Severe Bug in FtpCli resp. FtpSrv - Fix

2005-12-03 Thread Angus Robertson - Magenta Systems Ltd
 Following a fix:
 The data-socket must effectively be stopped from accepting a 
 connection once the primary transfer command has failed. If the 
 data-socket is simply closed then on client-side an error is raised - 
 so my solution is not to call datasocket.accept on the incoming 
 connection - by clearing datasocket.OnSessionAvailable.

Mt testing of the FTP server unit you emailed and which you said you'd 
sent to Francois shows your 'fix' does not work, at least in my 
testing.  Perhaps my test has shown up a different problem to the one 
you have fixed.  

The issue seems to be when the PASV command is sent, the server opens 
the data socket to listen for a connection from the client, but this 
does not happen if the subsequent RETV, LIST or STOR command fails to 
start.  So the data socket remains listening when the next PASV command 
comes in, and is closed then, but immediately setup up again to list, 
before it has closed properly, which I think is why there is an 
erroneous response from the closed event.  

Clearing OnSessionAvailable has not effect, since the client never opens 
a session.  

Angus
-- 
To unsubscribe or change your settings for TWSocket mailing list
please goto http://www.elists.org/mailman/listinfo/twsocket
Visit our website at http://www.overbyte.be


Re: [twsocket] Severe Bug in FtpCli resp. FtpSrv - Fix

2005-12-02 Thread Angus Robertson - Magenta Systems Ltd
 The data-socket must effectively be stopped from accepting a 
 connection once the primary transfer command has failed. 

I found your change made no difference to the issue of the extra 
response being generated, since it was triggered when the data socket 
was closed, and it was already open and listening when the RETR command 
was rejected.  

I've fixed TFtpServer by adding checks for the Client.PassiveMode flag 
still being set when the connection is closed, normally it's reset when 
the data connection is opened.  If it's still set, I skip the second 
response event and closed trigger event, for both STOR and RETR.

Angus
-- 
To unsubscribe or change your settings for TWSocket mailing list
please goto http://www.elists.org/mailman/listinfo/twsocket
Visit our website at http://www.overbyte.be


Re: [twsocket] Severe Bug in FtpCli resp. FtpSrv - Fix

2005-12-01 Thread Peter Feldbaumer
Followup  Fix to my first posting:

If you want to reproduce the bug even on a fast connection simply enter in 
File FtpCli

procedure TCustomFtpCli.Next1GetAsync;
...
SetErrorMessage;
FNext := nil;
-Sleep(500);
FDataSocket.Close;
DestroyLocalStream;
...
end;

This will cause the data-connection to be established before the client can 
revoke it since it receives the 501 response from the FtpSrv.
Once the data-connection is established also on the FtpSrv-side tearing it 
down will cause the 226 File sent ok to be issued, no matter if an 501 
Invalid RETR has already been sent.

My investigations show that this behaviour _on server side_ seems to be 
faulty - other FTP Servers always only answer ONCE (with e.g. 501) on the 
control connection if the transfer fails before any data is transferred (on 
the data-channel).

Following a fix:

The data-socket must effectively be stopped from accepting a connection 
once the primary transfer command has failed. If the data-socket is simply 
closed then on client-side an error is raised - so my solution is not to 
call datasocket.accept on the incoming connection - by clearing 
datasocket.OnSessionAvailable.

procedure TFtpServer.CommandRETR(...);
var ...
begin
{ --- FLD --- begin }
  try
{ --- FLD --- end }

 (here comes all the code that is in the procedure right now)

{ --- FLD --- begin }
  finally
if Client.PassiveMode and
   (StrLComp(PChar(Answer), '15', 2) 0) then // check for success 
150..159
begin
  Client.DataSocket.OnSessionAvailable:= nil;
end;
  end;
{ --- FLD --- end }
end;

This must be done for all commands that use the (passive) data connection; 
CommandRETR, CommandSTOR and so on...

best regards,
Peter

ps: please forget the last paragraph in my last posting - the described 
situation can't happen

--
Peter Feldbaumer
p dot feldbaumer at utanet dot at


 I found a bug in the FtpCli - FtpSrv combination.
 Steps to reproduce:

 1) (Client) put FtpCli into passive mode
 2) (Server) assign FtpSrv.FtpServerValidateGet
 3) (Client) request something from the Server - e.g. with FtpClient.Get
 4) (server) fail the resulting RETR command on the server-side in
 FtpServerValidateGet (either by setting Allowed to false or by raising an
 exception)

 If the connection between Client and Server is slow enough(!) this will 
 lead
 to wrong state in the client state-machine, so that subsequent RETR will
 fail! Below you can find a log that demonstrates the problem (logged on
 client side) - (please note that there are some custom-extended commands -
 namely STATUS and ACCESS - they all expect a one-line answer, just as
 regular ftp-commands).

 The error occurs in line L6. L1 to L4 are as expected, L4 is the result 
 from
 the failed FtpServerValidateGet.
 Then the client issues the next command L5 and it expects a 1 line answer
 (which comes in L7), however L6 is received inbetween as the answer 
 because
 the FtpSrv unexpectedly sends 226 File sent ok, although it never has
 transmitted anything. This unexpected answer shifts all subsequent
 server-answer and leads to an unexpected state at some time.

 L1:  PASV
 L2:  227 Entering Passive Mode (81,189,215,215,78,33).
 L3:  RETR _SYSTEMARCHIVE_5889c6e9f9fb40d68fa23d6d74011566
 L4:  501 Cannot RETR. IDENTICAL
 L5:  STATUS
 L6:  226 File sent ok
 L7:  ACCESS SYSTEM
 L8:  200 Haupt-Bildschirm: Geteilter Schirm
 L9:  PASV
 L10:  200 Ok. Access Type set!
 L11:  RETR _SYSTEMSTAT_0_500
 L12:  227 Entering Passive Mode (81,189,215,215,78,33).
 L13: ErrorMessage: 227 Entering Passive Mode (81,189,215,215,78,33).

 If you work on a fast network connection this problem doesn't occur, 
 because
 L4 AND L6 are received in one block and effectively form L4 and L5, 
 which
 doesn't shift anything.

 Reason for the problem:
 In passive mode FtpCli starts a passive data-connection to the server at 
 the
 same time as it sends the RETR command (in TCustomFtpCli.DoGetAsync()), so
 it does NOT wait for a response from the FtpSrv if the RETR-command
 alltogether is valid (in active mode this doesn't happen because then the
 FtpSrv starts the data-connection - and this only happens if the
 FtpSrv.FtpServerValidateGet succeeds).
 As soon as the client receives the 501 Cannot RETR. (triggered by
 TFtpServer.CommandRETR() and the call to FtpSrv.FtpServerValidateGet) it
 closes the data-connection again.
 But this triggers TFtpServer.ClientRetrSessionClosed() which in turn sends
 the226 File sent ok.

 So the reason for the problem is clear, however I don't know how to 
 correct
 it?
 Should
 a) the passive data-connection only be connected if / as soon as the
 primary command is approved by the server
 b) the server simply ignore the ClientRetrSessionClosed and not send
 anything if nothing was transmitted (scheduled to transmit)?

 btw: This led my to discover another fundamental problem with passive mode
 (which luckily obviously doesn't occur in reality):
 On