new upstream release (3.3.0); modify package compatibility for Stretch
[ossec-hids.git] / src / config / syscheck-config.c
old mode 100755 (executable)
new mode 100644 (file)
index 5995cf7..cc4946e
@@ -1,6 +1,3 @@
-/* @(#) $Id: ./src/config/syscheck-config.c, 2011/09/08 dcid Exp $
- */
-
 /* Copyright (C) 2009 Trend Micro Inc.
  * All right reserved.
  *
  * Foundation
  */
 
-
 #include "shared.h"
-
 #include "syscheck-config.h"
+#include "config.h"
 
 
-
-int dump_syscheck_entry(syscheck_config *syscheck, char *entry, int vals, int reg, char *restrictfile)
+int dump_syscheck_entry(syscheck_config *syscheck, const char *entry, int vals, int reg, const char *restrictfile)
 {
-    int pl = 0;
+    unsigned int pl = 0;
 
-    if(reg == 1)
-    {
-        #ifdef WIN32
-        if(syscheck->registry == NULL)
-        {
+    if (reg == 1) {
+#ifdef WIN32
+        if (syscheck->registry == NULL) {
             os_calloc(2, sizeof(char *), syscheck->registry);
             syscheck->registry[pl + 1] = NULL;
             os_strdup(entry, syscheck->registry[pl]);
-        }
-        else
-        {
-            while(syscheck->registry[pl] != NULL)
-            {
+        } else {
+            while (syscheck->registry[pl] != NULL) {
                 pl++;
             }
-            os_realloc(syscheck->registry, (pl +2) * sizeof(char *),
-                        syscheck->registry);
+            os_realloc(syscheck->registry, (pl + 2) * sizeof(char *),
+                       syscheck->registry);
             syscheck->registry[pl + 1] = NULL;
             os_strdup(entry, syscheck->registry[pl]);
         }
-        #endif
-
+#endif
     }
 
-
-    else
-    {
-        if(syscheck->dir == NULL)
-        {
+    else {
+        if (syscheck->dir == NULL) {
             os_calloc(2, sizeof(char *), syscheck->dir);
             syscheck->dir[pl + 1] = NULL;
             os_strdup(entry, syscheck->dir[pl]);
@@ -61,38 +47,33 @@ int dump_syscheck_entry(syscheck_config *syscheck, char *entry, int vals, int re
             os_calloc(2, sizeof(OSMatch *), syscheck->filerestrict);
             syscheck->filerestrict[pl] = NULL;
             syscheck->filerestrict[pl + 1] = NULL;
-        }
-        else
-        {
-            while(syscheck->dir[pl] != NULL)
-            {
+        } else {
+            while (syscheck->dir[pl] != NULL) {
                 pl++;
             }
-            os_realloc(syscheck->dir, (pl +2) * sizeof(char *),
+            os_realloc(syscheck->dir, (pl + 2) * sizeof(char *),
                        syscheck->dir);
             syscheck->dir[pl + 1] = NULL;
             os_strdup(entry, syscheck->dir[pl]);
 
-            os_realloc(syscheck->opts, (pl +2) * sizeof(int),
+            os_realloc(syscheck->opts, (pl + 2) * sizeof(int),
                        syscheck->opts);
             syscheck->opts[pl + 1] = 0;
             syscheck->opts[pl] = vals;
 
-            os_realloc(syscheck->filerestrict, (pl +2) * sizeof(char *),
+            os_realloc(syscheck->filerestrict, (pl + 2) * sizeof(OSMatch *),
                        syscheck->filerestrict);
             syscheck->filerestrict[pl] = NULL;
             syscheck->filerestrict[pl + 1] = NULL;
         }
-        if(restrictfile)
-        {
+        if (restrictfile) {
             os_calloc(1, sizeof(OSMatch), syscheck->filerestrict[pl]);
-            if(!OSMatch_Compile(restrictfile, syscheck->filerestrict[pl], 0))
-            {
+            if (!OSMatch_Compile(restrictfile, syscheck->filerestrict[pl], 0)) {
                 OSMatch *ptm;
 
                 ptm = syscheck->filerestrict[pl];
 
-                merror(REGEX_COMPILE, ARGV0, restrictfile,
+                merror(REGEX_COMPILE, __local_name, restrictfile,
                        ptm->error);
                 free(syscheck->filerestrict[pl]);
                 syscheck->filerestrict[pl] = NULL;
@@ -100,112 +81,93 @@ int dump_syscheck_entry(syscheck_config *syscheck, char *entry, int vals, int re
         }
     }
 
-    return(1);
+    return (1);
 }
 
-
-
-/* Read Windows registry configuration */
 #ifdef WIN32
+/* Read Windows registry configuration */
 int read_reg(syscheck_config *syscheck, char *entries)
 {
     int i;
     char **entry;
     char *tmp_str;
 
-
-    /* Getting each entry separately */
+    /* Get each entry separately */
     entry = OS_StrBreak(',', entries, MAX_DIR_SIZE); /* Max number */
 
-
-    /* entry can not be null */
-    if(entry == NULL)
-    {
-        return(0);
+    if (entry == NULL) {
+        return (0);
     }
 
-
-    /* Doing it for each Entry */
-    while(*entry)
-    {
+    while (*entry) {
         char *tmp_entry;
 
         tmp_entry = *entry;
 
-        /* Removing spaces at the beginning */
-        while(*tmp_entry == ' ')
-        {
+        /* Remove spaces at the beginning */
+        while (*tmp_entry == ' ') {
             tmp_entry++;
         }
 
-        /* Removing spaces at the end */
+        /* Remove spaces at the end */
         tmp_str = strchr(tmp_entry, ' ');
-        if(tmp_str)
-        {
+        if (tmp_str) {
             tmp_str++;
 
-            /* Checking if it is really at the end */
-            if((*tmp_str == '\0') || (*tmp_str == ' '))
-            {
+            /* Check if it is really at the end */
+            if ((*tmp_str == '\0') || (*tmp_str == ' ')) {
                 tmp_str--;
                 *tmp_str = '\0';
             }
         }
 
-
-        /* Adding entries - looking for the last available */
+        /* Add entries - look for the last available */
         i = 0;
-        while(syscheck->registry && syscheck->registry[i])
-        {
+        while (syscheck->registry && syscheck->registry[i]) {
             int str_len_i;
             int str_len_dir;
 
             str_len_dir = strlen(tmp_entry);
             str_len_i = strlen(syscheck->registry[i]);
 
-            if(str_len_dir > str_len_i)
-            {
+            if (str_len_dir > str_len_i) {
                 str_len_dir = str_len_i;
             }
 
             /* Duplicated entry */
-            if(strcmp(syscheck->registry[i], tmp_entry) == 0)
-            {
-                merror(SK_DUP, ARGV0, tmp_entry);
-                return(1);
+            if (strcmp(syscheck->registry[i], tmp_entry) == 0) {
+                merror(SK_DUP, __local_name, tmp_entry);
+                return (1);
             }
             i++;
         }
 
-        /* Adding new entry */
+        /* Add new entry */
         dump_syscheck_entry(syscheck, tmp_entry, 0, 1, NULL);
 
-
         /* Next entry */
         entry++;
     }
 
-    return(1);
+    return (1);
 }
-#endif /* For read_reg */
-
-
-
+#endif /* WIN32 */
 
 /* Read directories attributes */
-int read_attr(syscheck_config *syscheck, char *dirs, char **g_attrs, char **g_values)
+static int read_attr(syscheck_config *syscheck, const char *dirs, char **g_attrs, char **g_values)
 {
-    char *xml_check_all = "check_all";
-    char *xml_check_sum = "check_sum";
-    char *xml_check_sha1sum = "check_sha1sum";
-    char *xml_check_md5sum = "check_md5sum";
-    char *xml_check_size = "check_size";
-    char *xml_check_owner = "check_owner";
-    char *xml_check_group = "check_group";
-    char *xml_check_perm = "check_perm";
-    char *xml_real_time = "realtime";
-    char *xml_report_changes = "report_changes";
-    char *xml_restrict = "restrict";
+    const char *xml_check_all = "check_all";
+    const char *xml_check_sum = "check_sum";
+    const char *xml_check_sha1sum = "check_sha1sum";
+    const char *xml_check_md5sum = "check_md5sum";
+    const char *xml_check_size = "check_size";
+    const char *xml_check_owner = "check_owner";
+    const char *xml_check_group = "check_group";
+    const char *xml_check_perm = "check_perm";
+    const char *xml_real_time = "realtime";
+    const char *xml_report_changes = "report_changes";
+    const char *xml_restrict = "restrict";
+    const char *xml_no_recurse = "no_recurse";
 
     char *restrictfile = NULL;
     char **dir;
@@ -216,16 +178,12 @@ int read_attr(syscheck_config *syscheck, char *dirs, char **g_attrs, char **g_va
     int ret = 0, i;
 
     /* Dir can not be null */
-    if(dir == NULL)
-    {
-        return(0);
+    if (dir == NULL) {
+        return (0);
     }
 
-
-    /* Doing it for each directory */
-    while(*dir)
-    {
-        int i = 0;
+    while (*dir) {
+        int j = 0;
         int opts = 0;
         char *tmp_dir;
 
@@ -235,31 +193,26 @@ int read_attr(syscheck_config *syscheck, char *dirs, char **g_attrs, char **g_va
         tmp_dir = *dir;
         restrictfile = NULL;
 
-        /* Removing spaces at the beginning */
-        while(*tmp_dir == ' ')
-        {
+        /* Remove spaces at the beginning */
+        while (*tmp_dir == ' ') {
             tmp_dir++;
         }
 
-        /* Removing spaces at the end */
+        /* Remove spaces at the end */
         tmp_str = strchr(tmp_dir, ' ');
-        if(tmp_str)
-        {
+        if (tmp_str) {
             tmp_str++;
 
-            /* Checking if it is really at the end */
-            if((*tmp_str == '\0') || (*tmp_str == ' '))
-            {
+            /* Check if it is really at the end */
+            if ((*tmp_str == '\0') || (*tmp_str == ' ')) {
                 tmp_str--;
                 *tmp_str = '\0';
             }
         }
 
-
-        /* Getting the options */
-        if(!g_attrs || !g_values)
-        {
-            merror(SYSCHECK_NO_OPT, ARGV0, dirs);
+        /* Get the options */
+        if (!g_attrs || !g_values) {
+            merror(SYSCHECK_NO_OPT, __local_name, dirs);
             ret = 0;
             goto out_free;
         }
@@ -267,258 +220,196 @@ int read_attr(syscheck_config *syscheck, char *dirs, char **g_attrs, char **g_va
         attrs = g_attrs;
         values = g_values;
 
-        while(*attrs && *values)
-        {
-            /* Checking all */
-            if(strcmp(*attrs, xml_check_all) == 0)
-            {
-                if(strcmp(*values, "yes") == 0)
-                {
-                    opts|=CHECK_MD5SUM;
-                    opts|=CHECK_SHA1SUM;
-                    opts|=CHECK_PERM;
-                    opts|=CHECK_SIZE;
-                    opts|=CHECK_OWNER;
-                    opts|=CHECK_GROUP;
-                }
-                else if(strcmp(*values, "no") == 0)
-                {
-                }
-                else
-                {
-                    merror(SK_INV_OPT, ARGV0, *values, *attrs);
+        while (*attrs && *values) {
+            /* Check all */
+            if (strcmp(*attrs, xml_check_all) == 0) {
+                if (strcmp(*values, "yes") == 0) {
+                    opts |= CHECK_MD5SUM;
+                    opts |= CHECK_SHA1SUM;
+                    opts |= CHECK_PERM;
+                    opts |= CHECK_SIZE;
+                    opts |= CHECK_OWNER;
+                    opts |= CHECK_GROUP;
+                } else if (strcmp(*values, "no") == 0) {
+                   opts &= ~ ( CHECK_MD5SUM | CHECK_SHA1SUM | CHECK_PERM
+                      | CHECK_SIZE | CHECK_OWNER | CHECK_GROUP );
+                } else {
+                    merror(SK_INV_OPT, __local_name, *values, *attrs);
                     ret = 0;
                     goto out_free;
                 }
             }
-            /* Checking sum */
-            else if(strcmp(*attrs, xml_check_sum) == 0)
-            {
-                if(strcmp(*values, "yes") == 0)
-                {
-                    opts|=CHECK_MD5SUM;
-                    opts|=CHECK_SHA1SUM;
-                }
-                else if(strcmp(*values, "no") == 0)
-                {
-                }
-                else
-                {
-                    merror(SK_INV_OPT, ARGV0, *values, *attrs);
+            /* Check sum */
+            else if (strcmp(*attrs, xml_check_sum) == 0) {
+                if (strcmp(*values, "yes") == 0) {
+                    opts |= CHECK_MD5SUM;
+                    opts |= CHECK_SHA1SUM;
+                } else if (strcmp(*values, "no") == 0) {
+                   opts &= ~ ( CHECK_MD5SUM | CHECK_SHA1SUM );
+                } else {
+                    merror(SK_INV_OPT, __local_name, *values, *attrs);
                     ret = 0;
                     goto out_free;
                 }
             }
-            /* Checking md5sum */
-            else if(strcmp(*attrs, xml_check_md5sum) == 0)
-            {
-                if(strcmp(*values, "yes") == 0)
-                {
-                    opts|=CHECK_MD5SUM;
-                }
-                else if(strcmp(*values, "no") == 0)
-                {
-                }
-                else
-                {
-                    merror(SK_INV_OPT, ARGV0, *values, *attrs);
+            /* Check md5sum */
+            else if (strcmp(*attrs, xml_check_md5sum) == 0) {
+                if (strcmp(*values, "yes") == 0) {
+                    opts |= CHECK_MD5SUM;
+                } else if (strcmp(*values, "no") == 0) {
+                   opts &= ~ CHECK_MD5SUM;
+                } else {
+                    merror(SK_INV_OPT, __local_name, *values, *attrs);
                     ret = 0;
                     goto out_free;
                 }
             }
-            /* Checking sha1sum */
-            else if(strcmp(*attrs, xml_check_sha1sum) == 0)
-            {
-                if(strcmp(*values, "yes") == 0)
-                {
-                    opts|=CHECK_SHA1SUM;
-                }
-                else if(strcmp(*values, "no") == 0)
-                {
-                }
-                else
-                {
-                    merror(SK_INV_OPT, ARGV0, *values, *attrs);
+            /* Check sha1sum */
+            else if (strcmp(*attrs, xml_check_sha1sum) == 0) {
+                if (strcmp(*values, "yes") == 0) {
+                    opts |= CHECK_SHA1SUM;
+                } else if (strcmp(*values, "no") == 0) {
+                   opts &= ~ CHECK_SHA1SUM;
+                } else {
+                    merror(SK_INV_OPT, __local_name, *values, *attrs);
                     ret = 0;
                     goto out_free;
                 }
             }
-            /* Checking permission */
-            else if(strcmp(*attrs, xml_check_perm) == 0)
-            {
-                if(strcmp(*values, "yes") == 0)
-                {
-                    opts|=CHECK_PERM;
-                }
-                else if(strcmp(*values, "no") == 0)
-                {
-                }
-                else
-                {
-                    merror(SK_INV_OPT, ARGV0, *values, *attrs);
+            /* Check permission */
+            else if (strcmp(*attrs, xml_check_perm) == 0) {
+                if (strcmp(*values, "yes") == 0) {
+                    opts |= CHECK_PERM;
+                } else if (strcmp(*values, "no") == 0) {
+                   opts &= ~ CHECK_PERM;
+                } else {
+                    merror(SK_INV_OPT, __local_name, *values, *attrs);
                     ret = 0;
                     goto out_free;
                 }
             }
-            /* Checking size */
-            else if(strcmp(*attrs, xml_check_size) == 0)
-            {
-                if(strcmp(*values, "yes") == 0)
-                {
-                    opts|=CHECK_SIZE;
-                }
-                else if(strcmp(*values, "no") == 0)
-                {
-                }
-                else
-                {
-                    merror(SK_INV_OPT, ARGV0, *values, *attrs);
+            /* Check size */
+            else if (strcmp(*attrs, xml_check_size) == 0) {
+                if (strcmp(*values, "yes") == 0) {
+                    opts |= CHECK_SIZE;
+                } else if (strcmp(*values, "no") == 0) {
+                   opts &= ~ CHECK_SIZE;
+                } else {
+                    merror(SK_INV_OPT, __local_name, *values, *attrs);
                     ret = 0;
                     goto out_free;
                 }
             }
-            /* Checking owner */
-            else if(strcmp(*attrs, xml_check_owner) == 0)
-            {
-                if(strcmp(*values, "yes") == 0)
-                {
-                    opts|=CHECK_OWNER;
-                }
-                else if(strcmp(*values, "no") == 0)
-                {
-                }
-                else
-                {
-                    merror(SK_INV_OPT, ARGV0, *values, *attrs);
+            /* Check owner */
+            else if (strcmp(*attrs, xml_check_owner) == 0) {
+                if (strcmp(*values, "yes") == 0) {
+                    opts |= CHECK_OWNER;
+                } else if (strcmp(*values, "no") == 0) {
+                   opts &= ~ CHECK_OWNER;
+                } else {
+                    merror(SK_INV_OPT, __local_name, *values, *attrs);
                     ret = 0;
                     goto out_free;
                 }
             }
-            /* Checking group */
-            else if(strcmp(*attrs, xml_check_group) == 0)
-            {
-                if(strcmp(*values, "yes") == 0)
-                {
-                    opts|=CHECK_GROUP;
-                }
-                else if(strcmp(*values, "no") == 0)
-                {
-                }
-                else
-                {
-                    merror(SK_INV_OPT, ARGV0, *values, *attrs);
+            /* Check group */
+            else if (strcmp(*attrs, xml_check_group) == 0) {
+                if (strcmp(*values, "yes") == 0) {
+                    opts |= CHECK_GROUP;
+                } else if (strcmp(*values, "no") == 0) {
+                   opts &= ~ CHECK_GROUP;
+                } else {
+                    merror(SK_INV_OPT, __local_name, *values, *attrs);
                     ret = 0;
                     goto out_free;
                 }
-            }
-            else if(strcmp(*attrs, xml_real_time) == 0)
-            {
-                if(strcmp(*values, "yes") == 0)
-                {
-                    opts|=CHECK_REALTIME;
-                }
-                else if(strcmp(*values, "no") == 0)
-                {
-                }
-                else
-                {
-                    merror(SK_INV_OPT, ARGV0, *values, *attrs);
+            } else if (strcmp(*attrs, xml_real_time) == 0) {
+                if (strcmp(*values, "yes") == 0) {
+                    opts |= CHECK_REALTIME;
+                } else if (strcmp(*values, "no") == 0) {
+                   opts &= ~ CHECK_REALTIME;
+                } else {
+                    merror(SK_INV_OPT, __local_name, *values, *attrs);
                     ret = 0;
                     goto out_free;
                 }
-            }
-            else if(strcmp(*attrs, xml_report_changes) == 0)
-            {
-                if(strcmp(*values, "yes") == 0)
-                {
-                    opts|=CHECK_SEECHANGES;
+            } else if (strcmp(*attrs, xml_report_changes) == 0) {
+                if (strcmp(*values, "yes") == 0) {
+                    opts |= CHECK_SEECHANGES;
+                } else if (strcmp(*values, "no") == 0) {
+                   opts &= ~ CHECK_SEECHANGES;
+                } else {
+                    merror(SK_INV_OPT, __local_name, *values, *attrs);
+                    ret = 0;
+                    goto out_free;
                 }
-                else if(strcmp(*values, "no") == 0)
-                {
+            } else if (strcmp(*attrs, xml_restrict) == 0) {
+                if (restrictfile) {
+                    free(restrictfile);
+                    restrictfile = NULL;
                 }
-                else
-                {
-                    merror(SK_INV_OPT, ARGV0, *values, *attrs);
+                os_strdup(*values, restrictfile);
+            } else if (strcmp(*attrs, xml_no_recurse) == 0) {
+                if(strcmp(*values, "yes") == 0) {
+                    opts |= CHECK_NORECURSE;
+                } else {
+                    merror(SK_INV_OPT, __local_name, *values, *attrs);
                     ret = 0;
                     goto out_free;
                 }
-            }
-            else if(strcmp(*attrs, xml_restrict) == 0)
-            {
-                os_strdup(*values, restrictfile);
-            }
-            else
-            {
-                merror(SK_INV_ATTR, ARGV0, *attrs);
+            } else {
+                merror(SK_INV_ATTR, __local_name, *attrs);
                 ret = 0;
                 goto out_free;
             }
-            attrs++; values++;
+            attrs++;
+            values++;
         }
 
-
         /* You must have something set */
-        if(opts == 0)
-        {
-            merror(SYSCHECK_NO_OPT, ARGV0, dirs);
-            if(restrictfile) free(restrictfile);
+        if (opts == 0) {
+            merror(SYSCHECK_NO_OPT, __local_name, dirs);
             ret = 0;
             goto out_free;
         }
 
-
-        /* Adding directory - looking for the last available */
-        i = 0;
-        while(syscheck->dir && syscheck->dir[i])
-        {
-            int str_len_i;
-            int str_len_dir;
-
-            str_len_dir = strlen(tmp_dir);
-            str_len_i = strlen(syscheck->dir[i]);
-
-            if(str_len_dir > str_len_i)
-            {
-                str_len_dir = str_len_i;
-            }
-
+        /* Add directory - look for the last available */
+        j = 0;
+        while (syscheck->dir && syscheck->dir[j]) {
             /* Duplicate entry */
-            if(strcmp(syscheck->dir[i], tmp_dir) == 0)
-            {
-                merror(SK_DUP, ARGV0, tmp_dir);
+            if (strcmp(syscheck->dir[j], tmp_dir) == 0) {
+                merror(SK_DUP, __local_name, tmp_dir);
                 ret = 1;
                 goto out_free;
             }
 
-            i++;
+            j++;
         }
 
-
-        /* Checking for glob. */
-        #ifndef WIN32
-        if(strchr(tmp_dir, '*') ||
-           strchr(tmp_dir, '?') ||
-           strchr(tmp_dir, '['))
-        {
+        /* Check for glob */
+       /* The mingw32 builder used by travis.ci can't find glob.h 
+        * Yet glob must work on actual win32.  
+        */
+#ifndef __MINGW32__ 
+        if (strchr(tmp_dir, '*') ||
+                strchr(tmp_dir, '?') ||
+                strchr(tmp_dir, '[')) {
             int gindex = 0;
             glob_t g;
 
-            if(glob(tmp_dir, 0, NULL, &g) != 0)
-            {
-                merror(GLOB_ERROR, ARGV0, tmp_dir);
+            if (glob(tmp_dir, 0, NULL, &g) != 0) {
+                merror(GLOB_ERROR, __local_name, tmp_dir);
                 ret = 1;
                 goto out_free;
             }
 
-            if(g.gl_pathv[0] == NULL)
-            {
-                merror(GLOB_NFOUND, ARGV0, tmp_dir);
+            if (g.gl_pathv[0] == NULL) {
+                merror(GLOB_NFOUND, __local_name, tmp_dir);
                 ret = 1;
                 goto out_free;
             }
 
-            while(g.gl_pathv[gindex])
-            {
+            while (g.gl_pathv[gindex]) {
                 dump_syscheck_entry(syscheck, g.gl_pathv[gindex], opts, 0, restrictfile);
                 gindex++;
             }
@@ -526,21 +417,18 @@ int read_attr(syscheck_config *syscheck, char *dirs, char **g_attrs, char **g_va
             globfree(&g);
         }
 
-        else
-        {
+        else {
             dump_syscheck_entry(syscheck, tmp_dir, opts, 0, restrictfile);
         }
-        #else
-        dump_syscheck_entry(syscheck, tmp_dir, opts, 0, restrictfile);
-        #endif
+#else
+       dump_syscheck_entry(syscheck, tmp_dir, opts, 0, restrictfile);
+#endif
 
-        if(restrictfile)
-        {
+        if (restrictfile) {
             free(restrictfile);
             restrictfile = NULL;
         }
 
-
         /* Next entry */
         dir++;
     }
@@ -550,33 +438,35 @@ int read_attr(syscheck_config *syscheck, char *dirs, char **g_attrs, char **g_va
 out_free:
 
     i = 0;
-    while(dir_org[i])
+    while (dir_org[i]) {
         free(dir_org[i++]);
+    }
 
     free(dir_org);
+    free(restrictfile);
 
     return ret;
 }
 
-
-
-int Read_Syscheck(XML_NODE node, void *configp, void *mailp)
+int Read_Syscheck(XML_NODE node, void *configp, __attribute__((unused)) void *mailp)
 {
     int i = 0;
 
     /* XML Definitions */
-    char *xml_directories = "directories";
-    char *xml_registry = "windows_registry";
-    char *xml_time = "frequency";
-    char *xml_scanday = "scan_day";
-    char *xml_scantime = "scan_time";
-    char *xml_ignore = "ignore";
-    char *xml_registry_ignore = "registry_ignore";
-    char *xml_auto_ignore = "auto_ignore";
-    char *xml_alert_new_files = "alert_new_files";
-    char *xml_disabled = "disabled";
-    char *xml_scan_on_start = "scan_on_start";
-    char *xml_prefilter_cmd = "prefilter_cmd";
+    const char *xml_directories = "directories";
+    const char *xml_registry = "windows_registry";
+    const char *xml_time = "frequency";
+    const char *xml_scanday = "scan_day";
+    const char *xml_scantime = "scan_time";
+    const char *xml_ignore = "ignore";
+    const char *xml_registry_ignore = "registry_ignore";
+    const char *xml_auto_ignore = "auto_ignore";
+    const char *xml_alert_new_files = "alert_new_files";
+    const char *xml_disabled = "disabled";
+    const char *xml_scan_on_start = "scan_on_start";
+    const char *xml_prefilter_cmd = "prefilter_cmd";
+    const char *xml_skip_nfs = "skip_nfs";
+    const char *xml_nodiff = "nodiff";
 
     /* Configuration example
     <directories check_all="yes">/etc,/usr/bin</directories>
@@ -585,120 +475,115 @@ int Read_Syscheck(XML_NODE node, void *configp, void *mailp)
     */
 
     syscheck_config *syscheck;
-
     syscheck = (syscheck_config *)configp;
+    unsigned int nodiff_size = 0;
 
-
-    while(node[i])
-    {
-        if(!node[i]->element)
-        {
-            merror(XML_ELEMNULL, ARGV0);
-            return(OS_INVALID);
-        }
-        else if(!node[i]->content)
-        {
-            merror(XML_VALUENULL, ARGV0, node[i]->element);
-            return(OS_INVALID);
+    while (node[i]) {
+        if (!node[i]->element) {
+            merror(XML_ELEMNULL, __local_name);
+            return (OS_INVALID);
+        } else if (!node[i]->content) {
+            merror(XML_VALUENULL, __local_name, node[i]->element);
+            return (OS_INVALID);
         }
 
-        /* Getting directories */
-        else if(strcmp(node[i]->element,xml_directories) == 0)
-        {
+        /* Get directories */
+        else if (strcmp(node[i]->element, xml_directories) == 0) {
             char dirs[OS_MAXSTR];
 
-            #ifdef WIN32
-            ExpandEnvironmentStrings(node[i]->content, dirs, sizeof(dirs) -1);
-            #else
-            strncpy(dirs, node[i]->content, sizeof(dirs) -1);
-            #endif
+#ifdef WIN32
+            ExpandEnvironmentStrings(node[i]->content, dirs, sizeof(dirs) - 1);
+#else
+            strncpy(dirs, node[i]->content, sizeof(dirs) - 1);
+#endif
 
-            if(!read_attr(syscheck,
-                        dirs,
-                        node[i]->attributes,
-                        node[i]->values))
-            {
-                return(OS_INVALID);
+            if (!read_attr(syscheck,
+                           dirs,
+                           node[i]->attributes,
+                           node[i]->values)) {
+                return (OS_INVALID);
             }
         }
-        /* Getting windows registry */
-        else if(strcmp(node[i]->element,xml_registry) == 0)
-        {
-            #ifdef WIN32
-            if(!read_reg(syscheck, node[i]->content))
-            {
-                return(OS_INVALID);
+        /* Get Windows registry */
+        else if (strcmp(node[i]->element, xml_registry) == 0) {
+#ifdef WIN32
+            if (!read_reg(syscheck, node[i]->content)) {
+                return (OS_INVALID);
             }
-            #endif
+#endif
         }
-        /* Getting frequency */
-        else if(strcmp(node[i]->element,xml_time) == 0)
-        {
-            if(!OS_StrIsNum(node[i]->content))
-            {
-                merror(XML_VALUEERR,ARGV0,node[i]->element,node[i]->content);
-                return(OS_INVALID);
+        /* Get frequency */
+        else if (strcmp(node[i]->element, xml_time) == 0) {
+            if (!OS_StrIsNum(node[i]->content)) {
+                merror(XML_VALUEERR, __local_name, node[i]->element, node[i]->content);
+                return (OS_INVALID);
             }
 
             syscheck->time = atoi(node[i]->content);
         }
-        /* Getting scan time */
-        else if(strcmp(node[i]->element,xml_scantime) == 0)
-        {
+        /* Get scan time */
+        else if (strcmp(node[i]->element, xml_scantime) == 0) {
             syscheck->scan_time = OS_IsValidUniqueTime(node[i]->content);
-            if(!syscheck->scan_time)
-            {
-                merror(XML_VALUEERR,ARGV0,node[i]->element,node[i]->content);
-                return(OS_INVALID);
+            if (!syscheck->scan_time) {
+                merror(XML_VALUEERR, __local_name, node[i]->element, node[i]->content);
+                return (OS_INVALID);
             }
         }
 
-        /* Getting scan day */
-        else if(strcmp(node[i]->element,xml_scanday) == 0)
-        {
+        /* Get scan day */
+        else if (strcmp(node[i]->element, xml_scanday) == 0) {
             syscheck->scan_day = OS_IsValidDay(node[i]->content);
-            if(!syscheck->scan_day)
-            {
-                merror(XML_VALUEERR,ARGV0,node[i]->element,node[i]->content);
-                return(OS_INVALID);
+            if (!syscheck->scan_day) {
+                merror(XML_VALUEERR, __local_name, node[i]->element, node[i]->content);
+                return (OS_INVALID);
             }
         }
 
-        /* Getting if xml_scan_on_start. */
-        else if(strcmp(node[i]->element, xml_scan_on_start) == 0)
-        {
-            if(strcmp(node[i]->content, "yes") == 0)
+        /* Get if xml_scan_on_start */
+        else if (strcmp(node[i]->element, xml_scan_on_start) == 0) {
+            if (strcmp(node[i]->content, "yes") == 0) {
                 syscheck->scan_on_start = 1;
-            else if(strcmp(node[i]->content, "no") == 0)
+            } else if (strcmp(node[i]->content, "no") == 0) {
                 syscheck->scan_on_start = 0;
-            else
-            {
-                merror(XML_VALUEERR,ARGV0, node[i]->element, node[i]->content);
-                return(OS_INVALID);
+            } else {
+                merror(XML_VALUEERR, __local_name, node[i]->element, node[i]->content);
+                return (OS_INVALID);
             }
         }
 
-        /* Getting if disabled. */
-        else if(strcmp(node[i]->element,xml_disabled) == 0)
+        /* Get if disabled */
+        else if (strcmp(node[i]->element, xml_disabled) == 0) {
+            if (strcmp(node[i]->content, "yes") == 0) {
+                syscheck->disabled = 1;
+            } else if (strcmp(node[i]->content, "no") == 0) {
+                syscheck->disabled = 0;
+            } else {
+                merror(XML_VALUEERR, __local_name, node[i]->element, node[i]->content);
+                return (OS_INVALID);
+            }
+        }
+
+        /* Getting if skip_nfs. */
+        else if (strcmp(node[i]->element,xml_skip_nfs) == 0)
         {
             if(strcmp(node[i]->content, "yes") == 0)
-                syscheck->disabled = 1;
+                syscheck->skip_nfs = 1;
             else if(strcmp(node[i]->content, "no") == 0)
-                syscheck->disabled = 0;
+                syscheck->skip_nfs = 0;
             else
             {
-                merror(XML_VALUEERR,ARGV0,node[i]->element,node[i]->content);
+                merror(XML_VALUEERR,__local_name,node[i]->element,node[i]->content);
                 return(OS_INVALID);
             }
         }
 
         /* Getting file/dir ignore */
-        else if(strcmp(node[i]->element,xml_ignore) == 0)
+        else if (strcmp(node[i]->element,xml_ignore) == 0)
         {
-            int ign_size = 0;
+            unsigned int ign_size = 0;
 
-            /* For Windows, we attempt to expand environment variables. */
-            #ifdef WIN32
+#ifdef WIN32
+            /* For Windows, we attempt to expand environment variables */
             char *new_ig = NULL;
             os_calloc(2048, sizeof(char), new_ig);
 
@@ -706,194 +591,280 @@ int Read_Syscheck(XML_NODE node, void *configp, void *mailp)
 
             free(node[i]->content);
             node[i]->content = new_ig;
-            #endif
-
-            /* Adding if regex */
-            if(node[i]->attributes && node[i]->values)
-            {
-                if(node[i]->attributes[0] && node[i]->values[0] &&
-                   (strcmp(node[i]->attributes[0], "type") == 0) &&
-                   (strcmp(node[i]->values[0], "sregex") == 0))
-                {
+#endif
+            /* Add if regex */
+            if (node[i]->attributes && node[i]->values) {
+                if (node[i]->attributes[0] && node[i]->values[0] &&
+                        (strcmp(node[i]->attributes[0], "type") == 0) &&
+                        (strcmp(node[i]->values[0], "sregex") == 0)) {
                     OSMatch *mt_pt;
 
-                    if(!syscheck->ignore_regex)
-                    {
-                        os_calloc(2, sizeof(OSMatch *),syscheck->ignore_regex);
+                    if (!syscheck->ignore_regex) {
+                        os_calloc(2, sizeof(OSMatch *), syscheck->ignore_regex);
                         syscheck->ignore_regex[0] = NULL;
                         syscheck->ignore_regex[1] = NULL;
-                    }
-                    else
-                    {
-                        while(syscheck->ignore_regex[ign_size] != NULL)
+                    } else {
+                        while (syscheck->ignore_regex[ign_size] != NULL) {
                             ign_size++;
+                        }
 
                         os_realloc(syscheck->ignore_regex,
-                                sizeof(OSMatch *)*(ign_size +2),
-                                syscheck->ignore_regex);
-                        syscheck->ignore_regex[ign_size +1] = NULL;
+                                   sizeof(OSMatch *) * (ign_size + 2),
+                                   syscheck->ignore_regex);
+                        syscheck->ignore_regex[ign_size + 1] = NULL;
                     }
                     os_calloc(1, sizeof(OSMatch),
-                            syscheck->ignore_regex[ign_size]);
+                              syscheck->ignore_regex[ign_size]);
 
-                    if(!OSMatch_Compile(node[i]->content,
-                                        syscheck->ignore_regex[ign_size], 0))
-                    {
+                    if (!OSMatch_Compile(node[i]->content,
+                                         syscheck->ignore_regex[ign_size], 0)) {
                         mt_pt = (OSMatch *)syscheck->ignore_regex[ign_size];
-                        merror(REGEX_COMPILE, ARGV0, node[i]->content,
-                              mt_pt->error);
-                        return(0);
+                        merror(REGEX_COMPILE, __local_name, node[i]->content,
+                               mt_pt->error);
+                        return (0);
                     }
-                }
-                else
-                {
-                    merror(SK_INV_ATTR, ARGV0, node[i]->attributes[0]);
-                    return(OS_INVALID);
+                } else {
+                    merror(SK_INV_ATTR, __local_name, node[i]->attributes[0]);
+                    return (OS_INVALID);
                 }
             }
 
-            /* Adding if simple entry -- checking for duplicates */
-            else if(!os_IsStrOnArray(node[i]->content, syscheck->ignore))
-            {
-                if(!syscheck->ignore)
-                {
+            /* Add if simple entry -- check for duplicates */
+            else if (!os_IsStrOnArray(node[i]->content, syscheck->ignore)) {
+                if (!syscheck->ignore) {
                     os_calloc(2, sizeof(char *), syscheck->ignore);
                     syscheck->ignore[0] = NULL;
                     syscheck->ignore[1] = NULL;
-                }
-                else
-                {
-                    while(syscheck->ignore[ign_size] != NULL)
+                } else {
+                    while (syscheck->ignore[ign_size] != NULL) {
                         ign_size++;
+                    }
 
                     os_realloc(syscheck->ignore,
-                            sizeof(char *)*(ign_size +2),
-                            syscheck->ignore);
-                    syscheck->ignore[ign_size +1] = NULL;
+                               sizeof(char *) * (ign_size + 2),
+                               syscheck->ignore);
+                    syscheck->ignore[ign_size + 1] = NULL;
                 }
-                os_strdup(node[i]->content,syscheck->ignore[ign_size]);
+                os_strdup(node[i]->content, syscheck->ignore[ign_size]);
             }
         }
 
-        /* Getting registry ignore list */
-        else if(strcmp(node[i]->element,xml_registry_ignore) == 0)
-        {
-            #ifdef WIN32
+        /* Get registry ignore list */
+        else if (strcmp(node[i]->element, xml_registry_ignore) == 0) {
+#ifdef WIN32
             int ign_size = 0;
 
-            /* Adding if regex */
-            if(node[i]->attributes && node[i]->values)
-            {
-                if(node[i]->attributes[0] && node[i]->values[0] &&
-                   (strcmp(node[i]->attributes[0], "type") == 0) &&
-                   (strcmp(node[i]->values[0], "sregex") == 0))
-                {
+            /* Add if regex */
+            if (node[i]->attributes && node[i]->values) {
+                if (node[i]->attributes[0] && node[i]->values[0] &&
+                        (strcmp(node[i]->attributes[0], "type") == 0) &&
+                        (strcmp(node[i]->values[0], "sregex") == 0)) {
                     OSMatch *mt_pt;
 
-                    if(!syscheck->registry_ignore_regex)
-                    {
+                    if (!syscheck->registry_ignore_regex) {
                         os_calloc(2, sizeof(OSMatch *),
-                                     syscheck->registry_ignore_regex);
+                                  syscheck->registry_ignore_regex);
                         syscheck->registry_ignore_regex[0] = NULL;
                         syscheck->registry_ignore_regex[1] = NULL;
-                    }
-                    else
-                    {
-                        while(syscheck->registry_ignore_regex[ign_size] !=NULL)
+                    } else {
+                        while (syscheck->registry_ignore_regex[ign_size] != NULL) {
                             ign_size++;
+                        }
 
                         os_realloc(syscheck->registry_ignore_regex,
-                                sizeof(OSMatch *)*(ign_size +2),
-                                syscheck->registry_ignore_regex);
-                        syscheck->registry_ignore_regex[ign_size +1] = NULL;
+                                   sizeof(OSMatch *) * (ign_size + 2),
+                                   syscheck->registry_ignore_regex);
+                        syscheck->registry_ignore_regex[ign_size + 1] = NULL;
                     }
 
                     os_calloc(1, sizeof(OSMatch),
-                            syscheck->registry_ignore_regex[ign_size]);
+                              syscheck->registry_ignore_regex[ign_size]);
 
-                    if(!OSMatch_Compile(node[i]->content,
-                                syscheck->registry_ignore_regex[ign_size], 0))
-                    {
+                    if (!OSMatch_Compile(node[i]->content,
+                                         syscheck->registry_ignore_regex[ign_size], 0)) {
                         mt_pt = (OSMatch *)
                                 syscheck->registry_ignore_regex[ign_size];
-                        merror(REGEX_COMPILE, ARGV0, node[i]->content,
-                             mt_pt->error);
-                        return(0);
+                        merror(REGEX_COMPILE, __local_name, node[i]->content,
+                               mt_pt->error);
+                        return (0);
                     }
-                }
-                else
-                {
-                    merror(SK_INV_ATTR, ARGV0, node[i]->attributes[0]);
-                    return(OS_INVALID);
+                } else {
+                    merror(SK_INV_ATTR, __local_name, node[i]->attributes[0]);
+                    return (OS_INVALID);
                 }
             }
             /* We do not add duplicated entries */
-            else if(!os_IsStrOnArray(node[i]->content,
-                     syscheck->registry_ignore))
-            {
-                if(!syscheck->registry_ignore)
-                {
+            else if (!os_IsStrOnArray(node[i]->content,
+                                      syscheck->registry_ignore)) {
+                if (!syscheck->registry_ignore) {
                     os_calloc(2, sizeof(char *), syscheck->registry_ignore);
                     syscheck->registry_ignore[0] = NULL;
                     syscheck->registry_ignore[1] = NULL;
-                }
-                else
-                {
-                    while(syscheck->registry_ignore[ign_size] != NULL)
+                } else {
+                    while (syscheck->registry_ignore[ign_size] != NULL) {
                         ign_size++;
+                    }
 
                     os_realloc(syscheck->registry_ignore,
-                            sizeof(char *)*(ign_size +2),
-                            syscheck->registry_ignore);
-                    syscheck->registry_ignore[ign_size +1] = NULL;
+                               sizeof(char *) * (ign_size + 2),
+                               syscheck->registry_ignore);
+                    syscheck->registry_ignore[ign_size + 1] = NULL;
                 }
-                os_strdup(node[i]->content,syscheck->registry_ignore[ign_size]);
+                os_strdup(node[i]->content, syscheck->registry_ignore[ign_size]);
             }
-            #endif
-        }
-        else if(strcmp(node[i]->element,xml_auto_ignore) == 0)
-        {
-            /* auto_ignore is not read here. */
-        }
-        else if(strcmp(node[i]->element,xml_alert_new_files) == 0)
-        {
-            /* alert_new_files option is not read here. */
-        }
-        else if(strcmp(node[i]->element,xml_prefilter_cmd) == 0)
-        {
+#endif
+        /* Getting file/dir nodiff */
+        } else if (strcmp(node[i]->element,xml_nodiff) == 0) {
+#ifdef WIN32
+            /* For Windows, we attempt to expand environment variables */
+            char *new_nodiff = NULL;
+            os_calloc(2048, sizeof(char), new_nodiff);
+
+            ExpandEnvironmentStrings(node[i]->content, new_nodiff, 2047);
+
+            free(node[i]->content);
+            node[i]->content = new_nodiff;
+#endif
+            /* Add if regex */
+            if (node[i]->attributes && node[i]->values) {
+                if (node[i]->attributes[0] && node[i]->values[0] &&
+                        (strcmp(node[i]->attributes[0], "type") == 0) &&
+                        (strcmp(node[i]->values[0], "sregex") == 0)) {
+                    OSMatch *mt_pt;
+                    if (!syscheck->nodiff_regex) {
+                        os_calloc(2, sizeof(OSMatch *), syscheck->nodiff_regex);
+                        syscheck->nodiff_regex[0] = NULL;
+                        syscheck->nodiff_regex[1] = NULL;
+                    } else {
+                        while (syscheck->nodiff_regex[nodiff_size] != NULL) {
+                            nodiff_size++;
+                        }
+
+                        os_realloc(syscheck->nodiff_regex,
+                                   sizeof(OSMatch *) * (nodiff_size + 2),
+                                   syscheck->nodiff_regex);
+                        syscheck->nodiff_regex[nodiff_size + 1] = NULL;
+                    }
+                    os_calloc(1, sizeof(OSMatch),
+                              syscheck->nodiff_regex[nodiff_size]);
+                    debug1("Found nodiff regex node %s", node[i]->content);
+                    if (!OSMatch_Compile(node[i]->content,
+                                         syscheck->nodiff_regex[nodiff_size], 0)) {
+                        mt_pt = (OSMatch *)syscheck->nodiff_regex[nodiff_size];
+                        merror(REGEX_COMPILE, __local_name, node[i]->content,
+                               mt_pt->error);
+                        return (0);
+                    }
+                    debug1("Found nodiff regex node %s OK?", node[i]->content);
+                    debug1("Found nodiff regex size %d", nodiff_size);
+                } else {
+                    merror(SK_INV_ATTR, __local_name, node[i]->attributes[0]);
+                    return (OS_INVALID);
+                }
+            }
+
+            /* Add if simple entry -- check for duplicates */
+            else if (!os_IsStrOnArray(node[i]->content, syscheck->nodiff)) {
+                if (!syscheck->nodiff) {
+                    os_calloc(2, sizeof(char *), syscheck->nodiff);
+                    syscheck->nodiff[0] = NULL;
+                    syscheck->nodiff[1] = NULL;
+                } else {
+                    while (syscheck->nodiff[nodiff_size] != NULL) {
+                        nodiff_size++;
+                    }
+
+                    os_realloc(syscheck->nodiff,
+                               sizeof(char *) * (nodiff_size + 2),
+                               syscheck->nodiff);
+                    syscheck->nodiff[nodiff_size + 1] = NULL;
+                }
+                os_strdup(node[i]->content, syscheck->nodiff[nodiff_size]);
+            }
+        } else if (strcmp(node[i]->element, xml_auto_ignore) == 0) {
+            /* auto_ignore is not read here */
+        } else if (strcmp(node[i]->element, xml_alert_new_files) == 0) {
+            /* alert_new_files option is not read here */
+        } else if (strcmp(node[i]->element, xml_prefilter_cmd) == 0) {
             char cmd[OS_MAXSTR];
             struct stat statbuf;
 
-            #ifdef WIN32
-            ExpandEnvironmentStrings(node[i]->content, cmd, sizeof(cmd) -1);
-            #else
-            strncpy(cmd, node[i]->content, sizeof(cmd)-1);
-            #endif
+#ifdef WIN32
+            ExpandEnvironmentStrings(node[i]->content, cmd, sizeof(cmd) - 1);
+#else
+            strncpy(cmd, node[i]->content, sizeof(cmd) - 1);
+#endif
 
             if (strlen(cmd) > 0) {
                 char statcmd[OS_MAXSTR];
                 char *ix;
-                strncpy(statcmd, cmd, sizeof(statcmd)-1);
-                if (NULL != (ix = strchr(statcmd, ' '))) { *ix = '\0'; }
+                strncpy(statcmd, cmd, sizeof(statcmd) - 1);
+                if (NULL != (ix = strchr(statcmd, ' '))) {
+                    *ix = '\0';
+                }
                 if (stat(statcmd, &statbuf) == 0) {
-                    // More checks needed (perms, owner, etc.)
-                    os_calloc(1, strlen(cmd)+1, syscheck->prefilter_cmd);
+                    /* More checks needed (perms, owner, etc.) */
+                    os_calloc(1, strlen(cmd) + 1, syscheck->prefilter_cmd);
                     strncpy(syscheck->prefilter_cmd, cmd, strlen(cmd));
-                }
-                else
-                {
-                    merror(XML_VALUEERR,ARGV0, node[i]->element, node[i]->content);
-                    return(OS_INVALID);
+                } else {
+                    merror(XML_VALUEERR, __local_name, node[i]->element, node[i]->content);
+                    return (OS_INVALID);
                 }
             }
-        }
-        else
-        {
-            merror(XML_INVELEM, ARGV0, node[i]->element);
-            return(OS_INVALID);
+        } else {
+            merror(XML_INVELEM, __local_name, node[i]->element);
+            return (OS_INVALID);
         }
         i++;
     }
 
-    return(0);
+    return (0);
 }
+
+
+/* return a text version of the directory check option bits,
+ * in a provided string buffer
+ */
+char *syscheck_opts2str(char *buf, int buflen, int opts) {
+    int left = buflen;
+    int i;
+    int check_bits[] = {
+        CHECK_PERM,
+        CHECK_SIZE,
+        CHECK_OWNER,
+        CHECK_GROUP,
+       CHECK_MD5SUM,
+        CHECK_SHA1SUM,
+        CHECK_REALTIME,
+        CHECK_SEECHANGES,
+        CHECK_NORECURSE,
+       0
+       };
+    char *check_strings[] = {
+        "perm",
+        "size",
+        "owner",
+        "group",
+       "md5sum",
+        "sha1sum",
+        "realtime",
+        "report_changes",
+        "no_recurse",
+       NULL
+       };
+
+    buf[0] = '\0';
+    for ( i = 0; check_bits[ i ]; i++ ) {
+       if ( opts & check_bits[ i ] ) {
+           if ( left < buflen )  {
+               strncat( buf, " | ", left );
+               left -= 3;
+               }
+           strncat( buf, check_strings[ i ], left );
+           left = buflen - strlen( buf );
+           }
+       }
+
+    return buf;
+    }
+