diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-15 16:28:20 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-15 16:28:20 +0000 |
commit | dcc721a95bef6f0d8e6d8775b8efe33e5aecd562 (patch) | |
tree | 66a2774cd0ee294d019efd71d2544c70f42b2842 /contrib/pmpanngfw/pmpanngfw.c | |
parent | Initial commit. (diff) | |
download | rsyslog-dcc721a95bef6f0d8e6d8775b8efe33e5aecd562.tar.xz rsyslog-dcc721a95bef6f0d8e6d8775b8efe33e5aecd562.zip |
Adding upstream version 8.2402.0.upstream/8.2402.0
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'contrib/pmpanngfw/pmpanngfw.c')
-rw-r--r-- | contrib/pmpanngfw/pmpanngfw.c | 296 |
1 files changed, 296 insertions, 0 deletions
diff --git a/contrib/pmpanngfw/pmpanngfw.c b/contrib/pmpanngfw/pmpanngfw.c new file mode 100644 index 0000000..c65cee7 --- /dev/null +++ b/contrib/pmpanngfw/pmpanngfw.c @@ -0,0 +1,296 @@ +/* pmpanngfw.c + * + * this detects logs sent by Palo Alto Networks NGFW and transforms CSV into tab-separated fields + * for handling inside the mmnormalize + * + * Example: foo,"bar,""baz""",qux becomes foo<TAB>bar,"baz"<TAB>qux + * + * created 2010-12-13 by Luigi Mori (lmori@paloaltonetworks.com) based on pmsnare + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * -or- + * see COPYING.ASL20 in the source distribution + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "config.h" +#include "rsyslog.h" +#include <stdlib.h> +#include <string.h> +#include <assert.h> +#include <ctype.h> +#include "conf.h" +#include "syslogd-types.h" +#include "template.h" +#include "msg.h" +#include "module-template.h" +#include "glbl.h" +#include "errmsg.h" +#include "parser.h" +#include "datetime.h" +#include "unicode-helper.h" +#include "typedefs.h" +#include "rsconf.h" + +MODULE_TYPE_PARSER +MODULE_TYPE_NOKEEP +PARSER_NAME("rsyslog.panngfw") + +/* internal structures + */ +DEF_PMOD_STATIC_DATA +DEFobjCurrIf(glbl) +DEFobjCurrIf(parser) +DEFobjCurrIf(datetime) + + +/* static data */ +static int bParseHOSTNAMEandTAG; /* cache for the equally-named global param - performance enhancement */ + +typedef struct { + uint64 value; + uint64 mask; +} log_type_t; + +const log_type_t log_types[] = { + { 0x002c544145524854ULL, 0x00FFFFFFFFFFFFFFULL }, /* THREAT, */ + { 0x2c43494646415254ULL, 0xFFFFFFFFFFFFFFFFULL }, /* TRAFFIC, */ + { 0x002c4d4554535953ULL, 0x00FFFFFFFFFFFFFFULL }, /* CONFIG */ + { 0x002c4749464e4f43ULL, 0x00FFFFFFFFFFFFFFULL } /* SYSTEM */ +}; + +#define NUM_LOG_TYPES (sizeof(log_types)/sizeof(log_type_t)) + + +BEGINisCompatibleWithFeature +CODESTARTisCompatibleWithFeature + if(eFeat == sFEATUREAutomaticSanitazion) + iRet = RS_RET_OK; + if(eFeat == sFEATUREAutomaticPRIParsing) + iRet = RS_RET_OK; +ENDisCompatibleWithFeature + + + +BEGINparse + uchar *p2parse; + uchar *p2target; + uchar *msgend; + int lenMsg, lenDelta; + int state; + int num_fields = 4; + uchar *f3_commas[3]; + int cur_comma = 0; + uint64 log_type; + unsigned int j; +CODESTARTparse + #define CSV_DELIMITER '\t' + #define STATE_FIELD_START 0 + #define STATE_IN_FIELD 1 + #define STATE_IN_QUOTE 2 + #define STATE_IN_QUOTE_QUOTE 3 + + state = STATE_FIELD_START; + + dbgprintf("Message will now be parsed by fix Palo Alto Networks NGFW parser.\n"); + assert(pMsg != NULL); + assert(pMsg->pszRawMsg != NULL); + + lenMsg = pMsg->iLenRawMsg - pMsg->offAfterPRI; + /* note: offAfterPRI is already the number of PRI chars (do not add one!) */ + p2parse = pMsg->pszRawMsg + pMsg->offAfterPRI; /* point to start of text, after PRI */ + msgend = p2parse+lenMsg; + + dbgprintf("pmpanngfw: msg to look at: [%d]'%s'\n", lenMsg, p2parse); + + /* pass the first 3 fields */ + while(p2parse < msgend) { + if (*p2parse == ',') { + f3_commas[cur_comma] = p2parse; + if (cur_comma == 2) { + break; + } + cur_comma++; + } + p2parse++; + } + + /* check number of fields detected so far */ + if (cur_comma != 2) { + dbgprintf("not a PAN-OS syslog message: first 3 fields not found\n"); + ABORT_FINALIZE(RS_RET_COULD_NOT_PARSE); + } + + /* check msg length */ + p2parse++; + if ((p2parse > msgend) || ((msgend - p2parse) < (int)sizeof(uint64))) { + dbgprintf("not a PAN-OS syslog message: too short\n"); + ABORT_FINALIZE(RS_RET_COULD_NOT_PARSE); + } + + /* check log type */ + log_type = *((uint64 *)p2parse); + for(j = 0; j < (int)NUM_LOG_TYPES; j++) { + if ((log_type & log_types[j].mask) == log_types[j].value) + break; + } + if (j == NUM_LOG_TYPES) { + dbgprintf("not a PAN-OS syslog message, log type: %llx\n", log_type); + ABORT_FINALIZE(RS_RET_COULD_NOT_PARSE); + } + + /* set the delimiter */ + *f3_commas[0] = CSV_DELIMITER; + *f3_commas[1] = CSV_DELIMITER; + *f3_commas[2] = CSV_DELIMITER; + + p2target = p2parse; + + while(p2parse < msgend) { + switch(state) { + case STATE_FIELD_START: + switch(*p2parse) { + case '"': + state = STATE_IN_QUOTE; + p2parse++; + break; + + case ',': + state = STATE_FIELD_START; + *p2target = CSV_DELIMITER; + num_fields++; + p2parse++; + p2target++; + break; + + default: + state = STATE_IN_FIELD; + *p2target = *p2parse; + p2parse++; + p2target++; + } + break; + + case STATE_IN_FIELD: + switch(*p2parse) { + case ',': + state = STATE_FIELD_START; + *p2target = CSV_DELIMITER; + num_fields++; + p2parse++; + p2target++; + break; + + default: + *p2target = *p2parse; + p2parse++; + p2target++; + } + break; + + case STATE_IN_QUOTE: + switch(*p2parse) { + case '"': + state = STATE_IN_QUOTE_QUOTE; + p2parse++; + break; + + default: + *p2target = *p2parse; + p2parse++; + p2target++; + } + break; + + case STATE_IN_QUOTE_QUOTE: + switch(*p2parse) { + case '"': + state = STATE_IN_QUOTE; + *p2target = *p2parse; + p2parse++; + p2target++; + break; + + case ',': + state = STATE_FIELD_START; + *p2target = CSV_DELIMITER; + num_fields++; + p2parse++; + p2target++; + break; + + default: + dbgprintf("pmpanngfw: martian char (%d) after quote in quote\n", *p2parse); + ABORT_FINALIZE(RS_RET_COULD_NOT_PARSE); + } + break; + + default: + dbgprintf("how could I have reached this state ?!?\n"); + ABORT_FINALIZE(RS_RET_COULD_NOT_PARSE); + } + } + + if(p2parse != p2target) { + lenDelta = p2parse - p2target; + + assert(lenDelta >= 2); + + *p2target = 0; + + pMsg->iLenRawMsg -= lenDelta; + pMsg->iLenMSG -= lenDelta; + } + + lenMsg = p2target - (pMsg->pszRawMsg + pMsg->offAfterPRI); + + DBGPRINTF("pmpanngfw: new message: [%d]'%s'\n", lenMsg, pMsg->pszRawMsg + pMsg->offAfterPRI); + DBGPRINTF("pmpanngfw: # fields: %d\n", num_fields); + + ABORT_FINALIZE(RS_RET_COULD_NOT_PARSE); + +finalize_it: +ENDparse + + +BEGINmodExit +CODESTARTmodExit + /* release what we no longer need */ + objRelease(glbl, CORE_COMPONENT); + objRelease(parser, CORE_COMPONENT); + objRelease(datetime, CORE_COMPONENT); +ENDmodExit + + +BEGINqueryEtryPt +CODESTARTqueryEtryPt +CODEqueryEtryPt_STD_PMOD_QUERIES +CODEqueryEtryPt_IsCompatibleWithFeature_IF_OMOD_QUERIES +ENDqueryEtryPt + + +BEGINmodInit() +CODESTARTmodInit + *ipIFVersProvided = CURR_MOD_IF_VERSION; /* we only support the current interface specification */ +CODEmodInit_QueryRegCFSLineHdlr + CHKiRet(objUse(glbl, CORE_COMPONENT)); + CHKiRet(objUse(parser, CORE_COMPONENT)); + CHKiRet(objUse(datetime, CORE_COMPONENT)); + + DBGPRINTF("panngfw parser init called, compiled with version %s\n", VERSION); + bParseHOSTNAMEandTAG = glbl.GetParseHOSTNAMEandTAG(loadConf); + /* cache value, is set only during rsyslogd option processing */ + + +ENDmodInit + +/* vim:set ai: + */ |