FTPS with Python ftplib - Session reuse required
Asked Answered
R

2

21

So, I am trying to connect to an FTP server to get directory listings and download files. But the first command after the prot_p() function is raising an exception - Producing these errors from the log:

*get* '150 Here comes the directory listing.\r\n'
*resp* '150 Here comes the directory listing.'
*get* '522 SSL connection failed; session reuse required: see require_ssl_reuse
option in vsftpd.conf man page\r\n'
*resp* '522 SSL connection failed; session reuse required: see require_ssl_reuse
 option in vsftpd.conf man page'
Traceback (most recent call last):
  File "C:\temp\download.py", line 29, in <module>
    files = ftps.dir()
  File "C:\Python27\lib\ftplib.py", line 522, in dir
    self.retrlines(cmd, func)
  File "C:\Python27\lib\ftplib.py", line 725, in retrlines
    return self.voidresp()
  File "C:\Python27\lib\ftplib.py", line 224, in voidresp
    resp = self.getresp()
  File "C:\Python27\lib\ftplib.py", line 219, in getresp
    raise error_perm, resp
ftplib.error_perm: 522 SSL connection failed; session reuse required: see requir
e_ssl_reuse option in vsftpd.conf man page

Here is the code:

from ftplib import FTP_TLS
import os
import socket

host = 'example.com'
port = 34567
user = 'user1'
passwd = 'pass123'
acct = 'Normal'

ftps = FTP_TLS()

ftps.set_debuglevel(2)

ftps.connect(host, port)

print(ftps.getwelcome())
print(ftps.sock)

ftps.auth()

ftps.login(user, passwd, acct)

ftps.set_pasv(True)
ftps.prot_p()

print('Current directory:')
print(ftps.pwd())
files = ftps.dir()

ftps.quit()

I want to do this securely, hence using FTP over TLS Explicit. I have the idea that I may need to manipulate some settings in the Socket class referenced by ftplib. Changing the settings on the server is not a possibility. I have tested the server successfully with FileZilla client, an older version of WinSCP was raising the same error - although an upgrade to the newest version fixed it.

Any ideas?

Rida answered 2/2, 2013 at 6:2 Comment(0)
B
46

It can be now easily fixed for Python 3.6+ by this class (descendant of FTP_TLS):

class MyFTP_TLS(ftplib.FTP_TLS):
    """Explicit FTPS, with shared TLS session"""
    def ntransfercmd(self, cmd, rest=None):
        conn, size = ftplib.FTP.ntransfercmd(self, cmd, rest)
        if self._prot_p:
            conn = self.context.wrap_socket(conn,
                                            server_hostname=self.host,
                                            session=self.sock.session)  # this is the fix
        return conn, size

It takes the TLS session information from the initial "control" FTP connection and reuses it also for every second "data" connection that is frequently created and closed for every new data transfer of a file body or a directory list. The reuse is advantageous for the server because it does not require a repeated TLS handshake many times. That is exactly what you did see in the message session reuse required.

Behlke answered 9/4, 2017 at 0:22 Comment(2)
Thanks for the input! Just wonder when it will finally get past Review stage from Python bug issue :-)Valse
Thanks, this helped me hotpatch an FTP TLS upload - along with #44058232Eustacia
V
9

It looks more likely a vsftpd issue than ftplib as you mention an upgrade to the newest version fixed the problem.

Provided that you cannot touch server's settings, sub-classing the FTP_TLS may help resolve your issue, although it is quite a HACK in my opinion, referenced to this SO question & answers Python FTP TLS connection issue. You can also take a look from this python bug issue 19500:

" It is reasonable for the server to insist that the data connection uses a TLS cached session. This might be a cache of a previous data
connection or of a cleared control connection. If this is the reason for the refusal to allow the data transfer, then the '522' reply
should indicate this.

Note: This has an important impact on client design, but allows
servers to minimize the cycles used during TLS negotiation by
refusing to perform a full negotiation with a previously
authenticated client."

It appears that vsftpd server implemented exactly that by enforcing the "SSL session reuse between the control and data connection".

http://scarybeastsecurity.blogspot.com/2009/02/vsftpd-210-released.html

Looking at the source of Python core library ftplib.py, there isn't any regard to the idea of SSL session reuse between data connection vs. control connection (correct me if I am wrong here. I've tried FTP_TLS.transfercmd(cmd[, rest])¶, didn't work).

This issue is well documented on other FTP clients that supports FTPS, I.E. WinSCP: https://winscp.net/tracker/668

See test log file attached. A vsftpd server with "require_ssl_reuse" set to true in vsftpd.conf would do the trick and can be reproduced.

Hope this helps.

Valse answered 19/10, 2014 at 16:34 Comment(1)
Thank you for your answer. I never had control over the FTP server configuration and have since lost access and am unable to test this solution.Rida

© 2022 - 2024 — McMap. All rights reserved.