2011-11-12 56 views
6

我有一個程序正在偵聽Unix域套接字。識別連接到Unix域套接字的程序

當客戶端連接到套接字時,我想知道哪個程序已連接,然後決定是否允許連接(基於用戶/組設置)。

在Linux下這是可能的,如果是這樣,如何?

回答

8

是的,這在Linux上是可行的,但它不會很便攜。這是通過使用所謂的「輔助數據」與sendmsg/recvmsg實現的。

  • 使用SO_PASSCREDsetsockopt
  • 使用SCM_CREDENTIALSstruct ucred結構

此結構在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 */ 
}; 

注意你有你的msghdr.control填補這些了,內核會檢查它們是否正確。

主要的便攜性的障礙是,這種結構上的差異在其他Unix系統 - 例如在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

非常感謝。正是我在找什麼。可移植性不是問題。無論如何,代碼只能作爲本機代碼在Android上運行。 –

1

也許getpeernamegetsockname可以提供幫助。我認爲你的unix socket的許可是有用的(不確定)。如果你的accept -ed插座中使用輔助數據憑據是12

編輯

sendmsg要好得多,通過cnicutar以下的建議你可能會讀裏面/proc/self/fd/12的鏈接。

6

我搜索了這個頗有幾分,所以我會告訴你如何使用SO_PEERCRED這個例子在插座sock上獲得插座對等的pid/uid/gid:

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);