summaryrefslogtreecommitdiffstats
path: root/src/sh_audit.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/sh_audit.c')
-rw-r--r--src/sh_audit.c183
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 */