#991338 ftp-ssl: uploading with TLS fails after transfer

Package:
ftp-ssl
Source:
netkit-ftp-ssl
Description:
FTP client with SSL or TLS encryption support
Submitter:
Matija Nalis
Date:
2021-07-21 01:09:03 UTC
Severity:
normal
Tags:
#991338#5
Date:
2021-07-21 01:07:54 UTC
From:
To:
Dear Maintainer,

   * What led up to the situation?

Trying to upload to vsftpd server (3.0.3-12) with ftp-ssl using TLS.

   * What exactly did you do (or not do) that was effective (or
     ineffective)?

Uploading via plaintext FTP works normally. Tryed changing vsftpd options - did not help.
Fixing the ftp-ssl code helped.

   * What was the outcome of this action?

File uploads, but returns error "426 Failure reading network stream."

   * What outcome did you expect instead?

File uploads cleanly, without errors.

here is example transaction:

tekko% date > test.txt
tekko% ls -l test.txt
-rw-r--r-- 1 test test 30 Jul 21 02:34 test.txt
tekko% ftp-ssl -z secure ftp.example.org
Connected to ftp.example.org.
220 Welcome to VSFTPD
Name (ftp.example.org:test): test
234 Proceed with negotiation.
[SSL Cipher TLS_AES_256_GCM_SHA384]
200 PBSZ set to 0.
200 PROT now Private.
[Encrypted data transfer.]
331 Please specify the password.
Password:
230 Login successful.
Remote system type is UNIX.
Using binary mode to transfer files.
ftp> passive
Passive mode on.
ftp> put test.txt
local: test.txt remote: test.txt
227 Entering Passive Mode (195,190,136,132,242,251).
150 Ok to send data.
426 Failure reading network stream.
30 bytes sent in 0.00 secs (770.9705 kB/s)
ftp> dir test.txt
227 Entering Passive Mode (195,190,136,132,240,196).
150 Here comes the directory listing.
-rw-r--r--    1 ftp      ftp            30 Jul 21 02:35 test.txt
226 Directory send OK.
ftp>

I've looked up the ftp-ssl source, as well the official docs and did some debugging.

Problem seems to be that ftp-ssl is closing file descriptor before doing SSL_shutdown(),
thus losing unsent SSL data, which vsftpd then complains about.

So when SSL_shutdown() does run in ftp-ssl code, it then returns -1 as socket
is already gone.  According to the docs at https://linux.die.net/man/3/ssl_shutdown,
client should first call SSL_shutdown() (if needed twice), and only then should the
socket be closed.  Attached patch does so as documentation directs, and thus fixes
the problem for me - uploads now finish with regular "226 Transfer complete."