summaryrefslogtreecommitdiffstats
path: root/contrib/pmpanngfw/pmpanngfw.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/pmpanngfw/pmpanngfw.c')
-rw-r--r--contrib/pmpanngfw/pmpanngfw.c296
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:
+ */