new upstream release (3.3.0); modify package compatibility for Stretch
[ossec-hids.git] / src / analysisd / decoders / syscheck.c
old mode 100755 (executable)
new mode 100644 (file)
index 26350f3..a6d6758
@@ -1,6 +1,3 @@
-/* @(#) $Id: ./src/analysisd/decoders/syscheck.c, 2012/02/07 dcid Exp $
- */
-
 /* Copyright (C) 2009 Trend Micro Inc.
  * All right reserved.
  *
@@ -10,7 +7,6 @@
  * Foundation
  */
 
-
 /* Syscheck decoder */
 
 #include "eventinfo.h"
 #include "alerts/alerts.h"
 #include "decoder.h"
 
+#ifdef SQLITE_ENABLED
+#include "syscheck-sqlite.h"
+#endif
 
-typedef struct __sdb
-{
+typedef struct __sdb {
     char buf[OS_MAXSTR + 1];
-    char comment[OS_MAXSTR +1];
+    char comment[OS_MAXSTR + 1];
 
-    char size[OS_FLSIZE +1];
-    char perm[OS_FLSIZE +1];
-    char owner[OS_FLSIZE +1];
-    char gowner[OS_FLSIZE +1];
-    char md5[OS_FLSIZE +1];
-    char sha1[OS_FLSIZE +1];
+    char size[OS_FLSIZE + 1];
+    char perm[OS_FLSIZE + 1];
+    char owner[OS_FLSIZE + 1];
+    char gowner[OS_FLSIZE + 1];
+    char md5[OS_FLSIZE + 1];
+    char sha1[OS_FLSIZE + 1];
 
-    char agent_cp[MAX_AGENTS +1][1];
-    char *agent_ips[MAX_AGENTS +1];
-    FILE *agent_fps[MAX_AGENTS +1];
+    char agent_cp[MAX_AGENTS + 1][1];
+    char *agent_ips[MAX_AGENTS + 1];
+    FILE *agent_fps[MAX_AGENTS + 1];
 
     int db_err;
 
-
     /* Ids for decoder */
     int id1;
     int id2;
@@ -46,51 +43,74 @@ typedef struct __sdb
     int idn;
     int idd;
 
-
     /* Syscheck rule */
     OSDecoderInfo  *syscheck_dec;
 
-
     /* File search variables */
     fpos_t init_pos;
 
-}_sdb; /* syscheck db information */
-
+} _sdb; /* syscheck db information */
+
+/* Local variables */
+static _sdb sdb;
+
+/* Extract a token from a string */
+char *extract_token(const char *s, char *delim, int position) {
+    int count = 0;
+    char tmp[OS_MAXSTR + 1];
+    char *token;
+    strncpy(tmp,s, OS_MAXSTR);
+    token = strtok(tmp, delim);
+    while (token != NULL) {
+        count++;
+        token = strtok(NULL, delim);
+        if (count == position) {
+            return(token);
+        }
+    }
+    return(NULL);
+}
 
-/* Global variable */
-_sdb sdb;
 
+/* Validate a MD5 string format */
+int validate_md5(char *s) {
+    unsigned int i;
+    char *hex_chars = "abcdefABCDEF0123456789";
+    if (strlen(s) != 32) {
+        return(0);
+    }
+    for (i = 0; i < strlen(s); i++) {
+        if (!strchr(hex_chars, s[i])) return(0);
+    }
+    return(1);
+}
 
 
-/* SyscheckInit
- * Initialize the necessary information to process the syscheck information
- */
+/* Initialize the necessary information to process the syscheck information */
 void SyscheckInit()
 {
     int i = 0;
 
     sdb.db_err = 0;
 
-    for(;i <= MAX_AGENTS;i++)
-    {
+    for (; i <= MAX_AGENTS; i++) {
         sdb.agent_ips[i] = NULL;
         sdb.agent_fps[i] = NULL;
         sdb.agent_cp[i][0] = '0';
     }
 
-    /* Clearing db memory */
-    memset(sdb.buf, '\0', OS_MAXSTR +1);
-    memset(sdb.comment, '\0', OS_MAXSTR +1);
+    /* Clear db memory */
+    memset(sdb.buf, '\0', OS_MAXSTR + 1);
+    memset(sdb.comment, '\0', OS_MAXSTR + 1);
 
-    memset(sdb.size, '\0', OS_FLSIZE +1);
-    memset(sdb.perm, '\0', OS_FLSIZE +1);
-    memset(sdb.owner, '\0', OS_FLSIZE +1);
-    memset(sdb.gowner, '\0', OS_FLSIZE +1);
-    memset(sdb.md5, '\0', OS_FLSIZE +1);
-    memset(sdb.sha1, '\0', OS_FLSIZE +1);
+    memset(sdb.size, '\0', OS_FLSIZE + 1);
+    memset(sdb.perm, '\0', OS_FLSIZE + 1);
+    memset(sdb.owner, '\0', OS_FLSIZE + 1);
+    memset(sdb.gowner, '\0', OS_FLSIZE + 1);
+    memset(sdb.md5, '\0', OS_FLSIZE + 1);
+    memset(sdb.sha1, '\0', OS_FLSIZE + 1);
 
-
-    /* Creating decoder */
+    /* Create decoder */
     os_calloc(1, sizeof(OSDecoderInfo), sdb.syscheck_dec);
     sdb.syscheck_dec->id = getDecoderfromlist(SYSCHECK_MOD);
     sdb.syscheck_dec->name = SYSCHECK_MOD;
@@ -107,67 +127,54 @@ void SyscheckInit()
     return;
 }
 
-/* DB_IsCompleted
- * Checks if the db is completed for that specific agent.
- */
+/* Check if the db is completed for that specific agent */
 #define DB_IsCompleted(x) (sdb.agent_cp[x][0] == '1')?1:0
 
-
-void __setcompleted(char *agent)
+static void __setcompleted(const char *agent)
 {
     FILE *fp;
 
-    /* Getting agent file */
+    /* Get agent file */
     snprintf(sdb.buf, OS_FLSIZE , "%s/.%s.cpt", SYSCHECK_DIR, agent);
 
-    fp = fopen(sdb.buf,"w");
-    if(fp)
-    {
+    fp = fopen(sdb.buf, "w");
+    if (fp) {
         fprintf(fp, "#!X");
         fclose(fp);
     }
 }
 
-
-int __iscompleted(char *agent)
+static int __iscompleted(const char *agent)
 {
     FILE *fp;
 
-    /* Getting agent file */
+    /* Get agent file */
     snprintf(sdb.buf, OS_FLSIZE , "%s/.%s.cpt", SYSCHECK_DIR, agent);
 
-    fp = fopen(sdb.buf,"r");
-    if(fp)
-    {
+    fp = fopen(sdb.buf, "r");
+    if (fp) {
         fclose(fp);
-        return(1);
+        return (1);
     }
-    return(0);
+    return (0);
 }
 
-
-/* void DB_SetCompleted(Eventinfo *lf).
- * Set the database of a specific agent as completed.
- */
-void DB_SetCompleted(Eventinfo *lf)
+/* Set the database of a specific agent as completed */
+static void DB_SetCompleted(const Eventinfo *lf)
 {
     int i = 0;
 
-    /* Finding file pointer */
-    while(sdb.agent_ips[i] != NULL &&  i < MAX_AGENTS)
-    {
-        if(strcmp(sdb.agent_ips[i], lf->location) == 0)
-        {
-            /* Return if already set as completed. */
-            if(DB_IsCompleted(i))
-            {
+    /* Find file pointer */
+    while (sdb.agent_ips[i] != NULL &&  i < MAX_AGENTS) {
+        if (strcmp(sdb.agent_ips[i], lf->location) == 0) {
+            /* Return if already set as completed */
+            if (DB_IsCompleted(i)) {
                 return;
             }
 
             __setcompleted(lf->location);
 
-
-            /* Setting as completed in memory */
+            /* Set as completed in memory */
             sdb.agent_cp[i][0] = '1';
             return;
         }
@@ -177,87 +184,71 @@ void DB_SetCompleted(Eventinfo *lf)
 }
 
 
-/* DB_File
- * Return the file pointer to be used to verify the integrity
- */
-FILE *DB_File(char *agent, int *agent_id)
+/* Return the file pointer to be used to verify the integrity */
+static FILE *DB_File(const char *agent, int *agent_id)
 {
     int i = 0;
 
-    /* Finding file pointer */
-    while(sdb.agent_ips[i] != NULL  &&  i < MAX_AGENTS)
-    {
-        if(strcmp(sdb.agent_ips[i], agent) == 0)
-        {
-            /* Pointing to the beginning of the file */
-            fseek(sdb.agent_fps[i],0, SEEK_SET);
+    /* Find file pointer */
+    while (sdb.agent_ips[i] != NULL  &&  i < MAX_AGENTS) {
+        if (strcmp(sdb.agent_ips[i], agent) == 0) {
+            /* Point to the beginning of the file */
+            fseek(sdb.agent_fps[i], 0, SEEK_SET);
             *agent_id = i;
-            return(sdb.agent_fps[i]);
+            return (sdb.agent_fps[i]);
         }
 
         i++;
     }
 
     /* If here, our agent wasn't found */
-    if (i == MAX_AGENTS)
-    {
-        merror("%s: Unable to open integrity file. Increase MAX_AGENTS.",ARGV0);
-        return(NULL);
+    if (i == MAX_AGENTS) {
+        merror("%s: Unable to open integrity file. Increase MAX_AGENTS.", ARGV0);
+        return (NULL);
     }
 
     os_strdup(agent, sdb.agent_ips[i]);
 
-
-    /* Getting agent file */
-    snprintf(sdb.buf, OS_FLSIZE , "%s/%s", SYSCHECK_DIR,agent);
-
+    /* Get agent file */
+    snprintf(sdb.buf, OS_FLSIZE , "%s/%s", SYSCHECK_DIR, agent);
 
     /* r+ to read and write. Do not truncate */
-    sdb.agent_fps[i] = fopen(sdb.buf,"r+");
-    if(!sdb.agent_fps[i])
-    {
-        /* try opening with a w flag, file probably does not exist */
+    sdb.agent_fps[i] = fopen(sdb.buf, "r+");
+    if (!sdb.agent_fps[i]) {
+        /* Try opening with a w flag, file probably does not exist */
         sdb.agent_fps[i] = fopen(sdb.buf, "w");
-        if(sdb.agent_fps[i])
-        {
+        if (sdb.agent_fps[i]) {
             fclose(sdb.agent_fps[i]);
             sdb.agent_fps[i] = fopen(sdb.buf, "r+");
         }
     }
 
-    /* Checking again */
-    if(!sdb.agent_fps[i])
-    {
-        merror("%s: Unable to open '%s'",ARGV0, sdb.buf);
+    /* Check again */
+    if (!sdb.agent_fps[i]) {
+        merror("%s: Unable to open '%s'", ARGV0, sdb.buf);
 
         free(sdb.agent_ips[i]);
         sdb.agent_ips[i] = NULL;
-        return(NULL);
+        return (NULL);
     }
 
-
-    /* Returning the opened pointer (the beginning of it) */
-    fseek(sdb.agent_fps[i],0, SEEK_SET);
+    /* Return the opened pointer (the beginning of it) */
+    fseek(sdb.agent_fps[i], 0, SEEK_SET);
     *agent_id = i;
 
-
-    /* Getting if the agent was completed */
-    if(__iscompleted(agent))
-    {
+    /* Check if the agent was completed */
+    if (__iscompleted(agent)) {
         sdb.agent_cp[i][0] = '1';
     }
 
-    return(sdb.agent_fps[i]);
+    return (sdb.agent_fps[i]);
 }
 
-
-/* DB_Search
- * Search the DB for any entry related to the file being received
- */
-int DB_Search(char *f_name, char *c_sum, Eventinfo *lf)
+/* Search the DB for any entry related to the file being received */
+static int DB_Search(const char *f_name, const char *c_sum, Eventinfo *lf)
 {
     int p = 0;
-    int sn_size;
+    size_t sn_size;
     int agent_id;
 
     char *saved_sum;
@@ -265,181 +256,159 @@ int DB_Search(char *f_name, char *c_sum, Eventinfo *lf)
 
     FILE *fp;
 
+    /* Expose filename variable for active response */
+    os_strdup(f_name, lf->filename);
+
 
-    /* Getting db pointer */
+
+    /* Get db pointer */
     fp = DB_File(lf->location, &agent_id);
-    if(!fp)
-    {
-        merror("%s: Error handling integrity database.",ARGV0);
-        sdb.db_err++; /* Increment db error */
+    if (!fp) {
+        merror("%s: Error handling integrity database.", ARGV0);
+        sdb.db_err++;
         lf->data = NULL;
-        return(0);
+        return (0);
     }
 
-
-    /* Reads the integrity file and search for a possible
-     * entry
-     */
-    if(fgetpos(fp, &sdb.init_pos) == -1)
-    {
-        merror("%s: Error handling integrity database (fgetpos).",ARGV0);
-        return(0);
+    /* Read the integrity file and search for a possible entry */
+    if (fgetpos(fp, &sdb.init_pos) == -1) {
+        merror("%s: Error handling integrity database (fgetpos).", ARGV0);
+        return (0);
     }
 
-
-    /* Looping the file */
-    while(fgets(sdb.buf, OS_MAXSTR, fp) != NULL)
-    {
+    /* Loop over the file */
+    while (fgets(sdb.buf, OS_MAXSTR, fp) != NULL) {
         /* Ignore blank lines and lines with a comment */
-        if(sdb.buf[0] == '\n' || sdb.buf[0] == '#')
-        {
-            fgetpos(fp, &sdb.init_pos); /* getting next location */
+        if (sdb.buf[0] == '\n' || sdb.buf[0] == '#') {
+            fgetpos(fp, &sdb.init_pos); /* Get next location */
             continue;
         }
 
-
-        /* Getting name */
+        /* Get name */
         saved_name = strchr(sdb.buf, ' ');
-        if(saved_name == NULL)
-        {
-            merror("%s: Invalid integrity message in the database.",ARGV0);
-            fgetpos(fp, &sdb.init_pos); /* getting next location */
+        if (saved_name == NULL) {
+            merror("%s: Invalid integrity message in the database.", ARGV0);
+            fgetpos(fp, &sdb.init_pos); /* Get next location */
             continue;
         }
         *saved_name = '\0';
         saved_name++;
 
-
         /* New format - with a timestamp */
-        if(*saved_name == '!')
-        {
+        if (*saved_name == '!') {
             saved_name = strchr(saved_name, ' ');
-            if(saved_name == NULL)
-            {
-                merror("%s: Invalid integrity message in the database",ARGV0);
-                fgetpos(fp, &sdb.init_pos); /* getting next location */
+            if (saved_name == NULL) {
+                merror("%s: Invalid integrity message in the database", ARGV0);
+                fgetpos(fp, &sdb.init_pos); /* Get next location */
                 continue;
             }
             saved_name++;
         }
 
-
-        /* Removing new line from saved_name */
+        /* Remove newline from saved_name */
         sn_size = strlen(saved_name);
         sn_size -= 1;
-        if(saved_name[sn_size] == '\n')
+        if (saved_name[sn_size] == '\n') {
             saved_name[sn_size] = '\0';
+        }
 
-
-        /* If name is different, go to next one. */
-        if(strcmp(f_name,saved_name) != 0)
-        {
-            /* Saving currently location */
+        /* If name is different, go to next one */
+        if (strcmp(f_name, saved_name) != 0) {
+            /* Save current location */
             fgetpos(fp, &sdb.init_pos);
             continue;
         }
 
-
         saved_sum = sdb.buf;
 
-
         /* First three bytes are for frequency check */
-        saved_sum+=3;
-
+        saved_sum += 3;
 
-        /* checksum match, we can just return and keep going */
-        if(strcmp(saved_sum, c_sum) == 0)
-        {
+        /* Checksum match, we can just return and keep going */
+        if (strcmp(saved_sum, c_sum) == 0) {
             lf->data = NULL;
-            return(0);
+            return (0);
         }
 
 
+
+
         /* If we reached here, the checksum of the file has changed */
-        if(saved_sum[-3] == '!')
-        {
+        if (saved_sum[-3] == '!') {
             p++;
-            if(saved_sum[-2] == '!')
-            {
+            if (saved_sum[-2] == '!') {
                 p++;
-                if(saved_sum[-1] == '!')
+                if (saved_sum[-1] == '!') {
                     p++;
-                else if(saved_sum[-1] == '?')
-                    p+=2;
+                } else if (saved_sum[-1] == '?') {
+                    p += 2;
+                }
             }
         }
 
-
-        /* Checking the number of changes */
-        if(!Config.syscheck_auto_ignore)
-        {
+        /* Check the number of changes */
+        if (!Config.syscheck_auto_ignore) {
             sdb.syscheck_dec->id = sdb.id1;
-        }
-        else
-        {
-            switch(p)
-            {
+        } else {
+            switch (p) {
                 case 0:
-                sdb.syscheck_dec->id = sdb.id1;
-                break;
+                    sdb.syscheck_dec->id = sdb.id1;
+                    break;
 
                 case 1:
-                sdb.syscheck_dec->id = sdb.id2;
-                break;
+                    sdb.syscheck_dec->id = sdb.id2;
+                    break;
 
                 case 2:
-                sdb.syscheck_dec->id = sdb.id3;
-                break;
+                    sdb.syscheck_dec->id = sdb.id3;
+                    break;
 
                 default:
-                lf->data = NULL;
-                return(0);
-                break;
+                    lf->data = NULL;
+                    return (0);
+                    break;
             }
         }
 
+        /* Add new checksum to the database */
+        /* Commenting the file entry and adding a new one later */
+        if (fsetpos(fp, &sdb.init_pos)) {
+            merror("%s: Error handling integrity database (fsetpos).", ARGV0);
+            return (0);
+        }
+        fputc('#', fp);
 
-        /* Adding new checksum to the database */
-        /* Commenting the file entry and adding a new one latter */
-        fsetpos(fp, &sdb.init_pos);
-        fputc('#',fp);
-
-
-        /* Adding the new entry at the end of the file */
+        /* Add the new entry at the end of the file */
         fseek(fp, 0, SEEK_END);
-        fprintf(fp,"%c%c%c%s !%d %s\n",
+        fprintf(fp, "%c%c%c%s !%ld %s\n",
                 '!',
-                p >= 1? '!' : '+',
-                p == 2? '!' : (p > 2)?'?':'+',
+                p >= 1 ? '!' : '+',
+                p == 2 ? '!' : (p > 2) ? '?' : '+',
                 c_sum,
-                lf->time,
+                (long int)lf->time,
                 f_name);
         fflush(fp);
 
-
         /* File deleted */
-        if(c_sum[0] == '-' && c_sum[1] == '1')
-        {
+        if (c_sum[0] == '-' && c_sum[1] == '1') {
             sdb.syscheck_dec->id = sdb.idd;
             snprintf(sdb.comment, OS_MAXSTR,
-                    "File '%.756s' was deleted. Unable to retrieve "
-                    "checksum.", f_name);
+                     "File '%.756s' was deleted. Unable to retrieve "
+                     "checksum.", f_name);
         }
 
         /* If file was re-added, do not compare changes */
-        else if(saved_sum[0] == '-' && saved_sum[1] == '1')
-        {
+        else if (saved_sum[0] == '-' && saved_sum[1] == '1') {
             sdb.syscheck_dec->id = sdb.idn;
             snprintf(sdb.comment, OS_MAXSTR,
                      "File '%.756s' was re-added.", f_name);
         }
 
-        else
-        {
+        else {
             int oldperm = 0, newperm = 0;
 
-            /* Providing more info about the file change */
-            char *oldsize = NULL, *newsize = NULL;
+            /* Provide more info about the file change */
+            const char *oldsize = NULL, *newsize = NULL;
             char *olduid = NULL, *newuid = NULL;
             char *c_oldperm = NULL, *c_newperm = NULL;
             char *oldgid = NULL, *newgid = NULL;
@@ -453,8 +422,7 @@ int DB_Search(char *f_name, char *c_sum, Eventinfo *lf)
             c_newperm = strchr(c_sum, ':');
 
             /* Get old/new permissions */
-            if(c_oldperm && c_newperm)
-            {
+            if (c_oldperm && c_newperm) {
                 *c_oldperm = '\0';
                 c_oldperm++;
 
@@ -465,47 +433,38 @@ int DB_Search(char *f_name, char *c_sum, Eventinfo *lf)
                 olduid = strchr(c_oldperm, ':');
                 newuid = strchr(c_newperm, ':');
 
-                if(olduid && newuid)
-                {
+                if (olduid && newuid) {
                     *olduid = '\0';
                     *newuid = '\0';
-
                     olduid++;
                     newuid++;
 
                     oldgid = strchr(olduid, ':');
                     newgid = strchr(newuid, ':');
 
-                    if(oldgid && newgid)
-                    {
+                    if (oldgid && newgid) {
                         *oldgid = '\0';
                         *newgid = '\0';
-
                         oldgid++;
                         newgid++;
 
-
-                        /* Getting md5 */
+                        /* Get MD5 */
                         oldmd5 = strchr(oldgid, ':');
                         newmd5 = strchr(newgid, ':');
 
-                        if(oldmd5 && newmd5)
-                        {
+                        if (oldmd5 && newmd5) {
                             *oldmd5 = '\0';
                             *newmd5 = '\0';
-
                             oldmd5++;
                             newmd5++;
 
-                            /* getting sha1 */
+                            /* Get SHA-1 */
                             oldsha1 = strchr(oldmd5, ':');
                             newsha1 = strchr(newmd5, ':');
 
-                            if(oldsha1 && newsha1)
-                            {
+                            if (oldsha1 && newsha1) {
                                 *oldsha1 = '\0';
                                 *newsha1 = '\0';
-
                                 oldsha1++;
                                 newsha1++;
                             }
@@ -514,290 +473,253 @@ int DB_Search(char *f_name, char *c_sum, Eventinfo *lf)
                 }
             }
 
-            /* Getting integer values */
-            if(c_newperm && c_oldperm)
-            {
+            /* Get integer values */
+            if (c_newperm && c_oldperm) {
                 newperm = atoi(c_newperm);
                 oldperm = atoi(c_oldperm);
             }
 
-            /* Generating size message */
-            if(!oldsize || !newsize || strcmp(oldsize, newsize) == 0)
-            {
+            /* Generate size message */
+            if (!oldsize || !newsize || strcmp(oldsize, newsize) == 0) {
                 sdb.size[0] = '\0';
-            }
-            else
-            {
+            } else {
                 snprintf(sdb.size, OS_FLSIZE,
-                        "Size changed from '%s' to '%s'\n",
-                        oldsize, newsize);
+                         "Size changed from '%s' to '%s'\n",
+                         oldsize, newsize);
 
                 os_strdup(oldsize, lf->size_before);
                 os_strdup(newsize, lf->size_after);
             }
 
             /* Permission message */
-            if(oldperm == newperm)
-            {
+            if (oldperm == newperm) {
                 sdb.perm[0] = '\0';
-            }
-            else if(oldperm > 0 && newperm > 0)
-            {
-
-                snprintf(sdb.perm, OS_FLSIZE, "Permissions changed from "
-                        "'%c%c%c%c%c%c%c%c%c' "
-                        "to '%c%c%c%c%c%c%c%c%c'\n",
-                        (oldperm & S_IRUSR)? 'r' : '-',
-                        (oldperm & S_IWUSR)? 'w' : '-',
-
-                        (oldperm & S_ISUID)? 's' :
-                        (oldperm & S_IXUSR)? 'x' : '-',
-
-                        (oldperm & S_IRGRP)? 'r' : '-',
-                        (oldperm & S_IWGRP)? 'w' : '-',
-
-                        (oldperm & S_ISGID)? 's' :
-                        (oldperm & S_IXGRP)? 'x' : '-',
+            } else if (oldperm > 0 && newperm > 0) {
+               char opstr[10];
+               char npstr[10];
 
-                        (oldperm & S_IROTH)? 'r' : '-',
-                        (oldperm & S_IWOTH)? 'w' : '-',
+               strncpy(opstr, agent_file_perm(c_oldperm), sizeof(opstr) - 1);
+               strncpy(npstr, agent_file_perm(c_newperm), sizeof(npstr) - 1);
 
-                        (oldperm & S_ISVTX)? 't' :
-                        (oldperm & S_IXOTH)? 'x' : '-',
-
-
-
-                        (newperm & S_IRUSR)? 'r' : '-',
-                        (newperm & S_IWUSR)? 'w' : '-',
-
-                        (newperm & S_ISUID)? 's' :
-                        (newperm & S_IXUSR)? 'x' : '-',
-
-
-                        (newperm & S_IRGRP)? 'r' : '-',
-                        (newperm & S_IWGRP)? 'w' : '-',
-
-                        (newperm & S_ISGID)? 's' :
-                        (newperm & S_IXGRP)? 'x' : '-',
-
-                        (newperm & S_IROTH)? 'r' : '-',
-                        (newperm & S_IWOTH)? 'w' : '-',
-
-                        (newperm & S_ISVTX)? 't' :
-                        (newperm & S_IXOTH)? 'x' : '-');
+                snprintf(sdb.perm, OS_FLSIZE, "Permissions changed from "
+                         "'%9.9s' to '%9.9s'\n", opstr, npstr);
 
                 lf->perm_before = oldperm;
                 lf->perm_after = newperm;
             }
 
             /* Ownership message */
-            if(!newuid || !olduid || strcmp(newuid, olduid) == 0)
-            {
+            if (!newuid || !olduid || strcmp(newuid, olduid) == 0) {
                 sdb.owner[0] = '\0';
-            }
-            else
-            {
+            } else {
                 snprintf(sdb.owner, OS_FLSIZE, "Ownership was '%s', "
-                        "now it is '%s'\n",
-                        olduid, newuid);
+                         "now it is '%s'\n",
+                         olduid, newuid);
 
 
                 os_strdup(olduid, lf->owner_before);
                 os_strdup(newuid, lf->owner_after);
             }
 
-            /* group ownership message */
-            if(!newgid || !oldgid || strcmp(newgid, oldgid) == 0)
-            {
+            /* Group ownership message */
+            if (!newgid || !oldgid || strcmp(newgid, oldgid) == 0) {
                 sdb.gowner[0] = '\0';
-            }
-            else
-            {
-                snprintf(sdb.gowner, OS_FLSIZE,"Group ownership was '%s', "
-                        "now it is '%s'\n",
-                        oldgid, newgid);
+            } else {
+                snprintf(sdb.gowner, OS_FLSIZE, "Group ownership was '%s', "
+                         "now it is '%s'\n",
+                         oldgid, newgid);
                 os_strdup(oldgid, lf->gowner_before);
                 os_strdup(newgid, lf->gowner_after);
             }
 
-            /* md5 message */
-            if(!newmd5 || !oldmd5 || strcmp(newmd5, oldmd5) == 0)
-            {
+            /* MD5 message */
+            if (!newmd5 || !oldmd5 || strcmp(newmd5, oldmd5) == 0) {
                 sdb.md5[0] = '\0';
-            }
-            else
-            {
+            } else {
                 snprintf(sdb.md5, OS_FLSIZE, "Old md5sum was: '%s'\n"
-                        "New md5sum is : '%s'\n",
-                        oldmd5, newmd5);
+                         "New md5sum is : '%s'\n",
+                         oldmd5, newmd5);
                 os_strdup(oldmd5, lf->md5_before);
                 os_strdup(newmd5, lf->md5_after);
             }
 
-            /* sha1 */
-            if(!newsha1 || !oldsha1 || strcmp(newsha1, oldsha1) == 0)
-            {
+            /* SHA-1 message */
+            if (!newsha1 || !oldsha1 || strcmp(newsha1, oldsha1) == 0) {
                 sdb.sha1[0] = '\0';
-            }
-            else
-            {
+            } else {
                 snprintf(sdb.sha1, OS_FLSIZE, "Old sha1sum was: '%s'\n"
-                        "New sha1sum is : '%s'\n",
-                        oldsha1, newsha1);
+                         "New sha1sum is : '%s'\n",
+                         oldsha1, newsha1);
                 os_strdup(oldsha1, lf->sha1_before);
                 os_strdup(newsha1, lf->sha1_after);
             }
-            os_strdup(f_name, lf->filename);
-
 
             /* Provide information about the file */
             snprintf(sdb.comment, OS_MAXSTR, "Integrity checksum changed for: "
-                    "'%.756s'\n"
-                    "%s"
-                    "%s"
-                    "%s"
-                    "%s"
-                    "%s"
-                    "%s"
-                    "%s%s",
-                    f_name,
-                    sdb.size,
-                    sdb.perm,
-                    sdb.owner,
-                    sdb.gowner,
-                    sdb.md5,
-                    sdb.sha1,
-                    lf->data == NULL?"":"What changed:\n",
-                    lf->data == NULL?"":lf->data
+                     "'%.756s'\n"
+                     "%s"
+                     "%s"
+                     "%s"
+                     "%s"
+                     "%s"
+                     "%s"
+                     "%s%s",
+                     f_name,
+                     sdb.size,
+                     sdb.perm,
+                     sdb.owner,
+                     sdb.gowner,
+                     sdb.md5,
+                     sdb.sha1,
+                     lf->data == NULL ? "" : "What changed:\n",
+                     lf->data == NULL ? "" : lf->data
                     );
         }
 
-
-        /* Creating a new log message */
+        /* Create a new log message */
         free(lf->full_log);
         os_strdup(sdb.comment, lf->full_log);
         lf->log = lf->full_log;
         lf->data = NULL;
 
-
-        /* Setting decoder */
+        /* Set decoder */
         lf->decoder_info = sdb.syscheck_dec;
 
+        return (1);
 
-        return(1);
+    } /* Continue */
 
-    } /* continuiing... */
-
-
-    /* If we reach here, this file is not present on our database */
+    /* If we reach here, this file is not present in our database */
     fseek(fp, 0, SEEK_END);
-
-    fprintf(fp,"+++%s !%d %s\n", c_sum, lf->time, f_name);
-
+    fprintf(fp, "+++%s !%ld %s\n", c_sum, (long int)lf->time, f_name);
     fflush(fp);
 
     /* Alert if configured to notify on new files */
-    if((Config.syscheck_alert_new == 1) && (DB_IsCompleted(agent_id)))
-    {
+    /* TODO: debugging this - Scott */
+    /* if ((Config.syscheck_alert_new == 1) && (DB_IsCompleted(agent_id))) { */
+    if (Config.syscheck_alert_new == 1)  {
         sdb.syscheck_dec->id = sdb.idn;
 
         /* New file message */
         snprintf(sdb.comment, OS_MAXSTR,
-                              "New file '%.756s' "
-                              "added to the file system.", f_name);
+                 "New file '%.756s' "
+                 "added to the file system.", f_name);
 
 
-        /* Creating a new log message */
+        /* Create a new log message */
         free(lf->full_log);
         os_strdup(sdb.comment, lf->full_log);
         lf->log = lf->full_log;
 
-
-        /* Setting decoder */
+        /* Set decoder */
         lf->decoder_info = sdb.syscheck_dec;
         lf->data = NULL;
 
-        return(1);
+        return (1);
     }
 
     lf->data = NULL;
-    return(0);
+    return (0);
 }
 
-
 /* Special decoder for syscheck
  * Not using the default decoding lib for simplicity
  * and to be less resource intensive
  */
 int DecodeSyscheck(Eventinfo *lf)
 {
-    char *c_sum;
+    const char *c_sum;
     char *f_name;
 
+#ifdef SQLITE_ENABLED
+    char *p;
+    char stmt[OS_MAXSTR + 1];
+    sqlite3_stmt *res;
+    int error = 0;
+    int rec_count = 0;
+    const char *tail;
+#endif // SQLITE_ENABLED
 
     /* Every syscheck message must be in the following format:
      * checksum filename
      */
     f_name = strchr(lf->log, ' ');
-    if(f_name == NULL)
-    {
+    if (f_name == NULL) {
         /* If we don't have a valid syscheck message, it may be
-         * a database completed message.
+         * a database completed message
          */
-        if(strcmp(lf->log, HC_SK_DB_COMPLETED) == 0)
-        {
+        if (strcmp(lf->log, HC_SK_DB_COMPLETED) == 0) {
             DB_SetCompleted(lf);
-            return(0);
+            return (0);
         }
 
         merror(SK_INV_MSG, ARGV0);
-        return(0);
+        return (0);
     }
 
-
-    /* Zeroing to get the check sum */
+    /* Zero to get the check sum */
     *f_name = '\0';
     f_name++;
 
-
-    /* Getting diff. */
+    /* Get diff */
     lf->data = strchr(f_name, '\n');
-    if(lf->data)
-    {
+    if (lf->data) {
         *lf->data = '\0';
         lf->data++;
-    }
-    else
-    {
+    } else {
         lf->data = NULL;
     }
 
-
-
-    /* Checking if file is supposed to be ignored */
-    if(Config.syscheck_ignore)
-    {
+    /* Check if file is supposed to be ignored */
+    if (Config.syscheck_ignore) {
         char **ff_ig = Config.syscheck_ignore;
 
-        while(*ff_ig)
-        {
-            if(strncasecmp(*ff_ig, f_name, strlen(*ff_ig)) == 0)
-            {
+        while (*ff_ig) {
+            if (strncasecmp(*ff_ig, f_name, strlen(*ff_ig)) == 0) {
                 lf->data = NULL;
-                return(0);
+                return (0);
             }
 
             ff_ig++;
         }
     }
 
-
     /* Checksum is at the beginning of the log */
     c_sum = lf->log;
 
+    /* Extract the MD5 hash and search for it in the allowlist
+     * Sample message:
+     * 0:0:0:0:78f5c869675b1d09ddad870adad073f9:bd6c8d7a58b462aac86475e59af0e22954039c50
+     */
+#ifdef SQLITE_ENABLED
+    if (Config.md5_allowlist)  {
+        extern sqlite3 *conn;
+        if ((p = extract_token(c_sum, ":", 4))) {
+            if (!validate_md5(p)) { /* Never trust input from other origin */
+                merror("%s: Not a valid MD5 hash: '%s'", ARGV0, p);
+                return(0);
+            }
+            debug1("%s: Checking MD5 '%s' in %s", ARGV0, p, Config.md5_allowlist);
+            sprintf(stmt, "select md5sum from files where md5sum = \"%s\"", p);
+            error = sqlite3_prepare_v2(conn, stmt, 1000, &res, &tail);
+            if (error == SQLITE_OK) {
+                while (sqlite3_step(res) == SQLITE_ROW) {
+                    rec_count++;
+                }
+                if (rec_count) {    
+                    sqlite3_finalize(res);
+                    //sqlite3_close(conn);
+                    merror(MD5_NOT_CHECKED, ARGV0, p);
+                    return(0);
+                }
+            }
+            sqlite3_finalize(res);
+        }
+    }
+#endif
 
-    /* Searching for file changes */
-    return(DB_Search(f_name, c_sum, lf));
+    /* Search for file changes */
+    return (DB_Search(f_name, c_sum, lf));
 }
 
-/* EOF */