Linux 可插拔认证模块的基本概念与架构

Linux 可插拔认证模块的基本概念与架构

背景

  1. 一般的用户认证都是用户输入的密码和数据库中的密码进行对比
  2. 用户进行身份认证的时候抛出的几个问题
  • 如何真正实现正确鉴别用户的真实身份?
  • 在鉴别用户合法身份之后,如何确定用户可以对哪些资源进行访问?
  • 如何控制用户以何种方式来访问计算机资源?
  • 如何对用户的安全访问随时随地按需调整?

当前现状和存在的问题

当前的现状

  1. linux实现的功能
    linux中有/etc/passwd和/etc/shadow文件。
  • /etc/passwd:
    gluster: x:496:494:GlusterFS daemons:/run/gluster:/sbin/nologin
    用户名名: 密码占位符:uid:gid:用户说明:用户家目录:登录shell

  • /etc/shadow
    gluster:!!:17888::::::
    用户名:加密过后的密码:上一次修改密码的日期:俩次修改密码的最短间隔:密码过期前的警告时间:非活动时间:用户过期时间:保留

  1. 在 Linux 类操作系统中,定义用户信息和密码信息的字段和格式都需要符合标准的 Linux Naming Service Switch 定义,即 NSS 定义。因此用户信息只要保证满足 NSS 规范,就可以来源于本地 passwd 和 shadow 之外的其它信息数据库和认证源。所以在此基础上还派生出一些其它认证解决方案。例如 NIS、LDAP 等,都可作为存放用户信息的数据库,而存放用户口令或者鉴别用户身份的数据库,可以采用专用于网络环境的 Kerberos 以及智能卡鉴别系统等方式。

pam

可插拔认证模块pam的基本概念

这坨东西直接复制的,总地来说可以了解一下

  • 可插拔认证模块(PAM)机制采用模块化设计和插件功能,使用户可以轻易地在应用程序中插入新的认证模块或替换原先的组件,同时不必对应用程序做任何修改,从而使软件的定制、维持和升级更加轻松。因为认证和鉴别机制与应用程序之间相对独立。所以应用程序可以通 PAM API 来方便地使用 PAM 提供的各种鉴别功能而不必了解太多的底层细节。此外 PAM 的易用性也较强,主要表现在它对上层屏蔽了鉴别和认证的具体细节,所以用户不必被迫学习各种各样的鉴别方式,也不必记住多个口令;又由于它实现了多鉴别认证机制的集成问题,所以单个程序可以轻易集成多种鉴别机制,如 Kerberos 和 Diffie - Hellman 等认证机制,但用户仍可以用同一个口令登录而且感觉不到采取了各种不同的鉴别方法。

pam的分层体系结构

  1. 分层设计思想:就是让各鉴别模块从应用程序中独立出来,然后通过 PAM API 作为两者联系的纽带,这样应用程序就可以根据需要灵活地在其中"插入"所需要的鉴别功能模块,从而真正实现了在认证和鉴别基础上的随需应变

  2. 简单的说明一下这个图
      PAM 的 API 起着承上启下的作用,它是应用程序和认证鉴别模块之间联系的纽带和桥梁:
      当应用程序调用 PAM API 时,应用接口层按照 PAM 配置文件的定义来加载相应的认证鉴别模块。然后把请求(即从应用程序那里得到的参数)传递给底层的认证鉴别模块,这时认证鉴别模块就可以根据要求执行具体的认证鉴别操作了。当认证鉴别模块执行完相应的操作后,再将结果返回给应用接口层,然后由接口层根据配置的具体情况将来自认证鉴别模块的应答返回给应用程序。(这个实际上就是整体的认证流程,之后会针对实际的登录操作进行分析)
    5c01e6eb.png

  3. 具体的说一下这个图

  • 第一层:模块层(模块就是真正执行认证操作的c代码编译后的库文件)。模块层处于整个 PAM 体系结构中的最底层,它向上为接口层提供用户认证鉴别等服务。也就是说所有具体的认证鉴别工作都是由该层的模块来完成的。对于应用程序,有些不但需要验证用户的口令,还可能要求验证用户的帐户是否已经过期。此外有些应用程序也许还会要求记录和更改当前所产生的会话类的相关信息或改变用户口令等。所以 PAM 在模块层除了提供鉴别模块外,同时也提供了支持帐户管理、会话管理以及口令管理功能的模块。当然,这四种模块并不是所有应用程序都必需的,而是根据需要灵活取舍。比如虽然 login 可能要求访问上述所有的四种模块, 但是 su 可能仅仅需要使用到鉴别模块的功能即可。至于如何取舍则涉及到接口层的 PAM API 和配置文件。

  • 第二层:应用接口层(调用模块然后对模块返回的数据进行逻辑处理返回给应用程序)。应用接口层位于 PAM 结构的中间部分,它向上为应用程序屏蔽了用户鉴别等过程的具体细节,向下则调用模块层中的具体模块所提供的特定服务。由上图可以看出,它主要由 PAM API 和配置文件两部分组成。

    1. PAM API 可以分为两类:一类是用于调用下层特定模块的接口,这类接口与底层的模块相对应,包括:
    • 鉴别类接口:用于用户的pam_authenticate()接口和用于管理认证凭证的pam——setcred()接口对应着auth类型的模块

    • 帐号类接口:用于确认用户是否有权限登录系统的pam_acct_mgmt()接口对应着account类型的模块

    • 会话类接口:用于打开和关闭用户对话的pam_open_session()和pam_close_session()接口对对那个着session类型的模块。

    • 口令类接口:用于修改用户口令的pam_chauthtok()接口对应着password类型的模块

    1. 第二类接口通常并不与底层模块一一对应,它们的作用是对底层模块提供支持以及实现应用程序与模块之间的通信等。具体如下:
    • 管理性接口: 每组 PAM 事务从 pam_start()开始,结束于 pam_end()函数。接口 pam_get_item()和 pam_set_item()用来读写与 PAM 事务有关的状态信息。同时,能够用 pam_str()输出 PAM 接口的出错信息。
    • 应用程序与模块间的通讯接口:在应用程序初始化期间,某些诸如用户名之类的数据可以通过 pam_start()将其存放在 PAM 接口层中,以备将来底层模块使用。另外底层模块还可以使用 pam_putenv()向应用程序传递特定的环境变量,然后应用程序利用 pam_getenv()和 pam_getenvlist()读取这些变量。
    • 用户与模块间的通讯接口:pam_start()函数可以通过会话式的回调函数,让底层模块通过它们读写模块相关的鉴别信息,比如以应用程序所规定的方式提示用户输入口令。
    • 模块间通讯接口:尽管各模块是独立的,但是它们仍然能够通过 pam_get_item()和 pam_set_item()接口共享某些与鉴别会话有关的公用信息,诸如用户名、服务名、口令等。此外,这些 API 还可以用于在调用 pam_start()之后,让应用程序修改状态信息。
    • 读写模块状态信息的接口:接口 pam_get_data()和 pam_set_data()用以按照 PAM 句柄要求访问和更新特定模块的信息。此外,还可以在这些模块后附加一个清除数据函数,以便当调用 pam_end()时清除现场。
      由于 PAM 模块随需加载, 所以各模块始化任务在第一次调用时完成。如果某些模块的清除任务必须在鉴别会话结束时完成,则它们应该使用 pam_set_data()规定清除函数,这些执行清除任务的函数将在应用程序调用 pam_end()接口时被调用。
posted @ 2020-02-11 10:47  I'm杨呵呵  阅读(496)  评论(0编辑  收藏  举报