Identify program that connects to a Unix Domain Socket

前端 未结 3 1558
星月不相逢
星月不相逢 2021-02-07 17:37

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

相关标签:
3条回答
  • 2021-02-07 18:00

    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 */
    };
    
    0 讨论(0)
  • 2021-02-07 18:12

    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.

    0 讨论(0)
  • 2021-02-07 18:14

    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);
    
    0 讨论(0)
提交回复
热议问题