在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);
}
关于UNIXDOMAIN协议的接收发送者验证
最新推荐文章于 2021-03-21 14:46:33 发布
本文介绍了在Linux和FreeBSD上如何进行UNIXDOMAIN协议的接收和发送者验证。在Linux上,接收方需要设置SO_PASSCRED选项,并使用recvmsg接收,而发送方则需要使用sendmsg发送SCM_CREDS。在FreeBSD上,接收方无需设置选项,直接用recvmsg接收,发送方只需发送SCM_CREDS类型的消息。示例代码展示了服务器和客户端的实现过程。
摘要由CSDN通过智能技术生成