I have a program that is listening to a Unix Domain Socket.
When a client connects to the socket I\'d like to find out which program connected and then decide if I allow
Yes, this is possible on Linux, but it won't be very portable. It's achieved using what is called "ancillary data" with sendmsg
/ recvmsg
.
SO_PASSCRED
with setsockopt
SCM_CREDENTIALS
and the struct ucred
structureThis structure is defined 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 */
};
Note you have to fill these in your msghdr.control
, and the kernel will check if they're correct.
The main portability hindrance is that this structure differs on other Unixes - for example on FreeBSD it's:
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 */
};
Perhaps getpeername or getsockname could help. and I think that the permission of your unix socket are useful (not sure of that). And you might read the link inside /proc/self/fd/12
if your accept
-ed socket is 12.
EDIT
using ancillary data for credentials and sendmsg
is much better, as suggested by cnicutar below.
I searched for this quite a bit, so I will show you this example on how to use SO_PEERCRED
on a socket sock
to get the pid/uid/gid of the peer of a socket:
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);