Index: trunk/src/sh_audit.c
===================================================================
--- trunk/src/sh_audit.c	(revision 434)
+++ trunk/src/sh_audit.c	(revision 488)
@@ -28,10 +28,13 @@
 #include <errno.h>
 #include <unistd.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+
+#include "samhain.h"
+#include "sh_error.h"
 
 #if !defined(SH_COMPILE_STATIC) && defined(__linux__) && defined(HAVE_AUPARSE_H) && defined(HAVE_AUPARSE_LIB)
 #include <auparse.h>
 
-#include "samhain.h"
-#include "sh_error.h"
 #include "sh_extern.h"
 #include "sh_utils.h"
@@ -103,9 +106,10 @@
 }
     
-static char * doAuparse (char * file, time_t time, char * result, size_t rsize)
+static char * doAuparse (const char * file, time_t time, int tol, char * result, size_t rsize, int redo_flag)
 {
   struct recordState state;
   struct recordState stateFetched;
-
+  unsigned int       found_flag = 0;
+  
   auparse_state_t * au = auparse_init(AUSOURCE_LOGS, NULL);
 
@@ -131,6 +135,6 @@
   if (time != 0)
     {
-      ausearch_add_timestamp_item(au, ">=", time-1, 0, AUSEARCH_RULE_AND);
-      ausearch_add_timestamp_item(au, "<=", time+1, 0, AUSEARCH_RULE_AND);
+      ausearch_add_timestamp_item(au, ">=", time-tol, 0, AUSEARCH_RULE_AND);
+      ausearch_add_timestamp_item(au, "<=", time+tol, 0, AUSEARCH_RULE_AND);
     }
 
@@ -152,8 +156,25 @@
 	{
 	  memcpy(&state, &stateFetched, sizeof(state));
+	  ++found_flag;
 	}
       auparse_next_event(au);
     }
 
+  if (found_flag == 0 && redo_flag == S_FALSE)
+    {
+      size_t len = strlen(file);
+      char * path = SH_ALLOC(len + 2);
+      char * altres;
+      
+      sl_strlcpy(path, file, len+2);
+      path[len] = '/'; path[len+1] = '\0';
+      auparse_destroy(au);
+      
+      altres = doAuparse(path, time, tol, result, rsize, S_TRUE);
+
+      SH_FREE(path);
+      return altres;
+    }
+  
   if (0 == strcmp(state.success, "yes"))
     {
@@ -189,5 +210,5 @@
  * The 'result' array should be sized ~256 char. 
  */
-char * sh_audit_fetch (char * file, time_t time, char * result, size_t rsize)
+char * sh_audit_fetch (char * file, time_t mtime, time_t ctime, char * result, size_t rsize)
 {
   char * res = NULL;
@@ -195,10 +216,17 @@
   if (sh_audit_checkdaemon() >= 0)
     {
-      res = doAuparse (file, time, result, rsize);
+      time_t new;
+      char buf[64];
+      
+      if (mtime >= ctime) { new = mtime; }
+      else                { new = ctime; }
+
+      res = doAuparse (file, new, 1, result, rsize, S_FALSE);
 
       if (!res)
 	{
-	  res = doAuparse (file, 0, result, rsize);
+	  res = doAuparse (file, new, 3, result, rsize, S_FALSE);
 	}
+
     }
   return res;
@@ -226,4 +254,13 @@
 }
 
+static int  sh_audit_isdir(const char * file)
+{
+  struct stat buf;
+
+  if ( (0 == lstat (file, &buf)) && S_ISDIR(buf.st_mode))
+    return S_TRUE;
+  return S_FALSE;
+}
+
 static void sh_audit_mark_int (const char * file)
 {
@@ -246,4 +283,7 @@
       char * safe;
       char   ctl[64];
+      char   a1[32];
+      char   a2[32];
+      char   a3[32];
 
       sl_snprintf(command, len, _("%s -w %s -p wa -k samhain"),
@@ -256,4 +296,5 @@
 		       safe,
 		       _("sh_audit_mark") );
+
       SH_FREE(safe);
 
@@ -261,6 +302,24 @@
       sl_strlcpy(command, file, len);
 
-      sh_ext_system(ctl, ctl, "-w", command, "-p", "wa", "-k", _("samhain"), NULL);
-
+      sl_strlcpy(a3, _("samhain"), sizeof(a3));
+      sh_ext_system(ctl, ctl, "-w", command, "-p", "wa", "-k", a3, NULL);
+
+      /* Placing a watch on a directory will not place a watch on the
+       * directory inode, so we do this explicitely. 
+       */
+      if (S_TRUE == sh_audit_isdir(file))
+	{
+	  safe = sh_util_safe_name(file);
+	  sh_error_handle (SH_ERR_ALL, FIL__, __LINE__, 
+			   0, MSG_E_SUBGPATH,
+			   _("Add path watch for directory"),
+			   _("sh_audit_mark_int"), safe );
+	  SH_FREE(safe);
+	  sl_strlcpy(command, _("path="), len);
+	  sl_strlcat(command, file, len);
+	  sl_strlcpy(a1, _("always,exit"), sizeof(a1));
+	  sl_strlcpy(a2, _("perm=wa"), sizeof(a2));
+	  sh_ext_system(ctl, ctl, "-a", a1, "-F", command, "-F", a2, "-k", a3, NULL);
+	}
       SH_FREE(command);
     }
@@ -278,5 +337,10 @@
 {
   struct aud_list * this = SH_ALLOC(sizeof(struct aud_list));
+  size_t len = strlen(file);
+
   this->file = sh_util_strdup(file);
+  if ((len > 1) && (file[len-1] == '/'))
+    this->file[len-1] = '\0';
+  
   this->next = mark_these;
   mark_these = this;
@@ -284,4 +348,6 @@
 }
 
+/* Check whether it is already covered by a higher directory
+ */
 static int test_exchange (struct aud_list * this, char * file)
 {
@@ -312,6 +378,9 @@
 	   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;
 	     }
@@ -324,4 +393,6 @@
 }
 
+/* Place a path on the list of of paths to be watched
+ */
 void sh_audit_mark (char * file)
 {
@@ -335,4 +406,7 @@
   while (this)
     {
+      /* Check whether it is already covered by a higher
+       * directory 
+       */
       if (0 == test_exchange(this, file))
 	return;
@@ -464,8 +538,9 @@
 /* HAVE_AUPARSE_H */
 #else
-char * sh_audit_fetch (char * file, time_t time, char * result, size_t rsize)
+char * sh_audit_fetch (char * file, time_t mtime, time_t ctime, char * result, size_t rsize)
 {
   (void) file;
-  (void) time;
+  (void) mtime;
+  (void) ctime;
   (void) result;
   (void) rsize;
@@ -476,4 +551,7 @@
 {
   (void) file;
+  sh_error_handle(SH_ERR_WARN, FIL__, __LINE__, 0, MSG_E_SUBGEN,
+		  _("Setting audit watch not supported"),
+		  _("sh_audit_mark"));
   return;
 }
