diff options
Diffstat (limited to 'src/sh_audit.c')
-rw-r--r-- | src/sh_audit.c | 183 |
1 files changed, 130 insertions, 53 deletions
diff --git a/src/sh_audit.c b/src/sh_audit.c index 52d0c70..d4d4dd2 100644 --- a/src/sh_audit.c +++ b/src/sh_audit.c @@ -74,7 +74,7 @@ static int listRecords (auparse_state_t * au, struct recordState * state) sl_strlcpy(state->syscall, auparse_interpret_field(au), REC_SIZE_SYSCALL); if (auparse_find_field(au, _("success"))) - strncpy(state->success, auparse_interpret_field(au), REC_SIZE_SUCCESS); + sl_strlcpy(state->success, auparse_interpret_field(au), REC_SIZE_SUCCESS); if (auparse_find_field(au, "uid")) state->uid = auparse_get_field_int(au); @@ -147,7 +147,7 @@ static char * doAuparse (const char * file, time_t time, int tol, char * result, goto err; } - memset(&state, '\0', sizeof(state)); + memset(&state, 0, sizeof(state)); while (ausearch_next_event(au) == 1) { @@ -179,10 +179,13 @@ static char * doAuparse (const char * file, time_t time, int tol, char * result, if (0 == strcmp(state.success, "yes")) { + char time_str[81]; char * tmp_exe = sh_util_safe_name(state.exe); + + (void) sh_unix_gmttime (state.time, time_str, sizeof(time_str)); sl_snprintf(result, rsize, - _("time=%lu.%u, syscall=%s, auid=%u, uid=%u, gid=%u, euid=%u, egid=%u, fsuid=%u, fsgid=%u, exe=%s"), - (unsigned long) state.time, state.milli, + _("time=%lu.%u, timestamp=%s, syscall=%s, auid=%u, uid=%u, gid=%u, euid=%u, egid=%u, fsuid=%u, fsgid=%u, exe=%s"), + (unsigned long) state.time, state.milli, time_str, state.syscall, state.auid, state.uid, state.gid, state.euid, state.egid, state.fsuid, state.fsgid, tmp_exe); @@ -196,6 +199,23 @@ static char * doAuparse (const char * file, time_t time, int tol, char * result, return NULL; } +#define SH_AUDIT_DEF "wa" +static char sh_audit_flags[32] = SH_AUDIT_DEF; + +int sh_audit_set_flags(const char * str) +{ + if (!str || strlen(str) >= sizeof(sh_audit_flags)) + return -1; + sl_strlcpy(sh_audit_flags, str, sizeof(sh_audit_flags)); + return 0; +} +static void reset_audit_flags() +{ + sl_strlcpy(sh_audit_flags, SH_AUDIT_DEF, sizeof(sh_audit_flags)); + return; +} + + static int sh_audit_checkdaemon(); static int actl_pnum = -1; static char * actl_paths[4] = @@ -206,20 +226,23 @@ static char * actl_paths[4] = N_("/usr/bin/auditctl") }; +static char * getflags (char * file); /* Public function to fetch an audit record for path 'file', time 'time' * The 'result' array should be sized ~256 char. */ -char * sh_audit_fetch (char * file, time_t mtime, time_t ctime, char * result, size_t rsize) +char * sh_audit_fetch (char * file, time_t mtime, time_t ctime, time_t atime, char * result, size_t rsize) { - char * res = NULL; + char * res = NULL; + char * flags = getflags(file); if (sh_audit_checkdaemon() >= 0) { time_t new; - - if (mtime >= ctime) { new = mtime; } - else { new = ctime; } + + if (flags && (strchr(flags, 'r') || strchr(flags, 'x')) && atime >= ctime && atime >= mtime) { new = atime; } + else if (mtime >= ctime) { new = mtime; } + else { new = ctime; } res = doAuparse (file, new, 1, result, rsize, S_FALSE); @@ -250,6 +273,7 @@ void sh_audit_delete_all () sl_strlcpy(ctl, _(actl_paths[p]), sizeof(ctl)); sh_ext_system(ctl, ctl, "-D", "-k", _("samhain"), NULL); } + reset_audit_flags(); return; } @@ -262,7 +286,7 @@ static int sh_audit_isdir(const char * file) return S_FALSE; } -static void sh_audit_mark_int (const char * file) +static void sh_audit_mark_int (const char * file, const char * flags) { static int flushRules = 0; @@ -285,10 +309,10 @@ static void sh_audit_mark_int (const char * file) char a1[32]; char a2[32]; char a3[32]; + char a4[32]; - sl_snprintf(command, len, _("%s -w %s -p wa -k samhain"), - _(actl_paths[p]), - file); + sl_snprintf(command, len, _("%s -w %s -p %s -k samhain"), + _(actl_paths[p]), file, flags); safe = sh_util_safe_name_keepspace(command); sh_error_handle (SH_ERR_ALL, FIL__, __LINE__, @@ -302,7 +326,8 @@ static void sh_audit_mark_int (const char * file) sl_strlcpy(command, file, len); sl_strlcpy(a3, _("samhain"), sizeof(a3)); - sh_ext_system(ctl, ctl, "-w", command, "-p", "wa", "-k", a3, NULL); + sl_strlcpy(a4, flags, sizeof(a4)); + sh_ext_system(ctl, ctl, "-w", command, "-p", a4, "-k", a3, NULL); /* Placing a watch on a directory will not place a watch on the * directory inode, so we do this explicitely. @@ -318,7 +343,8 @@ static void sh_audit_mark_int (const char * file) sl_strlcpy(command, _("path="), len); sl_strlcat(command, file, len); sl_strlcpy(a1, _("always,exit"), sizeof(a1)); - sl_strlcpy(a2, _("perm=wa"), sizeof(a2)); + sl_strlcpy(a2, _("perm="), sizeof(a2)); + sl_strlcat(a2, flags, sizeof(a2)); sh_ext_system(ctl, ctl, "-a", a1, "-F", command, "-F", a2, "-k", a3, NULL); } SH_FREE(command); @@ -326,12 +352,47 @@ static void sh_audit_mark_int (const char * file) return; } +#define SH_AU_FLAGS_SIZ 32 struct aud_list { char * file; + char flags[SH_AU_FLAGS_SIZ]; struct aud_list * next; }; struct aud_list * mark_these = NULL; +static int marked_committed = 0; + +static void delete_listofmarked() +{ + struct aud_list * tmp; + struct aud_list * this = mark_these; + + mark_these = NULL; + + while (this) + { + tmp = this; + this = this->next; + + SH_FREE(tmp->file); + SH_FREE(tmp); + } + marked_committed = 0; +} + +static char * getflags (char * file) +{ + struct aud_list * this = mark_these; + + while (this) + { + if (0 == strcmp(file, this->file)) + return this->flags; + this = this->next; + } + /* no explicit rule for this file */ + return NULL; +} static void add_this (char * file) { @@ -339,8 +400,12 @@ static void add_this (char * file) size_t len = strlen(file); this->file = sh_util_strdup(file); + + /* strip trailing '/' */ if ((len > 1) && (file[len-1] == '/')) this->file[len-1] = '\0'; + + sl_strlcpy(this->flags, sh_audit_flags, SH_AU_FLAGS_SIZ); this->next = mark_these; mark_these = this; @@ -349,44 +414,50 @@ static void add_this (char * file) /* Check whether it is already covered by a higher directory */ -static int test_exchange (struct aud_list * this, char * file) +static int test_exchange (struct aud_list * this, const char * file) { size_t len0 = sl_strlen(this->file); size_t len1 = sl_strlen(file); int ret = -1; + if (!file || !this || !this->file) + return 0; + if (len0 == len1) { return strcmp(this->file, file); } else { - char * s0 = SH_ALLOC(len0 + 2); - char * s1 = SH_ALLOC(len1 + 2); - - sl_strlcpy(s0, this->file, len0 + 2); - sl_strlcpy(s1, file, len1 + 2); - - if (s0 < s1) - { - sl_strlcat(s0, "/", len0 + 2); - ret = strncmp(s0, s1, len0 + 1); - } - else - { - sl_strlcat(s1, "/", len1 + 2); - if (0 == strncmp(s0, s1, len1 + 1)) - { - size_t len = strlen(file); - SH_FREE(this->file); - this->file = sh_util_strdup(file); - if ((len > 1) && (file[len-1] == '/')) - this->file[len-1] = '\0'; - ret = 0; - } - } - SH_FREE(s0); - SH_FREE(s1); + if (0 == strcmp(this->flags, sh_audit_flags)) + { + char * s0 = SH_ALLOC(len0 + 2); + char * s1 = SH_ALLOC(len1 + 2); + + sl_strlcpy(s0, this->file, len0 + 2); + sl_strlcpy(s1, file, len1 + 2); + + if (s0 < s1) + { + sl_strlcat(s0, "/", len0 + 2); + ret = strncmp(s0, s1, len0 + 1); + } + else + { + sl_strlcat(s1, "/", len1 + 2); + if (0 == strncmp(s0, s1, len1 + 1)) + { + size_t len = strlen(file); + SH_FREE(this->file); + this->file = sh_util_strdup(file); + if ((len > 1) && (file[len-1] == '/')) + this->file[len-1] = '\0'; + ret = 0; + } + } + SH_FREE(s0); + SH_FREE(s1); + } } return ret; @@ -396,13 +467,18 @@ static int test_exchange (struct aud_list * this, char * file) */ void sh_audit_mark (char * file) { - struct aud_list * this = mark_these; + struct aud_list * this; + if (marked_committed != 0) + delete_listofmarked(); + if (!mark_these) { add_this (file); return; } + this = mark_these; + while (this) { /* Check whether it is already covered by a higher @@ -410,6 +486,7 @@ void sh_audit_mark (char * file) */ if (0 == test_exchange(this, file)) return; + this = this->next; } @@ -419,20 +496,14 @@ void sh_audit_mark (char * file) void sh_audit_commit () { - struct aud_list * next; struct aud_list * this = mark_these; - mark_these = NULL; - while (this) { - sh_audit_mark_int (this->file); - next = this->next; - SH_FREE(this->file); - SH_FREE(this); - this = next; + sh_audit_mark_int (this->file, this->flags); + this = this->next; } - + marked_committed = 1; } static int sh_audit_checkdaemon() @@ -537,11 +608,12 @@ static int sh_audit_checkdaemon() /* HAVE_AUPARSE_H */ #else -char * sh_audit_fetch (char * file, time_t mtime, time_t ctime, char * result, size_t rsize) +char * sh_audit_fetch (char * file, time_t mtime, time_t ctime, time_t atime, char * result, size_t rsize) { (void) file; (void) mtime; (void) ctime; + (void) atime; (void) result; (void) rsize; @@ -563,6 +635,11 @@ void sh_audit_commit () { return; } +int sh_audit_set_flags(const char * str) +{ + (void) str; + return -1; +} #endif /* client || standalone */ |