ftpd 1 user commands djbwares
ftpd UCSPI-TCP FTP server for static content
`ftpd` root

## Description

ftpd prints requested public files from the root directory hierarchy. The Bernstein convention is for root to be `/public/file`, but it can use other conventional locations such as `/home/publicfile/public` or `/var/www`.

ftpd accepts `FEAT`, `OPTS`, `HOST`, `PWD`, `CWD`, `CDUP`, `TYPE`, `PORT`, `EPSV`, `PASV`, `SPSV`, `REST`, `RETR`, `LIST`, `NLST`, and `QUIT` requests on standard input in `FTP` format. It prints responses on standard output, and local log information on standard error.

ftpd recognizes `USER`, `PASS`, `REIN`, and `ACCT`, but it does not check usernames or passwords. To work around a problem with various badly written FTP application-level gateways, it always asks for a password after a `USER` command if the username is "anonymous".

It has minimal support for `STRU`, `MODE`, `SIZE`, `SYST`, `HELP`, and `NOOP`.

ftpd exits silently if it runs out of memory, encounters an I/O error, or does not receive an input packet within 60 seconds.

Normally ftpd is run under a UCSPI-TCP server program (`tcp-socket-accept`, `s6-tcpserver`, or `tcpserver` spawning a server program per connection) to handle FTP connections from hosts around the Internet. Note that ftpd does not print the FTP greeting message; sending the greeting message is handled by the server (`line-banner` or the -B option to `tcpserver`).

### File handling

Initially, ftpd attempts to take the virtual host name `v` from UCSPI-TCP or UCSPI-SSL environment variables, in particular the `PROTO` and `SSLLOCALHOST`/`TCPLOCALHOST` environment variables. If those variables are not set, ftpd uses the host name `0` as an initial default. FTP clients may subsequently specify a host name with the `HOST` command. ftpd always converts the host name to lowercase. `REIN` does not re-initialize the virtual host name.

A request for a file or directory named `f` refers to `./v/f` inside the root directory hierarchy. ftpd thus advertises that it supports the TVFS feature.

ftpd has built-in support for `NLST` and `LIST`; it does not run an external root`/bin/ls`. It provides EPLF `LIST` responses, including EPLF options "i", "s", and "m".

### Unsupported features

ftpd does not support file/directory modification requests such as `STOR`, `STOU`, `APPE`, `DELE`, `RNFR`, and `RNTO`.

ftpd does not support `REIN`.

## Standards conformance

- Daniel J. Bernstein (1996). Easily Parsed LIST Format cr.yp.to.

## Security

ftpd chroots to root when it starts. It then sets its group id and user id to the numbers given in environment variables `GID` and `UID`, as set by `envuidgid` (or equivalent). ftpd does not allow dots immediately after slashes in file names. It converts any such dots to colons before attempting to open the file.

Earlier versions of `ftpd` required the `/etc/leapsecs.dat` to be copied under root. This file is now read before the chroot.

ftpd will refuse to read a file if the file

- is unreadable to user;

- is unreadable to group;

- is unreadable to world;

- is world-executable without being user-executable; or

- is anything but a regular file or directory: a socket, device, etc.

In directory listings, ftpd will skip a file if the name begins with a dot. It will also skip names that contain tildes, spaces, or control characters; note, however, that these files can still be accessed by someone who knows or guesses the name.

ftpd uses local ports above 1024 for PORT connections, rather than the standard port 20. It rejects remote ports below 1024, and it rejects third-party PORT. It also rejects third-party PASV.

## History

`ftpd` was originally part of Daniel J. Bernstein's publicfile toolset in 1999.

## Author

Original code and documentation by Daniel J. Bernstein. Documentation modernizations by Jonathan de Boyne Pollard.