# authlib

## Name

authlib -- Courier Authentication Library

## Synopsis

authpam {command} [arg...]

authpwd {command} [arg...]

authshadow {command} [arg...]

authuserdb {command} [arg...]

authvchkpw {command} [arg...]

authcram {command} [arg...]

authmysql {command} [arg...]

authpgsql {command} [arg...]

authldap {command} [arg...]

authdaemon {command} [arg...]

authcustom {command} [arg...]

authdaemond [start | stop | restart]

## DESCRIPTION

This library is used for two purposes:

1. Read an E-mail address that is supposed to be for a local account. Determine the local account's home directory, and system userid and groupid.

2. Read a login id and a password. If valid, determine the account's home directory, system userid, and groupid.

The term "authentication" is used in the following documentation to refer to either one of these two functions. The library contains several alternative authentication implementations, that may be selected at runtime.

`authdaemon`

  authenticates through a background daemon proxy. This is now the installation default. Unless otherwise specified, the `authdaemon` module will always be installed. `authdaemon` is installed instead of the other authentication modules. Those modules are instead compiled into a separate executable program, `authdaemond` that is initialized at system start, and runs in the background. The `authdaemon` authentication module forwards the authentication requests to `authdaemond`, which forwards the authentication request to the real authentication module, and the result of the request is eventually returned back to the application. Because the real authentication process runs as a persistent background process, it is possible for the authentication process to open and hold permanent connections to the back-end authentication database (be it an LDAP directory, a MySQL or a PostgreSQL server), instead of connecting and disconnecting for every request. Obviously, this tremendously improves the authentication performance.

`authpam`

  authenticates using the system's PAM library (pluggable authentication module). This is, essentially, a way to use existing PAM modules for authentication functionality. Note, however, that the authenticated account's home directory, userid and groupid are still read from the `/etc/passwd` file, since PAM functionality is limited to validating account passwords.

`authpwd`

  authenticates from the `/etc/passwd` file.

`authshadow`

  like `authpwd` except passwords are read from `/etc/shadow`.

`authuserdb`

  authenticates against the userdb(8) database.

`authvchkpw`

  supports existing `vpopmail/vchkpw` virtual domains.

`authcram`

  authenticates against the userdb(8) database using the challenge/response authentication mechanism (CRAM), instead of the traditional userid/password.

`authmysql`

  authenticates against a list of mail accounts stored in an external MySQL database. The `/usr/local/etc/courier/authmysqlrc` configuration file defines the particular details regarding the MySQL database and the schema of the mail account list table.

`authpgsql`

  authenticates against a list of mail accounts stored in an external PostgreSQL database. The `authpgsqlrc` configuration file defines the particular details regarding the PostgreSQL database and the schema of the mail account list table.

`authldap`

  authenticates against a list of mail accounts stored in an external LDAP directory. The `` configuration file defines the particular details regarding the LDAP directory layout.

`authcustom`

  this is a stub where custom authentication code can be added. This authentication module is just a stub that doesn't really do anything. It's purpose is to serve as a placeholder where custom authentication code can be easily added.

This is a complete list of available authentication modules. The actual installed authentication modules are determined by the resources on the server. For example, the `authmysql` authentication module will be installed only if the system provides MySQL support libraries.

### `authdaemon` authentication module

The following command must be executed from the system startup script in order for the `authdaemon` module to work (and remember that `authdaemon` is installed by default:

>     /usr/local/libexec/authlib/authdaemond start

"authdaemond stop" should also be added to the system shutdown script.

The `/var/spool/courier/authdaemon` subdirectory must be created in advance. This directory will have the filesystem socket used for interprocess communication between `authdaemon` and `authdaemond`. It goes without saying that the underlying filesystem for `/var/spool/courier/authdaemon` must support filesystem domain sockets. This pretty much excludes all network filesystems, so this directory should reside on a local disk.

`/var/spool/courier/authdaemon` MUST NOT HAVE any world-readable, executable or writable permissions! Under NO circumstances should this be allowed to happen. The exact permissions and ownership of `/var/spool/courier/authdaemon` varies. For the standalone versions of Courier-IMAP and SqWebMail, `/var/spool/courier/authdaemon` should be owned by root, and have no group or world permissions. For the Courier mail server, `/var/spool/courier/authdaemon` should be owned by the userid that Courier is installed under, and it must be readable and writable by the Courier user and group (but no world permissions).

### Configuring `authdaemond`

The `/usr/local/etc/courier/authdaemonrc` configuration file sets several operational parameters for the `authdaemond` process. See the comments in the default file installed for more information. Currently, `/usr/local/etc/courier/authdaemonrc` sets two parameters: number of daemon processes, and authentication modules/process that will be used.

Although `authdaemond` might include several authentication modules, not all of them may be used. This makes it possible to install the same authdaemond build on multiple systems with different authentication needs. The default module list specified in `/usr/local/etc/courier/authdaemonrc` would be a list of all the available authentication modules.

/usr/local/libexec/authlib/authdaemond is actually a very short shell script that executes the real authdaemond program. The available programs are authdaemond.plain, authdaemond.ldap, authdaemond.mysql, and authdaemond.pgsql. The "plain" program contains all the authentication modules except for `authldap`, `authmysql`, and `authpgsql`. The "ldap" program includes all the authentication modules in "plain", plus `authldap` Ditto for the "mysql" and "pgsql" processes.

This arrangement allows convenient creation of pre-configured binary packages. The authdaemond shell script runs authdaemond.plain only if none of the other processes are installed on the system. First, it checks if authdaemond.ldap, authdaemond.mysql, or authdaemond.pgsql is installed. If not, authdaemond.plain is brought up. This makes it possible to prepare a basic binary package that provides only basic authentication services and does not require either LDAP, MySQL, or PostgreSQL runtime support on the server. If either of these authentication requirements are needed, a separate binary sub-package will load the appropriate authdaemond process.

Note that it is not possible to use both LDAP and MySQL, for example, authentication at the same time. That's because their support is in different authdaemond processes, and only one authdaemond process can run at the same time. If both (or all three non-plain processes) are installed, the authdaemond script picks either the first one it finds, or whatever is explicitly specified in the `/usr/local/etc/courier/authdaemonrc` configuration file.

The number of authdaemond processes is also set in this configuration file. The more processes that are started, the more authentication requests can be handled. If authdaemon does not receive an answer within a moderate amount of time, it will declare an authentication failure, and abort. Try increasing the number of processes if you start seeing random authentication failures. However, that should only be used as a stop-gap measure. If the default number of authdaemond processes proves to be insufficient, it is far more likely that more resources are needed for the server: more RAM, a faster disk, or a faster CPU, at least in the humble opinion of the author. Increasing the number of processes should only be used as a stop-gap measure, until a more thorough analysis on the bottleneck can be made.

>     /usr/local/libexec/authlib/authdaemond restart

Run the above command after making any changes to `/usr/local/etc/courier/authdaemonrc`. "authdaemond restart" is required for any changes to take effect.

## AUTHENTICATION PROTOCOL

The rest of this documentation describes the internal protocol used by this authentication library. It is only of interest to developers who wish to extend the authentication library to support a custom authentication module, or a derived extension to an existing module.

The original implementation of this authentication library used small, self-contained, binary programs, named for their authentication module: `authldap`, `authpam`, and others. Later, the `authdaemon` module came about, which wrapped the other authentication modules into a separate background daemon process, which communicated with the `authdaemon` module. The `authdaemon` module is now always enabled by default, but it is still possible to build and install each authentication module as a self-contained binary program. Note, however, that applications such as `SqWebMail`, and `Courier` link directly with all the authentication modules, and will not use external modules for authentication.

`authdaemon` came about as a direct result of technical issues that prevented `SqWebMail` and `Courier` from using external binary modules. `authdaemond` is really nothing more than a simple application that links directly with the authentication modules, and talks to the `authdaemon` authentication module that follows this authentication protocol.

### Stand-alone authentication modules

This section describes the authentication protocol for self-contained authentication modules. Although the default configuration no longer uses self-contained modules, the stand-alone protocol serves as a foundation for the protocol used by authentication modules as part of the `authdaemond` authentication process, or when they are linked directly with the application that uses this authentication library.

Here's the typical way that stand-alone authentication modules are used:

1. A list of authentication modules are read from a configuration file. Multiple authentication modules could be available, but not all of them are required in most situations.

2. The application executes the following command:

>     LOGIN AUTHMODULE1 AUTHMODULE2 ... APP

`LOGIN` is a full pathname to an application that reads the authentication information, such as the userid and a password. Arguments to `LOGIN` are full pathnames to each authentication module (if there are more than one), followed by a full pathname to the main application.

3. `LOGIN` reads the userid and password, then runs the program specified by its first argument, which is the first authentication module. The remaining arguments are passed to the new process. The mechanism by which the authentication information is passed to the authentication module is described later.

4. Each authentication module reads the authentication information, and determines if the previous authentication module succesfully processed the authentication request. If not, the module attempts to authenticate it itself. In any event, the module runs the next program specified by its first argument, and the remaining arguments are passed along to the next program. If any previous authentication module succesfully processed the authentication request, the next program is run immediately without any further processing.

5. Eventually, `APP` runs, `APP` reads the authentication information and determines whether any authentication module managed to succesfully process the authentication request. If so, `APP` runs normally. Otherwise, `APP` runs `LOGIN` with its original arguments in order to return an error message ("Password invalid", or something similar) and read the next authentication request.

Daisy-chaining authentication modules, in this fashion, makes it possible to have hybrid systems that use multiple authentication modules. Example: using `authpam` to authenticate system accounts, and `authmysql` to authentication virtual mailboxes without a corresponding system account.

Here's a more detailed description of the overall process:

#### The `LOGIN` process

The `LOGIN` process checks if the `AUTHARGC` environment variable is set. If not, this is the first time the `LOGIN` process comes up, and `LOGIN` displays the initial login prompt. Additionally, the command line arguments to `LOGIN` are literal copied to the `AUTHARGC` and `AUTHARGVn` environment variables. That is: the number of command line arguments is saved in `AUTHARGC`; the zeroth command line argument is saved in `AUTHARGV0`; the remaining command line arguments are saved in `AUTHARGV1`, `AUTHARGV2`, and so on.

After obtaining the authentication information (such as the userid and password), `LOGIN` creates a pipe, and arranges for the output end of the pipe to be located on file descriptor #3. The `LOGIN` process forks; the original process then executes the first authentication module, in the manner described earlier; the child process writes the authentication record to the pipe, then terminates.

The authentication record is a chunk of data in the following format:

> `SERVICE<NEWLINE>AUTHTYPE<NEWLINE>AUTHDATA`

Each occurence of <NEWLINE> represents an ASCII linefeed character (#10). "`SERVICE`" identifies the service that originates the authentication request, such as "imap", or "webmail". Authentication module may use this identifier, or ignore it.

"`AUTHTYPE`" identifies the format of the authentication request. Everything after the second <NEWLINE> is an opaque blob of data, whose format is determined by `AUTHTYPE`.

NOTE: | There's a theoretical upper limit on the maximum size of the authentication record. It is high enough not to matter in most situations (the total number of characters allowed cannot be more than 8189 characters on a typical GNU/Linux system).

The following `AUTHTYPE` formats are currently defined:

`login`

  A typical userid/password authentication request. `AUTHDATA` contains the following data: userid<NEWLINE>password<NEWLINE>.

`cram-md5`

  Specifies the `CRAM-MD5` authentication request. `AUTHDATA` contains the following data: challenge<NEWLINE>response<NEWLINE>. The "challenge" and "response" strings are base64-encoded.

`cram-sha1`

  Specifies the `CRAM-SHA1` authentication request, instead of CRAM-MD5, and uses the same format for `AUTHDATA`.

#### The authentication module

The first thing an authentication module does is check if the environment variable `AUTHENTICATED` is set to a non-empty string. If so, it means that a previous authentication module has handled the authentication request, so this module simply runs the next program, specified by the first argument to this authentication module.

Otherwise, the authentication module reads the authentication record from file descriptor #3, and determines whether it wants to try this authentication record. If not, the module creates a new pipe, arranges the output of the pipe to be on file descriptor #3, forks, the parent process runs the next authentication module, and the child process writes the authentication record to the pipe, then exits.

There are two ways to handle an authentication request: 1) Use the `AUTHARGC` and `AUTHARGVn` variables to restart the entire authentication process - this is used in the event it is determined that the authentication request must be failed, or 2) run the next daisy-changed module, in the manner described previously, when it is determined that another authentication module can attempt to try to handle this request.

The following action occurs when the authentication module succesfully validates an authentication request:

1. The authenticated login ID is saved in the `AUTHENTICATED` environment variable.

2. The process's userid and groupid are reset to the corresponding userid and groupid of the authenticated login id, and the current directory is set to the process's defined home directory.

3. Some additional environment variables may also be initialized: `AUTHFULLNAME` - the login ID's full name; `MAILDIR` - the login ID's default maildir mailbox; `MAILDIRQUOTA` - the requested maildir quota.

#### The application process

Eventually, `APP` runs. The process closes file descriptor #3 (if it's open, and ignores the error if file descriptor #3 does not exist). If the `AUTHENTICATED` environment variable is set, it must mean that an authentication module was able to handle this authentication request, so `APP` starts up and runs normally. Otherwise the original command is reconstructed from the `AUTHARGC` and `AUTHARGVn` variables, and the initial login process runs again.

#### Library functions

This authentication library provides several convenient functions which can be used to quickly create a compliant login process, and its corresponding application. The login process should be structured as follows:

> Example 1. A sample LOGIN process

>     int main(int argc, char **argv)
>     {
>        if (authmoduser(argc, argv, TIMEOUT, ERR_TIMEOUT))
>        {
>           /* Print initial greeting here */
>        }
>        else
>        {
>           /* Error: invalid userid/password */
>        }

>        /* read userid and password */

>        authmod(argc-1, argv+1, SERVICE, AUTHTYPE, AUTHDATA);
>     }

The `authmoduser` function takes care of copying the command line parameters to their corresponding environment variables, and checking whether or not this is the initial time this process runs, or if it is running again after a failed authentication process. `TIMEOUT` specifies the absolute login timeout, `authmoduser` quietly terminates the process if it runs due to a failed authentication request and at least `TIMEOUT` seconds have elapsed since the first time `authmoduser` was run. `ERR_TIMEOUT` specifies the number of seconds that `authmoduser` will sleep after a failed authentication request.

The `SERVICE`, `AUTHTYPE`, and `AUTHDATA` arguments to `authmod` are null-terminated character strings that form the authentication request. `authmod` takes care of setting up the pipe to the first authentication module, and runs it.

The application process is even simpler:

> Example 2. A sample APP process

>     int main(int argc, char **argv)
>     {
>     const char *loginid=authmodclient();

>        /* Application begins normally */

>     }

The `authmodclient` function returns the authenticated login ID. If the authentication request failed, `authmodclient` reruns the original login process, and doesn't return.

### Inside an authentication modules

An authentication module needs to define the following structure:

> Example 3. struct authstaticinfo

>     struct authstaticinfo {
>             const char *auth_name;
>             char * (*auth_func)(const char *, const char *, char *, int,
>                             void (*)(struct authinfo *, void *),
>                             void *);
>             int (*auth_prefunc)(const char *, const char *,
>                             int (*)(struct authinfo *, void *),
>                             void *);
>             void (*auth_cleanupfunc)();
>             int (*auth_changepwd)(const char *, /* service */
>                                   const char *, /* userid */
>                                   const char *, /* oldpassword */
>                                   const char *); /* new password */
>             } ;

`auth_func` points to a function that handles the authentication request. If succesful, `auth_func` is responsible for resetting the userid and groupid, changing to the authentication account's home directory, and setting up the necessary environment variables. The first three arguments to `auth_func` will be `SERVICE`, `AUTHTYPE`, and `AUTHDATA`. The next argument is a boolean flag which is non-zero if the authentication code is being called in the context of a stand-alone authentication module, or zero if the authentication code is called directly by an application. The fifth argument points is a callback function pointer, which may be NULL. If it's not null, `auth_func` should not reset the userid, groupid, or the home directory of this process, but should instead initialize the `authinfo` structure, which is defined as follows:

> Example 4. struct authinfo

>     struct authinfo {
>             const char *sysusername;
>             const uid_t *sysuserid;
>             gid_t sysgroupid;
>             const char *homedir;

>             const char *address;	/* The E-mail address */
>             const char *fullname;	/* gecos, etc... */
>             const char *maildir;
>             const char *quota;

>             const char *passwd;
>             const char *clearpasswd;        /* For authldap */

>             unsigned staticindex;   /* When statically-linked functions are
>                                     ** called, this holds the index of the
>                                     ** authentication module in authstaticlist */

>             } ;

The `passwd`, `clearpasswd`, and `staticindex` fields are not used by `auth_func`. Either `sysusername` or `sysuserid` must be a non-NULL pointer. `sysuserid` specifies an explicit userid, otherwise `sysusername` is looked up in the password file.

The last argument to `auth_func` is an opaque pointer that gets passed as the second argument to the callback function.

`auth_func` should return a pointer to the authenticated loginid, in dynamic memory (the memory should be `free()`ed after user. A NULL return indicates an authentication failure. The authentication module should set errno to `EPERM` in the event that it the next authentication module should have a chance to process the authentication request, or use any other errno value to immediately fail the authentication request, and rerun the original login process.

### Linked authentication modules

The `auth_prefunc`, `auth_cleanupfunc`, and `auth_changepwd` functions are not used by stand-alone modules, but when the authentication module is directly linked with an application.

`auth_prefunc` verifies that the requested userid exists. No passwords are validated, the first two arguments to `auth_prefunc` are the userid, and `SERVICE`. `auth_prefunc` should initialize an `authinfo` structure, and run the callback function, the third argument to `auth_prefunc`. The callback function receives the fourth argument to `auth_prefunc` as an opaque pointer.

`auth_prefunc` should come back with the callback function's return code, if the requested userid was found. Otherwise, `auth_prefunc` should return a non-zero integer. A positive integer should be return in the event that this authentication request should be stopped, and a negative itneger if another authentication module can be tried. An application that links against this authentication library will run each configured authentication module's `auth_prefunc`, until some module is able to process the requested userid, or until `auth_prefunc` comes back with a non-zero positive return code.

`auth_func` or `auth_prefunc` might allocate some internal resources, which should be freed by calling `auth_cleanupfunc`.

The `auth_changepwd` function is called to implement the change password functionality.

### Other authentication library function

This authentication library contains several functions and macros that can be helpful in building authentication modules.

> Example 5. Turning `auth_func` into a module

>     #define MODULE  auth_func
>     #include        "mod.h"

`mod.h` contains template code that reads an authentication request from the previous authentication module, call `auth_func`, in such a manner, and appropriately run the next module in the authentication chain.

The `auth.h` header file also declares several useful functions that authentication-related code may find convenient.

#### Building authdaemond

This authentication library builds alternate versions of the authdaemond background process. Some authentication modules have dependencies on external libraries, such as `authldap`, `authmysql`, and `authpgsql`. The authentication library prepares separate versions of authdaemond for each authentication module with a dependency. Each one of these authdaemond versions will also include all other authentication modules that do not have dependencies.

The authentication module configuration for each authdaemond is set in the `authdaemond.versions` file. A new authentication module will have to be added to `authdaemond.versions` (potentially creating another authdaemond build). The `configure` script must be run after making any changes to `authdaemond.versions`.

## FILES

`/usr/local/etc/courier/authmodulelist` - list of authentication modules read by applications that directly link with `authlib`

`/usr/local/etc/courier/authdaemonrc` - authdaemond configuration file

`/usr/local/etc/courier/authldaprc` - authldap configuration file

`/usr/local/etc/courier/authmysqlrc` - authmysql configuration file

`/usr/local/etc/courier/authpgsqlrc` - authpgsql configuration file

## SEE ALSO

courier(8), userdb(8)