new upstream release (3.3.0); modify package compatibility for Stretch
[ossec-hids.git] / src / analysisd / decoders / decode-xml.c
old mode 100755 (executable)
new mode 100644 (file)
index 7afd4cd..d1eef1c
@@ -1,6 +1,3 @@
-/* @(#) $Id: ./src/analysisd/decoders/decode-xml.c, 2011/09/08 dcid Exp $
- */
-
 /* Copyright (C) 2009 Trend Micro Inc.
  * All rights reserved.
  *
  * and/or modify it under the terms of the GNU General Public
  * License (version 2) as published by the FSF - Free Software
  * Foundation.
- *
- * License details at the LICENSE file included with OSSEC or
- * online at: http://www.ossec.net/en/licensing.html
  */
 
-
 #include "shared.h"
 #include "os_regex/os_regex.h"
 #include "os_xml/os_xml.h"
-
-
 #include "analysisd.h"
 #include "eventinfo.h"
 #include "decoder.h"
 #include "plugin_decoders.h"
+#include "config.h"
 
 
 #ifdef TESTRULE
-  #undef XML_LDECODER
-  #define XML_LDECODER "etc/local_decoder.xml"
+#undef XML_LDECODER
+#define XML_LDECODER "etc/local_decoder.xml"
 #endif
 
-
 /* Internal functions */
-char *_loadmemory(char *at, char *str);
-OSStore *os_decoder_store = NULL;
+static char *_loadmemory(char *at, char *str);
+static int addDecoder2list(const char *name);
+static int os_setdecoderids(const char *p_name);
+static int ReadDecodeAttrs(char *const *names, char *const *values);
+static OSStore *os_decoder_store = NULL;
 
 
-/* Gets decoder id */
-int getDecoderfromlist(char *name)
+int getDecoderfromlist(const char *name)
 {
-    if(os_decoder_store)
-    {
-        return(OSStore_GetPosition(os_decoder_store, name));
+    if (os_decoder_store) {
+        return (OSStore_GetPosition(os_decoder_store, name));
     }
 
-    return(0);
+    return (0);
 }
 
-
-/* Adds decoder id */
-int addDecoder2list(char *name)
+static int addDecoder2list(const char *name)
 {
-    if(os_decoder_store == NULL)
-    {
+    if (os_decoder_store == NULL) {
         os_decoder_store = OSStore_Create();
-        if(os_decoder_store == NULL)
-        {
+        if (os_decoder_store == NULL) {
             merror(LIST_ERROR, ARGV0);
-            return(0);
+            return (0);
         }
     }
 
-    /* Storing data */
-    if(!OSStore_Put(os_decoder_store, name, NULL))
-    {
+    /* Store data */
+    if (!OSStore_Put(os_decoder_store, name, NULL)) {
         merror(LIST_ADD_ERROR, ARGV0);
-        return(0);
+        return (0);
     }
 
-    return(1);
+    return (1);
 }
 
-
-/* Set decoder ids */
-int os_setdecoderids(char *p_name)
+static int os_setdecoderids(const char *p_name)
 {
     OSDecoderNode *node;
     OSDecoderNode *child_node;
     OSDecoderInfo *nnode;
 
-
     node = OS_GetFirstOSDecoder(p_name);
 
+    if (!node) {
+        return (0);
+    }
 
-    /* Return if no node...
-     * This shouldn't happen here anyways.
-     */
-    if(!node)
-        return(0);
-
-    do
-    {
+    do {
         int p_id = 0;
-        char *p_name;
+        char *tmp_name;
 
         nnode = node->osdecoder;
         nnode->id = getDecoderfromlist(nnode->name);
 
-        /* Id can noit be 0 */
-        if(nnode->id == 0)
-        {
-            return(0);
+        /* Id cannot be 0 */
+        if (nnode->id == 0) {
+            return (0);
         }
 
         child_node = node->child;
 
-        if(!child_node)
-        {
+        if (!child_node) {
             continue;
         }
 
-
-        /* Setting parent id */
+        /* Set parent id */
         p_id = nnode->id;
-        p_name = nnode->name;
+        tmp_name = nnode->name;
 
-
-        /* Also setting on the child nodes */
-        while(child_node)
-        {
+        /* Also set on the child nodes */
+        while (child_node) {
             nnode = child_node->osdecoder;
 
-            if(nnode->use_own_name)
-            {
+            if (nnode->use_own_name) {
                 nnode->id = getDecoderfromlist(nnode->name);
-            }
-            else
-            {
+            } else {
                 nnode->id = p_id;
 
-                /* Setting parent name */
-                nnode->name = p_name;
+                /* Set parent name */
+                free(nnode->name);
+                nnode->name = strdup(tmp_name);
             }
 
-
-            /* Id can noit be 0 */
-            if(nnode->id == 0)
-            {
-                return(0);
+            /* Id cannot be 0 */
+            if (nnode->id == 0) {
+                return (0);
             }
             child_node = child_node->next;
         }
-    }while((node=node->next) != NULL);
+    } while ((node = node->next) != NULL);
 
-    return(1);
+    return (1);
 }
 
-
-/* Read attributes */
-int ReadDecodeAttrs(char **names, char **values)
+static int ReadDecodeAttrs(char *const *names, char *const *values)
 {
-    if(!names || !values)
-        return(0);
+    if (!names || !values) {
+        return (0);
+    }
 
-    if(!names[0] || !values[0])
-    {
-        return(0);
+    if (!names[0] || !values[0]) {
+        return (0);
     }
 
-    if(strcmp(names[0], "offset") == 0)
-    {
+    if (strcmp(names[0], "offset") == 0) {
         int offset = 0;
 
         /* Offsets can be: after_parent, after_prematch
          * or after_regex.
          */
-        if(strcmp(values[0],"after_parent") == 0)
-        {
+        if (strcmp(values[0], "after_parent") == 0) {
             offset |= AFTER_PARENT;
-        }
-        else if(strcmp(values[0],"after_prematch") == 0)
-        {
+        } else if (strcmp(values[0], "after_prematch") == 0) {
             offset |= AFTER_PREMATCH;
-        }
-        else if(strcmp(values[0],"after_regex") == 0)
-        {
+        } else if (strcmp(values[0], "after_regex") == 0) {
             offset |= AFTER_PREVREGEX;
-        }
-        else
-        {
+        } else {
             merror(INV_OFFSET, ARGV0, values[0]);
             offset |= AFTER_ERROR;
         }
 
-        return(offset);
+        return (offset);
     }
 
     /* Invalid attribute */
     merror(INV_ATTR, ARGV0, names[0]);
-    return(AFTER_ERROR);
+    return (AFTER_ERROR);
 }
 
-
-/* ReaddecodeXML */
-int ReadDecodeXML(char *file)
+int ReadDecodeXML(const char *file)
 {
     OS_XML xml;
     XML_NODE node = NULL;
@@ -201,72 +160,66 @@ int ReadDecodeXML(char *file)
     /* XML variables */
     /* These are the available options for the rule configuration */
 
-    char *xml_plugindecoder = "plugin_decoder";
-    char *xml_decoder = "decoder";
-    char *xml_decoder_name = "name";
-    char *xml_decoder_status = "status";
-    char *xml_usename = "use_own_name";
-    char *xml_parent = "parent";
-    char *xml_program_name = "program_name";
-    char *xml_prematch = "prematch";
-    char *xml_regex = "regex";
-    char *xml_order = "order";
-    char *xml_type = "type";
-    char *xml_fts = "fts";
-    char *xml_ftscomment = "ftscomment";
+    const char *xml_plugindecoder = "plugin_decoder";
+    const char *xml_decoder = "decoder";
+    const char *xml_decoder_name = "name";
+    const char *xml_decoder_status = "status";
+    const char *xml_usename = "use_own_name";
+    const char *xml_parent = "parent";
+    const char *xml_program_name = "program_name";
+    const char *xml_prematch = "prematch";
+    const char *xml_regex = "regex";
+    const char *xml_program_name_pcre2 = "program_name_pcre2";
+    const char *xml_prematch_pcre2 = "prematch_pcre2";
+    const char *xml_pcre2 = "pcre2";
+    const char *xml_order = "order";
+    const char *xml_type = "type";
+    const char *xml_fts = "fts";
+    const char *xml_ftscomment = "ftscomment";
+    const char *xml_accumulate = "accumulate";
 
     int i = 0;
     OSDecoderInfo *NULL_Decoder_tmp = NULL;
 
-
-    /* Reading the XML */
-    if((i = OS_ReadXML(file,&xml)) < 0)
-    {
-        if((i == -2) && (strcmp(file, XML_LDECODER) == 0))
-        {
-            return(-2);
+    /* Read the XML */
+    if ((i = OS_ReadXML(file, &xml)) < 0) {
+        if ((i == -2) && (strcmp(file, XML_LDECODER) == 0)) {
+            return (-2);
         }
 
         merror(XML_ERROR, ARGV0, file, xml.err, xml.err_line);
-        return(0);
+        return (0);
     }
 
-
-    /* Applying any variable found */
-    if(OS_ApplyVariables(&xml) != 0)
-    {
+    /* Apply any variables found */
+    if (OS_ApplyVariables(&xml) != 0) {
         merror(XML_ERROR_VAR, ARGV0, file, xml.err);
-        return(0);
+        return (0);
     }
 
-
-    /* Getting the root elements */
+    /* Get the root elements */
     node = OS_GetElementsbyNode(&xml, NULL);
-    if(!node)
-    {
-        if(strcmp(file, XML_LDECODER) != 0)
-        {
+    if (!node) {
+        if (strcmp(file, XML_LDECODER) != 0) {
             merror(XML_ELEMNULL, ARGV0);
-            return(0);
+            return (0);
         }
 
-        return(-2);
+        return (-2);
     }
 
-
-    /* Zeroing NULL_decoder */
-    os_calloc(1, sizeof(OSDecoderInfo), NULL_Decoder_tmp);
-    NULL_Decoder_tmp->id = 0;
-    NULL_Decoder_tmp->type = SYSLOG;
-    NULL_Decoder_tmp->name = NULL;
-    NULL_Decoder_tmp->fts = 0;
-    NULL_Decoder = (void *)NULL_Decoder_tmp;
-
-
+    /* Zero NULL_decoder */
+    if (!NULL_Decoder) {
+        os_calloc(1, sizeof(OSDecoderInfo), NULL_Decoder_tmp);
+        NULL_Decoder_tmp->id = 0;
+        NULL_Decoder_tmp->type = SYSLOG;
+        NULL_Decoder_tmp->name = NULL;
+        NULL_Decoder_tmp->fts = 0;
+        NULL_Decoder = NULL_Decoder_tmp;
+    }
 
     i = 0;
-    while(node[i])
-    {
+    while (node[i]) {
         XML_NODE elements = NULL;
         OSDecoderInfo *pi;
 
@@ -274,60 +227,51 @@ int ReadDecodeXML(char *file)
         char *regex;
         char *prematch;
         char *p_name;
+        char *pcre2;
+        char *prematch_pcre2;
+        char *p_name_pcre2;
 
-
-        if(!node[i]->element ||
-            strcasecmp(node[i]->element, xml_decoder) != 0)
-        {
+        if (!node[i]->element ||
+                strcasecmp(node[i]->element, xml_decoder) != 0) {
             merror(XML_INVELEM, ARGV0, node[i]->element);
-            return(0);
+            return (0);
         }
 
-
-        /* Getting name */
-        if((!node[i]->attributes) || (!node[i]->values)||
-           (!node[i]->values[0])  || (!node[i]->attributes[0])||
-           (strcasecmp(node[i]->attributes[0],xml_decoder_name)!= 0))
-        {
+        /* Get name */
+        if ((!node[i]->attributes) || (!node[i]->values) ||
+                (!node[i]->values[0])  || (!node[i]->attributes[0]) ||
+                (strcasecmp(node[i]->attributes[0], xml_decoder_name) != 0)) {
             merror(XML_INVELEM, ARGV0, node[i]->element);
-            return(0);
+            return (0);
         }
 
-
-        /* Checking for additional entries */
-        if(node[i]->attributes[1] && node[i]->values[1])
-        {
-            if(strcasecmp(node[i]->attributes[0],xml_decoder_status)!= 0)
-            {
+        /* Check for additional entries */
+        if (node[i]->attributes[1] && node[i]->values[1]) {
+            if (strcasecmp(node[i]->attributes[0], xml_decoder_status) != 0) {
                 merror(XML_INVELEM, ARGV0, node[i]->element);
-                return(0);
+                return (0);
             }
 
-            if(node[i]->attributes[2])
-            {
+            if (node[i]->attributes[2]) {
                 merror(XML_INVELEM, ARGV0, node[i]->element);
-                return(0);
+                return (0);
             }
         }
 
-
-        /* Getting decoder options */
-        elements = OS_GetElementsbyNode(&xml,node[i]);
-        if(elements == NULL)
-        {
+        /* Get decoder options */
+        elements = OS_GetElementsbyNode(&xml, node[i]);
+        if (elements == NULL) {
             merror(XML_ELEMNULL, ARGV0);
-            return(0);
+            return (0);
         }
 
-        /* Creating the OSDecoderInfo */
-        pi = (OSDecoderInfo *)calloc(1,sizeof(OSDecoderInfo));
-        if(pi == NULL)
-        {
-            merror(MEM_ERROR,ARGV0);
-            return(0);
+        /* Create the OSDecoderInfo */
+        pi = (OSDecoderInfo *)calloc(1, sizeof(OSDecoderInfo));
+        if (pi == NULL) {
+            merror(MEM_ERROR, ARGV0, errno, strerror(errno));
+            return (0);
         }
 
-
         /* Default values to the list */
         pi->parent = NULL;
         pi->id = 0;
@@ -335,10 +279,14 @@ int ReadDecodeXML(char *file)
         pi->order = NULL;
         pi->plugindecoder = NULL;
         pi->fts = 0;
+        pi->accumulate = 0;
         pi->type = SYSLOG;
         pi->prematch = NULL;
         pi->program_name = NULL;
         pi->regex = NULL;
+        pi->prematch_pcre2 = NULL;
+        pi->program_name_pcre2 = NULL;
+        pi->pcre2 = NULL;
         pi->use_own_name = 0;
         pi->get_next = 0;
         pi->regex_offset = 0;
@@ -347,267 +295,278 @@ int ReadDecodeXML(char *file)
         regex = NULL;
         prematch = NULL;
         p_name = NULL;
+        pcre2 = NULL;
+        prematch_pcre2 = NULL;
+        p_name_pcre2 = NULL;
 
-
-        /* Checking if strdup worked */
-        if(!pi->name)
-        {
-            merror(MEM_ERROR, ARGV0);
-            return(0);
+        /* Check if strdup worked */
+        if (!pi->name) {
+            merror(MEM_ERROR, ARGV0, errno, strerror(errno));
+            return (0);
         }
 
         /* Add decoder */
-        if(!addDecoder2list(pi->name))
-        {
-            merror(MEM_ERROR, ARGV0);
-            return(0);
+        if (!addDecoder2list(pi->name)) {
+            merror(MEM_ERROR, ARGV0, errno, strerror(errno));
+            free(pi->name);
+            free(pi);
+            return (0);
         }
 
-        /* Looping on all the elements */
-        while(elements[j])
-        {
-            if(!elements[j]->element)
-            {
+        /* Loop over all the elements */
+        while (elements[j]) {
+            if (!elements[j]->element) {
                 merror(XML_ELEMNULL, ARGV0);
-                return(0);
-            }
-            else if(!elements[j]->content)
-            {
+                return (0);
+            } else if (!elements[j]->content) {
                 merror(XML_VALUENULL, ARGV0, elements[j]->element);
-                return(0);
+                return (0);
             }
 
-            /* Checking if it is a child of a rule */
-            else if(strcasecmp(elements[j]->element, xml_parent) == 0)
-            {
+            /* Check if it is a child of a rule */
+            else if (strcasecmp(elements[j]->element, xml_parent) == 0) {
                 pi->parent = _loadmemory(pi->parent, elements[j]->content);
             }
 
-            /* Getting the regex */
-            else if(strcasecmp(elements[j]->element,xml_regex) == 0)
-            {
+            /* Get the regex */
+            else if (strcasecmp(elements[j]->element, xml_regex) == 0) {
                 int r_offset;
                 r_offset = ReadDecodeAttrs(elements[j]->attributes,
                                            elements[j]->values);
 
-                if(r_offset & AFTER_ERROR)
-                {
+                if (r_offset & AFTER_ERROR) {
                     merror(DEC_REGEX_ERROR, ARGV0, pi->name);
-                    return(0);
+                    return (0);
                 }
 
                 /* Only the first regex entry may have an offset */
-                if(regex && r_offset)
-                {
+                if (regex && r_offset) {
                     merror(DUP_REGEX, ARGV0, pi->name);
                     merror(DEC_REGEX_ERROR, ARGV0, pi->name);
-                    return(0);
+                    return (0);
                 }
 
                 /* regex offset */
-                if(r_offset)
-                {
+                if (r_offset) {
                     pi->regex_offset = r_offset;
                 }
 
                 /* Assign regex */
                 regex =
                     _loadmemory(regex,
-                            elements[j]->content);
+                                elements[j]->content);
             }
 
-            /* Getting the pre match */
-            else if(strcasecmp(elements[j]->element,xml_prematch)==0)
-            {
+            /* Get the PCRE2 */
+            else if (strcasecmp(elements[j]->element, xml_pcre2) == 0) {
+                int r_offset;
+                r_offset = ReadDecodeAttrs(elements[j]->attributes,
+                                           elements[j]->values);
+
+                if (r_offset & AFTER_ERROR) {
+                    merror(DEC_REGEX_ERROR, ARGV0, pi->name);
+                    return (0);
+                }
+
+                /* Only the first regex entry may have an offset */
+                if (pcre2 && r_offset) {
+                    merror(DUP_REGEX, ARGV0, pi->name);
+                    merror(DEC_REGEX_ERROR, ARGV0, pi->name);
+                    return (0);
+                }
+
+                /* regex offset */
+                if (r_offset) {
+                    pi->regex_offset = r_offset;
+                }
+
+                /* Assign regex */
+                pcre2 =
+                    _loadmemory(pcre2,
+                                elements[j]->content);
+            }
+
+            /* Get the pre match */
+            else if (strcasecmp(elements[j]->element, xml_prematch) == 0) {
                 int r_offset;
 
                 r_offset = ReadDecodeAttrs(
-                                      elements[j]->attributes,
-                                      elements[j]->values);
+                               elements[j]->attributes,
+                               elements[j]->values);
 
-                if(r_offset & AFTER_ERROR)
-                {
+                if (r_offset & AFTER_ERROR) {
                     ErrorExit(DEC_REGEX_ERROR, ARGV0, pi->name);
                 }
 
-
                 /* Only the first prematch entry may have an offset */
-                if(prematch && r_offset)
-                {
+                if (prematch && r_offset) {
                     merror(DUP_REGEX, ARGV0, pi->name);
                     ErrorExit(DEC_REGEX_ERROR, ARGV0, pi->name);
                 }
 
-                if(r_offset)
-                {
+                if (r_offset) {
                     pi->prematch_offset = r_offset;
                 }
 
                 prematch =
                     _loadmemory(prematch,
-                            elements[j]->content);
+                                elements[j]->content);
+            }
+            else if (strcasecmp(elements[j]->element, xml_prematch_pcre2) == 0) {
+                int r_offset;
+
+                r_offset = ReadDecodeAttrs(
+                               elements[j]->attributes,
+                               elements[j]->values);
+
+                if (r_offset & AFTER_ERROR) {
+                    ErrorExit(DEC_REGEX_ERROR, ARGV0, pi->name);
+                }
+
+                /* Only the first prematch entry may have an offset */
+                if (prematch_pcre2 && r_offset) {
+                    merror(DUP_REGEX, ARGV0, pi->name);
+                    ErrorExit(DEC_REGEX_ERROR, ARGV0, pi->name);
+                }
+
+                if (r_offset) {
+                    pi->prematch_offset = r_offset;
+                }
+
+                prematch_pcre2 =
+                    _loadmemory(prematch_pcre2,
+                                elements[j]->content);
             }
 
-            /* Getting program name */
-            else if(strcasecmp(elements[j]->element,xml_program_name) == 0)
-            {
+            /* Get program name */
+            else if (strcasecmp(elements[j]->element, xml_program_name) == 0) {
                 p_name = _loadmemory(p_name, elements[j]->content);
             }
+            else if (strcasecmp(elements[j]->element, xml_program_name_pcre2) == 0) {
+                p_name_pcre2 = _loadmemory(p_name_pcre2, elements[j]->content);
+            }
 
-            /* Getting the fts comment */
-            else if(strcasecmp(elements[j]->element,xml_ftscomment)==0)
-            {
+            /* Get the FTS comment */
+            else if (strcasecmp(elements[j]->element, xml_ftscomment) == 0) {
             }
 
-            else if(strcasecmp(elements[j]->element,xml_usename)==0)
-            {
-                if(strcmp(elements[j]->content,"true") == 0)
+            else if (strcasecmp(elements[j]->element, xml_usename) == 0) {
+                if (strcmp(elements[j]->content, "true") == 0) {
                     pi->use_own_name = 1;
+                }
             }
 
-            else if(strcasecmp(elements[j]->element, xml_plugindecoder) == 0)
-            {
+            else if (strcasecmp(elements[j]->element, xml_plugindecoder) == 0) {
                 int ed_c = 0;
-                for(ed_c = 0; plugin_decoders[ed_c] != NULL; ed_c++)
-                {
-                    if(strcmp(plugin_decoders[ed_c],
-                              elements[j]->content) == 0)
-                    {
-                        /* Initializing plugin */
-                        void (*dec_init)() = plugin_decoders_init[ed_c];
-
+                for (ed_c = 0; plugin_decoders[ed_c] != NULL; ed_c++) {
+                    if (strcmp(plugin_decoders[ed_c],
+                               elements[j]->content) == 0) {
+                        /* Initialize plugin */
+                        void (*dec_init)(void) = (void (*)(void)) plugin_decoders_init[ed_c];
                         dec_init();
-                        pi->plugindecoder = plugin_decoders_exec[ed_c];
+                        pi->plugindecoder = (void (*)(void *)) plugin_decoders_exec[ed_c];
                         break;
                     }
                 }
 
                 /* Decoder not found */
-                if(pi->plugindecoder == NULL)
-                {
+                if (pi->plugindecoder == NULL) {
                     merror(INV_DECOPTION, ARGV0, elements[j]->element,
-                                          elements[j]->content);
-                    return(0);
+                           elements[j]->content);
+                    return (0);
                 }
             }
 
-
-            /* Getting the type */
-            else if(strcmp(elements[j]->element, xml_type) == 0)
-            {
-                if(strcmp(elements[j]->content, "firewall") == 0)
+            /* Get the type */
+            else if (strcmp(elements[j]->element, xml_type) == 0) {
+                if (strcmp(elements[j]->content, "firewall") == 0) {
                     pi->type = FIREWALL;
-                else if(strcmp(elements[j]->content, "ids") == 0)
+                } else if (strcmp(elements[j]->content, "ids") == 0) {
                     pi->type = IDS;
-                else if(strcmp(elements[j]->content, "web-log") == 0)
+                } else if (strcmp(elements[j]->content, "web-log") == 0) {
                     pi->type = WEBLOG;
-                else if(strcmp(elements[j]->content, "syslog") == 0)
+                } else if (strcmp(elements[j]->content, "syslog") == 0) {
                     pi->type = SYSLOG;
-                else if(strcmp(elements[j]->content, "squid") == 0)
+                } else if (strcmp(elements[j]->content, "squid") == 0) {
                     pi->type = SQUID;
-                else if(strcmp(elements[j]->content, "windows") == 0)
+                } else if (strcmp(elements[j]->content, "windows") == 0) {
                     pi->type = DECODER_WINDOWS;
-                else if(strcmp(elements[j]->content, "host-information") == 0)
+                } else if (strcmp(elements[j]->content, "host-information") == 0) {
                     pi->type = HOST_INFO;
-                else if(strcmp(elements[j]->content, "ossec") == 0)
+                } else if (strcmp(elements[j]->content, "ossec") == 0) {
                     pi->type = OSSEC_RL;
-                else
-                {
+                } else {
                     merror("%s: Invalid decoder type '%s'.",
-                               ARGV0, elements[j]->content);
-                    return(0);
+                           ARGV0, elements[j]->content);
+                    return (0);
                 }
             }
 
-            /* Getting the order */
-            else if(strcasecmp(elements[j]->element,xml_order)==0)
-            {
+            /* Get the order */
+            else if (strcasecmp(elements[j]->element, xml_order) == 0) {
                 char **norder, **s_norder;
                 int order_int = 0;
 
-                /* Maximum number is 8 for the order */
-                norder = OS_StrBreak(',',elements[j]->content, 8);
+                /* Maximum number for the order is limited by decoder_order_size */
+                norder = OS_StrBreak(',', elements[j]->content, MAX_DECODER_ORDER_SIZE);
                 s_norder = norder;
-                os_calloc(8, sizeof(void *), pi->order);
+                os_calloc(Config.decoder_order_size, sizeof(void *), pi->order);
+                os_calloc(Config.decoder_order_size, sizeof(char *), pi->fields);
 
-
-                /* Initializing the function pointers */
-                while(order_int < 8)
-                {
-                    pi->order[order_int] = NULL;
-                    order_int++;
-                }
                 order_int = 0;
 
+                /* Check the values from the order */
+                while (*norder) {
+                    if (order_int >= Config.decoder_order_size) {
+                        ErrorExit("%s: ERROR: Order has too many fields.", ARGV0);
+                    }
+
+                    char *word = &(*norder)[strspn(*norder, " ")];
+                    word[strcspn(word, " ")] = '\0';
 
-                /* Checking the values from the order */
-                while(*norder)
-                {
-                    if(strstr(*norder, "dstuser") != NULL)
-                    {
-                        pi->order[order_int] = (void *)DstUser_FP;
+                    if (strlen(word) == 0) {
+                        ErrorExit("decode-xml: Wrong field '%s' in the order"
+                                  " of decoder '%s'", *norder, pi->name);
                     }
-                    else if(strstr(*norder, "srcuser") != NULL)
-                    {
-                        pi->order[order_int] = (void *)SrcUser_FP;
+
+                    if (!strcmp(word, "dstuser")) {
+                        pi->order[order_int] = DstUser_FP;
+                    } else if (!strcmp(word, "srcuser")) {
+                        pi->order[order_int] = SrcUser_FP;
                     }
                     /* User is an alias to dstuser */
-                    else if(strstr(*norder, "user") != NULL)
-                    {
-                        pi->order[order_int] = (void *)DstUser_FP;
-                    }
-                    else if(strstr(*norder, "srcip") != NULL)
-                    {
-                        pi->order[order_int] = (void *)SrcIP_FP;
-                    }
-                    else if(strstr(*norder, "dstip") != NULL)
-                    {
-                        pi->order[order_int] = (void *)DstIP_FP;
-                    }
-                    else if(strstr(*norder, "srcport") != NULL)
-                    {
-                        pi->order[order_int] = (void *)SrcPort_FP;
-                    }
-                    else if(strstr(*norder, "dstport") != NULL)
-                    {
-                        pi->order[order_int] = (void *)DstPort_FP;
-                    }
-                    else if(strstr(*norder, "protocol") != NULL)
-                    {
-                        pi->order[order_int] = (void *)Protocol_FP;
-                    }
-                    else if(strstr(*norder, "action") != NULL)
-                    {
-                        pi->order[order_int] = (void *)Action_FP;
-                    }
-                    else if(strstr(*norder, "id") != NULL)
-                    {
-                        pi->order[order_int] = (void *)ID_FP;
-                    }
-                    else if(strstr(*norder, "url") != NULL)
-                    {
-                        pi->order[order_int] = (void *)Url_FP;
-                    }
-                    else if(strstr(*norder, "data") != NULL)
-                    {
-                        pi->order[order_int] = (void *)Data_FP;
-                    }
-                    else if(strstr(*norder, "extra_data") != NULL)
-                    {
-                        pi->order[order_int] = (void *)Data_FP;
-                    }
-                    else if(strstr(*norder, "status") != NULL)
-                    {
-                        pi->order[order_int] = (void *)Status_FP;
-                    }
-                    else if(strstr(*norder, "system_name") != NULL)
-                    {
-                        pi->order[order_int] = (void *)SystemName_FP;
-                    }
-                    else
-                    {
-                        ErrorExit("decode-xml: Wrong field '%s' in the order"
-                                  " of decoder '%s'",*norder,pi->name);
+                    else if (!strcmp(word, "user")) {
+                        pi->order[order_int] = DstUser_FP;
+                    } else if (!strcmp(word, "srcip")) {
+                        pi->order[order_int] = SrcIP_FP;
+                    } else if (!strcmp(word, "dstip")) {
+                        pi->order[order_int] = DstIP_FP;
+                    } else if (!strcmp(word, "srcport")) {
+                        pi->order[order_int] = SrcPort_FP;
+                    } else if (!strcmp(word, "dstport")) {
+                        pi->order[order_int] = DstPort_FP;
+                    } else if (!strcmp(word, "protocol")) {
+                        pi->order[order_int] = Protocol_FP;
+                    } else if (!strcmp(word, "action")) {
+                        pi->order[order_int] = Action_FP;
+                    } else if (!strcmp(word, "id")) {
+                        pi->order[order_int] = ID_FP;
+                    } else if (!strcmp(word, "url")) {
+                        pi->order[order_int] = Url_FP;
+                    } else if (!strcmp(word, "data")) {
+                        pi->order[order_int] = Data_FP;
+                    } else if (!strcmp(word, "extra_data")) {
+                        pi->order[order_int] = Data_FP;
+                    } else if (!strcmp(word, "status")) {
+                        pi->order[order_int] = Status_FP;
+                    } else if (!strcmp(word, "system_name")) {
+                        pi->order[order_int] = SystemName_FP;
+                    } else if (strstr(*norder, "filename") != NULL) {
+                        pi->order[order_int] = FileName_FP;
+                    } else {
+                        pi->order[order_int] = DynamicField_FP;
+                        pi->fields[order_int] = strdup(*norder);
+
                     }
 
                     free(*norder);
@@ -619,90 +578,68 @@ int ReadDecodeXML(char *file)
                 free(s_norder);
             }
 
-            /* Getting the fts order */
-            else if(strcasecmp(elements[j]->element,xml_fts)==0)
-            {
+            else if (strcasecmp(elements[j]->element, xml_accumulate) == 0) {
+                /* Enable Accumulator */
+                pi->accumulate = 1;
+            }
+
+            /* Get the FTS order */
+            else if (strcasecmp(elements[j]->element, xml_fts) == 0) {
                 char **norder;
                 char **s_norder;
 
-                /* Maximum number is 8 for the fts */
-                norder = OS_StrBreak(',',elements[j]->content, 8);
-                if(norder == NULL)
-                    ErrorExit(MEM_ERROR,ARGV0);
-
+                /* Maximum number is 8 for the FTS */
+                norder = OS_StrBreak(',', elements[j]->content, 8);
+                if (norder == NULL) {
+                    ErrorExit(MEM_ERROR, ARGV0, errno, strerror(errno));
+                }
 
-                /* Saving the initial point to free later */
+                /* Save the initial point to free later */
                 s_norder = norder;
 
-
-                /* Checking the values from the fts */
-                while(*norder)
-                {
-                    if(strstr(*norder, "dstuser") != NULL)
-                    {
-                        pi->fts|=FTS_DSTUSER;
-                    }
-                    if(strstr(*norder, "user") != NULL)
-                    {
-                        pi->fts|=FTS_DSTUSER;
+                /* Check the values from the FTS */
+                while (*norder) {
+                    if (strstr(*norder, "dstuser") != NULL) {
+                        pi->fts |= FTS_DSTUSER;
                     }
-                    else if(strstr(*norder, "srcuser") != NULL)
-                    {
-                        pi->fts|=FTS_SRCUSER;
-                    }
-                    else if(strstr(*norder, "srcip") != NULL)
-                    {
-                        pi->fts|=FTS_SRCIP;
-                    }
-                    else if(strstr(*norder, "dstip") != NULL)
-                    {
-                        pi->fts|=FTS_DSTIP;
-                    }
-                    else if(strstr(*norder, "id") != NULL)
-                    {
-                        pi->fts|=FTS_ID;
-                    }
-                    else if(strstr(*norder, "location") != NULL)
-                    {
-                        pi->fts|=FTS_LOCATION;
-                    }
-                    else if(strstr(*norder, "data") != NULL)
-                    {
-                        pi->fts|=FTS_DATA;
-                    }
-                    else if(strstr(*norder, "extra_data") != NULL)
-                    {
-                        pi->fts|=FTS_DATA;
-                    }
-                    else if(strstr(*norder, "system_name") != NULL)
-                    {
-                        pi->fts|=FTS_SYSTEMNAME;
-                    }
-                    else if(strstr(*norder, "name") != NULL)
-                    {
-                        pi->fts|=FTS_NAME;
-                    }
-                    else
-                    {
+                    if (strstr(*norder, "user") != NULL) {
+                        pi->fts |= FTS_DSTUSER;
+                    } else if (strstr(*norder, "srcuser") != NULL) {
+                        pi->fts |= FTS_SRCUSER;
+                    } else if (strstr(*norder, "srcip") != NULL) {
+                        pi->fts |= FTS_SRCIP;
+                    } else if (strstr(*norder, "dstip") != NULL) {
+                        pi->fts |= FTS_DSTIP;
+                    } else if (strstr(*norder, "id") != NULL) {
+                        pi->fts |= FTS_ID;
+                    } else if (strstr(*norder, "location") != NULL) {
+                        pi->fts |= FTS_LOCATION;
+                    } else if (strstr(*norder, "data") != NULL) {
+                        pi->fts |= FTS_DATA;
+                    } else if (strstr(*norder, "extra_data") != NULL) {
+                        pi->fts |= FTS_DATA;
+                    } else if (strstr(*norder, "system_name") != NULL) {
+                        pi->fts |= FTS_SYSTEMNAME;
+                    } else if (strstr(*norder, "name") != NULL) {
+                        pi->fts |= FTS_NAME;
+                    } else {
                         ErrorExit("decode-xml: Wrong field '%s' in the fts"
-                                  " decoder '%s'",*norder, pi->name);
+                                  " decoder '%s'", *norder, pi->name);
                     }
 
                     free(*norder);
                     norder++;
                 }
 
-                /* Clearing the memory here */
+                /* Clear memory here */
                 free(s_norder);
-            }
-            else
-            {
+            } else {
                 merror("%s: Invalid element '%s' for "
-                        "decoder '%s'",
-                        ARGV0,
-                        elements[j]->element,
-                        node[i]->element);
-                return(0);
+                       "decoder '%s'",
+                       ARGV0,
+                       elements[j]->element,
+                       node[i]->element);
+                return (0);
             }
 
             /* NEXT */
@@ -714,162 +651,156 @@ int ReadDecodeXML(char *file)
 
 
         /* Prematch must be set */
-        if(!prematch && !pi->parent && !p_name)
-        {
+        if (!(prematch || prematch_pcre2) && !pi->parent && !(p_name || p_name_pcre2)) {
             merror(DECODE_NOPRE, ARGV0, pi->name);
             merror(DEC_REGEX_ERROR, ARGV0, pi->name);
-            return(0);
+            return (0);
         }
 
         /* If pi->regex is not set, fts must not be set too */
-        if((!regex && (pi->fts || pi->order)) || (regex && !pi->order))
-        {
+        if ((!(regex || pcre2) && (pi->fts || pi->order)) || ((regex || pcre2) && !pi->order)) {
             merror(DEC_REGEX_ERROR, ARGV0, pi->name);
-            return(0);
+            return (0);
         }
 
-
         /* For the offsets */
-        if((pi->regex_offset & AFTER_PARENT) && !pi->parent)
-        {
+        if ((pi->regex_offset & AFTER_PARENT) && !pi->parent) {
             merror(INV_OFFSET, ARGV0, "after_parent");
             merror(DEC_REGEX_ERROR, ARGV0, pi->name);
-            return(0);
+            return (0);
         }
 
-        if(pi->regex_offset & AFTER_PREMATCH)
-        {
+        if (pi->regex_offset & AFTER_PREMATCH) {
             /* If after_prematch is set, but rule have
              * no parent, set AFTER_PARENT and unset
              * pre_match.
              */
-            if(!pi->parent)
-            {
+            if (!pi->parent) {
                 pi->regex_offset = 0;
-                pi->regex_offset|= AFTER_PARENT;
-            }
-            else if(!prematch)
-            {
+                pi->regex_offset |= AFTER_PARENT;
+            } else if (!(prematch || prematch_pcre2)) {
                 merror(INV_OFFSET, ARGV0, "after_prematch");
                 merror(DEC_REGEX_ERROR, ARGV0, pi->name);
-                return(0);
+                return (0);
             }
         }
 
         /* For the after_regex offset */
-        if(pi->regex_offset & AFTER_PREVREGEX)
-        {
-            if(!pi->parent || !regex)
-            {
+        if (pi->regex_offset & AFTER_PREVREGEX) {
+            if (!pi->parent || !(regex || pcre2)) {
                 merror(INV_OFFSET, ARGV0, "after_regex");
                 merror(DEC_REGEX_ERROR, ARGV0, pi->name);
-                return(0);
+                return (0);
             }
         }
 
-
-        /* Checking the prematch offset */
-        if(pi->prematch_offset)
-        {
+        /* Check the prematch offset */
+        if (pi->prematch_offset) {
             /* Only the after parent is allowed */
-            if(pi->prematch_offset & AFTER_PARENT)
-            {
-                if(!pi->parent)
-                {
+            if (pi->prematch_offset & AFTER_PARENT) {
+                if (!pi->parent) {
                     merror(INV_OFFSET, ARGV0, "after_parent");
                     merror(DEC_REGEX_ERROR, ARGV0, pi->name);
-                    return(0);
+                    return (0);
                 }
-            }
-            else
-            {
+            } else {
                 merror(DEC_REGEX_ERROR, ARGV0, pi->name);
-                return(0);
+                return (0);
             }
         }
 
-
-        /* Compiling the regex/prematch */
-        if(prematch)
-        {
+        /* Compile the regex/prematch */
+        if (prematch) {
             os_calloc(1, sizeof(OSRegex), pi->prematch);
-            if(!OSRegex_Compile(prematch, pi->prematch, 0))
-            {
+            if (!OSRegex_Compile(prematch, pi->prematch, 0)) {
                 merror(REGEX_COMPILE, ARGV0, prematch, pi->prematch->error);
-                return(0);
+                return (0);
             }
 
             free(prematch);
         }
+        else if (prematch_pcre2) {
+            os_calloc(1, sizeof(OSPcre2), pi->prematch_pcre2);
+            if (!OSPcre2_Compile(prematch_pcre2, pi->prematch_pcre2, PCRE2_CASELESS)) {
+                merror(REGEX_COMPILE, ARGV0, prematch_pcre2, pi->prematch_pcre2->error);
+                return (0);
+            }
+
+            free(prematch_pcre2);
+        }
 
-        /* Compiling the p_name */
-        if(p_name)
-        {
+        /* Compile the p_name */
+        if (p_name) {
             os_calloc(1, sizeof(OSMatch), pi->program_name);
-            if(!OSMatch_Compile(p_name, pi->program_name, 0))
-            {
+            if (!OSMatch_Compile(p_name, pi->program_name, 0)) {
                 merror(REGEX_COMPILE, ARGV0, p_name, pi->program_name->error);
-                return(0);
+                return (0);
             }
 
             free(p_name);
         }
+        else if (p_name_pcre2) {
+            os_calloc(1, sizeof(OSPcre2), pi->program_name_pcre2);
+            if (!OSPcre2_Compile(p_name_pcre2, pi->program_name_pcre2, PCRE2_CASELESS)) {
+                merror(REGEX_COMPILE, ARGV0, p_name_pcre2, pi->program_name_pcre2->error);
+                return (0);
+            }
+
+            free(p_name_pcre2);
+        }
 
         /* We may not have the pi->regex */
-        if(regex)
-        {
+        if (regex) {
             os_calloc(1, sizeof(OSRegex), pi->regex);
-            if(!OSRegex_Compile(regex, pi->regex, OS_RETURN_SUBSTRING))
-            {
+            if (!OSRegex_Compile(regex, pi->regex, OS_RETURN_SUBSTRING)) {
                 merror(REGEX_COMPILE, ARGV0, regex, pi->regex->error);
-                return(0);
+                return (0);
             }
 
             /* We must have the sub_strings to retrieve the nodes */
-            if(!pi->regex->sub_strings)
-            {
+            if (!pi->regex->sub_strings) {
                 merror(REGEX_SUBS, ARGV0, regex);
-                return(0);
+                return (0);
             }
 
             free(regex);
         }
+        else if (pcre2) {
+            os_calloc(1, sizeof(OSPcre2), pi->pcre2);
+            if (!OSPcre2_Compile(pcre2, pi->pcre2, PCRE2_CASELESS)) {
+                merror(REGEX_COMPILE, ARGV0, pcre2, pi->pcre2->error);
+                return (0);
+            }
 
+            free(pcre2);
+        }
 
-        /* Validating arguments */
-        if(pi->plugindecoder && (pi->regex || pi->order))
-        {
+        /* Validate arguments */
+        if (pi->plugindecoder && (pi->regex || pi->order)) {
             merror(DECODE_ADD, ARGV0, pi->name);
-            return(0);
+            return (0);
         }
 
-        /* Adding osdecoder to the list */
-        if(!OS_AddOSDecoder(pi))
-        {
+        /* Add osdecoder to the list */
+        if (!OS_AddOSDecoder(pi)) {
             merror(DECODER_ERROR, ARGV0);
-            return(0);
+            return (0);
         }
 
         i++;
     } /* while (node[i]) */
 
 
-    /* Cleaning  node and XML structures */
+    /* Clean node and XML structures */
     OS_ClearNode(node);
-
-
     OS_ClearXML(&xml);
 
-
-    /* Done over here */
-    return(1);
+    return (1);
 }
 
-
-
 int SetDecodeXML()
 {
-    /* Adding rootcheck decoder to list */
+    /* Add rootcheck decoder to list */
     addDecoder2list(ROOTCHECK_MOD);
     addDecoder2list(SYSCHECK_MOD);
     addDecoder2list(SYSCHECK_MOD2);
@@ -879,76 +810,58 @@ int SetDecodeXML()
     addDecoder2list(HOSTINFO_NEW);
     addDecoder2list(HOSTINFO_MOD);
 
-
-    /* Setting ids - for our two lists */
-    if(!os_setdecoderids(NULL))
-    {
+    /* Set ids - for our two lists */
+    if (!os_setdecoderids(NULL)) {
         merror(DECODER_ERROR, ARGV0);
-        return(0);
+        return (0);
     }
-    if(!os_setdecoderids(ARGV0))
-    {
+    if (!os_setdecoderids(ARGV0)) {
         merror(DECODER_ERROR, ARGV0);
-        return(0);
+        return (0);
     }
 
-
-    /* Done over here */
-    return(1);
+    return (1);
 }
 
-
-/* _loadmemory: v0.1
- * Allocate memory at "*at" and copy *str to it.
- * If *at already exist, realloc the memory and cat str
- * on it.
- * It will return the new string
+/* Allocate memory at "*at" and copy *str to it
+ * If *at already exist, realloc the memory and cat str on it
+ * Returns the new string
  */
 char *_loadmemory(char *at, char *str)
 {
-    if(at == NULL)
-    {
-        int strsize = 0;
-        if((strsize = strlen(str)) < OS_SIZE_1024)
-        {
-            at = calloc(strsize+1,sizeof(char));
-            if(at == NULL)
-            {
-                merror(MEM_ERROR,ARGV0);
-                return(NULL);
+    if (at == NULL) {
+        size_t strsize = 0;
+        if ((strsize = strlen(str)) < OS_SIZE_8192) {
+            at = (char *) calloc(strsize + 1, sizeof(char));
+            if (at == NULL) {
+                merror(MEM_ERROR, ARGV0, errno, strerror(errno));
+                return (NULL);
             }
-            strncpy(at,str,strsize);
-            return(at);
-        }
-        else
-        {
-            merror(SIZE_ERROR,ARGV0,str);
-            return(NULL);
+            strncpy(at, str, strsize);
+            return (at);
+        } else {
+            merror(SIZE_ERROR, ARGV0, str);
+            return (NULL);
         }
     }
-    /* At is not null. Need to reallocat its memory and copy str to it */
-    else
-    {
-        int strsize = strlen(str);
-        int atsize = strlen(at);
-        int finalsize = atsize+strsize+1;
-        if(finalsize > OS_SIZE_1024)
-        {
-            merror(SIZE_ERROR,ARGV0,str);
-            return(NULL);
-        }
-        at = realloc(at, (finalsize +1)*sizeof(char));
-        if(at == NULL)
-        {
-            merror(MEM_ERROR,ARGV0);
-            return(NULL);
-        }
-        strncat(at,str,strsize);
+    /* At is not null. Need to reallocate its memory and copy str to it */
+    else {
+        size_t strsize = strlen(str);
+        size_t atsize = strlen(at);
+        size_t finalsize = atsize + strsize + 1;
+        if (finalsize > OS_SIZE_8192) {
+            merror(SIZE_ERROR, ARGV0, str);
+            return (NULL);
+        }
+        at = (char *) realloc(at, (finalsize + 1) * sizeof(char));
+        if (at == NULL) {
+            merror(MEM_ERROR, ARGV0, errno, strerror(errno));
+            return (NULL);
+        }
+        strncat(at, str, strsize);
         at[finalsize - 1] = '\0';
 
-        return(at);
+        return (at);
     }
-    return(NULL);
+    return (NULL);
 }
-
-/* EOF */