Linux-PAM_MWG.xml 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632
  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">
  4. <book id="mwg">
  5. <bookinfo>
  6. <title>The Linux-PAM Module Writers' Guide</title>
  7. <authorgroup>
  8. <author>
  9. <firstname>Andrew G.</firstname>
  10. <surname>Morgan</surname>
  11. <email>morgan@kernel.org</email>
  12. </author>
  13. <author>
  14. <firstname>Thorsten</firstname>
  15. <surname>Kukuk</surname>
  16. <email>kukuk@thkukuk.de</email>
  17. </author>
  18. </authorgroup>
  19. <releaseinfo>Version 1.1.2, 31. August 2010</releaseinfo>
  20. <abstract>
  21. <para>
  22. This manual documents what a programmer needs to know in order
  23. to write a module that conforms to the
  24. <emphasis remap='B'>Linux-PAM</emphasis> standard.It also
  25. discusses some security issues from the point of view of the
  26. module programmer.
  27. </para>
  28. </abstract>
  29. </bookinfo>
  30. <chapter id="mwg-introduction">
  31. <title>Introduction</title>
  32. <section id="mwg-introduction-description">
  33. <title>Description</title>
  34. <para>
  35. <emphasis remap='B'>Linux-PAM</emphasis> (Pluggable Authentication
  36. Modules for Linux) is a library that enables the local system
  37. administrator to choose how individual applications authenticate
  38. users. For an overview of the
  39. <emphasis remap='B'>Linux-PAM</emphasis> library see the
  40. <emphasis>Linux-PAM System Administrators' Guide</emphasis>.
  41. </para>
  42. <para>
  43. A <emphasis remap='B'>Linux-PAM</emphasis> module is a single
  44. executable binary file that can be loaded by the
  45. <emphasis remap='B'>Linux-PAM</emphasis> interface library.
  46. This PAM library is configured locally with a system file,
  47. <filename>/etc/pam.conf</filename>, to authenticate a user
  48. request via the locally available authentication modules. The
  49. modules themselves will usually be located in the directory
  50. <filename>/lib/security</filename> (or
  51. <filename>/lib64/security</filename>, depending on the architecture)
  52. and take the form of dynamically loadable object files (see
  53. <citerefentry>
  54. <refentrytitle>dlopen</refentrytitle><manvolnum>3</manvolnum>
  55. </citerefentry>. Alternatively, the modules can be statically
  56. linked into the <emphasis remap='B'>Linux-PAM</emphasis> library;
  57. this is mostly to allow <emphasis remap='B'>Linux-PAM</emphasis> to
  58. be used on platforms without dynamic linking available, but this is
  59. a <emphasis>deprecated</emphasis> functionality. It is the
  60. <emphasis remap='B'>Linux-PAM</emphasis> interface that is called
  61. by an application and it is the responsibility of the library to
  62. locate, load and call the appropriate functions in a
  63. <emphasis remap='B'>Linux-PAM</emphasis>-module.
  64. </para>
  65. <para>
  66. Except for the immediate purpose of interacting with the user
  67. (entering a password etc..) the module should never call the
  68. application directly. This exception requires a "conversation
  69. mechanism" which is documented below.
  70. </para>
  71. </section>
  72. <section id="mwg-introduction-synopsis">
  73. <title>Synopsis</title>
  74. <programlisting>
  75. #include &lt;security/pam_modules.h&gt;
  76. gcc -fPIC -c pam_module.c
  77. gcc -shared -o pam_module.so pam_module.o -lpam
  78. </programlisting>
  79. </section>
  80. </chapter>
  81. <chapter id="mwg-expected-by-module">
  82. <title>What can be expected by the module</title>
  83. <para>
  84. Here we list the interface that the conventions that all
  85. <emphasis remap='B'>Linux-PAM</emphasis> modules must adhere to.
  86. </para>
  87. <section id="mwg-expected-by-module-item">
  88. <title>
  89. Getting and setting <emphasis>PAM_ITEM</emphasis>s and
  90. <emphasis>data</emphasis>
  91. </title>
  92. <para>
  93. First, we cover what the module should expect from the
  94. <emphasis remap='B'>Linux-PAM</emphasis> library and a
  95. <emphasis remap='B'>Linux-PAM</emphasis> aware application.
  96. Essentially this is the <filename>libpam.*</filename> library.
  97. </para>
  98. <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
  99. href="pam_set_data.xml"/>
  100. <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
  101. href="pam_get_data.xml"/>
  102. <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
  103. href="pam_set_item.xml"/>
  104. <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
  105. href="pam_get_item.xml"/>
  106. <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
  107. href="pam_get_user.xml"/>
  108. <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
  109. href="pam_conv.xml"/>
  110. <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
  111. href="pam_putenv.xml"/>
  112. <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
  113. href="pam_getenv.xml"/>
  114. <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
  115. href="pam_getenvlist.xml"/>
  116. </section>
  117. <section id="mwg-expected-by-module-other">
  118. <title>
  119. Other functions provided by <filename>libpam</filename>
  120. </title>
  121. <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
  122. href="pam_strerror.xml"/>
  123. <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
  124. href="pam_fail_delay.xml"/>
  125. </section>
  126. </chapter>
  127. <chapter id="mwg-expected-of-module">
  128. <title>What is expected of a module</title>
  129. <para>
  130. The module must supply a sub-set of the six functions listed
  131. below. Together they define the function of a
  132. <emphasis remap='B'>Linux-PAM module</emphasis>. Module developers
  133. are strongly urged to read the comments on security that follow
  134. this list.
  135. </para>
  136. <section id="mwg-expected-of-module-overview">
  137. <title>Overview</title>
  138. <para>
  139. The six module functions are grouped into four independent
  140. management groups. These groups are as follows:
  141. <emphasis>authentication</emphasis>, <emphasis>account</emphasis>,
  142. <emphasis>session</emphasis> and <emphasis>password</emphasis>.
  143. To be properly defined, a module must define all functions within
  144. at least one of these groups. A single module may contain the
  145. necessary functions for <emphasis>all</emphasis> four groups.
  146. </para>
  147. <section id="mwg-expected-of-module-overview-1">
  148. <title>Functional independence</title>
  149. <para>
  150. The independence of the four groups of service a module can
  151. offer means that the module should allow for the possibility
  152. that any one of these four services may legitimately be called
  153. in any order. Thus, the module writer should consider the
  154. appropriateness of performing a service without the prior
  155. success of some other part of the module.
  156. </para>
  157. <para>
  158. As an informative example, consider the possibility that an
  159. application applies to change a user's authentication token,
  160. without having first requested that
  161. <emphasis remap='B'>Linux-PAM</emphasis> authenticate the
  162. user. In some cases this may be deemed appropriate: when
  163. <command>root</command> wants to change the authentication
  164. token of some lesser user. In other cases it may not be
  165. appropriate: when <command>joe</command> maliciously wants
  166. to reset <command>alice</command>'s password; or when anyone
  167. other than the user themself wishes to reset their
  168. <emphasis>KERBEROS</emphasis> authentication token. A policy
  169. for this action should be defined by any reasonable
  170. authentication scheme, the module writer should consider
  171. this when implementing a given module.
  172. </para>
  173. </section>
  174. <section id="mwg-expected-of-module-overview-2">
  175. <title>Minimizing administration problems</title>
  176. <para>
  177. To avoid system administration problems and the poor
  178. construction of a <filename>/etc/pam.conf</filename> file,
  179. the module developer may define all six of the following
  180. functions. For those functions that would not be called,
  181. the module should return <errorname>PAM_SERVICE_ERR</errorname>
  182. and write an appropriate message to the system log. When
  183. this action is deemed inappropriate, the function would
  184. simply return <errorname>PAM_IGNORE</errorname>.
  185. </para>
  186. </section>
  187. <section id="mwg-expected-of-module-overview-3">
  188. <title>Arguments supplied to the module</title>
  189. <para>
  190. The <parameter>flags</parameter> argument of each of
  191. the following functions can be logically OR'd with
  192. <parameter>PAM_SILENT</parameter>, which is used to inform the
  193. module to not pass any <emphasis>text</emphasis> (errors or
  194. warnings) application.
  195. </para>
  196. <para>
  197. The <parameter>argc</parameter> and <parameter>argv</parameter>
  198. arguments are taken from the line appropriate to this
  199. module---that is, with the <emphasis>service_name</emphasis>
  200. matching that of the application---in the configuration file
  201. (see the <emphasis remap='B'>Linux-PAM</emphasis>
  202. System Administrators' Guide). Together these two parameters
  203. provide the number of arguments and an array of pointers to
  204. the individual argument tokens. This will be familiar to C
  205. programmers as the ubiquitous method of passing command arguments
  206. to the function <function>main()</function>. Note, however, that
  207. the first argument (<parameter>argv[0]</parameter>) is a true
  208. argument and <emphasis>not</emphasis> the name of the module.
  209. </para>
  210. </section>
  211. </section>
  212. <section id="mwg-expected-of-module-auth">
  213. <title>Authentication management</title>
  214. <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
  215. href="pam_sm_authenticate.xml"/>
  216. <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
  217. href="pam_sm_setcred.xml"/>
  218. </section>
  219. <section id="mwg-expected-of-module-acct">
  220. <title>Account management</title>
  221. <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
  222. href="pam_sm_acct_mgmt.xml"/>
  223. </section>
  224. <section id="mwg-expected-of-module-session">
  225. <title>Session management</title>
  226. <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
  227. href="pam_sm_open_session.xml"/>
  228. <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
  229. href="pam_sm_close_session.xml"/>
  230. </section>
  231. <section id="mwg-expected-of-module-chauthtok">
  232. <title>Authentication token management</title>
  233. <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
  234. href="pam_sm_chauthtok.xml"/>
  235. </section>
  236. </chapter>
  237. <chapter id="mwg-see-options">
  238. <title>Generic optional arguments</title>
  239. <para>
  240. Here we list the generic arguments that all modules can expect to
  241. be passed. They are not mandatory, and their absence should be
  242. accepted without comment by the module.
  243. </para>
  244. <variablelist>
  245. <varlistentry>
  246. <term>debug</term>
  247. <listitem>
  248. <para>
  249. Use the <citerefentry>
  250. <refentrytitle>pam_syslog</refentrytitle><manvolnum>3</manvolnum>
  251. </citerefentry> call to log debugging information to the system
  252. log files.
  253. </para>
  254. </listitem>
  255. </varlistentry>
  256. <varlistentry>
  257. <term>use_first_pass</term>
  258. <listitem>
  259. <para>
  260. The module should not prompt the user for a password.
  261. Instead, it should obtain the previously typed password
  262. (by a call to <function>pam_get_item()</function> for the
  263. <parameter>PAM_AUTHTOK</parameter> item), and use that. If
  264. that doesn't work, then the user will not be authenticated.
  265. (This option is intended for <command>auth</command> and
  266. <command>passwd</command> modules only).
  267. </para>
  268. </listitem>
  269. </varlistentry>
  270. </variablelist>
  271. </chapter>
  272. <chapter id="mwg-see-programming">
  273. <title>Programming notes</title>
  274. <para>
  275. Here we collect some pointers for the module writer to bear in mind
  276. when writing/developing a <emphasis remap='B'>Linux-PAM</emphasis>
  277. compatible module.
  278. </para>
  279. <section id="mwg-see-programming-sec">
  280. <title>Security issues for module creation</title>
  281. <section id="mwg-see-programming-sec-res">
  282. <title>Sufficient resources</title>
  283. <para>
  284. Care should be taken to ensure that the proper execution
  285. of a module is not compromised by a lack of system resources.
  286. If a module is unable to open sufficient files to perform its
  287. task, it should fail gracefully, or request additional resources.
  288. Specifically, the quantities manipulated by the <citerefentry>
  289. <refentrytitle>setrlimit</refentrytitle><manvolnum>2</manvolnum>
  290. </citerefentry> family of commands should be taken into
  291. consideration.
  292. </para>
  293. </section>
  294. <section id="mwg-see-programming-sec-who">
  295. <title>Who´s who?</title>
  296. <para>
  297. Generally, the module may wish to establish the identity of
  298. the user requesting a service. This may not be the same as
  299. the username returned by <function>pam_get_user()</function>.
  300. Indeed, that is only going to be the name of the user under
  301. whose identity the service will be given. This is not
  302. necessarily the user that requests the service.
  303. </para>
  304. <para>
  305. In other words, user X runs a program that is setuid-Y, it
  306. grants the user to have the permissions of Z. A specific example
  307. of this sort of service request is the <command>su</command>
  308. program: user <command>joe</command> executes
  309. <command>su</command> to become the user <command>jane</command>.
  310. In this situation X=<command>joe</command>, Y=<command>root</command>
  311. and Z=<command>jane</command>. Clearly, it is important that
  312. the module does not confuse these different users and grant an
  313. inappropriate level of privilege.
  314. </para>
  315. <para>
  316. The following is the convention to be adhered to when juggling
  317. user-identities.
  318. </para>
  319. <itemizedlist>
  320. <listitem>
  321. <para>
  322. X, the identity of the user invoking the service request.
  323. This is the user identifier; returned by the function
  324. <citerefentry>
  325. <refentrytitle>getuid</refentrytitle><manvolnum>2</manvolnum>
  326. </citerefentry>.
  327. </para>
  328. </listitem>
  329. <listitem>
  330. <para>
  331. Y, the privileged identity of the application used to
  332. grant the requested service. This is the
  333. <emphasis>effective</emphasis> user identifier;
  334. returned by the function <citerefentry>
  335. <refentrytitle>geteuid</refentrytitle><manvolnum>2</manvolnum>
  336. </citerefentry>.
  337. </para>
  338. </listitem>
  339. <listitem>
  340. <para>
  341. Z, the user under whose identity the service will be granted.
  342. This is the username returned by
  343. <function>pam_get_user()</function> and also stored in the
  344. <emphasis remap='B'>Linux-PAM</emphasis> item,
  345. <emphasis>PAM_USER</emphasis>.
  346. </para>
  347. </listitem>
  348. <listitem>
  349. <para>
  350. <emphasis remap='B'>Linux-PAM</emphasis> has a place for
  351. an additional user identity that a module may care to make
  352. use of. This is the <emphasis>PAM_RUSER</emphasis> item.
  353. Generally, network sensitive modules/applications may wish
  354. to set/read this item to establish the identity of the user
  355. requesting a service from a remote location.
  356. </para>
  357. </listitem>
  358. </itemizedlist>
  359. <para>
  360. Note, if a module wishes to modify the identity of either the
  361. <emphasis>uid</emphasis> or <emphasis>euid</emphasis> of the
  362. running process, it should take care to restore the original
  363. values prior to returning control to the
  364. <emphasis remap='B'>Linux-PAM</emphasis> library.
  365. </para>
  366. </section>
  367. <section id="mwg-see-programming-sec-conv">
  368. <title>Using the conversation function</title>
  369. <para>
  370. Prior to calling the conversation function, the module should
  371. reset the contents of the pointer that will return the applications
  372. response. This is a good idea since the application may fail
  373. to fill the pointer and the module should be in a position to
  374. notice!
  375. </para>
  376. <para>
  377. The module should be prepared for a failure from the
  378. conversation. The generic error would be
  379. <emphasis>PAM_CONV_ERR</emphasis>, but anything other than
  380. <emphasis>PAM_SUCCESS</emphasis> should be treated as
  381. indicating failure.
  382. </para>
  383. </section>
  384. <section id="mwg-see-programming-sec-token">
  385. <title>Authentication tokens</title>
  386. <para>
  387. To ensure that the authentication tokens are not left lying
  388. around the items, <emphasis>PAM_AUTHTOK</emphasis> and
  389. <emphasis>PAM_OLDAUTHTOK</emphasis>, are not available to
  390. the application: they are defined in
  391. <filename>&lt;security/pam_modules.h&gt;</filename>. This
  392. is ostensibly for security reasons, but a maliciously
  393. programmed application will always have access to all memory
  394. of the process, so it is only superficially enforced. As a
  395. general rule the module should overwrite authentication tokens
  396. as soon as they are no longer needed. Especially before
  397. <function>free()</function>'ing them. The
  398. <emphasis remap='B'>Linux-PAM</emphasis> library is
  399. required to do this when either of these authentication
  400. token items are (re)set.
  401. </para>
  402. <para>
  403. Not to dwell too little on this concern; should the module
  404. store the authentication tokens either as (automatic) function
  405. variables or using <function>pam_[gs]et_data()</function> the
  406. associated memory should be over-written explicitly before it
  407. is released. In the case of the latter storage mechanism, the
  408. associated <function>cleanup()</function> function should
  409. explicitly overwrite the <varname>*data</varname> before
  410. <function>free()</function>'ing it: for example,
  411. <programlisting>
  412. /*
  413. * An example cleanup() function for releasing memory that was used to
  414. * store a password.
  415. */
  416. int cleanup(pam_handle_t *pamh, void *data, int error_status)
  417. {
  418. char *xx;
  419. if ((xx = data)) {
  420. while (*xx)
  421. *xx++ = '\0';
  422. free(data);
  423. }
  424. return PAM_SUCCESS;
  425. }
  426. </programlisting>
  427. </para>
  428. </section>
  429. </section>
  430. <section id="mwg-see-programming-syslog">
  431. <title>Use of <citerefentry>
  432. <refentrytitle>syslog</refentrytitle><manvolnum>3</manvolnum>
  433. </citerefentry></title>
  434. <para>
  435. Only rarely should error information be directed to the user.
  436. Usually, this is to be limited to
  437. <quote><emphasis>sorry you cannot login now</emphasis></quote>
  438. type messages. Information concerning errors in the configuration
  439. file, <filename>/etc/pam.conf</filename>, or due to some system
  440. failure encountered by the module, should be written to
  441. <citerefentry>
  442. <refentrytitle>syslog</refentrytitle><manvolnum>3</manvolnum>
  443. </citerefentry> with <emphasis>facility-type</emphasis>
  444. <emphasis remap='B'>LOG_AUTHPRIV</emphasis>.
  445. </para>
  446. <para>
  447. With a few exceptions, the level of logging is, at the discretion
  448. of the module developer. Here is the recommended usage of different
  449. logging levels:
  450. </para>
  451. <itemizedlist>
  452. <listitem>
  453. <para>
  454. As a general rule, errors encountered by a module should be
  455. logged at the <emphasis>LOG_ERR</emphasis> level. However,
  456. information regarding an unrecognized argument, passed to a
  457. module from an entry in the <filename>/etc/pam.conf</filename>
  458. file, is <emphasis>required</emphasis> to be logged at the
  459. <emphasis>LOG_ERR</emphasis> level.
  460. </para>
  461. </listitem>
  462. <listitem>
  463. <para>
  464. Debugging information, as activated by the
  465. <command>debug</command> argument to the module in
  466. <filename>/etc/pam.conf</filename>, should be logged
  467. at the <emphasis>LOG_DEBUG</emphasis> level.
  468. </para>
  469. </listitem>
  470. <listitem>
  471. <para>
  472. If a module discovers that its personal configuration
  473. file or some system file it uses for information is
  474. corrupted or somehow unusable, it should indicate this
  475. by logging messages at level, <emphasis>LOG_ALERT</emphasis>.
  476. </para>
  477. </listitem>
  478. <listitem>
  479. <para>
  480. Shortages of system resources, such as a failure to
  481. manipulate a file or <function>malloc()</function> failures
  482. should be logged at level <emphasis>LOG_CRIT</emphasis>.
  483. </para>
  484. </listitem>
  485. <listitem>
  486. <para>
  487. Authentication failures, associated with an incorrectly
  488. typed password should be logged at level,
  489. <emphasis>LOG_NOTICE</emphasis>.
  490. </para>
  491. </listitem>
  492. </itemizedlist>
  493. </section>
  494. <section id="mwg-see-programming-libs">
  495. <title>Modules that require system libraries</title>
  496. <para>
  497. Writing a module is much like writing an application. You
  498. have to provide the "conventional hooks" for it to work
  499. correctly, like <function>pam_sm_authenticate()</function>
  500. etc., which would correspond to the <function>main()</function>
  501. function in a normal function.
  502. </para>
  503. <para>
  504. Typically, the author may want to link against some standard system
  505. libraries. As when one compiles a normal program, this can be
  506. done for modules too: you simply append the
  507. <parameter>-l</parameter><emphasis>XXX</emphasis> arguments
  508. for the desired libraries when you create the shared module object.
  509. To make sure a module is linked to the
  510. <command>libwhatever.so</command> library
  511. when it is <function>dlopen()</function>ed, try:
  512. <programlisting>
  513. % gcc -shared -o pam_module.so pam_module.o -lwhatever
  514. </programlisting>
  515. </para>
  516. </section>
  517. </chapter>
  518. <chapter id="mwg-example">
  519. <title>An example module</title>
  520. <para>
  521. At some point, we may include a fully commented example of a module in
  522. this document. For now, please look at the modules directory of the
  523. <emphasis remap='B'>Linux-PAM</emphasis> sources.
  524. </para>
  525. </chapter>
  526. <chapter id="mwg-see-also">
  527. <title>See also</title>
  528. <itemizedlist>
  529. <listitem>
  530. <para>
  531. The Linux-PAM System Administrators' Guide.
  532. </para>
  533. </listitem>
  534. <listitem>
  535. <para>
  536. The Linux-PAM Application Developers' Guide.
  537. </para>
  538. </listitem>
  539. <listitem>
  540. <para>
  541. The V. Samar and R. Schemers (SunSoft), ``UNIFIED LOGIN WITH
  542. PLUGGABLE AUTHENTICATION MODULES'', Open Software Foundation
  543. Request For Comments 86.0, October 1995.
  544. </para>
  545. </listitem>
  546. </itemizedlist>
  547. </chapter>
  548. <chapter id='mwg-author'>
  549. <title>Author/acknowledgments</title>
  550. <para>
  551. This document was written by Andrew G. Morgan (morgan@kernel.org)
  552. with many contributions from
  553. Chris Adams, Peter Allgeyer, Tim Baverstock, Tim Berger, Craig S. Bell,
  554. Derrick J. Brashear, Ben Buxton, Seth Chaiklin, Oliver Crow, Chris Dent,
  555. Marc Ewing, Cristian Gafton, Emmanuel Galanos, Brad M. Garcia,
  556. Eric Hester, Roger Hu, Eric Jacksch, Michael K. Johnson, David Kinchlea,
  557. Olaf Kirch, Marcin Korzonek, Thorsten Kukuk, Stephen Langasek,
  558. Nicolai Langfeldt, Elliot Lee, Luke Kenneth Casson Leighton,
  559. Al Longyear, Ingo Luetkebohle, Marek Michalkiewicz, Robert Milkowski,
  560. Aleph One, Martin Pool, Sean Reifschneider, Jan Rekorajski, Erik Troan,
  561. Theodore Ts'o, Jeff Uphoff, Myles Uyema, Savochkin Andrey Vladimirovich,
  562. Ronald Wahl, David Wood, John Wilmes, Joseph S. D. Yao
  563. and Alex O. Yuriev.
  564. </para>
  565. <para>
  566. Thanks are also due to Sun Microsystems, especially to Vipin Samar and
  567. Charlie Lai for their advice. At an early stage in the development of
  568. <emphasis remap='B'>Linux-PAM</emphasis>, Sun graciously made the
  569. documentation for their implementation of PAM available. This act
  570. greatly accelerated the development of
  571. <emphasis remap='B'>Linux-PAM</emphasis>.
  572. </para>
  573. </chapter>
  574. <chapter id='mwg-copyright'>
  575. <title>Copyright information for this document</title>
  576. <programlisting>
  577. Copyright (c) 2006 Thorsten Kukuk &lt;kukuk@thkukuk.de&gt;
  578. Copyright (c) 1996-2002 Andrew G. Morgan &lt;morgan@kernel.org&gt;
  579. </programlisting>
  580. <para>
  581. Redistribution and use in source and binary forms, with or without
  582. modification, are permitted provided that the following conditions are
  583. met:
  584. </para>
  585. <programlisting>
  586. 1. Redistributions of source code must retain the above copyright
  587. notice, and the entire permission notice in its entirety,
  588. including the disclaimer of warranties.
  589. 2. Redistributions in binary form must reproduce the above copyright
  590. notice, this list of conditions and the following disclaimer in the
  591. documentation and/or other materials provided with the distribution.
  592. 3. The name of the author may not be used to endorse or promote
  593. products derived from this software without specific prior
  594. written permission.
  595. </programlisting>
  596. <para>
  597. Alternatively, this product may be distributed under the terms of
  598. the GNU General Public License (GPL), in which case the provisions
  599. of the GNU GPL are required instead of the above restrictions.
  600. (This clause is necessary due to a potential bad interaction between
  601. the GNU GPL and the restrictions contained in a BSD-style copyright.)
  602. </para>
  603. <programlisting>
  604. THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
  605. WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
  606. MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  607. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
  608. INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  609. BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
  610. OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  611. ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
  612. TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
  613. USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
  614. </programlisting>
  615. </chapter>
  616. </book>