1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21 /*
22 * Copyright (c) 2019 Peter Tribble.
23 */
24 /*
25 * Copyright (c) 1992, 2010, Oracle and/or its affiliates. All rights reserved.
26 */
27
28 #include <dirent.h>
29 #include <errno.h>
30 #include <locale.h>
31 #include <libintl.h>
32 #include <stdlib.h>
33 #include <strings.h>
34 #include <stdio.h>
35 #include <unistd.h>
36
37 #include <sys/types.h>
38 #include <sys/file.h>
39
40 #include <bsm/audit.h>
41 #include <bsm/audit_record.h>
42 #include <bsm/libbsm.h>
43
44 #include "praudit.h"
45 #include "toktable.h"
46
47 static int process_options(int *argc, char *argv[], char *names[]);
48
49 static int input_mode; /* audit file source */
50 static int format = PRF_DEFAULTM; /* output mode */
51
52 static char SEPARATOR[SEP_SIZE] = ","; /* field separator */
53
54 static FILE *gf = NULL;
55 static FILE *pf = NULL;
56
57 /*
58 * ----------------------------------------------------------------------
59 * praudit - display contents of audit trail file
60 *
61 * main() - main control
62 * input: - command line input:
63 * praudit -r|s -l -x -ddelim. -p pwfile -g grpfile -c filename(s)
64 * ----------------------------------------------------------------------
65 */
66
67 int
main(int argc,char ** argv)68 main(int argc, char **argv)
69 {
70 int i = 0, retstat;
71 char *names[MAXFILENAMES];
72
73 /* Internationalization */
74 (void) setlocale(LC_ALL, "");
75 (void) textdomain(TEXT_DOMAIN);
76 /*
77 * get audit file names
78 */
79 if ((retstat = process_options(&argc, argv, names)) == 0) {
80 if (pf != NULL) {
81 errno = 0;
82 loadnames(pf);
83 (void) fclose(pf);
84 if (errno != 0) {
85 (void) fprintf(stderr,
86 gettext("praudit: Problem reading passwd "
87 "file.\n"));
88 exit(1);
89 }
90 }
91 if (gf != NULL) {
92 errno = 0;
93 loadgroups(gf);
94 (void) fclose(gf);
95 if (errno != 0) {
96 (void) fprintf(stderr,
97 gettext("praudit: Problem reading group "
98 "file.\n"));
99 exit(1);
100 }
101 }
102 if (format & PRF_XMLM)
103 print_audit_xml_prolog();
104 do {
105 retstat = 0;
106 /*
107 * process each audit file
108 */
109 if (input_mode == FILEMODE) {
110 if (freopen(names[i], "r", stdin) == NULL) {
111 (void) fprintf(stderr,
112 gettext("praudit: Cannot associate "
113 "stdin with %s: %s\n"),
114 names[i], strerror(errno));
115 exit(1);
116 }
117 }
118
119 /*
120 * Call the library routine to format the
121 * audit data from stdin and print to stdout
122 */
123 retstat = print_audit(format, SEPARATOR);
124
125 } while ((++i < argc) && retstat >= 0);
126 }
127 if ((retstat == 0) && (format & PRF_XMLM))
128 print_audit_xml_ending();
129
130 if (retstat == -2) {
131 (void) printf(gettext("\nusage: praudit [-r/-s] [-l] [-x] "
132 "[-ddel] [-p file] [-g file] [-c] filename...\n"));
133 exit(1);
134 } else if (retstat < 0) {
135 exit(1);
136 }
137 return (0);
138 }
139
140
141 /*
142 * -------------------------------------------------------------------
143 * process_options() - get command line flags and file names
144 * input: - praudit [-r]/[-s] [-l] [-x] [-ddel] [-c]
145 * -p pwfile -g grpfile -c {audit file names}
146 * output: - {audit file names}
147 * globals set: format: RAWM / SHORTM / XML / ONELINE or DEFAULTM
148 * SEPARATOR: default, ",", set here if
149 * user specified
150 * NOTE: no changes required here for new audit record format
151 * -------------------------------------------------------------------
152 */
153 int
process_options(int * argc,char ** argv,char ** names)154 process_options(int *argc, char **argv, char **names)
155 {
156 int c, returnstat = 0;
157
158 /*
159 * check for flags
160 */
161
162 while ((c = getopt(*argc, argv, "crslxd:g:p:")) != -1) {
163 switch (c) {
164 case 'c':
165 format |= PRF_NOCACHE; /* turn off cache */
166 break;
167 case 'r':
168 if (format & PRF_SHORTM)
169 returnstat = -2;
170 else
171 format |= PRF_RAWM;
172 break;
173 case 's':
174 if (format & PRF_RAWM)
175 returnstat = -2;
176 else
177 format |= PRF_SHORTM;
178 break;
179 case 'l':
180 format |= PRF_ONELINE;
181 break;
182 case 'x':
183 format |= PRF_XMLM;
184 break;
185 case 'd':
186 if (strlen(optarg) < sizeof (SEPARATOR))
187 (void) strlcpy(SEPARATOR, optarg,
188 sizeof (SEPARATOR));
189 else {
190 (void) fprintf(stderr,
191 gettext("praudit: Delimiter too "
192 "long. Using default.\n"));
193 }
194 break;
195 case 'g':
196 if ((gf = fopen(optarg, "r")) == NULL) {
197 (void) fprintf(stderr, gettext("praudit: Cannot"
198 " open specified group file.\n"));
199 return (-1);
200 }
201 break;
202 case 'p':
203 if ((pf = fopen(optarg, "r")) == NULL) {
204 (void) fprintf(stderr, gettext("praudit: Cannot"
205 " open specified passwd file.\n"));
206 return (-1);
207 }
208 break;
209 default:
210 returnstat = -2;
211 break;
212 }
213 }
214
215 argv = &argv[optind - 1];
216 *argc -= optind;
217
218 if (*argc > MAXFILENAMES) {
219 (void) fprintf(stderr, gettext("praudit: Too many file "
220 "names.\n"));
221 return (-1);
222 }
223 if (*argc > 0) {
224 int count = *argc;
225
226 input_mode = FILEMODE;
227 /*
228 * copy file names from command line
229 */
230 do {
231 *names++ = *++argv;
232 } while (--count > 0);
233 } else
234 input_mode = PIPEMODE;
235
236 return (returnstat);
237 }
238