#define SMB_CONFIG_DEFAULT_STREAM_DEPTH 0
+#ifdef UNITTESTS
+static void SMBParserRegisterTests(void);
+#endif
+
static uint32_t stream_depth = SMB_CONFIG_DEFAULT_STREAM_DEPTH;
void RegisterRustSMBTCPParsers(void)
SCLogInfo("Parsed disabled for %s protocol. Protocol detection"
"still on.", proto_name);
}
+#ifdef UNITTESTS
+ AppLayerParserRegisterProtocolUnittests(IPPROTO_TCP, ALPROTO_SMB, SMBParserRegisterTests);
+#endif
return;
}
+
+#ifdef UNITTESTS
+#include "stream-tcp.h"
+#include "util-unittest-helper.h"
+
+/** \test multi transactions and cleanup */
+static int SMBParserTxCleanupTest(void)
+{
+ uint64_t ret[4];
+ AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+ FAIL_IF_NULL(alp_tctx);
+
+ StreamTcpInitConfig(TRUE);
+ TcpSession ssn;
+ memset(&ssn, 0, sizeof(ssn));
+
+ Flow *f = UTHBuildFlow(AF_INET, "1.2.3.4", "1.2.3.5", 1024, 445);
+ FAIL_IF_NULL(f);
+ f->protoctx = &ssn;
+ f->proto = IPPROTO_TCP;
+ f->alproto = ALPROTO_SMB;
+
+ char req_str[] ="\x00\x00\x00\x79\xfe\x53\x4d\x42\x40\x00\x01\x00\x00\x00\x00\x00" \
+ "\x05\x00\xe0\x1e\x10\x00\x00\x00\x00\x00\x00\x00\x0b\x00\x00\x00" \
+ "\x00\x00\x00\x00\x00\x00\x00\x00\x10\x72\xd2\x9f\x36\xc2\x08\x14" \
+ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \
+ "\x00\x00\x00\x00\x39\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00" \
+ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x80\x00\x00\x00" \
+ "\x00\x00\x00\x00\x07\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00" \
+ "\x78\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00";
+ req_str[28] = 0x01;
+ int r = AppLayerParserParse(NULL, alp_tctx, f, ALPROTO_SMB,
+ STREAM_TOSERVER | STREAM_START, (uint8_t *)req_str, sizeof(req_str));
+ FAIL_IF_NOT(r == 0);
+ req_str[28]++;
+ r = AppLayerParserParse(NULL, alp_tctx, f, ALPROTO_SMB,
+ STREAM_TOSERVER, (uint8_t *)req_str, sizeof(req_str));
+ FAIL_IF_NOT(r == 0);
+ req_str[28]++;
+ r = AppLayerParserParse(NULL, alp_tctx, f, ALPROTO_SMB,
+ STREAM_TOSERVER, (uint8_t *)req_str, sizeof(req_str));
+ FAIL_IF_NOT(r == 0);
+ req_str[28]++;
+ r = AppLayerParserParse(NULL, alp_tctx, f, ALPROTO_SMB,
+ STREAM_TOSERVER, (uint8_t *)req_str, sizeof(req_str));
+ FAIL_IF_NOT(r == 0);
+ req_str[28]++;
+ r = AppLayerParserParse(NULL, alp_tctx, f, ALPROTO_SMB,
+ STREAM_TOSERVER, (uint8_t *)req_str, sizeof(req_str));
+ FAIL_IF_NOT(r == 0);
+ req_str[28]++;
+ r = AppLayerParserParse(NULL, alp_tctx, f, ALPROTO_SMB,
+ STREAM_TOSERVER, (uint8_t *)req_str, sizeof(req_str));
+ FAIL_IF_NOT(r == 0);
+ req_str[28]++;
+ r = AppLayerParserParse(NULL, alp_tctx, f, ALPROTO_SMB,
+ STREAM_TOSERVER, (uint8_t *)req_str, sizeof(req_str));
+ FAIL_IF_NOT(r == 0);
+ req_str[28]++;
+ r = AppLayerParserParse(NULL, alp_tctx, f, ALPROTO_SMB,
+ STREAM_TOSERVER, (uint8_t *)req_str, sizeof(req_str));
+ FAIL_IF_NOT(r == 0);
+ req_str[28]++;
+
+ AppLayerParserTransactionsCleanup(f);
+ UTHAppLayerParserStateGetIds(f->alparser, &ret[0], &ret[1], &ret[2], &ret[3]);
+ FAIL_IF_NOT(ret[0] == 0); // inspect_id[0]
+ FAIL_IF_NOT(ret[1] == 0); // inspect_id[1]
+ FAIL_IF_NOT(ret[2] == 0); // log_id
+ FAIL_IF_NOT(ret[3] == 0); // min_id
+
+ char resp_str[] = "\x00\x00\x00\x98\xfe\x53\x4d\x42\x40\x00\x01\x00\x00\x00\x00\x00" \
+ "\x05\x00\x21\x00\x11\x00\x00\x00\x00\x00\x00\x00\x0b\x00\x00\x00" \
+ "\x00\x00\x00\x00\x00\x00\x00\x00\x10\x72\xd2\x9f\x36\xc2\x08\x14" \
+ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \
+ "\x00\x00\x00\x00\x59\x00\x00\x00\x01\x00\x00\x00\x48\x38\x40\xb3" \
+ "\x0f\xa8\xd3\x01\x84\x9a\x2b\x46\xf7\xa8\xd3\x01\x48\x38\x40\xb3" \
+ "\x0f\xa8\xd3\x01\x48\x38\x40\xb3\x0f\xa8\xd3\x01\x00\x00\x00\x00" \
+ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x10\x00\x00\x00" \
+ "\x00\x00\x00\x00\x9e\x8f\xb8\x91\x00\x00\x00\x00\x01\x5b\x11\xbb" \
+ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00";
+
+ resp_str[28] = 0x01;
+ r = AppLayerParserParse(NULL, alp_tctx, f, ALPROTO_SMB,
+ STREAM_TOCLIENT | STREAM_START, (uint8_t *)resp_str, sizeof(resp_str));
+ FAIL_IF_NOT(r == 0);
+ resp_str[28] = 0x04;
+ r = AppLayerParserParse(NULL, alp_tctx, f, ALPROTO_SMB,
+ STREAM_TOCLIENT, (uint8_t *)resp_str, sizeof(resp_str));
+ FAIL_IF_NOT(r == 0);
+ resp_str[28] = 0x05;
+ r = AppLayerParserParse(NULL, alp_tctx, f, ALPROTO_SMB,
+ STREAM_TOCLIENT, (uint8_t *)resp_str, sizeof(resp_str));
+ FAIL_IF_NOT(r == 0);
+ resp_str[28] = 0x06;
+ r = AppLayerParserParse(NULL, alp_tctx, f, ALPROTO_SMB,
+ STREAM_TOCLIENT, (uint8_t *)resp_str, sizeof(resp_str));
+ FAIL_IF_NOT(r == 0);
+ resp_str[28] = 0x08;
+ r = AppLayerParserParse(NULL, alp_tctx, f, ALPROTO_SMB,
+ STREAM_TOCLIENT, (uint8_t *)resp_str, sizeof(resp_str));
+ FAIL_IF_NOT(r == 0);
+ resp_str[28] = 0x02;
+ r = AppLayerParserParse(NULL, alp_tctx, f, ALPROTO_SMB,
+ STREAM_TOCLIENT, (uint8_t *)resp_str, sizeof(resp_str));
+ FAIL_IF_NOT(r == 0);
+ resp_str[28] = 0x07;
+ r = AppLayerParserParse(NULL, alp_tctx, f, ALPROTO_SMB,
+ STREAM_TOCLIENT, (uint8_t *)resp_str, sizeof(resp_str));
+ FAIL_IF_NOT(r == 0);
+ AppLayerParserTransactionsCleanup(f);
+
+ UTHAppLayerParserStateGetIds(f->alparser, &ret[0], &ret[1], &ret[2], &ret[3]);
+ FAIL_IF_NOT(ret[0] == 2); // inspect_id[0]
+ FAIL_IF_NOT(ret[1] == 2); // inspect_id[1]
+ FAIL_IF_NOT(ret[2] == 2); // log_id
+ FAIL_IF_NOT(ret[3] == 2); // min_id
+
+ resp_str[28] = 0x03;
+ r = AppLayerParserParse(NULL, alp_tctx, f, ALPROTO_SMB,
+ STREAM_TOCLIENT, (uint8_t *)resp_str, sizeof(resp_str));
+ FAIL_IF_NOT(r == 0);
+ AppLayerParserTransactionsCleanup(f);
+
+ UTHAppLayerParserStateGetIds(f->alparser, &ret[0], &ret[1], &ret[2], &ret[3]);
+ FAIL_IF_NOT(ret[0] == 8); // inspect_id[0]
+ FAIL_IF_NOT(ret[1] == 8); // inspect_id[1]
+ FAIL_IF_NOT(ret[2] == 8); // log_id
+ FAIL_IF_NOT(ret[3] == 8); // min_id
+
+ req_str[28] = 0x09;
+ r = AppLayerParserParse(NULL, alp_tctx, f, ALPROTO_SMB,
+ STREAM_TOSERVER | STREAM_EOF, (uint8_t *)req_str, sizeof(req_str));
+ FAIL_IF_NOT(r == 0);
+ AppLayerParserTransactionsCleanup(f);
+
+ UTHAppLayerParserStateGetIds(f->alparser, &ret[0], &ret[1], &ret[2], &ret[3]);
+ FAIL_IF_NOT(ret[0] == 8); // inspect_id[0] not updated by ..Cleanup() until full tx is done
+ FAIL_IF_NOT(ret[1] == 8); // inspect_id[1]
+ FAIL_IF_NOT(ret[2] == 8); // log_id
+ FAIL_IF_NOT(ret[3] == 8); // min_id
+
+ resp_str[28] = 0x09;
+ r = AppLayerParserParse(NULL, alp_tctx, f, ALPROTO_SMB,
+ STREAM_TOCLIENT | STREAM_EOF, (uint8_t *)resp_str, sizeof(resp_str));
+ FAIL_IF_NOT(r == 0);
+ AppLayerParserTransactionsCleanup(f);
+
+ UTHAppLayerParserStateGetIds(f->alparser, &ret[0], &ret[1], &ret[2], &ret[3]);
+ FAIL_IF_NOT(ret[0] == 9); // inspect_id[0]
+ FAIL_IF_NOT(ret[1] == 9); // inspect_id[1]
+ FAIL_IF_NOT(ret[2] == 9); // log_id
+ FAIL_IF_NOT(ret[3] == 9); // min_id
+
+ AppLayerParserThreadCtxFree(alp_tctx);
+ StreamTcpFreeConfig(TRUE);
+ UTHFreeFlow(f);
+
+ PASS;
+}
+
+static void SMBParserRegisterTests(void)
+{
+ UtRegisterTest("SMBParserTxCleanupTest", SMBParserTxCleanupTest);
+}
+
+#endif /* UNITTESTS */
#endif /* HAVE_RUST */