linux 扩展pam支持第三方认证

利用PAM支持第三方认证

linux pam的介绍

Linux pam是由sun公司开发的一款开源软件。PAM全称为Pluggable Authentication Modules,可动态插入删除的认证模块。
只需要修改相关配置,无需重启系统或服务,就可以更改认证方式。具有很高的灵活性。

PAM认证流程

  1. client使用远程登入到设备(以ssh登入为例).
  2. sshd或其他登入模块使用pam认证机制, 最终调用自定义开发的pam-xxx.so.
  3. pam-xxx.so调用第三方认证模块
  4. 第三方认证模块将认证结果返回给pam-xxx.so.
  5. pam-xxx.so将认证结果返回给sshd.
  6. 认证成后, sshd会根据/etc/passwd中配置的shell, 启动对应的shell.
1
2 pam
3 (user + pw)
4 认证结果
5 认证结果
6
N
Y
client
sshd
login
...
pam-sfos.so
api-auth
认证成功?
exit
根据/etc/passwd
启用设置的shell

PAM相关配置介绍

  • PAM的类别
    • PAM 的具体工作主要有以下四种类别(type):account,auth,password 以及 session
      • account: 在用户能不能使用某服务上具有发言权,但不负责身份认证。
        比如,account 这个 type 可以检查用户能不能在一天的某个时间段登录系统、这个用户有没有过期、
        以及当前的登录用户数是否已经饱和等等。通常情况下,在登录系统时,
        如果你连 account 这个条件都没满足的话,即便有密码也还是进不去系统的。
      • auth: 这个就是认证的type, 如果认证方式很多,密码、指纹、虹膜… 都是在这个type下 。
        auth 做的另外一件事情是权限授予,比如赋给用户某个组的组员身份等等。
      • password: 这个是控制密码相关的type,比如设置或修改密码。
      • session: 这个type主要是在登入前后做些准备工作,
        比如:用户登录之前要将用户家目录准备好,或者在用户登录之后输出 motd 等等
  • PAM 的配置文件

    PAM 的各个模块一般存放在 /lib/security/ 或 /lib64/security/ 中,以动态库文件的形式存在,文件名格式一般为 pam_*.so。
    PAM 的配置文件可以是 /etc/pam.conf 这一个文件,也可以是 /etc/pam.d/ 文件夹内的多个文件。
    如果 /etc/pam.d/ 这个文件夹存在,Linux-PAM 将自动忽略 /etc/pam.conf。

    • /etc/pam.conf 类型的格式:服务名称 工作类别 控制模式 模块路径 模块参数
    • /etc/pam.d/xxx的格式:工作类别 控制模式 模块路径 模块参数,如/etc/pam.d/sshd
    	sangfor@Austzhu: sfcli ✘  cat /etc/pam.d/sshd | grep -v "^#"
    	@include common-auth
    	account    required     pam_nologin.so
    	@include common-account
    	session [success=ok ignore=ignore module_unknown=ignore default=bad]        pam_selinux.so close
    	session    required     pam_loginuid.so
    	session    optional     pam_keyinit.so force revoke
    	@include common-session
    	session    optional     pam_motd.so  motd=/run/motd.dynamic
    	session    optional     pam_motd.so noupdate
    	session    optional     pam_mail.so standard noenv # [1]
    	session    required     pam_limits.so
    	session    required     pam_env.so # [1]
    	session    required     pam_env.so user_readenv=1 envfile=/etc/default/locale
    	session [success=ok ignore=ignore module_unknown=ignore default=bad]        pam_selinux.so open
    	@include common-password
    
    • 控制模式的描述
      • required: 如果本条目没有被满足,那最终本次认证一定失败,但认证过程不因此打断。
        整个栈运行完毕之后才会返回(已经注定了的)“认证失败”信号。
      • requisite: 如果本条目没有被满足,那本次认证一定失败,而且整个栈立即中止并返回错误信号。
      • sufficient: 如果本条目的条件被满足,且本条目之前没有任何required条目失败,则立即返回“认证成功”信号;
        如果对本条目的验证失败,不对结果造成影响。
      • optional: 该条目仅在整个栈中只有这一个条目时才有决定性作用,否则无论该条验证成功与否都和最终结果无关。
      • include: 将其他配置文件中的流程栈包含在当前的位置,就好像将其他配置文件中的内容复制粘贴到这里一样。
      • substack: 运行其他配置文件中的流程,并将整个运行结果作为该行的结果进行输出。
        该模式和 include 的不同点在于认证结果的作用域:如果某个流程栈 include 了一个带 requisite 的栈,
        这个 requisite 失败将直接导致认证失败,同时退出栈;而某个流程栈 substack 了同样的栈时,
        requisite 的失败只会导致这个子栈返回失败信号,母栈并不会在此退出。
    • 控制模式使用[返回值=行为]方式来控制: [value1=action1 value2=action2 ...]
      • 返回值valueN 一般有success、user_unknown、new_authtok_reqd、default..., 具体定义可以查看pam源码的_pam_types.h
      • actionN一般包含ignore bad die ok done reset N(一个自然数)
        • ignore: 在一个栈中有多个认证条目的情况下,如果标记 ignore 的返回值被命中,
          那么这条返回值不会对最终的认证结果产生影响。
        • bad: 标记 bad 的返回值被命中时,最终的认证结果注定会失败。
          此外,如果这条 bad 的返回值是整个栈的第一个失败项,那么整个栈的返回值一定是这个返回值,
          后面的认证无论结果怎样都改变不了现状了。
        • die: 标记 die 的返回值被命中时,马上退出栈并宣告失败。整个返回值为这个 die 的返回值。
        • ok: 在一个栈的运行过程中,如果 ok 前面没有返回值,或者前面的返回值为 PAM_SUCCESS,
          那么这个标记了 ok 的返回值将覆盖前面的返回值。
          但如果前面执行过的验证中有最终将导致失败的返回值,那 ok 标记的值将不会起作用。
        • done: 在前面没有 bad 值被命中的情况下,done 值被命中之后将马上被返回,并退出整个栈。
        • N(自然数): 功效和 ok 类似,并且会跳过接下来的 N 个验证步骤。如果 N = 0 则和 ok 完全相同。
        • 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]

pam-xxx.so扩展开发示例

#include <stdio.h>
#include <stdlib.h>
#include <security/pam_modules.h>
#include <security/pam_appl.h>
#include <security/pam_ext.h>
#include <security/pam_misc.h>
/**
 * 认证相关的函数
 */
int pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc, const char **argv)
{
	const char *ip = NULL;
	int ret = pam_get_item(pamh, PAM_RHOST, (const void **)&ip);
	printf("ret = %d, ip = %s\n", ret, ip?:"nil");
	pam_putenv(pamh, "test=testenv");
	return PAM_SUCCESS;
}

int pam_sm_setcred(pam_handle_t *pamh, int flags, int argc, const char **argv)
{
	printf("%s-%d\n", __func__, __LINE__);
	return PAM_CRED_ERR;
}

int pam_sm_acct_mgmt(pam_handle_t *pamh, int flags, int argc, const char **argv)
{
	printf("%s-%d\n", __func__, __LINE__);
	return PAM_AUTH_ERR;
}

int pam_sm_open_session(pam_handle_t *pamh, int flags, int argc, const char **argv)
{
	printf("%s-%d\n", __func__, __LINE__);
	return PAM_SUCCESS;
}

int pam_sm_close_session(pam_handle_t *pamh, int flags, int argc, const char **argv)
{
	printf("%s-%d\n", __func__, __LINE__);
	return PAM_SUCCESS;
}

int pam_sm_chauthtok(pam_handle_t *pamh, int flags, int argc, const char **argv)
{
	printf("%s-%d\n", __func__, __LINE__);
	return PAM_AUTHTOK_ERR;
}

#ifdef PAM_STATIC
struct pam_module _pam_radius_modstruct = {
  "pam_sfos",
  pam_sm_authenticate,
  pam_sm_setcred,
  pam_sm_acct_mgmt,
  pam_sm_open_session,
  pam_sm_close_session,
  pam_sm_chauthtok,
};
#endif
  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值