summaryrefslogtreecommitdiffstats
path: root/framework/src/audit/src/aureport.c
diff options
context:
space:
mode:
Diffstat (limited to 'framework/src/audit/src/aureport.c')
-rw-r--r--framework/src/audit/src/aureport.c338
1 files changed, 338 insertions, 0 deletions
diff --git a/framework/src/audit/src/aureport.c b/framework/src/audit/src/aureport.c
new file mode 100644
index 00000000..98511e01
--- /dev/null
+++ b/framework/src/audit/src/aureport.c
@@ -0,0 +1,338 @@
+/*
+ * aureport.c - main file for aureport utility
+ * Copyright 2005-08, 2010,11,2013 Red Hat Inc., Durham, North Carolina.
+ * All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Authors:
+ * Steve Grubb <sgrubb@redhat.com>
+ */
+
+#include "config.h"
+#include <stdio.h>
+#include <stdio_ext.h>
+#include <string.h>
+#include <stdlib.h>
+#include <getopt.h>
+#include <unistd.h>
+#include <ctype.h>
+#include <time.h>
+#include <errno.h>
+#include <sys/resource.h>
+#include <sys/stat.h>
+#include <locale.h>
+#include <sys/param.h>
+#include "libaudit.h"
+#include "auditd-config.h"
+#include "aureport-options.h"
+#include "aureport-scan.h"
+#include "ausearch-lol.h"
+#include "ausearch-lookup.h"
+
+
+event very_first_event, very_last_event;
+static FILE *log_fd = NULL;
+static lol lo;
+static int found = 0;
+static int files_to_process = 0; // Logs left when processing multiple
+static int userfile_is_dir = 0;
+static int process_logs(void);
+static int process_log_fd(const char *filename);
+static int process_stdin(void);
+static int process_file(char *filename);
+static int get_record(llist **);
+
+extern char *user_file;
+extern int force_logs;
+
+
+static int is_pipe(int fd)
+{
+ struct stat st;
+
+ if (fstat(fd, &st) == 0) {
+ if (S_ISFIFO(st.st_mode))
+ return 1;
+ }
+ return 0;
+}
+
+int main(int argc, char *argv[])
+{
+ struct rlimit limit;
+ int rc;
+
+ /* Check params and build regexpr */
+ setlocale (LC_ALL, "");
+ if (check_params(argc, argv))
+ return 1;
+
+ /* Raise the rlimits in case we're being started from a shell
+ * with restrictions. Not a fatal error. */
+ limit.rlim_cur = RLIM_INFINITY;
+ limit.rlim_max = RLIM_INFINITY;
+ setrlimit(RLIMIT_FSIZE, &limit);
+ setrlimit(RLIMIT_CPU, &limit);
+ set_aumessage_mode(MSG_STDERR, DBG_NO);
+ (void) umask( umask( 077 ) | 027 );
+ very_first_event.sec = 0;
+ reset_counters();
+
+ print_title();
+ lol_create(&lo);
+ if (user_file) {
+ struct stat sb;
+ if (stat(user_file, &sb) == -1) {
+ perror("stat");
+ return 1;
+ } else {
+ switch (sb.st_mode & S_IFMT) {
+ case S_IFDIR:
+ userfile_is_dir = 1;
+ rc = process_logs();
+ break;
+ case S_IFREG:
+ default:
+ rc = process_file(user_file);
+ break;
+ }
+ }
+ } else if (force_logs)
+ rc = process_logs();
+ else if (is_pipe(0))
+ rc = process_stdin();
+ else
+ rc = process_logs();
+ lol_clear(&lo);
+ if (rc)
+ return rc;
+
+ if (!found && report_detail == D_DETAILED && report_type != RPT_TIME) {
+ printf("<no events of interest were found>\n\n");
+ destroy_counters();
+ aulookup_destroy_uid_list();
+ aulookup_destroy_gid_list();
+ return 1;
+ } else
+ print_wrap_up();
+ destroy_counters();
+ aulookup_destroy_uid_list();
+ aulookup_destroy_gid_list();
+ free(user_file);
+ return 0;
+}
+
+static int process_logs(void)
+{
+ struct daemon_conf config;
+ char *filename;
+ int len, num = 0;
+
+ if (user_file && userfile_is_dir) {
+ char dirname[MAXPATHLEN];
+ clear_config (&config);
+
+ strcpy(dirname, user_file);
+ if (dirname[strlen(dirname)-1] != '/')
+ strcat(dirname, "/");
+ strcat (dirname, "audit.log");
+ free((void *)config.log_file);
+ config.log_file=strdup(dirname);
+ fprintf(stderr, "NOTE - using logs in %s\n", config.log_file);
+ } else {
+ /* Load config so we know where logs are */
+ if (load_config(&config, TEST_SEARCH))
+ fprintf(stderr, "NOTE - using built-in logs: %s\n",
+ config.log_file);
+ }
+
+ /* for each file */
+ len = strlen(config.log_file) + 16;
+ filename = malloc(len);
+ if (!filename) {
+ fprintf(stderr, "No memory\n");
+ free_config(&config);
+ return 1;
+ }
+ /* Find oldest log file */
+ snprintf(filename, len, "%s", config.log_file);
+ do {
+ if (access(filename, R_OK) != 0)
+ break;
+// FIXME: do a time check and put them on linked list for later
+ num++;
+ snprintf(filename, len, "%s.%d", config.log_file, num);
+ } while (1);
+ num--;
+ /*
+ * We note how many files we need to process
+ */
+ files_to_process = num;
+
+ /* Got it, now process logs from last to first */
+ if (num > 0)
+ snprintf(filename, len, "%s.%d", config.log_file, num);
+ else
+ snprintf(filename, len, "%s", config.log_file);
+ do {
+ int ret;
+ if ((ret = process_file(filename))) {
+ free(filename);
+ free_config(&config);
+ return ret;
+ }
+
+ /* Get next log file */
+ files_to_process--; /* one less file to process */
+ num--;
+ if (num > 0)
+ snprintf(filename, len, "%s.%d", config.log_file, num);
+ else if (num == 0)
+ snprintf(filename, len, "%s", config.log_file);
+ else
+ break;
+ } while (1);
+ free(filename);
+ free_config(&config);
+ return 0;
+}
+
+static int process_log_fd(const char *filename)
+{
+ llist *entries; // entries in a record
+ int ret;
+ int first = 0;
+ event first_event, last_event;
+
+ last_event.sec = 0;
+ last_event.milli = 0;
+
+ /* For each record in file */
+ do {
+ ret = get_record(&entries);
+ if ((ret != 0)||(entries->cnt == 0))
+ break;
+ // If report is RPT_TIME or RPT_SUMMARY, get
+ if (report_type <= RPT_SUMMARY) {
+ if (first == 0) {
+ list_get_event(entries, &first_event);
+ first = 1;
+ if (very_first_event.sec == 0)
+ list_get_event(entries,
+ &very_first_event);
+ }
+ list_get_event(entries, &last_event);
+ }
+ if (scan(entries)) {
+ // This is the per entry action item
+ if (per_event_processing(entries))
+ found = 1;
+ }
+ list_clear(entries);
+ free(entries);
+ } while (ret == 0);
+ fclose(log_fd);
+ // This is the per file action items
+ very_last_event.sec = last_event.sec;
+ very_last_event.milli = last_event.milli;
+ if (report_type == RPT_TIME) {
+ if (first == 0) {
+ printf("%s: no records\n", filename);
+ } else {
+ struct tm *btm;
+ char tmp[32];
+
+ printf("%s: ", filename);
+ btm = localtime(&first_event.sec);
+ strftime(tmp, sizeof(tmp), "%x %T", btm);
+ printf("%s.%03d - ", tmp, first_event.milli);
+ btm = localtime(&last_event.sec);
+ strftime(tmp, sizeof(tmp), "%x %T", btm);
+ printf("%s.%03d\n", tmp, last_event.milli);
+ }
+ }
+
+ return 0;
+}
+
+static int process_stdin(void)
+{
+ log_fd = stdin;
+
+ return process_log_fd("stdin");
+}
+
+static int process_file(char *filename)
+{
+ log_fd = fopen(filename, "rm");
+ if (log_fd == NULL) {
+ fprintf(stderr, "Error opening %s (%s)\n", filename,
+ strerror(errno));
+ return 1;
+ }
+
+ __fsetlocking(log_fd, FSETLOCKING_BYCALLER);
+ return process_log_fd(filename);
+}
+
+/*
+ * This function returns a malloc'd buffer of the next record in the audit
+ * logs. It returns 0 on success, 1 on eof, -1 on error.
+ */
+static int get_record(llist **l)
+{
+ char *rc;
+ char *buff = NULL;
+
+ *l = get_ready_event(&lo);
+ if (*l)
+ return 0;
+
+ while (1) {
+ if (!buff) {
+ buff = malloc(MAX_AUDIT_MESSAGE_LENGTH);
+ if (!buff)
+ return -1;
+ }
+ rc = fgets_unlocked(buff, MAX_AUDIT_MESSAGE_LENGTH,
+ log_fd);
+ if (rc) {
+ if (lol_add_record(&lo, buff)) {
+ *l = get_ready_event(&lo);
+ if (*l)
+ break;
+ }
+ } else {
+ free(buff);
+ if (feof_unlocked(log_fd)) {
+ // Only mark all events complete if this is
+ // the last file.
+ if (files_to_process == 0) {
+ terminate_all_events(&lo);
+ }
+ *l = get_ready_event(&lo);
+ if (*l)
+ return 0;
+ else
+ return 1;
+ } else
+ return -1;
+ }
+ }
+ free(buff);
+ return 0;
+}
+