authlib.html.in
上传用户:s81996212
上传日期:2007-01-04
资源大小:722k
文件大小:41k
- <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"
- "http://www.w3.org/TR/REC-html40/loose.dtd">
- <html>
- <head>
- <title>authlib - Courier Authentication Library</title>
- <!-- $Id: authlib.html.in,v 1.11 2000/04/27 23:41:27 mrsam Exp $ -->
- <!-- Copyright 1998 - 1999 Double Precision, Inc. See COPYING for -->
- <!-- distribution information. -->
- <!-- SECTION 8 -->
- <meta http-equiv="Content-Type" content="text/html">
- </head>
- <body text="#000000" bgcolor="#FFFFFF" link="#0000EE" vlink="#551A8B"
- alink="#FF0000">
- <h1>authlib - Courier Authentication Library</h1>
- <h2>SYNOPSIS</h2>
- <pre> authpam <i>program arg1 arg2...</i>
- authpwd <i>program arg1 arg2...</i>
- authshadow <i>program arg1 arg2...</i>
- authuserdb <i>program arg1 arg2...</i>
- authvchkpw <i>program arg1 arg2...</i>
- authcram <i>program arg1 arg2...</i>
- authmysql <i>program arg1 arg2...</i>
- authldap <i>program arg1 arg2...</i>
- authdaemon <i>program arg1 arg2...</i>
- authdaemond (start|stop|restart)</pre>
- <h2>DESCRIPTION</h2>
- <p>These modules read an account name and password from an external
- application, then return an indication to the external application whether or
- not the account name and password is valid. These modules cannot be normally
- executed from the command line because they expect to be executed by a
- separate application, which provides authentication information via
- environment variables and specially prepared pipes.</p>
- <p>These authentication modules are usually installed automatically by an
- application that uses them. Not every one of these modules will be installed.
- Different modules implement different ways of authenticating the account name
- and password. Only the modules that are compatible with your system will be
- installed by default.</p>
- <p><code>authpwd</code> validates the account name and password against your
- <code>/etc/passwd</code> file.</p>
- <p><code>authshadow</code> validates the account name and password against
- your <code>/etc/shadow</code> file.</p>
- <p><code>authuserdb</code> validates the account name and password against
- your <a href="userdb.html"><code>userdb(8)</code></a> database.</p>
- <p><code>authcram</code> also uses <a
- href="userdb.html"><code>userdb(8)</code></a>, but implements a
- challenge/response authentication mechanism (CRAM), instead of the traditional
- userid/password.</p>
- <p><code>authpam</code> validates the account name and password using your
- Pluggable Authentication Module (PAM) library. <code>authpam</code> allows
- PAM modules to be used to authenticate passwords by any application that uses
- this authentication library.</p>
- <p><code>authvchkpw</code> supports existing vchkpw-based virtual domain
- setups. New installations should use the <a
- href="userdb.html"><code>userdb(8)</code></a> database.</p>
- <p><code>authldap</code> is an experimental module that uses LDAP for
- authentication. <code>authldap</code> will authenticate clear-text or crypt-ed
- passwords in an LDAP database. If clear-text passwords are used,
- <code>authldap</code> will also be able to handle CRAM authentication, if the
- application that uses this authentication library supports CRAM
- authentication. See below for more information.</p>
- <p><code>authmysql</code> is another experimental module that authenticates
- against a MySQL table. See below for more information.</p>
- <p><code>authdaemon</code> is a background daemon proxy. See "<a
- href="#authdaemon"><code>AUTHDAEMON</code> authentication module</a>" for more
- information.</p>
- <p>As previously mentioned, only those modules that are appropriate to your
- particular system will be installed. The <code>authpam</code> module will be
- installed only if your system supports PAM authentication.
- <code>authldap</code> will be installed only if LDAP client libraries are
- available. <code>authpwd</code> and <code>authshadow</code> will not be
- installed if you have PAM authentication or LDAP authentication.
- <code>authvchkpw</code> is usually installed only if your system has the
- vpopmail/vchkpw account. <code>authuserdb</code> is usually installed in any
- case. <code>authcram</code> is installed only if the application that uses
- this authentication library supports CRAM authentication.
- <code>authmysql</code> is usually installed if MySQL client libraries are
- found, and <code>authvchkpw</code> is not installed.</p>
- <h2><code>AUTHLDAP</code> authentication module</h2>
- <p>This section applies if you have the <code>authldap</code> authentication
- module installed. This is an experimental authentication module, and may not
- be stable.</p>
- <p>The <code>authldap</code> authentication module reads a configuration file.
- The configuration file tells <code>authldap</code> where to obtain the
- information that it needs. A default configuration file will be installed in
- <code>@authldaprc@</code>.</p>
- <p>It will be necessary to edit this file in order to properly configure
- <code>authldap</code>. This configuration file contains a list of settings,
- one per line. Each line starts with the name of the setting, followed by one
- or more whitespace characters, followed by the setting value. Leading or
- trailing whitespace is not allowed.</p>
- <p>Comments in the default configuration file describe what each setting does.
- <code>LDAP_SERVER</code>, <code>LDAP_PORT</code>, <code>LDAP_BASEDN</code>,
- <code>LDAP_BINDDN</code>, and <code>LDAP_BINDPW</code> specify your LDAP
- server's coordinates. <code>LDAP_TIMEOUT</code> sets the timeout for the LDAP
- query.</p>
- <p>The LDAP query is keyed by the E-mail address. The <code>LDAP_MAIL</code>
- settings sets the LDAP attribute that is searched for, which should be "mail".
- The E-mail address should be of the form <code>user@domain</code>. If the
- domain is missing, authldap appends <code>LDAP_DOMAIN</code> to the query.</p>
- <p><code>authldap</code> will need to obtain the following attributes: the
- account's home directory, user and group ids, and the account password. These
- attributes are required. The password can be a clear-text password, or a
- crypt-ed password.</p>
- <p>There are also several optional attributes which, if present, will be used:
- the full name of the user, and the location of the user's main mailbox. If the
- mailbox location is not specified, the default location, as defined by the
- system administrator, will be used.</p>
- <p>The configuration file lists which LDAP attributes contain which
- properties. If all your accounts share the same global user and group IDs,
- which may be the case if you are authenticating access to a large number of
- virtual accounts, you can set the global user and group ID with the
- <code>LDAP_GLOB_UID</code> and <code>LDAP_GLOB_GID</code> setting. Otherwise,
- you must define <code>LDAP_UID</code> and <code>LDAP_GID</code> to be the LDAP
- attributes that contain the numerical user and group IDs.</p>
- <p><code>LDAP_HOMEDIR</code> specifies the name of the required LDAP attribute
- which contains the account's home directory, <code>LDAP_MAILDIR</code>
- specifies the name of the optional attribute that specifies the location of
- the default mailbox. If your virtual accounts have no home directory, set both
- <code>LDAP_HOMEDIR</code> and <code>LDAP_MAILDIR</code> to the same LDAP
- attribute that specifies the location of the virtual account's mailbox.</p>
- <p><code>LDAP_FULLNAME</code> is an optional LDAP attribute. Not every
- application that uses this authentication library will need it.</p>
- <p>You must define either LDAP_CLEARPW and LDAP_CRYPTPW. It is possible to
- define both of them, but, in practice, only one of them needs to be defined.
- If you store clear-text passwords, set <code>LDAP_CLEARPW</code> to the name
- of the LDAP attribute that holds the clear-text password. If you store
- crypt-ed passwords in LDAP, set <code>LDAP_CRYPTPW</code> to the name of the
- LDAP attribute that holds the crypt-ed password.</p>
- <p>If you store clear-text passwords, <code>authldap</code> will be able to
- carry out CRAM authentication. Only userid/password authentication is possible
- if crypt-ed password are used.</p>
- <h2><code>AUTHMYSQL</code> authentication module</h2>
- <p>This section applies if you have the <code>authmysql</code> authentication
- module installed. This is an experimental authentication module, and may not
- be stable.</p>
- <p><code>authmysql</code> functions like <code>authldap</code>, but uses a
- MySQL The <code>authmysql</code> authentication module reads a configuration
- file. The configuration file tells <code>authmysql</code> where to obtain the
- information that it needs. A default configuration file will be installed in
- <code>@authmysqlrc@</code>.</p>
- <p>It will be necessary to edit this file in order to properly configure
- <code>authmysql</code>. This configuration file contains a list of settings,
- one per line. Each line starts with the name of the setting, followed by one
- or more whitespace characters, followed by the setting value. Leading or
- trailing whitespace is not allowed.</p>
- <p>Comments in the default configuration file describe what each setting does.
- Consult the configuration file for more information.</p>
- <a name="authdaemon"></a>
- <h2><code>AUTHDAEMON</code> authentication module</h2>
- <p>This authentication library is used by applications in one of two ways: 1)
- individual authentication methods are compiled as standalone modules, or 2)
- individual authentication methods are statically linked with the
- application.</p>
- <p>Standalone modules have greater flexibility, but may not be very efficient
- in environments that use a database back-end, where the database connection
- and teardown is comparatively expensive. Each authentication request requires
- a new database connection to be established, and torn down. An example of
- when this happens is with the <code>authldap</code> and <code>authmysql</code>
- authentication modules.</p>
- <p>Even applications that statically linked with this authentication library
- may not fare much better. Typically, an instance of the application is
- invoked for every user, so essentially it works out to be the same thing.</p>
- <p>The <code>authdaemon</code> module is not a new authentication method.
- Enabling <code>authdaemon</code> in addition to any other modules will result
- in <code>authdaemon</code> being built as the only "official" authentication
- module. However, the remaining modules are compiled into a separate process,
- "<code>authdaemond</code>".</p>
- <p>It will be necessary to add the following command to your system startup
- script, to start <code>authdaemond</code> at system boot:</p>
- <pre> @libexecdir@/authlib/authdaemond start</pre>
- <p>This command starts an authentication daemon. The <code>authdaemon</code>
- authentication module takes an authentication request, and forwards it to the
- permanently running <code>authdaemond</code> daemon process, then returns the
- result to the application. The application "sees" only the
- <code>authdaemon</code> authentication module, which swallows every
- authentication requests, and passes it along to the <code>authdaemond</code>
- for processing, where all the real authentication modules do their stuff.</p>
- <p>It is necessary to start the <code>authdaemond</code> process as early as
- possible, when the system boots, because until that happens no authentication
- can take place. Additionally, the <code>@authdaemonvar@</code> subdirectory
- must be created in advance, that contains the filesystem socket used for
- interprocess communication, and other miscellania. It goes without saying that
- the underlying filesystem for <code>@authdaemonvar@</code> must support
- filesystem domain sockets. This pretty much excludes all network filesystems,
- so this directory must reside on a local disk.</p>
- <p><code>@authdaemonvar@</code> 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 <code>@authdaemonvar@</code>
- may vary. For the standalone versions of Courier-IMAP and SqWebMail,
- <code>@authdaemonvar@</code> should be owned by root, and have no group or
- world permissions. For the Courier mail server, <code>@authdaemonvar@</code>
- 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).</p>
- <h2>Configuring the <code>authdaemond</code> daemon</h2>
- <p>The <code>@authdaemonrc@</code> configuration file sets several operational
- parameters for the <code>authdaemond</code> process. See the comments in the
- default file installed for more information. Currently,
- <code>@authdaemonrc@</code> sets two parameters: number of daemon processes,
- and authentication modules that will be used.</p>
- <p>Although <code>authdaemond</code> might be built with several
- authentication modules, not all of them may be used. This allows for a single
- <code>authdaemond</code> build to be made that gets installed on multiple
- systems with different authentication needs. The default module list specified
- by <code>@authdaemonrc@</code> would be a list of all the available
- authentication modules.</p>
- <p>The number of <code>authdaemond</code> processes is also set in this
- configuration file. The more processes that are started, the more
- authentication requests can be handled. If <code>authdaemon</code> 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 <code>authdaemond</code>
- 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. secon</p>
- <p>After making any changes to @authdaemonrc@, run the following command for
- these changes to take effect:</p>
- <pre> @libexecdir@/authlib/authdaemond restart</pre>
- <p>The <code>stop</code> command is also available, to shut down the daemon
- completely.</p>
- <h2>CONFIGURING THE COURIER AUTHENTICATION LIBRARY</h2>
- <p>This authentication library is used by applications that typically consist
- of two separate parts. The first part waits for the user to enter the account
- name and password. Then, it runs one or more authentication modules, which
- check if the account name and password is valid. The second part of the
- application is then executed. If the password is valid, the second part of the
- application runs normally. Otherwise, the first part is executed again, to try
- to read another account name and password.</p>
- <p>This manual page provides generic instructions for using this
- authentication library. You will need to use the documentation that comes with
- each application to determine the filenames corresponding to the first, login,
- part and the second, application, part. The following example assumes that the
- application consists of the following programs: <code>/usr/bin/getlogin</code>
- and <code>/usr/bin/app</code>. <code>getlogin</code> reads the account name
- and password, and <code>app</code> is the actual application.</p>
- <p>The following command starts this application with the
- <code>authuserdb</code> and <code>authshadow</code> modules:</p>
- <pre>/usr/bin/getlogin @prefix@/lib/authuserdb
- @prefix@/lib/authshadow
- /usr/bin/app</pre>
- <p>After obtaining the account name and password, <code>getlogin</code> simply
- runs the program specified by its first argument, which is
- <code>authuserdb</code>. The remaining command line arguments to
- <code>getlogin</code> are received as arguments to <code>authuserdb</code>.
- Note that this is not a pipe, there is no | here. <code>authuserdb</code>
- receives the remaining arguments as its own arguments, checks the account name
- and password, then runs the program specified by the first argument, which is
- authshadow. <code>authshadow</code> receives the remaining argument, checks
- the account name and password, if necessary, then runs the program specified
- by its first argument.</p>
- <p>The protocol implemented by this authentication library permits
- multiple modules to try to authenticate the account name and password.
- Essentially, to start an application that uses this authentication library,
- you run its login part, then pass the pathnames to the authentication modules
- to be used as the arguments to the login part of the application. The pathname
- to the application part is usually the last argument. Where any module
- requires an option or an argument, the option or the argument is provided at
- the appropriate point on the command line.</p>
- <p>Any application that uses this authentication library can use any
- combination of authentication modules that are installed, unless there are
- specific restrictions mention in the documentation for each application. All
- pathnames must be absolute. Pathnames relative to the current directory are
- prohibited.</p>
- <p>Each authentication module runs the program specified by its first
- argument, after checking the account name and password. So, in the example
- given previous <code>/usr/bin/app</code> will be eventually executed by the
- last authentication module. Each authentication module checks if the account
- name and password has already been validated by a previous authentication
- module. If not, it tries to validate the account name and password by itself.
- The final module, the application part itself, checks if any authentication
- modules successfully validated the account name and password. If not, it will
- immediately execute the login part of the application using the same arguments
- that were originally used, and the process will begin again. Otherwise, if the
- account password was successfully accepted by any authentication module, the
- application part runs normally.</p>
- <p>The login portion of the application, <code>getlogin</code> in this
- example, must be executed by the superuser. After the account password is
- successfully validated, the authentication module sets its user and group IDs
- of the process to the user group IDs for that account, and sets its home
- directory to the account's home directory. However, if all authentication
- modules rejected the account name and password, the application module,
- <code>app</code> in this example, will still be a superuser process when it
- starts. That's fine, because the first thing it does is check if the
- authentication succeeded, and, if not, it will run the login process again.
- Obviously, you can't use just any application with this authentication
- library. An application must be specially written to understand and use this
- protocol.</p>
- <h2>NETWORK SERVICES</h2>
- <p>Applications that use this authentication library are usually network
- services, and must be started in response to a network connection. There are
- several ways to do that. One way is to use the <code>inetd(8)</code> daemon.
- Here is a sample entry in <code>/etc/inetd.conf</code> for a hypothetical IMAP
- server that uses this authentication library:</p>
- <pre>imap stream tcp nowait root /usr/bin/imaplogin /usr/bin/imaplogin
- @prefix@/lib/authpam /usr/bin/imapserver</pre>
- <p>This should all be entered on one line in <code>/etc/inetd.conf</code>.</p>
- <p>Note that some <code>inetd</code> implementations automatically infer the
- <code>argv[0]</code> argument from the filename. You can use those
- <code>inetd</code> servers by removing the second
- <code>/usr/bin/imaplogin</code> entry (in this particular case) ONLY if the
- inetd server does NOT strip the pathname from the<code></code>implied
- <code>argv[0]</code> argument. The application login process
- (<code>imaplogin</code> in this case), MUST know its complete pathname so that
- it can be executed again if the first password is rejected.</p>
- <h3><code>tcpserver</code></h3>
- <p>If you use Dan Bernstein's <code>tcpserver</code>, here's an equivalent
- <code>tcpserver</code> startup command for this hypothetical IMAP
- application:</p>
- <pre>/usr/local/bin/tcpserver -H -R 0 imap
- /usr/bin/imaplogin @prefix@/lib/authpam /usr/bin/imapserver & </pre>
- <h3><code>couriertcpd</code></h3>
- <p>If you use the <code>couriertcpd</code> server, here's an equivalent
- <code>couriertcpd</code> startup command for this hypothetical IMAP
- application:</p>
- <pre>/usr/local/bin/couriertcpd -nodnslookup -noidentlookup imap
- /usr/bin/imaplogin @prefix@/lib/authpam /usr/bin/imapserver & </pre>
- <p>You may specify appropriate options for <code>tcpserver</code> and
- <code>couriertcpd</code> that are right for you.</p>
- <h2>AUTHENTICATION PROTOCOL</h2>
- <p>The remainder of this document defines the protocol used by these
- authentication modules.</p>
- <p>The overall application that uses this authentication library is made up of
- at least three processes:</p>
- <p>The first process, called a "login process", is started as a superuser
- process in response to a network connection, or an equivalent event. It reads
- the userid and password, then starts an authentication module and securely
- transmits this information to the authentication module.</p>
- <p>The second process is an "authentication module" that attempts to validate
- the userid and password in some arbitrary fashion. Whether or not the password
- is authenticated, the authenticated module runs the next process. That's
- because the next process can be another authentication module, or the
- authenticated client process (see below). If one authentication module fails,
- another authentication module can be given a chance to authenticate the userid
- and password. An authentication module can also decide that other
- authentication modules can not be used to attempt to authenticate this userid
- and password, because it should be unequivocally rejected.</p>
- <p>If the authentication module successfully validates the userid and
- password, it sets the process's user and group ID to the authenticated user's,
- then sets the current directory to the authenticated user's home directory.
- The authentication module may also set some additional environment
- variables.</p>
- <p>The final process is called the "authenticated client" process in this
- documentation. Contrary to its name, it is possible that it will be called
- even if all modules rejected the userid and password, so the first thing it
- does is check whether that's the case.</p>
- <p>If any authentication module permanently rejects a userid and password, or
- if the authenticated client detects that all authenticated modules rejected
- the userid and password, the original login process is executed again, in
- order to try to read another password and start the process again.</p>
- <p>It is expected that the login process is initially started by a daemon
- process, and it begins with a relatively clean environment. Modules use
- environment variables and pipes in order to implement this authentication
- protocol. When the login process starts it can check these environment
- variables to determine if this is the first time it is run, or if it is
- executed again in order to read another userid and password, after the first
- pair was rejected.</p>
- <h2>AUTHENTICATION MODULES</h2>
- <p>The login process is usually invoked by some system daemon process in
- response to a network connection. argv[0] to the login process must be a
- complete pathname. Otherwise, the AUTHUSER environment variable must be set
- prior to running the login process, and it must contain a complete pathname.
- It is possible that certain systems might strip the full path from argv[0],
- leaving just the filename, so use AUTHUSER in that case</p>
- <p>Any options for the login process can be specified on the command line.</p>
- <p>The first argument after any options must be a full pathname to the first
- authentication module to run.</p>
- <p>It is possible to run two authentication modules, as previously described.
- The complete pathname of the second module should be the next argument.
- Additional authentication modules may also be specified in this fashion.</p>
- <p>The arguments to the login process end with a complete pathname to the
- authenticated client process, followed by any options it requires. Here is a
- hypothetical example of a complete invocation of the login process:<br>
- <br>
- </p>
- <pre> /usr/local/bin/readuserpass -d
- @prefix@/lib/authuserdb
- @prefix@/lib/authpam
- /usr/local/bin/dostuff -x
- <br>
- </pre>
- <p>This example runs <code>/usr/local/bin/readuserpass</code> to read the
- userid and password. This process uses the <code>-d</code> option. This is
- followed by two modules - <code>authuserdb</code> and <code>authpam</code> -
- they are specified as the modules which will be used to authenticate the
- userid and password. <code>/usr/local/bin/dostuff -x</code> is specified as
- the command to execute upon successful userid/password validation.</p>
- <h2>AUTHENTICATION LIBRARY</h2>
- <p>This and the following sections provide documentation that's of interest
- only if you want to write your own authentication modules. The low-level
- authentication protocol is defined later. The <code>libauth.a</code> and
- <code>libauthmod.a</code> libraries contain functions that handle all the low
- level details, and provide convenient high level authentication services that
- you can use to write your own authentication modules in C or C++.</p>
- <p>Under normal conditions, the login process reads its command line
- arguments, and processes any options it knows about. Afterwards, the remaining
- command line arguments specify the next process to run.</p>
- <p>The typical logic used by the login process is as follows:<br>
- <br>
- </p>
- <pre>int main(int argc, char **argv)
- {
- if (authmoduser(argc, argv, TIMEOUT, ERR_TIMEOUT))
- {
- /* Print initial greeting */
- }
- else
- {
- /* Error: invalid userid/password */
- }
- /* read userid and password */
- authmod(argc-1, argv+1, SERVICE, AUTHTYPE, AUTHDATA);
- }</pre>
- <p>This example does not use any options for the login process itself. If the
- login process parses any options, they must be removed from the argc/argv
- arguments to the call to the <code>authmod</code> function. For example, if
- the authentication user process received two options, subtract two from argc,
- and add two to argv to skip over them.</p>
- <p>The TIMEOUT argument specifies the authentication timeout, in seconds. The
- <code>authmoduser</code> function calls alarm to set up an alarm signal to be
- delivered after the specified period of time (which will terminate this
- process by default).</p>
- <p>The <code>authmoduser</code> function copies the command line arguments
- into environment variables. This allows the login process to be invoked with
- the same exact command line arguments in the event that the subsequent account
- password is rejected, in order to start the process again.</p>
- <p><code>authmoduser</code> checks if the environment variables are not
- already set, meaning that this is the first time the login process is
- executed. If so, it copies the command line arguments to environment
- variables, and returns non-zero.</p>
- <p>If the environment variables were already set, the function returns 0 in
- this case after sleeping for the amount of time specified by the
- <code>ERR_TIMEOUT</code> argument (in seconds). Note that the
- <code>TIMEOUT</code> time interval will generally be a cumulative value.
- <code>authmoduser</code> checks the system clock, and subsequent invocation of
- the login process will automatically cause <code>authmoduser</code> to
- subtract the time already used up during the initial invocation of the
- process.</p>
- <p>The return value from <code>authmoduser</code> can be used to determine
- whether a "password rejected" type of a message should be printed, or if a
- greeting message should be used instead.</p>
- <p>Afterwards, the userid and password are obtained, in some fashion, and the
- <code>authmod</code> function is called. The first two arguments to
- <code>authmod</code> must be exactly as shown. If <code>authmoduser</code>
- received <code>argc</code> and <code>argv</code>, <code>authmod</code> must
- receive <code>argc-1</code> and <code>argv+1</code>. If authmoduser received
- any options, argc/argv must be advanced appropriately. The next argument
- specifies the first authentication module to execute, which is precisely what
- the <code>authmod</code> function does.</p>
- <p><code>SERVICE</code> is a character string that specifies an
- "authentication service". This is not used by all authentication modules. The
- <code>authpam</code> module passes this directly to the PAM library, and the
- PAM library uses this value to look up a list of PAM modules to run.</p>
- <p><code>AUTHTYPE</code> and <code>AUTHDATA</code> are also both character
- strings. <code>AUTHTYPE</code> specifies the authentication type or format.
- The contents of <code>AUTHDATA</code> depend on <code>AUTHTYPE</code>.</p>
- <p>Currently, two <code>AUTHTYPE</code>s are defined: "login", which specifies
- the traditional userid/password authentication mechanism; and "cram-md5", that
- specifies the challenge/response authentication mechanism defined by <a
- href="ftp://ftp.isi.edu/in-notes/rfc2095.txt">RFC 2095</a>.</p>
- <p>When <code>AUTHTYPE</code> is set to "login", <code>AUTHDATA</code> must be
- set to the userid, followed by a newline character, and the password, also
- followed by the newline character.</p>
- <p>When AUTHTYPE is set to "cram-md5", AUTHDATA must be set to the
- base64-encoded challenge string followed by a newline character, then the
- base64-encoded response string, also followed by a newline character.</p>
- <p>Before running the first authentication module, <code>authmod</code> sets
- up a pipe on file descriptor 3 to the first authentication module, and writes
- the following to the pipe:
- <code>service<NL>AUTHTYPE<NL>AUTHDATA</code></p>
- <p><NL> represents the newline character. The pipe is immediately closed
- after writing this information. The authlib library does not use file
- descriptors 0, 1, and 2. They are preserved throughout the process.</p>
- <p>The logic in an authentication module is usually like this:</p>
- <pre>int main(int argc, char **argv)
- {
- const char *service, *authtype;
- char *authdata;
- authmod_init(argc, argv, &service, &authtype, &authdata);
- /* Attempt to accept this authentication request */
- if success
- {
- authmod_success(argc, argv);
- }
- if failed
- {
- authmod_fail(argc, argv)
- }
- if permanently failed
- {
- authmod_fail_completely();
- }
- }</pre>
- <p>The authentication module calls authmod_init as the first order of
- business. <code>authmod_init </code>receives the <code>argc</code> and
- <code>argv</code> arguments as main received them. <code>authmod_init</code>
- retrieves the service, authentication type, and data, and returns them.</p>
- <p>NOTE: There's a theoretical upper limit on the maximum number of characters
- read from the pipe on file descriptor 3. It is high enough that most people
- shouldn't worry about it (the total number of characters allowed cannot be
- more than 8189 characters on a typical Linux system).</p>
- <p>The authentication module then proceeds to authenticate this request in
- some arbitrary fashion. The end result must be a call to one of three
- functions: <code>authmod_success</code>, <code>authmod_fail</code>, or
- <code>authmod_fail_completely</code>.</p>
- <p><code>authmod_success</code> and <code>authmod_fail</code> must receive the
- <code>argc</code> and <code>argv</code> arguments that were received by main.
- They remove argv[0] from the array, and use the remaining arguments to specify
- the next process to execute.</p>
- <p>All three functions do not return, as they functions execute either the
- next process specified by command line arguments, or the login process
- again.</p>
- <p>Before calling <code>authmod_success</code>, an authentication module must
- reset its user and group id to the ones appropriate for the authenticated
- account, change to the account's home directory, and perform any additional
- initialization logic deemed necessary.</p>
- <p>If <code>authmod_success</code> is called, and the next process is another
- authentication module, the next module's <code>authmod_init</code> function
- will automatically call <code>authmod_success</code> itself, without returning
- to the main function.</p>
- <p><code>authmod_fail</code> should be called if the password has not been
- authenticated. If the next process is another authentication module, it will
- receive the service string, and authtype and authtype strings, via a pipe on
- file descriptor 3, and the next authentication module will get a crack at
- validating the password.</p>
- <p><code>authmod_fail_completely</code> should be called if the authentication
- module rejects the password, and the authentication module does not want to
- give any other authentication modules a chance to validate the userid and
- password. This is typically done if the authentication module believes that
- its the only authentication module that should be used to validate this
- authentication request, and that no other authentication modules should be
- able to do so. <code>authmod_fail_completely</code> reads the original
- arguments to the login process, then runs it.</p>
- <p>Eventually, the authenticated client process will be executed. That's the
- last process specified on the original command line to the login process.</p>
- <p>The only thing that the authentication client process needs to do is to
- make a call to the <code>authmodclient()</code> function as the very first
- order of business in <code>main()</code>. <code>authmodclient</code> takes no
- arguments. It checks whether or not any modules successfully authenticated the
- userid and password by calling <code>authmod_success</code>. In any other
- event, <code>authmodclient()</code> automatically executes the login process
- (without returning to main) to begin the authentication process again.</p>
- <h2>FUNCTIONS IN libauth.a</h2>
- <p>In addition to the authentication functions in libmodauth.a library, the
- libauth.a contains the following functions which may be useful when writing a
- new authentication module:</p>
- <pre>void authchangegroup(gid_t);
- void authchangeuidgid(uid_t, gid_t);
- void authchangeusername(const char *, const gid_t *);</pre>
- <p>An authentication module should call these function prior to calling
- <code>authmod_success</code>. These functions set the process's user and group
- IDs. Some systems feature supplementary group IDs in addition to standard
- group IDs, and you may not want the authenticated client process to inherit
- any auxiliary group IDs from the superuser login process. The configuration
- script for the libauth.a tries to detect if this is the case, and these
- functions will include code to remove all auxiliary group IDs.</p>
- <p><code>authchangegroup</code> changes the process's group ID to the one
- specified by its argument. <code>authchangeuidgid</code> changes both the
- group and the user ID. <code>authchangeusername</code> looks up the userid and
- the groupid in <code>/etc/passwd</code>. If the second argument to
- <code>authchangeusername</code> is not NULL, it points to a group ID which
- will override the group ID specified in the system's password database for
- this user. If it is NULL, the group ID and any auxiliary group IDs are
- retrieved from the system's password database (the auxiliary group IDs are
- reset in all other cases).</p>
- <h2>LOW LEVEL AUTHENTICATION PROTOCOL</h2>
- <p>The actual authentication protocol uses environment variables and pipes to
- communicate authentication information between modules. All of this
- functionality is implemented by high level functions in the
- <code>libauthmod.a</code> library. This documentation is provided in the event
- it is desired to put together a compatible authentication module without using
- the code from <code>libauthmod.a</code>.</p>
- <p>The login process performs the following procedure prior to running the
- first authentication module:</p>
- <p>1) The <code>AUTHENTICATED</code> environment variable is cleared (set to
- an empty string). <code>argv[0]</code> is checked to make sure it contains a
- full pathname, and its contents are used to set the <code>AUTHUSER</code>
- environment variable. If <code>AUTHUSER</code> is already set,
- <code>argv[0]</code> is ignored. If <code>argv[0]</code> does not contain a
- full pathname, <code>AUTHUSER</code> must already be set prior to running this
- process.</p>
- <p>2) <code>wait(2)</code> is repeatedly called to reap any zombie child
- processes that are a byproduct of this authentication protocol.
- <code>wait(2)</code> is called repeatedly until there are no more child
- processes left.</p>
- <p>3) The <code>AUTHARGC</code> environment variable is checked. If it is not
- defined it means that the process was invoked for the first time, by a system
- daemon process. If <code>AUTHARGC</code> is defined it means that this is not
- the first time this process was executed for this connection, and the previous
- authentication request failed.</p>
- <p>4) If necessary, <code>AUTHARGC</code> is set to contain the decimal value
- of argc, as received by main.</p>
- <p>5) The environment variables <code>ARGV0</code>, <code>ARGV1</code>, up to
- <code>ARGVn</code>, are initialized to the contents of the argv array, as
- received by main. <code>ARGV0</code> is set to the contents of
- <code>argv[0]</code>, <code>ARGV1</code> is set to the contents of
- <code>ARGV[2]</code>, and so on.</p>
- <p>6) If the login process wants to have an expiration time for the login
- attempt, then it should set the AUTHEXPIRE environment variable the first time
- the login process is called. <code>AUTHEXPIRE</code> should be set to the
- calculated expiration time, based on the system clock. Subsequent invocations
- (after failed authentication attempts) compare the system clock against the
- contents of <code>AUTHEXPIRE</code> to check if the login has expired. If not,
- it's possible to calculate how much time is left, and set the alarm clock to
- kill the process. The alarm clock is cleared if the next authentication
- attempt is entered before the alarm clock goes off.</p>
- <p>7) The login process then tries read a potential userid and password, in
- some sort of fashion, taking into account.</p>
- <p>8) After obtaining the userid and password, the authentication user process
- kills the expiration timer (if it was set), and creates a pipe. It forks, and
- the parent process connects the output of the pipe to file descriptor 3, then
- executes the next process specified by the command line arguments. The child
- process writes the following text to the pipe:</p>
- <p><code><b>service</b><NL><b>authtype</b><NL><b>authdata</b></code></p>
- <p><i>service</i>, <i>authtype</i>, and <i>authdata</i>, comprise the
- authentication request, as defined previously. They are separated by a newline
- character, <code><NL></code>. A pipe is used to send the authentication
- request to the authentication module instead of command line arguments or
- environment variables. That's because you do not want the password readable by
- anyone who happens to run <code>ps(1)</code> at the same time. After writing
- the authentication request to the pipe, the child process quickly
- terminates.</p>
- <p>An authentication module performs the following steps:</p>
- <p>1) Checks the <code>AUTHENTICATED</code> environment variable. If it is not
- empty, it means that some previous authentication module successfully
- authenticated the userid and the password, so the authentication module
- immediately executes the next process specified by the command line.
- Otherwise, the module reads the userid, password, and service from file
- descriptor 3 which is immediately closed afterwards.</p>
- <p>2) The authentication module calls <code>wait(2)</code> repeatedly to reap
- any zombie child processes.</p>
- <p>3) Following that, the authentication module attempt to authenticate this
- request. There are three possible outcomes.</p>
- <p>4) If the request is successfully authenticated, the module sets the
- process's userid, groupid, then changes to the account's home directory. The
- following environment variables are set: <code>AUTHENTICATED</code> is set to
- the userid; <code>AUTHFULLNAME</code> is set to the user's "full name";
- <code>AUTHADDR</code> is set to the user's return address. After these
- environment variables are set, the next process specified on the command line
- is executed.</p>
- <p>5) If the authentication request is rejected, the module process creates a
- pipe, forks, the parent process connects the output side of the pipe to file
- descriptor 3, then executes the next process specified by command line
- arguments line arguments. The child process writes the authentication request
- to the pipe, then immediately terminates. This allows the next authentication
- module, if present, to have the opportunity to authenticate this request.</p>
- <p>6) In order to permanently reject the authentication request, without
- invoking any additional authentication modules, the authentication module must
- execute the process specified by the <code>AUTHUSER</code> environment
- variable. The command line arguments for the process must be taken from the
- <code>AUTHARGVn</code> series environment variables, the number of which is
- given by the <code>ARGC</code> environment variable.</p>
- <p>An authenticated client process of this authentication library must take
- the following steps as the first order of business when it starts:</p>
- <p>1) Repeatedly call <code>wait(2)</code> to reap any zombie child
- processes.</p>
- <p>2) Verify that the <code>AUTHENTICATED</code> environment variable is not
- empty. If not, it means that none of the authentication modules successfully
- authenticated this request, so the process specified by <code>AUTHUSER</code>
- must be immediately invoked, with command line arguments set by the contents
- of <code>AUTHARGVn</code> series of environment variables.</p>
- <p>3) Otherwise, the client process is considered to be authenticated, and
- ready for business.</p>
- <h2>BUGS</h2>
- <p>File descriptor 3 is used in order to avoid messing with <i>program</i>'s
- stdin, stdout, and stderr.</p>
- <h2>SEE ALSO</h2>
- <p><a href="courier.html">courier(8),</a> <a
- href="userdb.html">userdb(8)</a></p>
- <p></p>
- </body>
- </html>