2 * aureport.c - main file for aureport utility
3 * Copyright 2005-08, 2010,11,2013 Red Hat Inc., Durham, North Carolina.
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 * Steve Grubb <sgrubb@redhat.com>
26 #include <stdio_ext.h>
34 #include <sys/resource.h>
37 #include <sys/param.h>
39 #include "auditd-config.h"
40 #include "aureport-options.h"
41 #include "aureport-scan.h"
42 #include "ausearch-lol.h"
43 #include "ausearch-lookup.h"
46 event very_first_event, very_last_event;
47 static FILE *log_fd = NULL;
50 static int files_to_process = 0; // Logs left when processing multiple
51 static int userfile_is_dir = 0;
52 static int process_logs(void);
53 static int process_log_fd(const char *filename);
54 static int process_stdin(void);
55 static int process_file(char *filename);
56 static int get_record(llist **);
58 extern char *user_file;
59 extern int force_logs;
62 static int is_pipe(int fd)
66 if (fstat(fd, &st) == 0) {
67 if (S_ISFIFO(st.st_mode))
73 int main(int argc, char *argv[])
78 /* Check params and build regexpr */
79 setlocale (LC_ALL, "");
80 if (check_params(argc, argv))
83 /* Raise the rlimits in case we're being started from a shell
84 * with restrictions. Not a fatal error. */
85 limit.rlim_cur = RLIM_INFINITY;
86 limit.rlim_max = RLIM_INFINITY;
87 setrlimit(RLIMIT_FSIZE, &limit);
88 setrlimit(RLIMIT_CPU, &limit);
89 set_aumessage_mode(MSG_STDERR, DBG_NO);
90 (void) umask( umask( 077 ) | 027 );
91 very_first_event.sec = 0;
98 if (stat(user_file, &sb) == -1) {
102 switch (sb.st_mode & S_IFMT) {
109 rc = process_file(user_file);
113 } else if (force_logs)
116 rc = process_stdin();
123 if (!found && report_detail == D_DETAILED && report_type != RPT_TIME) {
124 printf("<no events of interest were found>\n\n");
126 aulookup_destroy_uid_list();
127 aulookup_destroy_gid_list();
132 aulookup_destroy_uid_list();
133 aulookup_destroy_gid_list();
138 static int process_logs(void)
140 struct daemon_conf config;
144 if (user_file && userfile_is_dir) {
145 char dirname[MAXPATHLEN];
146 clear_config (&config);
148 strcpy(dirname, user_file);
149 if (dirname[strlen(dirname)-1] != '/')
150 strcat(dirname, "/");
151 strcat (dirname, "audit.log");
152 free((void *)config.log_file);
153 config.log_file=strdup(dirname);
154 fprintf(stderr, "NOTE - using logs in %s\n", config.log_file);
156 /* Load config so we know where logs are */
157 if (load_config(&config, TEST_SEARCH))
158 fprintf(stderr, "NOTE - using built-in logs: %s\n",
163 len = strlen(config.log_file) + 16;
164 filename = malloc(len);
166 fprintf(stderr, "No memory\n");
167 free_config(&config);
170 /* Find oldest log file */
171 snprintf(filename, len, "%s", config.log_file);
173 if (access(filename, R_OK) != 0)
175 // FIXME: do a time check and put them on linked list for later
177 snprintf(filename, len, "%s.%d", config.log_file, num);
181 * We note how many files we need to process
183 files_to_process = num;
185 /* Got it, now process logs from last to first */
187 snprintf(filename, len, "%s.%d", config.log_file, num);
189 snprintf(filename, len, "%s", config.log_file);
192 if ((ret = process_file(filename))) {
194 free_config(&config);
198 /* Get next log file */
199 files_to_process--; /* one less file to process */
202 snprintf(filename, len, "%s.%d", config.log_file, num);
204 snprintf(filename, len, "%s", config.log_file);
209 free_config(&config);
213 static int process_log_fd(const char *filename)
215 llist *entries; // entries in a record
218 event first_event, last_event;
221 last_event.milli = 0;
223 /* For each record in file */
225 ret = get_record(&entries);
226 if ((ret != 0)||(entries->cnt == 0))
228 // If report is RPT_TIME or RPT_SUMMARY, get
229 if (report_type <= RPT_SUMMARY) {
231 list_get_event(entries, &first_event);
233 if (very_first_event.sec == 0)
234 list_get_event(entries,
237 list_get_event(entries, &last_event);
240 // This is the per entry action item
241 if (per_event_processing(entries))
248 // This is the per file action items
249 very_last_event.sec = last_event.sec;
250 very_last_event.milli = last_event.milli;
251 if (report_type == RPT_TIME) {
253 printf("%s: no records\n", filename);
258 printf("%s: ", filename);
259 btm = localtime(&first_event.sec);
260 strftime(tmp, sizeof(tmp), "%x %T", btm);
261 printf("%s.%03d - ", tmp, first_event.milli);
262 btm = localtime(&last_event.sec);
263 strftime(tmp, sizeof(tmp), "%x %T", btm);
264 printf("%s.%03d\n", tmp, last_event.milli);
271 static int process_stdin(void)
275 return process_log_fd("stdin");
278 static int process_file(char *filename)
280 log_fd = fopen(filename, "rm");
281 if (log_fd == NULL) {
282 fprintf(stderr, "Error opening %s (%s)\n", filename,
287 __fsetlocking(log_fd, FSETLOCKING_BYCALLER);
288 return process_log_fd(filename);
292 * This function returns a malloc'd buffer of the next record in the audit
293 * logs. It returns 0 on success, 1 on eof, -1 on error.
295 static int get_record(llist **l)
300 *l = get_ready_event(&lo);
306 buff = malloc(MAX_AUDIT_MESSAGE_LENGTH);
310 rc = fgets_unlocked(buff, MAX_AUDIT_MESSAGE_LENGTH,
313 if (lol_add_record(&lo, buff)) {
314 *l = get_ready_event(&lo);
320 if (feof_unlocked(log_fd)) {
321 // Only mark all events complete if this is
323 if (files_to_process == 0) {
324 terminate_all_events(&lo);
326 *l = get_ready_event(&lo);