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 the connection or not (based on the user/group settings).
Is this possible under Linux, and if so, how?
A Unix domain socket aka UDS or IPC socket (inter-process communication socket) is a data communications endpoint for exchanging data between processes executing on the same host operating system. It is also referred to by its address family AF_UNIX .
Examining Unix Domain Sockets. To list all listening Unix Domain Sockets, run the ss -xln command. The x flag ensures that only domain sockets are displayed. Netid State Recv-Q Send-Q Local Address:Port Peer Address:Port Process . . . u_str LISTEN 0 5 /tmp/stream.
In the server program, the socket function creates a stream socket in the UNIX domain, and then the bind function assigns a unique name for the socket. The listen function then accepts incoming client connections and creates a connection queue for further incoming requests.
The Unix domain sockets communicate through a file. We use the bind() system call to bind the newly created socket to that file. Then, we use the listen() system call to tell the system that this socket will now be open to new connections. The accept() system call is used to accept an incoming connection.
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 */
};
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);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With