关于UNIXDOMAIN协议的接收发送者验证

本文介绍了在Linux和FreeBSD上如何进行UNIXDOMAIN协议的接收和发送者验证。在Linux上,接收方需要设置SO_PASSCRED选项,并使用recvmsg接收,而发送方则需要使用sendmsg发送SCM_CREDS。在FreeBSD上,接收方无需设置选项,直接用recvmsg接收,发送方只需发送SCM_CREDS类型的消息。示例代码展示了服务器和客户端的实现过程。
摘要由CSDN通过智能技术生成

在Linux上,
1) receiver 要 setsockopt SO_PASSCRED
2) sender 要显式的调用 sendmsg [cmsg_type SCM_CRENDENTIALS, cmsg_data 为 ucred 并由 sender 填充 (kernel会作检验,如果pid/uid/gid不正确, 则会报错 "Operation not permitted" )]
3) receiver 用 recvmsg 接收。

在 FreeBSD 上,
1) receiver 无需设定 socket选项,直接用 recvmsg 接收。
2) sender 用 sendmsg 发送一个 cmsg_type 为 SCM_CREDS 的 msg (相关结构为 struct cmsgcred, 这个无需 sender 显式填充, kernel会填入cmsgcred的相关成员值)

/* Based on the UNP's code, tested on kernel 2.4.20-8 */



/* server.c  --  credentials receiver */



#include <sys/types.h>

#include <sys/socket.h>

#include <sys/un.h>

#include <sys/uio.h>

#include <unistd.h>

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

#include <errno.h>

#include <linux/socket.h>



#define PATH "./myserv.unix"



typedef struct sockaddr SA;



static ssize_t read_cred(int, void *, size_t, struct ucred *);



int main(void)

{

        struct sockaddr_un      serv, cli;

        int                     listenfd, connfd;

        socklen_t               clilen;

        struct ucred            cred;

        char                    buf[10];

        const int               on = 1;



        if ((listenfd = socket(AF_LOCAL, SOCK_STREAM, 0)) < 0) {

                perror("socket error");

                exit(1);

        }



        memset(&serv, 0, sizeof(serv));

        serv.sun_family = AF_LOCAL;

        unlink(PATH);

        strncpy(serv.sun_path, PATH, sizeof(serv.sun_path) - 1);



        if (bind(listenfd, (SA *) &serv, sizeof(serv)) < 0) {

                perror("bind error");

                exit(1);

        }



        if (listen(listenfd, 1024) < 0) {

                perror("listen error");

                exit(1);

        }



        for ( ; ; ) {

                clilen = sizeof(cli);

                if ((connfd = accept(listenfd, (SA *) &cli, &clilen)) < 0)
{

                        if (errno == EINTR)

                                continue;

                        else {

                                perror("accept error");

                                exit(1);

                        }

                }



                if (setsockopt(connfd, SOL_SOCKET, SO_PASSCRED, &on,

                        sizeof(on)) < 0) {

                        perror("setsockopt error");

                        exit(1);

                }



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值