Question

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?

Was it helpful?

Solution

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 */
};

OTHER TIPS

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

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.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top