ProFTPD: Logins and Authentication

Logging into proftpd and being successfully authenticated by the server involves a lot of different modules and different checks. This document aims to discuss the sort of checks and configuration involved, and hopefully provide a better idea of how proftpd authenticates users.

PAM, which stands for Pluggable Authentication Modules, is an API intended to make it easy to replace the old Unix-style DES password hashes stored in /etc/passwd with a flexible system that allows system administrators to use MD5 checksums, SQL tables, LDAP servers, RADIUS servers, etc in place of that password check. However, what PAM does not provide is the rest of the user account information in /etc/passwd, i.e. the user's UID and GID, home directory, and shell. This means that PAM cannot be used as a drop-in replacement for user information stored in /etc/passwd. NSS (Name Service Switch) modules, supported by some operating systems, are a complementary API to PAM which can be used to supply the rest of this user information. proftpd uses the normal libc functions for looking up user information, and those libc functions typically read /etc/passwd. NSS is an abstraction layer within some libc implementations that causes those functions to read other sources rather than /etc/passwd. Regardless of NSS support, proftpd has support for "virtual" users via its authentication modules.

When configuring proftpd, the configure script will automatically try to determine whether your operating system supports PAM. If it does, the mod_auth_pam module will automatically be compiled into your proftpd. If you explicitly do not want PAM support, you can use the --disable-auth-pam configure option to disable this automatic detection. The point of using PAM is that it can provide an extra authentication step during a login. By "authentication", I mean that PAM answers a yes/no question: "Is this user who they say they are?". PAM modules are configured either in /etc/pam.conf or /etc/pam.d/, depending on your operating system. However, many of the PAM modules provided by vendors are not designed to work well with some of the authentication modules supported by proftpd. If PAM is not a necessity for you, and you plan to use one of the authentication modules (other than mod_auth_unix), then you need do nothing. By default, proftpd uses PAM as an additional check during logins, but if that check fails, the login may still succeed. If you do need the PAM check to be authoritative, then you need to use the AuthOrder directive, e.g.:

  AuthOrder mod_auth_pam.c* ...
To disable use of PAM entirely, use:
  <IfModule mod_auth_pam.c>
    AuthPAM off

Configuration Directives
There are several configuration directives that can cause login problems. The most common one is
RequireValidShell, so common that it is a FAQ. If proftpd does not actually use the shell configured for a user, why does it check to see if the shell is valid by looking in /etc/shells? Certain other FTP servers (e.g. wu-ftpd, pure-ftpd) do check for invalid shells and deny logins based on this criterion; proftpd follows this pattern so as not to surprise too many system administrators. Use of invalid shells is a common sysadmin trick for denying shell-based login access (e.g. ssh logins); many sites use other means, however, and so use of the RequireValidShell directive is also frequently seen.

Another reason why a client cannot login might be if the login user is root (or has a UID of zero, and hence has root privileges). Logging in as root is dangerous, and should be avoided if possible. If you do find it absolutely necessary to login as root, please use SSL/TLS, or at least tunnel your FTP connection using SSH. The RootLogin configuration directive is needed in your proftpd.conf in order for proftpd to explicitly allow root logins.

One uncommon obstacle that you might encounter to allowing a user to login is the possibility that that user is listed in an /etc/ftpusers file. This is another legacy check, courtesy of wu-ftpd. Any user that is listed in /etc/ftpusers is not allowed to login via FTP. A little backwards from what might be expected from the file name, I agree. proftpd was made to similarly honor any /etc/ftpusers file by default in order to ease the pain for sites migrating from wu-ftpd to proftpd. Disabling proftpd's check for this file is as simple as using the UseFtpUsers configuration directive, like so:

  UseFtpUsers off
in your proftpd.conf file.

The PersistentPasswd configuration directive can be necessary in some environments, particularly those that use NIS/YP, NSS modules, or (in the case of Mac OSX) the netinfo service. In order to be able to lookup and map UIDs and GIDs to names, as when listing directories and files, proftpd tries to keep the /etc/passwd file open. This is particularly relevant if the DefaultRoot directive is in effect, for once chrooted, proftpd cannot open /etc/passwd. However, services such as NIS, NSS, and netinfo function very differently while providing a file-like interface, and they do not function properly if proftpd keeps them open. Using:

  PersistentPasswd off
in your proftpd.conf should cause name lookups to work properly if you use NIS, NSS, or netinfo.

If you feel your logins are slow, then you might be encountering another FAQ. The timeouts when performing RFC931 ident lookups, and DNS reverse resolutions, add a noticeable delay to a login.

Anonymous Logins
Anonymous logins are allowed by defining an
<Anonymous> section, or context, in your proftpd.conf. No <Anonymous> contexts mean that proftpd will not allow anonymous logins. As the documentation describes, proftpd knows to treat a given login name (given to the server by the client via the USER FTP command) by seeing if the login name is the same as the User name in an <Anonymous> context. For example:

  <Anonymous /var/ftp/anon/dave>
    User dave
    Group ftpanon
would cause any client logging in as dave to be treated as an anonymous login, and to be handled using the <Anonymous> context above. This structure allows for multiple login names to be treated as anonymous logins, and for each anonymous login to have its own specific anonymous configuration. Some administrators use <Anonymous> contexts to define "virtual" users directly in their proftpd.conf, but this practice is discouraged. Virtual user accounts are discussed next.

Resolving ~
The DefaultRoot directive is commonly used to restrict or "
jail" users into specific directories, usually their individual home directories. This is done via:

  DefaultRoot ~
where the tilde (~) is expanded to the home directory of the logging in user. Now, when proftpd is resolving the tilde, it switches to the privileges of the logging-in user and attempts to resolve the home directory. This ensures that the user will, once restricted to that directory, will have the ability to see files and move around. So if using the tilde does not appear to be working in your configuration, double-check that the permissions on the home directory of the user in question at least allow that user to change into the directory (which requires execute permission on the home directory). If proftpd finds that the permissions are too restrictive, an error message like:
  chroot("~"): No such file or directory
will be logged.

Virtual Users
One question that often arises is "How do I create a proftpd user?" proftpd uses your system's /etc/passwd file by default, and so proftpd users are the same as your system users. "Virtual" users, sometimes described as FTP-only user accounts, are users that can login to proftpd, but who are separate from the normal system users, and who do not have entries in /etc/passwd. proftpd does not care how or where user information is defined. The daemon is designed with an abstraction layer on top of user information sources, and that abstraction is responsible for supplying that data that is required for every user: a name, a UID, a GID, a home directory, and a shell. A user's shell will not be used except in RequireValidShell checks, but it must still present. The code that is responsible for supplying this data, reading it from whatever storage format is supported, lies in proftpd's various configurable authentication modules.

Authentication Modules
proftpd uses authentication modules for accessing user account information. These modules implement an API that that daemon uses to lookup account information by name or by ID, to authenticate a user using the provided password, and to resolve names to IDs or IDs to names. The following authentication modules are all provided with proftpd:

Note that mod_auth_pam is not on this list because it cannot provide the necessary user account information. It can be used to supplement other auth modules by adding its PAM checks, however.

Since proftpd supports multiple authentication modules at the same time, how does it know which authentication module to use? What if you want to tell proftpd which modules to check, and in which order? What if you want some authentication modules to be used in one <VirtualHost>, and different authentication modules in another?

By default, proftpd will ask every configured authentication module about a given user, until it finds an authentication module that knows about that user, or until an authentication module signals an unrecoverable error. The order in which these modules are asked depends on the order of modules in the --with-modules option used when configuring proftpd.

Some modules can be figured to not "play nice" and allow other authentication modules a chance at providing user information. That is, some modules can be "authoritative", and if that module does not know about the user, it will signal an error and prevent proftpd from asking other modules. mod_auth_pam's AuthPAMAuthoritative directive, and the * syntax in the SQLAuthenticate directive of mod_sql, are examples of this authoritativeness. In general, it is best to avoid using such mechanisms, and to use the AuthOrder configuration directive instead.

The following illustrates a situation where AuthOrder is useful. The default build of proftpd has two authentication modules included: mod_auth_file and mod_auth_unix. proftpd will consult both modules when authenticating a user: first mod_auth_file, then mod_auth_unix. (Note: versions of proftpd before 1.2.8rc1 would only support either AuthUserFile or /etc/passwd, but not both at the same time.) If any authentication module can authenticate a user, then authentication succeeds. This holds true of other authentication modules like mod_ldap, mod_sql, mod_radius, etc.

However, if you only want proftpd to use your AuthUserFile and no other authentication modules, then you would use the AuthOrder directive like this:

  AuthOrder mod_auth_file.c
Or, if you use mod_sql and wanted proftpd to check your SQL tables first, and then default to system users:
  AuthOrder mod_sql.c mod_auth_unix.c
Note that the mod_auth.c module should never be used in an AuthOrder directive.

Frequently Asked Questions

Question: How can I configure proftpd to log/show the password typed by the user?
Answer: You cannot. Period. The proftpd code goes out of its way to ensure that the password is never logged.

© Copyright 2017 The ProFTPD Project
All Rights Reserved