Linux如何通过PAM管理授权?¶
引言¶
PAM
指的是Pluggable Authentication Modules
,以可插拔模块的形式来帮助Linux管理系统的授权。
PAM
将系统授权相关的逻辑功能做成共享链接库(/usr/lib64/security/
)的形式,然后其他需要授权操作的程序只需要调用这个共享库即可。
对于管理员来说,正确的设置复杂授权等工作就变成了一个简单的管理配置文件的工作了。
/etc/pam.d/配置目录¶
常用的涉及到授权的命令都使用了libpam
共享库,比如:
$ ldd /usr/bin/su
libpam.so.0 => /lib64/libpam.so.0 (0x00007fb74b974000)
libpam_misc.so.0 => /lib64/libpam_misc.so.0 (0x00007fb74b770000)
......
系统对常见的一些需要授权操作服务场景(比如su
)默认定义好了规则:
/etc/pam.d/chfn
/etc/pam.d/chsh
/etc/pam.d/config-util
/etc/pam.d/fingerprint-auth
/etc/pam.d/login
/etc/pam.d/other
/etc/pam.d/passwd
/etc/pam.d/password-auth
/etc/pam.d/polkit-1
/etc/pam.d/postlogin
/etc/pam.d/remote
/etc/pam.d/runuser
/etc/pam.d/runuser-l
/etc/pam.d/smartcard-auth
/etc/pam.d/su
/etc/pam.d/su-l
/etc/pam.d/system-auth
/etc/pam.d/systemd-user
比如su
命令对应的授权规则是:
$ cat /etc/pam.d/su
#%PAM-1.0
auth sufficient pam_rootok.so
# Uncomment the following line to implicitly trust users in the "wheel" group.
#auth sufficient pam_wheel.so trust use_uid
# Uncomment the following line to require a user to be in the "wheel" group.
#auth required pam_wheel.so use_uid
auth substack system-auth
auth include postlogin
account sufficient pam_succeed_if.so uid = 0 use_uid quiet
account include system-auth
password include system-auth
session include system-auth
session include postlogin
session optional pam_xauth.so
基本含义是根据规则,首先需要通过pam_rootok.so
模块检验是否能够获得root身份,之后再叠加更加严格的规则。比如如果要求只有wheel
用户组的用户可以使用sudo
命令,则可以要求必须通过pam_wheel.so
模块检验。
如果是以上服务场景之外的, 其他程序想要获取到授权,则统统归到/etc/pam.d/other
规则文件里面,其内容:
$ cat /etc/pam.d/other
#%PAM-1.0
auth required pam_deny.so
account required pam_deny.so
password required pam_deny.so
session required pam_deny.so
即系统默认自带的授权场景之外的其他授权行为一律拒绝。
授权规则语法¶
一般Unix
系统里面是使用文件/etc/pam.conf
来配置规则,其语法是:
但在Linux
里面常见的做法是将每个service name
以文件的形式单独存放到目录/etc/pam.d/
中,并且要求文件名必须是小写:
其中module-type
参数是auth
,account
,session
,password
.
其中control-flag
的含义如下:
Flag标志 | 失败后是否停止 | 成功后是否停止 | 备注 |
---|---|---|---|
binding | No | Yes | |
include | - | - | 包含其他服务规则进来 |
optional | No | No | 认证失败也忽略,除非是唯一的规则 |
required | No | No | 任何规则失败导致整体授权失败,但会全部执行完再返回错误 |
requisite | Yes | No | 一旦规则失败立即返回错误,不执行后面其他规则验证 |
sufficient | No | Yes | 只要通过当前模块认证就立马返回成功信息,即使前面有错误认证 |
自定义授权服务与规则¶
除非特殊情况,一般不应该去修改系统自带的授权服务规则文件,但可以自定义新的授权服务规则。
比如这里创建一个叫check
的服务配置文件/etc/pam.d/check
:
auth required pam_unix_auth.so
account required pam_unix_acct.so
session required pam_limits.so conf=/etc/security/limits.conf
现有一个程序调用这个授权服务:
// https://github.com/linux-pam/linux-pam/blob/master/examples/check_user.c
#include <security/pam_appl.h>
#include <security/pam_misc.h>
#include <stdio.h>
static struct pam_conv conv = {
misc_conv,
NULL
};
int main(int argc, char *argv[])
{
pam_handle_t *pamh=NULL;
int retval;
const char *user="nobody";
if(argc == 2) {
user = argv[1];
}
if(argc > 2) {
fprintf(stderr, "Usage: check_user [username]\n");
exit(1);
}
// 调用check授权服务
retval = pam_start("check", user, &conv, &pamh);
if (retval == PAM_SUCCESS)
retval = pam_authenticate(pamh, 0); /* is user really user? */
if (retval == PAM_SUCCESS)
retval = pam_acct_mgmt(pamh, 0); /* permitted access? */
/* This is where we have been authorized or not. */
if (retval == PAM_SUCCESS) {
fprintf(stdout, "Authenticated\n");
} else {
fprintf(stdout, "Not Authenticated\n");
}
if (pam_end(pamh,retval) != PAM_SUCCESS) { /* close Linux-PAM */
pamh = NULL;
fprintf(stderr, "check_user: failed to release authenticator\n");
exit(1);
}
return ( retval == PAM_SUCCESS ? 0:1 ); /* indicate success */
}
这样新开发的程序就可以使用自定义的授权服务规则了:
$ yum install pam-devel
$ gcc main.cpp -lpam -lpam_misc -o check_user
$ ./check_user
Password:
Not Authenticated
$ ./check_user test
Password:
Authenticated
$ ./check_user test
Password:
Not Authenticated
pam_limits管理会话资源分配¶
日常接触较多的是会话资源管理,比如:
$ ulimit -a
core file size (blocks, -c) 0
data seg size (kbytes, -d) unlimited
scheduling priority (-e) 0
file size (blocks, -f) unlimited
pending signals (-i) 7475
max locked memory (kbytes, -l) 64
max memory size (kbytes, -m) unlimited
open files (-n) 1048576
pipe size (512 bytes, -p) 8
POSIX message queues (bytes, -q) 819200
real-time priority (-r) 0
stack size (kbytes, -s) 8192
cpu time (seconds, -t) unlimited
max user processes (-u) unlimited
virtual memory (kbytes, -v) unlimited
file locks (-x) unlimited
这是系统当前会话的资源限制情况,它其实检查这些资源限制是通过pam_limits
模块进行的,这个模块默认是读取配置文件/etc/security/limits.conf
,还会读取/etc/security/limits.d/
目录下的配置文件。
如果是临时修改会话资源限制,则使用ulimit
命令:
如果是长期生效则修改配置文件/etc/security/limits.conf
:
#<domain> <type> <item> <value>
testUser hard maxlogins 1 # 该用户只可以有1个登录会话
@testGrp hard maxlogins 1 # 该用户组用户只可以有1个登录会话
* hard maxsyslogins 10 # 系统最多10个会话同时在线
testUser hard stack 10240 # 堆栈空间
testUser soft core 2 # 最多使用2个核CPU资源
testUser hard nofile 1024 # 最多打开1024个文件
总结¶
PAM
是方便Linux管理授权和资源分配的机制,而其中pamd_limits
是常用的管理会话资源的模块。
- 微信搜索: 「 MinYiLife 」, 关注公众号!
- 本文链接: https://www.lesliezhu.com/blog/2022/11/21/PAM_in_linux/
- 版权声明: 原创文章,如需转载请注明文章作者和出处。谢谢!