Unix Network Programming Episode 100

Receiving Sender Credentials

In Figure 14.13(See 9.3.6), we showed another type of data that can be passed along a Unix domain socket as ancillary data: user credentials. Exactly how credentials are packaged up and sent as ancillary data tends to be OS-specific. We describe FreeBSD here, and other Unix variants are similar (usually the challenge is determining which structure to use for the credentials). We describe this feature, even though it is not uniform across systems, because it is an important, yet simple, addition to the Unix domain protocols. When a client and server communicate using these protocols, the server often needs a way to know exactly who the client is, to validate that the client has permission to ask for the service being requested.

FreeBSD passes credentials in a cmsgcred structure, which is defined by including the <sys/socket.h> header.

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 of groups */
	gid_t cmcred_groups[CMGROUP_MAX]; /* groups */
};

Normally, CMGROUP_MAX is 16. cmcred_ngroups is always at least 1, with the first element of the array the effective group ID.
This information is always available on a Unix domain socket, although there are often special arrangments the sender must make to have the information included when sending, and there are often special arrangements (e.g., socket options) the receiver must make to get the credentials. On our FreeBSD system, the receiver doesn’t have to do anything special other than call recvmsg with an ancillary buffer large enough to hold the credentials, as we show in Figure 15.14. The sender, however, must include a cmsgcred structure when sending data using sendmsg.

#include "unp.h"

#define CONTROL_LEN (sizeof(struct cmsghdr)+sizeof(struct cmsgcred))

ssize_t read_cred(int fd, void *ptr, size_t nbytes, struct cmsgcred *cmsgcredptr)
{
    struct msghdr msg;
    struct iovec iov[1];
    char control[CONTROL_LEN];
    int n;

    msg.msg_name=NULL;
    msg.msg_namelen=0;
    iov[0].iov_base=ptr;
    iov[0].iov_len=nbytes;
    msg.msg_iov=iov;
    msg.msg_iovlen=1;
    msg.msg_controllen=sizeof(control);
    msg.msg_flags=0;

    if((n=recvmsg(fd, &msg, 0))<0)
        return n;

    cmsgcredptr->cmcred_ngroups=0;

    if(cmsgcredptr && msg.msg_controllen>0)
    {
        struct cmsghdr *cmptr=(struct cmsghdr *) control;

        if(cmptr->cmsg_len<CONTROL_LEN)
        {
            err_quit("control length=%d", cmptr->cmgs_len);
        }
        if(cmptr->cmsg_level!=SOL_SCOKET)
        {
            err_quit("control level!= SOL_SOCKET");
        }
        if(cmptr->cmsg_type!=SCM_CREDS)
        {
            err_quit("control type != SCM_CREDS");
        }
        memcpy(cmscredptr, CMSG_DATA(cmptr), sizeof(struct cmsgcred));
    }

    return n;
}

read_cred function: reads and returns sender’s credentials

  • 9
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值