2009-06-17 12 views
11

Sto provando a usare setuid() e setgid() per impostare i rispettivi id di un programma per eliminare i privilegi da root, ma per usarli ho bisogno di conoscere l'uid e il gid dell'utente che voglio modificare .Ottiene automaticamente UID e GID dal nome utente in Unix?

C'è una chiamata di sistema per fare questo? Non voglio hardcode o analizzare da/etc/passwd.

Inoltre mi piacerebbe fare questo a livello di codice piuttosto che usare:

id -u USERNAME

Qualsiasi aiuto sarebbe molto apprezzato

+0

Cosa c'è di sbagliato con l'analisi/etc/passwd? – eduffy

+1

Avrei dovuto dire, "Preferirei non analizzare/etc/passwd", poiché sospettavo che esistesse un modo più semplice e, grazie alle risposte, l'ho trovato. – Evan

+10

Una cosa errata con l'analisi di/etc/passwd è che i nomi utente potrebbero non essere memorizzati lì - potrebbero trovarsi da qualche parte su un server di directory (LDAP, ecc.). Un'altra cosa sbagliata è che è già fatto per te, da getpwnam() et al. –

risposta

3

Si desidera utilizzare la famiglia di chiamate di sistema getpw *, in genere in pwd.h. È essenzialmente un'interfaccia di livello C per le informazioni in/etc/passwd.

1

Guarda getpwnam e 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

Non hai mai liberato 'pwd' o' buffer' - ma perché ti preoccupi di allocare 'pwd' o' buffer' sull'heap comunque – Siler

+0

@Siler, ho aggiunto i liberi. Sono d'accordo che può essere fatto in pila (l'unica avvertenza è di assicurarsi che sysconf (_SC_GETPW_R_SIZE_MAX) non sia troppo grande (è improbabile che si trovi su un sistema realistico) Tuttavia, non lo riscriverò per quello –

+0

Questo è ottimo _quando si conosce il nome_utente, ma non è un sostituto di 'getuid()'. –

0

È possibile utilizzare i seguenti frammenti di codice:

#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; 
} 

Rif: getpwnam()getgrnam()