aboutsummaryrefslogtreecommitdiffstats
path: root/framework/src/audit/tools/aulast/aulast.c
diff options
context:
space:
mode:
Diffstat (limited to 'framework/src/audit/tools/aulast/aulast.c')
-rw-r--r--framework/src/audit/tools/aulast/aulast.c610
1 files changed, 0 insertions, 610 deletions
diff --git a/framework/src/audit/tools/aulast/aulast.c b/framework/src/audit/tools/aulast/aulast.c
deleted file mode 100644
index 00ae055a..00000000
--- a/framework/src/audit/tools/aulast/aulast.c
+++ /dev/null
@@ -1,610 +0,0 @@
-/*
- * aulast.c - A last program based on audit logs
- * Copyright (c) 2008-2009,2011 Red Hat Inc., Durham, North Carolina.
- * All Rights Reserved.
- *
- * This software may be freely redistributed and/or modified under the
- * terms of the GNU General Public License as published by the Free
- * Software Foundation; either version 2, 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; see the file COPYING. If not, write to the
- * Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * Authors:
- * Steve Grubb <sgrubb@redhat.com>
- */
-
-#include "config.h"
-#include <stdio.h>
-#include <locale.h>
-#include <string.h>
-#include <unistd.h>
-#include <errno.h>
-#include <pwd.h>
-#include <stdlib.h>
-#include "libaudit.h"
-#include "auparse.h"
-#include "aulast-llist.h"
-
-
-static llist l;
-static FILE *f = NULL;
-static char *kernel = NULL;
-
-/* command line params */
-static int cuid = -1, bad = 0, proof = 0, debug = 0;
-static char *cterm = NULL;
-
-void usage(void)
-{
- fprintf(stderr,
- "usage: aulast [--stdin] [--proof] [--extract] [-f file] [user name] [tty]\n");
-}
-
-/* This outputs a line of text reporting the login/out times */
-static void report_session(lnode* cur)
-{
- int notime = 0;
-
- // Don't list failed logins
- if (cur == NULL)
- return;
-
- if (cur->result != bad)
- return;
-
- if (cur->name) {
- // This is a reboot record
- printf("%-8.8s ", cur->name);
- if (cur->end == 0) {
- cur->end = time(NULL);
- notime = 1;
- }
- } else {
- struct passwd *p = getpwuid(cur->auid);
- if (p)
- printf("%-8.8s ", p->pw_name);
- else
- printf("%-8.u ", cur->auid);
- }
- if (strncmp("/dev/", cur->term, 5) == 0)
- printf("%-12.12s ", cur->term+5);
- else
- printf("%-12.12s ", cur->term);
- printf("%-16.16s ", cur->host ? cur->host : "?");
- printf("%-16.16s ", ctime(&cur->start));
- switch(cur->status)
- {
- case SESSION_START:
- printf(" still logged in\n");
- break;
- case DOWN:
- printf("- down\n");
- break;
- case CRASH:
- printf("- crash\n");
- break;
- case GONE:
- printf(" gone - no logout\n");
- break;
- case LOG_OUT: {
- time_t secs;
- int mins, hours, days;
- if (notime)
- printf("- %-7.5s", " ");
- else
- printf("- %-7.5s", ctime(&cur->end) + 11);
- secs = cur->end - cur->start;
- mins = (secs / 60) % 60;
- hours = (secs / 3600) % 24;
- days = secs / 86400;
- if (days)
- printf("(%d+%02d:%02d)\n", days, hours, mins);
- else
- printf("(%02d:%02d)\n", hours, mins);
- }
- break;
- default:
- printf("\n");
- break;
- }
- if (proof) {
- char start[32], end[32];
- struct tm *btm;
-
- if (cur->loginuid_proof == 0 && cur->result == 1) // Bad login
- printf(" audit event proof serial number:"
- " %lu\n", cur->user_login_proof);
- else
- printf(" audit event proof serial numbers:"
- " %lu, %lu, %lu\n", cur->loginuid_proof,
- cur->user_login_proof, cur->user_end_proof);
- printf(" Session data can be found with this search:\n");
- btm = localtime(&cur->start);
- strftime(start, sizeof(start), "%x %T", btm);
- if (cur->end != 0) {
- btm = localtime(&cur->end);
- strftime(end, sizeof(end), "%x %T", btm);
- printf(" ausearch --start %s --end %s",
- start, end);
- } else {
- printf(" ausearch --start %s", start);
- }
- if (cur->name == NULL)
- printf(" --session %d", cur->session);
- if (cur->loginuid_proof == 0 && cur->result == 1) // Bad login
- printf(" -a %lu", cur->user_login_proof);
- printf("\n\n");
- }
-}
-
-static void extract_record(auparse_state_t *au)
-{
- if (f == NULL)
- return;
-
- fprintf(f, "%s\n", auparse_get_record_text(au));
-}
-
-static void create_new_session(auparse_state_t *au)
-{
- const char *tpid, *tses, *tauid;
- int pid = -1, auid = -1, ses = -1;
- lnode *cur;
-
- // Get pid
- tpid = auparse_find_field(au, "pid");
- if (tpid)
- pid = auparse_get_field_int(au);
-
- // Get second auid field
- tauid = auparse_find_field(au, "old-auid");
- if (tauid)
- tauid = auparse_find_field(au, "auid");
- else { // kernel 3.13 or older
- auparse_first_record(au);
- auparse_find_field(au, "auid");
- auparse_next_field(au);
- tauid = auparse_find_field(au, "auid");
- }
- if (tauid)
- auid = auparse_get_field_int(au);
-
- // Get second ses field
- tses = auparse_find_field(au, "old-ses");
- if (tses)
- tses = auparse_find_field(au, "ses");
- else { // kernel 3.13 or older
- auparse_first_record(au);
- auparse_find_field(au, "ses");
- auparse_next_field(au);
- tses = auparse_find_field(au, "ses");
- }
- if (tses)
- ses = auparse_get_field_int(au);
-
- // Check that they are valid
- if (pid == -1 || auid ==-1 || ses == -1) {
- if (debug)
- fprintf(stderr, "Bad login for event: %lu\n",
- auparse_get_serial(au));
- return;
- }
-
- // See if this session is already open
- //cur = list_find_auid(&l, auid, pid, ses);
- cur = list_find_session(&l, ses);
- if (cur) {
- // This means we have an open session close it out
- cur->status = GONE;
- cur->end = auparse_get_time(au);
- report_session(cur);
- list_delete_cur(&l);
- }
-
- // If this is supposed to be limited to a specific
- // uid and we don't have that record, skip creating it
- if (cuid != -1 && cuid != auid) {
- if (debug)
- fprintf(stderr,
- "login reporting limited to %d for event: %lu\n",
- cuid, auparse_get_serial(au));
- return;
- }
-
- list_create_session(&l, auid, pid, ses, auparse_get_serial(au));
-}
-
-static void update_session_login(auparse_state_t *au)
-{
- const char *tpid, *tses, *tuid, *tacct=NULL, *host, *term, *tres;
- int pid = -1, uid = -1, ses = -1, result = -1;
- time_t start;
- lnode *cur;
-
- // Get pid
- tpid = auparse_find_field(au, "pid");
- if (tpid)
- pid = auparse_get_field_int(au);
-
- // Get ses field - skipping first uid
- tses = auparse_find_field(au, "ses");
- if (tses)
- ses = auparse_get_field_int(au);
-
- // Get second uid field - we should be positioned past the first one
- // gdm sends uid, everything else sends id, we try acct as last resort
- tuid = auparse_find_field(au, "uid");
- if (tuid)
- uid = auparse_get_field_int(au);
- else {
- auparse_first_record(au);
- tuid = auparse_find_field(au, "id");
- if (tuid)
- uid = auparse_get_field_int(au);
- else {
- auparse_first_record(au);
- tuid = auparse_find_field(au, "acct");
- if (tuid) {
- const char *tacct = auparse_interpret_field(au);
- struct passwd *pw = getpwnam (tacct);
- if (pw != NULL)
- uid = pw->pw_uid;
- } else
- auparse_first_record(au);
- }
- }
-
- start = auparse_get_time(au);
-
- host = auparse_find_field(au, "hostname");
- if (host && strcmp(host, "?") == 0)
- host = auparse_find_field(au, "addr");
-
- term = auparse_find_field(au, "terminal");
- if (term == NULL)
- term = "?";
- tres = auparse_find_field(au, "res");
- if (tres)
- tres = auparse_interpret_field(au);
- if (tres) {
- if (strcmp(tres, "success") == 0)
- result = 0;
- else
- result = 1;
- }
- // We only get tacct when its a bad login
- if (result == 1) {
- auparse_first_record(au);
- tacct = auparse_find_field(au, "acct");
- if (tacct)
- tacct = auparse_interpret_field(au);
- } else {
- // Check that they are valid
- if (pid == -1 || uid ==-1 || ses == -1) {
- if (debug)
- fprintf(stderr,
- "Bad user login for event: %lu\n",
- auparse_get_serial(au));
- return;
- }
- }
-
- // See if this session is already open
- if (result == 0)
- cur = list_find_auid(&l, uid, pid, ses);
- else
- cur = NULL;
- if (cur) {
- // If we are limited to a specific terminal and
- // we find out the session is not associated with
- // the terminal of interest, delete the current node
- if (cterm && strstr(term, cterm) == NULL) {
- list_delete_cur(&l);
- if (debug)
- fprintf(stderr,
- "User login limited to %s for event: %lu\n",
- cterm, auparse_get_serial(au));
- return;
- }
-
- // This means we have an open session - update it
- list_update_start(&l, start, host, term, result,
- auparse_get_serial(au));
-
- // If the results were failed, we can close it out
- /* FIXME: result cannot be true. This is dead code.
- if (result) {
- report_session(cur);
- list_delete_cur(&l);
- } */
- } else if (bad == 1 && result == 1) {
- // If it were a bad login and we are wanting bad logins
- // create the record and report it.
- lnode n;
-
- n.start = start;
- n.end = start;
- n.auid = uid;
- n.name = tacct;
- n.term = term;
- n.host = host;
- n.result = result;
- n.status = LOG_OUT;
- n.loginuid_proof = 0;
- n.user_login_proof = auparse_get_serial(au);
- n.user_end_proof = 0;
- report_session(&n);
- } else if (debug)
- printf("Session not found or updated\n");
-}
-
-static void update_session_logout(auparse_state_t *au)
-{
- const char *tses, *tauid, *tpid;
- int pid = -1, auid = -1, ses = -1;
- lnode *cur;
-
- // Get pid field
- tpid = auparse_find_field(au, "pid");
- if (tpid)
- pid = auparse_get_field_int(au);
-
- // Get auid field
- tauid = auparse_find_field(au, "auid");
- if (tauid)
- auid = auparse_get_field_int(au);
-
- // Get ses field
- tses = auparse_find_field(au, "ses");
- if (tses)
- ses = auparse_get_field_int(au);
-
- // Check that they are valid
- if (pid == -1 || auid ==-1 || ses == -1) {
- if (debug)
- fprintf(stderr, "Bad user logout for event: %lu\n",
- auparse_get_serial(au));
- return;
- }
-
- // See if this session is already open
- cur = list_find_auid(&l, auid, pid, ses);
- if (cur) {
- // if time never got updated, this must be a cron or su
- // session...so we will just delete it.
- if (cur->start) {
- // This means we have an open session close it out
- time_t end = auparse_get_time(au);
- list_update_logout(&l, end, auparse_get_serial(au));
- report_session(cur);
- } else if (debug)
- fprintf(stderr, "start time error for event: %lu\n",
- auparse_get_serial(au));
- list_delete_cur(&l);
- }
-}
-
-static void process_bootup(auparse_state_t *au)
-{
- lnode *cur;
- int start;
-
- // See if we have unclosed boot up and make into CRASH record
- list_first(&l);
- cur = list_get_cur(&l);
- while (cur) {
- if (cur->name) {
- cur->user_end_proof = auparse_get_serial(au);
- cur->status = CRASH;
- cur->end = auparse_get_time(au);
- report_session(cur);
- }
- cur = list_next(&l);
- }
-
- // Logout and process anyone still left in the machine
- list_first(&l);
- cur = list_get_cur(&l);
- while (cur) {
- if (cur->status != CRASH) {
- cur->user_end_proof = auparse_get_serial(au);
- cur->status = DOWN;
- cur->end = auparse_get_time(au);
- report_session(cur);
- }
- cur = list_next(&l);
- }
-
- // Since this is a boot message, all old entries should be gone
- list_clear(&l);
- list_create(&l);
-
- // make reboot record - user:reboot, tty:system boot, host: kernel
- start = auparse_get_time(au);
- list_create_session(&l, 0, 0, 0, auparse_get_serial(au));
- cur = list_get_cur(&l);
- cur->start = start;
- cur->name = strdup("reboot");
- cur->term = strdup("system boot");
- if (kernel)
- cur->host = strdup(kernel);
- cur->result = 0;
-}
-
-static void process_kernel(auparse_state_t *au)
-{
- const char *kernel_str = auparse_find_field(au, "kernel");
- if (kernel_str == NULL)
- return;
-
- free(kernel);
- kernel = strdup(kernel_str);
-}
-
-static void process_shutdown(auparse_state_t *au)
-{
- lnode *cur;
-
- // Find reboot record
- list_first(&l);
- cur = list_get_cur(&l);
- while (cur) {
- if (cur->name) {
- // Found it - close it out and display it
- time_t end = auparse_get_time(au);
- list_update_logout(&l, end, auparse_get_serial(au));
- report_session(cur);
- list_delete_cur(&l);
- return;
- }
- cur = list_next(&l);
- }
-}
-
-int main(int argc, char *argv[])
-{
- int i, use_stdin = 0;
- char *user = NULL, *file = NULL;
- struct passwd *p;
- auparse_state_t *au;
-
- setlocale (LC_ALL, "");
- for (i=1; i<argc; i++) {
- if (argv[i][0] != '-') {
- //take input and lookup as if it were a user name
- //if that fails assume its a tty
- if (user == NULL) {
- p = getpwnam(argv[i]);
- if (p) {
- cuid = p->pw_uid;
- user = argv[i];
- continue;
- }
- }
- if (cterm == NULL) {
- cterm = argv[i];
- } else {
- usage();
- return 1;
- }
- } else {
- if (strcmp(argv[i], "-f") == 0) {
- if (use_stdin == 0) {
- i++;
- file = argv[i];
- } else {
- fprintf(stderr,"stdin already given\n");
- return 1;
- }
- } else if (strcmp(argv[i], "--bad") == 0) {
- bad = 1;
- } else if (strcmp(argv[i], "--proof") == 0) {
- proof = 1;
- } else if (strcmp(argv[i], "--extract") == 0) {
- f = fopen("aulast.log", "wt");
- } else if (strcmp(argv[i], "--stdin") == 0) {
- if (file == NULL)
- use_stdin = 1;
- else {
- fprintf(stderr, "file already given\n");
- return 1;
- }
- } else if (strcmp(argv[i], "--debug") == 0) {
- debug = 1;
- } else {
- usage();
- return 1;
- }
- }
- }
- list_create(&l);
-
- // Search for successful user logins
- if (file)
- au = auparse_init(AUSOURCE_FILE, file);
- else if (use_stdin)
- au = auparse_init(AUSOURCE_FILE_POINTER, stdin);
- else {
- if (getuid()) {
- fprintf(stderr, "You probably need to be root for this to work\n");
- }
- au = auparse_init(AUSOURCE_LOGS, NULL);
- }
- if (au == NULL) {
- fprintf(stderr, "Error - %s\n", strerror(errno));
- goto error_exit_1;
- }
-
- // The theory: iterate though events
- // 1) when LOGIN is found, create a new session node
- // 2) if that session number exists, close out the old one
- // 3) when USER_LOGIN is found, update session node
- // 4) When USER_END is found update session node and close it out
- // 5) When BOOT record found make new record and check for previous
- // 6) If previous boot found, set status to crash and logout everyone
- // 7) When SHUTDOWN found, close out reboot record
-
- while (auparse_next_event(au) > 0) {
- // We will take advantage of the fact that all events
- // of interest are one record long
- int type = auparse_get_type(au);
- if (type < 0)
- continue;
- switch (type)
- {
- case AUDIT_LOGIN:
- create_new_session(au);
- extract_record(au);
- break;
- case AUDIT_USER_LOGIN:
- update_session_login(au);
- extract_record(au);
- break;
- case AUDIT_USER_END:
- update_session_logout(au);
- extract_record(au);
- break;
- case AUDIT_SYSTEM_BOOT:
- process_bootup(au);
- extract_record(au);
- break;
- case AUDIT_SYSTEM_SHUTDOWN:
- process_shutdown(au);
- extract_record(au);
- break;
- case AUDIT_DAEMON_START:
- process_kernel(au);
- extract_record(au);
- break;
- }
- }
- auparse_destroy(au);
-
- // Now output the leftovers
- list_first(&l);
- do {
- lnode *cur = list_get_cur(&l);
- report_session(cur);
- } while (list_next(&l));
-
- free(kernel);
- list_clear(&l);
- if (f)
- fclose(f);
- return 0;
-
-error_exit_1:
- list_clear(&l);
- if (f)
- fclose(f);
- return 1;
-}
-