1ca0716f5SRobert Watson /*-
2ca0716f5SRobert Watson  * Copyright (c) 2004-2008 Apple Inc.
3ca0716f5SRobert Watson  * Copyright (c) 2016 Robert N. M. Watson
4ca0716f5SRobert Watson  * All rights reserved.
5ca0716f5SRobert Watson  *
6ca0716f5SRobert Watson  * Portions of this software were developed by BAE Systems, the University of
7ca0716f5SRobert Watson  * Cambridge Computer Laboratory, and Memorial University under DARPA/AFRL
8ca0716f5SRobert Watson  * contract FA8650-15-C-7558 ("CADETS"), as part of the DARPA Transparent
9ca0716f5SRobert Watson  * Computing (TC) research program.
10ca0716f5SRobert Watson  *
11ca0716f5SRobert Watson  * Redistribution and use in source and binary forms, with or without
12ca0716f5SRobert Watson  * modification, are permitted provided that the following conditions
13ca0716f5SRobert Watson  * are met:
14ca0716f5SRobert Watson  * 1.  Redistributions of source code must retain the above copyright
15ca0716f5SRobert Watson  *     notice, this list of conditions and the following disclaimer.
16ca0716f5SRobert Watson  * 2.  Redistributions in binary form must reproduce the above copyright
17ca0716f5SRobert Watson  *     notice, this list of conditions and the following disclaimer in the
18ca0716f5SRobert Watson  *     documentation and/or other materials provided with the distribution.
19ca0716f5SRobert Watson  * 3.  Neither the name of Apple Inc. ("Apple") nor the names of
20ca0716f5SRobert Watson  *     its contributors may be used to endorse or promote products derived
21ca0716f5SRobert Watson  *     from this software without specific prior written permission.
22ca0716f5SRobert Watson  *
23ca0716f5SRobert Watson  * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND
24ca0716f5SRobert Watson  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25ca0716f5SRobert Watson  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26ca0716f5SRobert Watson  * ARE DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR
27ca0716f5SRobert Watson  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28ca0716f5SRobert Watson  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29eb336521SRobert Watson  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30ca0716f5SRobert Watson  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
31ca0716f5SRobert Watson  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
32ca0716f5SRobert Watson  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33ca0716f5SRobert Watson  * POSSIBILITY OF SUCH DAMAGE.
34ca0716f5SRobert Watson  */
35ca0716f5SRobert Watson 
36ca0716f5SRobert Watson /*
37ca0716f5SRobert Watson  * Tool used to merge and select audit records from audit trail files
38ca0716f5SRobert Watson  */
39ca0716f5SRobert Watson 
40ca0716f5SRobert Watson /*
41ca0716f5SRobert Watson  * XXX Currently we do not support merging of records from multiple
42ca0716f5SRobert Watson  * XXX audit trail files
434bd0c025SRobert Watson  * XXX We assume that records are sorted chronologically - both wrt to
444bd0c025SRobert Watson  * XXX the records present within the file and between the files themselves
454bd0c025SRobert Watson  */
464bd0c025SRobert Watson 
474bd0c025SRobert Watson #include <config/config.h>
484bd0c025SRobert Watson 
494bd0c025SRobert Watson #define	_GNU_SOURCE		/* Required for strptime() on glibc2. */
50ca0716f5SRobert Watson 
51ca0716f5SRobert Watson #ifdef HAVE_FULL_QUEUE_H
52506764c6SRobert Watson #include <sys/queue.h>
53506764c6SRobert Watson #else
54506764c6SRobert Watson #include <compat/queue.h>
55ca0716f5SRobert Watson #endif
56ca0716f5SRobert Watson 
57ca0716f5SRobert Watson #ifdef HAVE_CAP_ENTER
58ca0716f5SRobert Watson #include <sys/capsicum.h>
59ca0716f5SRobert Watson #include <sys/wait.h>
60ca0716f5SRobert Watson #endif
614bd0c025SRobert Watson 
624bd0c025SRobert Watson #include <bsm/libbsm.h>
63ca0716f5SRobert Watson 
64ca0716f5SRobert Watson #include <err.h>
65ca0716f5SRobert Watson #include <fnmatch.h>
664bd0c025SRobert Watson #include <grp.h>
674bd0c025SRobert Watson #include <pwd.h>
684bd0c025SRobert Watson #include <stdio.h>
69ca0716f5SRobert Watson #include <stdlib.h>
70ca0716f5SRobert Watson #include <sysexits.h>
71ca0716f5SRobert Watson #include <string.h>
72ca0716f5SRobert Watson #include <time.h>
73ca0716f5SRobert Watson #include <unistd.h>
74ca0716f5SRobert Watson #include <regex.h>
75ca0716f5SRobert Watson #include <errno.h>
76ca0716f5SRobert Watson 
77ca0716f5SRobert Watson #ifndef HAVE_STRLCPY
78ca0716f5SRobert Watson #include <compat/strlcpy.h>
79ca0716f5SRobert Watson #endif
80ca0716f5SRobert Watson 
81ca0716f5SRobert Watson #include "auditreduce.h"
82ca0716f5SRobert Watson 
83ca0716f5SRobert Watson static TAILQ_HEAD(tailhead, re_entry) re_head =
84ca0716f5SRobert Watson     TAILQ_HEAD_INITIALIZER(re_head);
85ca0716f5SRobert Watson 
86ca0716f5SRobert Watson extern char		*optarg;
87ca0716f5SRobert Watson extern int		 optind, optopt, opterr,optreset;
88ca0716f5SRobert Watson 
89ca0716f5SRobert Watson static au_mask_t	 maskp;		/* Class. */
90ca0716f5SRobert Watson static time_t		 p_atime;	/* Created after this time. */
91ca0716f5SRobert Watson static time_t		 p_btime;	/* Created before this time. */
92ca0716f5SRobert Watson static int		 p_auid;	/* Audit id. */
93ca0716f5SRobert Watson static int		 p_euid;	/* Effective user id. */
94ca0716f5SRobert Watson static int		 p_egid;	/* Effective group id. */
95ca0716f5SRobert Watson static int		 p_rgid;	/* Real group id. */
964bd0c025SRobert Watson static int		 p_ruid;	/* Real user id. */
974bd0c025SRobert Watson static int		 p_subid;	/* Subject id. */
984bd0c025SRobert Watson static const char	*p_zone;	/* Zone. */
994bd0c025SRobert Watson 
1004bd0c025SRobert Watson /*
1014bd0c025SRobert Watson  * Maintain a dynamically sized array of events for -m
1024bd0c025SRobert Watson  */
1034bd0c025SRobert Watson static uint16_t		*p_evec;	/* Event type list */
1044bd0c025SRobert Watson static int		 p_evec_used;	/* Number of events used */
1054bd0c025SRobert Watson static int		 p_evec_alloc;	/* Number of events allocated */
1064bd0c025SRobert Watson 
1074bd0c025SRobert Watson /*
1084bd0c025SRobert Watson  * Following are the objects (-o option) that we can select upon.
1094bd0c025SRobert Watson  */
1104bd0c025SRobert Watson static char	*p_fileobj = NULL;
1114bd0c025SRobert Watson static char	*p_msgqobj = NULL;
1124bd0c025SRobert Watson static char	*p_pidobj = NULL;
1134bd0c025SRobert Watson static char	*p_semobj = NULL;
1144bd0c025SRobert Watson static char	*p_shmobj = NULL;
1154bd0c025SRobert Watson static char	*p_sockobj = NULL;
1164bd0c025SRobert Watson 
1174bd0c025SRobert Watson static uint32_t opttochk = 0;
1184bd0c025SRobert Watson 
1194bd0c025SRobert Watson static int	select_zone(const char *zone, uint32_t *optchkd);
1204bd0c025SRobert Watson 
1214bd0c025SRobert Watson static void
parse_regexp(char * re_string)1224bd0c025SRobert Watson parse_regexp(char *re_string)
1234bd0c025SRobert Watson {
1244bd0c025SRobert Watson 	char *orig, *copy, re_error[64];
1254bd0c025SRobert Watson 	struct re_entry *rep;
1264bd0c025SRobert Watson 	int error, nstrs, i, len;
1274bd0c025SRobert Watson 
1284bd0c025SRobert Watson 	copy = strdup(re_string);
1294bd0c025SRobert Watson 	orig = copy;
1304bd0c025SRobert Watson 	len = strlen(copy);
1314bd0c025SRobert Watson 	for (nstrs = 0, i = 0; i < len; i++) {
1324bd0c025SRobert Watson 		if (copy[i] == ',' && i > 0) {
1334bd0c025SRobert Watson 			if (copy[i - 1] == '\\')
1344bd0c025SRobert Watson 				strlcpy(&copy[i - 1], &copy[i], len);
1354bd0c025SRobert Watson 			else {
1364bd0c025SRobert Watson 				nstrs++;
1374bd0c025SRobert Watson 				copy[i] = '\0';
1384bd0c025SRobert Watson 			}
1394bd0c025SRobert Watson 		}
1404bd0c025SRobert Watson 	}
1414bd0c025SRobert Watson 	TAILQ_INIT(&re_head);
1424bd0c025SRobert Watson 	for (i = 0; i < nstrs + 1; i++) {
143ca0716f5SRobert Watson 		rep = calloc(1, sizeof(*rep));
144ca0716f5SRobert Watson 		if (rep == NULL) {
145ca0716f5SRobert Watson 			(void) fprintf(stderr, "calloc: %s\n",
1464bd0c025SRobert Watson 			    strerror(errno));
147ca0716f5SRobert Watson 			exit(1);
148ca0716f5SRobert Watson 		}
149ca0716f5SRobert Watson 		if (*copy == '~') {
150ca0716f5SRobert Watson 			copy++;
151ca0716f5SRobert Watson 			rep->re_negate = 1;
152ca0716f5SRobert Watson 		}
153ca0716f5SRobert Watson 		rep->re_pattern = strdup(copy);
154ca0716f5SRobert Watson 		error = regcomp(&rep->re_regexp, rep->re_pattern,
155ca0716f5SRobert Watson 		    REG_EXTENDED | REG_NOSUB);
156ca0716f5SRobert Watson 		if (error != 0) {
157ca0716f5SRobert Watson 			regerror(error, &rep->re_regexp, re_error, 64);
158ca0716f5SRobert Watson 			(void) fprintf(stderr, "regcomp: %s\n", re_error);
159ca0716f5SRobert Watson 			exit(1);
160ca0716f5SRobert Watson 		}
161ca0716f5SRobert Watson 		TAILQ_INSERT_TAIL(&re_head, rep, re_glue);
162ca0716f5SRobert Watson 		len = strlen(copy);
163ca0716f5SRobert Watson 		copy += len + 1;
164ca0716f5SRobert Watson 	}
165ca0716f5SRobert Watson 	free(orig);
166ca0716f5SRobert Watson }
167ca0716f5SRobert Watson 
168ca0716f5SRobert Watson static void
usage(const char * msg)169ca0716f5SRobert Watson usage(const char *msg)
170ca0716f5SRobert Watson {
171ca0716f5SRobert Watson 	fprintf(stderr, "%s\n", msg);
172ca0716f5SRobert Watson 	fprintf(stderr, "Usage: auditreduce [options] [file ...]\n");
173ca0716f5SRobert Watson 	fprintf(stderr, "\tOptions are : \n");
174ca0716f5SRobert Watson 	fprintf(stderr, "\t-A : all records\n");
175ca0716f5SRobert Watson 	fprintf(stderr, "\t-a YYYYMMDD[HH[[MM[SS]]] : after date\n");
176ca0716f5SRobert Watson 	fprintf(stderr, "\t-b YYYYMMDD[HH[[MM[SS]]] : before date\n");
177ca0716f5SRobert Watson 	fprintf(stderr, "\t-c <flags> : matching class\n");
178ca0716f5SRobert Watson 	fprintf(stderr, "\t-d YYYYMMDD : on date\n");
179ca0716f5SRobert Watson 	fprintf(stderr, "\t-e <uid|name>  : effective user\n");
180ca0716f5SRobert Watson 	fprintf(stderr, "\t-f <gid|group> : effective group\n");
181ca0716f5SRobert Watson 	fprintf(stderr, "\t-g <gid|group> : real group\n");
182ca0716f5SRobert Watson 	fprintf(stderr, "\t-j <pid> : subject id \n");
183ca0716f5SRobert Watson 	fprintf(stderr, "\t-m <evno|evname> : matching event\n");
184ca0716f5SRobert Watson 	fprintf(stderr, "\t-o objecttype=objectvalue\n");
185ca0716f5SRobert Watson 	fprintf(stderr, "\t\t file=<pathname>\n");
186ca0716f5SRobert Watson 	fprintf(stderr, "\t\t msgqid=<ID>\n");
187ca0716f5SRobert Watson 	fprintf(stderr, "\t\t pid=<ID>\n");
188ca0716f5SRobert Watson 	fprintf(stderr, "\t\t semid=<ID>\n");
189ca0716f5SRobert Watson 	fprintf(stderr, "\t\t shmid=<ID>\n");
190ca0716f5SRobert Watson 	fprintf(stderr, "\t-r <uid|name> : real user\n");
191ca0716f5SRobert Watson 	fprintf(stderr, "\t-u <uid|name> : audit user\n");
192ca0716f5SRobert Watson 	fprintf(stderr, "\t-v : select non-matching records\n");
193ca0716f5SRobert Watson 	fprintf(stderr, "\t-z <zone> : zone name\n");
194ca0716f5SRobert Watson 	exit(EX_USAGE);
195ca0716f5SRobert Watson }
196ca0716f5SRobert Watson 
197ca0716f5SRobert Watson /*
198ca0716f5SRobert Watson  * Check if the given auid matches the selection criteria.
199ca0716f5SRobert Watson  */
200ca0716f5SRobert Watson static int
select_auid(int au)201ca0716f5SRobert Watson select_auid(int au)
202ca0716f5SRobert Watson {
203ca0716f5SRobert Watson 
204ca0716f5SRobert Watson 	/* Check if we want to select on auid. */
205ca0716f5SRobert Watson 	if (ISOPTSET(opttochk, OPT_u)) {
206ca0716f5SRobert Watson 		if (au != p_auid)
207ca0716f5SRobert Watson 			return (0);
208ca0716f5SRobert Watson 	}
209ca0716f5SRobert Watson 	return (1);
210ca0716f5SRobert Watson }
211ca0716f5SRobert Watson 
212ca0716f5SRobert Watson /*
213ca0716f5SRobert Watson  * Check if the given euid matches the selection criteria.
214ca0716f5SRobert Watson  */
215ca0716f5SRobert Watson static int
select_euid(int euser)216ca0716f5SRobert Watson select_euid(int euser)
217ca0716f5SRobert Watson {
218ca0716f5SRobert Watson 
219ca0716f5SRobert Watson 	/* Check if we want to select on euid. */
220ca0716f5SRobert Watson 	if (ISOPTSET(opttochk, OPT_e)) {
221ca0716f5SRobert Watson 		if (euser != p_euid)
222ca0716f5SRobert Watson 			return (0);
223ca0716f5SRobert Watson 	}
224ca0716f5SRobert Watson 	return (1);
225ca0716f5SRobert Watson }
226ca0716f5SRobert Watson 
227ca0716f5SRobert Watson /*
228ca0716f5SRobert Watson  * Check if the given egid matches the selection criteria.
229ca0716f5SRobert Watson  */
230ca0716f5SRobert Watson static int
select_egid(int egrp)231ca0716f5SRobert Watson select_egid(int egrp)
232ca0716f5SRobert Watson {
233ca0716f5SRobert Watson 
234ca0716f5SRobert Watson 	/* Check if we want to select on egid. */
235ca0716f5SRobert Watson 	if (ISOPTSET(opttochk, OPT_f)) {
236ca0716f5SRobert Watson 		if (egrp != p_egid)
237ca0716f5SRobert Watson 			return (0);
238ca0716f5SRobert Watson 	}
239ca0716f5SRobert Watson 	return (1);
240ca0716f5SRobert Watson }
241ca0716f5SRobert Watson 
242ca0716f5SRobert Watson /*
243ca0716f5SRobert Watson  * Check if the given rgid matches the selection criteria.
244ca0716f5SRobert Watson  */
245ca0716f5SRobert Watson static int
select_rgid(int grp)246ca0716f5SRobert Watson select_rgid(int grp)
247ca0716f5SRobert Watson {
248ca0716f5SRobert Watson 
249ca0716f5SRobert Watson 	/* Check if we want to select on rgid. */
250ca0716f5SRobert Watson 	if (ISOPTSET(opttochk, OPT_g)) {
251ca0716f5SRobert Watson 		if (grp != p_rgid)
252ca0716f5SRobert Watson 			return (0);
253ca0716f5SRobert Watson 	}
254ca0716f5SRobert Watson 	return (1);
255ca0716f5SRobert Watson }
256ca0716f5SRobert Watson 
257ca0716f5SRobert Watson /*
258ca0716f5SRobert Watson  * Check if the given ruid matches the selection criteria.
259ca0716f5SRobert Watson  */
260ca0716f5SRobert Watson static int
select_ruid(int user)261ca0716f5SRobert Watson select_ruid(int user)
262ca0716f5SRobert Watson {
263ca0716f5SRobert Watson 
264ca0716f5SRobert Watson 	/* Check if we want to select on rgid. */
265ca0716f5SRobert Watson 	if (ISOPTSET(opttochk, OPT_r)) {
266ca0716f5SRobert Watson 		if (user != p_ruid)
267ca0716f5SRobert Watson 			return (0);
268ca0716f5SRobert Watson 	}
269ca0716f5SRobert Watson 	return (1);
270ca0716f5SRobert Watson }
271ca0716f5SRobert Watson 
272ca0716f5SRobert Watson /*
273ca0716f5SRobert Watson  * Check if the given subject id (pid) matches the selection criteria.
274ca0716f5SRobert Watson  */
275ca0716f5SRobert Watson static int
select_subid(int subid)276ca0716f5SRobert Watson select_subid(int subid)
277ca0716f5SRobert Watson {
278ca0716f5SRobert Watson 
279ca0716f5SRobert Watson 	/* Check if we want to select on subject uid. */
280ca0716f5SRobert Watson 	if (ISOPTSET(opttochk, OPT_j)) {
281ca0716f5SRobert Watson 		if (subid != p_subid)
282ca0716f5SRobert Watson 			return (0);
283ca0716f5SRobert Watson 	}
284ca0716f5SRobert Watson 	return (1);
285ca0716f5SRobert Watson }
286ca0716f5SRobert Watson 
287ca0716f5SRobert Watson 
288ca0716f5SRobert Watson /*
289ca0716f5SRobert Watson  * Check if object's pid maches the given pid.
290ca0716f5SRobert Watson  */
291ca0716f5SRobert Watson static int
select_pidobj(uint32_t pid)292ca0716f5SRobert Watson select_pidobj(uint32_t pid)
293ca0716f5SRobert Watson {
294ca0716f5SRobert Watson 
295ca0716f5SRobert Watson 	if (ISOPTSET(opttochk, OPT_op)) {
296ca0716f5SRobert Watson 		if (pid != (uint32_t)strtol(p_pidobj, (char **)NULL, 10))
297ca0716f5SRobert Watson 			return (0);
298ca0716f5SRobert Watson 	}
299ca0716f5SRobert Watson 	return (1);
300ca0716f5SRobert Watson }
301ca0716f5SRobert Watson 
302ca0716f5SRobert Watson /*
303ca0716f5SRobert Watson  * Check if the given ipc object with the given type matches the selection
304ca0716f5SRobert Watson  * criteria.
305ca0716f5SRobert Watson  */
306ca0716f5SRobert Watson static int
select_ipcobj(u_char type,uint32_t id,uint32_t * optchkd)307ca0716f5SRobert Watson select_ipcobj(u_char type, uint32_t id, uint32_t *optchkd)
308ca0716f5SRobert Watson {
309ca0716f5SRobert Watson 
310ca0716f5SRobert Watson 	if (type == AT_IPC_MSG) {
311ca0716f5SRobert Watson 		SETOPT((*optchkd), OPT_om);
312ca0716f5SRobert Watson 		if (ISOPTSET(opttochk, OPT_om)) {
313ca0716f5SRobert Watson 			if (id != (uint32_t)strtol(p_msgqobj, (char **)NULL,
314ca0716f5SRobert Watson 			    10))
315ca0716f5SRobert Watson 				return (0);
316ca0716f5SRobert Watson 		}
317ca0716f5SRobert Watson 		return (1);
318ca0716f5SRobert Watson 	} else if (type == AT_IPC_SEM) {
319ca0716f5SRobert Watson 		SETOPT((*optchkd), OPT_ose);
3204bd0c025SRobert Watson 		if (ISOPTSET(opttochk, OPT_ose)) {
3214bd0c025SRobert Watson 			if (id != (uint32_t)strtol(p_semobj, (char **)NULL, 10))
322ca0716f5SRobert Watson 				return (0);
323ca0716f5SRobert Watson 		}
3244bd0c025SRobert Watson 		return (1);
325ca0716f5SRobert Watson 	} else if (type == AT_IPC_SHM) {
3264bd0c025SRobert Watson 		SETOPT((*optchkd), OPT_osh);
3274bd0c025SRobert Watson 		if (ISOPTSET(opttochk, OPT_osh)) {
3284bd0c025SRobert Watson 			if (id != (uint32_t)strtol(p_shmobj, (char **)NULL, 10))
3294bd0c025SRobert Watson 				return (0);
3304bd0c025SRobert Watson 		}
331ca0716f5SRobert Watson 		return (1);
332ca0716f5SRobert Watson 	}
3334bd0c025SRobert Watson 
334ca0716f5SRobert Watson 	/* Unknown type -- filter if *any* ipc filtering is required. */
335ca0716f5SRobert Watson 	if (ISOPTSET(opttochk, OPT_om) || ISOPTSET(opttochk, OPT_ose)
336ca0716f5SRobert Watson 	    || ISOPTSET(opttochk, OPT_osh))
337ca0716f5SRobert Watson 		return (0);
338ca0716f5SRobert Watson 
339ca0716f5SRobert Watson 	return (1);
340ca0716f5SRobert Watson }
341ca0716f5SRobert Watson 
342ca0716f5SRobert Watson 
343ca0716f5SRobert Watson /*
344ca0716f5SRobert Watson  * Check if the file name matches selection criteria.
345ca0716f5SRobert Watson  */
346ca0716f5SRobert Watson static int
select_filepath(char * path,uint32_t * optchkd)347ca0716f5SRobert Watson select_filepath(char *path, uint32_t *optchkd)
348ca0716f5SRobert Watson {
349ca0716f5SRobert Watson 	struct re_entry *rep;
350ca0716f5SRobert Watson 	int match;
351ca0716f5SRobert Watson 
352ca0716f5SRobert Watson 	SETOPT((*optchkd), OPT_of);
353ca0716f5SRobert Watson 	match = 1;
354ca0716f5SRobert Watson 	if (ISOPTSET(opttochk, OPT_of)) {
355ca0716f5SRobert Watson 		match = 0;
356ca0716f5SRobert Watson 		TAILQ_FOREACH(rep, &re_head, re_glue) {
357ca0716f5SRobert Watson 			if (regexec(&rep->re_regexp, path, 0, NULL,
358ca0716f5SRobert Watson 			    0) != REG_NOMATCH)
359ca0716f5SRobert Watson 				return (!rep->re_negate);
360ca0716f5SRobert Watson 		}
361ca0716f5SRobert Watson 	}
362ca0716f5SRobert Watson 	return (match);
363ca0716f5SRobert Watson }
364ca0716f5SRobert Watson 
365ca0716f5SRobert Watson /*
366ca0716f5SRobert Watson  * Returns 1 if the following pass the selection rules:
367ca0716f5SRobert Watson  *
368ca0716f5SRobert Watson  * before-time,
369ca0716f5SRobert Watson  * after time,
370ca0716f5SRobert Watson  * date,
371ca0716f5SRobert Watson  * class,
372ca0716f5SRobert Watson  * event
373ca0716f5SRobert Watson  */
374ca0716f5SRobert Watson static int
select_hdr32(tokenstr_t tok,uint32_t * optchkd)375ca0716f5SRobert Watson select_hdr32(tokenstr_t tok, uint32_t *optchkd)
376ca0716f5SRobert Watson {
377ca0716f5SRobert Watson 	uint16_t *ev;
378ca0716f5SRobert Watson 	int match;
379ca0716f5SRobert Watson 
380ca0716f5SRobert Watson 	SETOPT((*optchkd), (OPT_A | OPT_a | OPT_b | OPT_c | OPT_m | OPT_v));
381ca0716f5SRobert Watson 
382ca0716f5SRobert Watson 	/* The A option overrides a, b and d. */
383ca0716f5SRobert Watson 	if (!ISOPTSET(opttochk, OPT_A)) {
384ca0716f5SRobert Watson 		if (ISOPTSET(opttochk, OPT_a)) {
385ca0716f5SRobert Watson 			if (difftime((time_t)tok.tt.hdr32.s, p_atime) < 0) {
386ca0716f5SRobert Watson 				/* Record was created before p_atime. */
3874bd0c025SRobert Watson 				return (0);
3884bd0c025SRobert Watson 			}
3894bd0c025SRobert Watson 		}
3904bd0c025SRobert Watson 
3914bd0c025SRobert Watson 		if (ISOPTSET(opttochk, OPT_b)) {
3924bd0c025SRobert Watson 			if (difftime(p_btime, (time_t)tok.tt.hdr32.s) < 0) {
3934bd0c025SRobert Watson 				/* Record was created after p_btime. */
3944bd0c025SRobert Watson 				return (0);
3954bd0c025SRobert Watson 			}
3964bd0c025SRobert Watson 		}
3974bd0c025SRobert Watson 	}
3984bd0c025SRobert Watson 
3994bd0c025SRobert Watson 	if (ISOPTSET(opttochk, OPT_c)) {
4004bd0c025SRobert Watson 		/*
4014bd0c025SRobert Watson 		 * Check if the classes represented by the event matches
4024bd0c025SRobert Watson 		 * given class.
4034bd0c025SRobert Watson 		 */
4044bd0c025SRobert Watson 		if (au_preselect(tok.tt.hdr32.e_type, &maskp, AU_PRS_BOTH,
405ca0716f5SRobert Watson 		    AU_PRS_USECACHE) != 1)
406ca0716f5SRobert Watson 			return (0);
407ca0716f5SRobert Watson 	}
408ca0716f5SRobert Watson 
409ca0716f5SRobert Watson 	/* Check if event matches. */
410ca0716f5SRobert Watson 	if (ISOPTSET(opttochk, OPT_m)) {
411ca0716f5SRobert Watson 		match = 0;
412ca0716f5SRobert Watson 		for (ev = p_evec; ev < &p_evec[p_evec_used]; ev++)
413ca0716f5SRobert Watson 			if (tok.tt.hdr32.e_type == *ev)
414ca0716f5SRobert Watson 				match = 1;
415ca0716f5SRobert Watson 		if (match == 0)
416ca0716f5SRobert Watson 			return (0);
417ca0716f5SRobert Watson 	}
418ca0716f5SRobert Watson 
419ca0716f5SRobert Watson 	return (1);
420ca0716f5SRobert Watson }
421ca0716f5SRobert Watson 
422ca0716f5SRobert Watson static int
select_return32(tokenstr_t tok_ret32,tokenstr_t tok_hdr32,uint32_t * optchkd)423ca0716f5SRobert Watson select_return32(tokenstr_t tok_ret32, tokenstr_t tok_hdr32, uint32_t *optchkd)
424ca0716f5SRobert Watson {
425ca0716f5SRobert Watson 	int sorf;
426ca0716f5SRobert Watson 
427ca0716f5SRobert Watson 	SETOPT((*optchkd), (OPT_c));
428ca0716f5SRobert Watson 	if (tok_ret32.tt.ret32.status == 0)
429ca0716f5SRobert Watson 		sorf = AU_PRS_SUCCESS;
430ca0716f5SRobert Watson 	else
431ca0716f5SRobert Watson 		sorf = AU_PRS_FAILURE;
432ca0716f5SRobert Watson 	if (ISOPTSET(opttochk, OPT_c)) {
433ca0716f5SRobert Watson 		if (au_preselect(tok_hdr32.tt.hdr32.e_type, &maskp, sorf,
434ca0716f5SRobert Watson 		    AU_PRS_USECACHE) != 1)
435ca0716f5SRobert Watson 			return (0);
436ca0716f5SRobert Watson 	}
437ca0716f5SRobert Watson 	return (1);
438ca0716f5SRobert Watson }
439ca0716f5SRobert Watson 
440ca0716f5SRobert Watson /*
441ca0716f5SRobert Watson  * Return 1 if checks for the the following succeed
442ca0716f5SRobert Watson  * auid,
443ca0716f5SRobert Watson  * euid,
444ca0716f5SRobert Watson  * egid,
445ca0716f5SRobert Watson  * rgid,
446ca0716f5SRobert Watson  * ruid,
447ca0716f5SRobert Watson  * process id
448ca0716f5SRobert Watson  */
449ca0716f5SRobert Watson static int
select_proc32(tokenstr_t tok,uint32_t * optchkd)450ca0716f5SRobert Watson select_proc32(tokenstr_t tok, uint32_t *optchkd)
451ca0716f5SRobert Watson {
452ca0716f5SRobert Watson 
453ca0716f5SRobert Watson 	SETOPT((*optchkd), (OPT_u | OPT_e | OPT_f | OPT_g | OPT_r | OPT_op));
454ca0716f5SRobert Watson 
455ca0716f5SRobert Watson 	if (!select_auid(tok.tt.proc32.auid))
456ca0716f5SRobert Watson 		return (0);
457ca0716f5SRobert Watson 	if (!select_euid(tok.tt.proc32.euid))
458ca0716f5SRobert Watson 		return (0);
459ca0716f5SRobert Watson 	if (!select_egid(tok.tt.proc32.egid))
460ca0716f5SRobert Watson 		return (0);
461ca0716f5SRobert Watson 	if (!select_rgid(tok.tt.proc32.rgid))
462ca0716f5SRobert Watson 		return (0);
463ca0716f5SRobert Watson 	if (!select_ruid(tok.tt.proc32.ruid))
464ca0716f5SRobert Watson 		return (0);
465ca0716f5SRobert Watson 	if (!select_pidobj(tok.tt.proc32.pid))
466ca0716f5SRobert Watson 		return (0);
467ca0716f5SRobert Watson 	return (1);
468ca0716f5SRobert Watson }
469ca0716f5SRobert Watson 
470ca0716f5SRobert Watson /*
471ca0716f5SRobert Watson  * Return 1 if checks for the the following succeed
4724bd0c025SRobert Watson  * auid,
473ca0716f5SRobert Watson  * euid,
474ca0716f5SRobert Watson  * egid,
475ca0716f5SRobert Watson  * rgid,
476ca0716f5SRobert Watson  * ruid,
477ca0716f5SRobert Watson  * subject id
478ca0716f5SRobert Watson  */
479ca0716f5SRobert Watson static int
select_subj32(tokenstr_t tok,uint32_t * optchkd)480ca0716f5SRobert Watson select_subj32(tokenstr_t tok, uint32_t *optchkd)
481ca0716f5SRobert Watson {
482ca0716f5SRobert Watson 
483ca0716f5SRobert Watson 	SETOPT((*optchkd), (OPT_u | OPT_e | OPT_f | OPT_g | OPT_r | OPT_j));
484ca0716f5SRobert Watson 
485ca0716f5SRobert Watson 	if (!select_auid(tok.tt.subj32.auid))
486ca0716f5SRobert Watson 		return (0);
487ca0716f5SRobert Watson 	if (!select_euid(tok.tt.subj32.euid))
488ca0716f5SRobert Watson 		return (0);
489ca0716f5SRobert Watson 	if (!select_egid(tok.tt.subj32.egid))
490ca0716f5SRobert Watson 		return (0);
491ca0716f5SRobert Watson 	if (!select_rgid(tok.tt.subj32.rgid))
492ca0716f5SRobert Watson 		return (0);
493ca0716f5SRobert Watson 	if (!select_ruid(tok.tt.subj32.ruid))
494ca0716f5SRobert Watson 		return (0);
495ca0716f5SRobert Watson 	if (!select_subid(tok.tt.subj32.pid))
496ca0716f5SRobert Watson 		return (0);
497ca0716f5SRobert Watson 	return (1);
498ca0716f5SRobert Watson }
499ca0716f5SRobert Watson 
500ca0716f5SRobert Watson /*
5014bd0c025SRobert Watson  * Check if the given zone matches the selection criteria.
5024bd0c025SRobert Watson   */
503ca0716f5SRobert Watson static int
select_zone(const char * zone,uint32_t * optchkd)504ca0716f5SRobert Watson select_zone(const char *zone, uint32_t *optchkd)
505ca0716f5SRobert Watson {
506ca0716f5SRobert Watson 
507ca0716f5SRobert Watson 	SETOPT((*optchkd), OPT_z);
508ca0716f5SRobert Watson 	if (ISOPTSET(opttochk, OPT_z) && p_zone != NULL) {
509ca0716f5SRobert Watson 		if (fnmatch(p_zone, zone, FNM_PATHNAME) != 0)
510ca0716f5SRobert Watson 			return (0);
511ca0716f5SRobert Watson 	}
512ca0716f5SRobert Watson 	return (1);
513ca0716f5SRobert Watson }
514ca0716f5SRobert Watson 
515ca0716f5SRobert Watson /*
516ca0716f5SRobert Watson  * Read each record from the audit trail.  Check if it is selected after
517ca0716f5SRobert Watson  * passing through each of the options
518ca0716f5SRobert Watson  */
519ca0716f5SRobert Watson static int
select_records(FILE * fp)520ca0716f5SRobert Watson select_records(FILE *fp)
521ca0716f5SRobert Watson {
522ca0716f5SRobert Watson 	tokenstr_t tok_hdr32_copy;
523ca0716f5SRobert Watson 	u_char *buf;
524ca0716f5SRobert Watson 	tokenstr_t tok;
525ca0716f5SRobert Watson 	int reclen;
526ca0716f5SRobert Watson 	int bytesread;
527ca0716f5SRobert Watson 	int selected;
528ca0716f5SRobert Watson 	uint32_t optchkd;
529ca0716f5SRobert Watson 	int print;
530ca0716f5SRobert Watson 
5314bd0c025SRobert Watson 	int err = 0;
5324bd0c025SRobert Watson 	while ((reclen = au_read_rec(fp, &buf)) != -1) {
5334bd0c025SRobert Watson 		optchkd = 0;
5344bd0c025SRobert Watson 		bytesread = 0;
5354bd0c025SRobert Watson 		selected = 1;
536ca0716f5SRobert Watson 		while ((selected == 1) && (bytesread < reclen)) {
537ca0716f5SRobert Watson 			if (-1 == au_fetch_tok(&tok, buf + bytesread,
538ca0716f5SRobert Watson 			    reclen - bytesread)) {
539ca0716f5SRobert Watson 				/* Is this an incomplete record? */
540ca0716f5SRobert Watson 				err = 1;
541ca0716f5SRobert Watson 				break;
542ca0716f5SRobert Watson 			}
543ca0716f5SRobert Watson 
544ca0716f5SRobert Watson 			/*
545ca0716f5SRobert Watson 			 * For each token type we have have different
546ca0716f5SRobert Watson 			 * selection criteria.
547ca0716f5SRobert Watson 			 */
548ca0716f5SRobert Watson 			switch(tok.id) {
549ca0716f5SRobert Watson 			case AUT_HEADER32:
550ca0716f5SRobert Watson 					selected = select_hdr32(tok,
551ca0716f5SRobert Watson 					    &optchkd);
552ca0716f5SRobert Watson 					bcopy(&tok, &tok_hdr32_copy,
553ca0716f5SRobert Watson 					    sizeof(tok));
554ca0716f5SRobert Watson 					break;
555ca0716f5SRobert Watson 
556ca0716f5SRobert Watson 			case AUT_PROCESS32:
557ca0716f5SRobert Watson 					selected = select_proc32(tok,
558ca0716f5SRobert Watson 					    &optchkd);
559ca0716f5SRobert Watson 					break;
560ca0716f5SRobert Watson 
561ca0716f5SRobert Watson 			case AUT_SUBJECT32:
562ca0716f5SRobert Watson 					selected = select_subj32(tok,
563ca0716f5SRobert Watson 					    &optchkd);
564ca0716f5SRobert Watson 					break;
565ca0716f5SRobert Watson 
566ca0716f5SRobert Watson 			case AUT_IPC:
567ca0716f5SRobert Watson 					selected = select_ipcobj(
568ca0716f5SRobert Watson 					    tok.tt.ipc.type, tok.tt.ipc.id,
569ca0716f5SRobert Watson 					    &optchkd);
570ca0716f5SRobert Watson 					break;
571ca0716f5SRobert Watson 
572ca0716f5SRobert Watson 			case AUT_PATH:
573ca0716f5SRobert Watson 					selected = select_filepath(
574ca0716f5SRobert Watson 					    tok.tt.path.path, &optchkd);
575ca0716f5SRobert Watson 					break;
576ca0716f5SRobert Watson 
577ca0716f5SRobert Watson 			case AUT_RETURN32:
578ca0716f5SRobert Watson 				selected = select_return32(tok,
579ca0716f5SRobert Watson 				    tok_hdr32_copy, &optchkd);
580ca0716f5SRobert Watson 				break;
581ca0716f5SRobert Watson 
582ca0716f5SRobert Watson 			case AUT_ZONENAME:
583ca0716f5SRobert Watson 				selected = select_zone(tok.tt.zonename.zonename, &optchkd);
5844bd0c025SRobert Watson 				break;
585ca0716f5SRobert Watson 
586ca0716f5SRobert Watson 			default:
587ca0716f5SRobert Watson 				break;
588ca0716f5SRobert Watson 			}
589ca0716f5SRobert Watson 			bytesread += tok.len;
590ca0716f5SRobert Watson 		}
591ca0716f5SRobert Watson 		/* Check if all the options were matched. */
592ca0716f5SRobert Watson 		print = ((selected == 1) && (!err) && (!(opttochk & ~optchkd)));
593ca0716f5SRobert Watson 		if (ISOPTSET(opttochk, OPT_v))
594ca0716f5SRobert Watson 			print = !print;
595ca0716f5SRobert Watson 		if (print)
596ca0716f5SRobert Watson 			(void) fwrite(buf, 1, reclen, stdout);
597ca0716f5SRobert Watson 		free(buf);
598ca0716f5SRobert Watson 	}
599ca0716f5SRobert Watson 	return (0);
600ca0716f5SRobert Watson }
601ca0716f5SRobert Watson 
602ca0716f5SRobert Watson /*
603ca0716f5SRobert Watson  * The -o option has the form object_type=object_value.  Identify the object
604ca0716f5SRobert Watson  * components.
605ca0716f5SRobert Watson  */
606ca0716f5SRobert Watson static void
parse_object_type(char * name,char * val)607ca0716f5SRobert Watson parse_object_type(char *name, char *val)
608ca0716f5SRobert Watson {
609ca0716f5SRobert Watson 	if (val == NULL)
610ca0716f5SRobert Watson 		return;
611ca0716f5SRobert Watson 
612ca0716f5SRobert Watson 	if (!strcmp(name, FILEOBJ)) {
613ca0716f5SRobert Watson 		p_fileobj = val;
614ca0716f5SRobert Watson 		parse_regexp(val);
61523bf6e20SRobert Watson 		SETOPT(opttochk, OPT_of);
616ca0716f5SRobert Watson 	} else if (!strcmp(name, MSGQIDOBJ)) {
617ca0716f5SRobert Watson 		p_msgqobj = val;
618ca0716f5SRobert Watson 		SETOPT(opttochk, OPT_om);
619ca0716f5SRobert Watson 	} else if (!strcmp(name, PIDOBJ)) {
620ca0716f5SRobert Watson 		p_pidobj = val;
621ca0716f5SRobert Watson 		SETOPT(opttochk, OPT_op);
622ca0716f5SRobert Watson 	} else if (!strcmp(name, SEMIDOBJ)) {
623ca0716f5SRobert Watson 		p_semobj = val;
624ca0716f5SRobert Watson 		SETOPT(opttochk, OPT_ose);
625ca0716f5SRobert Watson 	} else if (!strcmp(name, SHMIDOBJ)) {
626ca0716f5SRobert Watson 		p_shmobj = val;
627ca0716f5SRobert Watson 		SETOPT(opttochk, OPT_osh);
628ca0716f5SRobert Watson 	} else if (!strcmp(name, SOCKOBJ)) {
629ca0716f5SRobert Watson 		p_sockobj = val;
630ca0716f5SRobert Watson 		SETOPT(opttochk, OPT_oso);
631ca0716f5SRobert Watson 	} else
6320814440eSRobert Watson 		usage("unknown value for -o");
633ca0716f5SRobert Watson }
634ca0716f5SRobert Watson 
635ca0716f5SRobert Watson int
main(int argc,char ** argv)636ca0716f5SRobert Watson main(int argc, char **argv)
637ca0716f5SRobert Watson {
638ca0716f5SRobert Watson 	struct group *grp;
639ca0716f5SRobert Watson 	struct passwd *pw;
640ca0716f5SRobert Watson 	struct tm tm;
641ca0716f5SRobert Watson 	au_event_t *n;
642ca0716f5SRobert Watson 	FILE *fp;
643ca0716f5SRobert Watson 	int i;
644ca0716f5SRobert Watson 	char *objval, *converr;
6450814440eSRobert Watson 	int ch;
646ca0716f5SRobert Watson 	char timestr[128];
647ca0716f5SRobert Watson 	char *fname;
648ca0716f5SRobert Watson 	uint16_t *etp;
649ca0716f5SRobert Watson #ifdef HAVE_CAP_ENTER
650ca0716f5SRobert Watson 	int retval, status;
651ca0716f5SRobert Watson 	pid_t childpid, pid;
652ca0716f5SRobert Watson #endif
653ca0716f5SRobert Watson 
654ca0716f5SRobert Watson 	converr = NULL;
655ca0716f5SRobert Watson 
656ca0716f5SRobert Watson 	while ((ch = getopt(argc, argv, "Aa:b:c:d:e:f:g:j:m:o:r:u:vz:")) != -1) {
657ca0716f5SRobert Watson 		switch(ch) {
658ca0716f5SRobert Watson 		case 'A':
659ca0716f5SRobert Watson 			SETOPT(opttochk, OPT_A);
660ca0716f5SRobert Watson 			break;
661ca0716f5SRobert Watson 
662ca0716f5SRobert Watson 		case 'a':
663ca0716f5SRobert Watson 			if (ISOPTSET(opttochk, OPT_a)) {
664ca0716f5SRobert Watson 				usage("d is exclusive with a and b");
665ca0716f5SRobert Watson 			}
6660814440eSRobert Watson 			SETOPT(opttochk, OPT_a);
667ca0716f5SRobert Watson 			bzero(&tm, sizeof(tm));
668ca0716f5SRobert Watson 			strptime(optarg, "%Y%m%d%H%M%S", &tm);
669ca0716f5SRobert Watson 			strftime(timestr, sizeof(timestr), "%Y%m%d%H%M%S",
670ca0716f5SRobert Watson 			    &tm);
671ca0716f5SRobert Watson 			/* fprintf(stderr, "Time converted = %s\n", timestr); */
672ca0716f5SRobert Watson 			p_atime = mktime(&tm);
673ca0716f5SRobert Watson 			break;
674ca0716f5SRobert Watson 
675ca0716f5SRobert Watson 		case 'b':
676ca0716f5SRobert Watson 			if (ISOPTSET(opttochk, OPT_b)) {
677ca0716f5SRobert Watson 				usage("d is exclusive with a and b");
678ca0716f5SRobert Watson 			}
679ca0716f5SRobert Watson 			SETOPT(opttochk, OPT_b);
680ca0716f5SRobert Watson 			bzero(&tm, sizeof(tm));
681ca0716f5SRobert Watson 			strptime(optarg, "%Y%m%d%H%M%S", &tm);
682ca0716f5SRobert Watson 			strftime(timestr, sizeof(timestr), "%Y%m%d%H%M%S",
683ca0716f5SRobert Watson 			    &tm);
684ca0716f5SRobert Watson 			/* fprintf(stderr, "Time converted = %s\n", timestr); */
685ca0716f5SRobert Watson 			p_btime = mktime(&tm);
686ca0716f5SRobert Watson 			break;
687ca0716f5SRobert Watson 
688ca0716f5SRobert Watson 		case 'c':
689ca0716f5SRobert Watson 			if (0 != getauditflagsbin(optarg, &maskp)) {
690ca0716f5SRobert Watson 				/* Incorrect class */
691ca0716f5SRobert Watson 				usage("Incorrect class");
692ca0716f5SRobert Watson 			}
693ca0716f5SRobert Watson 			SETOPT(opttochk, OPT_c);
694ca0716f5SRobert Watson 			break;
695ca0716f5SRobert Watson 
696ca0716f5SRobert Watson 		case 'd':
697ca0716f5SRobert Watson 			if (ISOPTSET(opttochk, OPT_b) || ISOPTSET(opttochk,
698ca0716f5SRobert Watson 			    OPT_a))
699ca0716f5SRobert Watson 				usage("'d' is exclusive with 'a' and 'b'");
700ca0716f5SRobert Watson 			SETOPT(opttochk, OPT_d);
701ca0716f5SRobert Watson 			bzero(&tm, sizeof(tm));
702ca0716f5SRobert Watson 			strptime(optarg, "%Y%m%d", &tm);
703ca0716f5SRobert Watson 			strftime(timestr, sizeof(timestr), "%Y%m%d", &tm);
704ca0716f5SRobert Watson 			/* fprintf(stderr, "Time converted = %s\n", timestr); */
705ca0716f5SRobert Watson 			p_atime = mktime(&tm);
706ca0716f5SRobert Watson 			tm.tm_hour = 23;
707ca0716f5SRobert Watson 			tm.tm_min = 59;
708ca0716f5SRobert Watson 			tm.tm_sec = 59;
709ca0716f5SRobert Watson 			strftime(timestr, sizeof(timestr), "%Y%m%d", &tm);
710ca0716f5SRobert Watson 			/* fprintf(stderr, "Time converted = %s\n", timestr); */
711ca0716f5SRobert Watson 			p_btime = mktime(&tm);
712ca0716f5SRobert Watson 			break;
713ca0716f5SRobert Watson 
714ca0716f5SRobert Watson 		case 'e':
715ca0716f5SRobert Watson 			p_euid = strtol(optarg, &converr, 10);
716ca0716f5SRobert Watson 			if (*converr != '\0') {
717ca0716f5SRobert Watson 				/* Try the actual name */
718ca0716f5SRobert Watson 				if ((pw = getpwnam(optarg)) == NULL)
719ca0716f5SRobert Watson 					break;
720ca0716f5SRobert Watson 				p_euid = pw->pw_uid;
721ca0716f5SRobert Watson 			}
722ca0716f5SRobert Watson 			SETOPT(opttochk, OPT_e);
723ca0716f5SRobert Watson 			break;
724ca0716f5SRobert Watson 
725ca0716f5SRobert Watson 		case 'f':
726ca0716f5SRobert Watson 			p_egid = strtol(optarg, &converr, 10);
727ca0716f5SRobert Watson 			if (*converr != '\0') {
728ca0716f5SRobert Watson 				/* Try actual group name. */
729ca0716f5SRobert Watson 				if ((grp = getgrnam(optarg)) == NULL)
730ca0716f5SRobert Watson 					break;
731ca0716f5SRobert Watson 				p_egid = grp->gr_gid;
732ca0716f5SRobert Watson 			}
733ca0716f5SRobert Watson 			SETOPT(opttochk, OPT_f);
734ca0716f5SRobert Watson 			break;
735ca0716f5SRobert Watson 
736ca0716f5SRobert Watson 		case 'g':
737ca0716f5SRobert Watson 			p_rgid = strtol(optarg, &converr, 10);
738ca0716f5SRobert Watson 			if (*converr != '\0') {
739ca0716f5SRobert Watson 				/* Try actual group name. */
740ca0716f5SRobert Watson 				if ((grp = getgrnam(optarg)) == NULL)
741ca0716f5SRobert Watson 					break;
742ca0716f5SRobert Watson 				p_rgid = grp->gr_gid;
743ca0716f5SRobert Watson 			}
744ca0716f5SRobert Watson 			SETOPT(opttochk, OPT_g);
745ca0716f5SRobert Watson 			break;
746ca0716f5SRobert Watson 
747ca0716f5SRobert Watson 		case 'j':
748ca0716f5SRobert Watson 			p_subid = strtol(optarg, (char **)NULL, 10);
749ca0716f5SRobert Watson 			SETOPT(opttochk, OPT_j);
750ca0716f5SRobert Watson 			break;
751ca0716f5SRobert Watson 
752ca0716f5SRobert Watson 		case 'm':
753ca0716f5SRobert Watson 			if (p_evec == NULL) {
754ca0716f5SRobert Watson 				p_evec_alloc = 32;
755ca0716f5SRobert Watson 				p_evec = malloc(sizeof(*etp) * p_evec_alloc);
756ca0716f5SRobert Watson 				if (p_evec == NULL)
757ca0716f5SRobert Watson 					err(1, "malloc");
758ca0716f5SRobert Watson 			} else if (p_evec_alloc == p_evec_used) {
759ca0716f5SRobert Watson 				p_evec_alloc <<= 1;
760ca0716f5SRobert Watson 				p_evec = realloc(p_evec,
761ca0716f5SRobert Watson 				    sizeof(*p_evec) * p_evec_alloc);
762ca0716f5SRobert Watson 				if (p_evec == NULL)
763ca0716f5SRobert Watson 					err(1, "realloc");
764ca0716f5SRobert Watson 			}
765ca0716f5SRobert Watson 			etp = &p_evec[p_evec_used++];
7664bd0c025SRobert Watson 			*etp = strtol(optarg, (char **)NULL, 10);
7674bd0c025SRobert Watson 			if (*etp == 0) {
7684bd0c025SRobert Watson 				/* Could be the string representation. */
7694bd0c025SRobert Watson 				n = getauevnonam(optarg);
7704bd0c025SRobert Watson 				if (n == NULL)
7714bd0c025SRobert Watson 					usage("Incorrect event name");
772ca0716f5SRobert Watson 				*etp = *n;
773ca0716f5SRobert Watson 			}
774ca0716f5SRobert Watson 			SETOPT(opttochk, OPT_m);
775ca0716f5SRobert Watson 			break;
776ca0716f5SRobert Watson 
777ca0716f5SRobert Watson 		case 'o':
778ca0716f5SRobert Watson 			objval = strchr(optarg, '=');
779ca0716f5SRobert Watson 			if (objval != NULL) {
780ca0716f5SRobert Watson 				*objval = '\0';
781ca0716f5SRobert Watson 				objval += 1;
782ca0716f5SRobert Watson 				parse_object_type(optarg, objval);
783ca0716f5SRobert Watson 			}
784ca0716f5SRobert Watson 			break;
785ca0716f5SRobert Watson 
786ca0716f5SRobert Watson 		case 'r':
787ca0716f5SRobert Watson 			p_ruid = strtol(optarg, &converr, 10);
788ca0716f5SRobert Watson 			if (*converr != '\0') {
789 				if ((pw = getpwnam(optarg)) == NULL)
790 					break;
791 				p_ruid = pw->pw_uid;
792 			}
793 			SETOPT(opttochk, OPT_r);
794 			break;
795 
796 		case 'u':
797 			p_auid = strtol(optarg, &converr, 10);
798 			if (*converr != '\0') {
799 				if ((pw = getpwnam(optarg)) == NULL)
800 					break;
801 				p_auid = pw->pw_uid;
802 			}
803 			SETOPT(opttochk, OPT_u);
804 			break;
805 
806 		case 'v':
807 			SETOPT(opttochk, OPT_v);
808 			break;
809 
810 		case 'z':
811 			p_zone = optarg;
812 			SETOPT(opttochk, OPT_z);
813 			break;
814 
815 		case '?':
816 		default:
817 			usage("Unknown option");
818 		}
819 	}
820 	argv += optind;
821 	argc -= optind;
822 
823 	if (argc == 0) {
824 #ifdef HAVE_CAP_ENTER
825 		retval = cap_enter();
826 		if (retval != 0 && errno != ENOSYS)
827 			err(EXIT_FAILURE, "cap_enter");
828 #endif
829 		if (select_records(stdin) == -1)
830 			errx(EXIT_FAILURE,
831 			    "Couldn't select records from stdin");
832 		exit(EXIT_SUCCESS);
833 	}
834 
835 	/*
836 	 * XXX: We should actually be merging records here.
837 	 */
838 	for (i = 0; i < argc; i++) {
839 		fname = argv[i];
840 		fp = fopen(fname, "r");
841 		if (fp == NULL)
842 			errx(EXIT_FAILURE, "Couldn't open %s", fname);
843 
844 		/*
845 		 * If operating with sandboxing, create a sandbox process for
846 		 * each trail file we operate on.  This avoids the need to do
847 		 * fancy things with file descriptors, etc, when iterating on
848 		 * a list of arguments.
849 		 *
850 		 * NB: Unlike praudit(1), auditreduce(1) terminates if it hits
851 		 * any errors.  Propagate the error from the child to the
852 		 * parent if any problems arise.
853 		 */
854 #ifdef HAVE_CAP_ENTER
855 		childpid = fork();
856 		if (childpid == 0) {
857 			/* Child. */
858 			retval = cap_enter();
859 			if (retval != 0 && errno != ENOSYS)
860 				errx(EXIT_FAILURE, "cap_enter");
861 			if (select_records(fp) == -1)
862 				errx(EXIT_FAILURE,
863 				    "Couldn't select records %s", fname);
864 			exit(0);
865 		}
866 
867 		/* Parent.  Await child termination, check exit value. */
868 		while ((pid = waitpid(childpid, &status, 0)) != childpid);
869 		if (WEXITSTATUS(status) != 0)
870 			exit(EXIT_FAILURE);
871 #else
872 		if (select_records(fp) == -1)
873 			errx(EXIT_FAILURE, "Couldn't select records %s",
874 			    fname);
875 #endif
876 		fclose(fp);
877 	}
878 	exit(EXIT_SUCCESS);
879 }
880