Git Product home page Git Product logo

pyftpdlib's Introduction

 Downloads Github stars Github forks Contributors Test coverage
 Latest version Binary packages License
  Windows (Py2, Windows) Documentation Status Twitter Follow

Quick links

About

Python FTP server library provides a high-level portable interface to easily write very efficient, scalable and asynchronous FTP servers with Python. It is the most complete RFC-959 FTP server implementation available for Python programming language.

Features

  • Extremely lightweight, fast and scalable (see why and benchmarks).
  • Uses sendfile(2) (see pysendfile) system call for uploads.
  • Uses epoll() / kqueue() / select() to handle concurrency asynchronously.
  • ...But can optionally skip to a multiple thread / process model (as in: you'll be free to block or use slow filesystems).
  • Portable: entirely written in pure Python; works with Python 2.7 and 3.X using a single code base.
  • Supports FTPS (RFC-4217), IPv6 (RFC-2428), Unicode file names (RFC-2640), MLSD/MLST commands (RFC-3659).
  • Support for virtual users and virtual filesystem.
  • Flexible system of "authorizers" able to manage both "virtual" and "real" users on on both UNIX and Windows.

Performances

Despite being written in an interpreted language, pyftpdlib has transfer rates comparable or superior to common UNIX FTP servers written in C. It usually tends to scale better (see benchmarks) because whereas vsftpd and proftpd use multiple processes to achieve concurrency, pyftpdlib only uses one (see the C10K problem).

pyftpdlib vs. proftpd 1.3.4

benchmark type pyftpdlib proftpd speedup
STOR (client -> server)

585.90 MB/sec

600.49 MB/sec -0.02x
RETR (server -> client) 1652.72 MB/sec 1524.05 MB/sec +0.08
300 concurrent clients (connect, login)

0.19 secs

9.98 secs +51x
STOR (1 file with 300 idle clients)

585.59 MB/sec

518.55 MB/sec +0.1x
RETR (1 file with 300 idle clients) 1497.58 MB/sec 1478.19 MB/sec 0x
300 concurrent clients (RETR 10M file)

3.41 secs

3.60 secs +0.05x
300 concurrent clients (STOR 10M file)

8.60 secs

11.56 secs +0.3x
300 concurrent clients (QUIT)

0.03 secs

0.39 secs +12x

pyftpdlib vs. vsftpd 2.3.5

benchmark type pyftpdlib vsftpd speedup
STOR (client -> server)

585.90 MB/sec

611.73 MB/sec -0.04x
RETR (server -> client) 1652.72 MB/sec 1512.92 MB/sec +0.09
300 concurrent clients (connect, login)

0.19 secs

20.39 secs +106x
STOR (1 file with 300 idle clients)

585.59 MB/sec

610.23 MB/sec -0.04x
RETR (1 file with 300 idle clients) 1497.58 MB/sec 1493.01 MB/sec 0x
300 concurrent clients (RETR 10M file)

3.41 secs

3.67 secs +0.07x
300 concurrent clients (STOR 10M file)

8.60 secs

9.82 secs +0.07x
300 concurrent clients (QUIT)

0.03 secs

0.01 secs +0.14x

For more benchmarks see here.

Quick start

>>> from pyftpdlib.authorizers import DummyAuthorizer
>>> from pyftpdlib.handlers import FTPHandler
>>> from pyftpdlib.servers import FTPServer
>>>
>>> authorizer = DummyAuthorizer()
>>> authorizer.add_user("user", "12345", "/home/giampaolo", perm="elradfmwMT")
>>> authorizer.add_anonymous("/home/nobody")
>>>
>>> handler = FTPHandler
>>> handler.authorizer = authorizer
>>>
>>> server = FTPServer(("127.0.0.1", 21), handler)
>>> server.serve_forever()
[I 13-02-19 10:55:42] >>> starting FTP server on 127.0.0.1:21 <<<
[I 13-02-19 10:55:42] poller: <class 'pyftpdlib.ioloop.Epoll'>
[I 13-02-19 10:55:42] masquerade (NAT) address: None
[I 13-02-19 10:55:42] passive ports: None
[I 13-02-19 10:55:42] use sendfile(2): True
[I 13-02-19 10:55:45] 127.0.0.1:34178-[] FTP session opened (connect)
[I 13-02-19 10:55:48] 127.0.0.1:34178-[user] USER 'user' logged in.
[I 13-02-19 10:56:27] 127.0.0.1:34179-[user] RETR /home/giampaolo/.vimrc completed=1 bytes=1700 seconds=0.001
[I 13-02-19 10:56:39] 127.0.0.1:34179-[user] FTP session closed (disconnect).

other code samples

Donate

A lot of time and effort went into making pyftpdlib as it is right now. If you feel pyftpdlib is useful to you or your business and want to support its future development please consider donating me some money.

pyftpdlib's People

Contributors

allseeingeyetolledewesew avatar andrewshulgin avatar ankurdedania avatar d3x avatar emilv avatar evgeneoskin avatar flibustenet avatar frankkkkk avatar frankli0324 avatar giampaolo avatar gliptak avatar hakai avatar hdid avatar jasonehines avatar jloden avatar kloczek avatar lurch avatar luzfcb avatar michelepetrazzo avatar moben avatar muffl0n avatar orangetux avatar pjona avatar ponypc avatar ryanb58 avatar sbraz avatar stat1c-void avatar tahirijaz24 avatar torypages avatar yuantailing avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

pyftpdlib's Issues

Set a max number of tries for finding unique filename on STOU

From [email protected] on July 18, 2007 20:38:56

What steps will reproduce the problem?  
1. Connecting to FTPd.
2. Sending a lot of STOU requests. 

Please use labels and text to provide additional information.  
Every time a STOU is received we start an infinite while loop stopped only
when a name unique for the file is found. We should set a maximum number of
tries to create a unique filename (e.g. 99), so that we decrease the
chances of a DoS situation.

Original issue: http://code.google.com/p/pyftpdlib/issues/detail?id=25

Data channel does not respect the outgoing data buffer

From [email protected] on November 16, 2007 03:33:00

The current implementation of DTPHandler.initiate_send method doesn't look
at what is specified in ac_out_buffer_size attribute which represents the
buffer size of the outgoing data defaulting to a maximum of 8192 bytes to
send in a single socket.send() call.

Note that this only happens when sending the data by using the file
producer which uses a buffer of 65536 bytes per read().

This represents a problem when using a modified DTPHandler class having
bandwidth throttling capabilities which needs a more precise throughput
when sending the data (we practically can't set a limit smaller than 65536
bytes per seconds).

We inherited this problem from the fixed asynchat module proposed in
Python's issue #1736190 ( http://bugs.python.org/issue1736190 ) we drew on.

I've fixed this in the revision #162 by having used the buffer() builtin
for slicing the data coming from the file handler. The data is now splitted
in pieces with a lenght equal to the value of the ac_out_buffer_size attribute.

Original issue: http://code.google.com/p/pyftpdlib/issues/detail?id=50

(RFC2577) Reject PORT for privileged ports

From [email protected] on June 18, 2007 21:41:52

According to RFC 2577 [1] it's a good idea rejecting data connection when a
privileged port (< 1024) is specified in PORT command.
Since that this is just *suggested* I would rencommend the use of a
specific "permit_unprivileged_port" attribute to be added in ftp_handler
class defaulting to False.

[1] http://www.wu-ftpd.org/rfc/rfc2577.html (chapter 3)

Original issue: http://code.google.com/p/pyftpdlib/issues/detail?id=11

Provide a way to control what ports to use for passive data-transfers

From [email protected] on September 15, 2007 13:53:42

When using pyftpdlib behind a NAT (see Issue #39 ) one big problem still
exists. The passive FTP connections will use ports from 1024 and up, which
means that you must forward all ports 1024-65535 from the NAT to the FTP
server! And you have to allow many (possibly) dangerous ports in your
firewalling rules! Not a good situation. 

To resolve this, it would be reasonable having a new FTPHandler's attribute
(e.g. "passive_ports") to control what ports pyftpdlib will use for its
passive data transfers.

Original issue: http://code.google.com/p/pyftpdlib/issues/detail?id=40

Server ident shouldn't be shown in the STAT response

From [email protected] on October 24, 2007 15:18:40

A client connected to ftpd sending a STAT command will receive the
following response:

211-Python FTP server library (pyftpdlib) 0.2.0 status:
  Connected to: 127.0.0.1:21
  Logged in as: anonymous
  TYPE: ASCII; STRUcture: File; MODE: Stream
  Data connection closed.
211 End of status.

The current pyftpdlib implementation provides no easy way to modify the
server ident ("pyftpdlib 0.2.0" in this case) provided with STAT response.
It would be good adding a new global variable for users who want to modify it.

Original issue: http://code.google.com/p/pyftpdlib/issues/detail?id=43

Race condition in STOU implementation

From [email protected] on August 30, 2007 15:09:27

The logic used to find out a unique file name when processing STOU command
is unsafe and should not be used.
The fix proposed by me in Issue 25 (SVN revision #37 ) consist of first
finding out a unique file name by using os.path.exists(), and then by
creating the new file with open() builtin function.
A similar approach is also used in the current 0.1.1 pyftpdlib release.

This methodology is unsafe since the file name refers to a file that did
not exist at some point, but by the time you get around to creating it,
someone else may have beaten you to the punch.

Original issue: http://code.google.com/p/pyftpdlib/issues/detail?id=34

Maximum connections limit problem on Python 2.3

From [email protected] on October 25, 2007 16:12:54

What steps will reproduce the problem?  
1. Configuring pyftpdlib by setting maximum connections limit option using
Python 2.3:

>>> from pyftpdlib import ftpserver
>>> ftpd = ftpserver.FTPServer(('0.0.0.0', 21), ftpserver.FTPHandler)
>>> ftpd.max_cons = 256
>>> ftpd.serve_forever()
Serving FTP on 0.0.0.0:21 

What is the expected output?  


What do you see instead?  
When trying to connect from client the following exception is raised by
pyftpdlib:

Traceback (most recent call last):
  File "C:\Python23\lib\asyncore.py", line 69, in read
    obj.handle_read_event()
  File "C:\Python23\lib\asyncore.py", line 384, in handle_read_event
    self.handle_accept()
  File "C:\Python23\lib\site-packages\pyftpdlib\ftpserver.py", line 2317,
in han
dle_accept
    print self._map
  File "C:\Python23\lib\asyncore.py", line 365, in __getattr__
    return getattr(self.socket, attr)
AttributeError: '_socketobject' object has no attribute '_map' 

Please use labels and text to provide additional information.  
This happens because Python 2.3 provides a version of asyncore.dispatcher
which does not provide the _map attribute (included in Python 2.4 and
higher) which is used in pyftpdlib for getting the number of current
connected clients.
A hack around such lack should be provided to grant backward compatibility
with Python version prior to 2.4.

Original issue: http://code.google.com/p/pyftpdlib/issues/detail?id=47

Implement site-to-site FXP feature

From [email protected] on September 07, 2007 19:54:03

Description:

FXP is part of the name of a popular Windows FTP client: 
http://www.flashfxp.com . This client has made the name "FXP" commonly used
as a synonym for site-to-site FTP transfers, for transferring a file
between two remote FTP servers without the transfer going through the
client's host. Sometimes "FXP" is referred to as a protocol; in fact, it is
not. The site-to-site transfer capability was deliberately designed into
RFC 959. More info can be found here: 
http://www.proftpd.org/docs/howto/FXP.html .


Implementation:

Actually pyftpdlib does not allow site-to-site transfers.
Because of a type of attack known as the "FTP bounce" attack: 
http://www.cert.org/advisories/CA-1997-27.html ...it will reject any connection 
from/to remote IP addresses which do not
match the client's IP address.

However, some site administrators may want to allow their servers to
support site-to-site transfers. 
pyftpdlib should provide a variable to allow administrators to disable
bounce protection for cases where FXP site-to-site transfer capability is
desired.

Original issue: http://code.google.com/p/pyftpdlib/issues/detail?id=36

"Invalid REST" error in test suite test_rest_on_stor (OS X, python 2.5)

From [email protected] on July 20, 2007 07:00:42

Platform:
python 2.5.1
OS X 10.4.1 (Intel)

Steps to reproduce:
1. install SVN revision 37 2. execute test/test_ftpd.py

Error output:
....................FEFE..
======================================================================
ERROR: test_rest_on_stor (__main__.ftp_store_data)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "test/test_ftpd.py", line 419, in test_rest_on_stor
    ftp.storbinary('appe 1.tmp', f1)
  File
"/Library/Frameworks/Python.framework/Versions/2.5/lib/python2.5/ftplib.py",
line 426, in storbinary
    conn = self.transfercmd(cmd)
  File
"/Library/Frameworks/Python.framework/Versions/2.5/lib/python2.5/ftplib.py",
line 356, in transfercmd
    return self.ntransfercmd(cmd, rest)[0]
  File
"/Library/Frameworks/Python.framework/Versions/2.5/lib/python2.5/ftplib.py",
line 327, in ntransfercmd
    resp = self.sendcmd(cmd)
  File
"/Library/Frameworks/Python.framework/Versions/2.5/lib/python2.5/ftplib.py",
line 241, in sendcmd
    return self.getresp()
  File
"/Library/Frameworks/Python.framework/Versions/2.5/lib/python2.5/ftplib.py",
line 207, in getresp
    resp = self.getmultiline()
  File
"/Library/Frameworks/Python.framework/Versions/2.5/lib/python2.5/ftplib.py",
line 193, in getmultiline
    line = self.getline()
  File
"/Library/Frameworks/Python.framework/Versions/2.5/lib/python2.5/ftplib.py",
line 183, in getline
    if not line: raise EOFError
EOFError

Original issue: http://code.google.com/p/pyftpdlib/issues/detail?id=26

Some session attributes aren't resetted on REIN

From [email protected] on August 14, 2007 19:42:55

According to RFC 959 [1] a REIN command should flush all I/O and account
information, except to allow any transfer in progress to be completed.  All
parameters must be resetted to the default settings and the control
connection should be left open.  This is identical to the state in which a
user finds himself immediately after the control connection is opened.

Current pyftpdlib release should also reset "restart_position" and
"current_type" FTPHandler's class attributes, actually not resetted, and,
if no data transfer is in progress, it should close the existing data
channel instance, if any.

[1] http://www.faqs.org/rfcs/rfc959.html (chapter 4.1.1).

Original issue: http://code.google.com/p/pyftpdlib/issues/detail?id=33

Stop buffering if extremely long lines are received

From [email protected] on May 18, 2007 22:59:01

Method "collect_incoming_data" of "ftp_handler" class should stop buffering
if received lines are too long (possible Denial-of-Service attacks).
Patch:


class ftp_handler(asynchat.async_chat):

    [...]

    def collect_incoming_data(self, data):        
        self.in_buffer = self.in_buffer + data

+        if len(self.in_buffer) > 2048:

+            self.in_buffer = ""


    def found_terminator(self):        
        line = self.in_buffer.strip()

    [...]

Original issue: http://code.google.com/p/pyftpdlib/issues/detail?id=3

Implement FEAT command

From [email protected] on October 22, 2007 00:43:55

It is not to be expected that all servers will necessarily support all of
the new commands defined in all future amendments to the FTP protocol.  In
order to permit clients to determine which new commands are supported by a
particular server, without trying each possible command, FEAT command was
added to the FTP command repertoire. It is described in RFC 2398 [1].

FEAT response must appear as the following:

211-Extensions supported:
 CMD1
 CMD2
 ...
211 End.

FEAT must be accepted also when the user is not yet authenticated.
Commands subsequent RFC959 implemented in the current pyftpdlib version are
MDTM and SIZE.

[1] http://www.networksorcery.com/enp/rfc/rfc2389.txt

Original issue: http://code.google.com/p/pyftpdlib/issues/detail?id=42

Problem when LISTing "broken" symbolic links

From [email protected] on November 01, 2007 17:28:01

What steps will reproduce the problem?  
1. Create a symbolic link.
2. Remove the file pointed by the symbolic link.
3. Run pyftpdlib.
4. Issue a LIST command for the directory containing the "broken" symbolic
link. 

What is the expected output?  


What do you see instead?  
Client will receive a "550 No such file or directory" error message because
os.stat() raises an exception when trying to follow the "broken" symbolic
link contained in that directory.
Reproducing the problem is quite easy:

root@uds:~# touch foo 
root@uds:~# ln -s foo x 
root@uds:~# rm foo 
root@uds:~# python 
Python 2.5.1 ( r251 :54863, May  2 2007, 16:56:35) 
[GCC 4.1.2 (Ubuntu 4.1.2-0ubuntu4)] on linux2 
Type "help", "copyright", "credits" or "license" for more information. 
>>> import os 
>>> os.stat('x') 
Traceback (most recent call last): 
  File "<stdin>", line 1, in <module> 
OSError: [Errno 2] No such file or directory: 'x' 

This is not reasonable since for a single "broken" symbolic link we lose
the remaining listing of all other files in that directory.
To avoid such problem my proposal is using use os.lstat() when os.stat() fails:

>>> os.lstat('x') 
(41471, 425170L, 2049L, 1, 0, 0, 3L, 1193652432, 1193651349, 
1193651349)

Original issue: http://code.google.com/p/pyftpdlib/issues/detail?id=49

test suite failure in test_stou() - incorrectly parsed STOU response

From [email protected] on July 20, 2007 09:37:17

What steps will reproduce the problem?  
1. run test suite prior to Revision 40 Running through the test suite on a 
Linux box to compare with OS X results,
there was a failure in test_stou() due to the filename being calculated as:

        filename = ftp.sendcmd('stou')[4:]

This caused a later call to os.remove to fail while trying to remove the
file "/path/to/my/test/suite/FILE: .0". The response from sendcmd is
actually in the below format:

        #filename comes in as  150 FILE: $filename

so I made the following change to the test suite to correctly remove the
prefix and also make it a little clearer how the filename was being parsed:

        filename = ftp.sendcmd('stou').replace('150 FILE: ', '')

Original issue: http://code.google.com/p/pyftpdlib/issues/detail?id=27

ABOR not checked in test suite

From [email protected] on July 23, 2007 19:55:05

The ABOR command is not currently tested in the unit test implementation.
The unit tests should be updated to include testing for various ABOR use
cases: 

Case 1: ABOR while no data channel is opened: respond with 225.

Case 2: user sends a PASV, a data-channel socket is listening but not
connected, and ABOR is sent: close listening data socket, respond with 225.

Case 3: data channel opened with PASV or PORT, but ABOR sent before a data
transfer has been started: close data channel, respond with 225.

Case 4: ABOR while a data transfer on DTP channel is in progress:
close data channel, respond with 426, respond with 226.

Original issue: http://code.google.com/p/pyftpdlib/issues/detail?id=28

Permit STAT also if user isn't authenticated yet

From [email protected] on July 13, 2007 18:59:41

What steps will reproduce the problem?  
Using STAT when user is not authenticated yet. 

What is the expected output?  


What do you see instead?  
STAT request is rejected with a "530 Log in with USER and PASS first" response. 

Please use labels and text to provide additional information.  
It would be better accepting STAT even if user isn't authenticated yet.
At the same time we should reject argumented STAT requests since that we
still don't want to provide directory LISTing over the command channel.

Original issue: http://code.google.com/p/pyftpdlib/issues/detail?id=21

Provide a compact list of recognized cmds on HELP

From [email protected] on July 25, 2007 02:13:44

Currently, the HELP command provided with no arguments lists all the
recognized commands and their description:

        ABOR  abort data-channel transfer
        ALLO  allocate space for file about to be sent (obsolete)
        APPE  resume upload
        CDUP  go to parent directory
        CWD   change current directory
        ...

Most FTPd implementations provide a simplified command listing with only
the command names: 

  ABOR    ALLO    APPE    CDUP    CWD     DELE    HELP    LIST
  MDTM    MKD     MODE    NLST    NOOP    PASS    PASV    PORT
  PWD     QUIT    REIN    REST    RETR    RMD     RNFR    RNTO
  ...

This would have our implementation match the formatting commonly in use by
most FTP servers, and will be easier for the client to parse.

Original issue: http://code.google.com/p/pyftpdlib/issues/detail?id=31

Socket's reuse_address used after the socket's binding

From [email protected] on May 26, 2007 16:22:46

In "serve_forever" method of "ftp_server" class "self.set_reuse_addr()" is
erroneously used *after* having tried to bind the ftpd socket and not *before*.
By calling asyncore.dispatcher object's set_reuse_addr() method we tell
ftpd to mark the socket as re-usable (setting the SO_REUSEADDR option).
Patch:


class ftp_server(asynchat.async_chat):
    """The base class for the backend."""

    def __init__(self, address, handler):
        asynchat.async_chat.__init__(self)
        self.address = address
        self.handler = handler
        self.create_socket(socket.AF_INET, socket.SOCK_STREAM)  

+        if os.name == 'posix':
+            self.set_reuse_addr()  

        self.bind(self.address)
        self.listen(5)

    def serve_forever(self): 
        log("Serving FTP on &#37;s:&#37;s." &#37;self.socket.getsockname())

-         if os.name == 'posix':
-             self.set_reuse_addr()

        # here we try to use poll(), if it exists, else we'll use select()
        asyncore.loop(timeout=1, use_poll=True)

Original issue: http://code.google.com/p/pyftpdlib/issues/detail?id=4

Provide permissions, owner, and group for files on UNIX platforms

From [email protected] on October 30, 2007 14:47:58

Currently, pyftpdlib does not fetch real permissions, owner and group for
files and folders, instead using default fake values. Since the permissions
and owner/group are not applicable in the same fashion on Windows, such
information is currently UNIX only.

The format_list() method of AbstractedFS should be modified to fetch the
owner/group names for each file and the permissions for owner/group/world
to match the standard "ls" output on UNIX platforms. Platforms where the
necessary modules do not exist should fall back on the default values we
use currently.

Original issue: http://code.google.com/p/pyftpdlib/issues/detail?id=48

Memory leak occurs on KeyboardInterrupt / SIGTERM

From [email protected] on July 13, 2007 19:33:46

What steps will reproduce the problem?  
1. Starting FTPd.
2. Connecting one or more client(s).
3. Stopping FTPd via KeyboardInterrupt or SIGTERM. 

What is the expected output?  


What do you see instead?  
A memory leak occurs. It may be detected by using:
>>> import gc
>>> gc.set_debug(gc.DEBUG_LEAK) 

Please use labels and text to provide additional information.  
When FTPd is stopped via KeyboardInterrupt or SIGTERM we should first close
all existent channels before definitively exit.

Original issue: http://code.google.com/p/pyftpdlib/issues/detail?id=22

Support for FTP servers behind NAT

From [email protected] on September 15, 2007 12:55:42

A server-side problem that can occur is when a client is trying to access
an FTP server on an internal network protected by a routing device. 
Because a server response from PASV includes an IP address and a port
number, if this IP address corresponds to a private network then the client
will not be able to connect to that private address.

    Client:  PASV
    Server:  227 Entering Passive Mode (10,0,0,1,204,173)

If left unaltered, the client would try to connect to port 52397 on the
private IP address 10.0.0.1 when in reality it should be connecting to the
external IP address of the routing device (e.g. 72.14.221.104).

A practice commonly used by most ftp servers is permitting to configure the
IP address response coming along PASV response request replacing it with
the NAT's IP address. It would be reasonable having the same opportunity in
pyftpdlib.

Original issue: http://code.google.com/p/pyftpdlib/issues/detail?id=39

PASS should be rejected if user is already authenticated

From [email protected] on July 13, 2007 20:30:44

What steps will reproduce the problem?  
1. Connecting to FTPd.
2. Logging in by using USER <username>, PASS <password>.
3. Providing PASS <password>. 

What is the expected output?  


What do you see instead?  
When PASS <password> is received for the second time we expect some kind of
error response while we get "230 User logged in" again.

Original issue: http://code.google.com/p/pyftpdlib/issues/detail?id=23

Wrong CDUP response code

From [email protected] on July 06, 2007 01:01:43

What steps will reproduce the problem?  
1. Sending a 'CDUP' command to FTP server when the current working
directory is different from '/'. 

What is the expected output?  


What do you see instead?  
According to RFC959 we expect a 200 or 250 response ( RFC959 says that code
200 is required but it also says that CDUP uses the same codes as CWD)
while we get 257.

Original issue: http://code.google.com/p/pyftpdlib/issues/detail?id=14

STOU should follow specifications defined into RFC1123

From [email protected] on June 07, 2007 00:24:35

STOU command implementation should follow specifications defined into the 
newer RFC1123 [1] which are different from those defined into RFC959 [2].
The 250 positive response indicated into RFC959 has been declared 
incorrect into RFC1123 that requires 125/150 instead.
Moreover RFC1123 wants an additional "FILE: " string to be returned into 
response:

125 FILE: <filename>
150 FILE: <filename>



[1] http://www.faqs.org/rfcs/rfc959.html (chapter 4.1.3)
[2] http://www.faqs.org/rfcs/rfc1123.html (chapter 4.1.2.9)

Original issue: http://code.google.com/p/pyftpdlib/issues/detail?id=8

Error on QUIT when user is not yet authenticated

From [email protected] on October 20, 2007 01:35:16

What steps will reproduce the problem?  
1. Connect to ftpd.
2. Send QUIT command before authenticating. 

What is the expected output?  


What do you see instead?  
The following exception is raised:

Traceback (most recent call last):
  File "asyncore.py", line 68, in read
    obj.handle_read_event()
  File "asyncore.py", line 390, in handle_read_event
    self.handle_read()
  File "asynchat.py", line 137, in handle_read
    self.found_terminator()
  File "/usr/lib/python2.5/site-packages/pyftpdlib/ftpserver.py", line
1134, in found_terminator
    method(arg) # call
  File "/usr/lib/python2.5/site-packages/pyftpdlib/ftpserver.py", line
1409, in ftp_QUIT
    msg_quit = self.authorizer.get_msg_quit(self.username)
  File "/usr/lib/python2.5/site-packages/pyftpdlib/ftpserver.py", line 330,
in get_msg_quit
    return self.user_table[username]['msg_quit']
KeyError: '' 

Please use labels and text to provide additional information.  
This happens because we ask the authorizer to tell us which is the user's
quitting message while no user is authenticated.

Original issue: http://code.google.com/p/pyftpdlib/issues/detail?id=41

Wrong HELP response code on unknown arg command

From [email protected] on October 24, 2007 16:15:53

When a HELP command is issued with an argument ftpd must return the help of
that particular command.
If such command is not valid (i.e. unknown) the actual pyftpdlib
implementation respond with 500 "Syntax error, command unrecognized" while
it would be more appropriate responding with 501 "Syntax error in
parameters or arguments" or 502 "Command not implemented".

Original issue: http://code.google.com/p/pyftpdlib/issues/detail?id=45

FTPServer.py provides no way to limit the number of acceptable connections (DoS vulnerability)

From [email protected] on June 06, 2007 00:07:20

FTPServer.py, independently if asyncore main polling loop uses select() or
poll(), raises an exception and block the loop when a high number of
simultaneous connections to handle simultaneously is reached. The number of
maximum connections is system-dependent as well as the type of error
raised. [1]

The problem with the base asyncore is that it provides no way to limit the 
number of acceptable connections. A way to limit them should be implemented
into FTPServer.py to avoid possible Denial of Service attacks.

Don't know if it is within the realm of problems that should be dealt with
by base FTPServer.py but since that a lot of FTP servers permit it, I find
it reasonable that FTPServer.py could provide a way to:
- configure/limit the number of maximum acceptable connections.
- (optionally) configure/limit the maximum number of clients which may be
connected from the same source internet address.

[1] A discussion about it can be found on Python SF tracking system where I
submitted a bug-report: 
https://sourceforge.net/tracker/?func=detail&atid=105470&aid=1685000&group_id=5470
 Comments are apreciated.

Original issue: http://code.google.com/p/pyftpdlib/issues/detail?id=5

Problems with pyftpdlib and Python CE

From [email protected] on July 15, 2007 22:41:33

What steps will reproduce the problem?  
1. install pyftpdlib
2. Run basic_ftp 
3. Try to change directory on a client ftp 

What is the expected output?  


What do you see instead?  
The Konqueror ftp client displays directory does not exist What version of the 
product are you using? On what operating system? Verion - pyftpdlib_0.1.1
OS - windows mobile 6
python version - Python-2.5-20061219 (Python CE 
[ http://pythonce.sourceforge.net/ ] ) Please provide any additional 
information below.

Original issue: http://code.google.com/p/pyftpdlib/issues/detail?id=24

Anonymous user write access

From [email protected] on September 10, 2007 06:43:10

Is it possible to make anonymous write access explicitly configurable with
necessary security warnings all over the place?

I use the library as a quick way to pass files from and to virtual machines
running on the host in secured environment, so there is no need in password
complication. I would like to avoid patching libraries and typing extra
options besides basic "ftp get ftp://host/file

Original issue: http://code.google.com/p/pyftpdlib/issues/detail?id=38

Extending compatiblity with older asyncore/python versions

From [email protected] on July 10, 2007 03:35:34

By using Python versions prior to 2.4 pyftpdlib fails starting on systems
where poll() is not available.

<snippet>
Traceback (most recent call last):
   File "/ffs/lib/python2.3/site-packages/pyftpdlib/FTPServer.py", line
1206, in serve_forever
    asyncore.loop(timeout=1, use_poll=True)
  File "/tgtsvr/lib/python2.3/asyncore.py", line 193, in loop
  File "/tgtsvr/lib/python2.3/asyncore.py", line 128, in poll2
ImportError: No module named poll
</snippet>

This does not happen with newer asyncore versions (included with Python 2.4
and higher) which first check if poll() is available or not, in which case
select() is silently used.
Instead of telling asyncore to use poll by default we should first check if
poll is available or not by simply using the following statement:

>>> asyncore.loop(timeout=1, use_poll=hasattr(asyncore.select, 'poll'))

This should grant backward compatibility with older asyncore versions
included with Python 2.2, 2.3 and 2.4.


Thanks to Greg Copeland (GCopeland AT efjohnson DOT com) for having
submitted such report.

Original issue: http://code.google.com/p/pyftpdlib/issues/detail?id=16

Path traversal vulnerability

From [email protected] on June 15, 2007 22:35:56

PATH TRAVERSAL VULNERABILTY

Most ftp filesystem commands are dangerously affected by path traversal.
The reason of this, is poor path filtering in 'normalize' and 'translate' 
methods of class 'abstracted_fs' (lines 1595-1625).

Tests have been conducted on pyftpdlib 0.1.1 on both windows xp and ubuntu 
7.04, revealing the same vulnerability.

Issuing following commands, user root's parent directory will erroneously 
be listed, giving access to forbidden parts of filesystem.

CWD /
LIST ..

Same problem affects commands like STOR and RETR, allowing an attacker to 
retrieve or upload arbitrary system files. This would be only limited by 
rights under which the server is running. For any reason user must be able 
to gain access to those areas.

In order to solve the problem, I've entirely rewritten both vulnerable 
methods.
I think this solution should be robust enough to avoid any path traversal 
issue.

Attachment: patch.py

Original issue: http://code.google.com/p/pyftpdlib/issues/detail?id=9

Asking for subversion repository support

From [email protected] on June 30, 2007 00:07:33

What steps will reproduce the problem?  
1. svn checkout http://pyftpdlib.googlecode.com/svn/trunk/ pyftpdlib 

What is the expected output?  


What do you see instead?  
Instead of a checked out copy of the source, I get an empty pyftpdlib
directory with only a .svn folder inside it What version of the product are you 
using? On what operating system? OS X client 

Please provide any additional information below.  
Revision 33 according to the checkout

Original issue: http://code.google.com/p/pyftpdlib/issues/detail?id=13

Wrong response on rejected data connection

From [email protected] on October 24, 2007 16:39:19

When a PASV command is issued by client a passive data socket is opened for
accepting the incoming data connection.
If FXP "site-to-site" feature is disabled and the resulting connection
comes from a remote IP address which does not match the client's IP address
a 421 "Service not available, closing control connection." is returned
dropping the foreign connection.

This is a wrong response type since RFC 959 specifies that this response
code type may be returned to any command if the service knows it must shut
down (while it doesn't). Moreover both command and data channels *won't* be
closed.

A 425 "Can't open data connection." would be a more appropriate response type.

Original issue: http://code.google.com/p/pyftpdlib/issues/detail?id=46

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.