PAM: Pluggable Authentication Modules for Linux(未完待续)

2023-05-16

 PAM简介

    PAM诞生自1995年,最先由SUN提出并应用于Solaris2.3上。在这之后,经过广大开发人员的不懈努力,各版本的UNIX系统陆续提供了对PAM的支持,包括FreeBSD和Linux。其中专门针对Linux实现的PAM,通常被称为Linux-PAM。这些不同的PAM,除了具体的实现不同外,框架和标准API都是相同的。因为这些知识具有普适性,所以本书并没有特别指明要介绍的是 Linux-PAM。
    为了实现“可拔插”性,又要兼顾易用性,PAM采用了分层的体系结构:让各认证模块从应用中独立出来,然后通过PAM API作为两者联系的纽带,应用程序可根据实际功能需要,灵活地在其中“插入”所需类别的认证功能模块。所以,PAM可以被划分为三层:应用层、接口层和认证模块层,如上图。
    PAM API处在中间位置,负责应用与各模块之间的通信。当用程序调用PAM API时,相关的API实现代码会按照“配置文件”的规定,加载并调用应的模块所提供的功能来执行具体的认证操作。这样,只要修改“配置文件”的相关项就以改变具体应用的认证方式。而且,也可以根据实际需要,任意添加新的认证模块来实特殊的认证方式。
    PAM为了提供更为细粒度的认证控制,给模块划分了四种类型,分别代表四种不同认证任务。它们是:auth、account、session 和 password。这些模块类型前可以有-,表示该模块的认证过程不计入日志,反之则计入。
    auth 类型的模块用来执行实际的证工作,比如:提示用户输入密码或判断用户是否为root 等;
    account 类型的模块负责对用户的各种属性进行检查,比如:某个用户的密码是否到期、root 用户是否允许在这个终端登录等;
    session 类型的模块用于执行用户登录前、退出后的一些操作,以及对每个会话进行跟踪和记录,比如:给新用户初始化home目录、记录用户登录的时间等。
    password类型的模块实现了用户密码的细粒度管理,比如: 设定密码的有效期、允许重复输入的次数等。
    这四类模块可以堆叠使用。也就是说,一个认证动作可以同时使用多个相同类型的模块共同去完成。这就像“陪审团”去判断一个用户是否“有罪”一样,只要达到相应的“比例”就可以作出结论。而且每个具体的模块也不会仅限于一种类型,它们的“身份”也会随时变化。具体应该怎样,一切由配置文件说了算。
    PAM的配置文件通常是pam.conf文件或pam.d目录,它们都会保存在/etc目录下。具体是使用pam.conf还是 pam.d目录,不同的发行版可能不同:centos、redhat、suse不存在pam.conf,debian和Ubuntu,同时存在pam.conf和pam.d目录。
    pam.conf和pam.d目录一般不会同时出现,即便同时出现,pam.conf也不会生效。在pam.conf文件中会有如下提示:
    NOTE: Most program use a file under the /etc/pam.d/ directory to setup their PAM service modules. This file is used only if that directory does not exist.(注意:大多数程序使用/etc/pam.d/ 目录下的文件来设置PAM服务模块。仅当该目录不存在时才使用此文件。)
    
    在使用pam.conf文件的时候,所有配置信息都会保存在这个文件中,使用pam.d文件的时候,每个应用会有一个与它对应的配置文件,对应方式就是具体的配置文件名会与对应的应用名相同。
 

控制标记

一条记录为一行,并且使用空白字符(包括 Tab)将其划分成多个字段。格式如下:
pam.conf配置格式:
[应用名]     [模块类型]         [控制标识]      [模块路径]      [模块参数1 模块参数2 ... 模块参数n]
serv.name     [-]module.type     ctrl.flag     module.[path]     ...[args..]    
pam.d/下文件配置格式:
[模块类型]         [控制标识]      [模块路径]      [模块参数1 模块参数2 ... 模块参数n]
[-]module.type     ctrl.flag     module.[path]     ...[args..] 

# 举例
cat /etc/pam.d/system-auth

#%PAM-1.0
# This file is auto-generated.
# User changes will be destroyed the next time authconfig is run.
auth        required      pam_env.so
auth required pam_faillock.so preauth silent audit deny=5 unlock_time=900 even_deny_root
auth        required      pam_faildelay.so delay=2000000
auth        sufficient    pam_unix.so nullok try_first_pass
auth        requisite     pam_succeed_if.so uid >= 1000 quiet_success
auth [default=die] pam_faillock.so authfail audit deny=5 unlock_time=10 even_deny_root
auth        required      pam_deny.so

每个应用都会配置多个相同类型的模块,这就是模块的堆叠使用。具体到执行阶段,同等类型的模块会被按照其出现的顺序来执行。
应用名为other代表了所有未明确指定配置项的应用,实质上并不存在叫other的应用。在/etc/pam.d/下也有一个命名为other的文件。
一般情况下,other对应的所有pam配置都应该是指向pam_deny.so的,拒绝所有请求。

假设A是条件,B是结论:
由A可以推出B
由B可以推出A~~则A是B的充分且必要条件

由A可以推出B
由B不可推出A~~则A是B的充分不必要条件

由A不可推出B
由B可以推出A~~则A是B的必要不充分条件

由A不可推出B
由B不可推出A~~则A是B的不充分不必要条件

由条件能推出结论,但由结论推不出这个条件,这个条件就是充分条件。
如果能由结论推出条件,但由条件推不出结论。此条件为必要条件。
如果既能由结论推出条件,又能有条件 推出结论。此条件为充要条件。

 

required(必要条件)

表示该模块的认证成功是用户通过认证的必要条件。也就是说,只要有一个被标明为 required 的模块认证失败,用户就一定不会通过认证。但是,即便这类模块认证失败,PAM 也不会立即将错误消息返回给应用,而是继续将其他模块都调用完毕之后才返回。这样做的目的就是为了麻痹“敌人”,让他们搞不清楚到底是哪里认证失败的。所以,required 是最常用的控制标记

requisite(必要条件)

 与required 差不多,但是只要用它标记的模块认证失败,就会立即返回给应用。具体的返回值与第一个认证失败的模块有关。一般被requisite标记的模块多数用来判定当前用户所处的环境,如果环境不够安全,即便是合法的用户也不会通过验证这是最严苛的要求,一般很少使用。但是 requisite 能够降低黑客利用不安全媒介获得输入密码的机会。

sufficient(充分条件)

表示该模块验证成功是用户通过认证的充分条件。只要这个模块验证成功了,就代表没有必要继续去认证这个用户了。那么相应的行为就是只要被suficient标记的模块一旦认证成功,就会立刻返回验证成功,把控制权交回应用程序。其后相关模块的所有控制都将会比忽略;但是需要注意的是sufficient的优先级低于required,那么如果有required失败,则最终的结果也是失败的;当sufficient 认证失败时,相当于optional,对认证结果不起作用。

optional

这表示即便该模块认证失败,用户也可能通过认证,除非别无它选。换句话说它仅供参考。而实际应用中,optional 所标记的模块只是显示些信息,根本不去做认证工作。

include

include 属于控制标记,只会对“模块类型”字段所标记的一类模块起作用。即便system-aut可能包含了全部四种类型的模块,也只有与当前记录所对应的那一类模块的那些记录被包含了进来。原文:
include    include all lines of given type from the configuration file specified as an argument to this control.

substack

substack 和include类似,不同之处在于,对子堆中的done和die的行为的评估不会导致跳过整个模块堆栈的其余部分,而只会跳过子模块。原文:
substack   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.
翻译:
包含作为此控件的参数指定的配置文件中给定类型的所有行。这与include不同,在子堆栈中评估done和die动作不会导致跳过整个模块堆栈的其余部分,而只会跳过子堆栈。
在子堆栈中的跳转(比如:自堆栈中也存在include或substack控制标识)也不会做出跳出它自身的评估,当在父堆栈中完成跳转时,整个子堆栈被算作一个模块。
reset操作将子堆栈重置为开始时的状态。
 
我们完全可以把substack当成用户认证阶段的“子过程”。

自定义控制标识

这是一种比较复杂的语法来设置控制标志,它由一组value=action形式的标记组成,标记之间以空格分开:
[value1=action1 value2=action2 ...]

valueN可以是Linux-PAM函数库中任何一个函数的返回值,返回值包括: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, incomplete, and default.最后一个(default)能够用来设置上面的返回值无法表达的行为。
 

常见的模块返回值

状态说明
success认证成功
auth_err认证失败
new_authtok_reqd说明需要新的认证令牌。有三种情况会返回这个状态:一是根据安全策略需要更改密码;二是密码为空;三是密码已经过期
ignore忽略底层account类型模块的返回状态,而且无论是否被required、sufficient和optional修饰。出于安全性考虑,这个返回状态通常要被忽略掉,这样其他模块的返回状态就会被参考
user_unknown未知用户
try_again已经通过了密码服务的初步检测
default所有没有注明的返回状态

PAM支持的动作列表

标记说明
ignore忽略这个返回状态,不会对验证结果产生影响;如果使用层叠模块,这个模块的返回状态将不会对应用程序获取的返回值产生影响。
bad表示这个返回状态代表验证失败,余下的模块调用也永远失败;它表示这个返回码应该被看作是模块验证失败。如果这个模块是层叠模块的第一个验证失败的模块,那么它的状态值就是整个层叠模块的状态值。
die与bad相同,但是应该立即返回到应用,不再继续调用余下模块;对层叠模块最终结果的影响相当于bad,并且立刻反回到应用程序。
ok表示这个返回状态应该被看作是验证成功,继续调用余下模块
done与ok相同,但是应该立即返回到应用,不再继续调用余下模块
N(一个整数)与ok相同,但是要跳过N个模块才能继续(就表示需要忽略后面堆叠的n个同样类型的模块。)
reset清除所有的返回状态,继续调用余下模块
  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]
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

PAM: Pluggable Authentication Modules for Linux(未完待续) 的相关文章

  • 客户端凭据授予的访问令牌是否可以映射到用户?

    我想使用 oauth2 中的客户端凭据授予来保护 API 但是 我希望访问令牌映射到单个用户 由我在带外信任 设置阶段选择 在该阶段我共享密钥 秘密 这是一个问题吗 我知道使用客户端凭据授予的访问令牌不应该在用户的上下文中 以这种方式绑定它
  • 在 Java 服务器中验证 Windows 用户

    我正在开发一个用 Java 编写的服务器和一个在同一网络上的 Windows 计算机上运行的客户端 用 Net 编写的桌面应用程序 我希望进行一些基本身份验证 以便服务器可以确定运行客户端的用户的用户名 而不需要用户在客户端中重新输入其 W
  • Django 自定义 UserManager 中的 self.model()

    所以 我对 Django 还很陌生 尽管我的代码在遵循 Django 文档 在 Django 中自定义身份验证 之后工作 但我不明白他们的示例中的 self model 实际如何工作 它来自哪里以及它如何与 自己 这是在文档底部找到的示例
  • 如何使用 keycloak 强制每个客户端登录(最佳实践?)

    我们目前正在实施 keycloak 但我们面临着一个问题 我们不确定解决它的最佳方法是什么 我们有不同的网络应用程序使用单点登录 并且运行良好 我们遇到的问题是 当我们在一个 Web 应用程序中使用 sso 登录 然后在另一个 Web 应用
  • Symfony 5.4 Security Bundle,注册后无法登录

    我在 5 4 版本上构建空的新项目 我使用这些命令来构建项目 composer create project symfony skeleton 5 4 testapp54 cd testapp54 composer require weba
  • 使用操作系统用户名/密码在 PHP 中进行身份验证?

    我想知道是否有一种方法可以使用 PHP 或者可能是其他一些 CGI 但最好是 PHP 来使用其操作系统 在本例中为 Linux Debian 5 用户名和密码来验证用户 可能的 难的 谢谢 一般来说 这种东西是特定于操作系统的 并与现有的身
  • IdentityServer4 客户端 - 刷新 CookieAuthenticationEvents 上的访问令牌

    我试图在访问令牌过期时使用刷新令牌 类似的问题已回答here https stackoverflow com a 41557598 3501052 And 更新令牌的示例代码 https stackoverflow com question
  • 客户端登录 - 如何在客户端安全地存储凭据?

    许多 API 都提供通过用户 密码组合远程访问其数据的功能 我想知道存储这些值的最佳方式是什么 高度安全的方式 即使 100 是不可能的 以便直接连接它们而无需每次都询问这些值 我推荐以下三种方法之一 使用身份验证令牌完全避免存储密码 在此
  • Grails + Spring Security:无法登录

    我刚刚开始学习Grails和Spring 我已经按照官方教程创建了一个登录系统 但我无法登录 用户名或密码不匹配 我知道 90 的情况下这是由于双重编码或多个数据源 这也导致双重编码 造成的 但我也没有这样做 class BootStrap
  • 游戏中心邀请处理程序,它属于哪里?

    我已经搜索了该网站并发现了这个 GameCenter 邀请处理程序 https stackoverflow com questions 4639284 gamecenter invitation handler He says 正如文档中所
  • python:API 令牌生成及其危险

    我正在按照 Flask Web Development 一书来实现基于令牌的身份验证 基本上 用户使用 HTTP 基本身份验证对其进行身份验证 并为其生成令牌 s Serializer app config SECRET KEY expir
  • 如何使用 Google 帐户对我们网站中的用户进行身份验证

    如何在我们的网站中使用 Google 帐户对用户进行身份验证 我希望用户重定向到谷歌登录页面 然后将他重定向到我的网站 我想要这个 PHP 实现 你要OAuth http code google com apis accounts docs
  • 在哪里可以找到 OpenID 提供商 URL 列表? [关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 我已经在我的网站上实现了 OpenID 但我很难找到 OpenID 提供商 URL 列表 我以为这很容
  • iPhone 应用程序在首次 Facebook Connect 授权/登录后崩溃

    我一直在到处寻找答案 但找不到 问题是 我有一个 iPhone 应用程序 在 AppStore 上 它使用脸书 iPhone SDK https github com facebook facebook iphone sdk 我使用 SDK
  • 使用socket.io进行用户身份验证

    我已经红色了这个教程 http howtonode org socket io auth http howtonode org socket io auth 它展示了如何使用express和socket io对用户进行身份验证 但是有没有一
  • java ee - 使用 servlet 对用户进行身份验证

    我刚刚开始学习java 还没有接触过java ee 我需要使用 servlet 来验证用户身份 请提供示例代码和技术文献 谢谢你 创建一个接受用户名 密码的 html 表单 将这些数据发布到 servlet 在 doPost 中读取这些数据
  • Cakedc.users => 总是重定向到主页

    我在新的 Cakephp 安装上使用插件 CakeDC Users 我有两个控制器 PagesController php CardsController php Pages 有 1 个操作 Beta 它是主页 Cards 有两个操作 索引
  • 如何在 JSF 中实现登录过滤器?

    即使用户知道某些页面的网址 我也想阻止某些页面的访问 例如 localhost 8080 user home xhtml 需要先登录 如果没有登录则重定向到 index xhtml 在 JSF 中如何做到这一点 我在谷歌上看到需要一个过滤器
  • SSO:SP 是否应该在每个请求中验证与 IDP 的会话

    根据 SP 发起的 SSO 流程 用户尝试访问 SP 由于用户未经身份验证 因此他会被重定向到 IDP 在其中输入凭据 成功登录后 IDP 在用户的浏览器中设置 cookie 在 IDP 的域下 并使用 SAML 响应将用户重定向回 SP
  • 需要将用户名和密码添加到 VB.NET Web 服务客户端中的 SOAP 标头

    我需要查询一个进行基本身份验证的 Web 服务 将用户名和密码放在请求标头中 我的客户端是用 VB NET Visual Basic Express Edition 2010 编写的 我已将 Web 服务添加到服务引用中 它为我自动生成了合

随机推荐

  • Qt5.14.2 编程应用

    目录 简介 什么是Qt Qt可以做什么 安装 ubuntu安装Qt5 14 2 1 xff0c 下载地址 xff1a Index of archive qt 5 14 5 14 2 2 xff0c 安装 示例与运行 查看官方示例源代码 创建
  • 解读AFNetworking4.0请求原理

    简介 AFNetworking4 0 是对NSURLSession的封装 xff0c 之前版本有NSURLConnection的封装 xff0c 现在已经被废弃 简单聊一下 xff0c 为啥AF要弃用之前的NSURLConnection封装
  • SSM框架中的数据库连接问题

    SSM框架搭建好以后 xff0c 由于log4j的日志输出有限 xff0c 经常遇见事务无法执行但是却很难定位的情况 DEBUG以后才发现是Mapper文件中的语法错误导致 所以 xff0c 在异常转化的拦截器类 xff08 Busines
  • 一文详解Unexpected character (‘“‘ (code 34)): was expecting comma to separate Object entries的问题

    文章目录 1 复现问题2 分析问题3 解决问题4 重要补充4 1 knife4j的详细教程 1 复现问题 今天在使用knife4j请求后端接口时 xff0c 首次请求能够正常访问 只是修改个参数值 xff0c 就报出如下错误信息 xff1a
  • 全网超详细的VMware虚拟机安装Kali Linux系统以及首次启动Kali Linux系统的注意事项

    文章目录 1 简述Kali Linux2 下载Kali Linux的镜像文件3 安装Kali Linux4 首次启动Kali Linux5 其他方法安装Kali Linux 1 简述Kali Linux 引入知乎上的一句话 xff0c 如下
  • Error attempting to get column ‘xxx‘ from result set. Cause: java.sql.SQLDataException错误的解决方法

    文章目录 1 复现错误2 分析错误3 解决错误4 文末总结 1 复现错误 今天写好导入hive表的详情列表的接口 xff0c 如下代码所示 xff1a span class token comment hive表导入的回调接口 64 aut
  • 文件传输协议FTP、SFTP、SCP

    今天在了解Ansible的时候看到了Ansible是基于SFTP协议进行文件传输的 xff0c 就想了解下FTP协议与SFTP协议的区别 xff0c 因为总结了这篇文章 应用层 xff1a HTTP xff08 Hypertext Tran
  • SSH配置免密登录 详解(踩坑无数总结)

    之前在使用Ansible部署工具的时候 xff0c 需要先配置好SSH免密登录 xff0c 在配置时踩了很多的坑 xff08 按照很多文章的步骤并不能完全配置好免密登录 xff09 xff0c 因此在踩完所有的坑之后 xff0c 总结出来这
  • CentOS7.6升级内核到5.11及build RPM包

    目录 源码编译方式升级内核 安装依赖包 升级GCC 编译安装kernel5 11 构建RPM包 安装RPM包 源码编译方式升级内核 在编译高版本内核之前 xff0c 构建编译环境以及依赖包安装是肯定的 xff1b 但是 xff0c Cent
  • 内存对齐规则--图文详解

    在之前的C语言结构体的学习中 xff0c 遇到了内存对齐的问题 xff0c 之后在C 43 43 的类的学习中 xff0c 再次遇到了内存对齐问题 xff0c 所以我觉得有必要总结一下这个知识点 内存对齐规则 1 xff09 第一个成员在与
  • #define定义宏函数 的正确使用

    如何使用宏来定义一个自定义函数呢 xff1f 首先我们来看下面这段代码 define SQUARE x x x int main int a 61 5 printf 34 SQUARE a d n 34 SQUARE a 这个值为25 pr
  • C语言运算符优先级列表(超详细)

    本篇文章是对C语言中运算符的优先级进行了详细的分析介绍 xff0c 需要的朋友参考下 C语言运算符优先级 优先级 运算符 名称或含义 使用形式 结合方向 说明 1 数组下标 数组名 常量表达式 左到右 圆括号 表达式 xff09 函数名 形
  • 直接插入排序讲解及代码实现

    基本思想 每一步将一个待排序的元素 xff0c 按其排序码的大小 xff0c 插入到前面已经排好序的一组元素的合适位置上去 xff0c 直到元素全部插完为止 当插入第i i gt 61 1 个元素时 xff0c 前面的array 0 arr
  • 虚拟地址空间 及 页表 详解

    虚拟地址空间 进程地址空间由进程可寻址的虚拟内存组成 xff0c 内核允许进程使用这种虚拟内存的地址 每个进程都有一个 32位或64位 的平坦地址空间 xff0c 空间的大小取决于体系结构 xff08 平坦指的是地址空间范围是一个独立的连续
  • vector 模拟实现

    define CRT SECURE NO WARNINGS 1 include lt iostream gt include lt algorithm gt include lt assert h gt include lt Windows
  • C语言中的字节对齐

    一 什么是字节对齐 一个基本类型的变量在内存中占用n个字节 则该变量的起始地址必须能够被n整除 即 存放起始地址 n 61 0 那么 就成该变量是字节对齐的 对于结构体 联合体而言 这个n取其所有基本类型的成员中占用空间字节数最大的那个 内
  • Gson转换Date类型出错处理(com.google.gson.internal.bind.DateTypeAdapter.deserializeToDate)

    用Gson做对象和Json字符串相互转换很方便 xff0c 但要把包含java util Date类型属性的对象转换成Json字符串 xff0c 如下面的代码 xff1a Gson gson 61 new Gson String p 61
  • orm框架sequelize的where条件接受动态参数传入

    在nodejs项目中 xff0c 接口会接收从前台传来的查询参数 xff0c 接口里面根据请求参数动态查询数据库 xff0c 例如分页参数等等 xff1b sequelize官方文档中并没有提及如何做 xff0c 不过可以利用sequeli
  • 判断单链表是否存在回环

    Author Victor LV Date 2016 9 6 10 14 Description 判断单链表是否有回环C 43 43 C 43 43 判断单链表是否存在回环 输入 list的头指针 返回 bool true表示有回环 fal
  • PAM: Pluggable Authentication Modules for Linux(未完待续)

    PAM简介 PAM诞生自1995年 xff0c 最先由SUN提出并应用于Solaris2 3上 在这之后 xff0c 经过广大开发人员的不懈努力 各版本的UNIX系统陆续提供了对PAM的支持 包括FreeBSD和Linux 其中专门针对Li