#linux #unix-socket
#linux #unix-сокет
Вопрос:
У меня есть программа, которая прослушивает доменный сокет Unix.
Когда клиент подключается к сокету, я хотел бы выяснить, какая программа подключилась, а затем решить, разрешаю ли я подключение или нет (на основе настроек пользователя / группы).
Возможно ли это в Linux, и если да, то каким образом?
Ответ №1:
Да, это возможно в Linux, но это будет не очень переносимо. Это достигается с использованием так называемых «вспомогательных данных» с помощью sendmsg
/ recvmsg
.
- Используйте
SO_PASSCRED
сsetsockopt
- Использование
SCM_CREDENTIALS
иstruct 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 */
};
Комментарии:
1. Большое вам спасибо. Именно то, что я искал. Переносимость не является проблемой. Код в любом случае будет выполняться только на Android как собственный код.
2. Привет, я новичок в сокете. Мне интересно, как я могу узнать PID процесса отправки. Спасибо.
Ответ №2:
Я довольно долго искал это, поэтому я покажу вам этот пример о том, как использовать SO_PEERCRED
на сокете sock
, чтобы получить pid / uid / gid узла сокета:
int len;
struct ucred ucred;
len = sizeof(struct ucred);
if (getsockopt(sock, SOL_SOCKET, SO_PEERCRED, amp;ucred, amp;len) == -1) {
//getsockopt failed
}
printf("Credentials from SO_PEERCRED: pid=%ld, euid=%ld, egid=%ldn",
(long) ucred.pid, (long) ucred.uid, (long) ucred.gid);
Комментарии:
1. Я также довольно много искал, и мне очень повезло, что я нашел этот ответ! Большинство других источников настаивают на том, что вам нужно использовать
sendmsg
иrecvmsg
, когда это просто неверно. Я добавлю, чтоsock
параметром в приведенном примере будет файловый дескриптор клиентского процесса, который вы хотите идентифицировать, и я обнаружил, что мне нужно обработать хотя бы одинread()
из данных клиента, иначе я получу неопределенные значения вucred
структуре.2. начиная с версии 2.8.0 (2009), требуется
_GNU_SOURCE
определение glibc. Специальный источник: github.com/apple/cups/issues/2860
Ответ №3:
Возможно, getpeername или getsockname могли бы помочь. и я думаю, что разрешение вашего сокета unix полезно (не уверен в этом). И вы могли бы прочитать ссылку внутри, /proc/self/fd/12
если ваш accept
установленный сокет равен 12.
Редактировать
намного лучше использовать вспомогательные данные для учетных данных и sendmsg
, как предлагает cnicutar ниже.