1 <?xml version='1.0' encoding='UTF-8'?>
2 <!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN"
3 "http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd">
6 <title>The Linux-PAM Application Developers' Guide</title>
9 <firstname>Andrew G.</firstname>
10 <surname>Morgan</surname>
11 <email>morgan@kernel.org</email>
14 <firstname>Thorsten</firstname>
15 <surname>Kukuk</surname>
16 <email>kukuk@thkukuk.de</email>
19 <releaseinfo>Version 0.99, 24. June 2006</releaseinfo>
22 This manual documents what an application developer needs to know
23 about the <emphasis remap='B'>Linux-PAM</emphasis> library. It
24 describes how an application might use the
25 <emphasis remap='B'>Linux-PAM</emphasis> library to authenticate
26 users. In addition it contains a description of the funtions
27 to be found in <filename>libpam_misc</filename> library, that can
28 be used in general applications. Finally, it contains some comments
29 on PAM related security issues for the application developer.
34 <chapter id="adg-introduction">
35 <title>Introduction</title>
36 <section id="adg-introduction-description">
37 <title>Description</title>
39 <emphasis remap='B'>Linux-PAM</emphasis>
40 (Pluggable Authentication Modules for Linux) is a library that enables
41 the local system administrator to choose how individual applications
42 authenticate users. For an overview of the
43 <emphasis remap='B'>Linux-PAM</emphasis> library see the
44 <emphasis>Linux-PAM System Administrators' Guide</emphasis>.
47 It is the purpose of the <emphasis remap='B'>Linux-PAM</emphasis>
48 project to liberate the development of privilege granting software
49 from the development of secure and appropriate authentication schemes.
50 This is accomplished by providing a documented library of functions
51 that an application may use for all forms of user authentication
52 management. This library dynamically loads locally configured
53 authentication modules that actually perform the authentication tasks.
56 From the perspective of an application developer the information
57 contained in the local configuration of the PAM library should not be
58 important. Indeed it is intended that an application treat the
59 functions documented here as a 'black box' that will deal with all
60 aspects of user authentication. 'All aspects' includes user
61 verification, account management, session initialization/termination
62 and also the resetting of passwords
63 (<emphasis>authentication tokens</emphasis>).
67 <section id="adg-introduction-synopsis">
68 <title>Synopsis</title>
70 For general applications that wish to use the services provided by
71 <emphasis remap='B'>Linux-PAM</emphasis> the following is a summary
72 of the relevant linking information:
74 #include <security/pam_appl.h>
76 cc -o application .... -lpam
80 In addition to <command>libpam</command>, there is a library of
81 miscellaneous functions that make the job of writing
82 <emphasis>PAM-aware</emphasis> applications easier (this library is not
83 covered in the DCE-RFC for PAM and is specific to the Linux-PAM
86 #include <security/pam_appl.h>
87 #include <security/pam_misc.h>
89 cc -o application .... -lpam -lpam_misc
95 <chapter id="adg-overview">
96 <title>Overview</title>
98 Most service-giving applications are restricted. In other words,
99 their service is not available to all and every prospective client.
100 Instead, the applying client must jump through a number of hoops to
101 convince the serving application that they are authorized to obtain
105 The process of <emphasis>authenticating</emphasis> a client is what
106 PAM is designed to manage. In addition to authentication, PAM provides
107 account management, credential management, session management and
108 authentication-token (password changing) management services. It is
109 important to realize when writing a PAM based application that these
110 services are provided in a manner that is
111 <emphasis remap='B'>transparent</emphasis> to the application. That is
112 to say, when the application is written, no assumptions can be made
113 about <emphasis>how</emphasis> the client will be authenticated.
116 The process of authentication is performed by the PAM library via a
117 call to <function>pam_authenticate()</function>. The return value
118 of this function will indicate whether a named client (the
119 <emphasis>user</emphasis>) has been authenticated. If the PAM library
120 needs to prompt the user for any information, such as their
121 <emphasis>name</emphasis> or a <emphasis>password</emphasis>
122 then it will do so. If the PAM library is configured to authenticate
123 the user using some silent protocol, it will do this too. (This
124 latter case might be via some hardware interface for example.)
127 It is important to note that the application must leave all decisions
128 about when to prompt the user at the discretion of the PAM library.
131 The PAM library, however, must work equally well for different styles
132 of application. Some applications, like the familiar
133 <command>login</command> and <command>passwd</command> are terminal
134 based applications, exchanges of information with the client in
135 these cases is as plain text messages. Graphically based applications,
136 however, have a more sophisticated interface. They generally interact
137 with the user via specially constructed dialogue boxes. Additionally,
138 network based services require that text messages exchanged with the
139 client are specially formatted for automated processing: one such
140 example is <command>ftpd</command> which prefixes each exchanged
141 message with a numeric identifier.
144 The presentation of simple requests to a client is thus something very
145 dependent on the protocol that the serving application will use. In
146 spite of the fact that PAM demands that it drives the whole
147 authentication process, it is not possible to leave such protocol
148 subtleties up to the PAM library. To overcome this potential problem,
149 the application provides the PAM library with a
150 <emphasis>conversation</emphasis> function. This function is called
151 from <emphasis>within</emphasis> the PAM library and enables the PAM
152 to directly interact with the client. The sorts of things that this
153 conversation function must be able to do are prompt the user with
154 text and/or obtain textual input from the user for processing by the
155 PAM library. The details of this function are provided in a later
159 For example, the conversation function may be called by the PAM
160 library with a request to prompt the user for a password. Its job is
161 to reformat the prompt request into a form that the client will
162 understand. In the case of <command>ftpd</command>, this might involve
163 prefixing the string with the number <command>331</command> and sending
164 the request over the network to a connected client. The conversation
165 function will then obtain any reply and, after extracting the typed
166 password, will return this string of text to the PAM library. Similar
167 concerns need to be addressed in the case of an X-based graphical
171 There are a number of issues that need to be addressed when one is
172 porting an existing application to become PAM compliant. A section
173 below has been devoted to this: Porting legacy applications.
176 Besides authentication, PAM provides other forms of management.
177 Session management is provided with calls to
178 <function>pam_open_session()</function> and
179 <function>pam_close_session()</function>. What these functions
180 actually do is up to the local administrator. But typically, they
181 could be used to log entry and exit from the system or for mounting
182 and unmounting the user's home directory. If an application provides
183 continuous service for a period of time, it should probably call
184 these functions, first open after the user is authenticated and then
185 close when the service is terminated.
188 Account management is another area that an application developer
189 should include with a call to <function>pam_acct_mgmt()</function>.
190 This call will perform checks on the good health of the user's account
191 (has it expired etc.). One of the things this function may check is
192 whether the user's authentication token has expired - in such a case the
193 application may choose to attempt to update it with a call to
194 <function>pam_chauthtok()</function>, although some applications
195 are not suited to this task (<command>ftp</command> for example)
196 and in this case the application should deny access to the user.
199 PAM is also capable of setting and deleting the users credentials with
200 the call <function>pam_setcred()</function>. This function should
201 always be called after the user is authenticated and before service
202 is offered to the user. By convention, this should be the last call
203 to the PAM library before the PAM session is opened. What exactly a
204 credential is, is not well defined. However, some examples are given
205 in the glossary below.
209 <chapter id="adg-interface">
211 The public interface to <emphasis remap='B'>Linux-PAM</emphasis>
214 Firstly, the relevant include file for the
215 <emphasis remap='B'>Linux-PAM</emphasis> library is
216 <function><security/pam_appl.h></function>.
217 It contains the definitions for a number of functions. After
218 listing these functions, we collect some guiding remarks for
221 <section id="adg-interface-by-app-expected">
222 <title>What can be expected by the application</title>
223 <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
224 href="pam_start.xml"/>
225 <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
227 <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
228 href="pam_set_item.xml"/>
229 <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
230 href="pam_get_item.xml"/>
231 <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
232 href="pam_strerror.xml"/>
233 <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
234 href="pam_fail_delay.xml"/>
235 <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
236 href="pam_authenticate.xml"/>
237 <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
238 href="pam_setcred.xml"/>
239 <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
240 href="pam_acct_mgmt.xml"/>
241 <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
242 href="pam_chauthtok.xml"/>
243 <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
244 href="pam_open_session.xml"/>
245 <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
246 href="pam_close_session.xml"/>
247 <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
248 href="pam_putenv.xml"/>
249 <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
250 href="pam_getenv.xml"/>
251 <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
252 href="pam_getenvlist.xml"/>
254 <section id="adg-interface-of-app-expected">
255 <title>What is expected of an application</title>
256 <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
257 href="pam_conv.xml"/>
259 <section id="adg-interface-programming-notes">
260 <title>Programming notes</title>
262 Note, all of the authentication service function calls accept the
263 token <emphasis remap='B'>PAM_SILENT</emphasis>, which instructs
264 the modules to not send messages to the application. This token
265 can be logically OR'd with any one of the permitted tokens specific
266 to the individual function calls.
267 <emphasis remap='B'>PAM_SILENT</emphasis> does not override the
268 prompting of the user for passwords etc., it only stops informative
269 messages from being generated.
274 <chapter id="adg-security">
276 Security issues of <emphasis remap='B'>Linux-PAM</emphasis>
279 PAM, from the perspective of an application, is a convenient API for
280 authenticating users. PAM modules generally have no increased
281 privilege over that possessed by the application that is making use of
282 it. For this reason, the application must take ultimate responsibility
283 for protecting the environment in which PAM operates.
286 A poorly (or maliciously) written application can defeat any
287 <emphasis remap='B'>Linux-PAM</emphasis> module's authentication
288 mechanisms by simply ignoring it's return values. It is the
289 applications task and responsibility to grant privileges and access
290 to services. The <emphasis remap='B'>Linux-PAM</emphasis> library
291 simply assumes the responsibility of <emphasis>authenticating</emphasis>
292 the user; ascertaining that the user <emphasis>is</emphasis> who they
293 say they are. Care should be taken to anticipate all of the documented
294 behavior of the <emphasis remap='B'>Linux-PAM</emphasis> library
295 functions. A failure to do this will most certainly lead to a future
299 <section id="adg-security-library-calls">
300 <title>Care about standard library calls</title>
302 In general, writers of authorization-granting applications should
303 assume that each module is likely to call any or
304 <emphasis>all</emphasis> 'libc' functions. For 'libc' functions
305 that return pointers to static/dynamically allocated structures
306 (ie. the library allocates the memory and the user is not expected
307 to '<function>free()</function>' it) any module call to this
308 function is likely to corrupt a pointer previously
309 obtained by the application. The application programmer should
310 either re-call such a 'libc' function after a call to the
311 <emphasis remap='B'>Linux-PAM</emphasis> library, or copy the
312 structure contents to some safe area of memory before passing
313 control to the <emphasis remap='B'>Linux-PAM</emphasis> library.
316 Two important function classes that fall into this category are
318 <refentrytitle>getpwnam</refentrytitle><manvolnum>3</manvolnum>
319 </citerefentry> and <citerefentry>
320 <refentrytitle>syslog</refentrytitle><manvolnum>3</manvolnum>
325 <section id="adg-security-service-name">
326 <title>Choice of a service name</title>
328 When picking the <emphasis>service-name</emphasis> that
329 corresponds to the first entry in the
330 <emphasis remap='B'>Linux-PAM</emphasis> configuration file,
331 the application programmer should <emphasis>avoid</emphasis>
332 the temptation of choosing something related to
333 <varname>argv[0]</varname>. It is a trivial matter for any user
334 to invoke any application on a system under a different name and
335 this should not be permitted to cause a security breach.
338 In general, this is always the right advice if the program is
339 setuid, or otherwise more privileged than the user that invokes
340 it. In some cases, avoiding this advice is convenient, but as an
341 author of such an application, you should consider well the ways
342 in which your program will be installed and used. (Its often the
343 case that programs are not intended to be setuid, but end up
344 being installed that way for convenience. If your program falls
345 into this category, don't fall into the trap of making this mistake.)
348 To invoke some <emphasis>target</emphasis> application by
349 another name, the user may symbolically link the target application
350 with the desired name. To be precise all the user need do is,
351 <command>ln -s /target/application ./preferred_name</command>
352 and then run <command>./preferred_name</command>.
355 By studying the <emphasis remap='B'>Linux-PAM</emphasis>
356 configuration file(s), an attacker can choose the
357 <command>preferred_name</command> to be that of a service enjoying
358 minimal protection; for example a game which uses
359 <emphasis remap='B'>Linux-PAM</emphasis> to restrict access to
360 certain hours of the day. If the service-name were to be linked
361 to the filename under which the service was invoked, it
362 is clear that the user is effectively in the position of
363 dictating which authentication scheme the service uses. Needless
364 to say, this is not a secure situation.
367 The conclusion is that the application developer should carefully
368 define the service-name of an application. The safest thing is to
369 make it a single hard-wired name.
373 <section id="adg-security-conv-function">
374 <title>The conversation function</title>
376 Care should be taken to ensure that the <function>conv()</function>
377 function is robust. Such a function is provided in the library
378 <command>libpam_misc</command> (see
379 <link linkend="adg-libpam-functions">below</link>).
383 <section id="adg-security-usre-identity">
384 <title>The identity of the user</title>
386 The <emphasis remap='B'>Linux-PAM</emphasis> modules will need
387 to determine the identity of the user who requests a service,
388 and the identity of the user who grants the service. These two
389 users will seldom be the same. Indeed there is generally a third
390 user identity to be considered, the new (assumed) identity of
391 the user once the service is granted.
394 The need for keeping tabs on these identities is clearly an
395 issue of security. One convention that is actively used by
396 some modules is that the identity of the user requesting a
397 service should be the current <emphasis>UID</emphasis>
398 (userid) of the running process; the identity of the
399 privilege granting user is the <emphasis>EUID</emphasis>
400 (effective userid) of the running process; the identity of
401 the user, under whose name the service will be executed, is
402 given by the contents of the <emphasis>PAM_USER</emphasis>
404 <refentrytitle>pam_get_item</refentrytitle><manvolnum>3</manvolnum>
405 </citerefentry>. Note, modules can change the values of
406 <emphasis>PAM_USER</emphasis> and <emphasis>PAM_RUSER</emphasis>
407 during any of the <function>pam_*()</function> library calls.
408 For this reason, the application should take care to use the
409 <function>pam_get_item()</function> every time it wishes to
410 establish who the authenticated user is (or will currently be).
413 For network-serving databases and other applications that provide
414 their own security model (independent of the OS kernel) the above
415 scheme is insufficient to identify the requesting user.
418 A more portable solution to storing the identity of the requesting
419 user is to use the <emphasis>PAM_RUSER</emphasis> <citerefentry>
420 <refentrytitle>pam_get_item</refentrytitle><manvolnum>3</manvolnum>
421 </citerefentry>. The application should supply this value before
422 attempting to authenticate the user with
423 <function>pam_authenticate()</function>. How well this name can be
424 trusted will ultimately be at the discretion of the local
425 administrator (who configures PAM for your application) and a
426 selected module may attempt to override the value where it can
427 obtain more reliable data. If an application is unable to determine
428 the identity of the requesting entity/user, it should not call
430 <refentrytitle>pam_set_item</refentrytitle><manvolnum>3</manvolnum>
431 </citerefentry> to set <emphasis>PAM_RUSER</emphasis>.
434 In addition to the <emphasis>PAM_RUSER</emphasis> item, the
435 application should supply the <emphasis>PAM_RHOST</emphasis>
436 (<emphasis>requesting host</emphasis>) item. As a general rule,
437 the following convention for its value can be assumed:
438 NULL = unknown; localhost = invoked directly from the local system;
439 <emphasis>other.place.xyz</emphasis> = some component of the
440 user's connection originates from this remote/requesting host. At
441 present, PAM has no established convention for indicating whether
442 the application supports a trusted path to communication from
447 <section id="adg-security-resources">
448 <title>Sufficient resources</title>
450 Care should be taken to ensure that the proper execution of an
451 application is not compromised by a lack of system resources. If an
452 application is unable to open sufficient files to perform its service,
453 it should fail gracefully, or request additional resources.
454 Specifically, the quantities manipulated by the <citerefentry>
455 <refentrytitle>setrlimit</refentrytitle><manvolnum>2</manvolnum>
456 </citerefentry> family of commands should be taken into consideration.
459 This is also true of conversation prompts. The application should not
460 accept prompts of arbitrary length with out checking for resource
461 allocation failure and dealing with such extreme conditions gracefully
462 and in a mannor that preserves the PAM API. Such tolerance may be
463 especially important when attempting to track a malicious adversary.
468 <chapter id='adg-libpam_misc'>
469 <title>A library of miscellaneous helper functions</title>
471 To aid the work of the application developer a library of
472 miscellaneous functions is provided. It is called
473 <command>libpam_miscy</command>, and contains a text based
474 conversation function, and routines for enhancing the standard
475 PAM-environment variable support.
478 The functions, structures and macros, made available by this
479 library can be defined by including
480 <function><security/pam_misc.h></function>. It should be
481 noted that this library is specific to
482 <emphasis remap='B'>Linux-PAM</emphasis> and is not referred to in
483 the defining DCE-RFC (see <link linkend="adg-see-also">See also</link>)
486 <section id='adg-libpam-functions'>
487 <title>Functions supplied</title>
488 <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
489 href="pam_misc_conv.xml"/>
490 <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
491 href="pam_misc_paste_env.xml"/>
492 <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
493 href="pam_misc_drop_env.xml"/>
494 <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
495 href="pam_misc_setenv.xml"/>
499 <chapter id='adg-porting'>
500 <title>Porting legacy applications</title>
502 The point of PAM is that the application is not supposed to
503 have any idea how the attached authentication modules will choose
504 to authenticate the user. So all they can do is provide a conversation
505 function that will talk directly to the user(client) on the modules'
509 Consider the case that you plug a retinal scanner into the login
510 program. In this situation the user would be prompted: "please look
511 into the scanner". No username or password would be needed - all this
512 information could be deduced from the scan and a database lookup. The
513 point is that the retinal scanner is an ideal task for a "module".
516 While it is true that a pop-daemon program is designed with the POP
517 protocol in mind and no-one ever considered attaching a retinal
518 scanner to it, it is also the case that the "clean" PAM'ification of
519 such a daemon would allow for the possibility of a scanner module
520 being be attached to it. The point being that the "standard"
521 pop-authentication protocol(s) [which will be needed to satisfy
522 inflexible/legacy clients] would be supported by inserting an
523 appropriate pam_qpopper module(s). However, having rewritten popd
524 once in this way any new protocols can be implemented in-situ.
527 One simple test of a ported application would be to insert the
528 <command>pam_permit</command> module and see if the application
529 demands you type a password... In such a case, <command>xlock</command>
530 would fail to lock the terminal - or would at best be a screen-saver,
531 ftp would give password free access to all etc.. Neither of
532 these is a very secure thing to do, but they do illustrate how
533 much flexibility PAM puts in the hands of the local admin.
536 The key issue, in doing things correctly, is identifying what is part
537 of the authentication procedure (how many passwords etc..) the
538 exchange protocol (prefixes to prompts etc., numbers like 331 in the
539 case of ftpd) and what is part of the service that the application
540 delivers. PAM really needs to have total control in the
541 authentication "procedure", the conversation function should only
542 deal with reformatting user prompts and extracting responses from raw
547 <chapter id='adg-glossary'>
548 <title>Glossary of PAM related terms</title>
550 The following are a list of terms used within this document.
554 <term>Authentication token</term>
557 Generally, this is a password. However, a user can authenticate
558 him/herself in a variety of ways. Updating the user's
559 authentication token thus corresponds to
560 <emphasis>refreshing</emphasis> the object they use to
561 authenticate themself with the system. The word password is
562 avoided to keep open the possibility that the authentication
563 involves a retinal scan or other non-textual mode of
569 <term>Credentials</term>
572 Having successfully authenticated the user, PAM is able to
573 establish certain characteristics/attributes of the user.
574 These are termed <emphasis>credentials</emphasis>. Examples
575 of which are group memberships to perform privileged tasks
576 with, and <emphasis>tickets</emphasis> in the form of
577 environment variables etc. . Some user-credentials, such as
578 the user's UID and GID (plus default group memberships) are
579 not deemed to be PAM-credentials. It is the responsibility
580 of the application to grant these directly.
587 <chapter id='adg-example'>
588 <title>An example application</title>
590 To get a flavor of the way a <emphasis remap='B'>Linux-PAM</emphasis>
591 application is written we include the following example. It prompts
592 the user for their password and indicates whether their account
593 is valid on the standard output, its return code also indicates
594 the success (<returnvalue>0</returnvalue> for success;
595 <returnvalue>1</returnvalue> for failure).
597 <programlisting><![CDATA[
599 This program was contributed by Shane Watts
600 [modifications by AGM and kukuk]
602 You need to add the following (or equivalent) to the
603 /etc/pam.d/check_user file:
604 # check authorization
605 auth required pam_unix.so
606 account required pam_unix.so
609 #include <security/pam_appl.h>
610 #include <security/pam_misc.h>
613 static struct pam_conv conv = {
618 int main(int argc, char *argv[])
620 pam_handle_t *pamh=NULL;
622 const char *user="nobody";
629 fprintf(stderr, "Usage: check_user [username]\n");
633 retval = pam_start("check_user", user, &conv, &pamh);
635 if (retval == PAM_SUCCESS)
636 retval = pam_authenticate(pamh, 0); /* is user really user? */
638 if (retval == PAM_SUCCESS)
639 retval = pam_acct_mgmt(pamh, 0); /* permitted access? */
641 /* This is where we have been authorized or not. */
643 if (retval == PAM_SUCCESS) {
644 fprintf(stdout, "Authenticated\n");
646 fprintf(stdout, "Not Authenticated\n");
649 if (pam_end(pamh,retval) != PAM_SUCCESS) { /* close Linux-PAM */
651 fprintf(stderr, "check_user: failed to release authenticator\n");
655 return ( retval == PAM_SUCCESS ? 0:1 ); /* indicate success */
661 <chapter id='adg-files'>
665 <term><filename>/usr/include/security/pam_appl.h</filename></term>
668 Header file with interfaces for
669 <emphasis remap='B'>Linux-PAM</emphasis> applications.
674 <term><filename>/usr/include/security/pam_misc.h</filename></term>
677 Header file for useful library functions for making
678 applications easier to write.
685 <chapter id="adg-see-also">
686 <title>See also</title>
690 The Linux-PAM System Administrators' Guide.
695 The Linux-PAM Module Writers' Guide.
700 The V. Samar and R. Schemers (SunSoft), ``UNIFIED LOGIN WITH
701 PLUGGABLE AUTHENTICATION MODULES'', Open Software Foundation
702 Request For Comments 86.0, October 1995.
708 <chapter id='adg-author'>
709 <title>Author/acknowledgments</title>
711 This document was written by Andrew G. Morgan (morgan@kernel.org)
712 with many contributions from
713 Chris Adams, Peter Allgeyer, Tim Baverstock, Tim Berger, Craig S. Bell,
714 Derrick J. Brashear, Ben Buxton, Seth Chaiklin, Oliver Crow, Chris Dent,
715 Marc Ewing, Cristian Gafton, Emmanuel Galanos, Brad M. Garcia,
716 Eric Hester, Roger Hu, Eric Jacksch, Michael K. Johnson, David Kinchlea,
717 Olaf Kirch, Marcin Korzonek, Thorsten Kukuk, Stephen Langasek,
718 Nicolai Langfeldt, Elliot Lee, Luke Kenneth Casson Leighton,
719 Al Longyear, Ingo Luetkebohle, Marek Michalkiewicz, Robert Milkowski,
720 Aleph One, Martin Pool, Sean Reifschneider, Jan Rekorajski, Erik Troan,
721 Theodore Ts'o, Jeff Uphoff, Myles Uyema, Savochkin Andrey Vladimirovich,
722 Ronald Wahl, David Wood, John Wilmes, Joseph S. D. Yao
726 Thanks are also due to Sun Microsystems, especially to Vipin Samar and
727 Charlie Lai for their advice. At an early stage in the development of
728 <emphasis remap='B'>Linux-PAM</emphasis>, Sun graciously made the
729 documentation for their implementation of PAM available. This act
730 greatly accelerated the development of
731 <emphasis remap='B'>Linux-PAM</emphasis>.
735 <chapter id='adg-copyright'>
736 <title>Copyright information for this document</title>
738 Copyright (c) 2006 Thorsten Kukuk <kukuk@thkukuk.de>
739 Copyright (c) 1996-2002 Andrew G. Morgan <morgan@kernel.org>
742 Redistribution and use in source and binary forms, with or without
743 modification, are permitted provided that the following conditions are
747 1. Redistributions of source code must retain the above copyright
748 notice, and the entire permission notice in its entirety,
749 including the disclaimer of warranties.
751 2. Redistributions in binary form must reproduce the above copyright
752 notice, this list of conditions and the following disclaimer in the
753 documentation and/or other materials provided with the distribution.
755 3. The name of the author may not be used to endorse or promote
756 products derived from this software without specific prior
760 Alternatively, this product may be distributed under the terms of
761 the GNU General Public License (GPL), in which case the provisions
762 of the GNU GPL are required instead of the above restrictions.
763 (This clause is necessary due to a potential bad interaction between
764 the GNU GPL and the restrictions contained in a BSD-style copyright.)
767 THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
768 WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
769 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
770 IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
771 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
772 BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
773 OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
774 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
775 TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
776 USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH