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