linux ACL权限控制之用户权限控制程序设计
linux中的ACL(Access Control List,访问控制列表)是一种比传统UNIX权限更细粒度的权限控制机制,允许为文件和目录设置更为具体的用户和组权限。本文介绍使用acl命令和程序api对文件进行更精细的用户权限控制。
1. 命令行示例
使用adduser命令添加两个普通用户vox和zoe
adduser -home /home/vox vox
adduser -home /home/zoe zoe
使用id命令分别查看vox和zoe的user id及group id:
使用su vox切换到vox用户并在用户主目录下创建一个名为testfile的文件,文件的内容为hello world!
查看testfile的权限:
可以看到文件的所有者为vox,组为vox,均对该文件拥有读写权限,其他用户只有读权限。使用chmod去除其他用户的读权限:
查看下vim的权限:
当前的登陆用户为vox,其他用户对vim拥有可读可写可执行权限,所以vox对vim拥有可读可写可执行权限,所以vox可以启动执行vim:
vim testfile
使用ps -au | grep vim可以看到运行vim的用户为vox:
因为vox拥有该文件的读写权限,所以如果登陆的用户为vox,vox可以使用vim查看testfile中的内容。
现在使用su zoe切换用户:
看看此时能不能使用vim打开testfile查看文件内容:
vim testfile
得到以下结果:
同样使用ps -au | grep vim可以看到运行vim的用户为zoe:
因为zoe拥有vim的执行权限,可以启动执行vim,其它用户对testfile无任何权限,zoe虽然可以启动vim,且vim的进程所有者为zoe,但该进程却无法读取testfile中的内容。
使用getfacl命令查看testfile的权限控制列表:
使用setfacl命令增加zoe对testfile的读权限:
(base) /home/vox$ sudo setfacl -m u:zoe:r testfile
再次使用getfacl命令查看testfile的权限控制列表:
zoe既不是文件所有者,也不属于组vox,other对该文件无任何权限,zoe虽然属于other,但却对该文件拥有读权限。
此时,用以下命令可以正常读取testfile的内容:
2. 代码示例
除了使用命令行,也可以使用linux的acl库在程序中使用相关c语言接口进行编程控制(根据以上id命令的输出结果,1002是用户zoe的user id),代码如下:
#include <stdio.h>
#include <stdlib.h>
#include <sys/acl.h>
int main() {
const char *filename = "/home/vox/testfile";
uid_t user_id = 1002;
// 获取文件的ACL
acl_t acl = acl_get_file(filename, ACL_TYPE_ACCESS);
if (acl == NULL) {
perror("Failed to get ACL");
return EXIT_FAILURE;
}
// 创建新ACL条目
acl_entry_t entry;
if (acl_create_entry(&acl, &entry) == -1) {
perror("Failed to create ACL entry");
acl_free(acl);
return EXIT_FAILURE;
}
// 设置条目类型为用户
if (acl_set_tag_type(entry, ACL_USER) == -1) {
perror("Failed to set tag type");
acl_free(acl);
return EXIT_FAILURE;
}
// 设置用户ID为限定符
if (acl_set_qualifier(entry, &user_id) == -1) {
perror("Failed to set qualifier");
acl_free(acl);
return EXIT_FAILURE;
}
// 设置权限(读)
acl_permset_t permset;
if (acl_get_permset(entry, &permset) == -1) {
perror("acl_get_permset failed");
acl_free(acl);
return EXIT_FAILURE;
}
acl_clear_perms(permset); // 清空权限
acl_add_perm(permset, ACL_READ); // 添加读权限
if (acl_set_permset(entry, permset) == -1) {
perror("acl_set_permset failed");
acl_free(acl);
return EXIT_FAILURE;
}
// 自动计算MASK条目(关键修复)
if (acl_calc_mask(&acl) == -1) {
perror("Failed to calculate mask");
acl_free(acl);
return EXIT_FAILURE;
}
// 验证ACL
if (acl_valid(acl) == -1) {
perror("Invalid ACL");
acl_free(acl);
return EXIT_FAILURE;
}
// 应用ACL到文件
if (acl_set_file(filename, ACL_TYPE_ACCESS, acl) == -1) {
perror("Failed to apply ACL");
acl_free(acl);
return EXIT_FAILURE;
}
// 释放资源
acl_free(acl);
return 0;
}
以上程序使用的各接口根据命名比较容易理解其功能,不再赘述。
将以上的testfile删除,重新创建一个testfile文件:
编译以上程序并执行:
使用getfacl testfile重新查看acl权限:
zoe也获得了testfile的读权限,和使用命令行操作的结果一致。
使用ls -l也可以查看testfile是否设置了acl权限:
在权限列多了一个+号。