<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	xmlns:creativeCommons="http://backend.userland.com/creativeCommonsRssModule">

<channel>
	<title>Challenge everything! &#187; PAM</title>
	<atom:link href="http://blogs.gnome.org/raywang/category/free-software/pam/feed/" rel="self" type="application/rss+xml" />
	<link>http://blogs.gnome.org/raywang</link>
	<description>Ray Wang&#039;s notes</description>
	<lastBuildDate>Mon, 30 May 2011 03:11:47 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
<creativeCommons:license>http://creativecommons.org/licenses/by/3.0/</creativeCommons:license>		<item>
		<title>深入 Linux PAM 体系结构</title>
		<link>http://blogs.gnome.org/raywang/2007/02/02/%e6%b7%b1%e5%85%a5-linux-pam-%e4%bd%93%e7%b3%bb%e7%bb%93%e6%9e%84/</link>
		<comments>http://blogs.gnome.org/raywang/2007/02/02/%e6%b7%b1%e5%85%a5-linux-pam-%e4%bd%93%e7%b3%bb%e7%bb%93%e6%9e%84/#comments</comments>
		<pubDate>Fri, 02 Feb 2007 06:20:00 +0000</pubDate>
		<dc:creator>raywang</dc:creator>
				<category><![CDATA[PAM]]></category>
		<category><![CDATA[Security]]></category>

		<guid isPermaLink="false">http://raywang.yo2.cn/articles/%e6%b7%b1%e5%85%a5-linux-pam-%e4%bd%93%e7%b3%bb%e7%bb%93%e6%9e%84.html</guid>
		<description><![CDATA[&#60;br&#62; <a href="http://blogs.gnome.org/raywang/2007/02/02/%e6%b7%b1%e5%85%a5-linux-pam-%e4%bd%93%e7%b3%bb%e7%bb%93%e6%9e%84/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<blockquote>
<div align="left"><font size="2">原文地址：http://www.ibm.com/developerworks/cn/linux/l-pam/index.html</font>
</div>
<p><font size="2"><br />
本文阐述了 Linux-PAM 的概念，同时还与读者一道分析了 Linux-PAM 的体系结构，作者希望籍此以加深读者对 Linux-PAM 的理解，以便对其有更深层的把握。</font></p></blockquote>
<p><font size="2"><a name="N10039"><span class="atitle">一、什么是Linux-PAM</span></a></font></p>
<p><font size="2">为 安全起见，计算机系统只有经过授权的合法用户才能访问，在这里如何正确鉴别用户的真实身份是一个关键的问题。所谓用户鉴别，就是用户向系统以一种安全的方 式提交自己的身份证明，然后由系统确认用户的身份是否属实的过程。换句话说，用户鉴别是系统的门户，每个用户进入到系统中都必须经过鉴别这一道关。 </font></p>
<p><font size="2">最初，Linux系统的用户鉴别过程就像各种Unix系统的一样：系统管理员为用户建立一个帐号并为其指定一个口令，用户 用此指定的口令登录后重新设置自己的口令，这样用户就具有了一个只有他自己知道的秘密口令。一般情况下，用户的口令经过加密处理后存放于 /etc/passwd 文件中。用户登录时，登录服务程序提示用户输入其用户名和口令，然后将口令加密并与 /etc/passwd 文件中对应帐号的加密口令进行比较，如果口令相匹配，说明用户的身份属实并允许此用户访问系统。这种思想基于只有用户自己知道他的口令，所以输入的口令是 正确的话，那么系统就认定他是所声称的那个人。 </font></p>
<p><font size="2">后来，还采用了许多其他的鉴别用户的方法，如用于网络环境的 Kerberos 以及基于智能卡的鉴别系统等。但是这些鉴别方案有一个通病：实现鉴别功能的代码通常作为应用程序的一部分而一起编译,这样问题就来了&#8212;&#8212;如果发现 所用算法存在某些缺陷或想采用另一种鉴别方法时，用户不得不重写（修改或替换）然后重新编译原程序。很明显，我们原先的鉴别方案缺乏灵活性，这里的牵一发 而动全身的情形很是让人恼火。 </font></p>
<p><font size="2">鉴于以上原因，人们开始寻找一种更佳的替代方案：一方面，将鉴别功能从应用中独立出来，单独进行模块化设计，实现和维护； 另一方面，为这些鉴别模块建立标准 API，以便各应用程序能方便的使用它们提供的各种功能；同时，鉴别机制对其上层用户（包括应用程序和最终用户）是透明的。直到 1995 年，SUN 的研究人员提出了一种满足以上需求的方案&#8211;插件式鉴别模块（PAM）机制并首次在其操作系统 Solaris 2.3 上部分实现。插件式鉴别模块（PAM）机制采用模块化设计和插件功能，使得我们可以轻易地在应用程序中插入新的鉴别模块或替换原先的组件,而不必对应用程 序做任何修改，从而使软件的定制、维持和升级更加轻松&#8211;因为鉴别机制与应用程序之间相对独立。应用程序可以通过 PAM API 方便的使用 PAM 提供的各种鉴别功能，而不必了解太多的底层细节。此外，PAM的易用性也较强，主要表现在它对上层屏蔽了鉴别的具体细节，所以用户不必被迫学习各种各样的 鉴别方式，也不必记住多个口令；又由于它实现了多鉴别机制的集成问题，所以单个程序可以轻易集成多种鉴别机制如 Kerberos 鉴别机制和 Diffie &#8211; Hellman 鉴别机制等，但用户仍可以用同一个口令登录而感觉不到采取了各种不同鉴别方法。 </font></p>
<p><font size="2">在广大开发人员的努力下，各版本的 UNIX 系统陆续提供对 PAM 的支持。其中，Linux-PAM 是专门为 Linux 机器实现的，包括 Caldera 1.3、2.2、Debian 2.2、Turbo Linux 3.6、Red Hat 5.0 以及 SuSE 6.2 及它们的后续版本都提供对 PAM 的支持。FreeBSD 从 3.1 版开始支持 PAM。需要注意的是，除了具体实现不同外，各种版本 Unix 系统上的 PAM 的框架是相同的，所以我们在这里介绍的 Linux-PAM 框架知识具有普遍性。因此在下文介绍其框架的过程中可以看到，我们并没有刻意区分 PAM 与 Linux－PAM 这两个术语。 </font></p>
<table cellspacing="0" cellpadding="0" align="right" class="no-print">
<tbody>
<tr align="right">
<td><font size="2"><img width="100%" height="4" src="http://www.ibm.com/i/c.gif"><br />
            </font></p>
<table cellspacing="0" cellpadding="0" border="0">
<tbody>
<tr>
<td valign="middle"><font size="2"></font></td>
<td valign="top" align="right"><font size="2"></font></td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
<p><font size="2"><a name="N1004E"><span class="atitle">二、PAM 的分层体系结构</span></a></font></p>
<p><font size="2">PAM 为了实现其插件功能和易用性，它采取了分层设计思想：让各鉴别模块从应用程序中独立出来，然后通过PAM API作为两者联系的纽带，这样应用程序就可以根据需要灵活地在其中&quot;插入&quot;所需鉴别功能模块，从而真正实现了&quot;鉴别功能，随需应变&quot;。实际上，这一思路 非常符合软件设计中的&quot;高内聚，低耦合&quot;这一重要思想，PAM 的体系如下简图所示： </font></p>
<p>         <font size="2"><img src="http://www.ibm.com/developerworks/cn/linux/l-pam/images/image01.jpg"></font>       </p>
<p>         <font size="2"><strong>图1  PAM体系结构</strong></font>       </p>
<p><font size="2">从 上图可以看出，PAM API 起着承上启下的作用，它是应用程序和鉴别模块之间联系的纽带：当应用程序调用 PAM API 时,应用接口层按照配置文件 pam.conf 的规定，加载相应的鉴别模块。然后把请求（即从应用程序那里得到的参数）传递给底层的鉴别模块,这时鉴别模块就可以根据要求执行具体的鉴别操作了。当鉴别 模块执行完相应操作后，将结果返回给应用接口层，然后由接口层根据配置的具体情况将来自鉴别模块的应答返回给应用程序。 </font></p>
<p><font size="2">上面描述了 PAM 的各个组成部分，以及它们作为整体的运作机理。下面将对 PAM 的关键的低二层分别加以介绍。 </font></p>
<table cellspacing="0" cellpadding="0" align="right" class="no-print">
<tbody>
<tr align="right">
<td><font size="2"><img width="100%" height="4" src="http://www.ibm.com/i/c.gif"><br />
            </font></td>
</tr>
</tbody>
</table>
<p><font size="2"><a name="N1006C"><span class="atitle">三、第一层：模块层</span></a></font></p>
<p><font size="2">模 块层处于整个结构的最底层，它向上为接口层提供用户鉴别等服务，也就是说所有具体的鉴别工作都是由该层的模块来完成的。对于应用程序，有些不但需要验证用 户的口令，还可能要求验证用户的帐户是否已经过期。此外,有些应用程序也许还会要求记录当前会话的有关信息或改变口令等，所以 PAM 在模块层除了提供鉴别模块外，同时提供了支持帐户管理、会话管理以及口令管理功能的模块。当然,这四种模块并不是所有应用程序所必需的,而是根据需要灵活 取舍,比如虽然 login 可能要求访问所有四种模块,但是 su 可能仅仅需要使用鉴别组件即可。至于如何取舍则涉及到接口层的 PAM API和配置文件,这部分内容将在下文中加以介绍。 </font></p>
<p><font size="2"><a name="N10075"><span class="atitle">四、第二层：应用接口层</span></a></font></p>
<p><font size="2">应用接口层位于 PAM 结构的中间部分，它向上为应用程序屏蔽了用户鉴别等过程的具体细节，向下调用模块层中的具体模块所提供的特定服务。由图1可以看出，它主要由 PAM API 和配置文件两部分组成，下面将逐一介绍。 </font></p>
<p><font size="2"> PAM API 可以分为两类，一类是用于调用下层特定模块的接口，这类接口与底层的模块相对应： </font></p>
<ol>
<li><font size="2">鉴别类接口：pam_authenticate（）用于鉴别用户，pam_setcred（）用于修改用户的秘密信息。 </font></li>
<li><font size="2">帐号类接口：pam_acct_mgmt（）检查受鉴别的用户所持帐户是否有权登陆系统，以及该帐户是否已过期等。 </font></li>
<li><font size="2">会话类接口：包括用于会话管理和记帐的 pam_open_session（）和 pam_close_session（）函数。 </font></li>
<li><font size="2">口令类接口：包括用于修改用户口令的 pam_chauthtok（）。 </font></li>
</ol>
<p><font size="2">第二类接口通常并不与底层模块一一对应，它们的作用是对底层模块提供支持以及实现应用程序与模块之间的通信等。具体如下： </font></p>
<ol>
<li><font size="2">管理性接口           <br />
    每组 PAM 事务从 pam_start（）开始，结束于 pam_end（）函数。接口 pam_get_item（）和 pam_set_item（）用来读写与 PAM 事务有关的状态信息。同时，能够用 pam_str()输出 PAM 接口的出错信息。         </font></li>
<li><font size="2">应用程序与模块间的通讯接口           <br />
    在 应用程序初始化期间,某些诸如用户名之类的数据可以通过 pam_start（）将其存放在PAM接口层中，以备将来底层模块使用。另外，底层模块还可以使用 pam_putenv()向应用程序传递特定的环境变量，然后应用程序利用 pam_getenv() 和 pam_getenvlist() 读取这些变量。 </font></li>
<li><font size="2">用户与模块间的通讯接口           <br />
    pam_start（）函数可以通过会话式的回调函数，让底层模块通过它们读写模块相关的鉴别信息，比如以应用程序所规定的方式提示用户输入口令。         </font></li>
<li><font size="2">模块间通讯接口           <br />
    尽管各模块是独立的,但是他们仍然能够通过 pam_get_item（）和 pam_set_item（）接口共享某些与鉴别会话有关的公用信息，诸如用户名、服务名、口令等。此外，这些API还可以用于在调用 pam_start（）之后，让应用程序修改状态信息。         </font></li>
<li><font size="2">读写模块状态信息的接口           <br />
    接口 pam_get_data（）和 pam_set_data（）用以按照PAM句柄要求访问和更新特定模块的信息。此外，还可以在这些模块后附加一个清除数据函数，以便当调用 pam_end（）时清除现场。         </font></li>
</ol>
<p><font size="2">由于 PAM 模块随需加载,所以各模块始化任务在第一次调用时完成。如果某些模块的清除任务必须在鉴别会话结束时完成,则它们应该使用 pam_set_data（）规定清除函数，这些执行清除任务的函数将在应用程序调用 pam_end（）接口时被调用。 </font></p>
<p><font size="2"><a name="N100B2"><span class="atitle">五、配置文件</span></a></font></p>
<p><font size="2">我们注意到，配置文件也放在了在应用接口层中，它与 PAM API 配合使用，从而达到了在应用中灵活插入所需鉴别模块的目的。它的作用主要是为应用选定具体的鉴别模块，模块间的组合以及规定模块的行为。下面是一个示例配置文件： </font></p>
<p>         <font size="2"><img src="http://www.ibm.com/developerworks/cn/linux/l-pam/images/image02.gif"></font>       </p>
<p>         <font size="2"><strong>图2.示例配置文件</strong></font>       </p>
<p><font size="2">我们可以看到,配置文件有许多登记项(每行对应一个登记项)组成,每一行又分为五列(每列对应一栏),详细解释如下: </font></p>
<p><font size="2">第一栏，service表示使用PAM的应用程序，比如login、passwd、rlogin等。这一栏中的OTHER表 示所有没在该文件中显式列出的应用。也就是说，如果所有程序具有相同的需求，整个配置文件只需要一行即可，并且该行的第一栏为OTHER。本例中，因为所 有应用程序使用相同的会话模块,所以实际上可以用单行，即 </font></p>
<table width="100%" cellspacing="0" cellpadding="0" border="0">
<tbody>
<tr>
<td class="code-outline">
<pre><font size="2">&quot; OTHER   session        required     pam_unix_session.so&quot;<br /></font>
            </td>
</tr>
</tbody>
</table>
<p><font size="2"><br />
</font></p>
<p><font size="2">来代替文件中的这些行： </font></p>
<table width="100%" cellspacing="0" cellpadding="0" border="0">
<tbody>
<tr>
<td class="code-outline">
<pre><font size="2">&quot;login   session     required     pam_unix_session.so<br />ftp     session     required     pam_unix_session.so<br />telnet  session     required     pam_unix_session.so&quot;。<br /></font>
            </td>
</tr>
</tbody>
</table>
<p><font size="2"><br />
</font></p>
<p><font size="2">第二栏,module_type指明程序所用PAM底 层模块的类型：auth表示鉴别类模块；account表示帐户类模块；session表示会话类模块；password表示口令类模块。注意，每行只能 指定一种类型模块，如果程序需要多种模块的话，可在多行中分别规定。 </font></p>
<p><font size="2">第三栏,control_flag规定如何处理模块的成功和失败情况。单个应用程序可以调用多种底层模块，这通常称为&quot;堆 叠&quot;，对应于某程序的按照配置文件中出现顺序执行的所有模块成为&quot;堆&quot;，堆中的各模块的地位与出错时的处理由control_flag栏的取值决定，它的 五种可能的取值分别为required、Requisite、sufficient或_optional，现介绍如下： </font></p>
<p><font size="2">required--它表示该模块的成功是用户通过鉴别的必要条件，换句话说，只有当对应于应用程序的所有带 required标记的模块全部成功后，该程序才能通过鉴别。同时，如果任何带required标记的模块出现了错误，PAM并不立刻将错误消息返回给应 用程序，而是在所有模块都调用完毕后才将错误消息返回调用它的程序。 </font></p>
<p><font size="2">Requisite--它与required相仿，只有带此标记的模块返回成功后，用户才能通过鉴别，不同之处在于其一旦失败就不再执行堆中后面的其它模块，并且鉴别过程到此结束。 </font></p>
<p><font size="2"> optional--它表示即便该模块失败，用户仍能通过鉴别。在PAM体系中，带有该标记的模块失败后将继续处理下一模块。 </font></p>
<p><font size="2">sufficient--它表示该模块取得成功是用户通过鉴别的充分条件,也就是说只要标记为sufficient的模块一 旦成功，那么PAM便立即向应用程序返回成功而不必尝试任何其他模块。当标记为sufficient的模块失败时，sufficient模块当做 optional对待。 </font></p>
<p><font size="2"> 第四栏,module_path指出PAM模块的位置。 </font></p>
<p><font size="2"> 第五栏,options用于向特定模块传递相关的选项，然后由模块分析解释这些任选项。比如使用此栏打开模块调试，或向某模块传递诸如超时值之类的参数等。另外，它还用于支持下文所述的口令映射技术。 </font></p>
<p><font size="2"> 如果任一栏出现错误,或某模块没有找到,那么所在行被忽略并将其作为严重错误进行记录。 </font></p>
<p><font size="2"> 本例中，login程序使用UNIX口令模块进行鉴别，而ftp程序却使用S/Key模块进行鉴别。如我们想改变ftp程序的鉴别方法，比如也用UNIX口令模块进行鉴别，那么我们不必改动源程序，只需将配置文件中的 </font></p>
<table width="100%" cellspacing="0" cellpadding="0" border="0">
<tbody>
<tr>
<td class="code-outline">
<pre><font size="2">ftp     auth        required     pam_skey_auth.so    debug<br /></font>
            </td>
</tr>
</tbody>
</table>
<p><font size="2"><br />
</font></p>
<p><font size="2">改为</font></p>
<table width="100%" cellspacing="0" cellpadding="0" border="0">
<tbody>
<tr>
<td class="code-outline">
<pre><font size="2">ftp     auth        required     pam_unix_auth.so    debug<br /></font>
            </td>
</tr>
</tbody>
</table>
<p><font size="2"><br />
</font></p>
<p><font size="2">这样，当用户使用ftp时，将用传统的UNIX口令鉴 别方式来验证其身份。由此可见，在PAM体制下为应用程序改变鉴别机制是一件轻松的事情。另外，PAM体制的堆叠功能还使得应用程序能够支持多种鉴别机 制，如下例中的login程序在配置文件中先后出现了三项与鉴别有关的登记项： </font></p>
<p>         <font size="2"><img src="http://www.ibm.com/developerworks/cn/linux/l-pam/images/image03.gif"></font>       </p>
<p>         <font size="2"><strong>图3.示例配置文件</strong></font>       </p>
<p><font size="2">当login 程序执行时先用pam_unix.so模块即传统的UNIX口令方式鉴别用户，然后再调用pam_kerb.so模块即Kerberos对用户进行鉴别， 最后用pam_rsa.so模块即RSA方式鉴别用户。在按上述顺序鉴别用户的过程中，如果pam_unix.so模块鉴别失败，它将继续调用下面的模块 进行鉴别而非立刻向login程序返回错误消息；pam_kerb.so模块也按同样方式处理，直到顺序处理完最后一个pam_rsa.so模块后， PAM才将前面出现的错误信息返回给login程序。对于该配置，即使pam_rsa.so模块顺利通过，只要pam_unix.so模块和 pam_kerb.so模块中有一个出现错误，用户就不能通过鉴别；相反，即使pam_rsa.so模块失败，只要pam_unix.so模块和 pam_kerb.so模块都通过了，用户也能通过鉴别。 </font></p>
<p><font size="2"><a name="N10119"><span class="atitle">六、口令映射</span></a></font></p>
<p><font size="2">在 同一个机器上使用多个鉴别机制，尤其是一个应用程序集成多种鉴别机制可能导致用户需要记忆多个口令，这会让用户觉得很不舒服。虽然可以让所有机制使用相同 的口令来获取易用性,但是这将削弱系统的安全性--如果其中任何一个机制的口令泄露了，则所有机制都会受到牵累。此外,不同的鉴别机制在口令长度、容许的 字符、更新间隔、有效期等方面可能具有他们特有的要求，这些要求也是为多鉴别机制使用同一个口令必须考虑的一个问题。 </font></p>
<p><font size="2">PAM为我们提供了这样一种解决方案,它不排除为所有鉴别机制共用一个口令,同时允许通过口令映射技术让每个机制使用不同 的口令。该方案用用户的&quot;主口令&quot;加密其他的&quot;副口令&quot;,并且将这些经过加密的副口令存放在一个用户能访问的地方。主口令一旦经过验证,鉴别模块就能用它 解密那些加密的副口令从而获得相应口令,然后将所需口令传递给鉴别模块。这称为&quot;口令映射&quot;。如果口令映射出现错误,或如果映射不存在,那么各鉴别模块应 该提示用户输入口令。为支持口令映射,主口令应保存在PAM第二层并且在需要时由其提供给堆叠的各个鉴别模块。同时，口令要在 pam_authenticate函数返回之前清除。为了保障口令映射的安全，主口令必须足够强壮,可以考虑使其的长度更长、组成口令字符的类型多样化并 使用混合类型的字符组成口令等有效措施。 </font></p>
<p><font size="2"> 口令如何加密及其存储完全取决于具体的实现：它能够将加密的副口令（也称作&quot;映射口令&quot;）存储在可靠或不可靠的地方,诸如智能卡、本地文件或目录服务。当然，如果加密的口令保存在一个不可靠的允许公共访问的地方,会留下受到字典攻击的隐患。 </font></p>
<p><font size="2"> 为实现口令映射，所有鉴别模块应支持以下四个映射选项∶ </font></p>
<ol>
<li><font size="2">use_first_pass∶它表示当该模块执行时不提示用户输入口令，而将该模块之前的提示用户输入的主口令作为它们的公共口令进行验证。如果用户没能通过主口令的鉴别，则该模块不提示用户输入口令。此选项一般说来在系统管理员想强制用同一个口令通过多模块时使用。 </font></li>
<li><font size="2">try_first_pass∶除了如果主口令不正确，将提示用户输入口令之外，它的用法与use_first_pass相同。 </font></li>
<li><font size="2">use_mapped_pass∶它表示使用口令映射技术得到此模块的有效口令。也就是说，该模块执行时不提示用户 输入口令，而是用映射口令即用主口令解密得到的该模块的副口令作为本模块的口令输入进行验证。如果在此之前用户没能通过主口令的鉴别，则该模块也不会提示 输入口令。 </font></li>
<li><font size="2">try_mapped_pass∶除了如果主口令不正确，它将提示用户输入口令之外，该项与use_mapped_pass用法相同。 </font></li>
</ol>
<p><font size="2">当口令更换后,PAM会保存所有新旧口令，并且使有关模块能够访问到它们。其他模块能够使用此信息更新加密的口令而不必强制用户再次输入口令。 </font></p>
<p><font size="2">现以下面的配置文件为例讲解口令映射： </font></p>
<p>         <font size="2"><img src="http://www.ibm.com/developerworks/cn/linux/l-pam/images/image04.gif"></font>       </p>
<p>         <font size="2"><strong>图4. 示例配置文件</strong></font>       </p>
<p><font size="2">在 这里login程序集成了三种鉴别方式：传统UNIX口令鉴别、Kerberos和RSA鉴别，但通常情况下用户仅输入一次口令便能通过鉴别了。当程序调 用pam_unix.so模块时，PAM提示用户输入他们的UNIX口令，然后由pam_kerb.so模块对用户输入的UNIX口令进行鉴别。继而调用 pam_kerb.so模块，由于该模块的选项为use_mapped_pass，它将利用口令映射机制进行认证，也就是说，如果UNIX口令鉴别通过的 话，就将其作为pam_kerb.so模块的主口令来解密其对应的映射口令从而进行Kerberos鉴别。如果pam_unix.so模块所需口令没能通 过验证，则无法进行口令映射，那么PAM将直接调用下一鉴别模块而不提示用户输入其Kerberos口令。最后一个模块的选项为 use_first_pass，所以pam_rsa.so模块将使用前边输入的主口令来鉴别用户，如果口令错误也不提示用户输入RSA口令。所以，只要第 一次输入的口令是正确的，并且映射口令存在，则一个口令便足以通过鉴别。 </font></p>
<p><font size="2"><a name="N10152"><span class="atitle">七、结束语</span></a></font></p>
<p><font size="2">Linux-PAM是一种使用灵活功能强大的用户鉴别机制，本文对它的组成结构以及各部分之间的关系进行了相应的分析，希望对读者理解PAM的机制有所帮助。</font></p>
<p><font size="2"><a name="resources"><span class="atitle">参考资料 </span></a></font></p>
<p><font size="2">1. 想了解更多的FLTK的知识和下载FLTK源代码等可以到         <a href="http://www.fltk.org/">www.fltk.org</a> 网站。         <a href="http://www.fltk.org/documentation.php">FLTK的编程手册</a>你想了解FLTK构件的事件方法等都在里面。OpenGL       </font></p>
<p><font size="2">2. 还是参考一下         <a href="http://www.opengl.org/">www.opengl.org</a>上的资料吧，有文档说明还有教学和源代码。       </font></p>
<p><font size="2"><br />
<a name="author"><span class="atitle">关于作者</span></a></font></p>
<table width="100%" cellspacing="0" cellpadding="0" border="0">
<tbody>
<tr>
<td colspan="3"><font size="2"><img width="100%" height="5" src="http://www.ibm.com/i/c.gif"></font></td>
</tr>
<tr valign="top" align="left">
<td><font size="2"></font></td>
<td><font size="2"><img width="4" height="5" src="http://www.ibm.com/i/c.gif"></font></td>
<td width="100%">
<p><font size="2">韩波，自由撰稿人，有近十年的C语言编程经验，主要感兴趣的领域为TCP/IP协议，Linux内核以及信息安全技术。作为自由撰稿人，其力求在不影响问题实质的前提下，尽量将要表达的内容以通俗易懂的形式摆在读者的面前。您可以通过         <a href="mailto:hbzzx2001@yahoo.com.cn?cc=">hbzzx2001@yahoo.com.cn</a>与他联系。       </font></p>
</td>
</tr>
</tbody>
</table>
]]></content:encoded>
			<wfw:commentRss>http://blogs.gnome.org/raywang/2007/02/02/%e6%b7%b1%e5%85%a5-linux-pam-%e4%bd%93%e7%b3%bb%e7%bb%93%e6%9e%84/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>PAM入门介绍 (也很不错)</title>
		<link>http://blogs.gnome.org/raywang/2007/02/01/pam%e5%85%a5%e9%97%a8%e4%bb%8b%e7%bb%8d-%e4%b9%9f%e5%be%88%e4%b8%8d%e9%94%99/</link>
		<comments>http://blogs.gnome.org/raywang/2007/02/01/pam%e5%85%a5%e9%97%a8%e4%bb%8b%e7%bb%8d-%e4%b9%9f%e5%be%88%e4%b8%8d%e9%94%99/#comments</comments>
		<pubDate>Thu, 01 Feb 2007 10:37:00 +0000</pubDate>
		<dc:creator>raywang</dc:creator>
				<category><![CDATA[PAM]]></category>
		<category><![CDATA[Security]]></category>

		<guid isPermaLink="false">http://raywang.yo2.cn/articles/pam%e5%85%a5%e9%97%a8%e4%bb%8b%e7%bb%8d-%e4%b9%9f%e5%be%88%e4%b8%8d%e9%94%99.html</guid>
		<description><![CDATA[&#60;br&#62; <a href="http://blogs.gnome.org/raywang/2007/02/01/pam%e5%85%a5%e9%97%a8%e4%bb%8b%e7%bb%8d-%e4%b9%9f%e5%be%88%e4%b8%8d%e9%94%99/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p><font size="2">原文地址：http://sinbad.zhoubin.com/read.html?board=UNIX&amp;num=482<br />
</font><br />
<font size="2">作者：netguy (netguy@nsfocus.com)<br />主页：http://www.nsfocus.com<br />日期：2000-10-07</p>
<p>PAM（Pluggable Authentication Modules ）是由Sun提出的一种认证机制。它通过提供一些<br />动态链接库和一套统一的API，将系统提供的服务 和该服务的认证方式分开，使得系统管理<br />员可以灵活地根据需要给不同的服务配置不同的认证方式而无需更改服务程序，同时也便于<br />向系 统中添加新的认证手段。<br />PAM最初是集成在Solaris中，目前已移植到其它系统中，如Linux、SunOS、HP-UX 9.0等。</p>
<p>一、PAM的结构</p>
<p>PAM的整个框架结构如下图所示：</p>
<p>系统管理员通过PAM配置文件来制定认证策略，即指定什么服务该采用什么样的认证方法；应<br />用程序开发者通过在服务程序中使用PAM API而实现对认证方法的调用；而PAM服务模块（se<br />rvice module）的开发者则利用PAM SPI（Service Module API）来编写认证模块（主 要是<br />引出一些函数pam_sm_xxxx( )供libpam调用），将不同的认证机制（比如传统的UNIX认证方<br />法、Kerberos等）加入到系统中；PAM核 心库（libpam）则读取配置文件，以此为根据将服<br />务程序和相应的认证方法联系起来。<br />二、PAM支持的四种管理界面：</p>
<p>1、认证管理（authentication management）<br />    主要是接受用户名和密码，进而对该用户的密码进行认证，并负责设置用户的一些秘密<br />信息。<br />2、帐户管理（account management）<br />    主要是检查帐户是否被允许登录系统，帐号是否已经过期，帐号的登录是否有时间段的<br />限制等等。<br />3、密码管理（password management）<br />    主要是用来修改用户的密码。<br />4、会话管理（session management）<br />    主要是提供对会话的管理和记账（accounting）。</p>
<p>三、PAM的文件：</p>
<p>      /usr/lib/libpam.so.*                  PAM核心库<br />/etc/pam.conf或者/etc/pam.d/          PAM配置文件<br />/usr/lib/security/pam_*.so            可动态加载的PAM service module<br />      对于RedHat，其目录不是/usr/lib，而是/lib。</p>
<p>四、PAM的配置：</p>
<p>PAM的配置是通过单个配置文件/etc/pam.conf。RedHat还支持另外一种配置方式，即通过配<br />置目录/etc/pam.d/，且这种的优先级要高于单 个配置文件的方式。</p>
<p>1、使用配置文件/etc/pam.conf</p>
<p>该文件是由如下的行所组成的：<br />service-name  module-type  control-flag  module-path  arguments</p>
<p>service-name 服务的名字，比如telnet、login、ftp等，服务名字&ldquo;OTHER&rdquo;代表所有没有<br />在该文件中明确配置的其它服务。<br />module-type  模块类型有四种：auth、account、session、password，即对应PAM所支持的<br />四种管理方式。同一个服务可以调用多个 PAM模块进行认证，这些模块构成一个stack。<br />control-flag 用来告诉PAM库该如何处理与该服务相关的PAM模块的成功或失败情况。它有四<br />种可能的 值：required，requisite，sufficient，optional。<br />    required 表示本模块必须返回成功才能通过认证，但是如果该模块返回失败的话，失败<br />结果也不会立即通知用户，而是要等到同一stack 中的所有模块全部执行完毕再将失败结果<br />返回给应用程序。可以认为是一个必要条件。<br />    requisite 与required类似，该模块必须返回成功才能通过认证，但是一旦该模块返回<br />失败，将不再执行同一stack内的任何模块，而是直 接将控制权返回给应用程序。是一个必<br />要条件。注：这种只有RedHat支持，Solaris不支持。<br />    sufficient 表明本模块返回成功已经足以通过身份认证的要求，不必再执行同一stack<br />内的其它模块，但是如果本模块返回失败的话可以 忽略。可以认为是一个充分条件。<br />    optional表明本模块是可选的，它的成功与否一般不会对身份认证起关键作用，其返回<br />值一般被忽略。<br />    对于control-flag，从Linux-PAM-0.63版本起，支持一种新的语法，具体可参看Linux <br />PAM文档。<br />module-path 用来指明本模块对应的程序文件的路径名，一般采用绝对路径，如果没有给出<br />绝对路径，默认该文件在目录/usr/lib/security下 面。<br />arguments  是用来传递给该模块的参数。一般来说每个模块的参数都不相同，可以由该模块<br />的开发者自己定义，但是也有以下几个共同 的参数：<br />    debug          该模块应当用syslog( )将调试信息写入到系统日志文件中。<br />    no_warn        表明该模块不应把警告信息发送给应用程序。<br />    use_first_pass  表明该模块不能提示用户输入密码，而应使用前一个模块从用户那里<br />得到的密码。<br />    try_first_pass  表明该模块首先应当使用前一个模块从用户那里得到的密码，如果该<br />密码验证不通过，再提示用户输入新的密码。<br />    use_mapped_pass 该模块不能提示用户输入密码，而是使用映射过的密码。<br />    expose_account  允许该模块显示用户的帐号名等信息，一般只能在安全的环境下使用<br />，因为泄漏用户名会对安全造成一定程度的威 胁。</p>
<p>2、使用配置目录/etc/pam.d/（只适用于RedHat Linux）</p>
<p>该目录下的每个文件的名字对应服务名，例如ftp服务对应文件/etc/pam.d/ftp。如果名为x<br />xxx的服务所对应的配置文件/etc/pam.d/xxxx不存 在，则该服务将使用默认的配置文件/et<br />c/pam.d/other。每个文件由如下格式的文本行所构成：<br />module-type  control-flag  module-path  arguments<br />每个字段的含义和/etc/pam.conf中的相同。</p>
<p>3、配置的例子</p>
<p>例一：用/etc/pam.conf配置默认的认证方式。</p>
<p>下面的例子将拒绝所有没有在/etc/pam.conf中明确配置的服务。OTHER代表没有明确配置的<br />其它所有服务，pam_deny模块的作用只是简 单地拒绝通过认证。<br />OTHER  auth    required      /usr/lib/security/pam_deny.so<br />OTHER  account  required      /usr/lib/security/pam_deny.so<br />OTHER  password required      /usr/lib/security/pam_deny.so<br />OTHER  session  required      /usr/lib/security/pam_deny.so</p>
<p>例二：通过/etc/pam.d/rsh文件配置rsh服务的认证方式。</p>
<p>rsh服务认证用户时，先使用/etc/hosts.equiv和.rhosts文件的认证方式，然后再根据/etc<br />/nologin文件的存在与否来判断是否允许该用户使用 rsh，最后使用password database来认<br />证用户。</p>
<p>auth      required    /lib/security/pam_rhosts_auth.so<br />auth      required    /lib/security/pam_nologin.so<br />account    required    /lib/security/pam_pwdb.so<br />session    required    /lib/security/pam_pwdb.so</p>
<p>例三：通过/etc/pam.conf配置ftpd的认证方式。</p>
<p>下面是ftpd服务利用PAM模块进行用户认证的三个步骤。首先用pam_ftp模块检查当前用户是<br />否为匿名用户，如果是匿名用户，则 sufficient控制标志表明无需再进行后面的认证步骤，<br />直接通过认证；否则继续使用pam_unix_auth模块来进行标准的unix认证，即用/etc/ passw<br />d和/etc/shadow进行认证；通过了pam_unix_auth模块的认证之后，还要继续用pam_listfil<br />e模块来检查该用户是否出现在文件/etc/ ftpusers中，如果是则该用户被deny掉。<br />ftpd    auth    sufficient  /usr/lib/security/pam_ftp.so<br />ftpd    auth    required    /usr/lib/security/pam_unix_auth.so use_first_pass<br />ftpd    auth    required    /usr/lib/security/pam_listfile.so \<br />                            onerr=succeed item=user sense=deny file=/etc/ftpuser<br />s</p>
<p>五、密码映射（password-mapping）</p>
<p>密码映射允许用户在不同的认证机制下使用不同的密码，其中有一个主密码（primary pass<br />word），其它密码为次密码（secondary pas<br />
swords，可能有多个）。主密码用来对次密码进<br />行加密。在主密码认证通过后，认证模块利用主密码将加密过的次密码（也称为 mapped pa<br />ssword）解密，并对次密码进行认证。<br />注：如果使用了一次性密码的机制，就不使用密码映射。</p>
<p>所有服务模块必须支持如下4个映射选项（在第四部分已经简单解释过）：</p>
<p>1、use_first_pass</p>
<p>这个选项指示本模块不能提示用户输入密码，而是使用已有的密码，即从第一个向用户提示<br />输入密码的模块那里取得密码，并对该密码进 行认证。</p>
<p>2、try_first_pass</p>
<p>这个选项指示本模块首先尝试使用已有的密码，即从第一个向用户提示输入密码的模块那里<br />取得密码，并对该密码进行认证。如果密码认 证失败，则再提示用户输入密码。</p>
<p>3、use_mapped_pass</p>
<p>这个选项指示本模块不能向用户提示输入密码，而应使用映射过的密码，即利用主密码将加<br />密过的次密码解密出来并进行认证。</p>
<p>4、try_mapped_pass</p>
<p>这个选项指示本模块首先尝试使用映射过的密码，即利用主密码将加密过的次密码解密出来<br />并进行认证。如果密码认证失败，则再提示用 户输入密码。</p>
<p>密码映射的例子：</p>
<p>下面是/etc/pam.conf中关于login服务的配置。这里login共有3种认证机制：Kerberos、UN<br />IX和RSA认证，两个required控制标志表明用户必 须通过Kerberos认证和UNIX认证才能使用<br />login服务，optional选项则说明RSA认证是可选的。首先用户输入主密码进行Kerberos认 证<br />；use_mapped_pass选项指示UNIX认证模块利用主密码将用于UNIX认证的次密码解密出来并对<br />该次密码进行认证；try_first_pass选项 指示RSA认证模块先使用第一个模块（即Kerberos<br />模块）的密码作为进行认证的密码，当对该密码认证失败时才提示用户输入用于RSA认 证的<br />次密码。<br />login  auth  required  pam_kerb_auth.so  debug<br />login  auth  required  pam_unix_auth.so  use_mapped_pass<br />login  auth  optional  pam_rsa_auth.so    try_first_pass</p>
<p>六、PAM API</p>
<p>1、框架API：</p>
<p>任何一个支持PAM的服务程序在进行认证时必须以pam_start( )开始进行初始化，最后以pam<br />_end( )结束以便进行清理工作。</p>
<p>2、认证管理API：</p>
<p>pam_authenticate( )对用户名/密码进行认证。<br />pam_setcred( )用来修改用户的秘密信息。</p>
<p>3、帐户管理API：</p>
<p>pam_acct_mgmt( )检查帐户本身是否有权限登录系统、帐户是否过期、帐户是否有登录时间<br />限制等。</p>
<p>4、密码管理API：</p>
<p>pam_chauthtok( )修改用户的密码。</p>
<p>5、会话管理API：</p>
<p>一个会话以pam_open_session( )开始，最后以pam_close_session( )结束。</p>
<p>6、其它：</p>
<p>pam_get_item( )、pam_set_item( )用来读写PAM事务(transaction)的状态信息。<br />pam_get_data( )、pam_set_data( )用来取得和设置PAM模块及会话的相关信息。<br />pam_putenv( )、pam_getenv( )、pam_getenvlist( )用来读写环境变量。<br />pam_strerror( )返回相关的错误信息。<br />例子程序（摘自Sun的白皮书）：</p>
<p>下面的例子使用PAM API写了一个简单的login服务程序（注：这不是个完整的程序，所以省<br />略了对pam_close_session的调用）。</p>
<p>#include &lt;security/pam_appl.h&gt;</p>
<p>/* 回调函数 */<br />static int login_conv(int num_msg, struct pam_message **msg, struct pam_response<br /> **response, void *appdata_ptr);<br />struct pam_conv pam_conv = {login_conv, NULL};<br />pam_handle_t *pamh;  /* 进行认证的PAM句柄 */</p>
<p>void main(int argc, char *argv[], char **renvp)<br />{<br />    /* 初始化，并提供一个回调函数 */<br />    if ((pam_start(&quot;login&quot;, user_name, &amp;pam_conv, &amp;pamh)) != PAM_SUCCESS)<br />        login_exit(1);</p>
<p>    /* 设置一些参数 */<br />    pam_set_item(pamh, PAM_TTY, ttyn);<br />    pam_set_item(pamh, PAM_RHOST, remote_host);</p>
<p>    while (!authenticated &amp;&amp; retry &lt; MAX_RETRIES)<br />    {<br />        status = pam_authenticate(pamh, 0);        /* 密码认证管理，检查用户输入<br />的密码是否正确 */<br />        authenticated = (status == PAM_SUCCESS);<br />    }</p>
<p>    if (status != PAM_SUCCESS)<br />    {<br />        fprintf(stderr,&quot;error: %s\n&quot;, pam_strerror(pamh, status)); /* 显示错误原<br />因 */<br />        login_exit(1);<br />    }</p>
<p>    /*  通过了密码认证之后再调用帐户管理API，检查用户帐号是否已经过期 */<br />    if ((status = pam_acct_mgmt(pamh, 0)) != PAM_SUCCESS)<br />    {<br />        if (status == PAM_AUTHTOK_EXPIRED)<br />        {<br />            status = pam_chauthtok(pamh, 0);  /* 过期则要求用户更改密码 */<br />            if (status != PAM_SUCCESS)<br />                login_exit(1);<br />        }<br />    }</p>
<p>    /* 通过帐户管理检查之后则打开会话 */<br />    if (status = pam_open_session(pamh, 0) != PAM_SUCCESS)<br />        login_exit(status);</p>
<p>    /* 设置用户组 */<br />    setgid(pwd-&gt;pw_gid);</p>
<p>    /*<br />    * Initialize the supplementary group access list before<br />    * pam_setcred because PAM modules might add groups<br />    * during the pam_setcred call<br />    */<br />    initgroups(user_name, pwd-&gt;pw_gid);</p>
<p>    status = pam_setcred(pamh, PAM_ESTABLISH_CRED);<br />    if (status != PAM_SUCCESS)<br />        login_exit(status);</p>
<p>    /* 设置真实的用户ID（或者有效的用户ID）*/<br />    setuid(pwd-&gt;pw_uid);</p>
<p>    pam_end(pamh, PAM_SUCCESS);  /* PAM事务的结束 */</p>
<p>    /*<br />    此处可用来实现与login有关的其它内容<br />    */<br />}</p>
<p>/* 出错则清理现场并退出 */<br />static void login_exit(int exit_code)<br />{<br />    if (pamh)<br />        pam_end(pamh, PAM_ABORT);<br />    exit(exit_code);<br />}</p>
<p>/* 这个回调函数被PAM认证模块调用以便显示错误信息或者或者用来取得用户输入，采用图<br />形界面的服务程序则应使用图形界面来取得 用户输入或显示提示信息*/<br />int login_conv(int num_msg, struct pam_message **msg, struct pam_response **resp<br />onse, void *appdata_ptr)<br />{<br />    while (num_msg&#8211;)<br />    {<br />        switch (m-&gt;msg_style)<br />        {<br />            case PAM_PROMPT_ECHO_OFF:<br />                r-&gt;resp = strdup(getpass(m-&gt;msg));<br />                break;<br />            case PAM_PROMPT_ECHO_ON:<br />                (void) fputs(m-&gt;msg, stdout);<br />                r-&gt;resp = malloc(PAM_MAX_RESP_SIZE);<br />                fgets(r-&gt;resp, PAM_MAX_RESP_SIZE, stdin);<br />                /* add code here to remove \n from fputs */<br />                break;<br />            case PAM_ERROR_MSG:<br />                (void) fputs(m-&gt;msg, stderr);<br />                break;<br />            case PAM_TEXT_INFO:<br />                (void) fputs(m-&gt;msg, stdout);<br />                break;<br />            default:<br />                log_error();<br />                break;<br />        }<br />    }<br />    return (PAM_SUCCESS);<br />}</p>
<p>七、PAM SPI</p>
<p>当服务程序（ftpd、telnetd等）调用PAM API函数pam_xxx( )时，由PAM 框架（libpam）根<br />据该服务在/etc/pam.conf文件中的配置调用指 定的PAM模块中对应的SPI函数pam_sm_xxx( <br />)。如下：</p>
<p>API函数的名字为pam_xxx( )，对应的SPI函数的名字为pam_sm_xxx( )，即每个服务模块需要<br />引出相应的函数以供libpam调用。为方便对 照，再列一下。</p>
<p>API                                    对应的 SPI</p>
<p>帐号管理 pam_acct_mgmt( )              pam_sm_acct_mgmt( )</p>
<p>认证管理 pam_authenticate( )          pam_ sm_authenticate( )</p>
<p>密码管理 pam_chauthtok( )              pam_ sm_chauthtok( )</p>
<p>会话管理 pam_open_session( )          pam_ sm_open_session( )</p>
<p>会话管理 pam_close_session( )          pam_ sm_close_session( )</p>
<p>认证管理 pa<br />
m_setcred( )                pam_ sm_setcred( )</p>
<p>八、常用的PAM服务模块</p>
<p>下面是Linux提供的PAM模块列表（只是其中一部分）：</p>
<p>模块文件          模块功能描述                  相关配置文件</p>
<p>pam_access      提供logdaemon风格的登录控制    /etc/security/access.conf</p>
<p>pam_chroot      提供类似chroot命令的功能</p>
<p>pam_cracklib    对密码的强度进行一定的检查    库文件libcrack和字典文件<br />                                                /usr/lib/cracklib_dict</p>
<p>pam_deny        总是无条件地使认证失败</p>
<p>pam_env          设置或取消环境变量            /etc/security/pam_env.conf</p>
<p>pam_filter      对输入输出流进行过滤          filters</p>
<p>pam_ftp.so      对匿名ftp用户进行认证</p>
<p>pam_group        当用户在指定的终端上请求指定的 /etc/security/group.conf<br />                服务时赋予该用户相应的组权限</p>
<p>pam_issue        在提示用户输入用户名之前显示  /etc/issue<br />                /etc/issue文件的内容</p>
<p>pam_krb4        对用户密码进行Kerberos认证    相应的Kerberos库文件</p>
<p>pam_lastlog      在用户登录成功后显示关于      /var/log/lastlog<br />                用户上次登录的信息，并维护<br />                /var/log/lastlog文件。</p>
<p>pam_limits      限制用户会话所能使用的系统资源 /etc/security/limits.conf</p>
<p>pam_listfile    根据指定的某个文件决定是否    例如/etc/ftpusers<br />                允许或禁止提供服务</p>
<p>pam_mail        检查用户的邮箱中是否有新邮件    /var/spool/mail/xxxx</p>
<p>pam_mkhomedir    为用户建立主目录                /etc/skel/</p>
<p>pam_motd        显示/etc/motd文件的内容        /etc/motd</p>
<p>pam_nologin      根据/etc/nologin文件的存在与否  /etc/nologin<br />                来决定用户认证是否成功</p>
<p>pam_permit      总是无条件地使认证成功</p>
<p>pam_pwdb        作为pam_unix_xxxx模块的一个替代。/etc/pwdb.conf<br />                使用Password Database通用接口<br />                进行认证。</p>
<p>pam_radius      提供远程身份验证拨入用户服务<br />                (RADIUS)的认证</p>
<p>pam_rhosts_auth  利用文件~/.rhosts和            /etc/hosts.equiv和~/.rhosts<br />                /etc/hosts.equiv对用户进行认证。</p>
<p>pam_rootok      检查用户是否为超级用户，如果<br />                是超级用户则无条件地通过认证。</p>
<p>pam_securetty    提供标准的Unix securetty检查  /etc/securetty</p>
<p>pam_time        提供基于时间的控制，比如限制  /etc/security/time.conf<br />                用户只能在某个时间段内才能登录</p>
<p>pam_unix        提供标准的Unix认证            /etc/passwd和 /etc/shadow</p>
<p>pam_userdb      利用Berkeley DB数据库来检查    Berkeley DB<br />                用户/密码</p>
<p>pam_warn        利用syslog( )记录一条告警信息</p>
<p>pam_wheel        只允许wheel组的用户有超级用户<br />                的存取权限</p>
<p>参考资料：</p>
<p>1、DCE/OSF-RFC 86.0<br />2、Linux-PAM documentation &amp; source code<br />3、Sun Solaris PAM documentation</p>
<p>&#8211;<br />※ 来源: http://sinbad.zhoubin.com </font></p>
]]></content:encoded>
			<wfw:commentRss>http://blogs.gnome.org/raywang/2007/02/01/pam%e5%85%a5%e9%97%a8%e4%bb%8b%e7%bb%8d-%e4%b9%9f%e5%be%88%e4%b8%8d%e9%94%99/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>基于PAM的用户认证  （不错，看完了清楚了不少）</title>
		<link>http://blogs.gnome.org/raywang/2007/02/01/%e5%9f%ba%e4%ba%8epam%e7%9a%84%e7%94%a8%e6%88%b7%e8%ae%a4%e8%af%81-%ef%bc%88%e4%b8%8d%e9%94%99%ef%bc%8c%e7%9c%8b%e5%ae%8c%e4%ba%86%e6%b8%85%e6%a5%9a%e4%ba%86%e4%b8%8d%e5%b0%91%ef%bc%89/</link>
		<comments>http://blogs.gnome.org/raywang/2007/02/01/%e5%9f%ba%e4%ba%8epam%e7%9a%84%e7%94%a8%e6%88%b7%e8%ae%a4%e8%af%81-%ef%bc%88%e4%b8%8d%e9%94%99%ef%bc%8c%e7%9c%8b%e5%ae%8c%e4%ba%86%e6%b8%85%e6%a5%9a%e4%ba%86%e4%b8%8d%e5%b0%91%ef%bc%89/#comments</comments>
		<pubDate>Thu, 01 Feb 2007 09:56:00 +0000</pubDate>
		<dc:creator>raywang</dc:creator>
				<category><![CDATA[PAM]]></category>
		<category><![CDATA[Security]]></category>

		<guid isPermaLink="false">http://raywang.yo2.cn/articles/%e5%9f%ba%e4%ba%8epam%e7%9a%84%e7%94%a8%e6%88%b7%e8%ae%a4%e8%af%81-%ef%bc%88%e4%b8%8d%e9%94%99%ef%bc%8c%e7%9c%8b%e5%ae%8c%e4%ba%86%e6%b8%85%e6%a5%9a%e4%ba%86%e4%b8%8d%e5%b0%91%ef%bc%89.html</guid>
		<description><![CDATA[&#60;br&#62; <a href="http://blogs.gnome.org/raywang/2007/02/01/%e5%9f%ba%e4%ba%8epam%e7%9a%84%e7%94%a8%e6%88%b7%e8%ae%a4%e8%af%81-%ef%bc%88%e4%b8%8d%e9%94%99%ef%bc%8c%e7%9c%8b%e5%ae%8c%e4%ba%86%e6%b8%85%e6%a5%9a%e4%ba%86%e4%b8%8d%e5%b0%91%ef%bc%89/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<h2><strong><font size="2">原文地址：http://linux.chinaitlab.com/manual/linuxschool/doc078.htm</font></strong></h2>
<h2><font size="2">11.2 基于PAM的用户认证</font></h2>
<p><font size="2">任何要授予用户特权的程序都要能够进行用户认证。当您登入系统时，您需要提供用 户名和口令，而后登入进程据此以检验登入的合法性&#8212;确认您就是该用户。还有除口 令认证之外的其他认证形式，而且口令的存储方式也是各不相同的。</font></p>
<p><font size="2">PAM（可插拔认证模块）方式允许系统管理员设置多种认证措施而无须重新编译要进 行认证的程序。使用PAM，您通过编辑一个配置文件来决定认证模块如何插入到程序 之中。大多数红帽子LINUX用户无须改动这个配置文件。因为如果使用RPM来安装程 序的话，系统会自动做有关改动。但是，如果您想定制认证模块的话，就需要理解配 置文件内容。</font></p>
<h3><font size="2">11.2.1 PAM 模块</font></h3>
<p><font size="2">PAM定义了四种类型的模块。auth模块提供实际的认证过程，可能是提示口令输入并 检查输入的口令，设置保密字如用户组或KERBEROS通行证。account模块负责检查并 确认是否可以进行认证（比如，帐户是否到期，用户此时此刻是否可以登入，等等）。 password模块被用来设置口令。一旦用户认证通过，session模块将被用来做使用户使用 其帐户前的初始化工作，如安装用户的HOME目录啦，使能用户的电子邮箱啦，等等。</font></p>
<p><font size="2">这些模块可以堆叠，多次使用。比如：rlogin通常使用至少两种认证方法，如果&ldquo;rhosts&rdquo; 认证成功了，就允许建立连接，否则还要进行标准的口令认证。</font></p>
<p><font size="2">随时可以加入新的模块，而PAM感知的程序可以被配置来使用它。举个例子，如果您 有一个一次性口令计算系统，可以写出一个模块来（系统中包含有如何书写模块的文 档资料），PAM感知的程序无须重新编译就可以使用这个新的一次性口令计算器。</font></p>
<h3><font size="2">11.2.2 服务</font></h3>
<p><font size="2">每个使用PAM的程序定义它自己的服务名称。login程序定义其服务类型为login,ftpd程序 定义其服务类型为ftp,等等。一般来说，服务类型就是存取该服务的程序的名字，而不 是提供服务的程序。</font></p>
<h3><font size="2">11.2.3 配置文件</font></h3>
<p><font size="2">目录/etc/pam.d被用来配置所有的PAM应用程序。（在早期的PAM版本中用的是 /etc/pam.conf;但是若/etc/pam.d不存在的话，仍旧会找/etc/pam.conf，不过记住，这是一个 过时的文件。）。每一个应用程序（确切的说是服务）都有它自己的配置文件。 一个真实的文件可能如下：</font></p>
<blockquote><p>
<font size="2"><tt>#%PAM-1.0<br />auth      required  /lib/security/pam_securetty.so<br />auth      required  /lib/security/pam_pwdb.so shadow nullok<br />auth      required  /lib/security/pam_nologin.so<br />account   required  /lib/security/pam_pwdb.so<br />password  required  /lib/security/pam_cracklib.so<br />password  required  /lib/security/pam_pwdb.so shadow<br />                                         nullok use_authtok<br />session   required  /lib/security/pam_pwdb.so</tt> </font>
</p></blockquote>
<p><font size="2">第一行是注释。任何以#开头的行都是注释。以下的三行排列着用于login认证的三个 模块其中第一行用以确认用户是否以root登入，允许登入的tty被列在文件/etc/securetty 中（如果文件存在的话）第二行将会使用户被提示输入口令并校验口令。第三行表示 查文件/etc/nologin是否存在，如果存在就显示其内容，而且如果用户不是root，则禁止 其登入。即便第一个模块失败了，也要完成三个模块的校验。这是一种安全上的考虑 &#8212;这种设计永远不要让用户知道他或她们为什么会被拒绝，否则会让其更容易突破认 证。您可以将&ldquo;required&rdquo;改成&ldquo;requisite&rdquo;来修改这种认证方式。也就是说，如果有任 何&ldquo;requisite&rdquo;模块以失败返回，整个PAM认证将终止再调用其它模块也以失败返回。</font></p>
<p><font size="2">第五行表示任何必要的记帐信息要被记载。例如，如果设置使用影子口令，pam_db.so 模块将被执行以检查该帐户是否失效或者用户口令是否超期而需要修改。</font></p>
<p><font size="2">第六行（该行需要折行来写）用以指定如果login程序改变用户的口令，它应当使用 pam_pwdb.so来完成。（这仅在auth模块检测到口令需要被改变时，例如一个影子口令 已经过期时才使用）</font></p>
<p><font size="2">最后一行表示pam_pwdb.so模块将被用来管理当前的会话过程。而目前该模块什么也不做； 它可以被替换为别的所需的模块。</font></p>
<p><font size="2">要注意配置文件中每一行的顺序不是任意的。尽管required模块以什么顺序被调用并没 有多大关系，但是还有其它一些控制符，其中optional很少在红帽子LINUX中使用，而 sufficient 和requisite就要求行的顺序不能颠倒。</font></p>
<p><font size="2">让我们来看一下rlogin的认证配置：</font></p>
<blockquote><p>
<font size="2"><tt>auth  required    /lib/security/pam_securetty.so<br />auth  sufficient  /lib/security/pam_rhosts_auth.so<br />auth  required    /lib/security/pam_pwdb.so shadow nullok<br />auth  required    /lib/security/pam_nologin.so</tt> </font>
</p></blockquote>
<p><font size="2">这和login的描述极为相似，但是其中比login的多一行模块描述，而且模块的顺序也不同。 首先,pam_securetty.so模块将禁止以root从不安全的终端登入。这将有效的阻止任何root方 式的远程登入。如果您不想禁止的话（在这种情况下，我们建议您的机器要么没和Internet 相连，要么呆在一个配置良好的防火墙后面），把这一行删掉就是了。其次，pam_nologin.so 模块将检查/etc/nologin，如上所述。第三点，如果pam_rhosts_auth.so模块认证通过，PAM就立 即以成功返回而不再做任何口令校验。如果pam_rhosts_auth.so认证失败，该失败将被忽略， 继续调用pam_pwdb.so模块进行正常的口令认证。如果您在securetty认证失败后不想让系统继续 以口令询问的话，您可以把pam_securetty.so模块的required 改为 requisite。</font></p>
<h3><font size="2">11.2.4 影子口令</font></h3>
<p><font size="2">pam_pwdb.so模块会自动检测您是否使用影子口令以做出相应的调整。请查看第 <a href="http://linux.chinaitlab.com/manual/linuxschool/doc079.htm#s11.3">11.3</a> 节获得更多有关操纵影子口令工具的信息。</font></p>
<h3><font size="2">11.2.5 更为详尽的信息</font></h3>
<p><font size="2">本章描述的仅仅是PAM的介绍性知识。更多的资料位于系统的/usr/doc/pam*，其中包含 了系统管理员指南，模块书写手册，应用系统开发者手册，和PAM标准说明DCE-RFC 86.0。同时，这些文档也可以从红帽子的WEB站点获得，http://www.redhat.com/linux-info/pam/.</font></p>
]]></content:encoded>
			<wfw:commentRss>http://blogs.gnome.org/raywang/2007/02/01/%e5%9f%ba%e4%ba%8epam%e7%9a%84%e7%94%a8%e6%88%b7%e8%ae%a4%e8%af%81-%ef%bc%88%e4%b8%8d%e9%94%99%ef%bc%8c%e7%9c%8b%e5%ae%8c%e4%ba%86%e6%b8%85%e6%a5%9a%e4%ba%86%e4%b8%8d%e5%b0%91%ef%bc%89/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>The Linux-PAM Administrator Guide (1)</title>
		<link>http://blogs.gnome.org/raywang/2007/01/31/the-linux-pam-administrator-guide-1/</link>
		<comments>http://blogs.gnome.org/raywang/2007/01/31/the-linux-pam-administrator-guide-1/#comments</comments>
		<pubDate>Wed, 31 Jan 2007 03:50:00 +0000</pubDate>
		<dc:creator>raywang</dc:creator>
				<category><![CDATA[PAM]]></category>
		<category><![CDATA[Security]]></category>

		<guid isPermaLink="false">http://raywang.yo2.cn/articles/the-linux-pam-administrator-guide-1.html</guid>
		<description><![CDATA[&#60;br&#62; <a href="http://blogs.gnome.org/raywang/2007/01/31/the-linux-pam-administrator-guide-1/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p><font size="2">The Linux-PAM Administrator Guide</p>
<p>原文地址: http://www.kernel.org/pub/linux/libs/pam/Linux-PAM-html/Linux-PAM_SAG.html<br />
作者:Andrew G. Morgan, morgan@linux.kernel.org<br />
翻译:孙国清(Thomas Sun),thomassun@yeah.net<br />
DRAFT v0.71 1999/11/8 这个文档所涉的是系统管理员须知的关于Linux-PAM库的知识. 它涉及了设置PAM的正确语法并讨论维护一个可靠系统的正确的策略.<br />
1. 介绍</p>
<p>Linux-PAM (Linux下的可插入式认证模组) 是一套共享函数库,允许系统管理员来决定应用程式如何识别用户.</p>
<p>换句话说,就是用不着(重写和)重新编译一个(支援PAM的)程式,就可以切换它所用的认证机制. 你可以整个的升级你的认证系统而不用去管应用程式本身.</p>
<p>传统上,当一个应用程序有身份识别的需求,它就不得不把某一种验证算法写进去. 例如,就传统的UN*X系统而言,核对使用者身份的方法就是要求用户输入正确的密码. 这密码,除了开头的两个字符作为&quot;salt&quot;,剩下的是加密过的(经由crypt(3)). 接著用户被验证这个加密过的密码是否与他在密码档(就是/etc/passwd文件)中他的那笔记录的第二栏相符.在这样的系统里,绝大部份权限的授予是基于这种单一的认证机制. 权限决定于个人的识别码(uid)和不同群组的成员.服务和程式是否可用由个人和群组的识别码决定.传统上,群组关系经由/etc/group文件中的记录来赋予.</p>
<p>不幸的是,随着计算机速度的不断提高,再加上满世界的关于网路计算的介绍,使得象这样曾是安全的验证机制,变得易受攻击了.面对这样的现实,新的验证方法正在持续的开发中.</p>
<p>Linux-PAM项目的目标是把赋权部分的开发以可靠的合适的鉴定模式从软件中分离出来。这目标已经通过提供一组库函数实现了，应用程序可以用这些函数来请求验证某个用户。这个 PAM 由特定的系统文件配置,/etc/pam.conf (或者是在/etc/pam.d/里的一系列配置文件)&nbsp; 以经由特定的可用的认证模组来鉴定某个用户的请求。 这些个模组通常位于/usr/lib/security目录并且以可动态加载的目标文件的形式出现 (参见 dlopen(3)).<br />
2. 文中的说明</p>
<p>在继续阅读之前, 请记住本文假定提到的文件位于默认的目录。这个默认的目录我们遵循RFC(RFC-86.0,见 bibliography) 中的约定。如果你正用一个支持PAM但是却选择以不同的方式发布这些文件的发布版的Linux(或是其他的OS) (Red Hat就是这样的发布版),&nbsp; 那你从文章中直接拷贝例子的时候就要注意一下了.</p>
<p>举个例子, where it is explicit, 本文假定PAM可加载目标文件(就是 模块)位于这个目录:&nbsp; /usr/lib/security/. 可是, Red Hat Linux, 为遵循Linux文件系统标准(the FSSTND),把这些文件放在/lib/security. 在使用本文的例子时请小心的做一些转换的工作。<br />
3. 概观</p>
<p>For the uninitiated，我们开始于考虑一个例子。我们来说说一个应用程序提供一些服务给用户； login 就是这样的程序。&nbsp; Login 做两件事，它首先确认提出请求的用户正是他们自己，第二步提供给他们所请求的服务： 就login而言服务即是一个命令行外壳（command shell）(如bash，tcsh，zsh之类。)以这个用户的身份去跑。</p>
<p>传统上，前一个步骤通过login提示用户输入密码然后确认系统是否同意登入；接着确认（就系统而言）用户确实是提出要求的那人。这类工作就是Linux-PAM的典型应用。</p>
<p>从应用程序员的角度看（在这个例子里就是写login程序的人）， Linux-PAM处理认证的工作&mdash;&mdash;确认用户的身份。</p>
<p>Linux-PAM的弹性在于，你，系统管理员有权来决定实施怎样的验证方案。你有权来设定你的系统里的任何支持PAM的应用程序的验证方案。就是说，你可以将验证方案设计成单纯的信任&gt;;任何人（pam_permit）到像偏执狂似的通过视网膜扫描，声音识别和一个密码！</p>
<p>举例说明你所面对的弹性，考虑以下情形：系统管理员（家中的父母）希望提高他的使用者（孩子们）的算术能力。她可以设置他们喜欢玩的 &ldquo;Shoot &#8216;em up&rdquo;（游戏，当然得支持PAM）通过提问小于12的一对随机数的乘积的办法来进行认证。很明显不管游戏本身如何，他们会很快学会乘法表。等他们再大些，认证可以升级到包括多位除法！（译者：我已经准备用这种办法来教我宝贝女儿学加减乘除了。）</p>
<p>Linux-PAM处理四种独立的（管理）工作。它们是： 认证管理； 帐号管理； 会话期间管理；和密码管理。&nbsp; The association of the preferred management scheme with the behavior of an application is made with entries in the relevant Linux -PAM configuration file. 管理的功能由配置文件中指定的模块 来完成。这文件的语法在 below部分讨论。</p>
<p>下面的插图描述了Linux-PAM的整个组织结构。</p>
<div></p>
<div><img border="0" class="blogimg" src="http://hiphotos.baidu.com/dream1123/pic/item/b3dfac4b785798f182025c86.jpg"></div>
</div>
<p>By way of explanation, 图的左边表示一个应用程序:X. 这应用程序有和Linux-PAM 库的接口并且在认证方面没有什么特别之处. Linux-PAM 函数库 (图的中部) 查询PAM配置文件的内容并且装入适用于程序 X 的模块. 这些模块进入四个管理组(&nbsp; 图的中下部)中的一个,并且以它们出现在配置文件中的顺序堆叠起来 . 这些模组由Linux-PAM呼叫后,为应用程序执行不同的认证工作 . 需要用户提供或提供给用户的文本信息,可以通过使用应用程序提供的conversation函数来交换.</p>
<p>3.1 Getting started</p>
<p>以下段落由Seth Chaiklin供稿:</p>
<p>到现在为止,我们描述了PAM如何工作在一个理想世界里,<br />
在这儿所有应用程序都被正确编写.<br />
然而,到此时(1998年10月), 这距离现实还太远.<br />
因此,在你试图把PAM用于你的系统时,还得考虑一些实际因素.</p>
<p>Why bother, is it really worth all the trouble?&nbsp; </p>
<p>如果你运行Linux作为单用户系统, 或者在一个所由用户都可信任的环境, 那么用PAM就没什么实际优势.</p>
<p>Ed: 事实上还是有一个好处, 你可以令认证变哑, 就象没有任何认证&#8230;.像Win95.</p>
<p>在网络环境里, 很显然,关于用户你必需多想点, it is clear that you need to think a little more about how users etc., are authenticated:]</p>
<p>如果运行Linux作为服务器, 提供一些不同的服务 (e.g., 经由密码控制的WWW区域限制, PPP), <br />
那PAM就有一些实际的和有趣的价值. 尤其是, 通过使用使用模块, PAM 能够使<br />
一个程序经过几个不同的密码库来查找, 哪怕那个程序没有专为那密码库写的代码. <br />
下面有一些例子Here are some examples of the possibilities<br />
that this enables.</p>
<p>&nbsp;&nbsp; o&nbsp; Apache 有一个模块提供PAM服务.&nbsp; 认证特定的目录权限可以让PAM来控制， <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 这意味着，所有PAM能调用的模块都可以被Apache使用，包括RADIUS,NIS,NCP<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (NCP用来经由Novell的密码库认证).</p>
<p>&nbsp;&nbsp; o&nbsp; pppd 有一个PAM化了的版本(来自 RedHat)&nbsp; 现在有可能用一系列的数据库来验证<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ppp用户. 作为对基于Linux的密码库(/etc/passwd,/etc/shadow)的扩充, 你可以<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 用PAM模块来进行基于Novell密码库或NT(NTLM)密码库的认证. </p>
<p>&nbsp;&nbsp; o&nbsp; 以上两则例子可以有组合应用.想象一下你办公室/部门的用户已经经过用户名/密码<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 认证登入Novell或NT.如果你想要他在Linux下的应用也用相同的用户名/密码<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (为PPP登入,web服务,或者只是普通的shell登入),你可以通过PAM进行基于这些已<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 存在的数据库(译者注:Novell的或者NT的)的用户认证,而无须在Linux和LAN服务器里<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 各自维护独立的数据库.</p>
<p>我可以让所有需要有用户认证的程序都来用PAM吗?</p>
<p>有的可以,有的不行.可以的是那些你能得到源代码,并且可以加入适当的PAM函数的程序.<br />
不行的是那些你无法得到源代码,并且可执行程序没有加入PAM的功能.</p>
<p>也就是说, 如果一个程序打算要用PAM,那么它必须在程序里直接的包含PAM函数.<br />
不这样做就不可能用PAM.</p>
<p>我怎么知道程序是否已经含有PAM的代码了呢?</p>
<p>一个快速的(但不总是可靠)的方法是执行ldd &lt;程序&gt;;<br />
如果 libpam 和 libpam_misc 不在程序所需的函数库之列,那么它将不会用PAM.<br />
然而,这两个函数库还是可能已经包含进程序了,不过问题依然存在,因为把PAM<br />
写死在程序不会如你期望的工作.所以一个更可靠的方法是做一下的测试:</p>
<p>在/etc/pam.d目录里,需要为程序设有一个配置文件.具体的文件名是写死在程序里的.<br />
通常和程序名一样,但却不总是这样.为举例说明,假设程序名字叫&quot;pamprog&quot;,配置文件<br />
是/etc/pam.d/pamprog.</p>
<p>在/etc/pam.d/pamprog里写这两行:</p>
<p>auth&nbsp;&nbsp;&nbsp; required&nbsp; pam_permit.so<br />
auth&nbsp;&nbsp;&nbsp; required&nbsp; pam_warn.so</p>
<p>
现在试着执行pamprog. 配置文件的第一行是说所有用户都被允许. 第二行会在你的<br />
syslog 文件(或者其它你的syslog会写的文件) 里写一个warning.<br />
如果这测试是成功的,那么你就知道你有一个&quot;懂&quot;pam的程序,并且你可以开始更有趣的工作:<br />
决定如何在你的/etc/pam.d/pamprog里堆彻PAM模块.</p>
<p>4. Linux-PAM的设定档</p>
<p>Linux-PAM 给系统管理员提供了相当大的弹性来设定系统里程式的权限赋予. 由PAM控制的系统安全的本地配置可以包含在以下两个地方:&nbsp; 或者是一个单一的系统文件: /etc/pam.conf; 或者是/etc/pam.d/ 目录下的文件. 本章我们来讨论这些文件的语法和一般的选项.<br />
4.1 设定档的语法</p>
<p>请注意, 在这些文件里 Linux-PAM 特有的符号是不区分大小写的. 而模块的路径,是大小写敏感的,因为它标识的是Linux下的文件的名字. 而任何模块参数的大小写分别由各个模块定义.</p>
<p>除以下的行之外,为系统管理员方便,还有两个特殊的字符: 注解由&#8217;#'开头,结束于行结束,另外,模块的描述行可以以 &#8216;\&#8217;脱字符延续到下一行.</p>
<p>通常/etc/pam.conf里的每一行有以下格式:</p>
<p>service-name&nbsp;&nbsp; module-type&nbsp;&nbsp; control-flag&nbsp;&nbsp; module-path&nbsp;&nbsp; arguments</p>
<p>接下来,我们来解释每个栏位的意思.另一种(也是常被采用的)设置Linux-PAM 的方法是通过/etc/pam.d/里的文件来实现.在我们解释完上面的那行之后, 我们就来讨论这种方法.</p>
<p>service-name</p>
<p>&nbsp;&nbsp;&nbsp; 这笔记录相关的服务名称.通常这服务名称是特定应用程序的名字.比如, `ftpd&#8217;, `rlogind&#8217; 和 `su&#8217; 这些. .</p>
<p>&nbsp;&nbsp;&nbsp; 有一个保留的服务名称,它是用来定义默认的认证机制的. 它就是`OTHER&#8217;,大小写无关.注意,当已经有为指定服务定义了模块,那么 `OTHER&#8217; 记录会被忽略.<br />
module-type</p>
<p>&nbsp;&nbsp;&nbsp; 模块的四种(目前是)类型.这四种类型是:</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; * auth; 这种模块类型确定有关用户认证的两方面. 第一,它确认用户就是他们自己,这通过指示应用程序提示用户输入密码或者其它证实身份的方法.第二,这类模块会赋予成员资格 Secondly,&nbsp; the module can grant group membership (independently of the /etc/groups file discussed above) or other privileges through its credential granting properties.<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; * account; 这些模块处理非认证级的帐号管理. 典型的用法是基于一天的不同时间段来限制/允许访问某服务,当前可用的系统资源 (最大用户数)或者限制特定用户&#8212;&#8217;root只能从控制台登录.<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; * session; 首先, 这类模块和一系列动作有关,指在用户得到/失去服务时要做的事. 这包括记录用户的登录/登出,挂载必须的目录等等.<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; * password; 这最后一种类型在更新用户的认证标志时需要. 通常,各个基于&quot;质问/回答&quot;(译注:指传统的用户名/密码的认证方法)的认证方法(auth)有一个对应的此模块.</p>
<p>control-flag</p>
<p>&nbsp;&nbsp;&nbsp; 控制符用来指示当某一模块返回成功或失败时PAM如何动作. 既然模块可以被堆叠 (同种类型的模块按先后顺序执行,一个接一个), 控制符决定每个模块的重要程度.应用程序不会直接接收&#8217;/etc/pam.conf&#8217; 里列出的每一个模块的成功或失败的结果. 相应的是,它只从 Linux-PAM接收一个 成功 或 失败 的结论. 这些模块的执行顺序就是它们在 /etc/pam.conf里的记录的顺序;排在前面的记录在排在后的记录之前被执行. 在Linux-PAM 0.60版本里, 这个control-flag 可以有两种语法来定义.</p>
<p>&nbsp;&nbsp;&nbsp; 简单一些(也是过去的)语法是用一个限定词指示相关模块的重要程度. 有四个关键字: required, requisite, sufficient 和 optional.</p>
<p>&nbsp;&nbsp;&nbsp; Linux-PAM 将这四个关键字解释为:</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; * required; 需要的,这表明此模块返回成功值对于整个module-type的成功是必要的. 此模块的返回失败并不会传回给用户直到剩下的模块(同样module-type)都执行过.<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; * requisite; 必要的,类似 required, 只不过, 当这类模块返回失败时,整个控制会立刻回到应用程序.&nbsp; 返回值同第一个 需要的 或 必要的模块返回的失败. 注意,这标志可以用来防止&nbsp; required or requisite module to fail. Note, this flag can be used to protect against the possibility of a user getting the opportunity to enter a password over an unsafe medium. It is conceivable that such behavior might inform an attacker of valid accounts on a system. This possibility should be weighed against the not insignificant concerns of exposing a sensitive password in a hostile environment.<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; * sufficient;&nbsp; 充分的,这模块返回的成功会被认为已经 充分满足Linux-PAM 库确认这类模块 (module-type)是成功的条件. 如果没有先前的requisite 模块返回了失败,那么不再会有其它&#8217;堆叠&#8217; 的模块被呼叫. (注意,&nbsp; 这种情况下,随后的requisite 模块就不会 被呼叫.). 这模块返回的失败不会看作是致命的错误而至影响应用程序从这module-type&nbsp; 得到成功的结果.<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; * optional; 可选的,正如这名字一样,此 control-flag 致使模块对最终的成功或失败的结果不会产生决定性的影响. 一般,Linux-PAM 在确定整个模块堆成功活失败时忽略这模块. 然而, 当从之前或后续的模块得不到明确的成功或失败的结果时,这模块将决定返回给应用程序的状态. 后种情况会出现在比如当其它模块返回PAM_IGNORE 时.</p>
<p>&nbsp;&nbsp;&nbsp; 更复杂(新)的语法则更明确,使管理员有更多的控制用户认证的空间. 这种控制符以方括号包含,由一系列的value=action 对组成:</p>
<p>&nbsp;&nbsp;&nbsp; [value1=action1 value2=action2 ...]</p>
<p>&nbsp;&nbsp;&nbsp; 这里的 valueI 有以下值 return values: success; open_err; symbol_err;&nbsp; service_err; system_err; buf_err; perm_denied; auth_err; cred_insufficient;&nbsp; authinfo_unavail; user_unknown; maxtries; new_authtok_reqd; acct_expired;&nbsp; session_err; cred_unavail; cred_expired; cred_err; no_module_data; conv_err;&nbsp; authtok_err; authtok_recover_err; authtok_lock_busy; authtok_disable_aging;&nbsp; try_again; ignore; abort; authtok_expired; module_unknown; bad_item; conv_again;&nbsp; incomplete; 和 default. 最后的 (default) 被用来定义当没有明确定义时的默认动作.</p>
<p>&nbsp;&nbsp;&nbsp; actionI 可以是一个正数或者是以下标识: ignore; ok; done; bad; die; 和 reset. 当以一个正数J 作为action 时,它的作用是指示以下J个模块将被跳过. 通过这种手段, 管理员可以开发出适度复杂的模块堆叠,它以许多不同的路径执行. 至于以何种路径则决定于某个模块的反应.</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; * ignore &#8211; 此类模块的返回状态将不会影响应用程序所得到的返回值.<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; * bad &#8211; 这表示相应的返回值将被认为是模块失败. 如果此模块是堆叠中的第一个失败的模块, 它的状态值将作为整个堆叠的状态.<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; * die &#8211; 和 bad 相同,不过会终止整个模块堆叠,PAM立即返回到应用程序.<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; * ok &#8211; 这告诉PAM 管理员要让此返回值直接作用于整个模块堆叠的返回. 换句话说, 如果堆叠的原先状态会导致返回&nbsp; PAM_SUCCESS, 这模块的返回值将会覆盖这结果. 请注意:如果堆叠的原先状态保存着一些意为模块失败的值,这&#8217;ok&#8217;将不会用来覆盖那样的值.<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; * done &#8211; 和 ok 一样, 不过会终止整个模块堆叠, PAM立即返回到应用程序.<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; * reset &#8211; 清除储存模块堆叠状态的内存并且重新开始下一组堆叠.</p>
<p>&nbsp;&nbsp;&nbsp; 来体会一下这种新语法的强大之处, 从 Linux-PAM-0.63起, 客户插件代理的概念被引进. 这多少使PAM支援从C/S应用程序固有的传输协议进行机器-机器的认证成为可能.(?) 通过 &#8220;[ ... value=action ... ]&#8221; 的语法, 使应用程序对支援binary prompt?的客户端采用binary prompt?, 而对旧有的客户端则向后兼容的采用另一种认证模式. 够灵活吧?<br />
module-path</p>
<p>&nbsp;&nbsp;&nbsp; 是可动态加载目标文件的路径; 也即可插入式模块 本身. 如果路径的首字符是 `/&#8217;, 那它被作为一个完整路径. 如果不是这样, 那模块的路径则会加上默认的模块路径: /usr/lib/security (见 above).<br />
args</p>
<p>&nbsp;&nbsp;&nbsp; args 是一组传给模块的参数. 类似一般Linux的指令的参数. 通常, 合法的参数是可选的并且是模块特有的. 无效的参数会被模块忽略, 可是, 当抓到一个无效参数, 模块被要求写一个错误信息到 syslog(3). 下一节有一个一般 选项的列表.</p>
<p>设定档里如果有任一行有格式错误, 那通常会导致认证流程失败. 相应的错误信息会通过呼叫syslog(3)写入系统日志.<br />
4.2 基于目录的设定</p>
<p>从0.56版开始有比单个配置文件更灵活的做法, 可以通过/etc/pam.d/里的文件来配置libpam. 这种方法,/etc/pam.d/里的文件名和服务名(service-name)相同(小写): 这是各服务的个性化设置档.</p>
<p>Linux-PAM 可以编译成两种模式之一. 首选的模式是使用/etc/pam.d/ 或/etc/pam.conf设定,但不是同时两者皆可.也就是说, 如果&lt;/etc/pam.d/目录存在那么libpam仅使用这目录里的文件当作设定档. 当/etc/pam.d/不存在时就用 /etc/pam.conf. 另一种模式是(是RedHat4.2以上版本的模式)按顺序同时用/etc/pam.d/和 /etc/pam.conf. 在这种模式下,/etc/pam.d/里的设定会覆盖/etc/pam.conf.</p>
<p>/etc/pam.d/里的文件的语法和/etc/pam.conf相似,由以下格式组成:</p>
<p>module-type&nbsp;&nbsp; control-flag&nbsp;&nbsp; module-path&nbsp;&nbsp; arguments</p>
<p>唯一的差别是service-name不再出现.service-name是给定的配置文件名. 例如,/etc/pam.d/login 里包含了login的配置.</p>
<p>此种设置方法比起处理单个文件有很多优点. 列举如下以帮助读者来决定采用何种方案:</p>
<p>&nbsp;&nbsp;&nbsp; * 遗漏应用程序的配置的机会比较小. 当手工编辑设定档时也少设定一个栏位.<br />
&nbsp;&nbsp;&nbsp; * 更易于维护. 配置某个应用程序不会有妨碍到别的应用程序的危险.<br />
&nbsp;&nbsp;&nbsp; * 建立不同的服务的配置文件为到某个文件的符号连接也是可能的. 这使保持不同的应用程序采用一致的系统策略变得容易些.&nbsp; (It should be noted, to conserve space, it is equally possible to hard link a number of configuration files. However, care should be taken when administering this arrangement as editing a hard linked file is likely to break the link.)<br />
&nbsp;&nbsp;&nbsp; * 更快的配置文件解析,只有和此服务相关的条目才会解析.<br />
&nbsp;&nbsp;&nbsp; * 采用文件系统的文件权限可以限制个别Linux-PAM设定档的读权限.<br />
&nbsp;&nbsp;&nbsp; * 包管理变得更简单. 每次当有新程序安装时,只需要附上/etc/pam.d/xxxxxx.</p>
<p>4.3 通用的可选参数</p>
<p>一下是一些基本所有模块都识别的可选参数.参数(包含这些)通常是可选的.</p>
<p>debug</p>
<p>&nbsp;&nbsp;&nbsp; 呼叫 syslog(3) 函数在系统日志里记录下debug信息.<br />
no_warn</p>
<p>&nbsp;&nbsp;&nbsp; 指示模块不要丢warning信息给应用程序.<br />
use_first_pass</p>
<p>&nbsp;&nbsp;&nbsp; 这模块将不会提示用户输入密码,它可以得到前面输入过的密码(从上一个auth模块)并且用它.如果那密码不正确,那么用户就不被认证.(这模块只对auth和password模块有意义.)<br />
try_first_pass</p>
<p>&nbsp;&nbsp;&nbsp; 这模块会先拿前面输入过的密码来认证(从上一个auth模块).如果通不过认证,就提示用户输入密码.(这模块只对auth模块有意义.)<br />
use_mapped_pass</p>
<p>&nbsp;&nbsp;&nbsp; 这参数目前没有任何Linux-PAM发布的模块支援,因为可能会违反美国加密软件出口限制.在美国国内,模块开发者当然可以自由的实现它(他国的开发者也一样).&nbsp; For compatibility reasons we describe its use as suggested in the DCE-RFC 86.0, see section bibliography for a pointer to this document.</p>
<p>&nbsp;&nbsp;&nbsp; use_mapped_pass 指示模块拿前一个模块生成的认证明文来产生一个加/解密的的键 ,以这键来安全的存储/取得此模块所需的认证标识.&nbsp; In this way the user can enter a single authentication token and be quietly authenticated by a number of stacked modules. Obviously a convenient feature that necessarily requires some reliably strong encryption to make it secure. This argument is intended for the auth and password module types only.<br />
expose_account</p>
<p>&nbsp;&nbsp;&nbsp; 通常模块暴露用户帐号的有关信息不是个安全的策略. 有时象用户名,用户的家目录,首选的shell这些信息可被用来攻击这帐号. 可是,这些信息不被视为威胁:在一个可信的环境里当要求输入密码时显示用户的全名, 这被叫做&quot;易用性&quot;.expose_account是个标准的模块参数,当管理员觉得合适(译注: 指暴露用户帐号的信息)时可以使模块和帐户信息少些离散.</p>
<p>4.4 设定档的范例</p>
<p>在这章,我们给出一些可以出现在Linux-PAM的设定档里的条目的范例. 作为第一次尝试配置你的系统,你可能会得的比实现它们更糟糕.<br />
默认策略</p>
<p>对于关键的系统,最好是有个适度安全的OTHER条目.以下是个&quot;偏执狂&quot;的设定 (以此开始不是个坏想法!):</p>
<p>#<br />
# default; deny access<br />
#<br />
OTHER&nbsp;&nbsp; auth&nbsp;&nbsp;&nbsp;&nbsp; required&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /usr/lib/security/pam_deny.so<br />
OTHER&nbsp;&nbsp; account&nbsp; required&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /usr/lib/security/pam_deny.so<br />
OTHER&nbsp;&nbsp; password required&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /usr/lib/security/pam_deny.so<br />
OTHER&nbsp;&nbsp; session&nbsp; required&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /usr/lib/security/pam_deny.so</p>
<p>Whilst fundamentally a secure default, this is not very sympathetic to a misconfigured system. For example, such a system is vulnerable to locking everyone out should the rest of the file become badly written.</p>
<p>pam_deny (在后面的章节里解释)不够复杂.比如,它被呼叫时不会记录任何信息, 如此除非用户告诉管理员说他不能执行某应用程序,管 &#8230;</p>
]]></content:encoded>
			<wfw:commentRss>http://blogs.gnome.org/raywang/2007/01/31/the-linux-pam-administrator-guide-1/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
<!-- This Quick Cache file was built for (  blogs.gnome.org/raywang/category/free-software/pam/feed/ ) in 2.62969 seconds, on Feb 10th, 2012 at 5:51 pm UTC. -->
<!-- This Quick Cache file will automatically expire ( and be re-built automatically ) on Feb 10th, 2012 at 6:51 pm UTC -->
