Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Identify program that connects to a Unix Domain Socket

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?

like image 231
Nils Pipenbrinck Avatar asked Nov 12 '11 14:11

Nils Pipenbrinck


People also ask

What are Unix domain socket connections?

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 .

How do I find my domain socket 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.

What is Unix Socket programming?

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.

How are UNIX domain sockets implemented?

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.


2 Answers

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.

  • Use SO_PASSCRED with setsockopt
  • Use SCM_CREDENTIALS and the struct ucred structure

This 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 */
};
like image 150
cnicutar Avatar answered Nov 09 '22 05:11

cnicutar


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);
like image 33
Zulakis Avatar answered Nov 09 '22 05:11

Zulakis