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?

Était-ce utile?

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

Autres conseils

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.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top