linux 调用 setgid()、initgroups()、setuid() 修改执行权限

原创
2016/05/18 23:09
阅读数 639

有时,我们需要在程序执行过程中修改程序运行权限。

一、源码

修改程序权限主要分三步。

1. 调用 setgid() 修改组ID。

2. 调用 initgroups() 修改附加组ID(一个用户可以属于多个组)。

3. 调用 setuid() 修改用户ID。

#include <stdio.h>
#include <unistd.h>
#include <shadow.h>
#include <pwd.h>
#include <grp.h>

void get_groups()
{
    const int gidsetsize = 1024;
    int grouplist[gidsetsize];

    // 获取附加组ID
    int n = getgroups(gidsetsize, grouplist);
    fprintf(stderr, "grouplist:");
    for (int i = 0; i < n; i++) {
        fprintf(stderr, "%d ", grouplist[i]);
    }
    fprintf(stderr, "\n");
}

void get_ids()
{
    fprintf(stderr, "uid = %d, euid = %d, gid = %d, egid = %d\n",
            getuid(), geteuid(), getgid(), getegid());
}

int main(int argc, char **argv)
{
    char username[] = "likui";
    char groupname[] = "likui";

    // 根据用户名获取用户ID
    struct passwd *pwd = getpwnam(username);
    if (pwd == NULL) {
        fprintf(stderr, "getopwnam error\n");
    }
    fprintf(stderr, "uid = %d\n", pwd->pw_uid);

    // 根据组名获取组ID
    struct group *grp;
    grp = getgrnam(groupname);
    if (grp == NULL) {
        fprintf(stderr, "getgrnam error\n");
    }
    fprintf(stderr, "gid = %d\n", grp->gr_gid);
    
    fprintf(stderr, "*** before ***\n");
    get_ids();
    get_groups();

    // 检查有效用户ID是否为 root,只有 root 能切换
    if (geteuid() == 0) {
        // 更改组ID
        if (setgid(grp->gr_gid) == -1) {
            perror("setgid");
        }

        // 更改附加组ID
        if (initgroups("likui", grp->gr_gid) == -1) {
            perror("initgroups");
        }

        // 更改用户ID
        if (setuid(pwd->pw_uid) == -1) {
            perror("setuid");
        }

        fprintf(stderr, "*** after ***\n");
        get_ids();
        get_groups();
    }

    return 0;
}

二、运行

普通权限运行

$ ./main 
uid = 1000
gid = 1000
*** before ***
uid = 1000, euid = 1000, gid = 1000, egid = 1000
grouplist:4 24 27 30 44 46 113 128 129 1000 1001 

root 权限执行

$ sudo ./main 
uid = 1000
gid = 1000
*** before ***
uid = 0, euid = 0, gid = 0, egid = 0
grouplist:0 
*** after ***
uid = 1000, euid = 1000, gid = 1000, egid = 1000
grouplist:4 24 27 30 44 46 113 128 129 1000 1001 

三、关于 initgroups

尝试注释

        // 更改附加组ID
        //if (initgroups("likui", grp->gr_gid) == -1) {
        //    perror("initgroups");
        //}

root 权限运行

$ sudo ./main 
uid = 1000
gid = 1000
*** before ***
uid = 0, euid = 0, gid = 0, egid = 0
grouplist:0 
*** after ***
uid = 1000, euid = 1000, gid = 1000, egid = 1000
grouplist:0 

grouplist 附加组ID未发生变化。

展开阅读全文
打赏
2
4 收藏
分享
加载中
更多评论
打赏
0 评论
4 收藏
2
分享
返回顶部
顶部