xref: /freebsd/contrib/openbsm/bin/auditdistd/subr.c (revision 863dbc94)
1aa772005SRobert Watson /*-
2aa772005SRobert Watson  * Copyright (c) 2011-2012 Pawel Jakub Dawidek <pawel@dawidek.net>
3aa772005SRobert Watson  * All rights reserved.
4aa772005SRobert Watson  *
5aa772005SRobert Watson  * Redistribution and use in source and binary forms, with or without
6aa772005SRobert Watson  * modification, are permitted provided that the following conditions
7aa772005SRobert Watson  * are met:
8aa772005SRobert Watson  * 1. Redistributions of source code must retain the above copyright
9aa772005SRobert Watson  *    notice, this list of conditions and the following disclaimer.
10aa772005SRobert Watson  * 2. Redistributions in binary form must reproduce the above copyright
11aa772005SRobert Watson  *    notice, this list of conditions and the following disclaimer in the
12aa772005SRobert Watson  *    documentation and/or other materials provided with the distribution.
13aa772005SRobert Watson  *
14aa772005SRobert Watson  * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
15aa772005SRobert Watson  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16aa772005SRobert Watson  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17aa772005SRobert Watson  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
18aa772005SRobert Watson  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19aa772005SRobert Watson  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20aa772005SRobert Watson  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21aa772005SRobert Watson  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22aa772005SRobert Watson  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23aa772005SRobert Watson  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24aa772005SRobert Watson  * SUCH DAMAGE.
25aa772005SRobert Watson  */
26aa772005SRobert Watson 
27aa772005SRobert Watson #include <config/config.h>
28aa772005SRobert Watson 
29aa772005SRobert Watson #ifdef HAVE_KQUEUE
30aa772005SRobert Watson #include <sys/types.h>
31aa772005SRobert Watson #include <sys/event.h>
32aa772005SRobert Watson #include <sys/time.h>
33aa772005SRobert Watson #endif
34aa772005SRobert Watson 
35aa772005SRobert Watson #include <errno.h>
36aa772005SRobert Watson #include <stdarg.h>
37aa772005SRobert Watson #include <stdio.h>
38aa772005SRobert Watson #include <string.h>
39aa772005SRobert Watson #include <unistd.h>
40aa772005SRobert Watson 
41aa772005SRobert Watson #ifndef HAVE_ARC4RANDOM
42aa772005SRobert Watson #include <openssl/rand.h>
43aa772005SRobert Watson #endif
44aa772005SRobert Watson 
45aa772005SRobert Watson #ifndef HAVE_STRLCAT
46aa772005SRobert Watson #include <compat/strlcat.h>
47aa772005SRobert Watson #endif
48aa772005SRobert Watson 
49aa772005SRobert Watson #include "auditdistd.h"
50aa772005SRobert Watson #include "pjdlog.h"
51aa772005SRobert Watson #include "subr.h"
52aa772005SRobert Watson 
53aa772005SRobert Watson int
vsnprlcat(char * str,size_t size,const char * fmt,va_list ap)54aa772005SRobert Watson vsnprlcat(char *str, size_t size, const char *fmt, va_list ap)
55aa772005SRobert Watson {
56aa772005SRobert Watson 	size_t len;
57aa772005SRobert Watson 
58aa772005SRobert Watson 	len = strlen(str);
59aa772005SRobert Watson 	return (vsnprintf(str + len, size - len, fmt, ap));
60aa772005SRobert Watson }
61aa772005SRobert Watson 
62aa772005SRobert Watson int
snprlcat(char * str,size_t size,const char * fmt,...)63aa772005SRobert Watson snprlcat(char *str, size_t size, const char *fmt, ...)
64aa772005SRobert Watson {
65aa772005SRobert Watson 	va_list ap;
66aa772005SRobert Watson 	int result;
67aa772005SRobert Watson 
68aa772005SRobert Watson 	va_start(ap, fmt);
69aa772005SRobert Watson 	result = vsnprlcat(str, size, fmt, ap);
70aa772005SRobert Watson 	va_end(ap);
71aa772005SRobert Watson 	return (result);
72aa772005SRobert Watson }
73aa772005SRobert Watson 
74aa772005SRobert Watson const char *
role2str(int role)75aa772005SRobert Watson role2str(int role)
76aa772005SRobert Watson {
77aa772005SRobert Watson 
78aa772005SRobert Watson 	switch (role) {
79aa772005SRobert Watson 	case ADIST_ROLE_SENDER:
80aa772005SRobert Watson 		return ("sender");
81aa772005SRobert Watson 	case ADIST_ROLE_RECEIVER:
82aa772005SRobert Watson 		return ("receiver");
83aa772005SRobert Watson 	}
84aa772005SRobert Watson 	return ("unknown");
85aa772005SRobert Watson }
86aa772005SRobert Watson 
87aa772005SRobert Watson const char *
adist_errstr(int error)88aa772005SRobert Watson adist_errstr(int error)
89aa772005SRobert Watson {
90aa772005SRobert Watson 
91aa772005SRobert Watson 	switch (error) {
92aa772005SRobert Watson 	case ADIST_ERROR_WRONG_ORDER:
93aa772005SRobert Watson 		return ("wrong operations order");
94aa772005SRobert Watson 	case ADIST_ERROR_INVALID_NAME:
95aa772005SRobert Watson 		return ("invalid trail file name");
96aa772005SRobert Watson 	case ADIST_ERROR_OPEN_OLD:
97aa772005SRobert Watson 		return ("attempt to open an old trail file");
98aa772005SRobert Watson 	case ADIST_ERROR_CREATE:
99aa772005SRobert Watson 		return ("creation of new trail file failed");
100aa772005SRobert Watson 	case ADIST_ERROR_OPEN:
101aa772005SRobert Watson 		return ("open of existing trail file failed");
102aa772005SRobert Watson 	case ADIST_ERROR_READ:
103aa772005SRobert Watson 		return ("read failed");
104aa772005SRobert Watson 	case ADIST_ERROR_WRITE:
105aa772005SRobert Watson 		return ("write failed");
106aa772005SRobert Watson 	case ADIST_ERROR_RENAME:
107aa772005SRobert Watson 		return ("rename of a trail file failed");
108aa772005SRobert Watson 	default:
109aa772005SRobert Watson 		return ("unknown error");
110aa772005SRobert Watson 	}
111aa772005SRobert Watson }
112aa772005SRobert Watson 
113aa772005SRobert Watson void
adreq_log(int loglevel,int debuglevel,int error,struct adreq * adreq,const char * fmt,...)114aa772005SRobert Watson adreq_log(int loglevel, int debuglevel, int error, struct adreq *adreq,
115aa772005SRobert Watson     const char *fmt, ...)
116aa772005SRobert Watson {
117aa772005SRobert Watson 	char msg[1024];
118aa772005SRobert Watson 	va_list ap;
119aa772005SRobert Watson 
120aa772005SRobert Watson 	va_start(ap, fmt);
121aa772005SRobert Watson 	(void)vsnprintf(msg, sizeof(msg), fmt, ap);
122aa772005SRobert Watson 	va_end(ap);
123aa772005SRobert Watson 	(void)snprlcat(msg, sizeof(msg), "(seq=%ju) ",
124aa772005SRobert Watson 	    (uintmax_t)adreq->adr_seq);
125aa772005SRobert Watson 	switch (adreq->adr_cmd) {
126aa772005SRobert Watson 	case ADIST_CMD_OPEN:
127aa772005SRobert Watson 		(void)snprlcat(msg, sizeof(msg), "OPEN(%s)",
128aa772005SRobert Watson 		    adreq->adr_data);
129aa772005SRobert Watson 		break;
130aa772005SRobert Watson 	case ADIST_CMD_APPEND:
131aa772005SRobert Watson 		(void)snprlcat(msg, sizeof(msg), "APPEND(%ju)",
132aa772005SRobert Watson 		    (uintmax_t)adreq->adr_datasize);
133aa772005SRobert Watson 		break;
134aa772005SRobert Watson 	case ADIST_CMD_CLOSE:
135aa772005SRobert Watson 		(void)snprlcat(msg, sizeof(msg), "CLOSE(%s)",
136aa772005SRobert Watson 		    adreq->adr_data);
137aa772005SRobert Watson 		break;
138aa772005SRobert Watson 	case ADIST_CMD_KEEPALIVE:
139aa772005SRobert Watson 		(void)snprlcat(msg, sizeof(msg), "KEEPALIVE");
140aa772005SRobert Watson 		break;
141aa772005SRobert Watson 	case ADIST_CMD_ERROR:
142aa772005SRobert Watson 		(void)snprlcat(msg, sizeof(msg), "ERROR");
143aa772005SRobert Watson 		break;
144aa772005SRobert Watson 	default:
145aa772005SRobert Watson 		(void)snprlcat(msg, sizeof(msg), "UNKNOWN(%hhu)",
146aa772005SRobert Watson 		    adreq->adr_cmd);
147aa772005SRobert Watson 		break;
148aa772005SRobert Watson 	}
149aa772005SRobert Watson 	if (error != -1)
150aa772005SRobert Watson 		(void)snprlcat(msg, sizeof(msg), ": %s", adist_errstr(error));
151aa772005SRobert Watson 	(void)strlcat(msg, ".", sizeof(msg));
152aa772005SRobert Watson 	pjdlog_common(loglevel, debuglevel, -1, "%s", msg);
153aa772005SRobert Watson }
154aa772005SRobert Watson 
155aa772005SRobert Watson int
adist_random(unsigned char * buf,size_t size)156aa772005SRobert Watson adist_random(unsigned char *buf, size_t size)
157aa772005SRobert Watson {
158aa772005SRobert Watson #ifdef HAVE_ARC4RANDOM_BUF
159aa772005SRobert Watson 	arc4random_buf(buf, size);
160aa772005SRobert Watson 	return (0);
161aa772005SRobert Watson #elif defined(HAVE_ARC4RANDOM)
162aa772005SRobert Watson 	uint32_t val;
163aa772005SRobert Watson 
164aa772005SRobert Watson 	PJDLOG_ASSERT(size > 0);
165aa772005SRobert Watson 	PJDLOG_ASSERT((size % sizeof(val)) == 0);
166aa772005SRobert Watson 
167aa772005SRobert Watson 	do {
168aa772005SRobert Watson 		val = arc4random();
169aa772005SRobert Watson 		bcopy(&val, buf, sizeof(val));
170aa772005SRobert Watson 		buf += sizeof(val);
171aa772005SRobert Watson 		size -= sizeof(val);
172aa772005SRobert Watson 	} while (size > 0);
173aa772005SRobert Watson 
174aa772005SRobert Watson 	return (0);
175aa772005SRobert Watson #else
176aa772005SRobert Watson 	if (RAND_bytes(buf, (int)size) == 0)
177aa772005SRobert Watson 		return (-1);
178aa772005SRobert Watson 	return (0);
179aa772005SRobert Watson #endif
180aa772005SRobert Watson }
181aa772005SRobert Watson 
182aa772005SRobert Watson static int wait_for_dir_kq = -1;
183aa772005SRobert Watson static int wait_for_file_kq = -1;
184aa772005SRobert Watson 
185aa772005SRobert Watson int
wait_for_dir_init(int fd)186aa772005SRobert Watson wait_for_dir_init(int fd)
187aa772005SRobert Watson {
188aa772005SRobert Watson #ifdef HAVE_KQUEUE
189aa772005SRobert Watson 	struct kevent ev;
190aa772005SRobert Watson 	int error, kq;
191aa772005SRobert Watson 
192aa772005SRobert Watson 	PJDLOG_ASSERT(wait_for_dir_kq == -1);
193aa772005SRobert Watson #endif
194aa772005SRobert Watson 
195aa772005SRobert Watson 	PJDLOG_ASSERT(fd != -1);
196aa772005SRobert Watson 
197aa772005SRobert Watson #ifdef HAVE_KQUEUE
198aa772005SRobert Watson 	kq = kqueue();
199aa772005SRobert Watson 	if (kq == -1) {
200aa772005SRobert Watson 		pjdlog_errno(LOG_WARNING, "kqueue() failed");
201aa772005SRobert Watson 		return (-1);
202aa772005SRobert Watson 	}
203aa772005SRobert Watson 	EV_SET(&ev, fd, EVFILT_VNODE, EV_ADD | EV_ENABLE | EV_CLEAR,
204aa772005SRobert Watson 	    NOTE_WRITE, 0, 0);
205aa772005SRobert Watson 	if (kevent(kq, &ev, 1, NULL, 0, NULL) == -1) {
206aa772005SRobert Watson 		error = errno;
207aa772005SRobert Watson 		pjdlog_errno(LOG_WARNING, "kevent() failed");
208aa772005SRobert Watson 		(void)close(kq);
209aa772005SRobert Watson 		errno = error;
210aa772005SRobert Watson 		return (-1);
211aa772005SRobert Watson 	}
212aa772005SRobert Watson 	wait_for_dir_kq = kq;
213aa772005SRobert Watson #endif
214aa772005SRobert Watson 
215aa772005SRobert Watson 	return (0);
216aa772005SRobert Watson }
217aa772005SRobert Watson 
218aa772005SRobert Watson int
wait_for_file_init(int fd)219aa772005SRobert Watson wait_for_file_init(int fd)
220aa772005SRobert Watson {
221aa772005SRobert Watson #ifdef HAVE_KQUEUE
222aa772005SRobert Watson 	struct kevent ev[2];
223aa772005SRobert Watson 	int error, kq;
224aa772005SRobert Watson #endif
225aa772005SRobert Watson 
226aa772005SRobert Watson 	PJDLOG_ASSERT(fd != -1);
227aa772005SRobert Watson 
228aa772005SRobert Watson #ifdef HAVE_KQUEUE
229aa772005SRobert Watson 	if (wait_for_file_kq != -1) {
230aa772005SRobert Watson 		close(wait_for_file_kq);
231863dbc94SPawel Jakub Dawidek 		wait_for_file_kq = -1;
232863dbc94SPawel Jakub Dawidek 	}
233863dbc94SPawel Jakub Dawidek 
234863dbc94SPawel Jakub Dawidek 	kq = kqueue();
235863dbc94SPawel Jakub Dawidek 	if (kq == -1) {
236aa772005SRobert Watson 		pjdlog_errno(LOG_WARNING, "kqueue() failed");
237aa772005SRobert Watson 		return (-1);
238aa772005SRobert Watson 	}
239aa772005SRobert Watson 	EV_SET(&ev[0], fd, EVFILT_VNODE, EV_ADD | EV_ENABLE | EV_CLEAR,
240aa772005SRobert Watson 	    NOTE_RENAME, 0, 0);
241aa772005SRobert Watson 	EV_SET(&ev[1], fd, EVFILT_READ, EV_ADD | EV_ENABLE | EV_CLEAR,
242aa772005SRobert Watson 	    0, 0, 0);
243aa772005SRobert Watson 	if (kevent(kq, ev, 2, NULL, 0, NULL) == -1) {
244aa772005SRobert Watson 		error = errno;
245aa772005SRobert Watson 		pjdlog_errno(LOG_WARNING, "kevent() failed");
246aa772005SRobert Watson 		(void)close(kq);
247aa772005SRobert Watson 		errno = error;
248aa772005SRobert Watson 		return (-1);
249aa772005SRobert Watson 	}
250aa772005SRobert Watson 	wait_for_file_kq = kq;
251aa772005SRobert Watson #endif
252aa772005SRobert Watson 
253aa772005SRobert Watson 	return (0);
254aa772005SRobert Watson }
255aa772005SRobert Watson 
256aa772005SRobert Watson /*
257aa772005SRobert Watson  * Wait for new file to appear in directory.
258aa772005SRobert Watson  */
259aa772005SRobert Watson void
wait_for_dir(void)260aa772005SRobert Watson wait_for_dir(void)
261aa772005SRobert Watson {
262aa772005SRobert Watson #ifdef HAVE_KQUEUE
263aa772005SRobert Watson 	struct kevent ev;
264aa772005SRobert Watson #endif
265aa772005SRobert Watson 
266aa772005SRobert Watson 	if (wait_for_dir_kq == -1) {
267aa772005SRobert Watson 		sleep(1);
268aa772005SRobert Watson 		return;
269aa772005SRobert Watson 	}
270aa772005SRobert Watson 
271aa772005SRobert Watson #ifdef HAVE_KQUEUE
272aa772005SRobert Watson 	PJDLOG_ASSERT(wait_for_dir_kq != -1);
273aa772005SRobert Watson 
274aa772005SRobert Watson 	if (kevent(wait_for_dir_kq, NULL, 0, &ev, 1, NULL) == -1) {
275aa772005SRobert Watson 		pjdlog_errno(LOG_WARNING, "kevent() failed");
276aa772005SRobert Watson 		sleep(1);
277aa772005SRobert Watson 	}
278aa772005SRobert Watson #endif
279aa772005SRobert Watson }
280aa772005SRobert Watson 
281aa772005SRobert Watson /*
282aa772005SRobert Watson  * Wait for file growth or rename.
283aa772005SRobert Watson  */
284aa772005SRobert Watson void
wait_for_file(void)285aa772005SRobert Watson wait_for_file(void)
286aa772005SRobert Watson {
287aa772005SRobert Watson #ifdef HAVE_KQUEUE
288aa772005SRobert Watson 	struct kevent ev[2];
289aa772005SRobert Watson #endif
290aa772005SRobert Watson 
291aa772005SRobert Watson 	if (wait_for_file_kq == -1) {
292aa772005SRobert Watson 		sleep(1);
293aa772005SRobert Watson 		return;
294aa772005SRobert Watson 	}
295aa772005SRobert Watson 
296aa772005SRobert Watson #ifdef HAVE_KQUEUE
297aa772005SRobert Watson 	PJDLOG_ASSERT(wait_for_file_kq != -1);
298aa772005SRobert Watson 
299aa772005SRobert Watson 	if (kevent(wait_for_file_kq, NULL, 0, ev, 2, NULL) == -1) {
300aa772005SRobert Watson 		pjdlog_errno(LOG_WARNING, "kevent() failed");
301aa772005SRobert Watson 		sleep(1);
302aa772005SRobert Watson 	}
303aa772005SRobert Watson #endif
304aa772005SRobert Watson }
305aa772005SRobert Watson