xref: /freebsd/contrib/openbsm/bin/praudit/praudit.c (revision 1f4bcc459a76b7aa664f3fd557684cd0ba6da352)
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 
45 extern char	*optarg;
46 extern int	 optind, optopt, opterr,optreset;
47 
48 static char	*del = ",";	/* Default delimiter. */
49 static int	 oneline = 0;
50 static int	 partial = 0;
51 static int	 oflags = AU_OFLAG_NONE;
52 
53 static void
54 usage(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  */
65 static int
66 print_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 
106 int
107 main(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 (1);
173 }
174