在sudo下运行时如何从C获取loggin用户 [英] How to get the loggin users from C when running under sudo

查看:212
本文介绍了在sudo下运行时如何从C获取loggin用户的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在编写一个将在sudo下运行的C应用程序.

I'm writing a C application that will be run under sudo.

我需要获取原始登录用户的UID.

I need to get the original logged in users UID.

我正在调用getuid,文档说明该状态将返回真实的UID.

I'm calling getuid which the documentation states will return the real UID.

我假设这将是登录用户的UID,但它返回的是0,这是根UID.

I assumed this would be the logged in user's UID but it instead returns 0 which is the root UID.

是否有一个api调用,可以让我获取登录用户的UID.

Is there an api call which will allow me to get the logged in users UID.

我知道SUDO_UID,但希望避免使用环境变量(或者我只是感到困难).

I'm aware of SUDO_UID but would prefer to avoid environment variables (or am I just being difficult).

推荐答案

这是我的解决方案,不使用依赖于stat()/proc/<pid>中文件的环境变量,因此仅适用于linux. 基本上,它会经过进程树,直到找到(sudo)pid=1,如果找到sudo,它将显示调用它的父进程以及该进程的uid.

Here is my solution without using environment variables relying on stat() and files in /proc/<pid>, so this makes it linux only. Basically it goes trough the process tree until it finds (sudo) or pid=1, if sudo is found it shows the parent process that called it and the uid for that.

hello_sudoer.c:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
struct process_info {
    pid_t pid;  
    // max file name is 255 + 2 for "()" in /proc/<pid>/stat
    char process_name[257]; 
    char status;
    pid_t ppid; // parent process id
    uid_t uid; // uid of this process
};

struct process_info get_process_info(pid_t pid){
    struct process_info pi;
    struct stat* s = malloc(sizeof(struct stat));
    memset(&pi, 0, sizeof(struct process_info));
    if(pid > 0) {
        char proc_path[64];
        FILE* proc_stat;
        memset(&proc_path, 0, sizeof(proc_path));
        sprintf(proc_path , "/proc/%d/stat", pid);
        proc_stat = fopen(proc_path, "r");
        if (proc_stat != NULL) {
            fscanf(proc_stat, "%d %s %c %d", 
                    &pi.pid, 
                    pi.process_name, 
                    &pi.status, 
                    &pi.ppid);

            // stat struct doesn't have the parent process id
            // as is only checking on the file properies of /proc/<pid> directory
            // so we can't get the info needed only with stat(2)
            // and stat file doesn't have uid so we can't only use that
            // we need both
            stat(proc_path, s); 
            pi.uid = s -> st_uid;
            free(s);
            fclose(proc_stat);
        } 

    } 
    return pi;
}

void print_process_info(struct process_info pi){
    printf("pid=%d file_name=%s status=%c uid=%d ppid=%d\n", 
            pi.pid, pi.process_name, pi.status, pi.uid, pi.ppid);
}

int main()
{
    pid_t pid = getpid();

    while (pid > 0) {
        struct process_info pi = get_process_info(pid);
        print_process_info(pi);

        if( strcmp("(sudo)" , pi.process_name) == 0 ) {
            // found sudo 
            struct process_info sudo_parent_info = get_process_info(pi.ppid);
            printf("user that ran sudo is uid=%d, from process: \n", 
                    sudo_parent_info.uid);
            print_process_info(sudo_parent_info);
            break;
        }
        pid = pi.ppid;
    }
    return 0;
}

示例输出:

pid=41769 file_name=(hello_sudoer.o) status=R uid=0 ppid=41749
pid=41749 file_name=(sudo) status=S uid=0 ppid=20078
user that ran sudo is uid=1000, from process: 
pid=20078 file_name=(bash) status=S uid=1000 ppid=5985

这篇关于在sudo下运行时如何从C获取loggin用户的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆