Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
idFTP with Secure Channel ?
#1
I need to use Secure Channel.

I can NOT use OpenSSL ( long story, but 100% can not be openSSL based )

So I use Delphi/Indy.SChannel/lib at master · tothpaul/Delphi (github.com)

Which has worked well for tIDHttp and such.. 

Included here is a FileZilla log of what I see when using it to connect.

While it uses TLS 1.3 here, TLS 1.2 is allowed also. Just don't see anyway in FileZilla to force 1.2... which really i don't think matters here, as it would be SChannel object doing that work?

This is a program that just connects to a few servers and doesn't really need to know or care about every single conneciton type under the sun that could exist.

But I am failing to get far.

Using Delphi 11.3 with Indy that comes installed along with SChannel object.

I have zero say / control of the server.

And to mention again, OpenSSL is NOT an option. 

Problem could be in TIdSSLIOHandlerSocketSChannel possibly?

If it is, ill have to switch us sadly to another FTP component that can work with these servers and not be OpenSSL dependent.

Would be sad, as we've been using TIDFTP for 20 years or more now.


But I know I have to be missing some stuff here. But google searching and ChatGTP keeps getting me into unsable states also, so last resort was here.

Source Snippet , I get to list and it fails.
In the end I need to upload a file and download a file.

Code:
  IdFTP1 := tidftp.Create(nil);
  ssl := TIdSSLIOHandlerSocketSChannel.Create(nil);
  ssl.ReuseSocket := rsTrue; // <--- just added this recently , not sure need this at all, doesnt change anything

  IdFTP1.OnStatus := FTPStatus;
  IdFTP1.OnTLSNotAvailable := TLSNotAvailable;
  IdFTP1.OnTLSHandShakeFailed := TLSHandShakeFailed;
  IdFTP1.OnTLSNegCmdFailed := TLSNegCmdFailed;

  IdFTP1.IOHandler := ssl;
  IdFTP1.UseTLS := utUseExplicitTLS;
  IdFTP1.Passive := True;
  
  IdFTP1.Host := 'sever.com';
  IdFTP1.Username := 'user';
  IdFTP1.Password := 'pass;
  IdFTP1.Connect;

  if IdFTP1.SupportsTLS then
  begin
    Memo1.lines.add('TLS IS SUPPORTED');
    idftp1.DataPortProtection := ftpdpsPrivate;
  end
  else
    Memo1.lines.add('TLS IS NOT SUPPORTED');

  IdFTP1.list;  /// <--- generates error "session reuse required"
Code:
Trace: CRealControlSocket::DoClose(66)
Trace: CControlSocket::DoClose(66)
Trace: CFtpControlSocket::ResetOperation(66)
Trace: CControlSocket::ResetOperation(66)
Trace: CFileZillaEnginePrivate::ResetOperation(66)
Trace: CRealControlSocket::DoClose(66)
Trace: CControlSocket::DoClose(66)
Trace: CFtpControlSocket::ResetOperation(66)
Trace: CControlSocket::ResetOperation(66)
Trace: CFileZillaEnginePrivate::ResetOperation(66)
Trace: CControlSocket::DoClose(66)
Trace: CControlSocket::ResetOperation(66)
Trace: CFileZillaEnginePrivate::ResetOperation(66)
Trace: CFileZillaEnginePrivate::ResetOperation(0)
Trace: CControlSocket::SendNextCommand()
Trace: CFtpLogonOpData::Send() in state 0
Status: Resolving address of some-ftp-server.com
Status: Connecting to xxx.yyy.zzz.151:21...
Status: Connection established, waiting for welcome message...
Trace: CFtpControlSocket::OnReceive()
Response: 220 (vsFTPd 3.0.5)
Trace: CFtpLogonOpData::ParseResponse() in state 1
Trace: CControlSocket::SendNextCommand()
Trace: CFtpLogonOpData::Send() in state 2
Command: AUTH TLS
Trace: CFtpControlSocket::OnReceive()
Response: 234 Proceed with negotiation.
Trace: CFtpLogonOpData::ParseResponse() in state 2
Status: Initializing TLS...
Trace: tls_layer_impl::client_handshake()
Trace: tls_layer_impl::continue_handshake()
Trace: TLS handshakep: About to send CLIENT HELLO
Trace: TLS handshakep: Sent CLIENT HELLO
Trace: tls_layer_impl::on_send()
Trace: tls_layer_impl::continue_handshake()
Trace: tls_layer_impl::on_read()
Trace: tls_layer_impl::continue_handshake()
Trace: tls_layer_impl::on_read()
Trace: tls_layer_impl::continue_handshake()
Trace: TLS handshakep: Received HELLO RETRY REQUEST
Trace: TLS handshakep: Processed HELLO RETRY REQUEST
Trace: TLS handshakep: About to send CLIENT HELLO
Trace: TLS handshakep: Sent CLIENT HELLO
Trace: tls_layer_impl::on_read()
Trace: tls_layer_impl::continue_handshake()
Trace: TLS handshakep: Received SERVER HELLO
Trace: TLS handshakep: Processed SERVER HELLO
Trace: TLS handshakep: Received ENCRYPTED EXTENSIONS
Trace: TLS handshakep: Processed ENCRYPTED EXTENSIONS
Trace: TLS handshakep: Received CERTIFICATE REQUEST
Trace: TLS handshakep: Processed CERTIFICATE REQUEST
Trace: tls_layer_impl::on_read()
Trace: tls_layer_impl::continue_handshake()
Trace: tls_layer_impl::on_read()
Trace: tls_layer_impl::continue_handshake()
Trace: tls_layer_impl::on_read()
Trace: tls_layer_impl::continue_handshake()
Trace: TLS handshakep: Received CERTIFICATE
Trace: TLS handshakep: Processed CERTIFICATE
Trace: TLS handshakep: Received CERTIFICATE VERIFY
Trace: TLS handshakep: Processed CERTIFICATE VERIFY
Trace: TLS handshakep: Received FINISHED
Trace: TLS handshakep: Processed FINISHED
Trace: TLS handshakep: About to send CERTIFICATE
Trace: TLS handshakep: Sent CERTIFICATE
Trace: TLS handshakep: About to send FINISHED
Trace: TLS handshakep: Sent FINISHED
Trace: TLS Handshake successful
Trace: Protocol: TLS1.3, Key exchange: ECDHE-SECP256R1-RSA-PSS-RSAE-SHA384, Cipher: AES-256-GCM, MAC: AEAD, ALPN: ftp
Trace: tls_layer_impl::verify_certificate()
Trace: System trust store decision: true
Trace: Sending certificate_verification_event
Trace: CFtpControlSocket::SetAsyncRequestReply
Trace: set_verification_result(true)
Status: TLS connection established.
Trace: CControlSocket::SendNextCommand()
Trace: CFtpLogonOpData::Send() in state 6
Command: USER <someusername>
Trace: CFtpControlSocket::OnReceive()
Trace: TLS handshakep: Received NEW SESSION TICKET
Trace: TLS handshakep: Processed NEW SESSION TICKET
Trace: gnutls_record_recv returned spurious EAGAIN
Trace: TLS handshakep: Received NEW SESSION TICKET
Trace: TLS handshakep: Processed NEW SESSION TICKET
Trace: gnutls_record_recv returned spurious EAGAIN
Trace: tls_layer_impl::on_read()
Trace: CFtpControlSocket::OnReceive()
Response: 331 Please specify the password.
Trace: CFtpLogonOpData::ParseResponse() in state 6
Trace: CControlSocket::SendNextCommand()
Trace: CFtpLogonOpData::Send() in state 6
Command: PASS *****
Trace: tls_layer_impl::on_read()
Trace: CFtpControlSocket::OnReceive()
Response: 230 Login successful.
Trace: CFtpLogonOpData::ParseResponse() in state 6
Status: Server does not support non-ASCII characters.
Trace: CControlSocket::SendNextCommand()
Trace: CFtpLogonOpData::Send() in state 11
Command: PBSZ 0
Trace: tls_layer_impl::on_read()
Trace: CFtpControlSocket::OnReceive()
Response: 200 PBSZ set to 0.
Trace: CFtpLogonOpData::ParseResponse() in state 11
Trace: CControlSocket::SendNextCommand()
Trace: CFtpLogonOpData::Send() in state 12
Command: PROT P
Trace: tls_layer_impl::on_read()
Trace: CFtpControlSocket::OnReceive()
Response: 200 PROT now Private.
Trace: CFtpLogonOpData::ParseResponse() in state 12
Status: Logged in
Trace: Measured latency of 7 ms
Trace: CFtpControlSocket::ResetOperation(0)
Trace: CControlSocket::ResetOperation(0)
Trace: CFtpLogonOpData::Reset(0) in state 15
Trace: CFileZillaEnginePrivate::ResetOperation(0)
Trace: CControlSocket::SendNextCommand()
Trace: CFtpListOpData::Send() in state 0
Status: Retrieving directory listing...
Trace: CFtpChangeDirOpData::Send() in state 0
Trace: CFtpChangeDirOpData::Send() in state 1
Command: PWD
Trace: tls_layer_impl::on_read()
Trace: CFtpControlSocket::OnReceive()
Response: 257 "/upload" is the current directory
Trace: CFtpChangeDirOpData::ParseResponse() in state 1
Trace: CFtpControlSocket::ResetOperation(0)
Trace: CControlSocket::ResetOperation(0)
Trace: CFtpChangeDirOpData::Reset(0) in state 1
Trace: CFtpListOpData::SubcommandResult(0) in state 1
Trace: CControlSocket::SendNextCommand()
Trace: CFtpListOpData::Send() in state 2
Trace: CFtpControlSocket::ResetOperation(0)
Trace: CControlSocket::ResetOperation(0)
Trace: CFtpListOpData::Reset(0) in state 2
Status: Directory listing of "/upload" successful
Trace: CFileZillaEnginePrivate::ResetOperation(0)
Reply
#2
(01-12-2024, 10:32 PM)cpstevenc Wrote: Problem could be in TIdSSLIOHandlerSocketSChannel possibly?

Seems like it, yes. See further below.

(01-12-2024, 10:32 PM)cpstevenc Wrote: If it is, ill have to switch us sadly to another FTP component that can work with these servers and not be OpenSSL dependent.

Indy is not dependent on OpenSSL, it just uses OpenSSL as the default out-of-the-box.
 
(01-12-2024, 10:32 PM)cpstevenc Wrote:
Code:
  if IdFTP1.SupportsTLS then
  begin
    Memo1.lines.add('TLS IS SUPPORTED');
    idftp1.DataPortProtection := ftpdpsPrivate;
  end
  else
    Memo1.lines.add('TLS IS NOT SUPPORTED');

Setting DataPortProtection does not need to be done conditionally like that. Just because the server supports TLS does not necessarily mean TLS is actually being used, particularly when using utUseExpliccitTLS. If you assign an SSLIOHandler, you should also set the DataPortProtection as well, and let TIdFTP decide internally whether to encrypt the data connection or not based on whether the control connection is actually encrypted.

(01-12-2024, 10:32 PM)cpstevenc Wrote:
Code:
  IdFTP1.list;  /// <--- generates error "session reuse required"

That is not an Indy error message, it is coming from the FTP server itself. Many FTPS-enabled servers expect the data connection to use the same TLS session as the control connection and/or of previous data connections. Indy's OpenSSL-based SSLIOHandler does that, but looking at the SChannel SSLIOHandler's implementation, I don't think it does.

When setting up a data connection, TIdFTP will Clone() the SSLIOHandler of the the control connection. The SChannel SSLIOHandler's implementation of Clone() simply creates a new TIdSSLIOHandlerSocketSChannel object, but does not do anything further to reuse/link the TLS session of the source object to the cloned object. Specifically, it is not sharing a credential handle across multiple connections, it is obtaining a new credential handle for each connection.

I see you have already filed a bug report with the author of the SChannel SSLIOHandler. I have commented on it as well.

Reply


Forum Jump:


Users browsing this thread: 1 Guest(s)