What is this?
=============

This is a set of replacement source files for the popular Washington University
enhanced FTP daemon, designed to fix bugs and increase security.  Many sites
are already running the current version 2.4 of this daemon because it is
considered more flexible and secure than the stock FTP servers that vendors
provide.  It is also being included as the standard "ftpd" in several freeware
Unix variants.

But there are still several problems with WU-ftpd-2.4.  Most serious, and
this problem exists in virtually ALL FTP servers, is the ability for an
anonymous user to make the server connect to an arbitrary port on an arbitrary
machine and pass data in one direction or the other.  This allows a whole
variety of annoyance and denial-of-service attacks, and in some cases could
allow unintended access to other machines.  Selection of data ports has
therefore been restricted in this version.

Another problem is with the extensions to the program themselves.  The "SITE"
command has received particular attention as being a potential security hole. 
File access permission checks pass through a large and complex body of code
that to this day is still not well-proven.  Part of this replacement kit allows
disabling this extra "extension" code for situations that don't need it --
notably, public FTP servers that organizations place out on the net for anyone
to retrieve files from.  Many of the extensions serve little or no purpose for
public FTP servers, although they may be of some use to people inside an
organization.  This kit allows compile-time disabling of the more questionable
parts of this extension code, and a default state of not using the rest of it.

Optional support for S/Key has been added.

Along the way, several outright bugs have been fixed, and some changes and new
code from a prerelease "Debian" Linux release merged in.  The exact changes to
the package are detailed below.  Please try to understand these changes, and
why they are there, before using this package.

Instructions:
=============

Un-tar the original wu-ftpd-2.4 distribution.  It creates a subdirectory for
itself, wu-ftpd-2.4/.  If you already have the source exploded somewhere else
and planned on using that, it is actually safer to create a new tree from the
original .tar.Z.

CD into the wu-ftpd-2.4/ subdirectory.

Un-tar the fix-kit.  This replaces various files in the source tree.  To see
the modifications, un-tar the fix-kit into some other directory first and
diff the trees.

If you want to build in S/Key support, skip down to the "Building S/Key"
section below.

Figure out what kind of system you need to build for, by typing "./build help"
and reading through the alternatives.  Let's assume you pick "foo".

Run the build script with a Magic Argument, by typing "./build fixed foo".
The "fixed" argument causes the script to pause in the middle and give you a
shell prompt.  This is a bit of a kludge, but seems the least painful way to
make this work without changing ALL the makefiles.

This shell is in the src/ subdirectory, so edit Makefile and make any of the
following changes:

	add -DPARANOID to CFLAGS to disable questionable functions.
	add -DANON_ONLY to CFLAGS if you're building an anonymous-only server.
	add -DSKEY to CFLAGS, and -lskey to LFLAGS, to add s/key support.
		Make sure skey.h is present in the src/ directory as well.
		If you REALLY want to use regular passwords, comment out the
		line mentioned in ftpd.c that normally disallows them.
	Arranging for static linking is recommended -- add whatever is
		appropriate for your site to LFLAGS.

Write the changed file and exit the shell, and the build will continue and
leave "ftpd" and related programs in both the src/ and bin/ subdirectories.
[They are linked to each other, really.]

If you want to build some different versions, for example with ANON_ONLY for
your "outside" service and an S/Key enabled one for "inside", you don't need
to run "build" again since you've already selected your Makefiles.  It is
faster to:

	cd to the src/ subdirectory
	change the Makefile as you wish
	make clean
	make

Place your built "ftpd", or multiple instances thereof, wherever you normally
keep the running daemon.  Note that the functions of the -a, -l, and -L command
line switches now defaults to TURNED OFF, so you may need to update your
inetd.conf.  The major change from the Debian release is the addition of the
"noretrieve" keyword in the ftpaccess file; there is also an updated manpage
describing it.

Building S/Key:
===============

You should be able to use any of the s/key distributions that let you build
the "libskey.a" library.  If you don't have one already, you should be able
to get one from the same site you got this fix-kit.

Build libskey.a.  For Hobbit's kit, use "make <systype> ALL=libskey.a".  Add
"MD=5" to this if you want to build an MD5 version.  Note that <systype> in
this case is NOT the same as the systype argument to wu-ftpd "build"!  For
any other packages, see the instructions that come with them.

Copy libskey.a to wu-ftpd-2.4/support, and skey.h to wu-ftpd-2.4/src.

Go back up and continue with the main build instructions.

Summary of changes:
===================

Lifted from the Debian wu-ftpd-2.4-4 release with little or no change:
  doc/ftpaccess.5
  doc/ftpd.8
  config/config.lnx
  config/config.s41
  src/access.c
  src/acl.c
  src/ftpcount.c
  src/ftpshut.c
  src/hostacc.c
  src/logwtmp.c

build: added a kludge for enabling these changes, by spawning a shell.
Added specific support for FreeBSD 2.0.  Also, copy the Makefiles and config.h
instead of hardlinking them, so that edits don't trash the original copies!

support/authuser.c: limit sscanf() of identd strings.

support/makefiles/*: minor changes to a couple of system-specific Makefiles.

*NOTE: everything following is under src/.

extensions.c: [Debian -- "noretrieve" ACL keyword handler, NULL fixups]

extensions.c: Fix losing null dereference in Debian checknoretrieve().

extensions.c: #ifdef PARANOID -- disallow file deletion completely.

ftpcmd.y: [Debian -- "bison" patch for linux just moved some decls around]

ftpcmd.y: check PORT command against a bunch of things: being logged in,
the client's source address, and the actual port number 1024 or greater.
See discussion of ports below.

ftpcmd.y: require login before various other things work: PASV, RNTO

ftpcmd.y: #ifdef PARANOID -- disable, trap, and log all SITE commands.
Comments withheld about the lineage of whoever cooked up *that* gem.

ftpd.c: [Debian -- support "noretrieve" ACL keyword; misc NULL fixups]

ftpd.c: preload assorted variables with reasonable values.  Globalize
guestpw and authuser and update them so all routines can access them for
correct logging.

ftpd.c: disallow "re-login".

ftpd.c: #ifdef ANON_ONLY -- only allow anonymous logins.  Designed for the
ftpd you hang out on your external machine.

ftpd.c: various places -- if told not to use the "ftpaccess" file, genuinely
don't use routines that deal with it at all.  [May save some of our butts
when someone finds a bug in the extensions code!]

ftpd.c: #ifdef SKEY, added s/key functionality.  The challenge emerges where
the "Password required for username" response is normally sent.

ftpd.c: add endspent() to the shadow code, per Marek M.

ftpd.c: Flag attempts to exploit the trojanized 2.2c version.

ftpd.c: #ifdef STUPID_SPRINTF -- break up big "sprintf" for xferlog into two
pieces.  On some systems, sprintf is BROKEN.  If you're using xferlog and your
ftpd crashes right after a transfer, you probably need this.

ftpd.c: #ifdef PARANOID, disable file overwriting, with either "put" or
"rename".

ftpd.c: Fix an ACL bug in renamefrom().  Doing two renames in a row would
bypass the setting in the ACL file...

ftpd.c: call realpath() to get current wd.

ftpd.c: close data ports upon exiting, and close old PASV port if told to
open a new one.  See note below on ports.

newvers.sh: include tiny little advertisement.

makefiles/Makefile.lnx: Mostly Debian; add -static, remove -DDEBUG, put
in the "bison fix".

makefiles/Makefile.fbs: Add for FreeBSD 2.0; slight mod of "bsd".

config/config.fbs: config.h for Freebsd 2.0.  Contains a hack to work around
the fact that freebsd stdlib.h comes with a realpath() and the define in
ftpd.c conflicts with it.  See note below about realpath().

config/config.lnx: Debian version, with the same realpath() hack added.
Linux has trouble with this too, but in unistd.h.  Put "realpath" back into
SRCS and OBJS definitions.

pathnames.linux: From Debian.  Use this as a starting point for customizing
pathnames.h on linux.  A remaining deficiency is that NONE of the sources even
*try* to reference the /usr/include/paths.h that many systems now have.

Notes:
======

Per a security advisory in early June 1995, make SURE your definition of
_PATH_EXECPATH is set to "/bin/ftp-exec" rather than "/bin" in whatever
pathnames.h you wind up building with.  This closes a potential "get-root"
hole that is present in several Linux distributions.  To be even more sure,
prohibit any use of SITE commands.

While looking for previously-done work for Linux compatibility, I ran across
an improved distribution from the Debian tree on tsx-11.mit.edu.  I have merged
those changes into this code as listed above.  Besides the "noretrieve"
keyword, most of the Debian changes are NULL fixups, where NULL is properly
changed to '\0' or 0.  Various #includes of <stdlib.h> and/or <unistd.h> have
been moved out of individual source files and into config.h.

If your ftp client has trouble with s/key, it may be because it truncates
passwords to 8 characters before sending them to the server.  SunOS "ftp"
does this, for example.  Get around this by using quoting:

	ftp> quote "user foobar"
	331 [s/key 97 ts04745] required for foobar.
	ftp> quote "pass lays joke hum sear woo rail"
	220 User foobar logged in.

Many systems now have a library realpath() function, which conflicts with the
one that comes with ftpd.  However, the version that comes with ftpd is aware
of its environment and briefly sets its effective UID to root to try and get
its working directory.  This is actually more useful if you have an "opaque"
directory that is mode xx1 or xx3, because although trying to read or "ls"
the directory will fail, ftpd can always determine where it is.  The "opaque"
directory is useful as a drop-off point for files intended for one recipient --
the name of the file is effectively a password for it.  To avoid the
compilation conflict, add "#define realpath realpath_on_steroids" to config.h
and use the realpath() you have the source for.

The supplied logwtmp() function doesn't work on Solaris and perhaps other
SV variants.  Swapping in Wietse Venema's sys4wtmp.c for logwtmp.c seems to
do the trick.  You can get this from his logdaemon package.  I'm glad that
*someone* understands this WTMPX idiocy, because I'm *still* having trouble
with it.  And every major vendor insists on doing it differently...

There are MYRIAD possibilities for the port-bouncing attack.  With a standard
ftpd, anyone has at their disposal a TCP socket on a "reserved port", which
some protocols are still relying on for security, and this socket can be
connected to anywhere else on the net and data passed through [albeit only in
one direction, goverened by use of STOR or RETR].  [It helps if there is a
writeable directory on the server somewhere.]

Consider these few examples.  STORing a file from another machine's "chargen"
port [or even the server's own port] will quickly fill the server's disk space.
RETRing a file containing an SMTP transaction to someone's mailer port could
allow fake mail that is virtually untraceable. Some rsh or rlogin
implementations may be weak and accept connections from port 20, and some sites
trust their firewall machines with r-access.  Stuffing an arbitrary .tar.Z down
someone's X port can't be too healthy.  You can probably cook up a hundred
other fun uses for this.  The fix is to only allow PORT commands back to the
client machine, and only on "high" ports.  Those that would argue that this
Breaks the Holy Protocol are invited to read the "fix-kit overview" and run
whatever Holy FTP Server they prefer.

Another problem was observed in the implementation of PASV.  This command
tells the server to open a listening port on its end, and expect the client
to connect to it for data transfer.  The problem was that once these sockets
were opened for listen, they were never closed, although they would accept
connections AND DATA anyway.  A simple program to read the port numbers,
connect to them, and fill the receive queues can easily crash the server
machine when it runs out of network data buffers.  PASV now cleans up after
itself, and ftpd also closes these ports when it exits.

You may need to put -DNO_MALLOC_PROTO in your chosen support/ Makefile, as
well as refer to the note about "arpa/ftp.h" in the INSTALL document.

Fixing this thing was a pain.  A lot of it reads like a second-rate undergrad
thesis, there is still plenty of sloppy code kicking around, configuration is
clumsy, and little thought seems to have been given towards true portability. 
I've gone after what I consider important, and hope that someone else will pick
up where I left off and make further improvements.

The fact that Washington U allowed a trojanized version of this to creep into
a MAJOR distribution site is a huge black mark on their record, as far as
I'm concerned.  Having looked at this code, and having observed significant
cracking activity originating from some of their machines, I trust them even
less now, despite their laudable efforts at maintaining an archive site.
Take this for what it's worth to you; I'm just ranting at this point.

Architecture considerations:
============================

The safest way to make things available to the net is to dedicated a machine
to this task, and run FTP and Web servers there.  The FTP server for such
a machine should ideally be built ANON_ONLY and PARANOID and run without the
swoopy extensions, but this can make maintenance difficult if several
different people have to maintain the server.  A workaround is to have an
"opaque" writeable directory [mode 733] that maintainers can "bounce" files
through and then manually copy to the right places with the right ownership. 
As the FTP daemon does in "anonymous" mode, a web server should also run in a
chrooted environment.

Some sites may not have this luxury of hardware, and one or two servers will
be performing many functions.  Or the users may demand the convenience of
FTPing files "as themselves" instead of using the "bounce" scheme. In this
case, the "outside" FTP daemon can continue as a "super-safe" version, but a
different daemon built to permit real user logins can also be run on a
different TCP port that is access-controlled for "inside" use only with a
wrapper program.  Most FTP client programs accept a port-number argument
for the control connection, and only default to 21.  If your FTP client
doesn't support this, beat up your vendor.  Both the FTP client and server
normally use (controlport - 1) for the data connection, which makes setting
up access control filters fairly easy.

The access extensions are often used to control "exportability" of certain
directories.  Failing any other method, one may feel a need to run the
"outside" server with the extensions enabled to provide this access control.
Keeping "SITE" disabled with the PARANOID directive is still recommended.
Please try to balance in your own mind the importance of keeping your own
site secure, versus feeding the idiocy of ITAR.  This is not to imply that
the extensions are inherently insecure, it is to imply that export restrictions
on software are stupid.  Since the format of the ACL file is rather obtuse,
an easily defensible "oversight" in its format can allow unrestricted access to
beneficial things like crypto code.

_H* 950612 v1.3
