Blog‎ > ‎

Python 3.2 MS FTPS/SSL/TLS lockup & fix

posted Nov 28, 2012, 8:51 AM by Sami Lehtinen   [ updated Dec 1, 2012, 2:17 AM ]
Had not so interesting debugging session. For some reason Python 3.2 ftplib.FTP_TLS doesn't work too well with MS FTP server when using explicit FTP(S)/TLS.
*get* '227 Entering Passive Mode (###,###,###,###,###,###).\n'
*resp* '227 Entering Passive Mode (###,###,###,###,###,###).'
*cmd* 'STOR __TEMP__b6ef0ade__'
*put* 'STOR __TEMP__b6ef0ade__\r\n'
*get* '125 Data connection already open; Transfer starting.\n'
*resp* '125 Data connection already open; Transfer starting.'
*exception* Transfer time out 

All that when calling ftplib.storbinary('STOR '+filename,file_handle)
Funny part is that everything did seem to work well except storbinary. For some unknown reason storbinary just always timed out, even if file was very small and timeout was something like 10 minutes. After checking detailed protocol debug logs, I found out that transfer actually finished. But it was  actually conn.unwind() which failed.
Quote from Python documentation:
Performs the SSL shutdown handshake, which removes the TLS layer from the underlying socket, and returns the underlying socket object. This can be used to go from encrypted operation over a connection to unencrypted. The socket instance returned should always be used for further communication with the other side of the connection, rather than the original socket instance (which may not function properly after the unwrap).

That caused whole FTP session to timeout and fail. After a while I tried my own version of ftplib, which just rems two lines from source (767,768).
766:                # shutdown ssl layer
767:                if isinstance(conn, ssl.SSLSocket):
768:                    conn.unwrap()

Proper fix would be naturally fixing the conn.unwarp() function. I really wonder if someone else has had the same problem, with other SSL/TLS realated Python programs.
For some unknown reason with MS FTP(S) server when storing data that row 768 hangs forever. I don't know why, but after this change everything works as I expected. Funny thing is that all other parts (retrbinary, ls, etc) work without this issue, it's only storing data when it fails.
I naturally tested this with my on ftp server and test server using filezilla server, and it does not require that change. So in case you have problem when storing binary data with Microsoft FTP Server and Python FTPS, just fix that. Then it will work.

RFC 4217 - Securing FTP with TLS
kw: hangs, doesn't work, fail, fails, ftp, ftpes, implicit, explicit, encryption, tls, python, server, stor, store, send, transmit, save, send, file, files, data, binary, upload, ftplib