Provided by:
courier-authdaemon_0.47-13ubuntu5_i386 
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 /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 /etc/courier/authldaprc
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/lib/courier/authlib/authdaemond start
"authdaemond stop" should also be added to the system shutdown script.
The /var/run/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/run/courier/authdaemon must support filesystem domain sockets.
This pretty much excludes all network filesystems, so this directory
should reside on a local disk.
/var/run/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/run/courier/authdaemon varies. For the standalone versions of
Courier-IMAP and SqWebMail, /var/run/courier/authdaemon should be owned
by root, and have no group or world permissions. For the Courier mail
server, /var/run/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 /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,
/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 /etc/courier/authdaemonrc
would be a list of all the available authentication modules.
/usr/lib/courier/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 /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/lib/courier/authlib/authdaemond restart
Run the above command after making any changes to
/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:
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:
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:
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:
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.
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
/etc/courier/authmodulelist - list of authentication modules read by
applications that directly link with authlib
/etc/courier/authdaemonrc - authdaemond configuration file
/etc/courier/authldaprc - authldap configuration file
/etc/courier/authmysqlrc - authmysql configuration file
/etc/courier/authpgsqlrc - authpgsql configuration file
SEE ALSO
courier(8), userdb(8)