diff options
author | Thorsten Kukuk <kukuk@thkukuk.de> | 2006-06-28 14:41:18 +0000 |
---|---|---|
committer | Thorsten Kukuk <kukuk@thkukuk.de> | 2006-06-28 14:41:18 +0000 |
commit | 95e6b22ccd72741a4b651deae208b184086f2e52 (patch) | |
tree | 0bc38582d9ebe760b8ddc8645cd581d9fa552ed6 /doc/pam_modules.sgml | |
parent | 504eedccf7e1d222092c6005fdc13705ab5d26b8 (diff) | |
download | pam-95e6b22ccd72741a4b651deae208b184086f2e52.tar.gz pam-95e6b22ccd72741a4b651deae208b184086f2e52.tar.bz2 pam-95e6b22ccd72741a4b651deae208b184086f2e52.zip |
Relevant BUGIDs:
Purpose of commit: cleanup
Commit summary:
---------------
* doc/CREDITS: Removed.
* doc/NOTES: Removed.
* doc/pam_appl.sgml: Removed.
* doc/pam_modules.sgml: Removed.
* doc/pam_source.sgml: Removed.
* doc/figs/pam_orient.txt: Removed.
* doc/figs: Removed.
* configure.in: Remove checks for sgml2* progrs, add sag, adg
and mwg Makefiles.
* doc/Makefile.am: Remove references to sgml, add sag, adg and mwg
directories.
Diffstat (limited to 'doc/pam_modules.sgml')
-rw-r--r-- | doc/pam_modules.sgml | 1505 |
1 files changed, 0 insertions, 1505 deletions
diff --git a/doc/pam_modules.sgml b/doc/pam_modules.sgml deleted file mode 100644 index 872e4d7d..00000000 --- a/doc/pam_modules.sgml +++ /dev/null @@ -1,1505 +0,0 @@ -<!doctype linuxdoc system> - -<!-- - - $Id$ - - Copyright (c) Andrew G. Morgan 1996-2001. All rights reserved. - - ** some sections, in this document, were contributed by other - ** authors. They carry individual copyrights. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - -1. Redistributions of source code must retain the above copyright - notice, and the entire permission notice in its entirety, - including the disclaimer of warranties. - -2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - -3. The name of the author may not be used to endorse or promote - products derived from this software without specific prior - written permission. - -ALTERNATIVELY, this product may be distributed under the terms of the -GNU General Public License, in which case the provisions of the GNU -GPL are required INSTEAD OF the above restrictions. (This clause is -necessary due to a potential bad interaction between the GNU GPL and -the restrictions contained in a BSD-style copyright.) - -THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED -WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, -INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS -OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR -TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE -USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH -DAMAGE. - - --> - -<article> - -<title>The Linux-PAM Module Writers' Guide -<author>Andrew G. Morgan, <tt>morgan@kernel.org</tt> -<date>DRAFT v0.76 2002/05/09 -<abstract> -This manual documents what a programmer needs to know in order to -write a module that conforms to the <bf/Linux-PAM/ standard. It also -discusses some security issues from the point of view of the module -programmer. -</abstract> - -<toc> - -<sect>Introduction - -<sect1> Synopsis -<p> -<tscreen> -<verb> -#include <security/pam_modules.h> - -gcc -fPIC -c pam_module-name.c -ld -x --shared -o pam_module-name.so pam_module-name.o -</verb> -</tscreen> - -<sect1> Description - -<p> -<bf/Linux-PAM/ (Pluggable Authentication Modules for Linux) is a -library that enables the local system administrator to choose how -individual applications authenticate users. For an overview of the -<bf/Linux-PAM/ library see the <bf/Linux-PAM/ System Administrators' -Guide. - -<p> -A <bf/Linux-PAM/ module is a single executable binary file that can be -loaded by the <bf/Linux-PAM/ interface library. This PAM library is -configured locally with a system file, <tt>/etc/pam.conf</tt>, to -authenticate a user request via the locally available authentication -modules. The modules themselves will usually be located in the -directory <tt>/usr/lib/security</tt> and take the form of dynamically -loadable object files (see dlopen(3)). Alternatively, the modules can -be statically linked into the <bf/Linux-PAM/ library; this is mostly to -allow <bf/Linux-PAM/ to be used on platforms without dynamic linking -available, but the two forms can be used together. It is the -<bf/Linux-PAM/ interface that is called by an application and it is -the responsibility of the library to locate, load and call the -appropriate functions in a <bf/Linux-PAM/-module. - -<p> -Except for the immediate purpose of interacting with the user -(entering a password etc..) the module should never call the -application directly. This exception requires a "conversation -mechanism" which is documented below. - -<sect>What can be expected by the module - -<p> -Here we list the interface that the conventions that all -<bf/Linux-PAM/ modules must adhere to. - -<sect1>Getting and setting <tt/PAM_ITEM/s and <em/data/ - -<p> -First, we cover what the module should expect from the <bf/Linux-PAM/ -library and a <bf/Linux-PAM/ <em/aware/ application. Essesntially this -is the <tt/libpam.*/ library. - -<sect2> -Setting data - -<p> -Synopsis: -<tscreen> -<verb> -extern int pam_set_data(pam_handle_t *pamh, - const char *module_data_name, - void *data, - void (*cleanup)(pam_handle_t *pamh, - void *data, int error_status) ); -</verb> -</tscreen> - -<p> -The modules may be dynamically loadable objects. In general such files -should not contain <tt/static/ variables. This and the subsequent -function provide a mechanism for a module to associate some data with -the handle <tt/pamh/. Typically a module will call the -<tt/pam_set_data()/ function to register some data under a (hopefully) -unique <tt/module_data_name/. The data is available for use by other -modules too but <em/not/ by an application. - -<p> -The function <tt/cleanup()/ is associated with the <tt/data/ and, if -non-<tt/NULL/, it is called when this data is over-written or -following a call to <tt/pam_end()/ (see the Linux-PAM Application -Developers' Guide). - -<p> -The <tt/error_status/ argument is used to indicate to the module the -sort of action it is to take in cleaning this data item. As an -example, Kerberos creates a ticket file during the authentication -phase, this file might be associated with a data item. When -<tt/pam_end()/ is called by the module, the <tt/error_status/ -carries the return value of the <tt/pam_authenticate()/ or other -<tt/libpam/ function as appropriate. Based on this value the Kerberos -module may choose to delete the ticket file (<em/authentication -failure/) or leave it in place. - -<p> -The <tt/error_status/ may have been logically OR'd with either of the -following two values: - -<p> -<descrip> -<tag><tt/PAM_DATA_REPLACE/</tag> - When a data item is being replaced (through a second call to -<tt/pam_set_data()/) this mask is used. Otherwise, the call is assumed -to be from <tt/pam_end()/. - -<tag><tt/PAM_DATA_SILENT/</tag> - Which indicates that the process would prefer to perform the -<tt/cleanup()/ quietly. That is, discourages logging/messages to the -user. - -</descrip> - - -<sect2> -Getting data - -<p> -Synopsis: -<tscreen> -<verb> -extern int pam_get_data(const pam_handle_t *pamh, - const char *module_data_name, - const void **data); -</verb> -</tscreen> - -<p> -This function together with the previous one provides a method of -associating module-specific data with the handle <tt/pamh/. A -successful call to <tt/pam_get_data/ will result in <tt/*data/ -pointing to the data associated with the <tt/module_data_name/. Note, -this data is <em/not/ a copy and should be treated as <em/constant/ -by the module. - -<p> -Note, if there is an entry but it has the value <tt/NULL/, then this -call returns <tt/PAM_NO_MODULE_DATA/. - -<sect2> -Setting items - -<p> -Synopsis: -<tscreen> -<verb> -extern int pam_set_item(pam_handle_t *pamh, - int item_type, - const void *item); -</verb> -</tscreen> - -<p> -This function is used to (re)set the value of one of the -<tt/item_type/s. The reader is urged to read the entry for this -function in the <bf/Linux-PAM/ application developers' manual. - -<p> -In addition to the <tt/item/s listed there, the module can set the -following two <tt/item_type/s: - -<p> -<descrip> -<tag><tt/PAM_AUTHTOK/</tag> - -The authentication token (often a password). This token should be -ignored by all module functions besides <tt/pam_sm_authenticate()/ and -<tt/pam_sm_chauthtok()/. In the former function it is used to pass the -most recent authentication token from one stacked module to -another. In the latter function the token is used for another -purpose. It contains the currently active authentication token. - -<tag><tt/PAM_OLDAUTHTOK/</tag> - -The old authentication token. This token should be ignored by all -module functions except <tt/pam_sm_chauthtok()/. - -</descrip> - -<p> -Both of these items are reset before returning to the application. -When resetting these items, the <bf/Linux-PAM/ library first writes -<tt/0/'s to the current tokens and then <tt/free()/'s the associated -memory. - -<p> -The return values for this function are listed in the -<bf>Linux-PAM</bf> Application Developers' Guide. - -<sect2> -Getting items - -<p> -Synopsis: -<tscreen> -<verb> -extern int pam_get_item(const pam_handle_t *pamh, - int item_type, - const void **item); -</verb> -</tscreen> - -<p> -This function is used to obtain the value of the specified -<tt/item_type/. It is better documented in the <bf/Linux-PAM/ -Application Developers' Guide. However, there are three things worth -stressing here: -<itemize> - -<item> -Generally, if the module wishes to obtain the name of the user, it -should not use this function, but instead perform a call to -<tt/pam_get_user()/ (see section <ref id="pam-get-user" -name="below">). - -<item> -The module is additionally privileged to read the authentication -tokens, <tt/PAM_AUTHTOK/ and <tt/PAM_OLDAUTHTOK/ (see the section -above on <tt/pam_set_data()/). - -<item> -The module should <em/not/ <tt/free()/ or alter the data pointed to by -<tt/*item/ after a successful return from <tt/pam_get_item()/. This -pointer points directly at the data contained within the <tt/*pamh/ -structure. Should a module require that a change is made to the this -<tt/ITEM/ it should make the appropriate call to <tt/pam_set_item()/. -</itemize> - -<sect2>The <em/conversation/ mechanism - -<p> -Following the call <tt>pam_get_item(pamh,PAM_CONV,&item)</tt>, the -pointer <tt/item/ points to a structure containing an a pointer to a -<em/conversation/-function that provides limited but direct access to -the application. The purpose of this function is to allow the module -to prompt the user for their password and pass other information in a -manner consistent with the application. For example, an X-windows -based program might pop up a dialog box to report a login -failure. Just as the application should not be concerned with the -method of authentication, so the module should not dictate the manner -in which input (output) is obtained from (presented to) to the user. - -<p> -<bf>The reader is strongly urged to read the more complete description of -the <tt/pam_conv/ structure, written from the perspective of the -application developer, in the <bf/Linux-PAM/ Application Developers' -Guide.</bf> - -<p> -The return values for this function are listed in the -<bf>Linux-PAM</bf> Application Developers' Guide. - -<p> -The <tt/pam_response/ structure returned after a call to the -<tt/pam_conv/ function must be <tt/free()/'d by the module. Since the -call to the conversation function originates from the module, it is -clear that this <tt/pam_response/ structure could be either statically -or dynamically (using <tt/malloc()/ etc.) allocated within the -application. Repeated calls to the conversation function would likely -overwrite static memory, so it is required that for a successful -return from the conversation function the memory for the response -structure is dynamically allocated by the application with one of the -<tt/malloc()/ family of commands and <em/must/ be <tt/free()/'d by the -module. - -<p> -If the <tt/pam_conv/ mechanism is used to enter authentication tokens, -the module should either pass the result to the <tt/pam_set_item()/ -library function, or copy it itself. In such a case, once the token -has been stored (by one of these methods or another one), the memory -returned by the application should be overwritten with <tt/0/'s, and -then <tt/free()/'d. - -There is a handy macro <tt/_pam_drop_reply()/ to be found in -<tt><security/_pam_macros.h></tt> that can be used to -conveniently cleanup a <tt/pam_response/ structure. (Note, this -include file is specific to the Linux-PAM sources, and whilst it will -work with Sun derived PAM implementations, it is not generally -distributed by Sun.) - -<sect2>Getting the name of a user<label id="pam-get-user"> - -<p> -Synopsis: -<tscreen> -<verb> -extern int pam_get_user(pam_handle_t *pamh, - const char **user, - const char *prompt); -</verb> -</tscreen> - -<p> -This is a <bf/Linux-PAM/ library function that returns the -(prospective) name of the user. To determine the username it does the -following things, in this order: -<itemize> - -<item> checks what <tt/pam_get_item(pamh, PAM_USER, ... );/ would have -returned. If this is not <tt/NULL/ this is what it returns. Otherwise, - -<item> obtains a username from the application via the <tt/pam_conv/ -mechanism, it prompts the user with the first non-<tt/NULL/ string in -the following list: -<itemize> - -<item> The <tt/prompt/ argument passed to the function -<item> What is returned by <tt/pam_get_item(pamh,PAM_USER_PROMPT, ... );/ -<item> The default prompt: ``Please enter username: '' - -</itemize> -</itemize> - -<p> -By whatever means the username is obtained, a pointer to it is -returned as the contents of <tt/*user/. Note, this memory should -<em/not/ be <tt/free()/'d by the module. Instead, it will be liberated -on the next call to <tt/pam_get_user()/, or by <tt/pam_end()/ when the -application ends its interaction with <bf/Linux-PAM/. - -<p> -Also, in addition, it should be noted that this function sets the -<tt/PAM_USER/ item that is associated with the <tt/pam_[gs]et_item()/ -function. - -<p> -The return value of this function is one of the following: -<itemize> - -<item> <tt/PAM_SUCCESS/ - username obtained. - -<item> <tt/PAM_CONV_AGAIN/ - converstation did not complete and the -caller is required to return control to the application, until such -time as the application has completed the conversation process. A -module calling <tt/pam_get_user()/ that obtains this return code, -should return <tt/PAM_INCOMPLETE/ and be prepared (when invoked the -next time) to recall <tt/pam_get_user()/ to fill in the user's name, -and then pick up where it left off as if nothing had happened. This -procedure is needed to support an event-driven application programming -model. - -<item> <tt/PAM_CONV_ERR/ - the conversation method supplied by the -application failed to obtain the username. - -</itemize> - -<sect2>Setting a Linux-PAM environment variable - -<p> -Synopsis: -<tscreen> -<verb> -extern int pam_putenv(pam_handle_t *pamh, const char *name_value); -</verb> -</tscreen> - -<p> -<bf/Linux-PAM/ comes equipped with a series of functions for -maintaining a set of <em/environment/ variables. The environment is -initialized by the call to <tt/pam_start()/ and is <bf/erased/ with a -call to <tt/pam_end()/. This <em/environment/ is associated with the -<tt/pam_handle_t/ pointer returned by the former call. - -<p> -The default environment is all but empty. It contains a single -<tt/NULL/ pointer, which is always required to terminate the -variable-list. The <tt/pam_putenv()/ function can be used to add a -new environment variable, replace an existing one, or delete an old -one. - -<p> -<itemize> -<item>Adding/replacing a variable<newline> - -To add or overwrite a <bf/Linux-PAM/ environment variable the value of -the argument <tt/name_value/, should be of the following form: -<tscreen> -<verb> -name_value="VARIABLE=VALUE OF VARIABLE" -</verb> -</tscreen> -Here, <tt/VARIABLE/ is the environment variable's name and what -follows the `<tt/=/' is its (new) value. (Note, that <tt/"VARIABLE="/ -is a valid value for <tt/name_value/, indicating that the variable is -set to <tt/""/.) - -<item> Deleting a variable<newline> - -To delete a <bf/Linux-PAM/ environment variable the value of -the argument <tt/name_value/, should be of the following form: -<tscreen> -<verb> -name_value="VARIABLE" -</verb> -</tscreen> -Here, <tt/VARIABLE/ is the environment variable's name and the absence -of an `<tt/=/' indicates that the variable should be removed. - -</itemize> - -<p> -In all cases <tt/PAM_SUCCESS/ indicates success. - -<sect2>Getting a Linux-PAM environment variable - -<p> -Synopsis: -<tscreen> -<verb> -extern const char *pam_getenv(pam_handle_t *pamh, const char *name); -</verb> -</tscreen> - -<p> -This function can be used to return the value of the given -variable. If the returned value is <tt/NULL/, the variable is not -known. - -<sect2>Listing the Linux-PAM environment - -<p> -Synopsis: -<tscreen> -<verb> -extern char * const *pam_getenvlist(pam_handle_t *pamh); -</verb> -</tscreen> - -<p> -This function returns a pointer to the entire <bf/Linux-PAM/ -environment array. At first sight the <em/type/ of the returned data -may appear a little confusing. It is basically a <em/read-only/ array -of character pointers, that lists the <tt/NULL/ terminated list of -environment variables set so far. - -<p> -Although, this is not a concern for the module programmer, we mention -here that an application should be careful to copy this entire array -before executing <tt/pam_end()/ otherwise all the variable information -will be lost. (There are functions in <tt/libpam_misc/ for this -purpose: <tt/pam_misc_copy_env()/ and <tt/pam_misc_drop_env()/.) - -<sect1>Other functions provided by <tt/libpam/ - -<sect2>Understanding errors - -<p> -<itemize> - -<item> -<tt>extern const char *pam_strerror(pam_handle_t *pamh, int errnum);</tt> - -<p> -This function returns some text describing the <bf/Linux-PAM/ error -associated with the argument <tt/errnum/. If the error is not -recognized <tt/``Unknown Linux-PAM error''/ is returned. - -</itemize> - -<sect2>Planning for delays - -<p> -<itemize> - -<item> -<tt>extern int pam_fail_delay(pam_handle_t *pamh, unsigned int -micro_sec)</tt> - -<p> -This function is offered by <bf/Linux-PAM/ to facilitate time delays -following a failed call to <tt/pam_authenticate()/ and before control -is returned to the application. When using this function the module -programmer should check if it is available with, -<tscreen> -<verb> -#ifdef PAM_FAIL_DELAY - .... -#endif /* PAM_FAIL_DELAY */ -</verb> -</tscreen> - -<p> -Generally, an application requests that a user is authenticated by -<bf/Linux-PAM/ through a call to <tt/pam_authenticate()/ or -<tt/pam_chauthtok()/. These functions call each of the <em/stacked/ -authentication modules listed in the <bf/Linux-PAM/ configuration -file. As directed by this file, one of more of the modules may fail -causing the <tt/pam_...()/ call to return an error. It is desirable -for there to also be a pause before the application continues. The -principal reason for such a delay is security: a delay acts to -discourage <em/brute force/ dictionary attacks primarily, but also -helps hinder <em/timed/ (cf. covert channel) attacks. - -<p> -The <tt/pam_fail_delay()/ function provides the mechanism by which an -application or module can suggest a minimum delay (of <tt/micro_sec/ -<em/micro-seconds/). <bf/Linux-PAM/ keeps a record of the longest time -requested with this function. Should <tt/pam_authenticate()/ fail, -the failing return to the application is delayed by an amount of time -randomly distributed (by up to 25%) about this longest value. - -<p> -Independent of success, the delay time is reset to its zero default -value when <bf/Linux-PAM/ returns control to the application. - -</itemize> - -<sect>What is expected of a module - -<p> -The module must supply a sub-set of the six functions listed -below. Together they define the function of a <bf/Linux-PAM -module/. Module developers are strongly urged to read the comments on -security that follow this list. - -<sect1> Overview - -<p> -The six module functions are grouped into four independent management -groups. These groups are as follows: <em/authentication/, -<em/account/, <em/session/ and <em/password/. To be properly defined, -a module must define all functions within at least one of these -groups. A single module may contain the necessary functions for -<em/all/ four groups. - -<sect2> Functional independence - -<p> -The independence of the four groups of service a module can offer -means that the module should allow for the possibility that any one of -these four services may legitimately be called in any order. Thus, the -module writer should consider the appropriateness of performing a -service without the prior success of some other part of the module. - -<p> -As an informative example, consider the possibility that an -application applies to change a user's authentication token, without -having first requested that <bf/Linux-PAM/ authenticate the user. In -some cases this may be deemed appropriate: when <tt/root/ wants to -change the authentication token of some lesser user. In other cases it -may not be appropriate: when <tt/joe/ maliciously wants to reset -<tt/alice/'s password; or when anyone other than the user themself -wishes to reset their <em/KERBEROS/ authentication token. A policy for -this action should be defined by any reasonable authentication scheme, -the module writer should consider this when implementing a given -module. - -<sect2> Minimizing administration problems - -<p> -To avoid system administration problems and the poor construction of a -<tt>/etc/pam.conf</tt> file, the module developer may define all -six of the following functions. For those functions that would not be -called, the module should return <tt/PAM_SERVICE_ERR/ and write an -appropriate message to the system log. When this action is deemed -inappropriate, the function would simply return <tt/PAM_IGNORE/. - -<sect2> Arguments supplied to the module - -<p> -The <tt/flags/ argument of each of the following functions can be -logically OR'd with <tt/PAM_SILENT/, which is used to inform the -module to not pass any <em/text/ (errors or warnings) to the -application. - -<p> -The <tt/argc/ and <tt/argv/ arguments are taken from the line -appropriate to this module---that is, with the <em/service_name/ -matching that of the application---in the configuration file (see the -<bf/Linux-PAM/ System Administrators' Guide). Together these two -parameters provide the number of arguments and an array of pointers to -the individual argument tokens. This will be familiar to C programmers -as the ubiquitous method of passing command arguments to the function -<tt/main()/. Note, however, that the first argument (<tt/argv[0]/) is -a true argument and <bf/not/ the name of the module. - -<sect1> Authentication management - -<p> -To be correctly initialized, <tt/PAM_SM_AUTH/ must be <tt/#define/'d -prior to including <tt><security/pam_modules.h></tt>. This will -ensure that the prototypes for static modules are properly declared. - -<p> -<itemize> - -<item> -<tt>PAM_EXTERN int pam_sm_authenticate(pam_handle_t *pamh, int flags, -int argc, const char **argv);</tt> - -<p> -This function performs the task of authenticating the user. - -<p> -The <tt/flags/ argument can be a logically OR'd with <tt/PAM_SILENT/ -and optionally take the following value: - -<p><descrip> -<tag><tt/PAM_DISALLOW_NULL_AUTHTOK/</tag> - return <tt/PAM_AUTH_ERR/ if the database of authentication -tokens for this authentication mechanism has a <tt/NULL/ entry for the -user. Without this flag, such a <tt/NULL/ token will lead to a success -without the user being prompted. -</descrip> - -<p> -Besides <tt/PAM_SUCCESS/ return values that can be sent by this -function are one of the following: - -<descrip> - -<tag><tt/PAM_AUTH_ERR/</tag> - The user was not authenticated -<tag><tt/PAM_CRED_INSUFFICIENT/</tag> - For some reason the application does not have sufficient -credentials to authenticate the user. -<tag><tt/PAM_AUTHINFO_UNAVAIL/</tag> - The modules were not able to access the authentication -information. This might be due to a network or hardware failure etc. -<tag><tt/PAM_USER_UNKNOWN/</tag> - The supplied username is not known to the authentication -service -<tag><tt/PAM_MAXTRIES/</tag> - One or more of the authentication modules has reached its -limit of tries authenticating the user. Do not try again. - -</descrip> - -<item> -<tt>PAM_EXTERN int pam_sm_setcred(pam_handle_t *pamh, int flags, int -argc, const char **argv);</tt> - -<p> -This function performs the task of altering the credentials of the -user with respect to the corresponding authorization -scheme. Generally, an authentication module may have access to more -information about a user than their authentication token. This -function is used to make such information available to the -application. It should only be called <em/after/ the user has been -authenticated but before a session has been established. - -<p> -Permitted flags, one of which, may be logically OR'd with -<tt/PAM_SILENT/ are, - -<p><descrip> -<tag><tt/PAM_ESTABLISH_CRED/</tag> - Set the credentials for the authentication service, -<tag><tt/PAM_DELETE_CRED/</tag> - Delete the credentials associated with the authentication service, -<tag><tt/PAM_REINITIALIZE_CRED/</tag> - Reinitialize the user credentials, and -<tag><tt/PAM_REFRESH_CRED/</tag> - Extend the lifetime of the user credentials. -</descrip> - -<p> -Prior to <bf/Linux-PAM-0.75/, and due to a deficiency with the way the -<tt/auth/ stack was handled in the case of the setcred stack being -processed, the module was required to attempt to return the same error -code as <tt/pam_sm_authenticate/ did. This was necessary to preserve -the logic followed by libpam as it executes the stack of -<em/authentication/ modules, when the application called either -<tt/pam_authenticate()/ or <tt/pam_setcred()/. Failing to do this, -led to confusion on the part of the System Administrator. - -<p> -For <bf/Linux-PAM-0.75/ and later, libpam handles the credential stack -much more sanely. The way the <tt/auth/ stack is navigated in order to -evaluate the <tt/pam_setcred()/ function call, independent of the -<tt/pam_sm_setcred()/ return codes, is exactly the same way that it -was navigated when evaluating the <tt/pam_authenticate()/ library -call. Typically, if a stack entry was ignored in evaluating -<tt/pam_authenticate()/, it will be ignored when libpam evaluates the -<tt/pam_setcred()/ function call. Otherwise, the return codes from -each module specific <tt/pam_sm_setcred()/ call are treated as -<tt/required/. - -<p> -Besides <tt/PAM_SUCCESS/, the module may return one of the following -errors: - -<p><descrip> -<tag><tt/PAM_CRED_UNAVAIL/</tag> - This module cannot retrieve the user's credentials. -<tag><tt/PAM_CRED_EXPIRED/</tag> - The user's credentials have expired. -<tag><tt/PAM_USER_UNKNOWN/</tag> - The user is not known to this authentication module. -<tag><tt/PAM_CRED_ERR/</tag> - This module was unable to set the credentials of the user. -</descrip> - -<p> -these, non-<tt/PAM_SUCCESS/, return values will typically lead to the -credential stack <em/failing/. The first such error will dominate in -the return value of <tt/pam_setcred()/. - -</itemize> - -<sect1> Account management - -<p> -To be correctly initialized, <tt/PAM_SM_ACCOUNT/ must be -<tt/#define/'d prior to including <tt><security/pam_modules.h></tt>. -This will ensure that the prototype for a static module is properly -declared. - -<p> -<itemize> - -<item> -<tt>PAM_EXTERN int pam_sm_acct_mgmt(pam_handle_t *pamh, int flags, int -argc, const char **argv);</tt> - -<p> -This function performs the task of establishing whether the user is -permitted to gain access at this time. It should be understood that -the user has previously been validated by an authentication -module. This function checks for other things. Such things might be: -the time of day or the date, the terminal line, remote -hostname, etc. . - -<p> -This function may also determine things like the expiration on -passwords, and respond that the user change it before continuing. - -<p> -Valid flags, which may be logically OR'd with <tt/PAM_SILENT/, are the -same as those applicable to the <tt/flags/ argument of -<tt/pam_sm_authenticate/. - -<p> -This function may return one of the following errors, - -<descrip> - -<tag><tt/PAM_ACCT_EXPIRED/</tag> - The user is no longer permitted access to the system. -<tag><tt/PAM_AUTH_ERR/</tag> - There was an authentication error. -<tag><tt/PAM_NEW_AUTHTOKEN_REQD/</tag> - The user's authentication token has expired. Before calling -this function again the application will arrange for a new one to be -given. This will likely result in a call to <tt/pam_sm_chauthtok()/. -<tag><tt/PAM_USER_UNKNOWN/</tag> - The user is not known to the module's account management -component. - -</descrip> - -</itemize> - -<sect1> Session management - -<p> -To be correctly initialized, <tt/PAM_SM_SESSION/ must be -<tt/#define/'d prior to including -<tt><security/pam_modules.h></tt>. This will ensure that the -prototypes for static modules are properly declared. - -<p> -The following two functions are defined to handle the -initialization/termination of a session. For example, at the beginning -of a session the module may wish to log a message with the system -regarding the user. Similarly, at the end of the session the module -would inform the system that the user's session has ended. - -<p> -It should be possible for sessions to be opened by one application and -closed by another. This either requires that the module uses only -information obtained from <tt/pam_get_item()/, or that information -regarding the session is stored in some way by the operating system -(in a file for example). - -<p> -<itemize> - -<item> -<tt>PAM_EXTERN int pam_sm_open_session(pam_handle_t *pamh, int flags, int -argc, const char **argv);</tt> - -<p> -This function is called to commence a session. The only valid, but -optional, flag is <tt/PAM_SILENT/. - -<p> -As a return value, <tt/PAM_SUCCESS/ signals success and -<tt/PAM_SESSION_ERR/ failure. - -<item> -<tt>PAM_EXTERN int pam_sm_close_session(pam_handle_t *pamh, int flags, int -argc, const char **argv);</tt> - -<p> -This function is called to terminate a session. The only valid, but -optional, flag is <tt/PAM_SILENT/. - -<p> -As a return value, <tt/PAM_SUCCESS/ signals success and -<tt/PAM_SESSION_ERR/ failure. - -</itemize> - -<sect1> Password management - -<p> -To be correctly initialized, <tt/PAM_SM_PASSWORD/ must be -<tt/#define/'d prior to including <tt><security/pam_modules.h></tt>. -This will ensure that the prototype for a static module is properly -declared. - -<p> -<itemize> - -<item> -<tt>PAM_EXTERN int pam_sm_chauthtok(pam_handle_t *pamh, int flags, int -argc, const char **argv);</tt> - -<p> -This function is used to (re-)set the authentication token of the -user. A valid flag, which may be logically OR'd with <tt/PAM_SILENT/, -can be built from the following list, - -<descrip> -<tag><tt/PAM_CHANGE_EXPIRED_AUTHTOK/</tag> - This argument indicates to the module that the users -authentication token (password) should only be changed if it has -expired. This flag is optional and <em/must/ be combined with one of -the following two flags. Note, however, the following two options are -<em/mutually exclusive/. - -<tag><tt/PAM_PRELIM_CHECK/</tag> - This indicates that the modules are being probed as to their -ready status for altering the user's authentication token. If the -module requires access to another system over some network it should -attempt to verify it can connect to this system on receiving this -flag. If a module cannot establish it is ready to update the user's -authentication token it should return <tt/PAM_TRY_AGAIN/, this -information will be passed back to the application. - -<tag><tt/PAM_UPDATE_AUTHTOK/</tag> - This informs the module that this is the call it should change -the authorization tokens. If the flag is logically OR'd with -<tt/PAM_CHANGE_EXPIRED_AUTHTOK/, the token is only changed if it has -actually expired. - -</descrip> - -<p> -Note, the <bf/Linux-PAM/ library calls this function twice in -succession. The first time with <tt/PAM_PRELIM_CHECK/ and then, if the -module does not return <tt/PAM_TRY_AGAIN/, subsequently with -<tt/PAM_UPDATE_AUTHTOK/. It is only on the second call that the -authorization token is (possibly) changed. - -<p> -<tt/PAM_SUCCESS/ is the only successful return value, valid -error-returns are: - -<descrip> -<tag><tt/PAM_AUTHTOK_ERR/</tag> - The module was unable to obtain the new authentication token. - -<tag><tt/PAM_AUTHTOK_RECOVERY_ERR/</tag> - The module was unable to obtain the old authentication token. - -<tag><tt/PAM_AUTHTOK_LOCK_BUSY/</tag> - Cannot change the authentication token since it is currently -locked. - -<tag><tt/PAM_AUTHTOK_DISABLE_AGING/</tag> - Authentication token aging has been disabled. - -<tag><tt/PAM_PERM_DENIED/</tag> - Permission denied. - -<tag><tt/PAM_TRY_AGAIN/</tag> - Preliminary check was unsuccessful. Signals an immediate return -to the application is desired. - -<tag><tt/PAM_USER_UNKNOWN/</tag> - The user is not known to the authentication token changing -service. - -</descrip> - -</itemize> - -<sect>Generic optional arguments - -<p> -Here we list the generic arguments that all modules can expect to -be passed. They are not mandatory, and their absence should be -accepted without comment by the module. - -<p> -<descrip> -<tag><tt/debug/</tag> - -Use the <tt/syslog(3)/ call to log debugging information to the system -log files. - -<tag><tt/no_warn/</tag> - -Instruct module to not give warning messages to the application. - -<tag><tt/use_first_pass/</tag> - -The module should not prompt the user for a password. Instead, it -should obtain the previously typed password (by a call to -<tt/pam_get_item()/ for the <tt/PAM_AUTHTOK/ item), and use that. If -that doesn't work, then the user will not be authenticated. (This -option is intended for <tt/auth/ and <tt/passwd/ modules only). - -<tag><tt/try_first_pass/</tag> - -The module should attempt authentication with the previously typed -password (by a call to <tt/pam_get_item()/ for the <tt/PAM_AUTHTOK/ -item). If that doesn't work, then the user is prompted for a -password. (This option is intended for <tt/auth/ modules only). - -<tag><tt/use_mapped_pass/</tag> - -<bf/WARNING:/ coding this functionality may cause the module writer to -break <em/local/ encryption laws. For example, in the U.S. there are -restrictions on the export computer code that is capable of strong -encryption. It has not been established whether this option is -affected by this law, but one might reasonably assume that it does -until told otherwise. For this reason, this option is not supported -by any of the modules distributed with <bf/Linux-PAM/. - -The intended function of this argument, however, is that the module -should take the existing authentication token from a previously -invoked module and use it as a key to retrieve the authentication -token for this module. For example, the module might create a strong -hash of the <tt/PAM_AUTHTOK/ item (established by a previously -executed module). Then, with logical-exclusive-or, use the result as a -<em/key/ to safely store/retrieve the authentication token for this -module in/from a local file <em/etc/. . - -<tag><tt/expose_account/</tag> - -<p> -In general the leakage of some information about user accounts is not -a secure policy for modules to adopt. Sometimes information such as -users names or home directories, or preferred shell, can be used to -attack a user's account. In some circumstances, however, this sort of -information is not deemed a threat: displaying a user's full name when -asking them for a password in a secured environment could also be -called being 'friendly'. The <tt/expose_account/ argument is a -standard module argument to encourage a module to be less discrete -about account information as it is deemed appropriate by the local -administrator. - -</descrip> - -<sect>Programming notes - -<p> -Here we collect some pointers for the module writer to bear in mind -when writing/developing a <bf/Linux-PAM/ compatible module. - -<sect1>Security issues for module creation - -<sect2>Sufficient resources - -<p> -Care should be taken to ensure that the proper execution of a module -is not compromised by a lack of system resources. If a module is -unable to open sufficient files to perform its task, it should fail -gracefully, or request additional resources. Specifically, the -quantities manipulated by the <tt/setrlimit(2)/ family of commands -should be taken into consideration. - -<sect2>Who's who? - -<p> -Generally, the module may wish to establish the identity of the user -requesting a service. This may not be the same as the username -returned by <tt/pam_get_user()/. Indeed, that is only going to be the -name of the user under whose identity the service will be given. This -is not necessarily the user that requests the service. - -<p> -In other words, user X runs a program that is setuid-Y, it grants the -user to have the permissions of Z. A specific example of this sort of -service request is the <em/su/ program: user <tt/joe/ executes -<em/su/ to become the user <em/jane/. In this situation X=<tt/joe/, -Y=<tt/root/ and Z=<tt/jane/. Clearly, it is important that the module -does not confuse these different users and grant an inappropriate -level of privilege. - -<p> -The following is the convention to be adhered to when juggling -user-identities. - -<p> -<itemize> -<item>X, the identity of the user invoking the service request. -This is the user identifier; returned by the function <tt/getuid(2)/. - -<item>Y, the privileged identity of the application used to grant the -requested service. This is the <em/effective/ user identifier; -returned by the function <tt/geteuid(2)/. - -<item>Z, the user under whose identity the service will be granted. -This is the username returned by <tt/pam_get_user(2)/ and also stored -in the <bf/Linux-PAM/ item, <tt/PAM_USER/. - -<item><bf/Linux-PAM/ has a place for an additional user identity that -a module may care to make use of. This is the <tt/PAM_RUSER/ item. -Generally, network sensitive modules/applications may wish to set/read -this item to establish the identity of the user requesting a service -from a remote location. - -</itemize> - -<p> -Note, if a module wishes to modify the identity of either the <tt/uid/ -or <tt/euid/ of the running process, it should take care to restore -the original values prior to returning control to the <bf/Linux-PAM/ -library. - -<sect2>Using the conversation function -<p> -Prior to calling the conversation function, the module should reset -the contents of the pointer that will return the applications -response. This is a good idea since the application may fail to fill -the pointer and the module should be in a position to notice! - -<p> -The module should be prepared for a failure from the conversation. The -generic error would be <tt/PAM_CONV_ERR/, but anything other than -<tt/PAM_SUCCESS/ should be treated as indicating failure. - -<sect2>Authentication tokens - -<p> -To ensure that the authentication tokens are not left lying around the -items, <tt/PAM_AUTHTOK/ and <tt/PAM_OLDAUTHTOK/, are not available to -the application: they are defined in -<tt><security/pam_modules.h></tt>. This is ostensibly for -security reasons, but a maliciously programmed application will always -have access to all memory of the process, so it is only superficially -enforced. As a general rule the module should overwrite -authentication tokens as soon as they are no longer needed. -Especially before <tt/free()/'ing them. The <bf/Linux-PAM/ library is -required to do this when either of these authentication token items -are (re)set. - -<p> -Not to dwell too little on this concern; should the module store the -authentication tokens either as (automatic) function variables or -using <tt/pam_[gs]et_data()/ the associated memory should be -over-written explicitly before it is released. In the case of the -latter storage mechanism, the associated <tt/cleanup()/ function -should explicitly overwrite the <tt/*data/ before <tt/free()/'ing it: -for example, - -<tscreen> -<verb> -/* - * An example cleanup() function for releasing memory that was used to - * store a password. - */ - -int cleanup(pam_handle_t *pamh, void *data, int error_status) -{ - char *xx; - - if ((xx = data)) { - while (*xx) - *xx++ = '\0'; - free(data); - } - return PAM_SUCCESS; -} -</verb> -</tscreen> - -<sect1>Use of <tt/syslog(3)/ - -<p> -Only rarely should error information be directed to the user. Usually, -this is to be limited to ``<em/sorry you cannot login now/'' type -messages. Information concerning errors in the configuration file, -<tt>/etc/pam.conf</tt>, or due to some system failure encountered by -the module, should be written to <tt/syslog(3)/ with -<em/facility-type/ <tt/LOG_AUTHPRIV/. - -<p> -With a few exceptions, the level of logging is, at the discretion of -the module developer. Here is the recommended usage of different -logging levels: - -<p> -<itemize> - -<item> -As a general rule, errors encountered by a module should be logged at -the <tt/LOG_ERR/ level. However, information regarding an unrecognized -argument, passed to a module from an entry in the -<tt>/etc/pam.conf</tt> file, is <bf/required/ to be logged at the -<tt/LOG_ERR/ level. - -<item> -Debugging information, as activated by the <tt/debug/ argument to the -module in <tt>/etc/pam.conf</tt>, should be logged at the -<tt/LOG_DEBUG/ level. - -<item> -If a module discovers that its personal configuration file or some -system file it uses for information is corrupted or somehow unusable, -it should indicate this by logging messages at level, <tt/LOG_ALERT/. - -<item> -Shortages of system resources, such as a failure to manipulate a file -or <tt/malloc()/ failures should be logged at level <tt/LOG_CRIT/. - -<item> -Authentication failures, associated with an incorrectly typed password -should be logged at level, <tt/LOG_NOTICE/. - -</itemize> - -<sect1> Modules that require system libraries - -<p> -Writing a module is much like writing an application. You have to -provide the "conventional hooks" for it to work correctly, like -<tt>pam_sm_authenticate()</tt> etc., which would correspond to the -<tt/main()/ function in a normal function. - -<p> -Typically, the author may want to link against some standard system -libraries. As when one compiles a normal program, this can be done for -modules too: you simply append the <tt>-l</tt><em>XXX</em> arguments -for the desired libraries when you create the shared module object. To -make sure a module is linked to the <tt>lib<em>whatever</em>.so</tt> -library when it is <tt>dlopen()</tt>ed, try: -<tscreen> -<verb> -% gcc -shared -Xlinker -x -o pam_module.so pam_module.o -lwhatever -</verb> -</tscreen> - -<sect1> Added requirements for <em/statically/ loaded modules. - -<!-- - Copyright (C) Michael K. Johnson 1996. - Last modified: AGM 1996/5/31. - --> - -<p> -Modules may be statically linked into libpam. This should be true of -all the modules distributed with the basic <bf/Linux-PAM/ -distribution. To be statically linked, a module needs to export -information about the functions it contains in a manner that does not -clash with other modules. - -The extra code necessary to build a static module should be delimited -with <tt/#ifdef PAM_STATIC/ and <tt/#endif/. The static code should do -the following: -<itemize> -<item> Define a single structure, <tt/struct pam_module/, called -<tt>_pam_<it>modname</it>_modstruct</tt>, where -<tt><it>modname</it></tt> is the name of the module <bf/as used in the -filesystem/ but without the leading directory name (generally -<tt>/usr/lib/security/</tt> or the suffix (generally <tt/.so/). - -</itemize> - -<p> -As a simple example, consider the following module code which defines -a module that can be compiled to be <em/static/ or <em/dynamic/: - -<p> -<tscreen> -<verb> -#include <stdio.h> /* for NULL define */ - -#define PAM_SM_PASSWORD /* the only pam_sm_... function declared */ -#include <security/pam_modules.h> - -PAM_EXTERN int pam_sm_chauthtok(pam_handle_t *pamh, int flags, - int argc, const char **argv) -{ - return PAM_SUCCESS; -} - -#ifdef PAM_STATIC /* for the case that this module is static */ - -struct pam_module _pam_modname_modstruct = { /* static module data */ - "pam_modname", - NULL, - NULL, - NULL, - NULL, - NULL, - pam_sm_chauthtok, -}; - -#endif /* end PAM_STATIC */ -</verb> -</tscreen> - -<p> -To be linked with <em/libpam/, staticly-linked modules must be built -from within the <tt>Linux-PAM-X.YY/modules/</tt> subdirectory of the -<bf/Linux-PAM/ source directory as part of a normal build of the -<bf/Linux-PAM/ system. - -The <em/Makefile/, for the module in question, must execute the -<tt/register_static/ shell script that is located in the -<tt>Linux-PAM-X.YY/modules/</tt> subdirectory. This is to ensure that -the module is properly registered with <em/libpam/. - -The <bf/two/ manditory arguments to <tt/register_static/ are the -title, and the pathname of the object file containing the module's -code. The pathname is specified relative to the -<tt>Linux-PAM-X.YY/modules</tt> directory. The pathname may be an -empty string---this is for the case that a single object file needs to -register more than one <tt/struct pam_module/. In such a case, exactly -one call to <tt/register_static/ must indicate the object file. - -<p> -Here is an example; a line in the <em/Makefile/ might look like this: -<tscreen> -<verb> -register: -ifdef STATIC - (cd ..; ./register_static pam_modname pam_modname/pam_modname.o) -endif -</verb> -</tscreen> - -For some further examples, see the <tt>modules</tt> subdirectory of -the current <bf/Linux-PAM/ distribution. - -<sect>An example module file - -<p> -At some point, we may include a fully commented example of a module in -this document. For now, we point the reader to these two locations in -the public CVS repository: -<itemize> -<item> A module that always succeeds: <tt><htmlurl -url="http://cvs.sourceforge.net/cgi-bin/viewcvs.cgi/pam/Linux-PAM/modules/pam_permit/" -name="http://cvs.sourceforge.net/cgi-bin/viewcvs.cgi/pam/Linux-PAM/modules/pam_permit/" -></tt> -<item> A module that always fails: <tt><htmlurl -url="http://cvs.sourceforge.net/cgi-bin/viewcvs.cgi/pam/Linux-PAM/modules/pam_deny/" -name="http://cvs.sourceforge.net/cgi-bin/viewcvs.cgi/pam/Linux-PAM/modules/pam_deny/" -></tt> -</itemize> - -<sect>Files - -<p><descrip> - -<tag><tt>/usr/lib/libpam.so.*</tt></tag> - -the shared library providing applications with access to -<bf/Linux-PAM/. - -<tag><tt>/etc/pam.conf</tt></tag> - -the <bf/Linux-PAM/ configuration file. - -<tag><tt>/usr/lib/security/pam_*.so</tt></tag> - -the primary location for <bf/Linux-PAM/ dynamically loadable object -files; the modules. - -</descrip> - -<sect>See also - -<p><itemize> -<item>The <bf/Linux-PAM/ System Administrators' Guide. -<item>The <bf/Linux-PAM/ Application Writers' Guide. -<item> -V. Samar and R. Schemers (SunSoft), ``UNIFIED LOGIN WITH PLUGGABLE -AUTHENTICATION MODULES'', Open Software Foundation Request For -Comments 86.0, October 1995. -</itemize> - -<sect>Notes - -<p> -I intend to put development comments here... like ``at the moment -this isn't actually supported''. At release time what ever is in -this section will be placed in the Bugs section below! :) - -<p> -<itemize> -<item> -Perhaps we should keep a registry of data-names as used by -<tt/pam_[gs]et_data()/ so there are no unintentional problems due to -conflicts? - -<item> -<tt/pam_strerror()/ should be internationalized.... - -<item> -There has been some debate about whether <tt/initgroups()/ should be -in an application or in a module. It was settled by Sun who stated -that initgroups is an action of the <em/application/. The modules are -permitted to add additional groups, however. - -<item> -Refinements/futher suggestions to <tt/syslog(3)/ usage by modules are -needed. - -</itemize> - -<sect>Author/acknowledgments - -<p> -This document was written by Andrew G. Morgan -(<tt/morgan@kernel.org/) with many contributions from -<!-- insert credits here --> -<!-- - an sgml list of people to credit for their contributions to Linux-PAM - $Id$ - --> -Chris Adams, -Peter Allgeyer, -Tim Baverstock, -Tim Berger, -Craig S. Bell, -Derrick J. Brashear, -Ben Buxton, -Seth Chaiklin, -Oliver Crow, -Chris Dent, -Marc Ewing, -Cristian Gafton, -Emmanuel Galanos, -Brad M. Garcia, -Eric Hester, -Roger Hu, -Eric Jacksch, -Michael K. Johnson, -David Kinchlea, -Olaf Kirch, -Marcin Korzonek, -Stephen Langasek, -Nicolai Langfeldt, -Elliot Lee, -Luke Kenneth Casson Leighton, -Al Longyear, -Ingo Luetkebohle, -Marek Michalkiewicz, -Robert Milkowski, -Aleph One, -Martin Pool, -Sean Reifschneider, -Jan Rekorajski, -Erik Troan, -Theodore Ts'o, -Jeff Uphoff, -Myles Uyema, -Savochkin Andrey Vladimirovich, -Ronald Wahl, -David Wood, -John Wilmes, -Joseph S. D. Yao -and -Alex O. Yuriev. - -<p> -Thanks are also due to Sun Microsystems, especially to Vipin Samar and -Charlie Lai for their advice. At an early stage in the development of -<bf/Linux-PAM/, Sun graciously made the documentation for their -implementation of PAM available. This act greatly accelerated the -development of <bf/Linux-PAM/. - -<sect>Bugs/omissions - -<p> -Few PAM modules currently exist. Few PAM-aware applications exist. -This document is hopelessly unfinished. Only a partial list of people is -credited for all the good work they have done. - -<sect>Copyright information for this document - -<p> -Copyright (c) Andrew G. Morgan 1996-2002. All rights reserved. -<newline> -Email: <tt><morgan@kernel.org></tt> - -<p> -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - -<p> -<itemize> - -<item> -1. Redistributions of source code must retain the above copyright - notice, and the entire permission notice in its entirety, - including the disclaimer of warranties. - -<item> -2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - -<item> -3. The name of the author may not be used to endorse or promote - products derived from this software without specific prior - written permission. - -</itemize> - -<p> -<bf/Alternatively/, this product may be distributed under the terms of -the GNU General Public License (GPL), in which case the provisions of -the GNU GPL are required <bf/instead of/ the above restrictions. -(This clause is necessary due to a potential bad interaction between -the GNU GPL and the restrictions contained in a BSD-style copyright.) - -<p> -THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED -WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, -INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS -OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR -TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE -USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH -DAMAGE. - -<p> -<tt>$Id$</tt> - -</article> |