1/*-
2 * Copyright (c) 2004-2009 Apple Inc.
3 * Copyright (c) 2006 Martin Voros
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1.  Redistributions of source code must retain the above copyright
10 *     notice, this list of conditions and the following disclaimer.
11 * 2.  Redistributions in binary form must reproduce the above copyright
12 *     notice, this list of conditions and the following disclaimer in the
13 *     documentation and/or other materials provided with the distribution.
14 * 3.  Neither the name of Apple Inc. ("Apple") nor the names of
15 *     its contributors may be used to endorse or promote products derived
16 *     from this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND
19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR
22 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
26 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
27 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28 * POSSIBILITY OF SUCH DAMAGE.
29 */
30
31/*
32 * Tool used to parse audit records conforming to the BSM structure.
33 */
34
35/*
36 * praudit [-lnpx] [-r | -s] [-d del] [file ...]
37 */
38
39#include <bsm/libbsm.h>
40
41#include <stdio.h>
42#include <stdlib.h>
43#include <unistd.h>
44
45extern char	*optarg;
46extern int	 optind, optopt, opterr,optreset;
47
48static char	*del = ",";	/* Default delimiter. */
49static int	 oneline = 0;
50static int	 partial = 0;
51static int	 oflags = AU_OFLAG_NONE;
52
53static void
54usage(void)
55{
56
57	fprintf(stderr, "usage: praudit [-lnpx] [-r | -s] [-d del] "
58	    "[file ...]\n");
59	exit(1);
60}
61
62/*
63 * Token printing for each token type .
64 */
65static int
66print_tokens(FILE *fp)
67{
68	u_char *buf;
69	tokenstr_t tok;
70	int reclen;
71	int bytesread;
72
73	/* Allow tail -f | praudit to work. */
74	if (partial) {
75		u_char type = 0;
76		/* Record must begin with a header token. */
77		do {
78			type = fgetc(fp);
79		} while(type != AUT_HEADER32);
80		ungetc(type, fp);
81	}
82
83	while ((reclen = au_read_rec(fp, &buf)) != -1) {
84		bytesread = 0;
85		while (bytesread < reclen) {
86			/* Is this an incomplete record? */
87			if (-1 == au_fetch_tok(&tok, buf + bytesread,
88			    reclen - bytesread))
89				break;
90			au_print_flags_tok(stdout, &tok, del, oflags);
91			bytesread += tok.len;
92			if (oneline) {
93				if (!(oflags & AU_OFLAG_XML))
94					printf("%s", del);
95			} else
96				printf("\n");
97		}
98		free(buf);
99		if (oneline)
100			printf("\n");
101		fflush(stdout);
102	}
103	return (0);
104}
105
106int
107main(int argc, char **argv)
108{
109	int ch;
110	int i;
111	FILE *fp;
112
113	while ((ch = getopt(argc, argv, "d:lnprsx")) != -1) {
114		switch(ch) {
115		case 'd':
116			del = optarg;
117			break;
118
119		case 'l':
120			oneline = 1;
121			break;
122
123		case 'n':
124			oflags |= AU_OFLAG_NORESOLVE;
125			break;
126
127		case 'p':
128			partial = 1;
129			break;
130
131		case 'r':
132			if (oflags & AU_OFLAG_SHORT)
133				usage();	/* Exclusive from shortfrm. */
134			oflags |= AU_OFLAG_RAW;
135			break;
136
137		case 's':
138			if (oflags & AU_OFLAG_RAW)
139				usage();	/* Exclusive from raw. */
140			oflags |= AU_OFLAG_SHORT;
141			break;
142
143		case 'x':
144			oflags |= AU_OFLAG_XML;
145			break;
146
147		case '?':
148		default:
149			usage();
150		}
151	}
152
153	if (oflags & AU_OFLAG_XML)
154		au_print_xml_header(stdout);
155
156	/* For each of the files passed as arguments dump the contents. */
157	if (optind == argc) {
158		print_tokens(stdin);
159		return (1);
160	}
161	for (i = optind; i < argc; i++) {
162		fp = fopen(argv[i], "r");
163		if ((fp == NULL) || (print_tokens(fp) == -1))
164			perror(argv[i]);
165		if (fp != NULL)
166			fclose(fp);
167	}
168
169	if (oflags & AU_OFLAG_XML)
170		au_print_xml_footer(stdout);
171
172	return (0);
173}
174