-/* @(#) $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:
* 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;
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;
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);
+}
+