Deleted Added
full compact
auditreduce.c (155131) auditreduce.c (155364)
1/*
2 * Copyright (c) 2004 Apple Computer, Inc.
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 * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
14 * its contributors may be used to endorse or promote products derived
15 * from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR
21 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
25 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
26 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 * POSSIBILITY OF SUCH DAMAGE.
28 *
1/*
2 * Copyright (c) 2004 Apple Computer, Inc.
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 * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
14 * its contributors may be used to endorse or promote products derived
15 * from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR
21 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
25 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
26 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 * POSSIBILITY OF SUCH DAMAGE.
28 *
29 * $P4: //depot/projects/trustedbsd/openbsm/bin/auditreduce/auditreduce.c#11 $
29 * $P4: //depot/projects/trustedbsd/openbsm/bin/auditreduce/auditreduce.c#13 $
30 */
31
32/*
33 * Tool used to merge and select audit records from audit trail files
34 */
35
36/*
37 * XXX Currently we do not support merging of records from multiple
38 * XXX audit trail files
39 * XXX We assume that records are sorted chronologically - both wrt to
40 * XXX the records present within the file and between the files themselves
41 */
42
43#include <bsm/libbsm.h>
44
45#include <stdio.h>
46#include <stdlib.h>
47#include <sysexits.h>
48#include <grp.h>
49#include <pwd.h>
50#include <string.h>
51#include <time.h>
52#include <unistd.h>
53
54#include "auditreduce.h"
55
56extern char *optarg;
57extern int optind, optopt, opterr,optreset;
58
59static au_mask_t maskp; /* Class. */
60static time_t p_atime; /* Created after this time. */
61static time_t p_btime; /* Created before this time. */
62static uint16_t p_evtype; /* Event that we are searching for. */
63static int p_auid; /* Audit id. */
64static int p_euid; /* Effective user id. */
65static int p_egid; /* Effective group id. */
66static int p_rgid; /* Real group id. */
67static int p_ruid; /* Real user id. */
68static int p_subid; /* Subject id. */
69
70/*
71 * Following are the objects (-o option) that we can select upon.
72 */
73static char *p_fileobj = NULL;
74static char *p_msgqobj = NULL;
75static char *p_pidobj = NULL;
76static char *p_semobj = NULL;
77static char *p_shmobj = NULL;
78static char *p_sockobj = NULL;
79
80static uint32_t opttochk = 0;
81
82static void
83usage(const char *msg)
84{
85 fprintf(stderr, "%s\n", msg);
86 fprintf(stderr, "Usage: auditreduce [options] audit-trail-file [....] \n");
87 fprintf(stderr, "\tOptions are : \n");
88 fprintf(stderr, "\t-A : all records\n");
89 fprintf(stderr, "\t-a YYYYMMDD[HH[[MM[SS]]] : after date\n");
90 fprintf(stderr, "\t-b YYYYMMDD[HH[[MM[SS]]] : before date\n");
91 fprintf(stderr, "\t-c <flags> : matching class\n");
92 fprintf(stderr, "\t-d YYYYMMDD : on date\n");
93 fprintf(stderr, "\t-e <uid|name> : effective user\n");
94 fprintf(stderr, "\t-f <gid|group> : effective group\n");
95 fprintf(stderr, "\t-g <gid|group> : real group\n");
96 fprintf(stderr, "\t-j <pid> : subject id \n");
97 fprintf(stderr, "\t-m <evno|evname> : matching event\n");
98 fprintf(stderr, "\t-o objecttype=objectvalue\n");
99 fprintf(stderr, "\t\t file=<pathname>\n");
100 fprintf(stderr, "\t\t msgqid=<ID>\n");
101 fprintf(stderr, "\t\t pid=<ID>\n");
102 fprintf(stderr, "\t\t semid=<ID>\n");
103 fprintf(stderr, "\t\t shmid=<ID>\n");
104 fprintf(stderr, "\t-r <uid|name> : real user\n");
105 fprintf(stderr, "\t-u <uid|name> : audit user\n");
106 exit(EX_USAGE);
107}
108
109/*
110 * Check if the given auid matches the selection criteria.
111 */
112static int
113select_auid(int au)
114{
115
116 /* Check if we want to select on auid. */
117 if (ISOPTSET(opttochk, OPT_u)) {
118 if (au != p_auid)
119 return (0);
120 }
121 return (1);
122}
123
124/*
125 * Check if the given euid matches the selection criteria.
126 */
127static int
128select_euid(int euser)
129{
130
131 /* Check if we want to select on euid. */
132 if (ISOPTSET(opttochk, OPT_e)) {
133 if (euser != p_euid)
134 return (0);
135 }
136 return (1);
137}
138
139/*
140 * Check if the given egid matches the selection criteria.
141 */
142static int
143select_egid(int egrp)
144{
145
146 /* Check if we want to select on egid. */
147 if (ISOPTSET(opttochk, OPT_f)) {
148 if (egrp != p_egid)
149 return (0);
150 }
151 return (1);
152}
153
154/*
155 * Check if the given rgid matches the selection criteria.
156 */
157static int
158select_rgid(int grp)
159{
160
161 /* Check if we want to select on rgid. */
162 if (ISOPTSET(opttochk, OPT_g)) {
163 if (grp != p_rgid)
164 return (0);
165 }
166 return (1);
167}
168
169/*
170 * Check if the given ruid matches the selection criteria.
171 */
172static int
173select_ruid(int user)
174{
175
176 /* Check if we want to select on rgid. */
177 if (ISOPTSET(opttochk, OPT_r)) {
178 if (user != p_ruid)
179 return (0);
180 }
181 return (1);
182}
183
184/*
185 * Check if the given subject id (pid) matches the selection criteria.
186 */
187static int
188select_subid(int subid)
189{
190
191 /* Check if we want to select on subject uid. */
192 if (ISOPTSET(opttochk, OPT_j)) {
193 if (subid != p_subid)
194 return (0);
195 }
196 return (1);
197}
198
199
200/*
201 * Check if object's pid maches the given pid.
202 */
203static int
204select_pidobj(uint32_t pid)
205{
206
207 if (ISOPTSET(opttochk, OPT_op)) {
208 if (pid != strtol(p_pidobj, (char **)NULL, 10))
209 return (0);
210 }
211 return (1);
212}
213
214/*
215 * Check if the given ipc object with the given type matches the selection
216 * criteria.
217 */
218static int
219select_ipcobj(u_char type, uint32_t id, uint32_t *optchkd)
220{
221
222 if (type == AT_IPC_MSG) {
223 SETOPT((*optchkd), OPT_om);
224 if (ISOPTSET(opttochk, OPT_om)) {
225 if (id != strtol(p_msgqobj, (char **)NULL, 10))
226 return (0);
227 }
228 return (1);
229 } else if (type == AT_IPC_SEM) {
230 SETOPT((*optchkd), OPT_ose);
231 if (ISOPTSET(opttochk, OPT_ose)) {
232 if (id != strtol(p_semobj, (char **)NULL, 10))
233 return (0);
234 }
235 return (1);
236 } else if (type == AT_IPC_SHM) {
237 SETOPT((*optchkd), OPT_osh);
238 if (ISOPTSET(opttochk, OPT_osh)) {
239 if (id != strtol(p_shmobj, (char **)NULL, 10))
240 return (0);
241 }
242 return (1);
243 }
244
245 /* Unknown type -- filter if *any* ipc filtering is required. */
246 if (ISOPTSET(opttochk, OPT_om) || ISOPTSET(opttochk, OPT_ose)
247 || ISOPTSET(opttochk, OPT_osh))
248 return (0);
249
250 return (1);
251}
252
253
254/*
255 * Check if the file name matches selection criteria.
256 */
257static int
258select_filepath(char *path, uint32_t *optchkd)
259{
260 char *loc;
261
262 SETOPT((*optchkd), OPT_of);
263 if (ISOPTSET(opttochk, OPT_of)) {
264 if (p_fileobj[0] == '~') {
265 /* Object should not be in path. */
266 loc = strstr(path, p_fileobj + 1);
267 if ((loc != NULL) && (loc == path))
268 return (0);
269 } else {
270 /* Object should be in path. */
271 loc = strstr(path, p_fileobj);
272 if ((loc == NULL) || (loc != path))
273 return (0);
274 }
275 }
276 return (1);
277}
278
279/*
280 * Returns 1 if the following pass the selection rules:
281 *
282 * before-time,
283 * after time,
284 * date,
285 * class,
286 * event
287 */
288static int
289select_hdr32(tokenstr_t tok, uint32_t *optchkd)
290{
291
292 SETOPT((*optchkd), (OPT_A | OPT_a | OPT_b | OPT_c | OPT_m));
293
294 /* The A option overrides a, b and d. */
295 if (!ISOPTSET(opttochk, OPT_A)) {
296 if (ISOPTSET(opttochk, OPT_a)) {
297 if (difftime((time_t)tok.tt.hdr32.s, p_atime) < 0) {
298 /* Record was created before p_atime. */
299 return (0);
300 }
301 }
302
303 if (ISOPTSET(opttochk, OPT_b)) {
304 if (difftime(p_btime, (time_t)tok.tt.hdr32.s) < 0) {
305 /* Record was created after p_btime. */
306 return (0);
307 }
308 }
309 }
310
311 if (ISOPTSET(opttochk, OPT_c)) {
312 /*
313 * Check if the classes represented by the event matches
314 * given class.
315 */
316 if (au_preselect(tok.tt.hdr32.e_type, &maskp, AU_PRS_BOTH,
317 AU_PRS_USECACHE) != 1)
318 return (0);
319 }
320
321 /* Check if event matches. */
322 if (ISOPTSET(opttochk, OPT_m)) {
323 if (tok.tt.hdr32.e_type != p_evtype)
324 return (0);
325 }
326
327 return (1);
328}
329
330/*
331 * Return 1 if checks for the the following succeed
332 * auid,
333 * euid,
334 * egid,
335 * rgid,
336 * ruid,
337 * process id
338 */
339static int
340select_proc32(tokenstr_t tok, uint32_t *optchkd)
341{
342
343 SETOPT((*optchkd), (OPT_u | OPT_e | OPT_f | OPT_g | OPT_r | OPT_op));
344
345 if (!select_auid(tok.tt.proc32.auid))
346 return (0);
347 if (!select_euid(tok.tt.proc32.euid))
348 return (0);
349 if (!select_egid(tok.tt.proc32.egid))
350 return (0);
351 if (!select_rgid(tok.tt.proc32.rgid))
352 return (0);
353 if (!select_ruid(tok.tt.proc32.ruid))
354 return (0);
355 if (!select_pidobj(tok.tt.proc32.pid))
356 return (0);
357 return (1);
358}
359
360/*
361 * Return 1 if checks for the the following succeed
362 * auid,
363 * euid,
364 * egid,
365 * rgid,
366 * ruid,
367 * subject id
368 */
369static int
370select_subj32(tokenstr_t tok, uint32_t *optchkd)
371{
372
373 SETOPT((*optchkd), (OPT_u | OPT_e | OPT_f | OPT_g | OPT_r | OPT_j));
374
375 if (!select_auid(tok.tt.subj32.auid))
376 return (0);
377 if (!select_euid(tok.tt.subj32.euid))
378 return (0);
379 if (!select_egid(tok.tt.subj32.egid))
380 return (0);
381 if (!select_rgid(tok.tt.subj32.rgid))
382 return (0);
383 if (!select_ruid(tok.tt.subj32.ruid))
384 return (0);
385 if (!select_subid(tok.tt.subj32.pid))
386 return (0);
387 return (1);
388}
389
390/*
391 * Read each record from the audit trail. Check if it is selected after
392 * passing through each of the options
393 */
394static int
395select_records(FILE *fp)
396{
397 u_char *buf;
398 tokenstr_t tok;
399 int reclen;
400 int bytesread;
401 int selected;
402 uint32_t optchkd;
403
404 int err = 0;
405 while ((reclen = au_read_rec(fp, &buf)) != -1) {
406 optchkd = 0;
407 bytesread = 0;
408 selected = 1;
409 while ((selected == 1) && (bytesread < reclen)) {
410 if (-1 == au_fetch_tok(&tok, buf + bytesread,
411 reclen - bytesread)) {
412 /* Is this an incomplete record? */
413 err = 1;
414 break;
415 }
416
417 /*
418 * For each token type we have have different
419 * selection criteria.
420 */
421 switch(tok.id) {
422 case AU_HEADER_32_TOKEN:
423 selected = select_hdr32(tok,
424 &optchkd);
425 break;
426
427 case AU_PROCESS_32_TOKEN:
428 selected = select_proc32(tok,
429 &optchkd);
430 break;
431
432 case AU_SUBJECT_32_TOKEN:
433 selected = select_subj32(tok,
434 &optchkd);
435 break;
436
437 case AU_IPC_TOKEN:
438 selected = select_ipcobj(
439 tok.tt.ipc.type, tok.tt.ipc.id,
440 &optchkd);
441 break;
442
443 case AU_FILE_TOKEN:
444 selected = select_filepath(
445 tok.tt.file.name, &optchkd);
446 break;
447
448 case AU_PATH_TOKEN:
449 selected = select_filepath(
450 tok.tt.path.path, &optchkd);
451 break;
452
453 /*
454 * The following tokens dont have any relevant
455 * attributes that we can select upon.
456 */
457 case AU_TRAILER_TOKEN:
458 case AU_ARG32_TOKEN:
459 case AU_ATTR32_TOKEN:
460 case AU_EXIT_TOKEN:
461 case AU_NEWGROUPS_TOKEN:
462 case AU_IN_ADDR_TOKEN:
463 case AU_IP_TOKEN:
464 case AU_IPCPERM_TOKEN:
465 case AU_IPORT_TOKEN:
466 case AU_OPAQUE_TOKEN:
467 case AU_RETURN_32_TOKEN:
468 case AU_SEQ_TOKEN:
469 case AU_TEXT_TOKEN:
470 case AU_ARB_TOKEN:
471 case AU_SOCK_TOKEN:
472 default:
473 break;
474 }
475 bytesread += tok.len;
476 }
477 if ((selected == 1) && (!err)) {
478 /* Check if all the options were matched. */
479 if (!(opttochk & ~optchkd)) {
480 /* XXX Write this record to the output file. */
481 /* default to stdout */
482 fwrite(buf, 1, reclen, stdout);
483 }
484 }
485 free(buf);
486 }
487 return (0);
488}
489
490/*
491 * The -o option has the form object_type=object_value. Identify the object
492 * components.
493 */
494void
495parse_object_type(char *name, char *val)
496{
497 if (val == NULL)
498 return;
499
500 if (!strcmp(name, FILEOBJ)) {
501 p_fileobj = val;
502 SETOPT(opttochk, OPT_of);
503 } else if (!strcmp(name, MSGQIDOBJ)) {
504 p_msgqobj = val;
505 SETOPT(opttochk, OPT_om);
506 } else if (!strcmp(name, PIDOBJ)) {
507 p_pidobj = val;
508 SETOPT(opttochk, OPT_op);
509 } else if (!strcmp(name, SEMIDOBJ)) {
510 p_semobj = val;
511 SETOPT(opttochk, OPT_ose);
512 } else if (!strcmp(name, SHMIDOBJ)) {
513 p_shmobj = val;
514 SETOPT(opttochk, OPT_osh);
515 } else if (!strcmp(name, SOCKOBJ)) {
516 p_sockobj = val;
517 SETOPT(opttochk, OPT_oso);
518 } else
519 usage("unknown value for -o");
520}
521
522int
523main(int argc, char **argv)
524{
525 struct group *grp;
526 struct passwd *pw;
527 struct tm tm;
528 au_event_t *n;
529 FILE *fp;
530 int i;
531 char *objval, *converr;
30 */
31
32/*
33 * Tool used to merge and select audit records from audit trail files
34 */
35
36/*
37 * XXX Currently we do not support merging of records from multiple
38 * XXX audit trail files
39 * XXX We assume that records are sorted chronologically - both wrt to
40 * XXX the records present within the file and between the files themselves
41 */
42
43#include <bsm/libbsm.h>
44
45#include <stdio.h>
46#include <stdlib.h>
47#include <sysexits.h>
48#include <grp.h>
49#include <pwd.h>
50#include <string.h>
51#include <time.h>
52#include <unistd.h>
53
54#include "auditreduce.h"
55
56extern char *optarg;
57extern int optind, optopt, opterr,optreset;
58
59static au_mask_t maskp; /* Class. */
60static time_t p_atime; /* Created after this time. */
61static time_t p_btime; /* Created before this time. */
62static uint16_t p_evtype; /* Event that we are searching for. */
63static int p_auid; /* Audit id. */
64static int p_euid; /* Effective user id. */
65static int p_egid; /* Effective group id. */
66static int p_rgid; /* Real group id. */
67static int p_ruid; /* Real user id. */
68static int p_subid; /* Subject id. */
69
70/*
71 * Following are the objects (-o option) that we can select upon.
72 */
73static char *p_fileobj = NULL;
74static char *p_msgqobj = NULL;
75static char *p_pidobj = NULL;
76static char *p_semobj = NULL;
77static char *p_shmobj = NULL;
78static char *p_sockobj = NULL;
79
80static uint32_t opttochk = 0;
81
82static void
83usage(const char *msg)
84{
85 fprintf(stderr, "%s\n", msg);
86 fprintf(stderr, "Usage: auditreduce [options] audit-trail-file [....] \n");
87 fprintf(stderr, "\tOptions are : \n");
88 fprintf(stderr, "\t-A : all records\n");
89 fprintf(stderr, "\t-a YYYYMMDD[HH[[MM[SS]]] : after date\n");
90 fprintf(stderr, "\t-b YYYYMMDD[HH[[MM[SS]]] : before date\n");
91 fprintf(stderr, "\t-c <flags> : matching class\n");
92 fprintf(stderr, "\t-d YYYYMMDD : on date\n");
93 fprintf(stderr, "\t-e <uid|name> : effective user\n");
94 fprintf(stderr, "\t-f <gid|group> : effective group\n");
95 fprintf(stderr, "\t-g <gid|group> : real group\n");
96 fprintf(stderr, "\t-j <pid> : subject id \n");
97 fprintf(stderr, "\t-m <evno|evname> : matching event\n");
98 fprintf(stderr, "\t-o objecttype=objectvalue\n");
99 fprintf(stderr, "\t\t file=<pathname>\n");
100 fprintf(stderr, "\t\t msgqid=<ID>\n");
101 fprintf(stderr, "\t\t pid=<ID>\n");
102 fprintf(stderr, "\t\t semid=<ID>\n");
103 fprintf(stderr, "\t\t shmid=<ID>\n");
104 fprintf(stderr, "\t-r <uid|name> : real user\n");
105 fprintf(stderr, "\t-u <uid|name> : audit user\n");
106 exit(EX_USAGE);
107}
108
109/*
110 * Check if the given auid matches the selection criteria.
111 */
112static int
113select_auid(int au)
114{
115
116 /* Check if we want to select on auid. */
117 if (ISOPTSET(opttochk, OPT_u)) {
118 if (au != p_auid)
119 return (0);
120 }
121 return (1);
122}
123
124/*
125 * Check if the given euid matches the selection criteria.
126 */
127static int
128select_euid(int euser)
129{
130
131 /* Check if we want to select on euid. */
132 if (ISOPTSET(opttochk, OPT_e)) {
133 if (euser != p_euid)
134 return (0);
135 }
136 return (1);
137}
138
139/*
140 * Check if the given egid matches the selection criteria.
141 */
142static int
143select_egid(int egrp)
144{
145
146 /* Check if we want to select on egid. */
147 if (ISOPTSET(opttochk, OPT_f)) {
148 if (egrp != p_egid)
149 return (0);
150 }
151 return (1);
152}
153
154/*
155 * Check if the given rgid matches the selection criteria.
156 */
157static int
158select_rgid(int grp)
159{
160
161 /* Check if we want to select on rgid. */
162 if (ISOPTSET(opttochk, OPT_g)) {
163 if (grp != p_rgid)
164 return (0);
165 }
166 return (1);
167}
168
169/*
170 * Check if the given ruid matches the selection criteria.
171 */
172static int
173select_ruid(int user)
174{
175
176 /* Check if we want to select on rgid. */
177 if (ISOPTSET(opttochk, OPT_r)) {
178 if (user != p_ruid)
179 return (0);
180 }
181 return (1);
182}
183
184/*
185 * Check if the given subject id (pid) matches the selection criteria.
186 */
187static int
188select_subid(int subid)
189{
190
191 /* Check if we want to select on subject uid. */
192 if (ISOPTSET(opttochk, OPT_j)) {
193 if (subid != p_subid)
194 return (0);
195 }
196 return (1);
197}
198
199
200/*
201 * Check if object's pid maches the given pid.
202 */
203static int
204select_pidobj(uint32_t pid)
205{
206
207 if (ISOPTSET(opttochk, OPT_op)) {
208 if (pid != strtol(p_pidobj, (char **)NULL, 10))
209 return (0);
210 }
211 return (1);
212}
213
214/*
215 * Check if the given ipc object with the given type matches the selection
216 * criteria.
217 */
218static int
219select_ipcobj(u_char type, uint32_t id, uint32_t *optchkd)
220{
221
222 if (type == AT_IPC_MSG) {
223 SETOPT((*optchkd), OPT_om);
224 if (ISOPTSET(opttochk, OPT_om)) {
225 if (id != strtol(p_msgqobj, (char **)NULL, 10))
226 return (0);
227 }
228 return (1);
229 } else if (type == AT_IPC_SEM) {
230 SETOPT((*optchkd), OPT_ose);
231 if (ISOPTSET(opttochk, OPT_ose)) {
232 if (id != strtol(p_semobj, (char **)NULL, 10))
233 return (0);
234 }
235 return (1);
236 } else if (type == AT_IPC_SHM) {
237 SETOPT((*optchkd), OPT_osh);
238 if (ISOPTSET(opttochk, OPT_osh)) {
239 if (id != strtol(p_shmobj, (char **)NULL, 10))
240 return (0);
241 }
242 return (1);
243 }
244
245 /* Unknown type -- filter if *any* ipc filtering is required. */
246 if (ISOPTSET(opttochk, OPT_om) || ISOPTSET(opttochk, OPT_ose)
247 || ISOPTSET(opttochk, OPT_osh))
248 return (0);
249
250 return (1);
251}
252
253
254/*
255 * Check if the file name matches selection criteria.
256 */
257static int
258select_filepath(char *path, uint32_t *optchkd)
259{
260 char *loc;
261
262 SETOPT((*optchkd), OPT_of);
263 if (ISOPTSET(opttochk, OPT_of)) {
264 if (p_fileobj[0] == '~') {
265 /* Object should not be in path. */
266 loc = strstr(path, p_fileobj + 1);
267 if ((loc != NULL) && (loc == path))
268 return (0);
269 } else {
270 /* Object should be in path. */
271 loc = strstr(path, p_fileobj);
272 if ((loc == NULL) || (loc != path))
273 return (0);
274 }
275 }
276 return (1);
277}
278
279/*
280 * Returns 1 if the following pass the selection rules:
281 *
282 * before-time,
283 * after time,
284 * date,
285 * class,
286 * event
287 */
288static int
289select_hdr32(tokenstr_t tok, uint32_t *optchkd)
290{
291
292 SETOPT((*optchkd), (OPT_A | OPT_a | OPT_b | OPT_c | OPT_m));
293
294 /* The A option overrides a, b and d. */
295 if (!ISOPTSET(opttochk, OPT_A)) {
296 if (ISOPTSET(opttochk, OPT_a)) {
297 if (difftime((time_t)tok.tt.hdr32.s, p_atime) < 0) {
298 /* Record was created before p_atime. */
299 return (0);
300 }
301 }
302
303 if (ISOPTSET(opttochk, OPT_b)) {
304 if (difftime(p_btime, (time_t)tok.tt.hdr32.s) < 0) {
305 /* Record was created after p_btime. */
306 return (0);
307 }
308 }
309 }
310
311 if (ISOPTSET(opttochk, OPT_c)) {
312 /*
313 * Check if the classes represented by the event matches
314 * given class.
315 */
316 if (au_preselect(tok.tt.hdr32.e_type, &maskp, AU_PRS_BOTH,
317 AU_PRS_USECACHE) != 1)
318 return (0);
319 }
320
321 /* Check if event matches. */
322 if (ISOPTSET(opttochk, OPT_m)) {
323 if (tok.tt.hdr32.e_type != p_evtype)
324 return (0);
325 }
326
327 return (1);
328}
329
330/*
331 * Return 1 if checks for the the following succeed
332 * auid,
333 * euid,
334 * egid,
335 * rgid,
336 * ruid,
337 * process id
338 */
339static int
340select_proc32(tokenstr_t tok, uint32_t *optchkd)
341{
342
343 SETOPT((*optchkd), (OPT_u | OPT_e | OPT_f | OPT_g | OPT_r | OPT_op));
344
345 if (!select_auid(tok.tt.proc32.auid))
346 return (0);
347 if (!select_euid(tok.tt.proc32.euid))
348 return (0);
349 if (!select_egid(tok.tt.proc32.egid))
350 return (0);
351 if (!select_rgid(tok.tt.proc32.rgid))
352 return (0);
353 if (!select_ruid(tok.tt.proc32.ruid))
354 return (0);
355 if (!select_pidobj(tok.tt.proc32.pid))
356 return (0);
357 return (1);
358}
359
360/*
361 * Return 1 if checks for the the following succeed
362 * auid,
363 * euid,
364 * egid,
365 * rgid,
366 * ruid,
367 * subject id
368 */
369static int
370select_subj32(tokenstr_t tok, uint32_t *optchkd)
371{
372
373 SETOPT((*optchkd), (OPT_u | OPT_e | OPT_f | OPT_g | OPT_r | OPT_j));
374
375 if (!select_auid(tok.tt.subj32.auid))
376 return (0);
377 if (!select_euid(tok.tt.subj32.euid))
378 return (0);
379 if (!select_egid(tok.tt.subj32.egid))
380 return (0);
381 if (!select_rgid(tok.tt.subj32.rgid))
382 return (0);
383 if (!select_ruid(tok.tt.subj32.ruid))
384 return (0);
385 if (!select_subid(tok.tt.subj32.pid))
386 return (0);
387 return (1);
388}
389
390/*
391 * Read each record from the audit trail. Check if it is selected after
392 * passing through each of the options
393 */
394static int
395select_records(FILE *fp)
396{
397 u_char *buf;
398 tokenstr_t tok;
399 int reclen;
400 int bytesread;
401 int selected;
402 uint32_t optchkd;
403
404 int err = 0;
405 while ((reclen = au_read_rec(fp, &buf)) != -1) {
406 optchkd = 0;
407 bytesread = 0;
408 selected = 1;
409 while ((selected == 1) && (bytesread < reclen)) {
410 if (-1 == au_fetch_tok(&tok, buf + bytesread,
411 reclen - bytesread)) {
412 /* Is this an incomplete record? */
413 err = 1;
414 break;
415 }
416
417 /*
418 * For each token type we have have different
419 * selection criteria.
420 */
421 switch(tok.id) {
422 case AU_HEADER_32_TOKEN:
423 selected = select_hdr32(tok,
424 &optchkd);
425 break;
426
427 case AU_PROCESS_32_TOKEN:
428 selected = select_proc32(tok,
429 &optchkd);
430 break;
431
432 case AU_SUBJECT_32_TOKEN:
433 selected = select_subj32(tok,
434 &optchkd);
435 break;
436
437 case AU_IPC_TOKEN:
438 selected = select_ipcobj(
439 tok.tt.ipc.type, tok.tt.ipc.id,
440 &optchkd);
441 break;
442
443 case AU_FILE_TOKEN:
444 selected = select_filepath(
445 tok.tt.file.name, &optchkd);
446 break;
447
448 case AU_PATH_TOKEN:
449 selected = select_filepath(
450 tok.tt.path.path, &optchkd);
451 break;
452
453 /*
454 * The following tokens dont have any relevant
455 * attributes that we can select upon.
456 */
457 case AU_TRAILER_TOKEN:
458 case AU_ARG32_TOKEN:
459 case AU_ATTR32_TOKEN:
460 case AU_EXIT_TOKEN:
461 case AU_NEWGROUPS_TOKEN:
462 case AU_IN_ADDR_TOKEN:
463 case AU_IP_TOKEN:
464 case AU_IPCPERM_TOKEN:
465 case AU_IPORT_TOKEN:
466 case AU_OPAQUE_TOKEN:
467 case AU_RETURN_32_TOKEN:
468 case AU_SEQ_TOKEN:
469 case AU_TEXT_TOKEN:
470 case AU_ARB_TOKEN:
471 case AU_SOCK_TOKEN:
472 default:
473 break;
474 }
475 bytesread += tok.len;
476 }
477 if ((selected == 1) && (!err)) {
478 /* Check if all the options were matched. */
479 if (!(opttochk & ~optchkd)) {
480 /* XXX Write this record to the output file. */
481 /* default to stdout */
482 fwrite(buf, 1, reclen, stdout);
483 }
484 }
485 free(buf);
486 }
487 return (0);
488}
489
490/*
491 * The -o option has the form object_type=object_value. Identify the object
492 * components.
493 */
494void
495parse_object_type(char *name, char *val)
496{
497 if (val == NULL)
498 return;
499
500 if (!strcmp(name, FILEOBJ)) {
501 p_fileobj = val;
502 SETOPT(opttochk, OPT_of);
503 } else if (!strcmp(name, MSGQIDOBJ)) {
504 p_msgqobj = val;
505 SETOPT(opttochk, OPT_om);
506 } else if (!strcmp(name, PIDOBJ)) {
507 p_pidobj = val;
508 SETOPT(opttochk, OPT_op);
509 } else if (!strcmp(name, SEMIDOBJ)) {
510 p_semobj = val;
511 SETOPT(opttochk, OPT_ose);
512 } else if (!strcmp(name, SHMIDOBJ)) {
513 p_shmobj = val;
514 SETOPT(opttochk, OPT_osh);
515 } else if (!strcmp(name, SOCKOBJ)) {
516 p_sockobj = val;
517 SETOPT(opttochk, OPT_oso);
518 } else
519 usage("unknown value for -o");
520}
521
522int
523main(int argc, char **argv)
524{
525 struct group *grp;
526 struct passwd *pw;
527 struct tm tm;
528 au_event_t *n;
529 FILE *fp;
530 int i;
531 char *objval, *converr;
532 char ch;
532 int ch;
533 char timestr[128];
534 char *fname;
535
536 converr = NULL;
537
538 while ((ch = getopt(argc, argv, "Aa:b:c:d:e:f:g:j:m:o:r:u:")) != -1) {
539 switch(ch) {
540 case 'A':
541 SETOPT(opttochk, OPT_A);
542 break;
543
544 case 'a':
545 if (ISOPTSET(opttochk, OPT_a)) {
546 usage("d is exclusive with a and b");
547 }
548 SETOPT(opttochk, OPT_a);
549 strptime(optarg, "%Y%m%d%H%M%S", &tm);
550 strftime(timestr, sizeof(timestr), "%Y%m%d%H%M%S",
551 &tm);
552 /* fprintf(stderr, "Time converted = %s\n", timestr); */
553 p_atime = mktime(&tm);
554 break;
555
556 case 'b':
557 if (ISOPTSET(opttochk, OPT_b)) {
558 usage("d is exclusive with a and b");
559 }
560 SETOPT(opttochk, OPT_b);
561 strptime(optarg, "%Y%m%d%H%M%S", &tm);
562 strftime(timestr, sizeof(timestr), "%Y%m%d%H%M%S",
563 &tm);
564 /* fprintf(stderr, "Time converted = %s\n", timestr); */
565 p_btime = mktime(&tm);
566 break;
567
568 case 'c':
569 if (0 != getauditflagsbin(optarg, &maskp)) {
570 /* Incorrect class */
571 usage("Incorrect class");
572 }
573 SETOPT(opttochk, OPT_c);
574 break;
575
576 case 'd':
577 if (ISOPTSET(opttochk, OPT_b) || ISOPTSET(opttochk,
578 OPT_a))
579 usage("'d' is exclusive with 'a' and 'b'");
580 SETOPT(opttochk, OPT_d);
581 strptime(optarg, "%Y%m%d", &tm);
582 strftime(timestr, sizeof(timestr), "%Y%m%d", &tm);
583 /* fprintf(stderr, "Time converted = %s\n", timestr); */
584 p_atime = mktime(&tm);
585 tm.tm_hour = 23;
586 tm.tm_min = 59;
587 tm.tm_sec = 59;
588 strftime(timestr, sizeof(timestr), "%Y%m%d", &tm);
589 /* fprintf(stderr, "Time converted = %s\n", timestr); */
590 p_btime = mktime(&tm);
591 break;
592
593 case 'e':
594 p_euid = strtol(optarg, &converr, 10);
595 if (*converr != '\0') {
596 /* Try the actual name */
597 if ((pw = getpwnam(optarg)) == NULL)
598 break;
599 p_euid = pw->pw_uid;
600 }
601 SETOPT(opttochk, OPT_e);
602 break;
603
604 case 'f':
605 p_egid = strtol(optarg, &converr, 10);
606 if (*converr != '\0') {
607 /* Try actual group name. */
608 if ((grp = getgrnam(optarg)) == NULL)
609 break;
610 p_egid = grp->gr_gid;
611 }
612 SETOPT(opttochk, OPT_f);
613 break;
614
615 case 'g':
616 p_rgid = strtol(optarg, &converr, 10);
617 if (*converr != '\0') {
618 /* Try actual group name. */
619 if ((grp = getgrnam(optarg)) == NULL)
620 break;
621 p_rgid = grp->gr_gid;
622 }
623 SETOPT(opttochk, OPT_g);
624 break;
625
626 case 'j':
627 p_subid = strtol(optarg, (char **)NULL, 10);
628 SETOPT(opttochk, OPT_j);
629 break;
630
631 case 'm':
632 p_evtype = strtol(optarg, (char **)NULL, 10);
633 if (p_evtype == 0) {
634 /* Could be the string representation. */
635 n = getauevnonam(optarg);
636 if (n == NULL)
637 usage("Incorrect event name");
638 p_evtype = *n;
639 free(n);
640 }
641 SETOPT(opttochk, OPT_m);
642 break;
643
644 case 'o':
645 objval = strchr(optarg, '=');
646 if (objval != NULL) {
647 *objval = '\0';
648 objval += 1;
649 parse_object_type(optarg, objval);
650 }
651 break;
652
653 case 'r':
654 p_ruid = strtol(optarg, &converr, 10);
655 if (*converr != '\0') {
656 if ((pw = getpwnam(optarg)) == NULL)
657 break;
658 p_ruid = pw->pw_uid;
659 }
660 SETOPT(opttochk, OPT_r);
661 break;
662
663 case 'u':
664 p_auid = strtol(optarg, &converr, 10);
665 if (*converr != '\0') {
666 if ((pw = getpwnam(optarg)) == NULL)
667 break;
668 p_auid = pw->pw_uid;
669 }
670 SETOPT(opttochk, OPT_u);
671 break;
672
673 case '?':
674 default:
675 usage("Unknown option");
676 }
677 }
678 argv += optind;
679 argc -= optind;
680
681 if (argc == 0)
682 usage("Filename needed");
683
684 /*
685 * XXX: We should actually be merging records here.
686 */
687 for (i = 0; i < argc; i++) {
688 fname = argv[i];
689 fp = fopen(fname, "r");
690 if (fp == NULL)
691 errx(EXIT_FAILURE, "Couldn't open %s", fname);
692 if (select_records(fp) == -1) {
693 errx(EXIT_FAILURE, "Couldn't select records %s",
694 fname);
695 }
696 fclose(fp);
697 }
698 exit(EXIT_SUCCESS);
699}
533 char timestr[128];
534 char *fname;
535
536 converr = NULL;
537
538 while ((ch = getopt(argc, argv, "Aa:b:c:d:e:f:g:j:m:o:r:u:")) != -1) {
539 switch(ch) {
540 case 'A':
541 SETOPT(opttochk, OPT_A);
542 break;
543
544 case 'a':
545 if (ISOPTSET(opttochk, OPT_a)) {
546 usage("d is exclusive with a and b");
547 }
548 SETOPT(opttochk, OPT_a);
549 strptime(optarg, "%Y%m%d%H%M%S", &tm);
550 strftime(timestr, sizeof(timestr), "%Y%m%d%H%M%S",
551 &tm);
552 /* fprintf(stderr, "Time converted = %s\n", timestr); */
553 p_atime = mktime(&tm);
554 break;
555
556 case 'b':
557 if (ISOPTSET(opttochk, OPT_b)) {
558 usage("d is exclusive with a and b");
559 }
560 SETOPT(opttochk, OPT_b);
561 strptime(optarg, "%Y%m%d%H%M%S", &tm);
562 strftime(timestr, sizeof(timestr), "%Y%m%d%H%M%S",
563 &tm);
564 /* fprintf(stderr, "Time converted = %s\n", timestr); */
565 p_btime = mktime(&tm);
566 break;
567
568 case 'c':
569 if (0 != getauditflagsbin(optarg, &maskp)) {
570 /* Incorrect class */
571 usage("Incorrect class");
572 }
573 SETOPT(opttochk, OPT_c);
574 break;
575
576 case 'd':
577 if (ISOPTSET(opttochk, OPT_b) || ISOPTSET(opttochk,
578 OPT_a))
579 usage("'d' is exclusive with 'a' and 'b'");
580 SETOPT(opttochk, OPT_d);
581 strptime(optarg, "%Y%m%d", &tm);
582 strftime(timestr, sizeof(timestr), "%Y%m%d", &tm);
583 /* fprintf(stderr, "Time converted = %s\n", timestr); */
584 p_atime = mktime(&tm);
585 tm.tm_hour = 23;
586 tm.tm_min = 59;
587 tm.tm_sec = 59;
588 strftime(timestr, sizeof(timestr), "%Y%m%d", &tm);
589 /* fprintf(stderr, "Time converted = %s\n", timestr); */
590 p_btime = mktime(&tm);
591 break;
592
593 case 'e':
594 p_euid = strtol(optarg, &converr, 10);
595 if (*converr != '\0') {
596 /* Try the actual name */
597 if ((pw = getpwnam(optarg)) == NULL)
598 break;
599 p_euid = pw->pw_uid;
600 }
601 SETOPT(opttochk, OPT_e);
602 break;
603
604 case 'f':
605 p_egid = strtol(optarg, &converr, 10);
606 if (*converr != '\0') {
607 /* Try actual group name. */
608 if ((grp = getgrnam(optarg)) == NULL)
609 break;
610 p_egid = grp->gr_gid;
611 }
612 SETOPT(opttochk, OPT_f);
613 break;
614
615 case 'g':
616 p_rgid = strtol(optarg, &converr, 10);
617 if (*converr != '\0') {
618 /* Try actual group name. */
619 if ((grp = getgrnam(optarg)) == NULL)
620 break;
621 p_rgid = grp->gr_gid;
622 }
623 SETOPT(opttochk, OPT_g);
624 break;
625
626 case 'j':
627 p_subid = strtol(optarg, (char **)NULL, 10);
628 SETOPT(opttochk, OPT_j);
629 break;
630
631 case 'm':
632 p_evtype = strtol(optarg, (char **)NULL, 10);
633 if (p_evtype == 0) {
634 /* Could be the string representation. */
635 n = getauevnonam(optarg);
636 if (n == NULL)
637 usage("Incorrect event name");
638 p_evtype = *n;
639 free(n);
640 }
641 SETOPT(opttochk, OPT_m);
642 break;
643
644 case 'o':
645 objval = strchr(optarg, '=');
646 if (objval != NULL) {
647 *objval = '\0';
648 objval += 1;
649 parse_object_type(optarg, objval);
650 }
651 break;
652
653 case 'r':
654 p_ruid = strtol(optarg, &converr, 10);
655 if (*converr != '\0') {
656 if ((pw = getpwnam(optarg)) == NULL)
657 break;
658 p_ruid = pw->pw_uid;
659 }
660 SETOPT(opttochk, OPT_r);
661 break;
662
663 case 'u':
664 p_auid = strtol(optarg, &converr, 10);
665 if (*converr != '\0') {
666 if ((pw = getpwnam(optarg)) == NULL)
667 break;
668 p_auid = pw->pw_uid;
669 }
670 SETOPT(opttochk, OPT_u);
671 break;
672
673 case '?':
674 default:
675 usage("Unknown option");
676 }
677 }
678 argv += optind;
679 argc -= optind;
680
681 if (argc == 0)
682 usage("Filename needed");
683
684 /*
685 * XXX: We should actually be merging records here.
686 */
687 for (i = 0; i < argc; i++) {
688 fname = argv[i];
689 fp = fopen(fname, "r");
690 if (fp == NULL)
691 errx(EXIT_FAILURE, "Couldn't open %s", fname);
692 if (select_records(fp) == -1) {
693 errx(EXIT_FAILURE, "Couldn't select records %s",
694 fname);
695 }
696 fclose(fp);
697 }
698 exit(EXIT_SUCCESS);
699}