aboutsummaryrefslogtreecommitdiffstats
path: root/framework/src/audit/contrib/skeleton.c
blob: 7e041042c65d57a94ed55b5300268392fca71b05 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
/* skeleton.c --
 * 
 * This is a sample program that you can customize to create your own audit
 * event handler. It will be started by auditd via the dispatcher option in
 * /etc/audit/auditd.conf. This program can be built as follows:
 *
 * gcc skeleton.c -o skeleton -laudit
 */

#include <stdio.h>
#include <sys/types.h>
#include <sys/uio.h>
#include <unistd.h>
#include <stdlib.h>
#include <signal.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>
#include <locale.h>
#include "libaudit.h"


// Local data
static volatile int signaled = 0;
static int pipe_fd;
static const char *pgm = "skeleton";

// Local functions
static int event_loop(void);

// SIGTERM handler
static void term_handler( int sig )
{
	signaled = 1;
}


/*
 * main is started by auditd. See dispatcher in auditd.conf
 */
int main(int argc, char *argv[])
{
	struct sigaction sa;

	setlocale (LC_ALL, "");
	openlog(pgm, LOG_PID, LOG_DAEMON);
	syslog(LOG_NOTICE, "starting...");

#ifndef DEBUG
	// Make sure we are root
	if (getuid() != 0) {
		syslog(LOG_ERR, "You must be root to run this program.");
		return 4;
	}
#endif

	// register sighandlers
	sa.sa_flags = 0 ;
	sa.sa_handler = term_handler;
	sigemptyset( &sa.sa_mask ) ;
	sigaction( SIGTERM, &sa, NULL );
	sa.sa_handler = term_handler;
	sigemptyset( &sa.sa_mask ) ;
	sigaction( SIGCHLD, &sa, NULL );
	sa.sa_handler = SIG_IGN;
	sigaction( SIGHUP, &sa, NULL );
	(void)chdir("/");

	// change over to pipe_fd
	pipe_fd = dup(0);
	close(0);
	open("/dev/null", O_RDONLY);
	fcntl(pipe_fd, F_SETFD, FD_CLOEXEC);

	// Start the program
	return event_loop();
}

static int event_loop(void)
{
	void *data;
	struct iovec vec[2];
	struct audit_dispatcher_header hdr;

	// allocate data structures
	data = malloc(MAX_AUDIT_MESSAGE_LENGTH);
	if (data == NULL) {
		syslog(LOG_ERR, "Cannot allocate buffer");
		return 1;
	}
	memset(data, 0, MAX_AUDIT_MESSAGE_LENGTH);
	memset(&hdr, 0, sizeof(hdr));

	do {
		int rc;
		struct timeval tv;
		fd_set fd;

		tv.tv_sec = 1;
		tv.tv_usec = 0;
		FD_ZERO(&fd);
		FD_SET(pipe_fd, &fd);
		rc = select(pipe_fd+1, &fd, NULL, NULL, &tv);
		if (rc == 0) 
			continue;
		 else if (rc == -1)
			break;

		/* Get header first. it is fixed size */
		vec[0].iov_base = (void*)&hdr;
		vec[0].iov_len = sizeof(hdr);
		do {
			rc = readv(fd, &vec[0], 1);
		} while (rc < 0 && errno == EINTR);

		if (rc > 0) {
	        	// Next payload 
			vec[1].iov_base = data;
			vec[1].iov_len = hdr.size; 
			do {
				rc = readv(fd, &vec[1], 1);
			} while (rc < 0 && errno == EINTR);
		}
		if (rc <= 0) {
			syslog(LOG_ERR, "rc == %d(%s)", rc, strerror(errno));
			continue;
		}

		// Handle events here. Just for illustration, we print
		// to syslog, but you will want to do something else.
		syslog(LOG_NOTICE,"type=%d, payload size=%d", 
			hdr.type, hdr.size);
		syslog(LOG_NOTICE,"data=\"%.*s\"", hdr.size,
			(char *)data);

	} while(!signaled);

	return 0;
}