mirror of https://github.com/OISF/suricata
You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
525 lines
19 KiB
C
525 lines
19 KiB
C
/* Copyright (C) 2017 Open Information Security Foundation
|
|
*
|
|
* You can copy, redistribute or modify this Program under the terms of
|
|
* the GNU General Public License version 2 as published by the Free
|
|
* Software Foundation.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* version 2 along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
|
* 02110-1301, USA.
|
|
*/
|
|
|
|
#include "suricata-common.h"
|
|
#include "suricata.h"
|
|
|
|
#include "app-layer-protos.h"
|
|
#include "app-layer-detect-proto.h"
|
|
#include "app-layer-parser.h"
|
|
|
|
#include "util-unittest.h"
|
|
|
|
#include "rust.h"
|
|
#include "app-layer-smb.h"
|
|
#include "rust-smb-smb-gen.h"
|
|
#include "rust-smb-files-gen.h"
|
|
#include "util-misc.h"
|
|
|
|
#define MIN_REC_SIZE 32+4 // SMB hdr + nbss hdr
|
|
|
|
static int SMBTCPParseRequest(Flow *f, void *state,
|
|
AppLayerParserState *pstate, const uint8_t *input, uint32_t input_len,
|
|
void *local_data, const uint8_t flags)
|
|
{
|
|
SCLogDebug("SMBTCPParseRequest");
|
|
uint16_t file_flags = FileFlowToFlags(f, STREAM_TOSERVER);
|
|
rs_smb_setfileflags(0, state, file_flags|FILE_USE_DETECT);
|
|
|
|
int res;
|
|
if (input == NULL && input_len > 0) {
|
|
res = rs_smb_parse_request_tcp_gap(state, input_len);
|
|
} else {
|
|
res = rs_smb_parse_request_tcp(f, state, pstate, input, input_len,
|
|
local_data, flags);
|
|
}
|
|
if (res != 1) {
|
|
SCLogDebug("SMB request%s of %u bytes, retval %d",
|
|
(input == NULL && input_len > 0) ? " is GAP" : "", input_len, res);
|
|
}
|
|
return res;
|
|
}
|
|
|
|
static int SMBTCPParseResponse(Flow *f, void *state,
|
|
AppLayerParserState *pstate, const uint8_t *input, uint32_t input_len,
|
|
void *local_data, const uint8_t flags)
|
|
{
|
|
SCLogDebug("SMBTCPParseResponse");
|
|
uint16_t file_flags = FileFlowToFlags(f, STREAM_TOCLIENT);
|
|
rs_smb_setfileflags(1, state, file_flags|FILE_USE_DETECT);
|
|
|
|
SCLogDebug("SMBTCPParseResponse %p/%u", input, input_len);
|
|
int res;
|
|
if (input == NULL && input_len > 0) {
|
|
res = rs_smb_parse_response_tcp_gap(state, input_len);
|
|
} else {
|
|
res = rs_smb_parse_response_tcp(f, state, pstate, input, input_len,
|
|
local_data, flags);
|
|
}
|
|
if (res != 1) {
|
|
SCLogDebug("SMB response%s of %u bytes, retval %d",
|
|
(input == NULL && input_len > 0) ? " is GAP" : "", input_len, res);
|
|
}
|
|
return res;
|
|
}
|
|
|
|
static uint16_t SMBTCPProbe(Flow *f, uint8_t direction,
|
|
const uint8_t *input, uint32_t len, uint8_t *rdir)
|
|
{
|
|
SCLogDebug("SMBTCPProbe");
|
|
|
|
if (len < MIN_REC_SIZE) {
|
|
return ALPROTO_UNKNOWN;
|
|
}
|
|
|
|
const int r = rs_smb_probe_tcp(direction, input, len, rdir);
|
|
switch (r) {
|
|
case 1:
|
|
return ALPROTO_SMB;
|
|
case 0:
|
|
return ALPROTO_UNKNOWN;
|
|
case -1:
|
|
default:
|
|
return ALPROTO_FAILED;
|
|
}
|
|
}
|
|
|
|
/** \internal
|
|
* \brief as SMB3 records have no direction indicator, fall
|
|
* back to the port numbers for a hint
|
|
*/
|
|
static uint16_t SMB3TCPProbe(Flow *f, uint8_t direction,
|
|
const uint8_t *input, uint32_t len, uint8_t *rdir)
|
|
{
|
|
SCEnter();
|
|
|
|
AppProto p = SMBTCPProbe(f, direction, input, len, rdir);
|
|
if (p != ALPROTO_SMB) {
|
|
SCReturnUInt(p);
|
|
}
|
|
|
|
uint16_t fsp = (f->flags & FLOW_DIR_REVERSED) ? f->dp : f->sp;
|
|
uint16_t fdp = (f->flags & FLOW_DIR_REVERSED) ? f->sp : f->dp;
|
|
SCLogDebug("direction %s flow sp %u dp %u fsp %u fdp %u",
|
|
(direction & STREAM_TOSERVER) ? "toserver" : "toclient",
|
|
f->sp, f->dp, fsp, fdp);
|
|
|
|
if (fsp == 445 && fdp != 445) {
|
|
if (direction & STREAM_TOSERVER) {
|
|
*rdir = STREAM_TOCLIENT;
|
|
} else {
|
|
*rdir = STREAM_TOSERVER;
|
|
}
|
|
}
|
|
SCLogDebug("returning ALPROTO_SMB for dir %s with rdir %s",
|
|
(direction & STREAM_TOSERVER) ? "toserver" : "toclient",
|
|
(*rdir == STREAM_TOSERVER) ? "toserver" : "toclient");
|
|
SCReturnUInt(ALPROTO_SMB);
|
|
}
|
|
|
|
static int SMBGetAlstateProgress(void *tx, uint8_t direction)
|
|
{
|
|
return rs_smb_tx_get_alstate_progress(tx, direction);
|
|
}
|
|
|
|
static uint64_t SMBGetTxCnt(void *alstate)
|
|
{
|
|
return rs_smb_state_get_tx_count(alstate);
|
|
}
|
|
|
|
static void *SMBGetTx(void *alstate, uint64_t tx_id)
|
|
{
|
|
return rs_smb_state_get_tx(alstate, tx_id);
|
|
}
|
|
|
|
static AppLayerGetTxIterTuple SMBGetTxIterator(
|
|
const uint8_t ipproto, const AppProto alproto,
|
|
void *alstate, uint64_t min_tx_id, uint64_t max_tx_id,
|
|
AppLayerGetTxIterState *istate)
|
|
{
|
|
return rs_smb_state_get_tx_iterator(alstate, min_tx_id, (uint64_t *)istate);
|
|
}
|
|
|
|
|
|
static void SMBSetTxLogged(void *alstate, void *tx, uint32_t logger)
|
|
{
|
|
rs_smb_tx_set_logged(alstate, tx, logger);
|
|
}
|
|
|
|
static LoggerId SMBGetTxLogged(void *alstate, void *tx)
|
|
{
|
|
return rs_smb_tx_get_logged(alstate, tx);
|
|
}
|
|
|
|
static void SMBStateTransactionFree(void *state, uint64_t tx_id)
|
|
{
|
|
rs_smb_state_tx_free(state, tx_id);
|
|
}
|
|
|
|
static DetectEngineState *SMBGetTxDetectState(void *tx)
|
|
{
|
|
return rs_smb_state_get_tx_detect_state(tx);
|
|
}
|
|
|
|
static int SMBSetTxDetectState(void *tx, DetectEngineState *s)
|
|
{
|
|
rs_smb_state_set_tx_detect_state(tx, s);
|
|
return 0;
|
|
}
|
|
|
|
static FileContainer *SMBGetFiles(void *state, uint8_t direction)
|
|
{
|
|
return rs_smb_getfiles(direction, state);
|
|
}
|
|
|
|
static AppLayerDecoderEvents *SMBGetEvents(void *tx)
|
|
{
|
|
return rs_smb_state_get_events(tx);
|
|
}
|
|
|
|
static int SMBGetEventInfoById(int event_id, const char **event_name,
|
|
AppLayerEventType *event_type)
|
|
{
|
|
return rs_smb_state_get_event_info_by_id(event_id, event_name, event_type);
|
|
}
|
|
|
|
static int SMBGetEventInfo(const char *event_name, int *event_id,
|
|
AppLayerEventType *event_type)
|
|
{
|
|
return rs_smb_state_get_event_info(event_name, event_id, event_type);
|
|
}
|
|
|
|
static void SMBSetDetectFlags(void *tx, uint8_t dir, uint64_t flags)
|
|
{
|
|
rs_smb_tx_set_detect_flags(tx, dir, flags);
|
|
}
|
|
|
|
static uint64_t SMBGetDetectFlags(void *tx, uint8_t dir)
|
|
{
|
|
return rs_smb_tx_get_detect_flags(tx, dir);
|
|
}
|
|
|
|
static void SMBStateTruncate(void *state, uint8_t direction)
|
|
{
|
|
return rs_smb_state_truncate(state, direction);
|
|
}
|
|
|
|
static int SMBRegisterPatternsForProtocolDetection(void)
|
|
{
|
|
int r = 0;
|
|
/* SMB1 */
|
|
r |= AppLayerProtoDetectPMRegisterPatternCSwPP(IPPROTO_TCP, ALPROTO_SMB,
|
|
"|ff|SMB", 8, 4, STREAM_TOSERVER, SMBTCPProbe,
|
|
MIN_REC_SIZE, MIN_REC_SIZE);
|
|
r |= AppLayerProtoDetectPMRegisterPatternCSwPP(IPPROTO_TCP, ALPROTO_SMB,
|
|
"|ff|SMB", 8, 4, STREAM_TOCLIENT, SMBTCPProbe,
|
|
MIN_REC_SIZE, MIN_REC_SIZE);
|
|
|
|
/* SMB2/3 */
|
|
r |= AppLayerProtoDetectPMRegisterPatternCSwPP(IPPROTO_TCP, ALPROTO_SMB,
|
|
"|fe|SMB", 8, 4, STREAM_TOSERVER, SMBTCPProbe,
|
|
MIN_REC_SIZE, MIN_REC_SIZE);
|
|
r |= AppLayerProtoDetectPMRegisterPatternCSwPP(IPPROTO_TCP, ALPROTO_SMB,
|
|
"|fe|SMB", 8, 4, STREAM_TOCLIENT, SMBTCPProbe,
|
|
MIN_REC_SIZE, MIN_REC_SIZE);
|
|
|
|
/* SMB3 encrypted records */
|
|
r |= AppLayerProtoDetectPMRegisterPatternCSwPP(IPPROTO_TCP, ALPROTO_SMB,
|
|
"|fd|SMB", 8, 4, STREAM_TOSERVER, SMB3TCPProbe,
|
|
MIN_REC_SIZE, MIN_REC_SIZE);
|
|
r |= AppLayerProtoDetectPMRegisterPatternCSwPP(IPPROTO_TCP, ALPROTO_SMB,
|
|
"|fd|SMB", 8, 4, STREAM_TOCLIENT, SMB3TCPProbe,
|
|
MIN_REC_SIZE, MIN_REC_SIZE);
|
|
return r == 0 ? 0 : -1;
|
|
}
|
|
|
|
static StreamingBufferConfig sbcfg = STREAMING_BUFFER_CONFIG_INITIALIZER;
|
|
static SuricataFileContext sfc = { &sbcfg };
|
|
|
|
#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 RegisterSMBParsers(void)
|
|
{
|
|
const char *proto_name = "smb";
|
|
|
|
/** SMB */
|
|
if (AppLayerProtoDetectConfProtoDetectionEnabled("tcp", proto_name)) {
|
|
AppLayerProtoDetectRegisterProtocol(ALPROTO_SMB, proto_name);
|
|
if (SMBRegisterPatternsForProtocolDetection() < 0)
|
|
return;
|
|
|
|
rs_smb_init(&sfc);
|
|
|
|
if (RunmodeIsUnittests()) {
|
|
AppLayerProtoDetectPPRegister(IPPROTO_TCP, "445", ALPROTO_SMB, 0,
|
|
MIN_REC_SIZE, STREAM_TOSERVER, SMBTCPProbe,
|
|
SMBTCPProbe);
|
|
} else {
|
|
int have_cfg = AppLayerProtoDetectPPParseConfPorts("tcp",
|
|
IPPROTO_TCP, proto_name, ALPROTO_SMB, 0,
|
|
MIN_REC_SIZE, SMBTCPProbe, SMBTCPProbe);
|
|
/* if we have no config, we enable the default port 445 */
|
|
if (!have_cfg) {
|
|
SCLogWarning(SC_ERR_SMB_CONFIG, "no SMB TCP config found, "
|
|
"enabling SMB detection on "
|
|
"port 445.");
|
|
AppLayerProtoDetectPPRegister(IPPROTO_TCP, "445", ALPROTO_SMB, 0,
|
|
MIN_REC_SIZE, STREAM_TOSERVER, SMBTCPProbe,
|
|
SMBTCPProbe);
|
|
}
|
|
}
|
|
} else {
|
|
SCLogInfo("Protocol detection and parser disabled for %s protocol.",
|
|
proto_name);
|
|
return;
|
|
}
|
|
|
|
if (AppLayerParserConfParserEnabled("tcp", proto_name)) {
|
|
AppLayerParserRegisterParser(IPPROTO_TCP, ALPROTO_SMB, STREAM_TOSERVER,
|
|
SMBTCPParseRequest);
|
|
AppLayerParserRegisterParser(IPPROTO_TCP , ALPROTO_SMB, STREAM_TOCLIENT,
|
|
SMBTCPParseResponse);
|
|
AppLayerParserRegisterStateFuncs(IPPROTO_TCP, ALPROTO_SMB,
|
|
rs_smb_state_new, rs_smb_state_free);
|
|
AppLayerParserRegisterTxFreeFunc(IPPROTO_TCP, ALPROTO_SMB,
|
|
SMBStateTransactionFree);
|
|
|
|
AppLayerParserRegisterGetEventsFunc(IPPROTO_TCP, ALPROTO_SMB,
|
|
SMBGetEvents);
|
|
AppLayerParserRegisterGetEventInfo(IPPROTO_TCP, ALPROTO_SMB,
|
|
SMBGetEventInfo);
|
|
AppLayerParserRegisterGetEventInfoById(IPPROTO_TCP, ALPROTO_SMB,
|
|
SMBGetEventInfoById);
|
|
|
|
AppLayerParserRegisterDetectStateFuncs(IPPROTO_TCP, ALPROTO_SMB,
|
|
SMBGetTxDetectState, SMBSetTxDetectState);
|
|
AppLayerParserRegisterGetTx(IPPROTO_TCP, ALPROTO_SMB, SMBGetTx);
|
|
AppLayerParserRegisterGetTxIterator(IPPROTO_TCP, ALPROTO_SMB, SMBGetTxIterator);
|
|
AppLayerParserRegisterGetTxCnt(IPPROTO_TCP, ALPROTO_SMB,
|
|
SMBGetTxCnt);
|
|
AppLayerParserRegisterLoggerFuncs(IPPROTO_TCP, ALPROTO_SMB,
|
|
SMBGetTxLogged, SMBSetTxLogged);
|
|
AppLayerParserRegisterGetStateProgressFunc(IPPROTO_TCP, ALPROTO_SMB,
|
|
SMBGetAlstateProgress);
|
|
AppLayerParserRegisterGetStateProgressCompletionStatus(ALPROTO_SMB,
|
|
rs_smb_state_progress_completion_status);
|
|
AppLayerParserRegisterDetectFlagsFuncs(IPPROTO_TCP, ALPROTO_SMB,
|
|
SMBGetDetectFlags, SMBSetDetectFlags);
|
|
AppLayerParserRegisterTruncateFunc(IPPROTO_TCP, ALPROTO_SMB,
|
|
SMBStateTruncate);
|
|
AppLayerParserRegisterGetFilesFunc(IPPROTO_TCP, ALPROTO_SMB, SMBGetFiles);
|
|
|
|
/* This parser accepts gaps. */
|
|
AppLayerParserRegisterOptionFlags(IPPROTO_TCP, ALPROTO_SMB,
|
|
APP_LAYER_PARSER_OPT_ACCEPT_GAPS);
|
|
|
|
ConfNode *p = ConfGetNode("app-layer.protocols.smb.stream-depth");
|
|
if (p != NULL) {
|
|
uint32_t value;
|
|
if (ParseSizeStringU32(p->val, &value) < 0) {
|
|
SCLogError(SC_ERR_SMB_CONFIG, "invalid value for stream-depth %s", p->val);
|
|
} else {
|
|
stream_depth = value;
|
|
}
|
|
}
|
|
SCLogConfig("SMB stream depth: %u", stream_depth);
|
|
|
|
AppLayerParserSetStreamDepth(IPPROTO_TCP, ALPROTO_SMB, stream_depth);
|
|
} else {
|
|
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 */
|