This document describes what the vsftpd code trusts, what it doesn't trust, and
the reasoning behind any trust decisions.

The importance of trust and trust relationships
===============================================

Imagine a largely well written and secure piece of code. Now imagine that this
piece of code delegates a task to an external program, perhaps in the name of
code reuse. Now, if this external program is sloppily coded and insecure, we've
wasted a lot of effort making our original program secure; our erroneous trust
of the buggy external program means we have a security leak, even though we
were careful in _our_ code.

There is a very similar situation with buggy library APIs. Imagine our secure
program calling some complex library function which lets the side down by
containing a security hole.

Lets put some concrete examples on the two similar above considerations. We can
even give examples in the context of FTP daemons.

1) External /bin/ls helper

A very common operation asked of FTP servers is to provide a directory listing.
Unfortunately, convention seems to be to emit the directory listing in UNIX
"/bin/ls -l" format. Even the Microsoft FTP service can be observed to do this.
When writing an FTP server for the UNIX platform, then, this leads to the
temptation to reuse /bin/ls as a child process, to avoid having to rewrite a
load of code to handle directory listings.

Even more unfortunately, FTP server writers seem to want to adopt the
versatility of the average /bin/ls implementation. This means they allow
clients to specify arbitrary parameters to /bin/ls.

By using an external /bin/ls command, we would tie the security of our FTP
server to that of the /bin/ls code. Be careful not to underestimate the amount
of code paths in /bin/ls which are explorable by a remote malicious user. GNU
/bin/ls has a myriad of options. Some of these options are complex such as -I
or the various formatting options. All it takes is a single coding flaw in the
handling of one of these options, and your FTP security is in trouble.

By using an external /bin/ls, you also inherit the risk of any dangerous or
complex APIs it uses. For example, calls to libc's complex fnmatch() or
glob() functions, which will get given arbitrary malicious user controlled
data as the search patterns. Also remember that users (and sometimes remote
users) can upload/create files, and filenames are a very prominent input
to /bin/ls.

To conclude: vsftpd has no intention of using an external /bin/ls program
because of the risks outlined above. Even if I were to audit e.g. GNU
fileutils /bin/ls, and also important parts of glibc, this would still leave
security in an unknown state on other platforms. The solution I have employed
is to write a minimal internal implementation of a /bin/ls listing generator;
it's hardly difficult. As a happy side effect, this will boost performance by
avoiding unneccesary fork()s and exec()s!

Here's some quick data about FTP servers which tend to use external ls
programs:

ftp.wuftpd.org:
ftp> ls --version
227 Entering Passive Mode (x.x.x.x.x.x)
150 Opening ASCII mode data connection for /bin/ls.
ls (GNU fileutils) 3.16
226 Transfer complete.

ftp.digital.com:
ftp> ls -v
227 Entering Passive Mode (x.x.x.x.x.x)
150 Opening ASCII mode data connection for /bin/ls.
/bin/ls: illegal option -- v
usage: ls [ -1ACFLRabcdfgilmnopqrstux ]  [files]
226 Transfer complete.

Note that /bin/ls is not the only external program invoked by common FTP
servers such as wu-ftpd. wu-ftpd also has the ability to invoke "tar" and
"gzip" on the fly, so there are trust relationships there too.


2) Complex library APIs

vsftpd is very careful to avoid using library calls which are potentially
dangerous. I would typically classify calls as dangerous if they interact
with the network non-trivially, or take malicious user supplied data and
start parsing it in a major way.

Some examples are clearly required (vsftpd avoids using any of the following):

1) fnmatch(). This is the libc glob pattern matcher. The danger comes
from the fact that the user supplies the glob pattern - "ls *.mp3" would
be a simple example. Furthermore, glob pattern matching is complex and
involves a lot of string handling.

2) gethostbyaddr(). This is a libc call to resolve an IP address to a hostname.
Unfortunately, doing this is quite complicated. When you call gethostbyaddr(),
a lot of work goes on under the covers. This usually involves making a network
call out to the DNS server, and, dangerously, parsing the response.

For clarity (and clarity is a very important part of security), all external
APIs used by vsftpd are encapsulated within two "system interaction" files,
named "sysutil.c", and "sysdeputil.c" (for the more variable/system dependent
calls). This provides a convenient audit point for ascertaining which calls
vsftpd trusts.

vsftpd-2.0.0 introduces SSL / TLS support using OpenSSL. OpenSSL is a massive
quantity of code which is essentially parsing complex protocol under the full
control of remote malicious clients. SSL / TLS is disabled by default, both
at compile time and run time. This forces packagers and administrators to make
the decision that they trust the OpenSSL library. I personally haven't yet
formed an opinion on whether I consider the OpenSSL code trustworthy.


Summary
=======

Be very aware of what APIs and/or programs you are trusting, or you might end
up creating a trust relationship which makes your program exploitable --
through no direct fault of your own.

