Home / Alt manpages / pam_ftp(8)

  • pam_ftp(8)
  • Admin command
  • linux

Enable Anonymous FTP Authentication Safely with pam_ftp

This guide adds anonymous FTP authentication to one PAM service file while keeping ordinary account authentication and an FTP deny list in the stack. It uses the pam_ftp module shipped by Ubuntu's libpam-modules version 1.5.3-5ubuntu5.7. Allow about 15 minutes: most of that is checking which FTP daemon and PAM service name your host actually uses.

Before you change anything

You need root access, an FTP daemon that uses PAM, and a clear decision that anonymous FTP is acceptable for this host. The module itself only supplies the auth module type. It does not create an FTP account, configure a daemon, publish a directory, or encrypt the connection.

Anonymous FTP is a security-sensitive choice. The manpage describes pam_ftp as unsafe and easily spoofable. Do not use it as evidence of a person's identity, as a general-purpose login method, or as a replacement for TLS and least-privilege daemon configuration. If you only need authenticated file transfer, use the FTP daemon's normal authenticated configuration instead.

Checkpoint

The file you change must be the PAM service file used by your daemon. The common example is /etc/pam.d/ftpd, but a daemon can use another service name. Inspect the daemon documentation or its service configuration before editing.

sudo test -r /etc/pam.d/ftpd && sudo sed -n '1,160p' /etc/pam.d/ftpd
dpkg-query -W -f='${Package} ${Version}\n' libpam-modules:amd64
test -r /lib/x86_64-linux-gnu/security/pam_ftp.so && echo 'pam_ftp module is installed'

Expected output includes the package version and pam_ftp module is installed. If the service file or module is absent, stop here. Do not create a guessed PAM file: the wrong service name will have no effect, while a malformed active file can lock out users.

1. Back up the active PAM file

Make a root-owned backup before changing authentication policy. Replace the path if your daemon uses a different PAM service file.

sudo cp -p /etc/pam.d/ftpd /etc/pam.d/ftpd.before-pam-ftp
sudo ls -l /etc/pam.d/ftpd /etc/pam.d/ftpd.before-pam-ftp

Keep the backup until a real login test has passed. To undo this guide, restore it with sudo cp -p /etc/pam.d/ftpd.before-pam-ftp /etc/pam.d/ftpd, then restart or reload the FTP daemon according to its own documentation.

2. Add the anonymous rule before ordinary authentication

Edit the service file as root and add the following stack. The first line is the change this guide makes. The remaining lines are the normal account and deny-list checks from the module's documented example; retain existing session and account rules in your file unless you have a specific reason to change them.

# Anonymous FTP authentication
auth    sufficient  pam_ftp.so
auth    required    pam_unix.so use_first_pass
auth    required    pam_listfile.so onerr=succeed item=user sense=deny file=/etc/ftpusers

sufficient means that a successful anonymous match can finish the auth stack, provided no earlier required module has failed. A name that is not accepted by pam_ftp falls through to pam_unix. The use_first_pass option tells pam_unix to use the authentication token already collected rather than asking for another one.

The last line denies users listed in /etc/ftpusers. With onerr=succeed, an error reading that list does not deny access. That is the documented example, but it is a deliberate availability-over-denial choice: make sure the file exists and is readable if the deny list matters to you.

Security checkpoint

Do not paste this stack into a file used by SSH, a display manager, or another unrelated service. Do not remove required, account, password, or session rules just to make the example fit.

3. Decide what anonymous names and passwords mean

By default, pam_ftp recognises the username ftp or anonymous. For either name, it sets the PAM username to ftp and treats the supplied password as an email-like value. The module splits that value at @ into the PAM remote-user and remote-host items. This is metadata for the rest of the PAM conversation, not proof that the address is real.

If the entered username is not one of those two names, the module places the entered password in the PAM authentication-token item and fails, allowing a later module such as pam_unix to handle ordinary authentication. The module returns success for the anonymous case and user-unknown for a user it does not know.

The installed binary accepts the module option users= followed by a comma-separated list. For example, this permits guestftp and public, and returns the first configured name, guestftp, as the PAM username:

auth    sufficient  pam_ftp.so users=guestftp,public

The local manpage's synopsis shows users=, while its options heading says ftp=. The installed module contains and accepts users=; use that spelling on this package. The ignore option tells the module not to process the email-like password address. Use it only when the downstream stack does not need the remote-user and remote-host items.

4. Check the file and test a controlled login

There is no universal offline syntax checker for every FTP daemon and PAM combination. Review the effective file, then use the daemon's own configuration test if it provides one. Avoid testing against a production account first.

sudo sed -n '1,120p' /etc/pam.d/ftpd
sudo grep -nE '^[[:space:]]*auth[[:space:]]+.*pam_(ftp|unix|listfile)\.so' /etc/pam.d/ftpd

Expected output shows pam_ftp.so before pam_unix.so, followed by the pam_listfile.so rule. The FTP daemon may need a restart or reload after the file changes; follow its service documentation and schedule that disruption.

From a separate test client, attempt one anonymous connection to the test service using the username anonymous and a placeholder address such as [email protected]. Confirm in the daemon log that the session reaches the anonymous FTP area and that no account outside the intended directory is exposed. Then test a deliberately denied name from /etc/ftpusers and one normal account, if your service is meant to support both.

Do not treat a successful anonymous login as a complete verification. Check the daemon's chroot or equivalent isolation, read and write permissions, upload handling, directory listing policy, connection encryption, and logging separately. Those behaviours are not provided by pam_ftp.

Common traps and recovery

  • No change in behaviour: the daemon may use another PAM service name, or may not use PAM at all. Find the daemon's actual PAM service before changing more files.
  • Repeated password prompts: confirm that pam_ftp.so is before pam_unix.so use_first_pass and that the stack has not been copied into the wrong service file.
  • Normal users can no longer authenticate: restore the backup immediately, reload the daemon, and test again. Do not keep editing a live authentication stack while locked out.
  • The deny list does not protect a name: check the exact username returned by the module and the spelling and permissions of /etc/ftpusers. Remember that a missing list is treated as success by the documented onerr=succeed rule.
  • Someone claims the email password proves identity: it does not. The module is explicitly spoofable and accepts user-supplied text.

Done means

  • The active PAM service file is the one used by the FTP daemon.
  • A root-owned backup exists and can be restored.
  • pam_ftp.so appears before ordinary authentication, with the deny-list rule reviewed.
  • Anonymous and ordinary test logins have the intended results.
  • The FTP daemon's directory isolation, permissions, encryption, uploads, and logs have been checked separately.