Home / Alt manpages / pam_ftp(8)

  • pam_ftp(8)
  • Admin command
  • linux

Enable Anonymous FTP Authentication Safely with pam_ftp

pam_ftp lets an FTP daemon accept the username ftp or anonymous with no real account, while ordinary logins and a deny list keep working. This guide adds that one rule to a PAM service file using the pam_ftp module shipped by Ubuntu's libpam-modules version 1.5.3-5ubuntu5.7. Allow about 15 minutes, most of it spent working out which FTP daemon and PAM service name your host actually uses.

Before you change anything

  • Get root access and confirm your FTP daemon actually uses PAM.
  • Decide, deliberately, that anonymous FTP belongs on this host. The module only supplies the auth type: it does not create an FTP account, configure a daemon, publish a directory or encrypt the connection.
  • Read the manpage's own verdict first. It calls pam_ftp unsafe and easily spoofable. Do not use it as proof of anyone's identity, as a general login method, or as a stand-in for TLS and a properly locked-down daemon. If you just need authenticated transfer, use the daemon's normal authenticated setup instead.

Checkpoint

The file you edit has to be the PAM service file your daemon actually reads. /etc/pam.d/ftpd is the common example, but your daemon may use a different service name, so check its documentation or configuration before touching anything.

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'

Expect to see the package version and pam_ftp module is installed. If the service file or module is missing, stop right there. Do not guess a PAM file into existence: the wrong service name simply does nothing, while a malformed active file can lock everyone out.

1. Back up the active PAM file

Make a root-owned backup before you touch authentication policy. Swap the path if your daemon uses a different 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

Recovery

Keep that backup until a real login test has passed. To undo everything here, run sudo cp -p /etc/pam.d/ftpd.before-pam-ftp /etc/pam.d/ftpd, then restart or reload the FTP daemon per its own documentation.

2. Add the anonymous rule ahead of ordinary authentication

Edit the service file as root. The first line below is the actual change; the rest are the normal account and deny-list checks from the module's documented example. Keep whatever session and account rules already exist 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 a successful anonymous match can finish the auth stack outright, as long as no earlier required module has already failed.
  • A name pam_ftp does not accept falls through to pam_unix. The use_first_pass option tells pam_unix to reuse the token already collected instead of prompting again.
  • The last line denies names listed in /etc/ftpusers. With onerr=succeed, an error reading that file does not deny access, that is the documented default, but it is an availability-over-denial choice: make sure the file exists and is readable if the deny list actually matters to you.

Security warning

Do not paste this stack into a file used by SSH, a display manager or any other unrelated service. Do not strip out 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 one, it sets the PAM username to ftp and treats whatever password was typed as an email-like value, splitting it at @ into the PAM remote-user and remote-host items. That is metadata carried into the rest of the PAM conversation, not proof the address is real.

Type a username outside those two, and the module drops the entered password into the PAM authentication-token item and fails, handing off to a later module such as pam_unix for ordinary authentication. So pam_ftp returns success for the anonymous case and user-unknown for anyone it does not recognise.

The installed binary also accepts a users= option with a comma-separated list. This permits guestftp and public, returning the first name in the list, guestftp, as the PAM username:

auth    sufficient  pam_ftp.so users=guestftp,public

Tip

The local manpage's synopsis shows users= while its options heading says ftp=. Trust users=, it is what the installed module actually contains and accepts on this package. The separate ignore option tells the module to skip processing the email-like password address; use it only when nothing downstream needs the remote-user and remote-host items.

4. Check the file and test a controlled login

There is no universal offline syntax checker that covers every FTP daemon and PAM combination. Review the effective file, then lean on the daemon's own configuration test if it has one, and never test 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

You should see pam_ftp.so before pam_unix.so, followed by the pam_listfile.so rule. The daemon may need a restart or reload after the file changes, so follow its own service documentation and schedule that disruption.

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

A successful anonymous login is not a complete verification on its own. Check the daemon's chroot or equivalent isolation, read and write permissions, upload handling, directory listing policy, connection encryption and logging separately, none of that comes from pam_ftp.

Common traps and recovery

  • Nothing changes. The daemon may use a different PAM service name, or may not use PAM at all. Find the daemon's actual PAM service before touching more files.
  • Repeated password prompts. Confirm pam_ftp.so sits before pam_unix.so use_first_pass, and that the stack has not ended up in 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 you are locked out.
  • The deny list does not stop a name. Check the exact username the module returns, and the spelling and permissions of /etc/ftpusers. A missing list counts as success under the documented onerr=succeed rule, remember.
  • Someone claims the email password proves identity. It does not. The module is explicitly spoofable and takes whatever text the client supplies.

Done means

  • You edited the actual PAM service file the FTP daemon uses.
  • A root-owned backup exists and you have confirmed it restores cleanly.
  • pam_ftp.so appears before ordinary authentication, and you have reviewed the deny-list rule.
  • Both anonymous and ordinary test logins behave the way you intended.
  • You checked the daemon's isolation, permissions, encryption, uploads and logs separately from this PAM change.