1

I used the filezilla server to create the ftp server. The ssl option is open on ports 21 and 990. I tried using the filezilla client to upload and download the file is still working well.I try upload file to FTP server use ftplib. Here my code:

from ftplib import FTP_TLS, FTP
import socket
import ssl

file = open('test.py','rb')

ftps = FTP_TLS()
ftps.set_debuglevel(2)
s = ftps.connect(host='192.168.1.102', port=21)
ftps.login(user="xxx", passwd="xxxxxx")
ftps.prot_p()
ftps.storbinary("STOR test.py", file)

And get error :

*get* '227 Entering Passive Mode (192,168,1,102,19,170)\r\n'
*resp* '227 Entering Passive Mode (192,168,1,102,19,170)'
*cmd* 'STOR test.py'
*put* 'STOR test.py\r\n'
*get* '150 Opening data channel for file upload to server of "/test.py"\r\n'
*resp* '150 Opening data channel for file upload to server of "/test.py"'
Traceback (most recent call last):
  File "ImplicitFTP.py", line 49, in <module>
    ftps.storbinary("STOR test.py", file)
  File "C:\Python27\lib\ftplib.py", line 760, in storbinary
    conn = self.transfercmd(cmd, rest)
  File "C:\Python27\lib\ftplib.py", line 376, in transfercmd
    return self.ntransfercmd(cmd, rest)[0]
  File "C:\Python27\lib\ftplib.py", line 713, in ntransfercmd
    server_hostname=self.host)
  File "C:\Python27\lib\ssl.py", line 363, in wrap_socket
    _context=self)
  File "C:\Python27\lib\ssl.py", line 611, in __init__
    self.do_handshake()
  File "C:\Python27\lib\ssl.py", line 840, in do_handshake
    self._sslobj.do_handshake()
ssl.SSLEOFError: EOF occurred in violation of protocol (_ssl.c:661)

Please help me. Thanks

  • 1
    There are [several similar posts](https://www.google.com/search?q="EOF+occurred+in+violation+of+protocol"+python+storbinary+ftps+site%3Astackoverflow.com). There can be several reasons for this problem but you don't provide enough information to dig further. Please check the existing posts for possible solutions to your problem. If none is found please provide enough details on how to reproduce the problem in your specific case, i.e. version of Python, OpenSSL and give access this specific server or another server which shows the same problem. – Steffen Ullrich Dec 04 '17 at 06:25
  • Also server-side log would help. – Martin Prikryl Dec 04 '17 at 07:41

1 Answers1

2

The problem is probably that the FTP server requires that the TLS session in the new data channel is the same as the control channel. This has not been fixed in Python 3.7. Subclass ftplib.FTP_TLS as in the solution found here https://stackoverflow.com/a/43301750 with a small fix by me:

import ftplib


class ReusedSslSocket(SSLSocket):
    def unwrap(self):
        pass


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)  # reuses TLS session            
            conn.__class__ = ReusedSslSocket  # we should not close reused ssl socket when file transfers finish
        return conn, size

Use it like this:

ftps = MyFTP_TLS()
AndersTornkvist
  • 2,610
  • 20
  • 38