2011-11-12 16 views

risposta

8

Sì, questo è possibile su Linux, ma non sarà molto portabile. È realizzato utilizzando i cosiddetti "dati ausiliari" con sendmsg/recvmsg.

  • Usa SO_PASSCRED con setsockopt
  • Usa SCM_CREDENTIALS e la struttura struct ucred

Tale struttura è definita in Linux:

struct ucred { 
    pid_t pid; /* process ID of the sending process */ 
    uid_t uid; /* user ID of the sending process */ 
    gid_t gid; /* group ID of the sending process */ 
}; 

Nota che devi compilare questi nella vostra msghdr.control, e il kernel controllerà se sono corretti.

La portabilità principale ostacolo è che questa struttura si differenzia da altri sistemi Unix - per esempio su FreeBSD è:

struct cmsgcred { 
    pid_t cmcred_pid;   /* PID of sending process */ 
    uid_t cmcred_uid;   /* real UID of sending process */ 
    uid_t cmcred_euid;   /* effective UID of sending process */ 
    gid_t cmcred_gid;   /* real GID of sending process */ 
    short cmcred_ngroups;  /* number or groups */ 
    gid_t cmcred_groups[CMGROUP_MAX];  /* groups */ 
}; 
+0

Grazie mille. Esattamente quello che stavo cercando. La portabilità non è un problema. Il codice verrà eseguito solo su Android come codice nativo comunque. –

1

Forse getpeername o getsockname potrebbe aiutare. e penso che il permesso del tuo unix socket sia utile (non ne sono sicuro). E si potrebbe leggere il link all'interno /proc/self/fd/12 se il accept presa -ed è 12.

EDIT

utilizzando i dati ausiliari per le credenziali e sendmsg è molto meglio, come suggerito da cnicutar di seguito.

6

ho cercato per questo un po ', quindi vi mostrerà questo esempio su come utilizzare SO_PEERCRED su un socket sock per ottenere il pid/uid/gid del peer di una presa di corrente:

int len; 
struct ucred ucred; 

len = sizeof(struct ucred); 

if (getsockopt(sock, SOL_SOCKET, SO_PEERCRED, &ucred, &len) == -1) { 
    //getsockopt failed 
} 

printf("Credentials from SO_PEERCRED: pid=%ld, euid=%ld, egid=%ld\n", 
    (long) ucred.pid, (long) ucred.uid, (long) ucred.gid);