PAM管理手册

PAM管理手册

PS:因为是从WORD复制过来的,格式有点问题

3、总览

对于初学者,我们先从一个例子开始。我们使用一个可以授权一些服务给用户的应用为例;login就是这一个这样的程序。Login做两件事情,一是为有需求的用户建立连接,二是为他们提供所请求的服务,在login这个例子中服务是一个使用用户标识符运行的命令行shell(bash, tcsh, zsh, 等等)。

一般的步骤是这样的,login程序提示用户输入密码然后使用本地系统验证;验证通过后用户就可以登陆到系统。这个过程是委派给Linux-PAM的。

从程序员的观点来看Linux-PAM就是身份验证功能——验证用户标识符。

Linux-PAM的灵活性完全取决于系统管理员,可以通过明确的指定哪些身份验证是通过它来决定的。可以随意设置任意支持PAM的软件使用PAM身份验证在你的Linux系统上。你能通过anything(或者简单的信任pam_permit)去验证something(它甚至可以绑定了虹膜扫描、声音匹配或一次性密码)。

举一个灵活的例子给你,考虑下面的情况:一个系统管理员(家长)希望改善他用户(孩子)的数学能力。他能配置他们最爱的“Shoot’em up game”(支持PAM的软件)使用几个小于12的随机数相乘,通过身份验证后才能使用。这很显然,如果对玩游戏有任何好处他们将去学习他们的乘法表(It is clear that if the game is any good they will soon learn their multiplication tables. As they mature, the authentication can be upgraded to include(long) division!)

Linux-PAM的工作分为4个分开的部分。他们是:身份验证管理(authentication management)、账号管理(account management)、会话管理(session management)和密码管理(password management)。在相应的Linux-PAM配置文件中组织符合应用程序行为的管理任务。而管理功能是被写在配置文件中指定的模块(modules)执行的。对于这个文件的语法以后章节中讨论。

下图显示了Linux-PAM总体组织方式:

LINUX-PAM

顺便解释一下,图的左边描述了应用程序;应用X,是一个类似使用了Linux-PAM库的应用程序接口,并且不知道指定文件的配置验证方法。Linux-PAM库(中间部分)与PAM配置文件协商并加载应用X的模块。被加载的模块按着在配置文件中显示的顺序加载进入一个或四个管理组中(中间下面的部分)。这些模块当被Linux-PAM调用时,为应用程序执行多种验证任务。文本信息可以从用户获得(或提交给用户),可以使用应用程序支持的交互功能。

如果程序打算使用PAM,那么PAM功能代码必须存在于程序中。如果你可以访问程序原代码,那么你可以添加适合的PAM功能到程序里。如果你不能访问原代码,并且程序中没有包含PAM功能,那么就不能使用PAM。

4Linux-PAM配置文件

当一个支持PAM的应用启动时,它会激活它的附件送到PAM-API中。激活执行大量的任务,最重要的是读取配置文件:/etc/pam.conf或者/etc/pam.d目录中的内容。如果这个文件夹出现的话,那么Linux-PAM会忽略/etc/pam.conf文件。

这个文件列出了服务请求的验证任务,PAM将会作哪些事,还有如果验证失败后的相应行为。

4.1、配置文件语法

/etc/pam.conf文件的语法,这个文件是由一个规则列表组成的,每个规则占用一行,但是也可以通过换行符扩展到第二行中(”\<LF>”)。注释符号使用“#”,可以注释一整行,直到行的结尾。

第个规则的格式是通过空格分开的符号标记(tokens),前三项是大小写不敏感的:

(service    type          control     module-path    module-arguments)

服务         类型         控制         模块路径         模块参数

当配置文件包含在/etc/pam.d/目录中时,语法是一样的,除了缺少“服务”字段。在这种情况下,“服务”是/etc/pam.d/目录下的一个文件名,这个文件名必须是小写。

PAM的一个重要特性是,多种验证规则可以应用于一个服务上。(An important feature of PAM, is that a number of rules may be stacked to combine the services of a number of PAMs for a given authentication task.)

“服务”可以是符合应用程序的服务名,像:login或su这样的名字。这个服务名是为default规则保留的。只有涉及该服务的行,才会给予相关联的“服务-应用”。

“类型”是对应规则的管理组类型。它被用于管理分组,指定哪些模块子序列到相应的分组里。有效值是:(auth, account, password, session)(后面所说的“栈”,很有可能是“类型”

account:

这种类型的模块执行基于账号的非身份验证。它通常用于限制/允许访问:基于一天中的某些时间、当前系统可用资源(最大用户数)或某些用户(root)登陆仅限于控制台。

auth:

这种类型的模块提供两方面验证用户。首先,它用户连接后它会通过应用程序给予用户一个输入密码或其他表示信息的提示。最后,模块可以获得组权限或其他特权,然后通过它的委任状授予所有权。(Secondly, the module can grant group membership or other privileges through its credential granting properties.)

password:

这种类型的模块是用于更新相应用户的密码(authentication token)其实就是密码)。通常这里有一个基于auth类型的模块用于“疑问、响应”。(Typically, there is one module for each ‘challenge/response’ based authentication (auth) type)

session:

这种类型的模块负责在用户获得“服务”之前(后)做一些需要完成的事情。比如记录一些涉及用户打开(关闭)数据的交互信息、挂载目录等等。

如果在上面列出的“类型”值设置一个‘-’前缀,在因为系统缺失模块而不能加载时,PAM库不会使用系统日志功能记录。这个功能在模块不一定安装在系统上或者不需要正确的身份验证和授权时特别有用。(This can be useful especially for modules which are not always installed on the system and are not required for correct authentication and authorization of the login session.)

第三个字段,“控制”指示了在身份验证的任务中PAM-API模块失败后应该继续进行的动作行为。对于“控制”字段有两种语法:一种是简单的单个关键字;另一种复杂一点的是调用一个方括号中的“值=动作”对

对于简单的语法有效“控制”值是:

required:

如果PAM发生故障将最终导致PAM-API返回失效,但仅当剩下的模块(当前“类型”的“服务”)已经加载后。(failure of such a PAM will ultimately lead to the PAM-API returning failure but only after the remaining stacked modules (for this service and type) have been invoked.)

requisite:

和required类似,但是在某些情况这种“控制”会直接返回给应用程序或更高级别的PAM栈一个失败。返回的值是与第一个required或requiste模块相关的。注意,这个标记可以用于防止用户在不安全中间件上输入密码的可能。可以想象,这样的行为可能会通知攻击者在系统上的有效账户。在一个危险的环境中应该考虑不用这种标记,因为涉及暴露一个敏感密码。(This possibility should be weighed against the not insignificant concerns of exposing a sensitive password in a hostile environment.)

sufficient:

如果模块执行成功并且之前没有required模块失败,那么PAM会返回成功结果给应用程序或父类PAM栈,这个执行会立即发生,不会调用栈中其它模块。如果sufficient类的模块失败PAM模块会忽略,并继续处理其他模块。

Optional:

只有当这个类型的模块是“服务+类型”中唯一的模块时才重要。

Include:

包含给予配置文件中的所有行,配置文件在参数中指定。

Substack:

包含给予配置文件中的所有行,配置文件在参数中指定。它和include的不同之处在于对“完成”(done)和“死亡”(die)动作的评估,在substack 中不会引发跳过其余完整的模块栈,但仅是在substack中。在substack中的“跳跃”同样不能使评估(evaluation)跳出它,并且当“跳跃”在父栈(parent stack)中完成时,完整的substack是被计为一个模块的。Reset动作将会重置模块大子栈开始处的状态。(include all lines of given type from the configuration file specified as an argument to this control. This differs from include in that evaluation of the done and die actions in a substack does not cause skipping the rest of the complete module stack, but only of the substack. Jumps in a substack also can not make evaluation jump out of it, and the whole substack is counted as one module when the jump is done in a parent stack. The reset action will reset the state of a module stack to the state it was in as of beginning of the substack evaluation.)

 

对于复杂语法的有效“控制”值,如下形式:

[value1=action1 value2=action2 …]

valueN相应的值来自于程序调用相应行上定义的模块的返回值。它可以是下面的中一个:success, open_err, symbol_err, service_err, system_err, buf_err, perm_denied, auth_err, cred_insufficient, authinfo_unavail, user_unknown, maxtries, new_authtok_reqd, acct_expired, session_err, cred_unavail, cred_expired, cred_err, no_module_data, conv_err, authtok_err, authtok_recover_err, authtok_lock_busy, authtok_disable_aging, try_again, ignore, abort, authtok_expired, module_unknown, bad_item, conv_again, incompletedefault

在这些的最后default意味着所有这些值都没被匹配到。注意,完整的PAM错误列表在/usr/include/security/_pam_types.h中可以找到。actionN可以是如下形式中的一个:

ignore:

模块的返回值状态不会提交给返回代码让应用程序获得。

bad:

这个动作指出返回代码应该是通过失效模块得到的。如果这个模块是栈中第一个失效的模块,那么它的状态值将被用于整个栈。

die:

和“bad”相等,并终止模块栈和PAM立即返回给应用程序。

ok:

这个动作是说管理员认为应该这个返回代码应该直接提交到整个栈的返回代码上。换句话说,如果栈之前的状态指向了PAM_SUCCESS那么模块的返回代码将会覆盖这个值。注意,如果栈状态指出之前模块有失败的值存在,那么“ok”这个值是不会去覆盖失败的状态的。

done:

和“ok”相等,并且终止模块栈和PAM立即返回给应用程序。

N(一个无符号整型):

和“ok”相等,并跳过栈里后面N个模块。注意,N不能等于0。

reset:

清除模块栈所有的内存状态,并且开始下一个模块。(clear all memory of the state of the module stack and start again with the next stacked module.)

在四种关键字:required; requisite; sufficient; 和 optional,在方括号[…]表达式中的语法是相同的,如下所示:

required

[success=ok     new_authtok_reqd=ok          ignore=ignore           default=bad]

 

requisite

[success=ok     new_authtok_reqd=ok    ignore=ignore           default=die]

 

Sufficient

[success=done                   new_authtok_reqd=done        default=ignore]

 

Optional

[success=ok     new_authtok_reqd=ok    default=ignore]

“模块路径”可以是完整的觉对路径(以“/”开始),也可以是默认模块位置(/lib/security/或/lib64/security/)的相对路径。

 

“模块参数”是用空格分隔的符号列表,可以用来修改给定的PAM行为。类似的参数将被写在单独模块的文档中。注意,如果想要在参数中加入空格,就要用方括号括住参数。

以squid为例:

squid auth required pam_mysql.so user=passwd_query passwd=mada \          db=eminence [query=select user_name from internet_service \          where user_name=’%u’ and password=PASSWORD(‘%p’) and \          service=’web_proxy’]当使用这个惯例时,你可以包含‘[’字符在字符串中,并且如果同时希望使用‘]’字符的话,要使用转意字符进行转意‘\]’。也就是说:[..[..\]..] 内容是: ..[..]..    在配置文件中的任意行中,如果格式不正确的话,通常都会导致验证处理失败。一个相应的错误会通过syslog写到系统日志中。

4.2略

4.3 配置文件举例这一节我们给出一些在Linux-PAM配置文件中的例子。做为第一次试图配置你的系统,这些并不值得去实现。如果系统想要更安全,它最好有一些其它的安全项,下面这些是比较极端的设置(但并不是一个坏的开始):## default; deny access#Other      auth           required       pam_deny.soOther      account        required       pam_deny.soOther      password       required       pam_deny.soOther      session        required       pam_deny.so 对于一个没有配置过的系统,这个配置作为最基本的安全默认规则并不是很称心如意。例如,系统很容易被锁死,对于没有在PAM中配置过的程序,它的配置文件将变的很难写。模块pam_deny并不是很复杂。例如,当它被调用时不会记录任何信息,所以除非用户联系管理员,并告知应用服务被拒绝。另外,下面这些行,将会有一些适当的警告给管理员。## default; wake up! This application is not configured#Other      auth           required       pam_warn.soOther      password       required       pam_warn.so按如上配置就会有两个“other auth ”行在同一个栈中。在使用/etc/pam.d/这种目录结构配置时,相应的设置应该是这样的:## default configuration: /ect/pam.d/other#Auth               required       pam_warn.soAuth               required       pam_deny.soAccount            required       pam_deny.soPassword           required       pam_warn.soSession            required       pam_deny.so这是在给予/etc/pam.d/目录时的一个简明配置。

 5、安全问题

5.1如果做错了什么事最常见的问题是如果删除了/etc/pam.d/*或/etc/pam.conf文件,那你的系统就会被锁死,怎么办呢?想办法恢复系统文件,要不就重装系统。(PS:这节主要内容就是这样)

5.2避免使用一个没用的“other”配置Other配置是所有使用PAM软件的默认配置,如果它写不好的话系统容易遭到攻击。这有一个简单的other配置文件。Pam_deny模块是用于拒绝访问的,pam_warn是用于发送消息给系统日志的。## The PAM configuration file for the ‘other’ service#Auth               required       pam_deny.soAuth               required       pam_warn.soAccount            required       pam_deny.soAccount            required       pam_warn.soPassword           required       pam_deny.soPassword           required       pam_warn.soSession            required       pam_deny.soSession            required       pam_warn.so

6、可用模块说明

6.1. pam_access –logdaemon类登陆访问控制

Pam_access.so [debug][nodefgroup][noaudit][accessfile=file][fieldsep=sep][listsep=sep]

6.1.1描述pam_access模块主要用于访问管理。它提供基于登陆名、主机名、域名、IP地址、网段和非网络登陆的终端命令行的logdaemon类的登陆访问控制。在默认的情况下,如果没有指定其它的文件,访问管理的配置是提取自/etc/security/access.conf。如果Linux-PAM支持audit,那么模块会报告拒绝登陆的信息(主机或终端)。

6.1.2描述/etc/security/access.conf文件指定了(user/group,host)、(user/group,network/netmask)或(user/group,tty)的组合,哪些可以同意,哪些要拒绝。当某人登陆到系统时,将会扫描access.conf这个文件,当匹配到第一个的时候,就决定是接受还是拒绝。Access.conf文件中每一行都分为三个字段,每部分用冒号分隔“:”:Permission:users/groups:origins第一个字段“permission”可以是“+”(加号)同意访问,或“-”(减号)访问拒绝。第二个字段“users/groups”可以是一个登陆名或组名的列表,也可以写ALL(代表所有都能匹配上)。用于区分用户名和组名的方法是在组名上加括号,如(group)。第三个字段“origins”可以是一个或多个tty名字(用于非网络登陆)、主机名、域名(以“.”开始)、host addresses、internet network numbers(以“.”结尾)、网段(IP/子网掩码)或ALL(所有都匹配)再或者LOCAL。LOCAL关键字当且仅当PAM_RHOST没有设置并且<origin>字段设置成PAM_TTY或PAM_SERVICE时才能匹配。如果系统支持你可以使用@netgroupname这种形式用于主机和用户。@@netgroupname的语法仅被用户模式(user pattern)支持,并且它使本地系统主机名被传送到网络组(netgroup)匹配额外的用户名。这可能不会正常工作,在一些libc实现上会一直失效。(The @@netgroupname syntax is supported in the user pattern only and it makes the local system hostname to be passed to the netgroup match call in addition to the user name. This might not work correctly on some libc implementations causing the match to always fail.)“EXCEPT”操作让写规则变的简洁。如果nodefgroup没有置设置,当登陆名没有匹配成功时会查找组文件。以“#”开头,表示注释。

6.1.3选项Accessfile=/path/to/access.conf如果要使用非默认位置的access.conf文件的话,就使用该选项。DebugDebug信息会输出到syslog中。Noaudit不显示登陆失败的信息。Fieldsep=separators修改access.conf文件中默认的分割符Nodefgroup不再去匹配组。

6.1.4模块可用类型该模块可以用于所有类型(auth,account,password和session)

6.1.5返回值PAM_SUCCESS允许访问PAM_PERM_DENIED禁止访问PAM_IGNORE什么也不做,调用pam_setcredPAM_ABORT并不是能得到所有的相关数据或选项。PAM_USER_UNKNOWN未知系统用户

6.1.6文件/etc/security/access.conf默认配置文件

6.1.7例子这些例子中有一些是来自于/etc/security/access.conf文件。
Root用户可以从cron、X11 终端:0、tty1、…、tty5、tty6+:root:crond:0 tty1 tty2 tty3 tty4 tty5 tty6

Root用户可以从如下IP地址登陆,这并不意味着只有IPV4的IP才能登陆,如果这些IPV4相对应的IPV6地址也可以登陆。

+:root:192.168.200.1  192.168.200.4   192.168.200.9+:root:127.0.0.1

Root用户可以从192.168.201.网段访问(使用字符串进行匹配),这种写法等价于192.168.201.0/255.255.255.0,不过最后用后者代替前者。
+:root:192.168.201.

Root用户可以从主机foo1.bar.org和foo2.bar.org来访问(同样使用字符串进行匹配)
+:root:foo1.bar.org foo2.bar.org

Root用户可以从foo.bar.org域来访问(同样使用字符串进行匹配)
+:root:.foo.bar.org

Root用户拒绝从任何源来访问

-:root:ALL

用户foo和netgroup成员——admins允许从任何源访问,这仅当netgroup服务可用时才能工作。

+:@admins foo:ALL

用户john和foo可以从IPV6地址:2001:db8:0:101::1 进行访问

+:john  foo: 2001:db8:0:101::1

用户john可能通过IPV6地址段(网络/掩码)登陆:

+:john: 2001:db8:0:101::/64

禁止从控制台登陆所有用户,但是除了wheel组的成员,shutdown和sync用户

-:ALL EXCEPT (wheel) shutdown sync:LOCAL

禁止所有用户用任何方式登陆

-:ALL:ALL

6.2.pam_cracklib –检查不符合字典规则的密码

pam_cracklib.so […]

6.2.1 描述

这个模块被放到所给应用程序的password栈中,用于提供对密码的强度检查(strength-checking)。 这个模块的动作是提示用户的密码和密码强度是否违反了系统字典或一系列不安全设定的规则。 第一个动作仅是提醒密码然后再检查强度,如何密码被认为是符合强度要求的,那么会再提醒一次。只有都通过后密码才被传给子队列模块。 强度检查:首先cracklib在系统字典里轮训检查,密码是否是其中的一部分;密码检查会进行:

(1)新密码是不是一个回文。(2)Is the new password the old one with only a change of case?(3)新密码是否和旧的一样,它有一个参数difok,指出新密码和旧密码有几处相同,默认是5。(4)新密码太短。它有6个参数,minlen,maxclassrepeat,ucredit,lcredit,和ocredit。(5)新密码是曾经用过的旧密码(6)检查相同的连续字符(7)是否由很长的无变化字符组成(我觉得和6类似,原文:Optional check for too long monotonic character sequence)(8)检查密码中是否包含用户名。对于标准的unix密码加密这个模块可以很好的工作。如果使用MD5加密,密码长度超过8个字符时,这个模块的默认设置很难让用户得到一个满意的新密码。特别是当要求新的密码不能包含旧密码中一半字符的严格限制。例如,一个旧密码是“the quick brown fox jumped over the lazy dogs”,那么在默认的设置,是很难生成新密码的。另外默认设置是允许密码字符少于5个。

6.2.2 选项debug:输出调试信息到syslog(3)。 authtok_type=XXX默认会提示“New UNIX password:”和“Retype UNIX password:”,可以通过这个参数把UNIX改成XXX部分。 retry=N提示用户还有几次输错机会,这个默认值是1。 difok=N这个参数用于约束新旧密码之间有几个字符不同,默认值是5。 minlen=N新密码的最小长度,这个参数的默认长度是9。但这个模块有双重限制,有一个硬性限制是最少5个字符,如果要想让密码少于5个,那就不能使用这个模块。 dcredit=N(N>=0)如果新密码中的数字小于等于N,每一个数字就会复制一份,并要满足minlen的限定。默认情况下dcredit是1。 lcredit=N(N>=0)如果新密码中的小字字符小于等于N,那么每个字符都会再复制一份,并要满足minlen的限定。默认值是1。 ucredit=N(N>=0)如果新密码中的大字字符小于等于N,那么每个字符都会再复制一份,并要满足minlen的限定。默认值是1。 ocredit=N(N>=0)如果新密码中的其它字符小于等于N,那么每个字符都会再复制一份,并要满足minlen的限定。默认值是1。 minclass=N密码中要包含几种字符(数字、大小字符、小字字符、其它字符),默认值是0

发表回复