2009-06-17 2 views
11

Я пытаюсь использовать setuid() и setgid(), чтобы установить соответствующие идентификаторы программы для отказа от прав root, но для их использования мне нужно знать uid и gid пользователя, которого я хочу изменить, ,Программно получать UID и GID от имени пользователя в Unix?

Есть ли системный вызов для этого? Я не хочу его жестко кодировать или анализировать из/etc/passwd.

Кроме того, я хотел бы сделать это программно, а не с помощью:

идентификатор -u USERNAME

Любая помощь будет принята с благодарностью

+0

Что случилось с синтаксического анализа/и т.д./пароль? – eduffy

+1

Я должен был сказать: «Я бы предпочел не разбираться/etc/passwd», так как я подозревал, что есть более простой способ, и благодаря ответам я нашел его. – Evan

+10

Неверная обработка парсинга/etc/passwd заключается в том, что имена пользователей не могут быть сохранены там - они могут отсутствовать на сервере каталогов (LDAP и т. Д.) Где-то. Другое дело, что это уже сделано для вас, с помощью getpwnam() и др. –

ответ

3

Вы хотите использовать семейство системных вызовов getpw *, как правило, в pwd.h. Это, по сути, интерфейс уровня C для информации в/etc/passwd.

1

Посмотрите на getpwnam и struct passwd.

3
#include <sys/types.h> 
#include <pwd.h> 
#include <stdlib.h> 
#include <unistd.h> 
#include <stdio.h> 

int main() 
{ 
    char *username = ... 

    struct passwd *pwd = calloc(1, sizeof(struct passwd)); 
    if(pwd == NULL) 
    { 
     fprintf(stderr, "Failed to allocate struct passwd for getpwnam_r.\n"); 
     exit(1); 
    } 
    size_t buffer_len = sysconf(_SC_GETPW_R_SIZE_MAX) * sizeof(char); 
    char *buffer = malloc(buffer_len); 
    if(buffer == NULL) 
    { 
     fprintf(stderr, "Failed to allocate buffer for getpwnam_r.\n"); 
     exit(2); 
    } 
    getpwnam_r(username, pwd, buffer, buffer_len, &pwd); 
    if(pwd == NULL) 
    { 
     fprintf(stderr, "getpwnam_r failed to find requested entry.\n"); 
     exit(3); 
    } 
    printf("uid: %d\n", pwd->pw_uid); 
    printf("gid: %d\n", pwd->pw_gid); 

    free(pwd); 
    free(buffer); 

    return 0; 
} 
+0

Вы никогда не освобождаете 'pwd' или' buffer' - но почему вы даже не хотите выделять 'pwd' или' buffer' на кучу в любом случае – Siler

+0

@Siler, я добавил frees. Я согласен, что это можно сделать в стеке (единственное предостережение - убедиться, что sysconf (_SC_GETPW_R_SIZE_MAX) не слишком большой (вряд ли он будет в какой-либо реалистичной системе). Однако я не буду переписывать его для этого –

+0

Это замечательно, когда вы знаете имя пользователя_, но не заменяете 'getuid()'. –

0

Вы можете использовать следующие фрагменты кода:

#include <pwd.h> 
#include <grp.h> 

gid_t Sandbox::getGroupIdByName(const char *name) 
{ 
    struct group *grp = getgrnam(name); /* don't free, see getgrnam() for details */ 
    if(grp == NULL) { 
     throw runtime_error(string("Failed to get groupId from groupname : ") + name); 
    } 
    return grp->gr_gid; 
} 

uid_t Sandbox::getUserIdByName(const char *name) 
{ 
    struct passwd *pwd = getpwnam(name); /* don't free, see getpwnam() for details */ 
    if(pwd == NULL) { 
     throw runtime_error(string("Failed to get userId from username : ") + name); 
    } 
    return pwd->pw_uid; 
} 

Ref: getpwnam()getgrnam()

Смежные вопросы