从源码分析,使用unix域流式套接字接收auditd分发程序audispd的二进制审计消息,篇二,与audispd建立通讯,源码分析通讯报文大小结构

259 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第16天,点击查看活动详情

简介

上一篇中,我们知道可以建立unix sock tcp与audispd建立通讯,但是我们只知道可以收到消息,我们还不知道消息的内容,这期中我们将会开始使用自己编写的代码与audispd建立通讯,并且初步了解audispd发送过来的消息格式

创建unix域套接字接收消息

  • 示例程序中出现过的头文件
    #include <stdio.h>
    #include <stdlib.h>
    #include <sys/socket.h>
    #include <sys/types.h>
    #include <sys/un.h>
    #include <unistd.h>
    #include <libaudit.h>
    

创建unix sock

struct sockaddr_un server_addr;

server_addr.sun_family = AF_UNIX;

//此处的路径是配置中的路径
strcpy(server_addr.sun_path, "/var/run/theMessage_audispd");

int sockfd = socket(AF_UNIX, SOCK_STREAM, 0);
if(sockfd < 0)
        return -1;

//本地通信 连接audisp启动的服务端
int result = connect(sockfd, (struct sockaddr *)&server_addr, sizeof(server_addr));
if(result < 0) 
{
    close(sockfd);
    return -1;
}

while(1)
{
    memset(buff, 0, sizeof(buff)); 
    int len;

    if((len = read(sockfd, buff, sizeof(buff))) > 0)
        printf("%s\n", buff);
}

当我们看到程序顺利执行,可以收到消息,或者阻塞等待收到消息,就算是成功的第一步了,我们接收到了audisptd分发的消息了,但是有一个问题,我们这篇需要使用的二进制来接收消息,直接按字符串打印保不齐会出现啥,接下来,我们从源码角度分析接收到的消息是什么内容

源码分析通讯数据报

  • 这个loop函数,是循环收消息的函数,也就是audispd的主要任务函数

    /home/kira/rpmbuild/BUILD/audit-3.0.1/audisp/audispd.c
    
    static int event_loop(void)
    
  • 这个函数里,就出现了发送二进制的函数

    /* Now send the event to the right child */
    if (conf->p->type == S_AF_UNIX) {
    	if (conf->p->format == F_STRING)
    		send_af_unix_string(v, len);
    	else
    		send_af_unix_binary(e);
    }
    
  • 看一下send_af_unix_binary这个函数的内容

    void send_af_unix_binary(event_t *e)
    {
    	if (sock < 0) 
    		return;
    
    	if (conn >= 0) {
    		int rc;
    		struct iovec vec[2];
    
    		vec[0].iov_base = &e->hdr;
    		vec[0].iov_len = sizeof(struct audit_dispatcher_header);
    		vec[1].iov_base = e->data;
    		vec[1].iov_len = MAX_AUDIT_MESSAGE_LENGTH;
    		do {
    			rc = writev(conn, vec, 2);
    		} while (rc < 0 && errno == EINTR);
    		if (rc < 0 && errno == EPIPE) {
    			close(conn);
    			conn = -1;
    			stop_watching();
    			start_watching();
    		}
    	} 
    }
    
  • 啊哈,是调用writev发送了两段东西,分别是一个结构体,一个data数组,大小是MAX_AUDIT_MESSAGE_LENGTH + sizeof(struct audit_dispatcher_header)

  • 到这里可以看到,其实每次从unix tcp sock接收到的消息,都是固定的大小,那么我们做audispd观察者的时候,就可以设定这个固定大小的数组来接收消息,audispd这样处理有好处有坏处

    • 好处是每条消息的大小一致,不需要考虑消息对齐
    • 坏处是这个大小很大,后续可以看到其实很多消息的长度小得多,不足这个消息最大长度的1/10,造成一定的空间浪费

    完结,撒花

    本期中,我们初探了audispd的源码,看到了真正audispd发送消息的函数位置,只有发送了一个结构体,一个字符数组,下一章节中,我们将会更加深入audispd的源码,探索audispd的消息是怎么组合的,这个结构体的每一个字段的含义。