new upstream release (3.3.0); modify package compatibility for Stretch
[ossec-hids.git] / src / analysisd / decoders / decoder.c
old mode 100755 (executable)
new mode 100644 (file)
index 7f73f24..cc20b1a
@@ -1,6 +1,3 @@
-/* @(#) $Id: ./src/analysisd/decoders/decoder.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 "eventinfo.h"
 #include "decoder.h"
+#include "config.h"
 
 
 
-/* DecodeEvent.
- * Will use the osdecoders to decode the received event.
- */
+/* Use the osdecoders to decode the received event */
 void DecodeEvent(Eventinfo *lf)
 {
     OSDecoderNode *node;
     OSDecoderNode *child_node;
     OSDecoderInfo *nnode;
 
-    const char *llog;
-    const char *pmatch;
-    const char *cmatch;
+    const char *llog = NULL;
+    const char *pmatch = NULL;
+    const char *cmatch = NULL;
     const char *regex_prev = NULL;
 
-
     node = OS_GetFirstOSDecoder(lf->program_name);
 
-
-    /* Return if no node...
-     * This shouldn't happen here anyways.
-     */
-    if(!node)
+    if (!node) {
         return;
+    }
 
-
-    #ifdef TESTRULE
-    if(!alert_only)
-    {
+#ifdef TESTRULE
+    if (!alert_only) {
         print_out("\n**Phase 2: Completed decoding.");
     }
-    #endif
+#endif
 
-    do
-    {
+    do {
         nnode = node->osdecoder;
 
-
-        /* First checking program name */
-        if(lf->program_name)
-        {
-            if(!OSMatch_Execute(lf->program_name, lf->p_name_size,
-                        nnode->program_name))
-            {
-                continue;
+        /* First check program name */
+        if (lf->program_name) {
+            if (nnode->program_name) {
+                if (!OSMatch_Execute(lf->program_name, lf->p_name_size,
+                                     nnode->program_name)) {
+                    continue;
+                }
+                pmatch = lf->log;
+            } else if (nnode->program_name_pcre2) {
+                if (!OSPcre2_Execute(lf->program_name, nnode->program_name_pcre2)) {
+                    continue;
+                }
+                pmatch = lf->log;
             }
-            pmatch = lf->log;
         }
 
-
         /* If prematch fails, go to the next osdecoder in the list */
-        if(nnode->prematch)
-        {
-            if(!(pmatch = OSRegex_Execute(lf->log, nnode->prematch)))
-            {
+        if (nnode->prematch) {
+            if (!(pmatch = OSRegex_Execute(lf->log, nnode->prematch))) {
+                continue;
+            }
+        }
+        else if (nnode->prematch_pcre2) {
+            if (!(pmatch = OSPcre2_Execute(lf->log, nnode->prematch_pcre2))) {
                 continue;
             }
-
-            /* Next character */
-            if(*pmatch != '\0')
-                pmatch++;
         }
 
-
-        #ifdef TESTRULE
-        if(!alert_only)print_out("       decoder: '%s'", nnode->name);
-        #endif
-
+#ifdef TESTRULE
+        if (!alert_only) {
+            print_out("       decoder: '%s'", nnode->name);
+        }
+#endif
 
         lf->decoder_info = nnode;
-
-
         child_node = node->child;
 
-
         /* If no child node is set, set the child node
          * as if it were the child (ugh)
          */
-        if(!child_node)
-        {
+        if (!child_node) {
             child_node = node;
         }
 
-        else
-        {
+        else {
             /* Check if we have any child osdecoder */
-            while(child_node)
-            {
+            while (child_node) {
                 nnode = child_node->osdecoder;
 
-
                 /* If we have a pre match and it matches, keep
                  * going. If we don't have a prematch, stop
                  * and go for the regexes.
                  */
-                if(nnode->prematch)
-                {
-                    const char *llog;
+                if (nnode->prematch) {
+                    const char *llog2;
 
                     /* If we have an offset set, use it */
-                    if(nnode->prematch_offset & AFTER_PARENT)
-                    {
-                        llog = pmatch;
+                    if (nnode->prematch_offset & AFTER_PARENT) {
+                        llog2 = pmatch;
+                    } else {
+                        llog2 = lf->log;
                     }
-                    else
-                    {
-                        llog = lf->log;
+
+                    if ((cmatch = OSRegex_Execute(llog2, nnode->prematch))) {
+                        lf->decoder_info = nnode;
+
+                        break;
                     }
+                } else if (nnode->prematch_pcre2) {
+                    const char *llog2;
 
-                    if((cmatch = OSRegex_Execute(llog, nnode->prematch)))
-                    {
-                        if(*cmatch != '\0')
-                            cmatch++;
+                    /* If we have an offset set, use it */
+                    if (nnode->prematch_offset & AFTER_PARENT) {
+                        llog2 = pmatch;
+                    } else {
+                        llog2 = lf->log;
+                    }
 
+                    if ((cmatch = OSPcre2_Execute(llog2, nnode->prematch_pcre2))) {
                         lf->decoder_info = nnode;
 
                         break;
                     }
-                }
-                else
-                {
+                } else {
                     cmatch = pmatch;
                     break;
                 }
 
-
                 /* If we have multiple regex-only childs,
                  * do not attempt to go any further with them.
                  */
-                if(child_node->osdecoder->get_next)
-                {
-                    do
-                    {
+                if (child_node->osdecoder->get_next) {
+                    do {
                         child_node = child_node->next;
-                    }while(child_node && child_node->osdecoder->get_next);
+                    } while (child_node && child_node->osdecoder->get_next);
 
-                    if(!child_node)
+                    if (!child_node) {
                         return;
+                    }
 
                     child_node = child_node->next;
                     nnode = NULL;
-                }
-                else
-                {
+                } else {
                     child_node = child_node->next;
                     nnode = NULL;
                 }
             }
         }
 
-
         /* Nothing matched */
-        if(!nnode)
+        if (!nnode) {
             return;
+        }
 
-
-        /* If we have a external decoder, execute it */
-        if(nnode->plugindecoder)
-        {
+        /* If we have an external decoder, execute it */
+        if (nnode->plugindecoder) {
             nnode->plugindecoder(lf);
             return;
         }
 
-
-        /* Getting the regex */
-        while(child_node)
-        {
-            if(nnode->regex)
-            {
-                int i = 0;
+        /* Get the regex */
+        while (child_node) {
+            if (nnode->regex) {
+                int i;
 
                 /* With regex we have multiple options
                  * regarding the offset:
@@ -201,34 +175,25 @@ void DecodeEvent(Eventinfo *lf)
                  * after some previous regex,
                  * or any offset
                  */
-                if(nnode->regex_offset)
-                {
-                    if(nnode->regex_offset & AFTER_PARENT)
-                    {
+                if (nnode->regex_offset) {
+                    if (nnode->regex_offset & AFTER_PARENT) {
                         llog = pmatch;
-                    }
-                    else if(nnode->regex_offset & AFTER_PREMATCH)
-                    {
+                    } else if (nnode->regex_offset & AFTER_PREMATCH) {
                         llog = cmatch;
-                    }
-                    else if(nnode->regex_offset & AFTER_PREVREGEX)
-                    {
-                        if(!regex_prev)
+                    } else if (nnode->regex_offset & AFTER_PREVREGEX) {
+                        if (!regex_prev) {
                             llog = cmatch;
-                        else
+                        } else {
                             llog = regex_prev;
+                        }
                     }
-                }
-                else
-                {
+                } else {
                     llog = lf->log;
                 }
 
                 /* If Regex does not match, return */
-                if(!(regex_prev = OSRegex_Execute(llog, nnode->regex)))
-                {
-                    if(nnode->get_next)
-                    {
+                if (!(regex_prev = OSRegex_Execute(llog, nnode->regex))) {
+                    if (nnode->get_next) {
                         child_node = child_node->next;
                         nnode = child_node->osdecoder;
                         continue;
@@ -236,30 +201,86 @@ void DecodeEvent(Eventinfo *lf)
                     return;
                 }
 
+                lf->decoder_info = nnode;
+
+                for (i = 0; nnode->regex->sub_strings[i]; i++) {
+                    if (i >= Config.decoder_order_size) {
+                        ErrorExit("%s: ERROR: Regex has too many groups.", ARGV0);
+                    }
+
+                    if (nnode->order[i])
+                        nnode->order[i](lf, nnode->regex->sub_strings[i], i);
+                    else
+                        /* We do not free any memory used above */
+                        os_free(nnode->regex->sub_strings[i]);
+
+                    nnode->regex->sub_strings[i] = NULL;
+                }
+
+                /* If we have a next regex, try getting it */
+                if (nnode->get_next) {
+                    child_node = child_node->next;
+                    nnode = child_node->osdecoder;
+                    continue;
+                }
 
-                /* Fixing next pointer */
-                if(*regex_prev != '\0')
-                    regex_prev++;
+                break;
+            }
+            else if (nnode->pcre2) {
+                int i;
 
-                while(nnode->regex->sub_strings[i])
-                {
-                    if(nnode->order[i])
-                    {
-                        nnode->order[i](lf, nnode->regex->sub_strings[i]);
-                        nnode->regex->sub_strings[i] = NULL;
-                        i++;
+                /* With regex we have multiple options
+                 * regarding the offset:
+                 * after the prematch,
+                 * after the parent,
+                 * after some previous regex,
+                 * or any offset
+                 */
+                if (nnode->regex_offset) {
+                    if (nnode->regex_offset & AFTER_PARENT) {
+                        llog = pmatch;
+                    } else if (nnode->regex_offset & AFTER_PREMATCH) {
+                        llog = cmatch;
+                    } else if (nnode->regex_offset & AFTER_PREVREGEX) {
+                        if (!regex_prev) {
+                            llog = cmatch;
+                        } else {
+                            llog = regex_prev;
+                        }
+                    }
+                } else {
+                    llog = lf->log;
+                }
+
+                /* If Regex does not match, return */
+                if (!(regex_prev = OSPcre2_Execute(llog, nnode->pcre2))) {
+                    if (nnode->get_next) {
+                        child_node = child_node->next;
+                        nnode = child_node->osdecoder;
                         continue;
                     }
+                    return;
+                }
 
-                    /* We do not free any memory used above */
-                    os_free(nnode->regex->sub_strings[i]);
-                    nnode->regex->sub_strings[i] = NULL;
-                    i++;
+
+                lf->decoder_info = nnode;
+
+                for (i = 0; nnode->pcre2->sub_strings[i]; i++) {
+                    if (i >= Config.decoder_order_size) {
+                        ErrorExit("%s: ERROR: Regex has too many groups.", ARGV0);
+                    }
+
+                    if (nnode->order[i])
+                        nnode->order[i](lf, nnode->pcre2->sub_strings[i], i);
+                    else
+                        /* We do not free any memory used above */
+                        os_free(nnode->pcre2->sub_strings[i]);
+
+                    nnode->pcre2->sub_strings[i] = NULL;
                 }
 
                 /* If we have a next regex, try getting it */
-                if(nnode->get_next)
-                {
+                if (nnode->get_next) {
                     child_node = child_node->next;
                     nnode = child_node->osdecoder;
                     continue;
@@ -268,147 +289,235 @@ void DecodeEvent(Eventinfo *lf)
                 break;
             }
 
+
             /* If we don't have a regex, we may leave now */
             return;
         }
 
         /* ok to return  */
         return;
-    }while((node=node->next) != NULL);
+    } while ((node = node->next) != NULL);
 
-    #ifdef TESTRULE
-    if(!alert_only)
-    {
+#ifdef TESTRULE
+    if (!alert_only) {
         print_out("       No decoder matched.");
     }
-    #endif
-
+#endif
 }
 
-
 /*** Event decoders ****/
-void *DstUser_FP(Eventinfo *lf, char *field)
+
+void *DstUser_FP(Eventinfo *lf, char *field, __attribute__((unused)) int order)
 {
-    #ifdef TESTRULE
-    if(!alert_only)print_out("       dstuser: '%s'", field);
-    #endif
+#ifdef TESTRULE
+    if (!alert_only) {
+        print_out("       dstuser: '%s'", field);
+    }
+#endif
 
     lf->dstuser = field;
-    return(NULL);
+    return (NULL);
 }
-void *SrcUser_FP(Eventinfo *lf, char *field)
+
+void *SrcUser_FP(Eventinfo *lf, char *field, __attribute__((unused)) int order)
 {
-    #ifdef TESTRULE
-    if(!alert_only)print_out("       srcuser: '%s'", field);
-    #endif
+#ifdef TESTRULE
+    if (!alert_only) {
+        print_out("       srcuser: '%s'", field);
+    }
+#endif
 
     lf->srcuser = field;
-    return(NULL);
+    return (NULL);
 }
-void *SrcIP_FP(Eventinfo *lf, char *field)
+
+void *SrcIP_FP(Eventinfo *lf, char *field, __attribute__((unused)) int order)
 {
+#ifdef TESTRULE
+    if (!alert_only) {
+        print_out("       srcip: '%s'", field);
+    }
+#endif
+
+    lf->srcip = field;
+
+#ifdef LIBGEOIP_ENABLED
+
+    if(!lf->srcgeoip) { 
+        lf->srcgeoip = GetGeoInfobyIP(lf->srcip);
+    }
+
     #ifdef TESTRULE
-    if(!alert_only)print_out("       srcip: '%s'", field);
+        if (lf->srcgeoip && !alert_only)
+            print_out("       srcgeoip: '%s'", lf->srcgeoip);
     #endif
 
-    lf->srcip = field;
-    return(NULL);
+#endif
+    return (NULL);
+
 }
-void *DstIP_FP(Eventinfo *lf, char *field)
+
+void *DstIP_FP(Eventinfo *lf, char *field, __attribute__((unused)) int order)
 {
+#ifdef TESTRULE
+    if (!alert_only) {
+        print_out("       dstip: '%s'", field);
+    }
+#endif
+
+    lf->dstip = field;
+#ifdef LIBGEOIP_ENABLED
+
+    if(!lf->dstgeoip) { 
+        lf->dstgeoip = GetGeoInfobyIP(lf->dstip);
+    }
     #ifdef TESTRULE
-    if(!alert_only)print_out("       dstip: '%s'", field);
+        if (lf->dstgeoip && !alert_only)
+            print_out("       dstgeoip: '%s'", lf->dstgeoip);
     #endif
 
-    lf->dstip = field;
-    return(NULL);
+#endif
+    return (NULL);
+
 }
-void *SrcPort_FP(Eventinfo *lf, char *field)
+
+void *SrcPort_FP(Eventinfo *lf, char *field, __attribute__((unused)) int order)
 {
-    #ifdef TESTRULE
-    if(!alert_only)print_out("       srcport: '%s'", field);
-    #endif
+#ifdef TESTRULE
+    if (!alert_only) {
+        print_out("       srcport: '%s'", field);
+    }
+#endif
 
     lf->srcport = field;
-    return(NULL);
+    return (NULL);
 }
-void *DstPort_FP(Eventinfo *lf, char *field)
+
+void *DstPort_FP(Eventinfo *lf, char *field, __attribute__((unused)) int order)
 {
-    #ifdef TESTRULE
-    if(!alert_only)print_out("       dstport: '%s'", field);
-    #endif
+#ifdef TESTRULE
+    if (!alert_only) {
+        print_out("       dstport: '%s'", field);
+    }
+#endif
 
     lf->dstport = field;
-    return(NULL);
+    return (NULL);
 }
-void *Protocol_FP(Eventinfo *lf, char *field)
+
+void *Protocol_FP(Eventinfo *lf, char *field, __attribute__((unused)) int order)
 {
-    #ifdef TESTRULE
-    if(!alert_only)print_out("       proto: '%s'", field);
-    #endif
+#ifdef TESTRULE
+    if (!alert_only) {
+        print_out("       proto: '%s'", field);
+    }
+#endif
 
     lf->protocol = field;
-    return(NULL);
+    return (NULL);
 }
-void *Action_FP(Eventinfo *lf, char *field)
+
+void *Action_FP(Eventinfo *lf, char *field, __attribute__((unused)) int order)
 {
-    #ifdef TESTRULE
-    if(!alert_only)print_out("       action: '%s'", field);
-    #endif
+#ifdef TESTRULE
+    if (!alert_only) {
+        print_out("       action: '%s'", field);
+    }
+#endif
 
     lf->action = field;
-    return(NULL);
+    return (NULL);
 }
-void *ID_FP(Eventinfo *lf, char *field)
+
+void *ID_FP(Eventinfo *lf, char *field, __attribute__((unused)) int order)
 {
-    #ifdef TESTRULE
-    if(!alert_only)print_out("       id: '%s'", field);
-    #endif
+#ifdef TESTRULE
+    if (!alert_only) {
+        print_out("       id: '%s'", field);
+    }
+#endif
 
     lf->id = field;
-    return(NULL);
+    return (NULL);
 }
-void *Url_FP(Eventinfo *lf, char *field)
+
+void *Url_FP(Eventinfo *lf, char *field, __attribute__((unused)) int order)
 {
-    #ifdef TESTRULE
-    if(!alert_only)print_out("       url: '%s'", field);
-    #endif
+#ifdef TESTRULE
+    if (!alert_only) {
+        print_out("       url: '%s'", field);
+    }
+#endif
 
     lf->url = field;
-    return(NULL);
+    return (NULL);
 }
-void *Data_FP(Eventinfo *lf, char *field)
+
+void *Data_FP(Eventinfo *lf, char *field, __attribute__((unused)) int order)
 {
-    #ifdef TESTRULE
-    if(!alert_only)print_out("       extra_data: '%s'", field);
-    #endif
+#ifdef TESTRULE
+    if (!alert_only) {
+        print_out("       extra_data: '%s'", field);
+    }
+#endif
 
     lf->data = field;
-    return(NULL);
+    return (NULL);
 }
-void *Status_FP(Eventinfo *lf, char *field)
+
+void *Status_FP(Eventinfo *lf, char *field, __attribute__((unused)) int order)
 {
-    #ifdef TESTRULE
-    if(!alert_only)print_out("       status: '%s'", field);
-    #endif
+#ifdef TESTRULE
+    if (!alert_only) {
+        print_out("       status: '%s'", field);
+    }
+#endif
 
     lf->status = field;
-    return(NULL);
+    return (NULL);
 }
-void *SystemName_FP(Eventinfo *lf, char *field)
+
+void *SystemName_FP(Eventinfo *lf, char *field, __attribute__((unused)) int order)
 {
-    #ifdef TESTRULE
-    if(!alert_only)print_out("       system_name: '%s'", field);
-    #endif
+#ifdef TESTRULE
+    if (!alert_only) {
+        print_out("       system_name: '%s'", field);
+    }
+#endif
 
     lf->systemname = field;
-    return(NULL);
+    return (NULL);
 }
-void *None_FP(Eventinfo *lf, char *field)
+
+void *FileName_FP(Eventinfo *lf, char *field, __attribute__((unused)) int order)
 {
-    free(field);
-    return(NULL);
+#ifdef TESTRULE
+    if (!alert_only) {
+        print_out("       filename: '%s'", field);
+    }
+#endif
+
+    lf->filename = field;
+    return (NULL);
 }
 
 
-/* EOF */
+void *DynamicField_FP(Eventinfo *lf, char *field, int order)
+{
+#ifdef TESTRULE
+    if (!alert_only) {
+        print_out("       %s: '%s'", lf->decoder_info->fields[order], field);
+    }
+#endif
+
+    lf->fields[order] = field;
+
+    return (NULL);
+}
+
+void *None_FP(__attribute__((unused)) Eventinfo *lf, char *field, __attribute__((unused)) int order)
+{
+    free(field);
+    return (NULL);
+}
+