From 0d7159b525f36dd77c68fee22d6c6ef363e084cd Mon Sep 17 00:00:00 2001 From: Anoop Saldanha Date: Sun, 4 Aug 2013 12:08:59 +0530 Subject: [PATCH] App layer protocol detection updated and improved. We now use confirmation from both directions and set events if there's a mismatch between the 2 directions. FPs from corrupt flows have disappeared with this. --- src/app-layer-dcerpc-udp.c | 3 +- src/app-layer-dcerpc.c | 5 +- src/app-layer-detect-proto.c | 13 +- src/app-layer-ftp.c | 3 +- src/app-layer-htp.c | 8 +- src/app-layer-parser.c | 19 +- src/app-layer-parser.h | 17 +- src/app-layer-smb.c | 4 +- src/app-layer-smb2.c | 2 +- src/app-layer-smtp.c | 115 +- src/app-layer-ssh.c | 3 +- src/app-layer-ssl.c | 13 +- src/app-layer.c | 2977 +++++++++++++++++++++++++++++++++- src/app-layer.h | 5 +- src/flow-util.h | 8 + src/flow.h | 4 + src/runmode-unittests.c | 2 + src/stream-tcp-private.h | 2 + src/stream-tcp-reassemble.c | 1044 +++++++----- src/stream-tcp-reassemble.h | 3 + src/stream-tcp.c | 4 +- src/stream-tcp.h | 6 + 22 files changed, 3718 insertions(+), 542 deletions(-) diff --git a/src/app-layer-dcerpc-udp.c b/src/app-layer-dcerpc-udp.c index 68b343da20..53a2cbf442 100644 --- a/src/app-layer-dcerpc-udp.c +++ b/src/app-layer-dcerpc-udp.c @@ -722,6 +722,7 @@ void RegisterDCERPCUDPParsers(void) { if (AppLayerProtoDetectionEnabled("dcerpc")) { AlpProtoAdd(&alp_proto_ctx, proto_name, IPPROTO_UDP, ALPROTO_DCERPC_UDP, "|04 00|", 2, 0, STREAM_TOSERVER); + AppLayerRegisterParserAcceptableDataDirection(ALPROTO_DCERPC_UDP, STREAM_TOSERVER); } else { SCLogInfo("Protocol detection and parser disabled for %s protocol.", "dcerpc"); @@ -740,7 +741,7 @@ void RegisterDCERPCUDPParsers(void) { "still on.", "dcerpc"); } #ifdef UNITTESTS - AppLayerRegisterUnittests(ALPROTO_DCERPC_UDP, DCERPCUDPParserRegisterTests); + AppLayerParserRegisterUnittests(ALPROTO_DCERPC_UDP, DCERPCUDPParserRegisterTests); #endif return; diff --git a/src/app-layer-dcerpc.c b/src/app-layer-dcerpc.c index 37a12f61e1..c9bb211218 100644 --- a/src/app-layer-dcerpc.c +++ b/src/app-layer-dcerpc.c @@ -1871,6 +1871,9 @@ void RegisterDCERPCParsers(void) { if (AppLayerProtoDetectionEnabled(proto_name)) { AlpProtoAdd(&alp_proto_ctx, proto_name, IPPROTO_TCP, ALPROTO_DCERPC, "|05 00|", 2, 0, STREAM_TOSERVER); + /* toclient direction */ + AlpProtoAdd(&alp_proto_ctx, proto_name, IPPROTO_TCP, ALPROTO_DCERPC, "|05 00|", 2, 0, STREAM_TOCLIENT); + AppLayerRegisterParserAcceptableDataDirection(ALPROTO_DCERPC, STREAM_TOSERVER); } else { SCLogInfo("Protocol detection and parser disabled for %s protocol.", proto_name); @@ -1889,7 +1892,7 @@ void RegisterDCERPCParsers(void) { "still on.", proto_name); } #ifdef UNITTESTS - AppLayerRegisterUnittests(ALPROTO_DCERPC, DCERPCParserRegisterTests); + AppLayerParserRegisterUnittests(ALPROTO_DCERPC, DCERPCParserRegisterTests); #endif return; diff --git a/src/app-layer-detect-proto.c b/src/app-layer-detect-proto.c index 1cff7053c0..7e911ccaf8 100644 --- a/src/app-layer-detect-proto.c +++ b/src/app-layer-detect-proto.c @@ -573,8 +573,17 @@ uint16_t AppLayerDetectGetProto(AlpProtoDetectCtx *ctx, { if (!FLOW_IS_PM_DONE(f, flags)) { uint16_t pm_results[ALPROTO_MAX]; - if (AppLayerDetectGetProtoPMParser(ctx, tctx, f, buf, buflen, flags, ipproto, pm_results) != 0) { - return pm_results[0]; + uint16_t pm_matches = AppLayerDetectGetProtoPMParser(ctx, tctx, f, buf, buflen, flags, ipproto, pm_results); + uint8_t dir = (flags & STREAM_TOSERVER) ? 0 : 1; + for (uint16_t i = 0; i < pm_matches; i++) { + if (al_proto_table[pm_results[i]].pp_alproto_map[dir] != NULL) { + if (pm_results[i] != al_proto_table[pm_results[i]].pp_alproto_map[dir](buf, buflen, NULL)) { + /* \todo set event */ + continue; + } + } + + return pm_results[i]; } } if (!FLOW_IS_PP_DONE(f, flags)) diff --git a/src/app-layer-ftp.c b/src/app-layer-ftp.c index 6930a9c4f8..7cb19ff6ec 100644 --- a/src/app-layer-ftp.c +++ b/src/app-layer-ftp.c @@ -270,6 +270,7 @@ void RegisterFTPParsers(void) { AlpProtoAdd(&alp_proto_ctx, proto_name, IPPROTO_TCP, ALPROTO_FTP, "USER ", 5, 0, STREAM_TOSERVER); AlpProtoAdd(&alp_proto_ctx, proto_name, IPPROTO_TCP, ALPROTO_FTP, "PASS ", 5, 0, STREAM_TOSERVER); AlpProtoAdd(&alp_proto_ctx, proto_name, IPPROTO_TCP, ALPROTO_FTP, "PORT ", 5, 0, STREAM_TOSERVER); + AppLayerRegisterParserAcceptableDataDirection(ALPROTO_FTP, STREAM_TOSERVER | STREAM_TOCLIENT); } if (AppLayerParserEnabled(proto_name)) { @@ -286,7 +287,7 @@ void RegisterFTPParsers(void) { "still on.", proto_name); } #ifdef UNITTESTS - AppLayerRegisterUnittests(ALPROTO_FTP, FTPParserRegisterTests); + AppLayerParserRegisterUnittests(ALPROTO_FTP, FTPParserRegisterTests); #endif } diff --git a/src/app-layer-htp.c b/src/app-layer-htp.c index 2fb6987fcd..d556893dfd 100644 --- a/src/app-layer-htp.c +++ b/src/app-layer-htp.c @@ -2420,6 +2420,12 @@ void RegisterHTPParsers(void) AlpProtoAdd(&alp_proto_ctx, proto_name, IPPROTO_TCP, ALPROTO_HTTP, "OPTIONS|09|", 8, 0, STREAM_TOSERVER); AlpProtoAdd(&alp_proto_ctx, proto_name, IPPROTO_TCP, ALPROTO_HTTP, "CONNECT|20|", 8, 0, STREAM_TOSERVER); AlpProtoAdd(&alp_proto_ctx, proto_name, IPPROTO_TCP, ALPROTO_HTTP, "CONNECT|09|", 8, 0, STREAM_TOSERVER); + + /* toclient direction */ + AlpProtoAdd(&alp_proto_ctx, proto_name, IPPROTO_TCP, ALPROTO_HTTP, "HTTP/0.9", 8, 0, STREAM_TOCLIENT); + AlpProtoAdd(&alp_proto_ctx, proto_name, IPPROTO_TCP, ALPROTO_HTTP, "HTTP/1.0", 8, 0, STREAM_TOCLIENT); + AlpProtoAdd(&alp_proto_ctx, proto_name, IPPROTO_TCP, ALPROTO_HTTP, "HTTP/1.1", 8, 0, STREAM_TOCLIENT); + AppLayerRegisterParserAcceptableDataDirection(ALPROTO_HTTP, STREAM_TOSERVER); } else { SCLogInfo("Protocol detection and parser disabled for %s protocol", proto_name); @@ -2451,7 +2457,7 @@ void RegisterHTPParsers(void) "still on.", proto_name); } #ifdef UNITTESTS - AppLayerRegisterUnittests(ALPROTO_HTTP, HTPParserRegisterTests); + AppLayerParserRegisterUnittests(ALPROTO_HTTP, HTPParserRegisterTests); #endif SCReturn; diff --git a/src/app-layer-parser.c b/src/app-layer-parser.c index 12c5e774fd..fe9b3a40af 100644 --- a/src/app-layer-parser.c +++ b/src/app-layer-parser.c @@ -758,7 +758,7 @@ int AppLayerRegisterProto(char *name, uint8_t proto, uint8_t flags, } #ifdef UNITTESTS -void AppLayerRegisterUnittests(uint16_t proto, void (*RegisterUnittests)(void)) { +void AppLayerParserRegisterUnittests(uint16_t proto, void (*RegisterUnittests)(void)) { al_proto_table[proto].RegisterUnittests = RegisterUnittests; } #endif @@ -2240,6 +2240,23 @@ static inline void AppLayerInsertNewProbingParser(AppLayerProbingParser **pp, return; } +void AppLayerRegisterParserAcceptableDataDirection(uint16_t al_proto, + uint8_t flags) +{ + al_proto_table[al_proto].flags |= (flags & (STREAM_TOSERVER | STREAM_TOCLIENT)); + + return; +} + +void AppLayerMapProbingParserAgainstAlproto(uint16_t al_proto, + uint8_t flags, + ProbingParserFPtr ProbingParser) +{ + al_proto_table[al_proto].pp_alproto_map[(flags & STREAM_TOSERVER) ? 0 : 1] = ProbingParser; + + return; +} + void AppLayerRegisterProbingParser(AlpProtoDetectCtx *ctx, uint16_t ip_proto, char *portstr, diff --git a/src/app-layer-parser.h b/src/app-layer-parser.h index a2dccfefa3..ba016e9498 100644 --- a/src/app-layer-parser.h +++ b/src/app-layer-parser.h @@ -34,6 +34,9 @@ typedef struct AppLayerLocalMap_ { uint16_t parser_id; } AppLayerLocalMap; +typedef uint16_t (*ProbingParserFPtr)(uint8_t *input, uint32_t input_len, + uint32_t *offset); + /** \brief Mapping between ALPROTO_* and L7Parsers * * Map the proto to the parsers for the to_client and to_server directions. @@ -66,6 +69,10 @@ typedef struct AppLayerProto_ { void *(*StateGetTx)(void *alstate, uint64_t tx_id); int (*StateGetAlstateProgressCompletionStatus)(uint8_t direction); + ProbingParserFPtr pp_alproto_map[2]; + /* The current values taken are STREAM_TOSERVER, STREAM_TOCLIENT */ + uint8_t flags; + #ifdef UNITTESTS void (*RegisterUnittests)(void); #endif @@ -138,9 +145,6 @@ typedef struct AppLayerParserStateStore_ { AppLayerDecoderEvents *decoder_events; } AppLayerParserStateStore; -typedef uint16_t (*ProbingParserFPtr)(uint8_t *input, uint32_t input_len, - uint32_t *offset); - typedef struct AppLayerParserTableElement_ { int (*AppLayerParser)(Flow *f, void *protocol_state, AppLayerParserState *parser_state, uint8_t *input, uint32_t input_len, @@ -242,6 +246,11 @@ int AppLayerRegisterParser(char *name, uint16_t proto, uint16_t parser_id, void *local_data, AppLayerParserResult *output), char *dependency); +void AppLayerRegisterParserAcceptableDataDirection(uint16_t al_proto, + uint8_t flags); +void AppLayerMapProbingParserAgainstAlproto(uint16_t al_proto, + uint8_t flags, + ProbingParserFPtr ProbingParser); void AppLayerRegisterProbingParser(struct AlpProtoDetectCtx_ *, uint16_t ip_proto, char *portstr, @@ -250,7 +259,7 @@ void AppLayerRegisterProbingParser(struct AlpProtoDetectCtx_ *, uint8_t flags, ProbingParserFPtr ProbingParser); #ifdef UNITTESTS -void AppLayerRegisterUnittests(uint16_t proto, void (*RegisterUnittests)(void)); +void AppLayerParserRegisterUnittests(uint16_t proto, void (*RegisterUnittests)(void)); #endif void AppLayerRegisterStateFuncs(uint16_t proto, void *(*StateAlloc)(void), void (*StateFree)(void *)); diff --git a/src/app-layer-smb.c b/src/app-layer-smb.c index 7b9989ab7c..fa4740d8dd 100644 --- a/src/app-layer-smb.c +++ b/src/app-layer-smb.c @@ -1420,6 +1420,8 @@ void RegisterSMBParsers(void) { SMB_PROBING_PARSER_MIN_DEPTH, 0, SMBProbingParser); } + + AppLayerRegisterParserAcceptableDataDirection(ALPROTO_SMB, STREAM_TOSERVER); } else { SCLogInfo("Protocol detection and parser disabled for %s protocol.", proto_name); @@ -1436,7 +1438,7 @@ void RegisterSMBParsers(void) { } #ifdef UNITTESTS - AppLayerRegisterUnittests(ALPROTO_SMB, SMBParserRegisterTests); + AppLayerParserRegisterUnittests(ALPROTO_SMB, SMBParserRegisterTests); #endif return; } diff --git a/src/app-layer-smb2.c b/src/app-layer-smb2.c index 1b303bfd49..81f5f5c5e7 100644 --- a/src/app-layer-smb2.c +++ b/src/app-layer-smb2.c @@ -531,7 +531,7 @@ void RegisterSMB2Parsers(void) { } #ifdef UNITTESTS - AppLayerRegisterUnittests(ALPROTO_SMB2, SMB2ParserRegisterTests); + AppLayerParserRegisterUnittests(ALPROTO_SMB2, SMB2ParserRegisterTests); #endif return; } diff --git a/src/app-layer-smtp.c b/src/app-layer-smtp.c index 6d54bfca23..81ac8ee051 100644 --- a/src/app-layer-smtp.c +++ b/src/app-layer-smtp.c @@ -532,26 +532,16 @@ static int SMTPProcessReply(SMTPState *state, Flow *f, reply_code = smtp_reply_map[pmq->pattern_id_array[0]].enum_value; if (state->cmds_idx == state->cmds_cnt) { - /* decoder event - unable to match reply with request */ - SCLogDebug("unable to match reply with request"); - SCReturnInt(-1); - } - - /* kinda hack needed for us. Our parser logs commands, to be - * matched against server replies. SMTP is normally accompanied by a - * toclient welcome message, which would have had no command to - * accompany it with. And also alproto detection sees to it that the - * toserver stream is the first one to be processed by the app layer. - * Hence check the first reply and if it is a welcome message(220), - * leave without matching it against any buffered command */ - if (!(state->parser_state & SMTP_PARSER_STATE_FIRST_REPLY_SEEN)) { - state->parser_state |= SMTP_PARSER_STATE_FIRST_REPLY_SEEN; - if (reply_code == SMTP_REPLY_220) { - return 0; + if (!(state->parser_state & SMTP_PARSER_STATE_FIRST_REPLY_SEEN)) { + state->parser_state |= SMTP_PARSER_STATE_FIRST_REPLY_SEEN; + if (reply_code == SMTP_REPLY_220) + SCReturnInt(0); + else + AppLayerDecoderEventsSetEvent(f, SMTP_DECODER_EVENT_INVALID_REPLY); } else { - /* set decoder event - first reply from server not a welcome message */ - AppLayerDecoderEventsSetEvent(f, - SMTP_DECODER_EVENT_NO_SERVER_WELCOME_MESSAGE); + /* decoder event - unable to match reply with request */ + SCLogDebug("unable to match reply with request"); + SCReturnInt(-1); } } @@ -633,6 +623,10 @@ static int SMTPProcessRequest(SMTPState *state, Flow *f, { SCEnter(); + if (!(state->parser_state & SMTP_PARSER_STATE_FIRST_REPLY_SEEN)) { + AppLayerDecoderEventsSetEvent(f, SMTP_DECODER_EVENT_NO_SERVER_WELCOME_MESSAGE); + } + /* there are 2 commands that can push it into this COMMAND_DATA mode - * STARTTLS and DATA */ if (!(state->parser_state & SMTP_PARSER_STATE_COMMAND_DATA_MODE)) { @@ -852,6 +846,9 @@ void RegisterSMTPParsers(void) STREAM_TOSERVER); AlpProtoAdd(&alp_proto_ctx, proto_name, IPPROTO_TCP, ALPROTO_SMTP, "HELO", 4, 0, STREAM_TOSERVER); + AlpProtoAdd(&alp_proto_ctx, proto_name, IPPROTO_TCP, ALPROTO_SMTP, "QUIT", 4, 0, + STREAM_TOSERVER); + AppLayerRegisterParserAcceptableDataDirection(ALPROTO_SMTP, STREAM_TOCLIENT); } else { SCLogInfo("Protocol detection and parser disabled for %s protocol.", proto_name); @@ -877,7 +874,7 @@ void RegisterSMTPParsers(void) SMTPSetMpmState(); #ifdef UNITTESTS - AppLayerRegisterUnittests(ALPROTO_SMTP, SMTPParserRegisterTests); + AppLayerParserRegisterUnittests(ALPROTO_SMTP, SMTPParserRegisterTests); #endif return; } @@ -966,8 +963,8 @@ int SMTPParserTest01(void) void *thread_local_data = SMTPLocalStorageAlloc(); SCMutexLock(&f.m); - r = AppLayerParse(thread_local_data, &f, ALPROTO_SMTP, STREAM_TOSERVER, - request1, request1_len); + r = AppLayerParse(thread_local_data, &f, ALPROTO_SMTP, STREAM_TOCLIENT, + welcome_reply, welcome_reply_len); if (r != 0) { printf("smtp check returned %" PRId32 ", expected 0: ", r); SCMutexUnlock(&f.m); @@ -980,17 +977,16 @@ int SMTPParserTest01(void) goto end; } if (smtp_state->input_len != 0 || - smtp_state->cmds_cnt != 1 || + smtp_state->cmds_cnt != 0 || smtp_state->cmds_idx != 0 || - smtp_state->cmds[0] != SMTP_COMMAND_OTHER_CMD || - smtp_state->parser_state != 0) { + smtp_state->parser_state != SMTP_PARSER_STATE_FIRST_REPLY_SEEN) { printf("smtp parser in inconsistent state\n"); goto end; } SCMutexLock(&f.m); - r = AppLayerParse(thread_local_data, &f, ALPROTO_SMTP, STREAM_TOCLIENT, - welcome_reply, welcome_reply_len); + r = AppLayerParse(thread_local_data, &f, ALPROTO_SMTP, STREAM_TOSERVER, + request1, request1_len); if (r != 0) { printf("smtp check returned %" PRId32 ", expected 0: ", r); SCMutexUnlock(&f.m); @@ -1323,8 +1319,8 @@ int SMTPParserTest02(void) void *thread_local_data = SMTPLocalStorageAlloc(); SCMutexLock(&f.m); - r = AppLayerParse(thread_local_data, &f, ALPROTO_SMTP, STREAM_TOSERVER, - request1, request1_len); + r = AppLayerParse(thread_local_data, &f, ALPROTO_SMTP, STREAM_TOCLIENT, + welcome_reply, welcome_reply_len); if (r != 0) { printf("smtp check returned %" PRId32 ", expected 0: ", r); SCMutexUnlock(&f.m); @@ -1337,17 +1333,16 @@ int SMTPParserTest02(void) goto end; } if (smtp_state->input_len != 0 || - smtp_state->cmds_cnt != 1 || + smtp_state->cmds_cnt != 0 || smtp_state->cmds_idx != 0 || - smtp_state->cmds[0] != SMTP_COMMAND_OTHER_CMD || - smtp_state->parser_state != 0) { + smtp_state->parser_state != SMTP_PARSER_STATE_FIRST_REPLY_SEEN) { printf("smtp parser in inconsistent state\n"); goto end; } SCMutexLock(&f.m); - r = AppLayerParse(thread_local_data, &f, ALPROTO_SMTP, STREAM_TOCLIENT, - welcome_reply, welcome_reply_len); + r = AppLayerParse(thread_local_data, &f, ALPROTO_SMTP, STREAM_TOSERVER, + request1, request1_len); if (r != 0) { printf("smtp check returned %" PRId32 ", expected 0: ", r); SCMutexUnlock(&f.m); @@ -1956,8 +1951,8 @@ int SMTPParserTest03(void) void *thread_local_data = SMTPLocalStorageAlloc(); SCMutexLock(&f.m); - r = AppLayerParse(thread_local_data, &f, ALPROTO_SMTP, STREAM_TOSERVER, - request1, request1_len); + r = AppLayerParse(thread_local_data, &f, ALPROTO_SMTP, STREAM_TOCLIENT, + welcome_reply, welcome_reply_len); if (r != 0) { printf("smtp check returned %" PRId32 ", expected 0: ", r); SCMutexUnlock(&f.m); @@ -1970,17 +1965,16 @@ int SMTPParserTest03(void) goto end; } if (smtp_state->input_len != 0 || - smtp_state->cmds_cnt != 1 || + smtp_state->cmds_cnt != 0 || smtp_state->cmds_idx != 0 || - smtp_state->cmds[0] != SMTP_COMMAND_OTHER_CMD || - smtp_state->parser_state != 0) { + smtp_state->parser_state != SMTP_PARSER_STATE_FIRST_REPLY_SEEN) { printf("smtp parser in inconsistent state\n"); goto end; } SCMutexLock(&f.m); - r = AppLayerParse(thread_local_data, &f, ALPROTO_SMTP, STREAM_TOCLIENT, - welcome_reply, welcome_reply_len); + r = AppLayerParse(thread_local_data, &f, ALPROTO_SMTP, STREAM_TOSERVER, + request1, request1_len); if (r != 0) { printf("smtp check returned %" PRId32 ", expected 0: ", r); SCMutexUnlock(&f.m); @@ -2102,8 +2096,8 @@ int SMTPParserTest04(void) void *thread_local_data = SMTPLocalStorageAlloc(); SCMutexLock(&f.m); - r = AppLayerParse(thread_local_data, &f, ALPROTO_SMTP, STREAM_TOSERVER, - request1, request1_len); + r = AppLayerParse(thread_local_data, &f, ALPROTO_SMTP, STREAM_TOCLIENT, + welcome_reply, welcome_reply_len); if (r != 0) { printf("smtp check returned %" PRId32 ", expected 0: ", r); SCMutexUnlock(&f.m); @@ -2116,17 +2110,16 @@ int SMTPParserTest04(void) goto end; } if (smtp_state->input_len != 0 || - smtp_state->cmds_cnt != 1 || + smtp_state->cmds_cnt != 0 || smtp_state->cmds_idx != 0 || - smtp_state->cmds[0] != SMTP_COMMAND_OTHER_CMD || - smtp_state->parser_state != 0) { + smtp_state->parser_state != SMTP_PARSER_STATE_FIRST_REPLY_SEEN) { printf("smtp parser in inconsistent state\n"); goto end; } SCMutexLock(&f.m); - r = AppLayerParse(thread_local_data, &f, ALPROTO_SMTP, STREAM_TOCLIENT, - welcome_reply, welcome_reply_len); + r = AppLayerParse(thread_local_data, &f, ALPROTO_SMTP, STREAM_TOSERVER, + request1, request1_len); if (r != 0) { printf("smtp check returned %" PRId32 ", expected 0: ", r); SCMutexUnlock(&f.m); @@ -2248,8 +2241,8 @@ int SMTPParserTest05(void) void *thread_local_data = SMTPLocalStorageAlloc(); SCMutexLock(&f.m); - r = AppLayerParse(thread_local_data, &f, ALPROTO_SMTP, STREAM_TOSERVER, - request1, request1_len); + r = AppLayerParse(thread_local_data, &f, ALPROTO_SMTP, STREAM_TOCLIENT, + welcome_reply, welcome_reply_len); if (r != 0) { printf("smtp check returned %" PRId32 ", expected 0: ", r); SCMutexUnlock(&f.m); @@ -2262,17 +2255,16 @@ int SMTPParserTest05(void) goto end; } if (smtp_state->input_len != 0 || - smtp_state->cmds_cnt != 1 || + smtp_state->cmds_cnt != 0 || smtp_state->cmds_idx != 0 || - smtp_state->cmds[0] != SMTP_COMMAND_OTHER_CMD || - smtp_state->parser_state != 0) { + smtp_state->parser_state != SMTP_PARSER_STATE_FIRST_REPLY_SEEN) { printf("smtp parser in inconsistent state\n"); goto end; } SCMutexLock(&f.m); - r = AppLayerParse(thread_local_data, &f, ALPROTO_SMTP, STREAM_TOCLIENT, - welcome_reply, welcome_reply_len); + r = AppLayerParse(thread_local_data, &f, ALPROTO_SMTP, STREAM_TOSERVER, + request1, request1_len); if (r != 0) { printf("smtp check returned %" PRId32 ", expected 0: ", r); SCMutexUnlock(&f.m); @@ -2543,8 +2535,8 @@ int SMTPParserTest06(void) void *thread_local_data = SMTPLocalStorageAlloc(); SCMutexLock(&f.m); - r = AppLayerParse(thread_local_data, &f, ALPROTO_SMTP, STREAM_TOSERVER, - request1, request1_len); + r = AppLayerParse(thread_local_data, &f, ALPROTO_SMTP, STREAM_TOCLIENT, + welcome_reply, welcome_reply_len); if (r != 0) { printf("smtp check returned %" PRId32 ", expected 0: ", r); SCMutexUnlock(&f.m); @@ -2557,17 +2549,16 @@ int SMTPParserTest06(void) goto end; } if (smtp_state->input_len != 0 || - smtp_state->cmds_cnt != 1 || + smtp_state->cmds_cnt != 0 || smtp_state->cmds_idx != 0 || - smtp_state->cmds[0] != SMTP_COMMAND_OTHER_CMD || - smtp_state->parser_state != 0) { + smtp_state->parser_state != SMTP_PARSER_STATE_FIRST_REPLY_SEEN) { printf("smtp parser in inconsistent state\n"); goto end; } SCMutexLock(&f.m); - r = AppLayerParse(thread_local_data, &f, ALPROTO_SMTP, STREAM_TOCLIENT, - welcome_reply, welcome_reply_len); + r = AppLayerParse(thread_local_data, &f, ALPROTO_SMTP, STREAM_TOSERVER, + request1, request1_len); if (r != 0) { printf("smtp check returned %" PRId32 ", expected 0: ", r); SCMutexUnlock(&f.m); diff --git a/src/app-layer-ssh.c b/src/app-layer-ssh.c index 700b280fac..c915af5adf 100644 --- a/src/app-layer-ssh.c +++ b/src/app-layer-ssh.c @@ -741,6 +741,7 @@ void RegisterSSHParsers(void) /** SSH */ if (AppLayerProtoDetectionEnabled(proto_name)) { AlpProtoAdd(&alp_proto_ctx, proto_name, IPPROTO_TCP, ALPROTO_SSH, "SSH-", 4, 0, STREAM_TOSERVER); + AppLayerRegisterParserAcceptableDataDirection(ALPROTO_SSH, STREAM_TOSERVER | STREAM_TOCLIENT); } else { SCLogInfo("Protocol detection and parser disabled for %s protocol.", proto_name); @@ -759,7 +760,7 @@ void RegisterSSHParsers(void) } #ifdef UNITTESTS - AppLayerRegisterUnittests(ALPROTO_SSH, SSHParserRegisterTests); + AppLayerParserRegisterUnittests(ALPROTO_SSH, SSHParserRegisterTests); #endif } diff --git a/src/app-layer-ssl.c b/src/app-layer-ssl.c index 0a782611f2..cd1a1bdfcd 100644 --- a/src/app-layer-ssl.c +++ b/src/app-layer-ssl.c @@ -1016,6 +1016,15 @@ void RegisterSSLParsers(void) AlpProtoAdd(&alp_proto_ctx, proto_name, IPPROTO_TCP, ALPROTO_TLS, "|01 03 03|", 3, 0, STREAM_TOSERVER); AlpProtoAdd(&alp_proto_ctx, proto_name, IPPROTO_TCP, ALPROTO_TLS, "|16 03 03|", 3, 0, STREAM_TOSERVER); /* client hello */ + /* toclient direction */ + AlpProtoAdd(&alp_proto_ctx, proto_name, IPPROTO_TCP, ALPROTO_TLS, "|16 03 00|", 3, 0, STREAM_TOCLIENT); /* server hello */ + /** TLSv1 */ + AlpProtoAdd(&alp_proto_ctx, proto_name, IPPROTO_TCP, ALPROTO_TLS, "|16 03 01|", 3, 0, STREAM_TOCLIENT); /* server hello */ + /** TLSv1.1 */ + AlpProtoAdd(&alp_proto_ctx, proto_name, IPPROTO_TCP, ALPROTO_TLS, "|16 03 02|", 3, 0, STREAM_TOCLIENT); /* server hello */ + /** TLSv1.2 */ + AlpProtoAdd(&alp_proto_ctx, proto_name, IPPROTO_TCP, ALPROTO_TLS, "|16 03 03|", 3, 0, STREAM_TOCLIENT); /* server hello */ + if (RunmodeIsUnittests()) { AppLayerRegisterProbingParser(&alp_proto_ctx, IPPROTO_TCP, @@ -1030,6 +1039,8 @@ void RegisterSSLParsers(void) 0, 3, SSLProbingParser); } + + AppLayerRegisterParserAcceptableDataDirection(ALPROTO_TLS, STREAM_TOSERVER); } else { SCLogInfo("Protocol detection and parser disabled for %s protocol", proto_name); @@ -1060,7 +1071,7 @@ void RegisterSSLParsers(void) } #ifdef UNITTESTS - AppLayerRegisterUnittests(ALPROTO_TLS, SSLParserRegisterTests); + AppLayerParserRegisterUnittests(ALPROTO_TLS, SSLParserRegisterTests); #endif /* Get the value of no reassembly option from the config file */ diff --git a/src/app-layer.c b/src/app-layer.c index d77b9b24d8..6f950e2732 100644 --- a/src/app-layer.c +++ b/src/app-layer.c @@ -113,12 +113,13 @@ extern AlpProtoDetectCtx alp_proto_ctx; * \retval 0 ok * \retval -1 error */ -int AppLayerHandleTCPData(AlpProtoDetectThreadCtx *dp_ctx, Flow *f, - TcpSession *ssn, TcpStream *stream, - uint8_t *data, uint32_t data_len, +int AppLayerHandleTCPData(ThreadVars *tv, TcpReassemblyThreadCtx *ra_ctx, + Flow *f, TcpSession *ssn, TcpStream *stream, + uint8_t *data, uint32_t data_len, Packet *p, uint8_t flags) { SCEnter(); + AlpProtoDetectThreadCtx *dp_ctx = &ra_ctx->dp_ctx; DEBUG_ASSERT_FLOW_LOCKED(f); @@ -135,17 +136,34 @@ int AppLayerHandleTCPData(AlpProtoDetectThreadCtx *dp_ctx, Flow *f, SCReturnInt(r); } + uint16_t *alproto; + uint16_t *alproto_otherdir; + uint8_t dir; + if (flags & STREAM_TOSERVER) { + alproto = &f->alproto_ts; + alproto_otherdir = &f->alproto_tc; + dir = 0; + } else { + alproto = &f->alproto_tc; + alproto_otherdir = &f->alproto_ts; + dir = 1; + } + /* if we don't know the proto yet and we have received a stream * initializer message, we run proto detection. * We receive 2 stream init msgs (one for each direction) but we * only run the proto detection once. */ - if (f->alproto == ALPROTO_UNKNOWN && (flags & STREAM_GAP)) { - //stream->flags |= STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED; - ssn->client.flags |= STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED; - ssn->server.flags |= STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED; + if (*alproto == ALPROTO_UNKNOWN && (flags & STREAM_GAP)) { + stream->flags |= STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED; SCLogDebug("ALPROTO_UNKNOWN flow %p, due to GAP in stream start", f); - StreamTcpSetSessionNoReassemblyFlag(ssn, 0); - } else if (f->alproto == ALPROTO_UNKNOWN && (flags & STREAM_START)) { + StreamTcpSetSessionNoReassemblyFlag(ssn, dir); + } else if (*alproto == ALPROTO_UNKNOWN && (flags & STREAM_START)) { + uint32_t data_al_so_far; + if (data_len == 0) + data_al_so_far = 0; + else + data_al_so_far = f->data_al_so_far[dir]; + SCLogDebug("Stream initializer (len %" PRIu32 ")", data_len); #ifdef PRINT if (data_len > 0) { @@ -158,25 +176,91 @@ int AppLayerHandleTCPData(AlpProtoDetectThreadCtx *dp_ctx, Flow *f, #endif PACKET_PROFILING_APP_PD_START(dp_ctx); - f->alproto = AppLayerDetectGetProto(&alp_proto_ctx, dp_ctx, f, - data, data_len, flags, IPPROTO_TCP); + *alproto = AppLayerDetectGetProto(&alp_proto_ctx, dp_ctx, f, + data, data_len, flags, IPPROTO_TCP); PACKET_PROFILING_APP_PD_END(dp_ctx); - if (f->alproto != ALPROTO_UNKNOWN) { - //stream->flags |= STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED; - ssn->client.flags |= STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED; - ssn->server.flags |= STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED; - - PACKET_PROFILING_APP_START(dp_ctx, f->alproto); - r = AppLayerParse(dp_ctx->alproto_local_storage[f->alproto], f, f->alproto, flags, data, data_len); - PACKET_PROFILING_APP_END(dp_ctx, f->alproto); - } else { - if ((FLOW_IS_PM_DONE(f, STREAM_TOSERVER)) && (FLOW_IS_PM_DONE(f, STREAM_TOCLIENT)) && - (FLOW_IS_PP_DONE(f, STREAM_TOSERVER)) && (FLOW_IS_PP_DONE(f, STREAM_TOCLIENT))) { + if (*alproto != ALPROTO_UNKNOWN) { + if (*alproto_otherdir != ALPROTO_UNKNOWN && *alproto_otherdir != *alproto) { + /* \todo set event */ + f->alproto = f->alproto_ts = f->alproto_tc = ALPROTO_UNKNOWN; FlowSetSessionNoApplayerInspectionFlag(f); - //stream->flags |= STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED; ssn->client.flags |= STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED; ssn->server.flags |= STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED; + } else { + f->alproto = *alproto; + stream->flags |= STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED; + + if ((ssn->data_first_seen_dir & (STREAM_TOSERVER | STREAM_TOCLIENT)) && + !(flags & ssn->data_first_seen_dir)) { + TcpStream *opposing_stream = NULL; + if (stream == &ssn->client) { + opposing_stream = &ssn->server; + p->flowflags &= ~FLOW_PKT_TOCLIENT; + p->flowflags |= FLOW_PKT_TOSERVER; + } else { + opposing_stream = &ssn->client; + p->flowflags &= ~FLOW_PKT_TOSERVER; + p->flowflags |= FLOW_PKT_TOCLIENT; + } + + int ret = StreamTcpReassembleAppLayer(tv, ra_ctx, ssn, opposing_stream, p); + if (stream == &ssn->client) { + p->flowflags &= ~FLOW_PKT_TOSERVER; + p->flowflags |= FLOW_PKT_TOCLIENT; + } else { + p->flowflags &= ~FLOW_PKT_TOCLIENT; + p->flowflags |= FLOW_PKT_TOSERVER; + } + if (ret < 0) { + r = -1; + goto end; + } + } + + if (ssn->data_first_seen_dir != 0x01) { + if (al_proto_table[*alproto].flags && !(al_proto_table[*alproto].flags & ssn->data_first_seen_dir)) { + /* \todo Set event */ + r = -1; + f->alproto = f->alproto_ts = f->alproto_tc = ALPROTO_UNKNOWN; + FlowSetSessionNoApplayerInspectionFlag(f); + ssn->server.flags |= STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED; + ssn->client.flags |= STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED; + /* Set a value that is neither STREAM_TOSERVER, nor STREAM_TOCLIENT */ + ssn->data_first_seen_dir = 0x01; + goto end; + } + } + + /* Set a value that is neither STREAM_TOSERVER, nor STREAM_TOCLIENT */ + ssn->data_first_seen_dir = 0x01; + + PACKET_PROFILING_APP_START(dp_ctx, *alproto); + r = AppLayerParse(dp_ctx->alproto_local_storage[*alproto], f, *alproto, flags, data + data_al_so_far, data_len - data_al_so_far); + PACKET_PROFILING_APP_END(dp_ctx, *alproto); + f->data_al_so_far[dir] = 0; + } + } else { + if (*alproto_otherdir != ALPROTO_UNKNOWN) { + PACKET_PROFILING_APP_START(dp_ctx, *alproto_otherdir); + r = AppLayerParse(dp_ctx->alproto_local_storage[*alproto_otherdir], f, *alproto_otherdir, flags, + data + data_al_so_far, data_len - data_al_so_far); + PACKET_PROFILING_APP_END(dp_ctx, *alproto_otherdir); + if (FLOW_IS_PM_DONE(f, flags) && FLOW_IS_PP_DONE(f, flags)) { + /* \todo event. Unable to detect protocol for one direction */ + stream->flags |= STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED; + f->data_al_so_far[dir] = 0; + } else { + f->data_al_so_far[dir] = data_len; + } + } else { + if (FLOW_IS_PM_DONE(f, STREAM_TOSERVER) && FLOW_IS_PP_DONE(f, STREAM_TOSERVER) && + FLOW_IS_PM_DONE(f, STREAM_TOCLIENT) && FLOW_IS_PP_DONE(f, STREAM_TOCLIENT)) { + ssn->client.flags |= STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED; + ssn->server.flags |= STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED; + ssn->data_first_seen_dir = 0x01; + FlowSetSessionNoApplayerInspectionFlag(f); + } } } } else { @@ -202,6 +286,7 @@ int AppLayerHandleTCPData(AlpProtoDetectThreadCtx *dp_ctx, Flow *f, } } + end: SCReturnInt(r); } @@ -360,3 +445,2849 @@ int AppLayerHandleUdp(AlpProtoDetectThreadCtx *dp_ctx, Flow *f, Packet *p) SCReturnInt(r); } +/************Unittests*************/ + +#ifdef UNITTESTS + +#include "stream-tcp.h" +#include "stream-tcp-private.h" +#include "stream-tcp-reassemble.h" +#include "stream-tcp-inline.h" +#include "stream-tcp-util.h" +#include "stream.h" +#include "util-unittest.h" + +/** + * \test GET -> HTTP/1.1 + */ +static int AppLayerTest01(void) +{ + Packet *p = SCMalloc(SIZE_OF_PACKET); + if (unlikely(p == NULL)) + return 0; + Flow f; + ThreadVars tv; + StreamTcpThread *stt = NULL; + TCPHdr tcph; + PacketQueue pq; + memset(&pq,0,sizeof(PacketQueue)); + memset(p, 0, SIZE_OF_PACKET); + memset (&f, 0, sizeof(Flow)); + memset(&tv, 0, sizeof (ThreadVars)); + StreamTcpThreadInit(&tv, NULL, (void **)&stt); + memset(&tcph, 0, sizeof (TCPHdr)); + + f.flags = FLOW_IPV4; + p->pkt = (uint8_t *)(p + 1); + p->flow = &f; + p->tcph = &tcph; + + int ret = 0; + + StreamTcpInitConfig(TRUE); + + tcph.th_win = htons(5480); + tcph.th_flags = TH_SYN; + p->flowflags = FLOW_PKT_TOSERVER; + p->payload_len = 0; + p->payload = NULL; + if (StreamTcpPacket(&tv, p, stt, &pq) == -1) + goto end; + + TcpSession *ssn = (TcpSession *)f.protoctx; + + /* handshake */ + if (ssn->server.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED || + ssn->client.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED || + f.alproto != ALPROTO_UNKNOWN || + f.alproto_ts != ALPROTO_UNKNOWN || + f.alproto_tc != ALPROTO_UNKNOWN || + f.data_al_so_far[0] != 0 || + f.data_al_so_far[1] != 0 || + f.flags & FLOW_NO_APPLAYER_INSPECTION || + FLOW_IS_PM_DONE(&f, STREAM_TOSERVER) || FLOW_IS_PP_DONE(&f, STREAM_TOSERVER) || + FLOW_IS_PM_DONE(&f, STREAM_TOCLIENT) || FLOW_IS_PP_DONE(&f, STREAM_TOCLIENT) || + ssn->data_first_seen_dir != 0) { + printf("failure 1\n"); + goto end; + } + + + /* handshake */ + p->tcph->th_ack = htonl(1); + p->tcph->th_flags = TH_SYN | TH_ACK; + p->flowflags = FLOW_PKT_TOCLIENT; + p->payload_len = 0; + p->payload = NULL; + if (StreamTcpPacket(&tv, p, stt, &pq) == -1) + goto end; + if (ssn->server.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED || + ssn->client.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED || + f.alproto != ALPROTO_UNKNOWN || + f.alproto_ts != ALPROTO_UNKNOWN || + f.alproto_tc != ALPROTO_UNKNOWN || + f.data_al_so_far[0] != 0 || + f.data_al_so_far[1] != 0 || + f.flags & FLOW_NO_APPLAYER_INSPECTION || + FLOW_IS_PM_DONE(&f, STREAM_TOSERVER) || FLOW_IS_PP_DONE(&f, STREAM_TOSERVER) || + FLOW_IS_PM_DONE(&f, STREAM_TOCLIENT) || FLOW_IS_PP_DONE(&f, STREAM_TOCLIENT) || + ssn->data_first_seen_dir != 0) { + printf("failure 2\n"); + goto end; + } + + /* handshake */ + p->tcph->th_ack = htonl(1); + p->tcph->th_seq = htonl(1); + p->tcph->th_flags = TH_ACK; + p->flowflags = FLOW_PKT_TOSERVER; + p->payload_len = 0; + p->payload = NULL; + if (StreamTcpPacket(&tv, p, stt, &pq) == -1) + goto end; + if (ssn->server.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED || + ssn->client.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED || + f.alproto != ALPROTO_UNKNOWN || + f.alproto_ts != ALPROTO_UNKNOWN || + f.alproto_tc != ALPROTO_UNKNOWN || + f.data_al_so_far[0] != 0 || + f.data_al_so_far[1] != 0 || + f.flags & FLOW_NO_APPLAYER_INSPECTION || + FLOW_IS_PM_DONE(&f, STREAM_TOSERVER) || FLOW_IS_PP_DONE(&f, STREAM_TOSERVER) || + FLOW_IS_PM_DONE(&f, STREAM_TOCLIENT) || FLOW_IS_PP_DONE(&f, STREAM_TOCLIENT) || + ssn->data_first_seen_dir != 0) { + printf("failure 3\n"); + goto end; + } + + /* full request */ + uint8_t request[] = { + 0x47, 0x45, 0x54, 0x20, 0x2f, 0x69, 0x6e, 0x64, + 0x65, 0x78, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0x20, + 0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, 0x2e, 0x30, + 0x0d, 0x0a, 0x48, 0x6f, 0x73, 0x74, 0x3a, 0x20, + 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x68, 0x6f, 0x73, + 0x74, 0x0d, 0x0a, 0x55, 0x73, 0x65, 0x72, 0x2d, + 0x41, 0x67, 0x65, 0x6e, 0x74, 0x3a, 0x20, 0x41, + 0x70, 0x61, 0x63, 0x68, 0x65, 0x42, 0x65, 0x6e, + 0x63, 0x68, 0x2f, 0x32, 0x2e, 0x33, 0x0d, 0x0a, + 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x3a, 0x20, + 0x2a, 0x2f, 0x2a, 0x0d, 0x0a, 0x0d, 0x0a }; + p->tcph->th_ack = htonl(1); + p->tcph->th_seq = htonl(1); + p->tcph->th_flags = TH_PUSH | TH_ACK; + p->flowflags = FLOW_PKT_TOSERVER; + p->payload_len = sizeof(request); + p->payload = request; + if (StreamTcpPacket(&tv, p, stt, &pq) == -1) + goto end; + if (ssn->server.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED || + ssn->client.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED || + f.alproto != ALPROTO_UNKNOWN || + f.alproto_ts != ALPROTO_UNKNOWN || + f.alproto_tc != ALPROTO_UNKNOWN || + f.data_al_so_far[0] != 0 || + f.data_al_so_far[1] != 0 || + f.flags & FLOW_NO_APPLAYER_INSPECTION || + FLOW_IS_PM_DONE(&f, STREAM_TOSERVER) || FLOW_IS_PP_DONE(&f, STREAM_TOSERVER) || + FLOW_IS_PM_DONE(&f, STREAM_TOCLIENT) || FLOW_IS_PP_DONE(&f, STREAM_TOCLIENT) || + ssn->data_first_seen_dir != STREAM_TOSERVER) { + printf("failure 4\n"); + goto end; + } + + /* full response - request ack */ + uint8_t response[] = { + 0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, 0x2e, 0x31, + 0x20, 0x32, 0x30, 0x30, 0x20, 0x4f, 0x4b, 0x0d, + 0x0a, 0x44, 0x61, 0x74, 0x65, 0x3a, 0x20, 0x46, + 0x72, 0x69, 0x2c, 0x20, 0x32, 0x33, 0x20, 0x53, + 0x65, 0x70, 0x20, 0x32, 0x30, 0x31, 0x31, 0x20, + 0x30, 0x36, 0x3a, 0x32, 0x39, 0x3a, 0x33, 0x39, + 0x20, 0x47, 0x4d, 0x54, 0x0d, 0x0a, 0x53, 0x65, + 0x72, 0x76, 0x65, 0x72, 0x3a, 0x20, 0x41, 0x70, + 0x61, 0x63, 0x68, 0x65, 0x2f, 0x32, 0x2e, 0x32, + 0x2e, 0x31, 0x35, 0x20, 0x28, 0x55, 0x6e, 0x69, + 0x78, 0x29, 0x20, 0x44, 0x41, 0x56, 0x2f, 0x32, + 0x0d, 0x0a, 0x4c, 0x61, 0x73, 0x74, 0x2d, 0x4d, + 0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, 0x64, 0x3a, + 0x20, 0x54, 0x68, 0x75, 0x2c, 0x20, 0x30, 0x34, + 0x20, 0x4e, 0x6f, 0x76, 0x20, 0x32, 0x30, 0x31, + 0x30, 0x20, 0x31, 0x35, 0x3a, 0x30, 0x34, 0x3a, + 0x34, 0x36, 0x20, 0x47, 0x4d, 0x54, 0x0d, 0x0a, + 0x45, 0x54, 0x61, 0x67, 0x3a, 0x20, 0x22, 0x61, + 0x62, 0x38, 0x39, 0x36, 0x35, 0x2d, 0x32, 0x63, + 0x2d, 0x34, 0x39, 0x34, 0x33, 0x62, 0x37, 0x61, + 0x37, 0x66, 0x37, 0x66, 0x38, 0x30, 0x22, 0x0d, + 0x0a, 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x2d, + 0x52, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x3a, 0x20, + 0x62, 0x79, 0x74, 0x65, 0x73, 0x0d, 0x0a, 0x43, + 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x4c, + 0x65, 0x6e, 0x67, 0x74, 0x68, 0x3a, 0x20, 0x34, + 0x34, 0x0d, 0x0a, 0x43, 0x6f, 0x6e, 0x6e, 0x65, + 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x63, + 0x6c, 0x6f, 0x73, 0x65, 0x0d, 0x0a, 0x43, 0x6f, + 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x54, 0x79, + 0x70, 0x65, 0x3a, 0x20, 0x74, 0x65, 0x78, 0x74, + 0x2f, 0x68, 0x74, 0x6d, 0x6c, 0x0d, 0x0a, 0x58, + 0x2d, 0x50, 0x61, 0x64, 0x3a, 0x20, 0x61, 0x76, + 0x6f, 0x69, 0x64, 0x20, 0x62, 0x72, 0x6f, 0x77, + 0x73, 0x65, 0x72, 0x20, 0x62, 0x75, 0x67, 0x0d, + 0x0a, 0x0d, 0x0a, 0x3c, 0x68, 0x74, 0x6d, 0x6c, + 0x3e, 0x3c, 0x62, 0x6f, 0x64, 0x79, 0x3e, 0x3c, + 0x68, 0x31, 0x3e, 0x49, 0x74, 0x20, 0x77, 0x6f, + 0x72, 0x6b, 0x73, 0x21, 0x3c, 0x2f, 0x68, 0x31, + 0x3e, 0x3c, 0x2f, 0x62, 0x6f, 0x64, 0x79, 0x3e, + 0x3c, 0x2f, 0x68, 0x74, 0x6d, 0x6c, 0x3e }; + p->tcph->th_ack = htonl(88); + p->tcph->th_seq = htonl(1); + p->tcph->th_flags = TH_PUSH | TH_ACK; + p->flowflags = FLOW_PKT_TOCLIENT; + p->payload_len = sizeof(response); + p->payload = response; + if (StreamTcpPacket(&tv, p, stt, &pq) == -1) + goto end; + if (ssn->server.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED || + !(ssn->client.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED) || + f.alproto != ALPROTO_HTTP || + f.alproto_ts != ALPROTO_HTTP || + f.alproto_tc != ALPROTO_UNKNOWN || + f.data_al_so_far[0] != 0 || + f.data_al_so_far[1] != 0 || + f.flags & FLOW_NO_APPLAYER_INSPECTION || + !FLOW_IS_PM_DONE(&f, STREAM_TOSERVER) || FLOW_IS_PP_DONE(&f, STREAM_TOSERVER) || + FLOW_IS_PM_DONE(&f, STREAM_TOCLIENT) || FLOW_IS_PP_DONE(&f, STREAM_TOCLIENT) || + ssn->data_first_seen_dir != 0x01) { + printf("failure 5\n"); + goto end; + } + + /* response ack */ + p->tcph->th_ack = htonl(328); + p->tcph->th_seq = htonl(88); + p->tcph->th_flags = TH_ACK; + p->flowflags = FLOW_PKT_TOSERVER; + p->payload_len = 0; + p->payload = NULL; + if (StreamTcpPacket(&tv, p, stt, &pq) == -1) + goto end; + if (!(ssn->server.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED) || + !(ssn->client.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED) || + f.alproto != ALPROTO_HTTP || + f.alproto_ts != ALPROTO_HTTP || + f.alproto_tc != ALPROTO_HTTP || + f.data_al_so_far[0] != 0 || + f.data_al_so_far[1] != 0 || + f.flags & FLOW_NO_APPLAYER_INSPECTION || + !FLOW_IS_PM_DONE(&f, STREAM_TOSERVER) || FLOW_IS_PP_DONE(&f, STREAM_TOSERVER) || + !FLOW_IS_PM_DONE(&f, STREAM_TOCLIENT) || FLOW_IS_PP_DONE(&f, STREAM_TOCLIENT) || + ssn->data_first_seen_dir != 0x01) { + printf("failure 6\n"); + goto end; + } + + StreamTcpSessionClear(p->flow->protoctx); + + ret = 1; +end: + StreamTcpFreeConfig(TRUE); + SCFree(p); + return ret; +} + +/** + * \test GE -> T -> HTTP/1.1 + */ +static int AppLayerTest02(void) +{ + Packet *p = SCMalloc(SIZE_OF_PACKET); + if (unlikely(p == NULL)) + return 0; + Flow f; + ThreadVars tv; + StreamTcpThread *stt = NULL; + TCPHdr tcph; + PacketQueue pq; + memset(&pq,0,sizeof(PacketQueue)); + memset(p, 0, SIZE_OF_PACKET); + memset (&f, 0, sizeof(Flow)); + memset(&tv, 0, sizeof (ThreadVars)); + StreamTcpThreadInit(&tv, NULL, (void **)&stt); + memset(&tcph, 0, sizeof (TCPHdr)); + + f.flags = FLOW_IPV4; + p->pkt = (uint8_t *)(p + 1); + p->flow = &f; + p->tcph = &tcph; + + int ret = 0; + + StreamTcpInitConfig(TRUE); + + /* handshake */ + tcph.th_win = htons(5480); + tcph.th_flags = TH_SYN; + p->flowflags = FLOW_PKT_TOSERVER; + p->payload_len = 0; + p->payload = NULL; + if (StreamTcpPacket(&tv, p, stt, &pq) == -1) + goto end; + + TcpSession *ssn = (TcpSession *)f.protoctx; + + if (ssn->server.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED || + ssn->client.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED || + f.alproto != ALPROTO_UNKNOWN || + f.alproto_ts != ALPROTO_UNKNOWN || + f.alproto_tc != ALPROTO_UNKNOWN || + f.data_al_so_far[0] != 0 || + f.data_al_so_far[1] != 0 || + f.flags & FLOW_NO_APPLAYER_INSPECTION || + FLOW_IS_PM_DONE(&f, STREAM_TOSERVER) || FLOW_IS_PP_DONE(&f, STREAM_TOSERVER) || + FLOW_IS_PM_DONE(&f, STREAM_TOCLIENT) || FLOW_IS_PP_DONE(&f, STREAM_TOCLIENT) || + ssn->data_first_seen_dir != 0) { + printf("failure 1\n"); + goto end; + } + + + /* handshake */ + p->tcph->th_ack = htonl(1); + p->tcph->th_flags = TH_SYN | TH_ACK; + p->flowflags = FLOW_PKT_TOCLIENT; + p->payload_len = 0; + p->payload = NULL; + if (StreamTcpPacket(&tv, p, stt, &pq) == -1) + goto end; + if (ssn->server.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED || + ssn->client.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED || + f.alproto != ALPROTO_UNKNOWN || + f.alproto_ts != ALPROTO_UNKNOWN || + f.alproto_tc != ALPROTO_UNKNOWN || + f.data_al_so_far[0] != 0 || + f.data_al_so_far[1] != 0 || + f.flags & FLOW_NO_APPLAYER_INSPECTION || + FLOW_IS_PM_DONE(&f, STREAM_TOSERVER) || FLOW_IS_PP_DONE(&f, STREAM_TOSERVER) || + FLOW_IS_PM_DONE(&f, STREAM_TOCLIENT) || FLOW_IS_PP_DONE(&f, STREAM_TOCLIENT) || + ssn->data_first_seen_dir != 0) { + printf("failure 2\n"); + goto end; + } + + /* handshake */ + p->tcph->th_ack = htonl(1); + p->tcph->th_seq = htonl(1); + p->tcph->th_flags = TH_ACK; + p->flowflags = FLOW_PKT_TOSERVER; + p->payload_len = 0; + p->payload = NULL; + if (StreamTcpPacket(&tv, p, stt, &pq) == -1) + goto end; + if (ssn->server.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED || + ssn->client.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED || + f.alproto != ALPROTO_UNKNOWN || + f.alproto_ts != ALPROTO_UNKNOWN || + f.alproto_tc != ALPROTO_UNKNOWN || + f.data_al_so_far[0] != 0 || + f.data_al_so_far[1] != 0 || + f.flags & FLOW_NO_APPLAYER_INSPECTION || + FLOW_IS_PM_DONE(&f, STREAM_TOSERVER) || FLOW_IS_PP_DONE(&f, STREAM_TOSERVER) || + FLOW_IS_PM_DONE(&f, STREAM_TOCLIENT) || FLOW_IS_PP_DONE(&f, STREAM_TOCLIENT) || + ssn->data_first_seen_dir != 0) { + printf("failure 3\n"); + goto end; + } + + /* partial request */ + uint8_t request1[] = { 0x47, 0x45, }; + p->tcph->th_ack = htonl(1); + p->tcph->th_seq = htonl(1); + p->tcph->th_flags = TH_PUSH | TH_ACK; + p->flowflags = FLOW_PKT_TOSERVER; + p->payload_len = sizeof(request1); + p->payload = request1; + if (StreamTcpPacket(&tv, p, stt, &pq) == -1) + goto end; + if (ssn->server.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED || + ssn->client.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED || + f.alproto != ALPROTO_UNKNOWN || + f.alproto_ts != ALPROTO_UNKNOWN || + f.alproto_tc != ALPROTO_UNKNOWN || + f.data_al_so_far[0] != 0 || + f.data_al_so_far[1] != 0 || + f.flags & FLOW_NO_APPLAYER_INSPECTION || + FLOW_IS_PM_DONE(&f, STREAM_TOSERVER) || FLOW_IS_PP_DONE(&f, STREAM_TOSERVER) || + FLOW_IS_PM_DONE(&f, STREAM_TOCLIENT) || FLOW_IS_PP_DONE(&f, STREAM_TOCLIENT) || + ssn->data_first_seen_dir != STREAM_TOSERVER) { + printf("failure 4\n"); + goto end; + } + + /* response ack against partial request */ + p->tcph->th_ack = htonl(3); + p->tcph->th_seq = htonl(1); + p->tcph->th_flags = TH_ACK; + p->flowflags = FLOW_PKT_TOCLIENT; + p->payload_len = 0; + p->payload = NULL; + if (StreamTcpPacket(&tv, p, stt, &pq) == -1) + goto end; + if (ssn->server.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED || + ssn->client.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED || + f.alproto != ALPROTO_UNKNOWN || + f.alproto_ts != ALPROTO_UNKNOWN || + f.alproto_tc != ALPROTO_UNKNOWN || + f.data_al_so_far[0] != 0 || + f.data_al_so_far[1] != 0 || + f.flags & FLOW_NO_APPLAYER_INSPECTION || + FLOW_IS_PM_DONE(&f, STREAM_TOSERVER) || !FLOW_IS_PP_DONE(&f, STREAM_TOSERVER) || + FLOW_IS_PM_DONE(&f, STREAM_TOCLIENT) || FLOW_IS_PP_DONE(&f, STREAM_TOCLIENT) || + ssn->data_first_seen_dir != STREAM_TOSERVER) { + printf("failure 5\n"); + goto end; + } + + /* complete partial request */ + uint8_t request2[] = { + 0x54, 0x20, 0x2f, 0x69, 0x6e, 0x64, + 0x65, 0x78, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0x20, + 0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, 0x2e, 0x30, + 0x0d, 0x0a, 0x48, 0x6f, 0x73, 0x74, 0x3a, 0x20, + 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x68, 0x6f, 0x73, + 0x74, 0x0d, 0x0a, 0x55, 0x73, 0x65, 0x72, 0x2d, + 0x41, 0x67, 0x65, 0x6e, 0x74, 0x3a, 0x20, 0x41, + 0x70, 0x61, 0x63, 0x68, 0x65, 0x42, 0x65, 0x6e, + 0x63, 0x68, 0x2f, 0x32, 0x2e, 0x33, 0x0d, 0x0a, + 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x3a, 0x20, + 0x2a, 0x2f, 0x2a, 0x0d, 0x0a, 0x0d, 0x0a }; + p->tcph->th_ack = htonl(1); + p->tcph->th_seq = htonl(3); + p->tcph->th_flags = TH_PUSH | TH_ACK; + p->flowflags = FLOW_PKT_TOSERVER; + p->payload_len = sizeof(request2); + p->payload = request2; + if (StreamTcpPacket(&tv, p, stt, &pq) == -1) + goto end; + if (ssn->server.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED || + ssn->client.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED || + f.alproto != ALPROTO_UNKNOWN || + f.alproto_ts != ALPROTO_UNKNOWN || + f.alproto_tc != ALPROTO_UNKNOWN || + f.data_al_so_far[0] != 0 || + f.data_al_so_far[1] != 0 || + f.flags & FLOW_NO_APPLAYER_INSPECTION || + FLOW_IS_PM_DONE(&f, STREAM_TOSERVER) || !FLOW_IS_PP_DONE(&f, STREAM_TOSERVER) || + FLOW_IS_PM_DONE(&f, STREAM_TOCLIENT) || FLOW_IS_PP_DONE(&f, STREAM_TOCLIENT) || + ssn->data_first_seen_dir != STREAM_TOSERVER) { + printf("failure 6\n"); + goto end; + } + + /* response - request ack */ + uint8_t response[] = { + 0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, 0x2e, 0x31, + 0x20, 0x32, 0x30, 0x30, 0x20, 0x4f, 0x4b, 0x0d, + 0x0a, 0x44, 0x61, 0x74, 0x65, 0x3a, 0x20, 0x46, + 0x72, 0x69, 0x2c, 0x20, 0x32, 0x33, 0x20, 0x53, + 0x65, 0x70, 0x20, 0x32, 0x30, 0x31, 0x31, 0x20, + 0x30, 0x36, 0x3a, 0x32, 0x39, 0x3a, 0x33, 0x39, + 0x20, 0x47, 0x4d, 0x54, 0x0d, 0x0a, 0x53, 0x65, + 0x72, 0x76, 0x65, 0x72, 0x3a, 0x20, 0x41, 0x70, + 0x61, 0x63, 0x68, 0x65, 0x2f, 0x32, 0x2e, 0x32, + 0x2e, 0x31, 0x35, 0x20, 0x28, 0x55, 0x6e, 0x69, + 0x78, 0x29, 0x20, 0x44, 0x41, 0x56, 0x2f, 0x32, + 0x0d, 0x0a, 0x4c, 0x61, 0x73, 0x74, 0x2d, 0x4d, + 0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, 0x64, 0x3a, + 0x20, 0x54, 0x68, 0x75, 0x2c, 0x20, 0x30, 0x34, + 0x20, 0x4e, 0x6f, 0x76, 0x20, 0x32, 0x30, 0x31, + 0x30, 0x20, 0x31, 0x35, 0x3a, 0x30, 0x34, 0x3a, + 0x34, 0x36, 0x20, 0x47, 0x4d, 0x54, 0x0d, 0x0a, + 0x45, 0x54, 0x61, 0x67, 0x3a, 0x20, 0x22, 0x61, + 0x62, 0x38, 0x39, 0x36, 0x35, 0x2d, 0x32, 0x63, + 0x2d, 0x34, 0x39, 0x34, 0x33, 0x62, 0x37, 0x61, + 0x37, 0x66, 0x37, 0x66, 0x38, 0x30, 0x22, 0x0d, + 0x0a, 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x2d, + 0x52, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x3a, 0x20, + 0x62, 0x79, 0x74, 0x65, 0x73, 0x0d, 0x0a, 0x43, + 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x4c, + 0x65, 0x6e, 0x67, 0x74, 0x68, 0x3a, 0x20, 0x34, + 0x34, 0x0d, 0x0a, 0x43, 0x6f, 0x6e, 0x6e, 0x65, + 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x63, + 0x6c, 0x6f, 0x73, 0x65, 0x0d, 0x0a, 0x43, 0x6f, + 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x54, 0x79, + 0x70, 0x65, 0x3a, 0x20, 0x74, 0x65, 0x78, 0x74, + 0x2f, 0x68, 0x74, 0x6d, 0x6c, 0x0d, 0x0a, 0x58, + 0x2d, 0x50, 0x61, 0x64, 0x3a, 0x20, 0x61, 0x76, + 0x6f, 0x69, 0x64, 0x20, 0x62, 0x72, 0x6f, 0x77, + 0x73, 0x65, 0x72, 0x20, 0x62, 0x75, 0x67, 0x0d, + 0x0a, 0x0d, 0x0a, 0x3c, 0x68, 0x74, 0x6d, 0x6c, + 0x3e, 0x3c, 0x62, 0x6f, 0x64, 0x79, 0x3e, 0x3c, + 0x68, 0x31, 0x3e, 0x49, 0x74, 0x20, 0x77, 0x6f, + 0x72, 0x6b, 0x73, 0x21, 0x3c, 0x2f, 0x68, 0x31, + 0x3e, 0x3c, 0x2f, 0x62, 0x6f, 0x64, 0x79, 0x3e, + 0x3c, 0x2f, 0x68, 0x74, 0x6d, 0x6c, 0x3e }; + p->tcph->th_ack = htonl(88); + p->tcph->th_seq = htonl(1); + p->tcph->th_flags = TH_PUSH | TH_ACK; + p->flowflags = FLOW_PKT_TOCLIENT; + p->payload_len = sizeof(response); + p->payload = response; + if (StreamTcpPacket(&tv, p, stt, &pq) == -1) + goto end; + if (ssn->server.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED || + !(ssn->client.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED) || + f.alproto != ALPROTO_HTTP || + f.alproto_ts != ALPROTO_HTTP || + f.alproto_tc != ALPROTO_UNKNOWN || + f.data_al_so_far[0] != 0 || + f.data_al_so_far[1] != 0 || + f.flags & FLOW_NO_APPLAYER_INSPECTION || + !FLOW_IS_PM_DONE(&f, STREAM_TOSERVER) || !FLOW_IS_PP_DONE(&f, STREAM_TOSERVER) || + FLOW_IS_PM_DONE(&f, STREAM_TOCLIENT) || FLOW_IS_PP_DONE(&f, STREAM_TOCLIENT) || + ssn->data_first_seen_dir != 0x01) { + printf("failure 7\n"); + goto end; + } + + /* response ack */ + p->tcph->th_ack = htonl(328); + p->tcph->th_seq = htonl(88); + p->tcph->th_flags = TH_ACK; + p->flowflags = FLOW_PKT_TOSERVER; + p->payload_len = 0; + p->payload = NULL; + if (StreamTcpPacket(&tv, p, stt, &pq) == -1) + goto end; + if (!(ssn->server.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED) || + !(ssn->client.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED) || + f.alproto != ALPROTO_HTTP || + f.alproto_ts != ALPROTO_HTTP || + f.alproto_tc != ALPROTO_HTTP || + f.data_al_so_far[0] != 0 || + f.data_al_so_far[1] != 0 || + f.flags & FLOW_NO_APPLAYER_INSPECTION || + !FLOW_IS_PM_DONE(&f, STREAM_TOSERVER) || !FLOW_IS_PP_DONE(&f, STREAM_TOSERVER) || + !FLOW_IS_PM_DONE(&f, STREAM_TOCLIENT) || FLOW_IS_PP_DONE(&f, STREAM_TOCLIENT) || + ssn->data_first_seen_dir != 0x01) { + printf("failure 8\n"); + goto end; + } + + StreamTcpSessionClear(p->flow->protoctx); + + ret = 1; +end: + StreamTcpFreeConfig(TRUE); + SCFree(p); + return ret; +} + +/** + * \test GET -> RUBBISH(PM AND PP DONE IN ONE GO) + */ + static int AppLayerTest03(void) +{ + Packet *p = SCMalloc(SIZE_OF_PACKET); + if (unlikely(p == NULL)) + return 0; + Flow f; + ThreadVars tv; + StreamTcpThread *stt = NULL; + TCPHdr tcph; + PacketQueue pq; + memset(&pq,0,sizeof(PacketQueue)); + memset(p, 0, SIZE_OF_PACKET); + memset (&f, 0, sizeof(Flow)); + memset(&tv, 0, sizeof (ThreadVars)); + StreamTcpThreadInit(&tv, NULL, (void **)&stt); + memset(&tcph, 0, sizeof (TCPHdr)); + + f.flags = FLOW_IPV4; + p->pkt = (uint8_t *)(p + 1); + p->flow = &f; + p->tcph = &tcph; + + int ret = 0; + + StreamTcpInitConfig(TRUE); + + tcph.th_win = htons(5480); + tcph.th_flags = TH_SYN; + p->flowflags = FLOW_PKT_TOSERVER; + p->payload_len = 0; + p->payload = NULL; + if (StreamTcpPacket(&tv, p, stt, &pq) == -1) + goto end; + + TcpSession *ssn = (TcpSession *)f.protoctx; + + /* handshake */ + if (ssn->server.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED || + ssn->client.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED || + f.alproto != ALPROTO_UNKNOWN || + f.alproto_ts != ALPROTO_UNKNOWN || + f.alproto_tc != ALPROTO_UNKNOWN || + f.data_al_so_far[0] != 0 || + f.data_al_so_far[1] != 0 || + f.flags & FLOW_NO_APPLAYER_INSPECTION || + FLOW_IS_PM_DONE(&f, STREAM_TOSERVER) || FLOW_IS_PP_DONE(&f, STREAM_TOSERVER) || + FLOW_IS_PM_DONE(&f, STREAM_TOCLIENT) || FLOW_IS_PP_DONE(&f, STREAM_TOCLIENT) || + ssn->data_first_seen_dir != 0) { + printf("failure 1\n"); + goto end; + } + + /* handshake */ + p->tcph->th_ack = htonl(1); + p->tcph->th_flags = TH_SYN | TH_ACK; + p->flowflags = FLOW_PKT_TOCLIENT; + p->payload_len = 0; + p->payload = NULL; + if (StreamTcpPacket(&tv, p, stt, &pq) == -1) + goto end; + if (ssn->server.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED || + ssn->client.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED || + f.alproto != ALPROTO_UNKNOWN || + f.alproto_ts != ALPROTO_UNKNOWN || + f.alproto_tc != ALPROTO_UNKNOWN || + f.data_al_so_far[0] != 0 || + f.data_al_so_far[1] != 0 || + f.flags & FLOW_NO_APPLAYER_INSPECTION || + FLOW_IS_PM_DONE(&f, STREAM_TOSERVER) || FLOW_IS_PP_DONE(&f, STREAM_TOSERVER) || + FLOW_IS_PM_DONE(&f, STREAM_TOCLIENT) || FLOW_IS_PP_DONE(&f, STREAM_TOCLIENT) || + ssn->data_first_seen_dir != 0) { + printf("failure 2\n"); + goto end; + } + + /* handshake */ + p->tcph->th_ack = htonl(1); + p->tcph->th_seq = htonl(1); + p->tcph->th_flags = TH_ACK; + p->flowflags = FLOW_PKT_TOSERVER; + p->payload_len = 0; + p->payload = NULL; + if (StreamTcpPacket(&tv, p, stt, &pq) == -1) + goto end; + if (ssn->server.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED || + ssn->client.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED || + f.alproto != ALPROTO_UNKNOWN || + f.alproto_ts != ALPROTO_UNKNOWN || + f.alproto_tc != ALPROTO_UNKNOWN || + f.data_al_so_far[0] != 0 || + f.data_al_so_far[1] != 0 || + f.flags & FLOW_NO_APPLAYER_INSPECTION || + FLOW_IS_PM_DONE(&f, STREAM_TOSERVER) || FLOW_IS_PP_DONE(&f, STREAM_TOSERVER) || + FLOW_IS_PM_DONE(&f, STREAM_TOCLIENT) || FLOW_IS_PP_DONE(&f, STREAM_TOCLIENT) || + ssn->data_first_seen_dir != 0) { + printf("failure 3\n"); + goto end; + } + + /* request */ + uint8_t request[] = { + 0x47, 0x45, 0x54, 0x20, 0x2f, 0x69, 0x6e, 0x64, + 0x65, 0x78, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0x20, + 0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, 0x2e, 0x30, + 0x0d, 0x0a, 0x48, 0x6f, 0x73, 0x74, 0x3a, 0x20, + 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x68, 0x6f, 0x73, + 0x74, 0x0d, 0x0a, 0x55, 0x73, 0x65, 0x72, 0x2d, + 0x41, 0x67, 0x65, 0x6e, 0x74, 0x3a, 0x20, 0x41, + 0x70, 0x61, 0x63, 0x68, 0x65, 0x42, 0x65, 0x6e, + 0x63, 0x68, 0x2f, 0x32, 0x2e, 0x33, 0x0d, 0x0a, + 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x3a, 0x20, + 0x2a, 0x2f, 0x2a, 0x0d, 0x0a, 0x0d, 0x0a }; + p->tcph->th_ack = htonl(1); + p->tcph->th_seq = htonl(1); + p->tcph->th_flags = TH_PUSH | TH_ACK; + p->flowflags = FLOW_PKT_TOSERVER; + p->payload_len = sizeof(request); + p->payload = request; + if (StreamTcpPacket(&tv, p, stt, &pq) == -1) + goto end; + if (ssn->server.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED || + ssn->client.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED || + f.alproto != ALPROTO_UNKNOWN || + f.alproto_ts != ALPROTO_UNKNOWN || + f.alproto_tc != ALPROTO_UNKNOWN || + f.data_al_so_far[0] != 0 || + f.data_al_so_far[1] != 0 || + f.flags & FLOW_NO_APPLAYER_INSPECTION || + FLOW_IS_PM_DONE(&f, STREAM_TOSERVER) || FLOW_IS_PP_DONE(&f, STREAM_TOSERVER) || + FLOW_IS_PM_DONE(&f, STREAM_TOCLIENT) || FLOW_IS_PP_DONE(&f, STREAM_TOCLIENT) || + ssn->data_first_seen_dir != STREAM_TOSERVER) { + printf("failure 4\n"); + goto end; + } + + /* rubbish response */ + uint8_t response[] = { + 0x58, 0x54, 0x54, 0x50, 0x2f, 0x31, 0x2e, 0x31, + 0x20, 0x32, 0x30, 0x30, 0x20, 0x4f, 0x4b, 0x0d, + 0x0a, 0x44, 0x61, 0x74, 0x65, 0x3a, 0x20, 0x46, + 0x72, 0x69, 0x2c, 0x20, 0x32, 0x33, 0x20, 0x53, + 0x65, 0x70, 0x20, 0x32, 0x30, 0x31, 0x31, 0x20, + 0x30, 0x36, 0x3a, 0x32, 0x39, 0x3a, 0x33, 0x39, + 0x20, 0x47, 0x4d, 0x54, 0x0d, 0x0a, 0x53, 0x65, + 0x72, 0x76, 0x65, 0x72, 0x3a, 0x20, 0x41, 0x70, + 0x61, 0x63, 0x68, 0x65, 0x2f, 0x32, 0x2e, 0x32, + 0x2e, 0x31, 0x35, 0x20, 0x28, 0x55, 0x6e, 0x69, + 0x78, 0x29, 0x20, 0x44, 0x41, 0x56, 0x2f, 0x32, + 0x0d, 0x0a, 0x4c, 0x61, 0x73, 0x74, 0x2d, 0x4d, + 0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, 0x64, 0x3a, + 0x20, 0x54, 0x68, 0x75, 0x2c, 0x20, 0x30, 0x34, + 0x20, 0x4e, 0x6f, 0x76, 0x20, 0x32, 0x30, 0x31, + 0x30, 0x20, 0x31, 0x35, 0x3a, 0x30, 0x34, 0x3a, + 0x34, 0x36, 0x20, 0x47, 0x4d, 0x54, 0x0d, 0x0a, + 0x45, 0x54, 0x61, 0x67, 0x3a, 0x20, 0x22, 0x61, + 0x62, 0x38, 0x39, 0x36, 0x35, 0x2d, 0x32, 0x63, + 0x2d, 0x34, 0x39, 0x34, 0x33, 0x62, 0x37, 0x61, + 0x37, 0x66, 0x37, 0x66, 0x38, 0x30, 0x22, 0x0d, + 0x0a, 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x2d, + 0x52, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x3a, 0x20, + 0x62, 0x79, 0x74, 0x65, 0x73, 0x0d, 0x0a, 0x43, + 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x4c, + 0x65, 0x6e, 0x67, 0x74, 0x68, 0x3a, 0x20, 0x34, + 0x34, 0x0d, 0x0a, 0x43, 0x6f, 0x6e, 0x6e, 0x65, + 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x63, + 0x6c, 0x6f, 0x73, 0x65, 0x0d, 0x0a, 0x43, 0x6f, + 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x54, 0x79, + 0x70, 0x65, 0x3a, 0x20, 0x74, 0x65, 0x78, 0x74, + 0x2f, 0x68, 0x74, 0x6d, 0x6c, 0x0d, 0x0a, 0x58, + 0x2d, 0x50, 0x61, 0x64, 0x3a, 0x20, 0x61, 0x76, + 0x6f, 0x69, 0x64, 0x20, 0x62, 0x72, 0x6f, 0x77, + 0x73, 0x65, 0x72, 0x20, 0x62, 0x75, 0x67, 0x0d, + 0x0a, 0x0d, 0x0a, 0x3c, 0x68, 0x74, 0x6d, 0x6c, + 0x3e, 0x3c, 0x62, 0x6f, 0x64, 0x79, 0x3e, 0x3c, + 0x68, 0x31, 0x3e, 0x49, 0x74, 0x20, 0x77, 0x6f, + 0x72, 0x6b, 0x73, 0x21, 0x3c, 0x2f, 0x68, 0x31, + 0x3e, 0x3c, 0x2f, 0x62, 0x6f, 0x64, 0x79, 0x3e, + 0x3c, 0x2f, 0x68, 0x74, 0x6d, 0x6c, 0x3e }; + p->tcph->th_ack = htonl(88); + p->tcph->th_seq = htonl(1); + p->tcph->th_flags = TH_PUSH | TH_ACK; + p->flowflags = FLOW_PKT_TOCLIENT; + p->payload_len = sizeof(response); + p->payload = response; + if (StreamTcpPacket(&tv, p, stt, &pq) == -1) + goto end; + if (ssn->server.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED || + !(ssn->client.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED) || + f.alproto != ALPROTO_HTTP || + f.alproto_ts != ALPROTO_HTTP || + f.alproto_tc != ALPROTO_UNKNOWN || + f.data_al_so_far[0] != 0 || + f.data_al_so_far[1] != 0 || + f.flags & FLOW_NO_APPLAYER_INSPECTION || + !FLOW_IS_PM_DONE(&f, STREAM_TOSERVER) || FLOW_IS_PP_DONE(&f, STREAM_TOSERVER) || + FLOW_IS_PM_DONE(&f, STREAM_TOCLIENT) || FLOW_IS_PP_DONE(&f, STREAM_TOCLIENT) || + ssn->data_first_seen_dir != 0x01) { + printf("failure 5\n"); + goto end; + } + + /* response ack */ + p->tcph->th_ack = htonl(328); + p->tcph->th_seq = htonl(88); + p->tcph->th_flags = TH_ACK; + p->flowflags = FLOW_PKT_TOSERVER; + p->payload_len = 0; + p->payload = NULL; + if (StreamTcpPacket(&tv, p, stt, &pq) == -1) + goto end; + if (!(ssn->server.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED) || + !(ssn->client.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED) || + f.alproto != ALPROTO_HTTP || + f.alproto_ts != ALPROTO_HTTP || + f.alproto_tc != ALPROTO_UNKNOWN || + f.data_al_so_far[0] != 0 || + f.data_al_so_far[1] != 0 || + f.flags & FLOW_NO_APPLAYER_INSPECTION || + !FLOW_IS_PM_DONE(&f, STREAM_TOSERVER) || FLOW_IS_PP_DONE(&f, STREAM_TOSERVER) || + !FLOW_IS_PM_DONE(&f, STREAM_TOCLIENT) || !FLOW_IS_PP_DONE(&f, STREAM_TOCLIENT) || + ssn->data_first_seen_dir != 0x01) { + printf("failure 6\n"); + goto end; + } + + StreamTcpSessionClear(p->flow->protoctx); + + ret = 1; +end: + StreamTcpFreeConfig(TRUE); + SCFree(p); + return ret; +} + +/** + * \test GE -> RUBBISH(TC - PM AND PP NOT DONE) -> RUBBISH(TC - PM AND PP DONE). + */ +static int AppLayerTest04(void) +{ + Packet *p = SCMalloc(SIZE_OF_PACKET); + if (unlikely(p == NULL)) + return 0; + Flow f; + ThreadVars tv; + StreamTcpThread *stt = NULL; + TCPHdr tcph; + PacketQueue pq; + memset(&pq,0,sizeof(PacketQueue)); + memset(p, 0, SIZE_OF_PACKET); + memset (&f, 0, sizeof(Flow)); + memset(&tv, 0, sizeof (ThreadVars)); + StreamTcpThreadInit(&tv, NULL, (void **)&stt); + memset(&tcph, 0, sizeof (TCPHdr)); + + f.flags = FLOW_IPV4; + p->pkt = (uint8_t *)(p + 1); + p->flow = &f; + p->tcph = &tcph; + + int ret = 0; + + StreamTcpInitConfig(TRUE); + + /* handshake */ + tcph.th_win = htons(5480); + tcph.th_flags = TH_SYN; + p->flowflags = FLOW_PKT_TOSERVER; + p->payload_len = 0; + p->payload = NULL; + if (StreamTcpPacket(&tv, p, stt, &pq) == -1) + goto end; + + TcpSession *ssn = (TcpSession *)f.protoctx; + + if (ssn->server.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED || + ssn->client.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED || + f.alproto != ALPROTO_UNKNOWN || + f.alproto_ts != ALPROTO_UNKNOWN || + f.alproto_tc != ALPROTO_UNKNOWN || + f.data_al_so_far[0] != 0 || + f.data_al_so_far[1] != 0 || + f.flags & FLOW_NO_APPLAYER_INSPECTION || + FLOW_IS_PM_DONE(&f, STREAM_TOSERVER) || FLOW_IS_PP_DONE(&f, STREAM_TOSERVER) || + FLOW_IS_PM_DONE(&f, STREAM_TOCLIENT) || FLOW_IS_PP_DONE(&f, STREAM_TOCLIENT) || + ssn->data_first_seen_dir != 0) { + printf("failure 1\n"); + goto end; + } + + /* handshake */ + p->tcph->th_ack = htonl(1); + p->tcph->th_flags = TH_SYN | TH_ACK; + p->flowflags = FLOW_PKT_TOCLIENT; + p->payload_len = 0; + p->payload = NULL; + if (StreamTcpPacket(&tv, p, stt, &pq) == -1) + goto end; + if (ssn->server.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED || + ssn->client.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED || + f.alproto != ALPROTO_UNKNOWN || + f.alproto_ts != ALPROTO_UNKNOWN || + f.alproto_tc != ALPROTO_UNKNOWN || + f.data_al_so_far[0] != 0 || + f.data_al_so_far[1] != 0 || + f.flags & FLOW_NO_APPLAYER_INSPECTION || + FLOW_IS_PM_DONE(&f, STREAM_TOSERVER) || FLOW_IS_PP_DONE(&f, STREAM_TOSERVER) || + FLOW_IS_PM_DONE(&f, STREAM_TOCLIENT) || FLOW_IS_PP_DONE(&f, STREAM_TOCLIENT) || + ssn->data_first_seen_dir != 0) { + printf("failure 2\n"); + goto end; + } + + /* handshake */ + p->tcph->th_ack = htonl(1); + p->tcph->th_seq = htonl(1); + p->tcph->th_flags = TH_ACK; + p->flowflags = FLOW_PKT_TOSERVER; + p->payload_len = 0; + p->payload = NULL; + if (StreamTcpPacket(&tv, p, stt, &pq) == -1) + goto end; + if (ssn->server.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED || + ssn->client.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED || + f.alproto != ALPROTO_UNKNOWN || + f.alproto_ts != ALPROTO_UNKNOWN || + f.alproto_tc != ALPROTO_UNKNOWN || + f.data_al_so_far[0] != 0 || + f.data_al_so_far[1] != 0 || + f.flags & FLOW_NO_APPLAYER_INSPECTION || + FLOW_IS_PM_DONE(&f, STREAM_TOSERVER) || FLOW_IS_PP_DONE(&f, STREAM_TOSERVER) || + FLOW_IS_PM_DONE(&f, STREAM_TOCLIENT) || FLOW_IS_PP_DONE(&f, STREAM_TOCLIENT) || + ssn->data_first_seen_dir != 0) { + printf("failure 3\n"); + goto end; + } + + /* request */ + uint8_t request[] = { + 0x47, 0x45, 0x54, 0x20, 0x2f, 0x69, 0x6e, 0x64, + 0x65, 0x78, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0x20, + 0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, 0x2e, 0x30, + 0x0d, 0x0a, 0x48, 0x6f, 0x73, 0x74, 0x3a, 0x20, + 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x68, 0x6f, 0x73, + 0x74, 0x0d, 0x0a, 0x55, 0x73, 0x65, 0x72, 0x2d, + 0x41, 0x67, 0x65, 0x6e, 0x74, 0x3a, 0x20, 0x41, + 0x70, 0x61, 0x63, 0x68, 0x65, 0x42, 0x65, 0x6e, + 0x63, 0x68, 0x2f, 0x32, 0x2e, 0x33, 0x0d, 0x0a, + 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x3a, 0x20, + 0x2a, 0x2f, 0x2a, 0x0d, 0x0a, 0x0d, 0x0a }; + p->tcph->th_ack = htonl(1); + p->tcph->th_seq = htonl(1); + p->tcph->th_flags = TH_PUSH | TH_ACK; + p->flowflags = FLOW_PKT_TOSERVER; + p->payload_len = sizeof(request); + p->payload = request; + if (StreamTcpPacket(&tv, p, stt, &pq) == -1) + goto end; + if (ssn->server.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED || + ssn->client.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED || + f.alproto != ALPROTO_UNKNOWN || + f.alproto_ts != ALPROTO_UNKNOWN || + f.alproto_tc != ALPROTO_UNKNOWN || + f.data_al_so_far[0] != 0 || + f.data_al_so_far[1] != 0 || + f.flags & FLOW_NO_APPLAYER_INSPECTION || + FLOW_IS_PM_DONE(&f, STREAM_TOSERVER) || FLOW_IS_PP_DONE(&f, STREAM_TOSERVER) || + FLOW_IS_PM_DONE(&f, STREAM_TOCLIENT) || FLOW_IS_PP_DONE(&f, STREAM_TOCLIENT) || + ssn->data_first_seen_dir != STREAM_TOSERVER) { + printf("failure 4\n"); + goto end; + } + + /* partial response */ + uint8_t response1[] = { 0x58, 0x54, 0x54, 0x50, }; + p->tcph->th_ack = htonl(88); + p->tcph->th_seq = htonl(1); + p->tcph->th_flags = TH_PUSH | TH_ACK; + p->flowflags = FLOW_PKT_TOCLIENT; + p->payload_len = sizeof(response1); + p->payload = response1; + if (StreamTcpPacket(&tv, p, stt, &pq) == -1) + goto end; + if (ssn->server.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED || + !(ssn->client.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED) || + f.alproto != ALPROTO_HTTP || + f.alproto_ts != ALPROTO_HTTP || + f.alproto_tc != ALPROTO_UNKNOWN || + f.data_al_so_far[0] != 0 || + f.data_al_so_far[1] != 0 || + f.flags & FLOW_NO_APPLAYER_INSPECTION || + !FLOW_IS_PM_DONE(&f, STREAM_TOSERVER) || FLOW_IS_PP_DONE(&f, STREAM_TOSERVER) || + FLOW_IS_PM_DONE(&f, STREAM_TOCLIENT) || FLOW_IS_PP_DONE(&f, STREAM_TOCLIENT) || + ssn->data_first_seen_dir != 0x01) { + printf("failure 5\n"); + goto end; + } + + /* partial response ack */ + p->tcph->th_ack = htonl(5); + p->tcph->th_seq = htonl(88); + p->tcph->th_flags = TH_ACK; + p->flowflags = FLOW_PKT_TOSERVER; + p->payload_len = 0; + p->payload = NULL; + if (StreamTcpPacket(&tv, p, stt, &pq) == -1) + goto end; + if (ssn->server.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED || + !(ssn->client.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED) || + f.alproto != ALPROTO_HTTP || + f.alproto_ts != ALPROTO_HTTP || + f.alproto_tc != ALPROTO_UNKNOWN || + f.data_al_so_far[0] != 0 || + f.data_al_so_far[1] != 4 || + f.flags & FLOW_NO_APPLAYER_INSPECTION || + !FLOW_IS_PM_DONE(&f, STREAM_TOSERVER) || FLOW_IS_PP_DONE(&f, STREAM_TOSERVER) || + FLOW_IS_PM_DONE(&f, STREAM_TOCLIENT) || !FLOW_IS_PP_DONE(&f, STREAM_TOCLIENT) || + ssn->data_first_seen_dir != 0x01) { + printf("failure 6\n"); + goto end; + } + + /* remaining response */ + uint8_t response2[] = { + 0x2f, 0x31, 0x2e, 0x31, + 0x20, 0x32, 0x30, 0x30, 0x20, 0x4f, 0x4b, 0x0d, + 0x0a, 0x44, 0x61, 0x74, 0x65, 0x3a, 0x20, 0x46, + 0x72, 0x69, 0x2c, 0x20, 0x32, 0x33, 0x20, 0x53, + 0x65, 0x70, 0x20, 0x32, 0x30, 0x31, 0x31, 0x20, + 0x30, 0x36, 0x3a, 0x32, 0x39, 0x3a, 0x33, 0x39, + 0x20, 0x47, 0x4d, 0x54, 0x0d, 0x0a, 0x53, 0x65, + 0x72, 0x76, 0x65, 0x72, 0x3a, 0x20, 0x41, 0x70, + 0x61, 0x63, 0x68, 0x65, 0x2f, 0x32, 0x2e, 0x32, + 0x2e, 0x31, 0x35, 0x20, 0x28, 0x55, 0x6e, 0x69, + 0x78, 0x29, 0x20, 0x44, 0x41, 0x56, 0x2f, 0x32, + 0x0d, 0x0a, 0x4c, 0x61, 0x73, 0x74, 0x2d, 0x4d, + 0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, 0x64, 0x3a, + 0x20, 0x54, 0x68, 0x75, 0x2c, 0x20, 0x30, 0x34, + 0x20, 0x4e, 0x6f, 0x76, 0x20, 0x32, 0x30, 0x31, + 0x30, 0x20, 0x31, 0x35, 0x3a, 0x30, 0x34, 0x3a, + 0x34, 0x36, 0x20, 0x47, 0x4d, 0x54, 0x0d, 0x0a, + 0x45, 0x54, 0x61, 0x67, 0x3a, 0x20, 0x22, 0x61, + 0x62, 0x38, 0x39, 0x36, 0x35, 0x2d, 0x32, 0x63, + 0x2d, 0x34, 0x39, 0x34, 0x33, 0x62, 0x37, 0x61, + 0x37, 0x66, 0x37, 0x66, 0x38, 0x30, 0x22, 0x0d, + 0x0a, 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x2d, + 0x52, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x3a, 0x20, + 0x62, 0x79, 0x74, 0x65, 0x73, 0x0d, 0x0a, 0x43, + 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x4c, + 0x65, 0x6e, 0x67, 0x74, 0x68, 0x3a, 0x20, 0x34, + 0x34, 0x0d, 0x0a, 0x43, 0x6f, 0x6e, 0x6e, 0x65, + 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x63, + 0x6c, 0x6f, 0x73, 0x65, 0x0d, 0x0a, 0x43, 0x6f, + 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x54, 0x79, + 0x70, 0x65, 0x3a, 0x20, 0x74, 0x65, 0x78, 0x74, + 0x2f, 0x68, 0x74, 0x6d, 0x6c, 0x0d, 0x0a, 0x58, + 0x2d, 0x50, 0x61, 0x64, 0x3a, 0x20, 0x61, 0x76, + 0x6f, 0x69, 0x64, 0x20, 0x62, 0x72, 0x6f, 0x77, + 0x73, 0x65, 0x72, 0x20, 0x62, 0x75, 0x67, 0x0d, + 0x0a, 0x0d, 0x0a, 0x3c, 0x68, 0x74, 0x6d, 0x6c, + 0x3e, 0x3c, 0x62, 0x6f, 0x64, 0x79, 0x3e, 0x3c, + 0x68, 0x31, 0x3e, 0x49, 0x74, 0x20, 0x77, 0x6f, + 0x72, 0x6b, 0x73, 0x21, 0x3c, 0x2f, 0x68, 0x31, + 0x3e, 0x3c, 0x2f, 0x62, 0x6f, 0x64, 0x79, 0x3e, + 0x3c, 0x2f, 0x68, 0x74, 0x6d, 0x6c, 0x3e }; + p->tcph->th_ack = htonl(88); + p->tcph->th_seq = htonl(5); + p->tcph->th_flags = TH_PUSH | TH_ACK; + p->flowflags = FLOW_PKT_TOCLIENT; + p->payload_len = sizeof(response2); + p->payload = response2; + if (StreamTcpPacket(&tv, p, stt, &pq) == -1) + goto end; + if (ssn->server.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED || + !(ssn->client.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED) || + f.alproto != ALPROTO_HTTP || + f.alproto_ts != ALPROTO_HTTP || + f.alproto_tc != ALPROTO_UNKNOWN || + f.data_al_so_far[0] != 0 || + f.data_al_so_far[1] != 4 || + f.flags & FLOW_NO_APPLAYER_INSPECTION || + !FLOW_IS_PM_DONE(&f, STREAM_TOSERVER) || FLOW_IS_PP_DONE(&f, STREAM_TOSERVER) || + FLOW_IS_PM_DONE(&f, STREAM_TOCLIENT) || !FLOW_IS_PP_DONE(&f, STREAM_TOCLIENT) || + ssn->data_first_seen_dir != 0x01) { + printf("failure 7\n"); + goto end; + } + + /* response ack */ + p->tcph->th_ack = htonl(328); + p->tcph->th_seq = htonl(88); + p->tcph->th_flags = TH_ACK; + p->flowflags = FLOW_PKT_TOSERVER; + p->payload_len = 0; + p->payload = NULL; + if (StreamTcpPacket(&tv, p, stt, &pq) == -1) + goto end; + if (!(ssn->server.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED) || + !(ssn->client.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED) || + f.alproto != ALPROTO_HTTP || + f.alproto_ts != ALPROTO_HTTP || + f.alproto_tc != ALPROTO_UNKNOWN || + f.data_al_so_far[0] != 0 || + f.data_al_so_far[1] != 0 || + f.flags & FLOW_NO_APPLAYER_INSPECTION || + !FLOW_IS_PM_DONE(&f, STREAM_TOSERVER) || FLOW_IS_PP_DONE(&f, STREAM_TOSERVER) || + !FLOW_IS_PM_DONE(&f, STREAM_TOCLIENT) || !FLOW_IS_PP_DONE(&f, STREAM_TOCLIENT) || + ssn->data_first_seen_dir != 0x01) { + printf("failure 8\n"); + goto end; + } + + StreamTcpSessionClear(p->flow->protoctx); + + ret = 1; +end: + StreamTcpFreeConfig(TRUE); + SCFree(p); + return ret; +} + +/** + * \test RUBBISH -> HTTP/1.1 + */ +static int AppLayerTest05(void) +{ + Packet *p = SCMalloc(SIZE_OF_PACKET); + if (unlikely(p == NULL)) + return 0; + Flow f; + ThreadVars tv; + StreamTcpThread *stt = NULL; + TCPHdr tcph; + PacketQueue pq; + memset(&pq,0,sizeof(PacketQueue)); + memset(p, 0, SIZE_OF_PACKET); + memset (&f, 0, sizeof(Flow)); + memset(&tv, 0, sizeof (ThreadVars)); + StreamTcpThreadInit(&tv, NULL, (void **)&stt); + memset(&tcph, 0, sizeof (TCPHdr)); + + f.flags = FLOW_IPV4; + p->pkt = (uint8_t *)(p + 1); + p->flow = &f; + p->tcph = &tcph; + + int ret = 0; + + StreamTcpInitConfig(TRUE); + + tcph.th_win = htons(5480); + tcph.th_flags = TH_SYN; + p->flowflags = FLOW_PKT_TOSERVER; + p->payload_len = 0; + p->payload = NULL; + if (StreamTcpPacket(&tv, p, stt, &pq) == -1) + goto end; + + TcpSession *ssn = (TcpSession *)f.protoctx; + + /* handshake */ + if (ssn->server.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED || + ssn->client.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED || + f.alproto != ALPROTO_UNKNOWN || + f.alproto_ts != ALPROTO_UNKNOWN || + f.alproto_tc != ALPROTO_UNKNOWN || + f.data_al_so_far[0] != 0 || + f.data_al_so_far[1] != 0 || + f.flags & FLOW_NO_APPLAYER_INSPECTION || + FLOW_IS_PM_DONE(&f, STREAM_TOSERVER) || FLOW_IS_PP_DONE(&f, STREAM_TOSERVER) || + FLOW_IS_PM_DONE(&f, STREAM_TOCLIENT) || FLOW_IS_PP_DONE(&f, STREAM_TOCLIENT) || + ssn->data_first_seen_dir != 0) { + printf("failure 1\n"); + goto end; + } + + + /* handshake */ + p->tcph->th_ack = htonl(1); + p->tcph->th_flags = TH_SYN | TH_ACK; + p->flowflags = FLOW_PKT_TOCLIENT; + p->payload_len = 0; + p->payload = NULL; + if (StreamTcpPacket(&tv, p, stt, &pq) == -1) + goto end; + if (ssn->server.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED || + ssn->client.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED || + f.alproto != ALPROTO_UNKNOWN || + f.alproto_ts != ALPROTO_UNKNOWN || + f.alproto_tc != ALPROTO_UNKNOWN || + f.data_al_so_far[0] != 0 || + f.data_al_so_far[1] != 0 || + f.flags & FLOW_NO_APPLAYER_INSPECTION || + FLOW_IS_PM_DONE(&f, STREAM_TOSERVER) || FLOW_IS_PP_DONE(&f, STREAM_TOSERVER) || + FLOW_IS_PM_DONE(&f, STREAM_TOCLIENT) || FLOW_IS_PP_DONE(&f, STREAM_TOCLIENT) || + ssn->data_first_seen_dir != 0) { + printf("failure 2\n"); + goto end; + } + + /* handshake */ + p->tcph->th_ack = htonl(1); + p->tcph->th_seq = htonl(1); + p->tcph->th_flags = TH_ACK; + p->flowflags = FLOW_PKT_TOSERVER; + p->payload_len = 0; + p->payload = NULL; + if (StreamTcpPacket(&tv, p, stt, &pq) == -1) + goto end; + if (ssn->server.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED || + ssn->client.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED || + f.alproto != ALPROTO_UNKNOWN || + f.alproto_ts != ALPROTO_UNKNOWN || + f.alproto_tc != ALPROTO_UNKNOWN || + f.data_al_so_far[0] != 0 || + f.data_al_so_far[1] != 0 || + f.flags & FLOW_NO_APPLAYER_INSPECTION || + FLOW_IS_PM_DONE(&f, STREAM_TOSERVER) || FLOW_IS_PP_DONE(&f, STREAM_TOSERVER) || + FLOW_IS_PM_DONE(&f, STREAM_TOCLIENT) || FLOW_IS_PP_DONE(&f, STREAM_TOCLIENT) || + ssn->data_first_seen_dir != 0) { + printf("failure 3\n"); + goto end; + } + + /* full request */ + uint8_t request[] = { + 0x48, 0x45, 0x54, 0x20, 0x2f, 0x69, 0x6e, 0x64, + 0x65, 0x78, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0x20, + 0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, 0x2e, 0x30, + 0x0d, 0x0a, 0x48, 0x6f, 0x73, 0x74, 0x3a, 0x20, + 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x68, 0x6f, 0x73, + 0x74, 0x0d, 0x0a, 0x55, 0x73, 0x65, 0x72, 0x2d, + 0x41, 0x67, 0x65, 0x6e, 0x74, 0x3a, 0x20, 0x41, + 0x70, 0x61, 0x63, 0x68, 0x65, 0x42, 0x65, 0x6e, + 0x63, 0x68, 0x2f, 0x32, 0x2e, 0x33, 0x0d, 0x0a, + 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x3a, 0x20, + 0x2a, 0x2f, 0x2a, 0x0d, 0x0a, 0x0d, 0x0a }; + p->tcph->th_ack = htonl(1); + p->tcph->th_seq = htonl(1); + p->tcph->th_flags = TH_PUSH | TH_ACK; + p->flowflags = FLOW_PKT_TOSERVER; + p->payload_len = sizeof(request); + p->payload = request; + if (StreamTcpPacket(&tv, p, stt, &pq) == -1) + goto end; + if (ssn->server.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED || + ssn->client.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED || + f.alproto != ALPROTO_UNKNOWN || + f.alproto_ts != ALPROTO_UNKNOWN || + f.alproto_tc != ALPROTO_UNKNOWN || + f.data_al_so_far[0] != 0 || + f.data_al_so_far[1] != 0 || + f.flags & FLOW_NO_APPLAYER_INSPECTION || + FLOW_IS_PM_DONE(&f, STREAM_TOSERVER) || FLOW_IS_PP_DONE(&f, STREAM_TOSERVER) || + FLOW_IS_PM_DONE(&f, STREAM_TOCLIENT) || FLOW_IS_PP_DONE(&f, STREAM_TOCLIENT) || + ssn->data_first_seen_dir != STREAM_TOSERVER) { + printf("failure 4\n"); + goto end; + } + + /* full response - request ack */ + uint8_t response[] = { + 0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, 0x2e, 0x31, + 0x20, 0x32, 0x30, 0x30, 0x20, 0x4f, 0x4b, 0x0d, + 0x0a, 0x44, 0x61, 0x74, 0x65, 0x3a, 0x20, 0x46, + 0x72, 0x69, 0x2c, 0x20, 0x32, 0x33, 0x20, 0x53, + 0x65, 0x70, 0x20, 0x32, 0x30, 0x31, 0x31, 0x20, + 0x30, 0x36, 0x3a, 0x32, 0x39, 0x3a, 0x33, 0x39, + 0x20, 0x47, 0x4d, 0x54, 0x0d, 0x0a, 0x53, 0x65, + 0x72, 0x76, 0x65, 0x72, 0x3a, 0x20, 0x41, 0x70, + 0x61, 0x63, 0x68, 0x65, 0x2f, 0x32, 0x2e, 0x32, + 0x2e, 0x31, 0x35, 0x20, 0x28, 0x55, 0x6e, 0x69, + 0x78, 0x29, 0x20, 0x44, 0x41, 0x56, 0x2f, 0x32, + 0x0d, 0x0a, 0x4c, 0x61, 0x73, 0x74, 0x2d, 0x4d, + 0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, 0x64, 0x3a, + 0x20, 0x54, 0x68, 0x75, 0x2c, 0x20, 0x30, 0x34, + 0x20, 0x4e, 0x6f, 0x76, 0x20, 0x32, 0x30, 0x31, + 0x30, 0x20, 0x31, 0x35, 0x3a, 0x30, 0x34, 0x3a, + 0x34, 0x36, 0x20, 0x47, 0x4d, 0x54, 0x0d, 0x0a, + 0x45, 0x54, 0x61, 0x67, 0x3a, 0x20, 0x22, 0x61, + 0x62, 0x38, 0x39, 0x36, 0x35, 0x2d, 0x32, 0x63, + 0x2d, 0x34, 0x39, 0x34, 0x33, 0x62, 0x37, 0x61, + 0x37, 0x66, 0x37, 0x66, 0x38, 0x30, 0x22, 0x0d, + 0x0a, 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x2d, + 0x52, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x3a, 0x20, + 0x62, 0x79, 0x74, 0x65, 0x73, 0x0d, 0x0a, 0x43, + 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x4c, + 0x65, 0x6e, 0x67, 0x74, 0x68, 0x3a, 0x20, 0x34, + 0x34, 0x0d, 0x0a, 0x43, 0x6f, 0x6e, 0x6e, 0x65, + 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x63, + 0x6c, 0x6f, 0x73, 0x65, 0x0d, 0x0a, 0x43, 0x6f, + 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x54, 0x79, + 0x70, 0x65, 0x3a, 0x20, 0x74, 0x65, 0x78, 0x74, + 0x2f, 0x68, 0x74, 0x6d, 0x6c, 0x0d, 0x0a, 0x58, + 0x2d, 0x50, 0x61, 0x64, 0x3a, 0x20, 0x61, 0x76, + 0x6f, 0x69, 0x64, 0x20, 0x62, 0x72, 0x6f, 0x77, + 0x73, 0x65, 0x72, 0x20, 0x62, 0x75, 0x67, 0x0d, + 0x0a, 0x0d, 0x0a, 0x3c, 0x68, 0x74, 0x6d, 0x6c, + 0x3e, 0x3c, 0x62, 0x6f, 0x64, 0x79, 0x3e, 0x3c, + 0x68, 0x31, 0x3e, 0x49, 0x74, 0x20, 0x77, 0x6f, + 0x72, 0x6b, 0x73, 0x21, 0x3c, 0x2f, 0x68, 0x31, + 0x3e, 0x3c, 0x2f, 0x62, 0x6f, 0x64, 0x79, 0x3e, + 0x3c, 0x2f, 0x68, 0x74, 0x6d, 0x6c, 0x3e }; + p->tcph->th_ack = htonl(88); + p->tcph->th_seq = htonl(1); + p->tcph->th_flags = TH_PUSH | TH_ACK; + p->flowflags = FLOW_PKT_TOCLIENT; + p->payload_len = sizeof(response); + p->payload = response; + if (StreamTcpPacket(&tv, p, stt, &pq) == -1) + goto end; + if (ssn->server.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED || + ssn->client.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED || + f.alproto != ALPROTO_UNKNOWN || + f.alproto_ts != ALPROTO_UNKNOWN || + f.alproto_tc != ALPROTO_UNKNOWN || + f.data_al_so_far[0] != 0 || + f.data_al_so_far[1] != 0 || + f.flags & FLOW_NO_APPLAYER_INSPECTION || + !FLOW_IS_PM_DONE(&f, STREAM_TOSERVER) || !FLOW_IS_PP_DONE(&f, STREAM_TOSERVER) || + FLOW_IS_PM_DONE(&f, STREAM_TOCLIENT) || FLOW_IS_PP_DONE(&f, STREAM_TOCLIENT) || + ssn->data_first_seen_dir != STREAM_TOSERVER) { + printf("failure 5\n"); + goto end; + } + + /* response ack */ + p->tcph->th_ack = htonl(328); + p->tcph->th_seq = htonl(88); + p->tcph->th_flags = TH_ACK; + p->flowflags = FLOW_PKT_TOSERVER; + p->payload_len = 0; + p->payload = NULL; + if (StreamTcpPacket(&tv, p, stt, &pq) == -1) + goto end; + if (!(ssn->server.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED) || + !(ssn->client.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED) || + f.alproto != ALPROTO_HTTP || + f.alproto_ts != ALPROTO_UNKNOWN || + f.alproto_tc != ALPROTO_HTTP || + f.data_al_so_far[0] != 0 || + f.data_al_so_far[1] != 0 || + f.flags & FLOW_NO_APPLAYER_INSPECTION || + !FLOW_IS_PM_DONE(&f, STREAM_TOSERVER) || !FLOW_IS_PP_DONE(&f, STREAM_TOSERVER) || + !FLOW_IS_PM_DONE(&f, STREAM_TOCLIENT) || FLOW_IS_PP_DONE(&f, STREAM_TOCLIENT) || + ssn->data_first_seen_dir != 0x01) { + printf("failure 6\n"); + goto end; + } + + StreamTcpSessionClear(p->flow->protoctx); + + ret = 1; +end: + StreamTcpFreeConfig(TRUE); + SCFree(p); + return ret; +} + +/** + * \test HTTP/1.1 -> GET + */ +static int AppLayerTest06(void) +{ + Packet *p = SCMalloc(SIZE_OF_PACKET); + if (unlikely(p == NULL)) + return 0; + Flow f; + ThreadVars tv; + StreamTcpThread *stt = NULL; + TCPHdr tcph; + PacketQueue pq; + memset(&pq,0,sizeof(PacketQueue)); + memset(p, 0, SIZE_OF_PACKET); + memset (&f, 0, sizeof(Flow)); + memset(&tv, 0, sizeof (ThreadVars)); + StreamTcpThreadInit(&tv, NULL, (void **)&stt); + memset(&tcph, 0, sizeof (TCPHdr)); + + f.flags = FLOW_IPV4; + p->pkt = (uint8_t *)(p + 1); + p->flow = &f; + p->tcph = &tcph; + + int ret = 0; + + StreamTcpInitConfig(TRUE); + + tcph.th_win = htons(5480); + tcph.th_flags = TH_SYN; + p->flowflags = FLOW_PKT_TOSERVER; + p->payload_len = 0; + p->payload = NULL; + if (StreamTcpPacket(&tv, p, stt, &pq) == -1) + goto end; + + TcpSession *ssn = (TcpSession *)f.protoctx; + + /* handshake */ + if (ssn->server.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED || + ssn->client.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED || + f.alproto != ALPROTO_UNKNOWN || + f.alproto_ts != ALPROTO_UNKNOWN || + f.alproto_tc != ALPROTO_UNKNOWN || + f.data_al_so_far[0] != 0 || + f.data_al_so_far[1] != 0 || + f.flags & FLOW_NO_APPLAYER_INSPECTION || + FLOW_IS_PM_DONE(&f, STREAM_TOSERVER) || FLOW_IS_PP_DONE(&f, STREAM_TOSERVER) || + FLOW_IS_PM_DONE(&f, STREAM_TOCLIENT) || FLOW_IS_PP_DONE(&f, STREAM_TOCLIENT) || + ssn->data_first_seen_dir != 0) { + printf("failure 1\n"); + goto end; + } + + + /* handshake */ + p->tcph->th_ack = htonl(1); + p->tcph->th_flags = TH_SYN | TH_ACK; + p->flowflags = FLOW_PKT_TOCLIENT; + p->payload_len = 0; + p->payload = NULL; + if (StreamTcpPacket(&tv, p, stt, &pq) == -1) + goto end; + if (ssn->server.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED || + ssn->client.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED || + f.alproto != ALPROTO_UNKNOWN || + f.alproto_ts != ALPROTO_UNKNOWN || + f.alproto_tc != ALPROTO_UNKNOWN || + f.data_al_so_far[0] != 0 || + f.data_al_so_far[1] != 0 || + f.flags & FLOW_NO_APPLAYER_INSPECTION || + FLOW_IS_PM_DONE(&f, STREAM_TOSERVER) || FLOW_IS_PP_DONE(&f, STREAM_TOSERVER) || + FLOW_IS_PM_DONE(&f, STREAM_TOCLIENT) || FLOW_IS_PP_DONE(&f, STREAM_TOCLIENT) || + ssn->data_first_seen_dir != 0) { + printf("failure 2\n"); + goto end; + } + + /* handshake */ + p->tcph->th_ack = htonl(1); + p->tcph->th_seq = htonl(1); + p->tcph->th_flags = TH_ACK; + p->flowflags = FLOW_PKT_TOSERVER; + p->payload_len = 0; + p->payload = NULL; + if (StreamTcpPacket(&tv, p, stt, &pq) == -1) + goto end; + if (ssn->server.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED || + ssn->client.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED || + f.alproto != ALPROTO_UNKNOWN || + f.alproto_ts != ALPROTO_UNKNOWN || + f.alproto_tc != ALPROTO_UNKNOWN || + f.data_al_so_far[0] != 0 || + f.data_al_so_far[1] != 0 || + f.flags & FLOW_NO_APPLAYER_INSPECTION || + FLOW_IS_PM_DONE(&f, STREAM_TOSERVER) || FLOW_IS_PP_DONE(&f, STREAM_TOSERVER) || + FLOW_IS_PM_DONE(&f, STREAM_TOCLIENT) || FLOW_IS_PP_DONE(&f, STREAM_TOCLIENT) || + ssn->data_first_seen_dir != 0) { + printf("failure 3\n"); + goto end; + } + + /* full response - request ack */ + uint8_t response[] = { + 0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, 0x2e, 0x31, + 0x20, 0x32, 0x30, 0x30, 0x20, 0x4f, 0x4b, 0x0d, + 0x0a, 0x44, 0x61, 0x74, 0x65, 0x3a, 0x20, 0x46, + 0x72, 0x69, 0x2c, 0x20, 0x32, 0x33, 0x20, 0x53, + 0x65, 0x70, 0x20, 0x32, 0x30, 0x31, 0x31, 0x20, + 0x30, 0x36, 0x3a, 0x32, 0x39, 0x3a, 0x33, 0x39, + 0x20, 0x47, 0x4d, 0x54, 0x0d, 0x0a, 0x53, 0x65, + 0x72, 0x76, 0x65, 0x72, 0x3a, 0x20, 0x41, 0x70, + 0x61, 0x63, 0x68, 0x65, 0x2f, 0x32, 0x2e, 0x32, + 0x2e, 0x31, 0x35, 0x20, 0x28, 0x55, 0x6e, 0x69, + 0x78, 0x29, 0x20, 0x44, 0x41, 0x56, 0x2f, 0x32, + 0x0d, 0x0a, 0x4c, 0x61, 0x73, 0x74, 0x2d, 0x4d, + 0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, 0x64, 0x3a, + 0x20, 0x54, 0x68, 0x75, 0x2c, 0x20, 0x30, 0x34, + 0x20, 0x4e, 0x6f, 0x76, 0x20, 0x32, 0x30, 0x31, + 0x30, 0x20, 0x31, 0x35, 0x3a, 0x30, 0x34, 0x3a, + 0x34, 0x36, 0x20, 0x47, 0x4d, 0x54, 0x0d, 0x0a, + 0x45, 0x54, 0x61, 0x67, 0x3a, 0x20, 0x22, 0x61, + 0x62, 0x38, 0x39, 0x36, 0x35, 0x2d, 0x32, 0x63, + 0x2d, 0x34, 0x39, 0x34, 0x33, 0x62, 0x37, 0x61, + 0x37, 0x66, 0x37, 0x66, 0x38, 0x30, 0x22, 0x0d, + 0x0a, 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x2d, + 0x52, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x3a, 0x20, + 0x62, 0x79, 0x74, 0x65, 0x73, 0x0d, 0x0a, 0x43, + 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x4c, + 0x65, 0x6e, 0x67, 0x74, 0x68, 0x3a, 0x20, 0x34, + 0x34, 0x0d, 0x0a, 0x43, 0x6f, 0x6e, 0x6e, 0x65, + 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x63, + 0x6c, 0x6f, 0x73, 0x65, 0x0d, 0x0a, 0x43, 0x6f, + 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x54, 0x79, + 0x70, 0x65, 0x3a, 0x20, 0x74, 0x65, 0x78, 0x74, + 0x2f, 0x68, 0x74, 0x6d, 0x6c, 0x0d, 0x0a, 0x58, + 0x2d, 0x50, 0x61, 0x64, 0x3a, 0x20, 0x61, 0x76, + 0x6f, 0x69, 0x64, 0x20, 0x62, 0x72, 0x6f, 0x77, + 0x73, 0x65, 0x72, 0x20, 0x62, 0x75, 0x67, 0x0d, + 0x0a, 0x0d, 0x0a, 0x3c, 0x68, 0x74, 0x6d, 0x6c, + 0x3e, 0x3c, 0x62, 0x6f, 0x64, 0x79, 0x3e, 0x3c, + 0x68, 0x31, 0x3e, 0x49, 0x74, 0x20, 0x77, 0x6f, + 0x72, 0x6b, 0x73, 0x21, 0x3c, 0x2f, 0x68, 0x31, + 0x3e, 0x3c, 0x2f, 0x62, 0x6f, 0x64, 0x79, 0x3e, + 0x3c, 0x2f, 0x68, 0x74, 0x6d, 0x6c, 0x3e }; + p->tcph->th_ack = htonl(1); + p->tcph->th_seq = htonl(1); + p->tcph->th_flags = TH_PUSH | TH_ACK; + p->flowflags = FLOW_PKT_TOCLIENT; + p->payload_len = sizeof(response); + p->payload = response; + if (StreamTcpPacket(&tv, p, stt, &pq) == -1) + goto end; + if (ssn->server.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED || + ssn->client.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED || + f.alproto != ALPROTO_UNKNOWN || + f.alproto_ts != ALPROTO_UNKNOWN || + f.alproto_tc != ALPROTO_UNKNOWN || + f.data_al_so_far[0] != 0 || + f.data_al_so_far[1] != 0 || + f.flags & FLOW_NO_APPLAYER_INSPECTION || + FLOW_IS_PM_DONE(&f, STREAM_TOSERVER) || FLOW_IS_PP_DONE(&f, STREAM_TOSERVER) || + FLOW_IS_PM_DONE(&f, STREAM_TOCLIENT) || FLOW_IS_PP_DONE(&f, STREAM_TOCLIENT) || + ssn->data_first_seen_dir != STREAM_TOCLIENT) { + printf("failure 4\n"); + goto end; + } + + /* full request - response ack*/ + uint8_t request[] = { + 0x47, 0x45, 0x54, 0x20, 0x2f, 0x69, 0x6e, 0x64, + 0x65, 0x78, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0x20, + 0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, 0x2e, 0x30, + 0x0d, 0x0a, 0x48, 0x6f, 0x73, 0x74, 0x3a, 0x20, + 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x68, 0x6f, 0x73, + 0x74, 0x0d, 0x0a, 0x55, 0x73, 0x65, 0x72, 0x2d, + 0x41, 0x67, 0x65, 0x6e, 0x74, 0x3a, 0x20, 0x41, + 0x70, 0x61, 0x63, 0x68, 0x65, 0x42, 0x65, 0x6e, + 0x63, 0x68, 0x2f, 0x32, 0x2e, 0x33, 0x0d, 0x0a, + 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x3a, 0x20, + 0x2a, 0x2f, 0x2a, 0x0d, 0x0a, 0x0d, 0x0a }; + p->tcph->th_ack = htonl(328); + p->tcph->th_seq = htonl(1); + p->tcph->th_flags = TH_PUSH | TH_ACK; + p->flowflags = FLOW_PKT_TOSERVER; + p->payload_len = sizeof(request); + p->payload = request; + if (StreamTcpPacket(&tv, p, stt, &pq) == -1) + goto end; + if (!(ssn->server.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED) || + !(ssn->client.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED) || + f.alproto != ALPROTO_UNKNOWN || + f.alproto_ts != ALPROTO_UNKNOWN || + f.alproto_tc != ALPROTO_UNKNOWN || + f.data_al_so_far[0] != 0 || + f.data_al_so_far[1] != 0 || + !(f.flags & FLOW_NO_APPLAYER_INSPECTION) || + FLOW_IS_PM_DONE(&f, STREAM_TOSERVER) || FLOW_IS_PP_DONE(&f, STREAM_TOSERVER) || + !FLOW_IS_PM_DONE(&f, STREAM_TOCLIENT) || FLOW_IS_PP_DONE(&f, STREAM_TOCLIENT) || + ssn->data_first_seen_dir != 0x01) { + printf("failure 5\n"); + goto end; + } + + StreamTcpSessionClear(p->flow->protoctx); + + ret = 1; +end: + StreamTcpFreeConfig(TRUE); + SCFree(p); + return ret; +} + +/** + * \test GET -> DCERPC + */ +static int AppLayerTest07(void) +{ + Packet *p = SCMalloc(SIZE_OF_PACKET); + if (unlikely(p == NULL)) + return 0; + Flow f; + ThreadVars tv; + StreamTcpThread *stt = NULL; + TCPHdr tcph; + PacketQueue pq; + memset(&pq,0,sizeof(PacketQueue)); + memset(p, 0, SIZE_OF_PACKET); + memset (&f, 0, sizeof(Flow)); + memset(&tv, 0, sizeof (ThreadVars)); + StreamTcpThreadInit(&tv, NULL, (void **)&stt); + memset(&tcph, 0, sizeof (TCPHdr)); + + f.flags = FLOW_IPV4; + p->pkt = (uint8_t *)(p + 1); + p->flow = &f; + p->tcph = &tcph; + + int ret = 0; + + StreamTcpInitConfig(TRUE); + + tcph.th_win = htons(5480); + tcph.th_flags = TH_SYN; + p->flowflags = FLOW_PKT_TOSERVER; + p->payload_len = 0; + p->payload = NULL; + if (StreamTcpPacket(&tv, p, stt, &pq) == -1) + goto end; + + TcpSession *ssn = (TcpSession *)f.protoctx; + + /* handshake */ + if (ssn->server.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED || + ssn->client.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED || + f.alproto != ALPROTO_UNKNOWN || + f.alproto_ts != ALPROTO_UNKNOWN || + f.alproto_tc != ALPROTO_UNKNOWN || + f.data_al_so_far[0] != 0 || + f.data_al_so_far[1] != 0 || + f.flags & FLOW_NO_APPLAYER_INSPECTION || + FLOW_IS_PM_DONE(&f, STREAM_TOSERVER) || FLOW_IS_PP_DONE(&f, STREAM_TOSERVER) || + FLOW_IS_PM_DONE(&f, STREAM_TOCLIENT) || FLOW_IS_PP_DONE(&f, STREAM_TOCLIENT) || + ssn->data_first_seen_dir != 0) { + printf("failure 1\n"); + goto end; + } + + + /* handshake */ + p->tcph->th_ack = htonl(1); + p->tcph->th_flags = TH_SYN | TH_ACK; + p->flowflags = FLOW_PKT_TOCLIENT; + p->payload_len = 0; + p->payload = NULL; + if (StreamTcpPacket(&tv, p, stt, &pq) == -1) + goto end; + if (ssn->server.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED || + ssn->client.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED || + f.alproto != ALPROTO_UNKNOWN || + f.alproto_ts != ALPROTO_UNKNOWN || + f.alproto_tc != ALPROTO_UNKNOWN || + f.data_al_so_far[0] != 0 || + f.data_al_so_far[1] != 0 || + f.flags & FLOW_NO_APPLAYER_INSPECTION || + FLOW_IS_PM_DONE(&f, STREAM_TOSERVER) || FLOW_IS_PP_DONE(&f, STREAM_TOSERVER) || + FLOW_IS_PM_DONE(&f, STREAM_TOCLIENT) || FLOW_IS_PP_DONE(&f, STREAM_TOCLIENT) || + ssn->data_first_seen_dir != 0) { + printf("failure 2\n"); + goto end; + } + + /* handshake */ + p->tcph->th_ack = htonl(1); + p->tcph->th_seq = htonl(1); + p->tcph->th_flags = TH_ACK; + p->flowflags = FLOW_PKT_TOSERVER; + p->payload_len = 0; + p->payload = NULL; + if (StreamTcpPacket(&tv, p, stt, &pq) == -1) + goto end; + if (ssn->server.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED || + ssn->client.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED || + f.alproto != ALPROTO_UNKNOWN || + f.alproto_ts != ALPROTO_UNKNOWN || + f.alproto_tc != ALPROTO_UNKNOWN || + f.data_al_so_far[0] != 0 || + f.data_al_so_far[1] != 0 || + f.flags & FLOW_NO_APPLAYER_INSPECTION || + FLOW_IS_PM_DONE(&f, STREAM_TOSERVER) || FLOW_IS_PP_DONE(&f, STREAM_TOSERVER) || + FLOW_IS_PM_DONE(&f, STREAM_TOCLIENT) || FLOW_IS_PP_DONE(&f, STREAM_TOCLIENT) || + ssn->data_first_seen_dir != 0) { + printf("failure 3\n"); + goto end; + } + + /* full request */ + uint8_t request[] = { + 0x47, 0x45, 0x54, 0x20, 0x2f, 0x69, 0x6e, 0x64, + 0x65, 0x78, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0x20, + 0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, 0x2e, 0x30, + 0x0d, 0x0a, 0x48, 0x6f, 0x73, 0x74, 0x3a, 0x20, + 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x68, 0x6f, 0x73, + 0x74, 0x0d, 0x0a, 0x55, 0x73, 0x65, 0x72, 0x2d, + 0x41, 0x67, 0x65, 0x6e, 0x74, 0x3a, 0x20, 0x41, + 0x70, 0x61, 0x63, 0x68, 0x65, 0x42, 0x65, 0x6e, + 0x63, 0x68, 0x2f, 0x32, 0x2e, 0x33, 0x0d, 0x0a, + 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x3a, 0x20, + 0x2a, 0x2f, 0x2a, 0x0d, 0x0a, 0x0d, 0x0a }; + p->tcph->th_ack = htonl(1); + p->tcph->th_seq = htonl(1); + p->tcph->th_flags = TH_PUSH | TH_ACK; + p->flowflags = FLOW_PKT_TOSERVER; + p->payload_len = sizeof(request); + p->payload = request; + if (StreamTcpPacket(&tv, p, stt, &pq) == -1) + goto end; + if (ssn->server.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED || + ssn->client.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED || + f.alproto != ALPROTO_UNKNOWN || + f.alproto_ts != ALPROTO_UNKNOWN || + f.alproto_tc != ALPROTO_UNKNOWN || + f.data_al_so_far[0] != 0 || + f.data_al_so_far[1] != 0 || + f.flags & FLOW_NO_APPLAYER_INSPECTION || + FLOW_IS_PM_DONE(&f, STREAM_TOSERVER) || FLOW_IS_PP_DONE(&f, STREAM_TOSERVER) || + FLOW_IS_PM_DONE(&f, STREAM_TOCLIENT) || FLOW_IS_PP_DONE(&f, STREAM_TOCLIENT) || + ssn->data_first_seen_dir != STREAM_TOSERVER) { + printf("failure 4\n"); + goto end; + } + + /* full response - request ack */ + uint8_t response[] = { + 0x05, 0x00, 0x4d, 0x42, 0x2f, 0x31, 0x2e, 0x31, + 0x20, 0x32, 0x30, 0x30, 0x20, 0x4f, 0x4b, 0x0d, + 0x0a, 0x44, 0x61, 0x74, 0x65, 0x3a, 0x20, 0x46, + 0x72, 0x69, 0x2c, 0x20, 0x32, 0x33, 0x20, 0x53, + 0x65, 0x70, 0x20, 0x32, 0x30, 0x31, 0x31, 0x20, + 0x30, 0x36, 0x3a, 0x32, 0x39, 0x3a, 0x33, 0x39, + 0x20, 0x47, 0x4d, 0x54, 0x0d, 0x0a, 0x53, 0x65, + 0x72, 0x76, 0x65, 0x72, 0x3a, 0x20, 0x41, 0x70, + 0x61, 0x63, 0x68, 0x65, 0x2f, 0x32, 0x2e, 0x32, + 0x2e, 0x31, 0x35, 0x20, 0x28, 0x55, 0x6e, 0x69, + 0x78, 0x29, 0x20, 0x44, 0x41, 0x56, 0x2f, 0x32, + 0x0d, 0x0a, 0x4c, 0x61, 0x73, 0x74, 0x2d, 0x4d, + 0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, 0x64, 0x3a, + 0x20, 0x54, 0x68, 0x75, 0x2c, 0x20, 0x30, 0x34, + 0x20, 0x4e, 0x6f, 0x76, 0x20, 0x32, 0x30, 0x31, + 0x30, 0x20, 0x31, 0x35, 0x3a, 0x30, 0x34, 0x3a, + 0x34, 0x36, 0x20, 0x47, 0x4d, 0x54, 0x0d, 0x0a, + 0x45, 0x54, 0x61, 0x67, 0x3a, 0x20, 0x22, 0x61, + 0x62, 0x38, 0x39, 0x36, 0x35, 0x2d, 0x32, 0x63, + 0x2d, 0x34, 0x39, 0x34, 0x33, 0x62, 0x37, 0x61, + 0x37, 0x66, 0x37, 0x66, 0x38, 0x30, 0x22, 0x0d, + 0x0a, 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x2d, + 0x52, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x3a, 0x20, + 0x62, 0x79, 0x74, 0x65, 0x73, 0x0d, 0x0a, 0x43, + 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x4c, + 0x65, 0x6e, 0x67, 0x74, 0x68, 0x3a, 0x20, 0x34, + 0x34, 0x0d, 0x0a, 0x43, 0x6f, 0x6e, 0x6e, 0x65, + 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x63, + 0x6c, 0x6f, 0x73, 0x65, 0x0d, 0x0a, 0x43, 0x6f, + 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x54, 0x79, + 0x70, 0x65, 0x3a, 0x20, 0x74, 0x65, 0x78, 0x74, + 0x2f, 0x68, 0x74, 0x6d, 0x6c, 0x0d, 0x0a, 0x58, + 0x2d, 0x50, 0x61, 0x64, 0x3a, 0x20, 0x61, 0x76, + 0x6f, 0x69, 0x64, 0x20, 0x62, 0x72, 0x6f, 0x77, + 0x73, 0x65, 0x72, 0x20, 0x62, 0x75, 0x67, 0x0d, + 0x0a, 0x0d, 0x0a, 0x3c, 0x68, 0x74, 0x6d, 0x6c, + 0x3e, 0x3c, 0x62, 0x6f, 0x64, 0x79, 0x3e, 0x3c, + 0x68, 0x31, 0x3e, 0x49, 0x74, 0x20, 0x77, 0x6f, + 0x72, 0x6b, 0x73, 0x21, 0x3c, 0x2f, 0x68, 0x31, + 0x3e, 0x3c, 0x2f, 0x62, 0x6f, 0x64, 0x79, 0x3e, + 0x3c, 0x2f, 0x68, 0x74, 0x6d, 0x6c, 0x3e }; + p->tcph->th_ack = htonl(88); + p->tcph->th_seq = htonl(1); + p->tcph->th_flags = TH_PUSH | TH_ACK; + p->flowflags = FLOW_PKT_TOCLIENT; + p->payload_len = sizeof(response); + p->payload = response; + if (StreamTcpPacket(&tv, p, stt, &pq) == -1) + goto end; + if (ssn->server.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED || + !(ssn->client.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED) || + f.alproto != ALPROTO_HTTP || + f.alproto_ts != ALPROTO_HTTP || + f.alproto_tc != ALPROTO_UNKNOWN || + f.data_al_so_far[0] != 0 || + f.data_al_so_far[1] != 0 || + f.flags & FLOW_NO_APPLAYER_INSPECTION || + !FLOW_IS_PM_DONE(&f, STREAM_TOSERVER) || FLOW_IS_PP_DONE(&f, STREAM_TOSERVER) || + FLOW_IS_PM_DONE(&f, STREAM_TOCLIENT) || FLOW_IS_PP_DONE(&f, STREAM_TOCLIENT) || + ssn->data_first_seen_dir != 0x01) { + printf("failure 5\n"); + goto end; + } + + /* response ack */ + p->tcph->th_ack = htonl(328); + p->tcph->th_seq = htonl(88); + p->tcph->th_flags = TH_ACK; + p->flowflags = FLOW_PKT_TOSERVER; + p->payload_len = 0; + p->payload = NULL; + if (StreamTcpPacket(&tv, p, stt, &pq) == -1) + goto end; + if (!(ssn->server.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED) || + !(ssn->client.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED) || + f.alproto != ALPROTO_UNKNOWN || + f.alproto_ts != ALPROTO_UNKNOWN || + f.alproto_tc != ALPROTO_UNKNOWN || + f.data_al_so_far[0] != 0 || + f.data_al_so_far[1] != 0 || + !(f.flags & FLOW_NO_APPLAYER_INSPECTION) || + !FLOW_IS_PM_DONE(&f, STREAM_TOSERVER) || FLOW_IS_PP_DONE(&f, STREAM_TOSERVER) || + !FLOW_IS_PM_DONE(&f, STREAM_TOCLIENT) || FLOW_IS_PP_DONE(&f, STREAM_TOCLIENT) || + ssn->data_first_seen_dir != 0x01) { + printf("failure 6\n"); + goto end; + } + + StreamTcpSessionClear(p->flow->protoctx); + + ret = 1; +end: + StreamTcpFreeConfig(TRUE); + SCFree(p); + return ret; +} + +/** + * \test SMB -> HTTP/1.1 + */ +static int AppLayerTest08(void) +{ + Packet *p = SCMalloc(SIZE_OF_PACKET); + if (unlikely(p == NULL)) + return 0; + Flow f; + ThreadVars tv; + StreamTcpThread *stt = NULL; + TCPHdr tcph; + PacketQueue pq; + memset(&pq,0,sizeof(PacketQueue)); + memset(p, 0, SIZE_OF_PACKET); + memset (&f, 0, sizeof(Flow)); + memset(&tv, 0, sizeof (ThreadVars)); + StreamTcpThreadInit(&tv, NULL, (void **)&stt); + memset(&tcph, 0, sizeof (TCPHdr)); + + f.flags = FLOW_IPV4; + p->pkt = (uint8_t *)(p + 1); + p->flow = &f; + p->tcph = &tcph; + + int ret = 0; + + StreamTcpInitConfig(TRUE); + + tcph.th_win = htons(5480); + tcph.th_flags = TH_SYN; + p->flowflags = FLOW_PKT_TOSERVER; + p->payload_len = 0; + p->payload = NULL; + if (StreamTcpPacket(&tv, p, stt, &pq) == -1) + goto end; + + TcpSession *ssn = (TcpSession *)f.protoctx; + + /* handshake */ + if (ssn->server.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED || + ssn->client.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED || + f.alproto != ALPROTO_UNKNOWN || + f.alproto_ts != ALPROTO_UNKNOWN || + f.alproto_tc != ALPROTO_UNKNOWN || + f.data_al_so_far[0] != 0 || + f.data_al_so_far[1] != 0 || + f.flags & FLOW_NO_APPLAYER_INSPECTION || + FLOW_IS_PM_DONE(&f, STREAM_TOSERVER) || FLOW_IS_PP_DONE(&f, STREAM_TOSERVER) || + FLOW_IS_PM_DONE(&f, STREAM_TOCLIENT) || FLOW_IS_PP_DONE(&f, STREAM_TOCLIENT) || + ssn->data_first_seen_dir != 0) { + printf("failure 1\n"); + goto end; + } + + + /* handshake */ + p->tcph->th_ack = htonl(1); + p->tcph->th_flags = TH_SYN | TH_ACK; + p->flowflags = FLOW_PKT_TOCLIENT; + p->payload_len = 0; + p->payload = NULL; + if (StreamTcpPacket(&tv, p, stt, &pq) == -1) + goto end; + if (ssn->server.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED || + ssn->client.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED || + f.alproto != ALPROTO_UNKNOWN || + f.alproto_ts != ALPROTO_UNKNOWN || + f.alproto_tc != ALPROTO_UNKNOWN || + f.data_al_so_far[0] != 0 || + f.data_al_so_far[1] != 0 || + f.flags & FLOW_NO_APPLAYER_INSPECTION || + FLOW_IS_PM_DONE(&f, STREAM_TOSERVER) || FLOW_IS_PP_DONE(&f, STREAM_TOSERVER) || + FLOW_IS_PM_DONE(&f, STREAM_TOCLIENT) || FLOW_IS_PP_DONE(&f, STREAM_TOCLIENT) || + ssn->data_first_seen_dir != 0) { + printf("failure 2\n"); + goto end; + } + + /* handshake */ + p->tcph->th_ack = htonl(1); + p->tcph->th_seq = htonl(1); + p->tcph->th_flags = TH_ACK; + p->flowflags = FLOW_PKT_TOSERVER; + p->payload_len = 0; + p->payload = NULL; + if (StreamTcpPacket(&tv, p, stt, &pq) == -1) + goto end; + if (ssn->server.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED || + ssn->client.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED || + f.alproto != ALPROTO_UNKNOWN || + f.alproto_ts != ALPROTO_UNKNOWN || + f.alproto_tc != ALPROTO_UNKNOWN || + f.data_al_so_far[0] != 0 || + f.data_al_so_far[1] != 0 || + f.flags & FLOW_NO_APPLAYER_INSPECTION || + FLOW_IS_PM_DONE(&f, STREAM_TOSERVER) || FLOW_IS_PP_DONE(&f, STREAM_TOSERVER) || + FLOW_IS_PM_DONE(&f, STREAM_TOCLIENT) || FLOW_IS_PP_DONE(&f, STREAM_TOCLIENT) || + ssn->data_first_seen_dir != 0) { + printf("failure 3\n"); + goto end; + } + + /* full request */ + uint8_t request[] = { + 0x05, 0x00, 0x54, 0x20, 0x2f, 0x69, 0x6e, 0x64, + 0x65, 0x78, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0x20, + 0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, 0x2e, 0x30, + 0x0d, 0x0a, 0x48, 0x6f, 0x73, 0x74, 0x3a, 0x20, + 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x68, 0x6f, 0x73, + 0x74, 0x0d, 0x0a, 0x55, 0x73, 0x65, 0x72, 0x2d, + 0x41, 0x67, 0x65, 0x6e, 0x74, 0x3a, 0x20, 0x41, + 0x70, 0x61, 0x63, 0x68, 0x65, 0x42, 0x65, 0x6e, + 0x63, 0x68, 0x2f, 0x32, 0x2e, 0x33, 0x0d, 0x0a, + 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x3a, 0x20, + 0x2a, 0x2f, 0x2a, 0x0d, 0x0a, 0x0d, 0x0a }; + p->tcph->th_ack = htonl(1); + p->tcph->th_seq = htonl(1); + p->tcph->th_flags = TH_PUSH | TH_ACK; + p->flowflags = FLOW_PKT_TOSERVER; + p->payload_len = sizeof(request); + p->payload = request; + if (StreamTcpPacket(&tv, p, stt, &pq) == -1) + goto end; + if (ssn->server.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED || + ssn->client.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED || + f.alproto != ALPROTO_UNKNOWN || + f.alproto_ts != ALPROTO_UNKNOWN || + f.alproto_tc != ALPROTO_UNKNOWN || + f.data_al_so_far[0] != 0 || + f.data_al_so_far[1] != 0 || + f.flags & FLOW_NO_APPLAYER_INSPECTION || + FLOW_IS_PM_DONE(&f, STREAM_TOSERVER) || FLOW_IS_PP_DONE(&f, STREAM_TOSERVER) || + FLOW_IS_PM_DONE(&f, STREAM_TOCLIENT) || FLOW_IS_PP_DONE(&f, STREAM_TOCLIENT) || + ssn->data_first_seen_dir != STREAM_TOSERVER) { + printf("failure 4\n"); + goto end; + } + + /* full response - request ack */ + uint8_t response[] = { + 0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, 0x2e, 0x31, + 0x20, 0x32, 0x30, 0x30, 0x20, 0x4f, 0x4b, 0x0d, + 0x0a, 0x44, 0x61, 0x74, 0x65, 0x3a, 0x20, 0x46, + 0x72, 0x69, 0x2c, 0x20, 0x32, 0x33, 0x20, 0x53, + 0x65, 0x70, 0x20, 0x32, 0x30, 0x31, 0x31, 0x20, + 0x30, 0x36, 0x3a, 0x32, 0x39, 0x3a, 0x33, 0x39, + 0x20, 0x47, 0x4d, 0x54, 0x0d, 0x0a, 0x53, 0x65, + 0x72, 0x76, 0x65, 0x72, 0x3a, 0x20, 0x41, 0x70, + 0x61, 0x63, 0x68, 0x65, 0x2f, 0x32, 0x2e, 0x32, + 0x2e, 0x31, 0x35, 0x20, 0x28, 0x55, 0x6e, 0x69, + 0x78, 0x29, 0x20, 0x44, 0x41, 0x56, 0x2f, 0x32, + 0x0d, 0x0a, 0x4c, 0x61, 0x73, 0x74, 0x2d, 0x4d, + 0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, 0x64, 0x3a, + 0x20, 0x54, 0x68, 0x75, 0x2c, 0x20, 0x30, 0x34, + 0x20, 0x4e, 0x6f, 0x76, 0x20, 0x32, 0x30, 0x31, + 0x30, 0x20, 0x31, 0x35, 0x3a, 0x30, 0x34, 0x3a, + 0x34, 0x36, 0x20, 0x47, 0x4d, 0x54, 0x0d, 0x0a, + 0x45, 0x54, 0x61, 0x67, 0x3a, 0x20, 0x22, 0x61, + 0x62, 0x38, 0x39, 0x36, 0x35, 0x2d, 0x32, 0x63, + 0x2d, 0x34, 0x39, 0x34, 0x33, 0x62, 0x37, 0x61, + 0x37, 0x66, 0x37, 0x66, 0x38, 0x30, 0x22, 0x0d, + 0x0a, 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x2d, + 0x52, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x3a, 0x20, + 0x62, 0x79, 0x74, 0x65, 0x73, 0x0d, 0x0a, 0x43, + 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x4c, + 0x65, 0x6e, 0x67, 0x74, 0x68, 0x3a, 0x20, 0x34, + 0x34, 0x0d, 0x0a, 0x43, 0x6f, 0x6e, 0x6e, 0x65, + 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x63, + 0x6c, 0x6f, 0x73, 0x65, 0x0d, 0x0a, 0x43, 0x6f, + 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x54, 0x79, + 0x70, 0x65, 0x3a, 0x20, 0x74, 0x65, 0x78, 0x74, + 0x2f, 0x68, 0x74, 0x6d, 0x6c, 0x0d, 0x0a, 0x58, + 0x2d, 0x50, 0x61, 0x64, 0x3a, 0x20, 0x61, 0x76, + 0x6f, 0x69, 0x64, 0x20, 0x62, 0x72, 0x6f, 0x77, + 0x73, 0x65, 0x72, 0x20, 0x62, 0x75, 0x67, 0x0d, + 0x0a, 0x0d, 0x0a, 0x3c, 0x68, 0x74, 0x6d, 0x6c, + 0x3e, 0x3c, 0x62, 0x6f, 0x64, 0x79, 0x3e, 0x3c, + 0x68, 0x31, 0x3e, 0x49, 0x74, 0x20, 0x77, 0x6f, + 0x72, 0x6b, 0x73, 0x21, 0x3c, 0x2f, 0x68, 0x31, + 0x3e, 0x3c, 0x2f, 0x62, 0x6f, 0x64, 0x79, 0x3e, + 0x3c, 0x2f, 0x68, 0x74, 0x6d, 0x6c, 0x3e }; + p->tcph->th_ack = htonl(88); + p->tcph->th_seq = htonl(1); + p->tcph->th_flags = TH_PUSH | TH_ACK; + p->flowflags = FLOW_PKT_TOCLIENT; + p->payload_len = sizeof(response); + p->payload = response; + if (StreamTcpPacket(&tv, p, stt, &pq) == -1) + goto end; + if (ssn->server.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED || + !(ssn->client.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED) || + f.alproto != ALPROTO_DCERPC || + f.alproto_ts != ALPROTO_DCERPC || + f.alproto_tc != ALPROTO_UNKNOWN || + f.data_al_so_far[0] != 0 || + f.data_al_so_far[1] != 0 || + f.flags & FLOW_NO_APPLAYER_INSPECTION || + !FLOW_IS_PM_DONE(&f, STREAM_TOSERVER) || FLOW_IS_PP_DONE(&f, STREAM_TOSERVER) || + FLOW_IS_PM_DONE(&f, STREAM_TOCLIENT) || FLOW_IS_PP_DONE(&f, STREAM_TOCLIENT) || + ssn->data_first_seen_dir != 0x01) { + printf("failure 5\n"); + goto end; + } + + /* response ack */ + p->tcph->th_ack = htonl(328); + p->tcph->th_seq = htonl(88); + p->tcph->th_flags = TH_ACK; + p->flowflags = FLOW_PKT_TOSERVER; + p->payload_len = 0; + p->payload = NULL; + if (StreamTcpPacket(&tv, p, stt, &pq) == -1) + goto end; + if (!(ssn->server.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED) || + !(ssn->client.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED) || + f.alproto != ALPROTO_UNKNOWN || + f.alproto_ts != ALPROTO_UNKNOWN || + f.alproto_tc != ALPROTO_UNKNOWN || + f.data_al_so_far[0] != 0 || + f.data_al_so_far[1] != 0 || + !(f.flags & FLOW_NO_APPLAYER_INSPECTION) || + !FLOW_IS_PM_DONE(&f, STREAM_TOSERVER) || FLOW_IS_PP_DONE(&f, STREAM_TOSERVER) || + !FLOW_IS_PM_DONE(&f, STREAM_TOCLIENT) || FLOW_IS_PP_DONE(&f, STREAM_TOCLIENT) || + ssn->data_first_seen_dir != 0x01) { + printf("failure 6\n"); + goto end; + } + + StreamTcpSessionClear(p->flow->protoctx); + + ret = 1; +end: + StreamTcpFreeConfig(TRUE); + SCFree(p); + return ret; +} + +/** + * \test RUBBISH(TC - PM and PP NOT DONE) -> + * RUBBISH(TC - PM and PP DONE) -> + * RUBBISH(TS - PM and PP DONE) + */ +static int AppLayerTest09(void) +{ + Packet *p = SCMalloc(SIZE_OF_PACKET); + if (unlikely(p == NULL)) + return 0; + Flow f; + ThreadVars tv; + StreamTcpThread *stt = NULL; + TCPHdr tcph; + PacketQueue pq; + memset(&pq,0,sizeof(PacketQueue)); + memset(p, 0, SIZE_OF_PACKET); + memset (&f, 0, sizeof(Flow)); + memset(&tv, 0, sizeof (ThreadVars)); + StreamTcpThreadInit(&tv, NULL, (void **)&stt); + memset(&tcph, 0, sizeof (TCPHdr)); + + f.flags = FLOW_IPV4; + p->pkt = (uint8_t *)(p + 1); + p->flow = &f; + p->tcph = &tcph; + + int ret = 0; + + StreamTcpInitConfig(TRUE); + + tcph.th_win = htons(5480); + tcph.th_flags = TH_SYN; + p->flowflags = FLOW_PKT_TOSERVER; + p->payload_len = 0; + p->payload = NULL; + if (StreamTcpPacket(&tv, p, stt, &pq) == -1) + goto end; + + TcpSession *ssn = (TcpSession *)f.protoctx; + + /* handshake */ + if (ssn->server.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED || + ssn->client.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED || + f.alproto != ALPROTO_UNKNOWN || + f.alproto_ts != ALPROTO_UNKNOWN || + f.alproto_tc != ALPROTO_UNKNOWN || + f.data_al_so_far[0] != 0 || + f.data_al_so_far[1] != 0 || + f.flags & FLOW_NO_APPLAYER_INSPECTION || + FLOW_IS_PM_DONE(&f, STREAM_TOSERVER) || FLOW_IS_PP_DONE(&f, STREAM_TOSERVER) || + FLOW_IS_PM_DONE(&f, STREAM_TOCLIENT) || FLOW_IS_PP_DONE(&f, STREAM_TOCLIENT) || + ssn->data_first_seen_dir != 0) { + printf("failure 1\n"); + goto end; + } + + + /* handshake */ + p->tcph->th_ack = htonl(1); + p->tcph->th_flags = TH_SYN | TH_ACK; + p->flowflags = FLOW_PKT_TOCLIENT; + p->payload_len = 0; + p->payload = NULL; + if (StreamTcpPacket(&tv, p, stt, &pq) == -1) + goto end; + if (ssn->server.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED || + ssn->client.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED || + f.alproto != ALPROTO_UNKNOWN || + f.alproto_ts != ALPROTO_UNKNOWN || + f.alproto_tc != ALPROTO_UNKNOWN || + f.data_al_so_far[0] != 0 || + f.data_al_so_far[1] != 0 || + f.flags & FLOW_NO_APPLAYER_INSPECTION || + FLOW_IS_PM_DONE(&f, STREAM_TOSERVER) || FLOW_IS_PP_DONE(&f, STREAM_TOSERVER) || + FLOW_IS_PM_DONE(&f, STREAM_TOCLIENT) || FLOW_IS_PP_DONE(&f, STREAM_TOCLIENT) || + ssn->data_first_seen_dir != 0) { + printf("failure 2\n"); + goto end; + } + + /* handshake */ + p->tcph->th_ack = htonl(1); + p->tcph->th_seq = htonl(1); + p->tcph->th_flags = TH_ACK; + p->flowflags = FLOW_PKT_TOSERVER; + p->payload_len = 0; + p->payload = NULL; + if (StreamTcpPacket(&tv, p, stt, &pq) == -1) + goto end; + if (ssn->server.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED || + ssn->client.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED || + f.alproto != ALPROTO_UNKNOWN || + f.alproto_ts != ALPROTO_UNKNOWN || + f.alproto_tc != ALPROTO_UNKNOWN || + f.data_al_so_far[0] != 0 || + f.data_al_so_far[1] != 0 || + f.flags & FLOW_NO_APPLAYER_INSPECTION || + FLOW_IS_PM_DONE(&f, STREAM_TOSERVER) || FLOW_IS_PP_DONE(&f, STREAM_TOSERVER) || + FLOW_IS_PM_DONE(&f, STREAM_TOCLIENT) || FLOW_IS_PP_DONE(&f, STREAM_TOCLIENT) || + ssn->data_first_seen_dir != 0) { + printf("failure 3\n"); + goto end; + } + + /* full request */ + uint8_t request1[] = { + 0x47, 0x47, 0x49, 0x20, 0x2f, 0x69, 0x6e, 0x64 }; + p->tcph->th_ack = htonl(1); + p->tcph->th_seq = htonl(1); + p->tcph->th_flags = TH_PUSH | TH_ACK; + p->flowflags = FLOW_PKT_TOSERVER; + p->payload_len = sizeof(request1); + p->payload = request1; + if (StreamTcpPacket(&tv, p, stt, &pq) == -1) + goto end; + if (ssn->server.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED || + ssn->client.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED || + f.alproto != ALPROTO_UNKNOWN || + f.alproto_ts != ALPROTO_UNKNOWN || + f.alproto_tc != ALPROTO_UNKNOWN || + f.data_al_so_far[0] != 0 || + f.data_al_so_far[1] != 0 || + f.flags & FLOW_NO_APPLAYER_INSPECTION || + FLOW_IS_PM_DONE(&f, STREAM_TOSERVER) || FLOW_IS_PP_DONE(&f, STREAM_TOSERVER) || + FLOW_IS_PM_DONE(&f, STREAM_TOCLIENT) || FLOW_IS_PP_DONE(&f, STREAM_TOCLIENT) || + ssn->data_first_seen_dir != STREAM_TOSERVER) { + printf("failure 4\n"); + goto end; + } + + /* response - request ack */ + p->tcph->th_ack = htonl(9); + p->tcph->th_seq = htonl(1); + p->tcph->th_flags = TH_PUSH | TH_ACK; + p->flowflags = FLOW_PKT_TOCLIENT; + p->payload_len = 0; + p->payload = NULL; + if (StreamTcpPacket(&tv, p, stt, &pq) == -1) + goto end; + if (ssn->server.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED || + ssn->client.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED || + f.alproto != ALPROTO_UNKNOWN || + f.alproto_ts != ALPROTO_UNKNOWN || + f.alproto_tc != ALPROTO_UNKNOWN || + f.data_al_so_far[0] != 0 || + f.data_al_so_far[1] != 0 || + f.flags & FLOW_NO_APPLAYER_INSPECTION || + FLOW_IS_PM_DONE(&f, STREAM_TOSERVER) || !FLOW_IS_PP_DONE(&f, STREAM_TOSERVER) || + FLOW_IS_PM_DONE(&f, STREAM_TOCLIENT) || FLOW_IS_PP_DONE(&f, STREAM_TOCLIENT) || + ssn->data_first_seen_dir != STREAM_TOSERVER) { + printf("failure 5\n"); + goto end; + } + + /* full request */ + uint8_t request2[] = { + 0x44, 0x44, 0x45, 0x20, 0x2f, 0x69, 0x6e, 0x64 }; + p->tcph->th_ack = htonl(1); + p->tcph->th_seq = htonl(9); + p->tcph->th_flags = TH_PUSH | TH_ACK; + p->flowflags = FLOW_PKT_TOSERVER; + p->payload_len = sizeof(request2); + p->payload = request2; + if (StreamTcpPacket(&tv, p, stt, &pq) == -1) + goto end; + if (ssn->server.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED || + ssn->client.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED || + f.alproto != ALPROTO_UNKNOWN || + f.alproto_ts != ALPROTO_UNKNOWN || + f.alproto_tc != ALPROTO_UNKNOWN || + f.data_al_so_far[0] != 0 || + f.data_al_so_far[1] != 0 || + f.flags & FLOW_NO_APPLAYER_INSPECTION || + FLOW_IS_PM_DONE(&f, STREAM_TOSERVER) || !FLOW_IS_PP_DONE(&f, STREAM_TOSERVER) || + FLOW_IS_PM_DONE(&f, STREAM_TOCLIENT) || FLOW_IS_PP_DONE(&f, STREAM_TOCLIENT) || + ssn->data_first_seen_dir != STREAM_TOSERVER) { + printf("failure 6\n"); + goto end; + } + + /* full response - request ack */ + uint8_t response[] = { + 0x55, 0x74, 0x54, 0x50, 0x2f, 0x31, 0x2e, 0x31, + 0x20, 0x32, 0x30, 0x30, 0x20, 0x4f, 0x4b, 0x0d, + 0x0a, 0x44, 0x61, 0x74, 0x65, 0x3a, 0x20, 0x46, + 0x72, 0x69, 0x2c, 0x20, 0x32, 0x33, 0x20, 0x53, + 0x65, 0x70, 0x20, 0x32, 0x30, 0x31, 0x31, 0x20, + 0x30, 0x36, 0x3a, 0x32, 0x39, 0x3a, 0x33, 0x39, + 0x20, 0x47, 0x4d, 0x54, 0x0d, 0x0a, 0x53, 0x65, + 0x72, 0x76, 0x65, 0x72, 0x3a, 0x20, 0x41, 0x70, + 0x61, 0x63, 0x68, 0x65, 0x2f, 0x32, 0x2e, 0x32, + 0x2e, 0x31, 0x35, 0x20, 0x28, 0x55, 0x6e, 0x69, + 0x78, 0x29, 0x20, 0x44, 0x41, 0x56, 0x2f, 0x32, + 0x0d, 0x0a, 0x4c, 0x61, 0x73, 0x74, 0x2d, 0x4d, + 0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, 0x64, 0x3a, + 0x20, 0x54, 0x68, 0x75, 0x2c, 0x20, 0x30, 0x34, + 0x20, 0x4e, 0x6f, 0x76, 0x20, 0x32, 0x30, 0x31, + 0x30, 0x20, 0x31, 0x35, 0x3a, 0x30, 0x34, 0x3a, + 0x34, 0x36, 0x20, 0x47, 0x4d, 0x54, 0x0d, 0x0a, + 0x45, 0x54, 0x61, 0x67, 0x3a, 0x20, 0x22, 0x61, + 0x62, 0x38, 0x39, 0x36, 0x35, 0x2d, 0x32, 0x63, + 0x2d, 0x34, 0x39, 0x34, 0x33, 0x62, 0x37, 0x61, + 0x37, 0x66, 0x37, 0x66, 0x38, 0x30, 0x22, 0x0d, + 0x0a, 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x2d, + 0x52, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x3a, 0x20, + 0x62, 0x79, 0x74, 0x65, 0x73, 0x0d, 0x0a, 0x43, + 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x4c, + 0x65, 0x6e, 0x67, 0x74, 0x68, 0x3a, 0x20, 0x34, + 0x34, 0x0d, 0x0a, 0x43, 0x6f, 0x6e, 0x6e, 0x65, + 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x63, + 0x6c, 0x6f, 0x73, 0x65, 0x0d, 0x0a, 0x43, 0x6f, + 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x54, 0x79, + 0x70, 0x65, 0x3a, 0x20, 0x74, 0x65, 0x78, 0x74, + 0x2f, 0x68, 0x74, 0x6d, 0x6c, 0x0d, 0x0a, 0x58, + 0x2d, 0x50, 0x61, 0x64, 0x3a, 0x20, 0x61, 0x76, + 0x6f, 0x69, 0x64, 0x20, 0x62, 0x72, 0x6f, 0x77, + 0x73, 0x65, 0x72, 0x20, 0x62, 0x75, 0x67, 0x0d, + 0x0a, 0x0d, 0x0a, 0x3c, 0x68, 0x74, 0x6d, 0x6c, + 0x3e, 0x3c, 0x62, 0x6f, 0x64, 0x79, 0x3e, 0x3c, + 0x68, 0x31, 0x3e, 0x49, 0x74, 0x20, 0x77, 0x6f, + 0x72, 0x6b, 0x73, 0x21, 0x3c, 0x2f, 0x68, 0x31, + 0x3e, 0x3c, 0x2f, 0x62, 0x6f, 0x64, 0x79, 0x3e, + 0x3c, 0x2f, 0x68, 0x74, 0x6d, 0x6c, 0x3e }; + p->tcph->th_ack = htonl(17); + p->tcph->th_seq = htonl(1); + p->tcph->th_flags = TH_PUSH | TH_ACK; + p->flowflags = FLOW_PKT_TOCLIENT; + p->payload_len = sizeof(response); + p->payload = response; + if (StreamTcpPacket(&tv, p, stt, &pq) == -1) + goto end; + if (ssn->server.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED || + ssn->client.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED || + f.alproto != ALPROTO_UNKNOWN || + f.alproto_ts != ALPROTO_UNKNOWN || + f.alproto_tc != ALPROTO_UNKNOWN || + f.data_al_so_far[0] != 0 || + f.data_al_so_far[1] != 0 || + f.flags & FLOW_NO_APPLAYER_INSPECTION || + !FLOW_IS_PM_DONE(&f, STREAM_TOSERVER) || !FLOW_IS_PP_DONE(&f, STREAM_TOSERVER) || + FLOW_IS_PM_DONE(&f, STREAM_TOCLIENT) || FLOW_IS_PP_DONE(&f, STREAM_TOCLIENT) || + ssn->data_first_seen_dir != STREAM_TOSERVER) { + printf("failure 7\n"); + goto end; + } + + /* response ack */ + p->tcph->th_ack = htonl(328); + p->tcph->th_seq = htonl(17); + p->tcph->th_flags = TH_ACK; + p->flowflags = FLOW_PKT_TOSERVER; + p->payload_len = 0; + p->payload = NULL; + if (StreamTcpPacket(&tv, p, stt, &pq) == -1) + goto end; + if (!(ssn->server.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED) || + !(ssn->client.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED) || + f.alproto != ALPROTO_UNKNOWN || + f.alproto_ts != ALPROTO_UNKNOWN || + f.alproto_tc != ALPROTO_UNKNOWN || + f.data_al_so_far[0] != 0 || + f.data_al_so_far[1] != 0 || + !(f.flags & FLOW_NO_APPLAYER_INSPECTION) || + !FLOW_IS_PM_DONE(&f, STREAM_TOSERVER) || !FLOW_IS_PP_DONE(&f, STREAM_TOSERVER) || + !FLOW_IS_PM_DONE(&f, STREAM_TOCLIENT) || !FLOW_IS_PP_DONE(&f, STREAM_TOCLIENT) || + ssn->data_first_seen_dir != 0x01) { + printf("failure 8\n"); + goto end; + } + + StreamTcpSessionClear(p->flow->protoctx); + + ret = 1; +end: + StreamTcpFreeConfig(TRUE); + SCFree(p); + return ret; +} + +/** + * \test RUBBISH(TC - PM and PP DONE) -> + * RUBBISH(TS - PM and PP DONE) + */ +static int AppLayerTest10(void) +{ + Packet *p = SCMalloc(SIZE_OF_PACKET); + if (unlikely(p == NULL)) + return 0; + Flow f; + ThreadVars tv; + StreamTcpThread *stt = NULL; + TCPHdr tcph; + PacketQueue pq; + memset(&pq,0,sizeof(PacketQueue)); + memset(p, 0, SIZE_OF_PACKET); + memset (&f, 0, sizeof(Flow)); + memset(&tv, 0, sizeof (ThreadVars)); + StreamTcpThreadInit(&tv, NULL, (void **)&stt); + memset(&tcph, 0, sizeof (TCPHdr)); + + f.flags = FLOW_IPV4; + p->pkt = (uint8_t *)(p + 1); + p->flow = &f; + p->tcph = &tcph; + + int ret = 0; + + StreamTcpInitConfig(TRUE); + + tcph.th_win = htons(5480); + tcph.th_flags = TH_SYN; + p->flowflags = FLOW_PKT_TOSERVER; + p->payload_len = 0; + p->payload = NULL; + if (StreamTcpPacket(&tv, p, stt, &pq) == -1) + goto end; + + TcpSession *ssn = (TcpSession *)f.protoctx; + + /* handshake */ + if (ssn->server.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED || + ssn->client.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED || + f.alproto != ALPROTO_UNKNOWN || + f.alproto_ts != ALPROTO_UNKNOWN || + f.alproto_tc != ALPROTO_UNKNOWN || + f.data_al_so_far[0] != 0 || + f.data_al_so_far[1] != 0 || + f.flags & FLOW_NO_APPLAYER_INSPECTION || + FLOW_IS_PM_DONE(&f, STREAM_TOSERVER) || FLOW_IS_PP_DONE(&f, STREAM_TOSERVER) || + FLOW_IS_PM_DONE(&f, STREAM_TOCLIENT) || FLOW_IS_PP_DONE(&f, STREAM_TOCLIENT) || + ssn->data_first_seen_dir != 0) { + printf("failure 1\n"); + goto end; + } + + + /* handshake */ + p->tcph->th_ack = htonl(1); + p->tcph->th_flags = TH_SYN | TH_ACK; + p->flowflags = FLOW_PKT_TOCLIENT; + p->payload_len = 0; + p->payload = NULL; + if (StreamTcpPacket(&tv, p, stt, &pq) == -1) + goto end; + if (ssn->server.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED || + ssn->client.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED || + f.alproto != ALPROTO_UNKNOWN || + f.alproto_ts != ALPROTO_UNKNOWN || + f.alproto_tc != ALPROTO_UNKNOWN || + f.data_al_so_far[0] != 0 || + f.data_al_so_far[1] != 0 || + f.flags & FLOW_NO_APPLAYER_INSPECTION || + FLOW_IS_PM_DONE(&f, STREAM_TOSERVER) || FLOW_IS_PP_DONE(&f, STREAM_TOSERVER) || + FLOW_IS_PM_DONE(&f, STREAM_TOCLIENT) || FLOW_IS_PP_DONE(&f, STREAM_TOCLIENT) || + ssn->data_first_seen_dir != 0) { + printf("failure 2\n"); + goto end; + } + + /* handshake */ + p->tcph->th_ack = htonl(1); + p->tcph->th_seq = htonl(1); + p->tcph->th_flags = TH_ACK; + p->flowflags = FLOW_PKT_TOSERVER; + p->payload_len = 0; + p->payload = NULL; + if (StreamTcpPacket(&tv, p, stt, &pq) == -1) + goto end; + if (ssn->server.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED || + ssn->client.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED || + f.alproto != ALPROTO_UNKNOWN || + f.alproto_ts != ALPROTO_UNKNOWN || + f.alproto_tc != ALPROTO_UNKNOWN || + f.data_al_so_far[0] != 0 || + f.data_al_so_far[1] != 0 || + f.flags & FLOW_NO_APPLAYER_INSPECTION || + FLOW_IS_PM_DONE(&f, STREAM_TOSERVER) || FLOW_IS_PP_DONE(&f, STREAM_TOSERVER) || + FLOW_IS_PM_DONE(&f, STREAM_TOCLIENT) || FLOW_IS_PP_DONE(&f, STREAM_TOCLIENT) || + ssn->data_first_seen_dir != 0) { + printf("failure 3\n"); + goto end; + } + + /* full request */ + uint8_t request1[] = { + 0x47, 0x47, 0x49, 0x20, 0x2f, 0x69, 0x6e, 0x64, + 0x47, 0x47, 0x49, 0x20, 0x2f, 0x69, 0x6e, 0x64 }; + p->tcph->th_ack = htonl(1); + p->tcph->th_seq = htonl(1); + p->tcph->th_flags = TH_PUSH | TH_ACK; + p->flowflags = FLOW_PKT_TOSERVER; + p->payload_len = sizeof(request1); + p->payload = request1; + if (StreamTcpPacket(&tv, p, stt, &pq) == -1) + goto end; + if (ssn->server.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED || + ssn->client.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED || + f.alproto != ALPROTO_UNKNOWN || + f.alproto_ts != ALPROTO_UNKNOWN || + f.alproto_tc != ALPROTO_UNKNOWN || + f.data_al_so_far[0] != 0 || + f.data_al_so_far[1] != 0 || + f.flags & FLOW_NO_APPLAYER_INSPECTION || + FLOW_IS_PM_DONE(&f, STREAM_TOSERVER) || FLOW_IS_PP_DONE(&f, STREAM_TOSERVER) || + FLOW_IS_PM_DONE(&f, STREAM_TOCLIENT) || FLOW_IS_PP_DONE(&f, STREAM_TOCLIENT) || + ssn->data_first_seen_dir != STREAM_TOSERVER) { + printf("failure 4\n"); + goto end; + } + + /* response - request ack */ + p->tcph->th_ack = htonl(17); + p->tcph->th_seq = htonl(1); + p->tcph->th_flags = TH_PUSH | TH_ACK; + p->flowflags = FLOW_PKT_TOCLIENT; + p->payload_len = 0; + p->payload = NULL; + if (StreamTcpPacket(&tv, p, stt, &pq) == -1) + goto end; + if (ssn->server.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED || + ssn->client.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED || + f.alproto != ALPROTO_UNKNOWN || + f.alproto_ts != ALPROTO_UNKNOWN || + f.alproto_tc != ALPROTO_UNKNOWN || + f.data_al_so_far[0] != 0 || + f.data_al_so_far[1] != 0 || + f.flags & FLOW_NO_APPLAYER_INSPECTION || + !FLOW_IS_PM_DONE(&f, STREAM_TOSERVER) || !FLOW_IS_PP_DONE(&f, STREAM_TOSERVER) || + FLOW_IS_PM_DONE(&f, STREAM_TOCLIENT) || FLOW_IS_PP_DONE(&f, STREAM_TOCLIENT) || + ssn->data_first_seen_dir != STREAM_TOSERVER) { + printf("failure 5\n"); + goto end; + } + + /* full response - request ack */ + uint8_t response[] = { + 0x55, 0x74, 0x54, 0x50, 0x2f, 0x31, 0x2e, 0x31, + 0x20, 0x32, 0x30, 0x30, 0x20, 0x4f, 0x4b, 0x0d, + 0x0a, 0x44, 0x61, 0x74, 0x65, 0x3a, 0x20, 0x46, + 0x72, 0x69, 0x2c, 0x20, 0x32, 0x33, 0x20, 0x53, + 0x65, 0x70, 0x20, 0x32, 0x30, 0x31, 0x31, 0x20, + 0x30, 0x36, 0x3a, 0x32, 0x39, 0x3a, 0x33, 0x39, + 0x20, 0x47, 0x4d, 0x54, 0x0d, 0x0a, 0x53, 0x65, + 0x72, 0x76, 0x65, 0x72, 0x3a, 0x20, 0x41, 0x70, + 0x61, 0x63, 0x68, 0x65, 0x2f, 0x32, 0x2e, 0x32, + 0x2e, 0x31, 0x35, 0x20, 0x28, 0x55, 0x6e, 0x69, + 0x78, 0x29, 0x20, 0x44, 0x41, 0x56, 0x2f, 0x32, + 0x0d, 0x0a, 0x4c, 0x61, 0x73, 0x74, 0x2d, 0x4d, + 0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, 0x64, 0x3a, + 0x20, 0x54, 0x68, 0x75, 0x2c, 0x20, 0x30, 0x34, + 0x20, 0x4e, 0x6f, 0x76, 0x20, 0x32, 0x30, 0x31, + 0x30, 0x20, 0x31, 0x35, 0x3a, 0x30, 0x34, 0x3a, + 0x34, 0x36, 0x20, 0x47, 0x4d, 0x54, 0x0d, 0x0a, + 0x45, 0x54, 0x61, 0x67, 0x3a, 0x20, 0x22, 0x61, + 0x62, 0x38, 0x39, 0x36, 0x35, 0x2d, 0x32, 0x63, + 0x2d, 0x34, 0x39, 0x34, 0x33, 0x62, 0x37, 0x61, + 0x37, 0x66, 0x37, 0x66, 0x38, 0x30, 0x22, 0x0d, + 0x0a, 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x2d, + 0x52, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x3a, 0x20, + 0x62, 0x79, 0x74, 0x65, 0x73, 0x0d, 0x0a, 0x43, + 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x4c, + 0x65, 0x6e, 0x67, 0x74, 0x68, 0x3a, 0x20, 0x34, + 0x34, 0x0d, 0x0a, 0x43, 0x6f, 0x6e, 0x6e, 0x65, + 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x63, + 0x6c, 0x6f, 0x73, 0x65, 0x0d, 0x0a, 0x43, 0x6f, + 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x54, 0x79, + 0x70, 0x65, 0x3a, 0x20, 0x74, 0x65, 0x78, 0x74, + 0x2f, 0x68, 0x74, 0x6d, 0x6c, 0x0d, 0x0a, 0x58, + 0x2d, 0x50, 0x61, 0x64, 0x3a, 0x20, 0x61, 0x76, + 0x6f, 0x69, 0x64, 0x20, 0x62, 0x72, 0x6f, 0x77, + 0x73, 0x65, 0x72, 0x20, 0x62, 0x75, 0x67, 0x0d, + 0x0a, 0x0d, 0x0a, 0x3c, 0x68, 0x74, 0x6d, 0x6c, + 0x3e, 0x3c, 0x62, 0x6f, 0x64, 0x79, 0x3e, 0x3c, + 0x68, 0x31, 0x3e, 0x49, 0x74, 0x20, 0x77, 0x6f, + 0x72, 0x6b, 0x73, 0x21, 0x3c, 0x2f, 0x68, 0x31, + 0x3e, 0x3c, 0x2f, 0x62, 0x6f, 0x64, 0x79, 0x3e, + 0x3c, 0x2f, 0x68, 0x74, 0x6d, 0x6c, 0x3e }; + p->tcph->th_ack = htonl(17); + p->tcph->th_seq = htonl(1); + p->tcph->th_flags = TH_PUSH | TH_ACK; + p->flowflags = FLOW_PKT_TOCLIENT; + p->payload_len = sizeof(response); + p->payload = response; + if (StreamTcpPacket(&tv, p, stt, &pq) == -1) + goto end; + if (ssn->server.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED || + ssn->client.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED || + f.alproto != ALPROTO_UNKNOWN || + f.alproto_ts != ALPROTO_UNKNOWN || + f.alproto_tc != ALPROTO_UNKNOWN || + f.data_al_so_far[0] != 0 || + f.data_al_so_far[1] != 0 || + f.flags & FLOW_NO_APPLAYER_INSPECTION || + !FLOW_IS_PM_DONE(&f, STREAM_TOSERVER) || !FLOW_IS_PP_DONE(&f, STREAM_TOSERVER) || + FLOW_IS_PM_DONE(&f, STREAM_TOCLIENT) || FLOW_IS_PP_DONE(&f, STREAM_TOCLIENT) || + ssn->data_first_seen_dir != STREAM_TOSERVER) { + printf("failure 7\n"); + goto end; + } + + /* response ack */ + p->tcph->th_ack = htonl(328); + p->tcph->th_seq = htonl(17); + p->tcph->th_flags = TH_ACK; + p->flowflags = FLOW_PKT_TOSERVER; + p->payload_len = 0; + p->payload = NULL; + if (StreamTcpPacket(&tv, p, stt, &pq) == -1) + goto end; + if (!(ssn->server.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED) || + !(ssn->client.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED) || + f.alproto != ALPROTO_UNKNOWN || + f.alproto_ts != ALPROTO_UNKNOWN || + f.alproto_tc != ALPROTO_UNKNOWN || + f.data_al_so_far[0] != 0 || + f.data_al_so_far[1] != 0 || + !(f.flags & FLOW_NO_APPLAYER_INSPECTION) || + !FLOW_IS_PM_DONE(&f, STREAM_TOSERVER) || !FLOW_IS_PP_DONE(&f, STREAM_TOSERVER) || + !FLOW_IS_PM_DONE(&f, STREAM_TOCLIENT) || !FLOW_IS_PP_DONE(&f, STREAM_TOCLIENT) || + ssn->data_first_seen_dir != 0x01) { + printf("failure 8\n"); + goto end; + } + + StreamTcpSessionClear(p->flow->protoctx); + + ret = 1; +end: + StreamTcpFreeConfig(TRUE); + SCFree(p); + return ret; +} + +/** + * \test RUBBISH(TC - PM and PP DONE) -> + * RUBBISH(TS - PM and PP NOT DONE) -> + * RUBBISH(TS - PM and PP DONE) + */ +static int AppLayerTest11(void) +{ + Packet *p = SCMalloc(SIZE_OF_PACKET); + if (unlikely(p == NULL)) + return 0; + Flow f; + ThreadVars tv; + StreamTcpThread *stt = NULL; + TCPHdr tcph; + PacketQueue pq; + memset(&pq,0,sizeof(PacketQueue)); + memset(p, 0, SIZE_OF_PACKET); + memset (&f, 0, sizeof(Flow)); + memset(&tv, 0, sizeof (ThreadVars)); + StreamTcpThreadInit(&tv, NULL, (void **)&stt); + memset(&tcph, 0, sizeof (TCPHdr)); + + f.flags = FLOW_IPV4; + p->pkt = (uint8_t *)(p + 1); + p->flow = &f; + p->tcph = &tcph; + + int ret = 0; + + StreamTcpInitConfig(TRUE); + + tcph.th_win = htons(5480); + tcph.th_flags = TH_SYN; + p->flowflags = FLOW_PKT_TOSERVER; + p->payload_len = 0; + p->payload = NULL; + if (StreamTcpPacket(&tv, p, stt, &pq) == -1) + goto end; + + TcpSession *ssn = (TcpSession *)f.protoctx; + + /* handshake */ + if (ssn->server.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED || + ssn->client.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED || + f.alproto != ALPROTO_UNKNOWN || + f.alproto_ts != ALPROTO_UNKNOWN || + f.alproto_tc != ALPROTO_UNKNOWN || + f.data_al_so_far[0] != 0 || + f.data_al_so_far[1] != 0 || + f.flags & FLOW_NO_APPLAYER_INSPECTION || + FLOW_IS_PM_DONE(&f, STREAM_TOSERVER) || FLOW_IS_PP_DONE(&f, STREAM_TOSERVER) || + FLOW_IS_PM_DONE(&f, STREAM_TOCLIENT) || FLOW_IS_PP_DONE(&f, STREAM_TOCLIENT) || + ssn->data_first_seen_dir != 0) { + printf("failure 1\n"); + goto end; + } + + + /* handshake */ + p->tcph->th_ack = htonl(1); + p->tcph->th_flags = TH_SYN | TH_ACK; + p->flowflags = FLOW_PKT_TOCLIENT; + p->payload_len = 0; + p->payload = NULL; + if (StreamTcpPacket(&tv, p, stt, &pq) == -1) + goto end; + if (ssn->server.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED || + ssn->client.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED || + f.alproto != ALPROTO_UNKNOWN || + f.alproto_ts != ALPROTO_UNKNOWN || + f.alproto_tc != ALPROTO_UNKNOWN || + f.data_al_so_far[0] != 0 || + f.data_al_so_far[1] != 0 || + f.flags & FLOW_NO_APPLAYER_INSPECTION || + FLOW_IS_PM_DONE(&f, STREAM_TOSERVER) || FLOW_IS_PP_DONE(&f, STREAM_TOSERVER) || + FLOW_IS_PM_DONE(&f, STREAM_TOCLIENT) || FLOW_IS_PP_DONE(&f, STREAM_TOCLIENT) || + ssn->data_first_seen_dir != 0) { + printf("failure 2\n"); + goto end; + } + + /* handshake */ + p->tcph->th_ack = htonl(1); + p->tcph->th_seq = htonl(1); + p->tcph->th_flags = TH_ACK; + p->flowflags = FLOW_PKT_TOSERVER; + p->payload_len = 0; + p->payload = NULL; + if (StreamTcpPacket(&tv, p, stt, &pq) == -1) + goto end; + if (ssn->server.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED || + ssn->client.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED || + f.alproto != ALPROTO_UNKNOWN || + f.alproto_ts != ALPROTO_UNKNOWN || + f.alproto_tc != ALPROTO_UNKNOWN || + f.data_al_so_far[0] != 0 || + f.data_al_so_far[1] != 0 || + f.flags & FLOW_NO_APPLAYER_INSPECTION || + FLOW_IS_PM_DONE(&f, STREAM_TOSERVER) || FLOW_IS_PP_DONE(&f, STREAM_TOSERVER) || + FLOW_IS_PM_DONE(&f, STREAM_TOCLIENT) || FLOW_IS_PP_DONE(&f, STREAM_TOCLIENT) || + ssn->data_first_seen_dir != 0) { + printf("failure 3\n"); + goto end; + } + + /* full request */ + uint8_t request1[] = { + 0x47, 0x47, 0x49, 0x20, 0x2f, 0x69, 0x6e, 0x64, + 0x47, 0x47, 0x49, 0x20, 0x2f, 0x69, 0x6e, 0x64 }; + p->tcph->th_ack = htonl(1); + p->tcph->th_seq = htonl(1); + p->tcph->th_flags = TH_PUSH | TH_ACK; + p->flowflags = FLOW_PKT_TOSERVER; + p->payload_len = sizeof(request1); + p->payload = request1; + if (StreamTcpPacket(&tv, p, stt, &pq) == -1) + goto end; + if (ssn->server.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED || + ssn->client.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED || + f.alproto != ALPROTO_UNKNOWN || + f.alproto_ts != ALPROTO_UNKNOWN || + f.alproto_tc != ALPROTO_UNKNOWN || + f.data_al_so_far[0] != 0 || + f.data_al_so_far[1] != 0 || + f.flags & FLOW_NO_APPLAYER_INSPECTION || + FLOW_IS_PM_DONE(&f, STREAM_TOSERVER) || FLOW_IS_PP_DONE(&f, STREAM_TOSERVER) || + FLOW_IS_PM_DONE(&f, STREAM_TOCLIENT) || FLOW_IS_PP_DONE(&f, STREAM_TOCLIENT) || + ssn->data_first_seen_dir != STREAM_TOSERVER) { + printf("failure 4\n"); + goto end; + } + + /* response - request ack */ + p->tcph->th_ack = htonl(17); + p->tcph->th_seq = htonl(1); + p->tcph->th_flags = TH_PUSH | TH_ACK; + p->flowflags = FLOW_PKT_TOCLIENT; + p->payload_len = 0; + p->payload = NULL; + if (StreamTcpPacket(&tv, p, stt, &pq) == -1) + goto end; + if (ssn->server.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED || + ssn->client.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED || + f.alproto != ALPROTO_UNKNOWN || + f.alproto_ts != ALPROTO_UNKNOWN || + f.alproto_tc != ALPROTO_UNKNOWN || + f.data_al_so_far[0] != 0 || + f.data_al_so_far[1] != 0 || + f.flags & FLOW_NO_APPLAYER_INSPECTION || + !FLOW_IS_PM_DONE(&f, STREAM_TOSERVER) || !FLOW_IS_PP_DONE(&f, STREAM_TOSERVER) || + FLOW_IS_PM_DONE(&f, STREAM_TOCLIENT) || FLOW_IS_PP_DONE(&f, STREAM_TOCLIENT) || + ssn->data_first_seen_dir != STREAM_TOSERVER) { + printf("failure 5\n"); + goto end; + } + + /* full response - request ack */ + uint8_t response1[] = { + 0x55, 0x74, 0x54, 0x50, }; + p->tcph->th_ack = htonl(17); + p->tcph->th_seq = htonl(1); + p->tcph->th_flags = TH_PUSH | TH_ACK; + p->flowflags = FLOW_PKT_TOCLIENT; + p->payload_len = sizeof(response1); + p->payload = response1; + if (StreamTcpPacket(&tv, p, stt, &pq) == -1) + goto end; + if (ssn->server.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED || + ssn->client.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED || + f.alproto != ALPROTO_UNKNOWN || + f.alproto_ts != ALPROTO_UNKNOWN || + f.alproto_tc != ALPROTO_UNKNOWN || + f.data_al_so_far[0] != 0 || + f.data_al_so_far[1] != 0 || + f.flags & FLOW_NO_APPLAYER_INSPECTION || + !FLOW_IS_PM_DONE(&f, STREAM_TOSERVER) || !FLOW_IS_PP_DONE(&f, STREAM_TOSERVER) || + FLOW_IS_PM_DONE(&f, STREAM_TOCLIENT) || FLOW_IS_PP_DONE(&f, STREAM_TOCLIENT) || + ssn->data_first_seen_dir != STREAM_TOSERVER) { + printf("failure 6\n"); + goto end; + } + + /* response ack from request */ + p->tcph->th_ack = htonl(5); + p->tcph->th_seq = htonl(17); + p->tcph->th_flags = TH_ACK; + p->flowflags = FLOW_PKT_TOSERVER; + p->payload_len = 0; + p->payload = NULL; + if (StreamTcpPacket(&tv, p, stt, &pq) == -1) + goto end; + if (ssn->server.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED || + ssn->client.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED || + f.alproto != ALPROTO_UNKNOWN || + f.alproto_ts != ALPROTO_UNKNOWN || + f.alproto_tc != ALPROTO_UNKNOWN || + f.data_al_so_far[0] != 0 || + f.data_al_so_far[1] != 0 || + f.flags & FLOW_NO_APPLAYER_INSPECTION || + !FLOW_IS_PM_DONE(&f, STREAM_TOSERVER) || !FLOW_IS_PP_DONE(&f, STREAM_TOSERVER) || + FLOW_IS_PM_DONE(&f, STREAM_TOCLIENT) || !FLOW_IS_PP_DONE(&f, STREAM_TOCLIENT) || + ssn->data_first_seen_dir != STREAM_TOSERVER) { + printf("failure 7\n"); + goto end; + } + + uint8_t response2[] = { + 0x2f, 0x31, 0x2e, 0x31, + 0x20, 0x32, 0x30, 0x30, 0x20, 0x4f, 0x4b, 0x0d, + 0x0a, 0x44, 0x61, 0x74, 0x65, 0x3a, 0x20, 0x46, + 0x72, 0x69, 0x2c, 0x20, 0x32, 0x33, 0x20, 0x53, + 0x65, 0x70, 0x20, 0x32, 0x30, 0x31, 0x31, 0x20, + 0x30, 0x36, 0x3a, 0x32, 0x39, 0x3a, 0x33, 0x39, + 0x20, 0x47, 0x4d, 0x54, 0x0d, 0x0a, 0x53, 0x65, + 0x72, 0x76, 0x65, 0x72, 0x3a, 0x20, 0x41, 0x70, + 0x61, 0x63, 0x68, 0x65, 0x2f, 0x32, 0x2e, 0x32, + 0x2e, 0x31, 0x35, 0x20, 0x28, 0x55, 0x6e, 0x69, + 0x78, 0x29, 0x20, 0x44, 0x41, 0x56, 0x2f, 0x32, + 0x0d, 0x0a, 0x4c, 0x61, 0x73, 0x74, 0x2d, 0x4d, + 0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, 0x64, 0x3a, + 0x20, 0x54, 0x68, 0x75, 0x2c, 0x20, 0x30, 0x34, + 0x20, 0x4e, 0x6f, 0x76, 0x20, 0x32, 0x30, 0x31, + 0x30, 0x20, 0x31, 0x35, 0x3a, 0x30, 0x34, 0x3a, + 0x34, 0x36, 0x20, 0x47, 0x4d, 0x54, 0x0d, 0x0a, + 0x45, 0x54, 0x61, 0x67, 0x3a, 0x20, 0x22, 0x61, + 0x62, 0x38, 0x39, 0x36, 0x35, 0x2d, 0x32, 0x63, + 0x2d, 0x34, 0x39, 0x34, 0x33, 0x62, 0x37, 0x61, + 0x37, 0x66, 0x37, 0x66, 0x38, 0x30, 0x22, 0x0d, + 0x0a, 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x2d, + 0x52, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x3a, 0x20, + 0x62, 0x79, 0x74, 0x65, 0x73, 0x0d, 0x0a, 0x43, + 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x4c, + 0x65, 0x6e, 0x67, 0x74, 0x68, 0x3a, 0x20, 0x34, + 0x34, 0x0d, 0x0a, 0x43, 0x6f, 0x6e, 0x6e, 0x65, + 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x63, + 0x6c, 0x6f, 0x73, 0x65, 0x0d, 0x0a, 0x43, 0x6f, + 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x54, 0x79, + 0x70, 0x65, 0x3a, 0x20, 0x74, 0x65, 0x78, 0x74, + 0x2f, 0x68, 0x74, 0x6d, 0x6c, 0x0d, 0x0a, 0x58, + 0x2d, 0x50, 0x61, 0x64, 0x3a, 0x20, 0x61, 0x76, + 0x6f, 0x69, 0x64, 0x20, 0x62, 0x72, 0x6f, 0x77, + 0x73, 0x65, 0x72, 0x20, 0x62, 0x75, 0x67, 0x0d, + 0x0a, 0x0d, 0x0a, 0x3c, 0x68, 0x74, 0x6d, 0x6c, + 0x3e, 0x3c, 0x62, 0x6f, 0x64, 0x79, 0x3e, 0x3c, + 0x68, 0x31, 0x3e, 0x49, 0x74, 0x20, 0x77, 0x6f, + 0x72, 0x6b, 0x73, 0x21, 0x3c, 0x2f, 0x68, 0x31, + 0x3e, 0x3c, 0x2f, 0x62, 0x6f, 0x64, 0x79, 0x3e, + 0x3c, 0x2f, 0x68, 0x74, 0x6d, 0x6c, 0x3e }; + p->tcph->th_ack = htonl(17); + p->tcph->th_seq = htonl(5); + p->tcph->th_flags = TH_PUSH | TH_ACK; + p->flowflags = FLOW_PKT_TOCLIENT; + p->payload_len = sizeof(response2); + p->payload = response2; + if (StreamTcpPacket(&tv, p, stt, &pq) == -1) + goto end; + if (ssn->server.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED || + ssn->client.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED || + f.alproto != ALPROTO_UNKNOWN || + f.alproto_ts != ALPROTO_UNKNOWN || + f.alproto_tc != ALPROTO_UNKNOWN || + f.data_al_so_far[0] != 0 || + f.data_al_so_far[1] != 0 || + f.flags & FLOW_NO_APPLAYER_INSPECTION || + !FLOW_IS_PM_DONE(&f, STREAM_TOSERVER) || !FLOW_IS_PP_DONE(&f, STREAM_TOSERVER) || + FLOW_IS_PM_DONE(&f, STREAM_TOCLIENT) || !FLOW_IS_PP_DONE(&f, STREAM_TOCLIENT) || + ssn->data_first_seen_dir != STREAM_TOSERVER) { + printf("failure 8\n"); + goto end; + } + + /* response ack from request */ + p->tcph->th_ack = htonl(328); + p->tcph->th_seq = htonl(17); + p->tcph->th_flags = TH_ACK; + p->flowflags = FLOW_PKT_TOSERVER; + p->payload_len = 0; + p->payload = NULL; + if (StreamTcpPacket(&tv, p, stt, &pq) == -1) + goto end; + if (!(ssn->server.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED) || + !(ssn->client.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED) || + f.alproto != ALPROTO_UNKNOWN || + f.alproto_ts != ALPROTO_UNKNOWN || + f.alproto_tc != ALPROTO_UNKNOWN || + f.data_al_so_far[0] != 0 || + f.data_al_so_far[1] != 0 || + !(f.flags & FLOW_NO_APPLAYER_INSPECTION) || + !FLOW_IS_PM_DONE(&f, STREAM_TOSERVER) || !FLOW_IS_PP_DONE(&f, STREAM_TOSERVER) || + !FLOW_IS_PM_DONE(&f, STREAM_TOCLIENT) || !FLOW_IS_PP_DONE(&f, STREAM_TOCLIENT) || + ssn->data_first_seen_dir != 0x01) { + printf("failure 9\n"); + goto end; + } + + StreamTcpSessionClear(p->flow->protoctx); + + ret = 1; +end: + StreamTcpFreeConfig(TRUE); + SCFree(p); + return ret; +} + +#endif + +void AppLayerRegisterUnittests(void) +{ +#ifdef UNITTESTS + UtRegisterTest("AppLayerTest01", AppLayerTest01, 1); + UtRegisterTest("AppLayerTest02", AppLayerTest02, 1); + UtRegisterTest("AppLayerTest03", AppLayerTest03, 1); + UtRegisterTest("AppLayerTest04", AppLayerTest04, 1); + UtRegisterTest("AppLayerTest05", AppLayerTest05, 1); + UtRegisterTest("AppLayerTest06", AppLayerTest06, 1); + UtRegisterTest("AppLayerTest07", AppLayerTest07, 1); + UtRegisterTest("AppLayerTest08", AppLayerTest08, 1); + UtRegisterTest("AppLayerTest09", AppLayerTest09, 1); + UtRegisterTest("AppLayerTest10", AppLayerTest10, 1); + UtRegisterTest("AppLayerTest11", AppLayerTest11, 1); +#endif + + return; +} diff --git a/src/app-layer.h b/src/app-layer.h index 4465ce8256..047aca9433 100644 --- a/src/app-layer.h +++ b/src/app-layer.h @@ -38,10 +38,13 @@ uint16_t AppLayerGetProtoFromPacket(Packet *); void *AppLayerGetProtoStateFromPacket(Packet *); void *AppLayerGetProtoStateFromFlow(Flow *); -int AppLayerHandleTCPData(AlpProtoDetectThreadCtx *, Flow *, TcpSession *, TcpStream *, uint8_t *, uint32_t, uint8_t); +int AppLayerHandleTCPData(ThreadVars *tv, TcpReassemblyThreadCtx *ra_ctx, Flow *f, + TcpSession *ssn, TcpStream *stream, uint8_t *data, uint32_t data_len, Packet *p, uint8_t flags); int AppLayerHandleTCPMsg(AlpProtoDetectThreadCtx *, StreamMsg *); //int AppLayerHandleMsg(AlpProtoDetectThreadCtx *, StreamMsg *); int AppLayerHandleUdp(AlpProtoDetectThreadCtx *, Flow *, Packet *p); +void AppLayerRegisterUnittests(void); + #endif /* __APP_LAYER_H__ */ diff --git a/src/flow-util.h b/src/flow-util.h index 09a177c845..03cf471848 100644 --- a/src/flow-util.h +++ b/src/flow-util.h @@ -50,6 +50,10 @@ FLOWLOCK_INIT((f)); \ (f)->protoctx = NULL; \ (f)->alproto = 0; \ + (f)->alproto_ts = 0; \ + (f)->alproto_tc = 0; \ + (f)->data_al_so_far[0] = 0; \ + (f)->data_al_so_far[1] = 0; \ (f)->de_ctx_id = 0; \ (f)->alparser = NULL; \ (f)->alstate = NULL; \ @@ -85,6 +89,10 @@ (f)->alparser = NULL; \ (f)->alstate = NULL; \ (f)->alproto = 0; \ + (f)->alproto_ts = 0; \ + (f)->alproto_tc = 0; \ + (f)->data_al_so_far[0] = 0; \ + (f)->data_al_so_far[1] = 0; \ (f)->de_ctx_id = 0; \ if ((f)->de_state != NULL) { \ DetectEngineStateReset((f)->de_state, (STREAM_TOSERVER | STREAM_TOCLIENT)); \ diff --git a/src/flow.h b/src/flow.h index 98080626d0..ddde858462 100644 --- a/src/flow.h +++ b/src/flow.h @@ -327,6 +327,10 @@ typedef struct Flow_ uint8_t pad0; uint16_t alproto; /**< \brief application level protocol */ + uint16_t alproto_ts; + uint16_t alproto_tc; + + uint32_t data_al_so_far[2]; /** detection engine ctx id used to inspect this flow. Set at initial * inspection. If it doesn't match the currently in use de_ctx, the diff --git a/src/runmode-unittests.c b/src/runmode-unittests.c index 8113da5c0a..b58abcbd8c 100644 --- a/src/runmode-unittests.c +++ b/src/runmode-unittests.c @@ -63,6 +63,7 @@ #include "app-layer-detect-proto.h" #include "app-layer-parser.h" +#include "app-layer.h" #include "app-layer-smb.h" #include "app-layer-dcerpc.h" #include "app-layer-dcerpc-udp.h" @@ -257,6 +258,7 @@ int RunUnittests(int list_unittests, char *regex_arg) #ifdef __SC_CUDA_SUPPORT__ CudaBufferRegisterUnittests(); #endif + AppLayerRegisterUnittests(); if (list_unittests) { UtListTests(regex_arg); } else { diff --git a/src/stream-tcp-private.h b/src/stream-tcp-private.h index 5296ec3dd8..6e9f9922c4 100644 --- a/src/stream-tcp-private.h +++ b/src/stream-tcp-private.h @@ -215,6 +215,8 @@ typedef struct TcpSession_ { struct StreamMsg_ *toclient_smsg_head; /**< list of stream msgs (for detection inspection) */ struct StreamMsg_ *toclient_smsg_tail; /**< list of stream msgs (for detection inspection) */ + int8_t data_first_seen_dir; + TcpStateQueue *queue; /**< list of SYN/ACK candidates */ } TcpSession; diff --git a/src/stream-tcp-reassemble.c b/src/stream-tcp-reassemble.c index f3dc9e3e38..53267d7c88 100644 --- a/src/stream-tcp-reassemble.c +++ b/src/stream-tcp-reassemble.c @@ -1630,6 +1630,14 @@ int StreamTcpReassembleHandleSegmentHandleData(ThreadVars *tv, TcpReassemblyThre { SCEnter(); + if (ssn->data_first_seen_dir == 0) { + if (p->flowflags & FLOW_PKT_TOSERVER) { + ssn->data_first_seen_dir = STREAM_TOSERVER; + } else { + ssn->data_first_seen_dir = STREAM_TOCLIENT; + } + } + /* If we have reached the defined depth for either of the stream, then stop reassembling the TCP session */ uint32_t size = StreamTcpReassembleCheckDepth(stream, TCP_GET_SEQ(p), p->payload_len); @@ -1856,8 +1864,8 @@ static int StreamTcpReassembleInlineAppLayer (ThreadVars *tv, SCLogDebug("sending empty eof message"); /* send EOF to app layer */ STREAM_SET_INLINE_FLAGS(ssn, stream, p, flags); - AppLayerHandleTCPData(&ra_ctx->dp_ctx, p->flow, ssn, stream, - NULL, 0, flags); + AppLayerHandleTCPData(tv, ra_ctx, p->flow, ssn, stream, + NULL, 0, p, flags); PACKET_PROFILING_APP_STORE(&ra_ctx->dp_ctx, p); } else { @@ -1935,8 +1943,8 @@ static int StreamTcpReassembleInlineAppLayer (ThreadVars *tv, STREAM_SET_INLINE_FLAGS(ssn, stream, p, flags); /* process what we have so far */ - AppLayerHandleTCPData(&ra_ctx->dp_ctx, p->flow, ssn, stream, - data, data_len, flags); + AppLayerHandleTCPData(tv, ra_ctx, p->flow, ssn, stream, + data, data_len, p, flags); PACKET_PROFILING_APP_STORE(&ra_ctx->dp_ctx, p); data_sent += data_len; @@ -1964,8 +1972,8 @@ static int StreamTcpReassembleInlineAppLayer (ThreadVars *tv, /* send gap signal */ STREAM_SET_INLINE_FLAGS(ssn, stream, p, flags); - AppLayerHandleTCPData(&ra_ctx->dp_ctx, p->flow, ssn, stream, - NULL, 0, flags|STREAM_GAP); + AppLayerHandleTCPData(tv, ra_ctx, p->flow, ssn, stream, + NULL, 0, p, flags|STREAM_GAP); PACKET_PROFILING_APP_STORE(&ra_ctx->dp_ctx, p); data_len = 0; @@ -2036,8 +2044,8 @@ static int StreamTcpReassembleInlineAppLayer (ThreadVars *tv, /* process what we have so far */ STREAM_SET_INLINE_FLAGS(ssn, stream, p, flags); BUG_ON(data_len > sizeof(data)); - AppLayerHandleTCPData(&ra_ctx->dp_ctx, p->flow, ssn, stream, - data, data_len, flags); + AppLayerHandleTCPData(tv, ra_ctx, p->flow, ssn, stream, + data, data_len, p, flags); PACKET_PROFILING_APP_STORE(&ra_ctx->dp_ctx, p); data_sent += data_len; data_len = 0; @@ -2090,8 +2098,8 @@ static int StreamTcpReassembleInlineAppLayer (ThreadVars *tv, /* process what we have so far */ STREAM_SET_INLINE_FLAGS(ssn, stream, p, flags); BUG_ON(data_len > sizeof(data)); - AppLayerHandleTCPData(&ra_ctx->dp_ctx, p->flow, ssn, stream, - data, data_len, flags); + AppLayerHandleTCPData(tv, ra_ctx, p->flow, ssn, stream, + data, data_len, p, flags); PACKET_PROFILING_APP_STORE(&ra_ctx->dp_ctx, p); data_sent += data_len; data_len = 0; @@ -2126,8 +2134,8 @@ static int StreamTcpReassembleInlineAppLayer (ThreadVars *tv, /* process what we have so far */ STREAM_SET_INLINE_FLAGS(ssn, stream, p, flags); BUG_ON(data_len > sizeof(data)); - AppLayerHandleTCPData(&ra_ctx->dp_ctx, p->flow, ssn, stream, - data, data_len, flags); + AppLayerHandleTCPData(tv, ra_ctx, p->flow, ssn, stream, + data, data_len, p, flags); PACKET_PROFILING_APP_STORE(&ra_ctx->dp_ctx, p); data_sent += data_len; } @@ -2136,8 +2144,8 @@ static int StreamTcpReassembleInlineAppLayer (ThreadVars *tv, SCLogDebug("sending empty eof message"); /* send EOF to app layer */ STREAM_SET_INLINE_FLAGS(ssn, stream, p, flags); - AppLayerHandleTCPData(&ra_ctx->dp_ctx, p->flow, ssn, stream, - NULL, 0, flags); + AppLayerHandleTCPData(tv, ra_ctx, p->flow, ssn, stream, + NULL, 0, p, flags); PACKET_PROFILING_APP_STORE(&ra_ctx->dp_ctx, p); } @@ -2570,9 +2578,9 @@ void StreamTcpPruneSession(Flow *f, uint8_t flags) { * * \todo this function is too long, we need to break it up. It needs it BAD */ -static int StreamTcpReassembleAppLayer (ThreadVars *tv, - TcpReassemblyThreadCtx *ra_ctx, TcpSession *ssn, TcpStream *stream, - Packet *p) +int StreamTcpReassembleAppLayer (ThreadVars *tv, TcpReassemblyThreadCtx *ra_ctx, + TcpSession *ssn, TcpStream *stream, + Packet *p) { SCEnter(); @@ -2595,8 +2603,8 @@ static int StreamTcpReassembleAppLayer (ThreadVars *tv, SCLogDebug("sending empty eof message"); /* send EOF to app layer */ STREAM_SET_FLAGS(ssn, stream, p, flags); - AppLayerHandleTCPData(&ra_ctx->dp_ctx, p->flow, ssn, stream, - NULL, 0, flags); + AppLayerHandleTCPData(tv, ra_ctx, p->flow, ssn, stream, + NULL, 0, p, flags); PACKET_PROFILING_APP_STORE(&ra_ctx->dp_ctx, p); SCReturnInt(0); @@ -2699,8 +2707,8 @@ static int StreamTcpReassembleAppLayer (ThreadVars *tv, STREAM_SET_FLAGS(ssn, stream, p, flags); /* process what we have so far */ - AppLayerHandleTCPData(&ra_ctx->dp_ctx, p->flow, ssn, stream, - data, data_len, flags); + AppLayerHandleTCPData(tv, ra_ctx, p->flow, ssn, stream, + data, data_len, p, flags); PACKET_PROFILING_APP_STORE(&ra_ctx->dp_ctx, p); data_len = 0; } @@ -2726,8 +2734,8 @@ static int StreamTcpReassembleAppLayer (ThreadVars *tv, /* send gap signal */ STREAM_SET_FLAGS(ssn, stream, p, flags); - AppLayerHandleTCPData(&ra_ctx->dp_ctx, p->flow, ssn, stream, - NULL, 0, flags|STREAM_GAP); + AppLayerHandleTCPData(tv, ra_ctx, p->flow, ssn, stream, + NULL, 0, p, flags|STREAM_GAP); PACKET_PROFILING_APP_STORE(&ra_ctx->dp_ctx, p); data_len = 0; @@ -2823,8 +2831,8 @@ static int StreamTcpReassembleAppLayer (ThreadVars *tv, /* process what we have so far */ STREAM_SET_FLAGS(ssn, stream, p, flags); BUG_ON(data_len > sizeof(data)); - AppLayerHandleTCPData(&ra_ctx->dp_ctx, p->flow, ssn, stream, - data, data_len, flags); + AppLayerHandleTCPData(tv, ra_ctx, p->flow, ssn, stream, + data, data_len, p, flags); PACKET_PROFILING_APP_STORE(&ra_ctx->dp_ctx, p); data_len = 0; @@ -2883,8 +2891,8 @@ static int StreamTcpReassembleAppLayer (ThreadVars *tv, /* process what we have so far */ STREAM_SET_FLAGS(ssn, stream, p, flags); BUG_ON(data_len > sizeof(data)); - AppLayerHandleTCPData(&ra_ctx->dp_ctx, p->flow, ssn, stream, - data, data_len, flags); + AppLayerHandleTCPData(tv, ra_ctx, p->flow, ssn, stream, + data, data_len, p, flags); PACKET_PROFILING_APP_STORE(&ra_ctx->dp_ctx, p); data_len = 0; @@ -2930,8 +2938,8 @@ static int StreamTcpReassembleAppLayer (ThreadVars *tv, /* process what we have so far */ STREAM_SET_FLAGS(ssn, stream, p, flags); BUG_ON(data_len > sizeof(data)); - AppLayerHandleTCPData(&ra_ctx->dp_ctx, p->flow, ssn, stream, - data, data_len, flags); + AppLayerHandleTCPData(tv, ra_ctx, p->flow, ssn, stream, + data, data_len, p, flags); PACKET_PROFILING_APP_STORE(&ra_ctx->dp_ctx, p); } @@ -5997,9 +6005,16 @@ static int StreamTcpReassembleTest37(void) { * until the app layer protocol has been detected and one smsg from * toserver side has been sent to app layer. * + * Unittest modified by commit - + * + * commit bab1636377bb4f1b7b889f4e3fd594795085eaa4 + * Author: Anoop Saldanha + * Date: Fri Feb 15 18:58:33 2013 +0530 + * + * Improved app protocol detection. + * * \retval On success it returns 1 and on failure 0. */ - static int StreamTcpReassembleTest38 (void) { int ret = 0; Packet *p = PacketGetFromAlloc(); @@ -6022,12 +6037,12 @@ static int StreamTcpReassembleTest38 (void) { StreamTcpInitConfig(TRUE); TcpReassemblyThreadCtx *ra_ctx = StreamTcpReassembleInitThreadCtx(); - uint8_t httpbuf1[] = "POST / HTTP/1.0\r\nUser-Agent: Victor/1.0\r\n\r\n"; - uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */ - - uint8_t httpbuf2[] = "HTTP/1.0 200 OK\r\nServer: VictorServer/1.0\r\n\r\n"; + uint8_t httpbuf2[] = "POST / HTTP/1.0\r\nUser-Agent: Victor/1.0\r\n\r\n"; uint32_t httplen2 = sizeof(httpbuf2) - 1; /* minus the \0 */ + uint8_t httpbuf1[] = "HTTP/1.0 200 OK\r\nServer: VictorServer/1.0\r\n\r\n"; + uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */ + FLOW_INITIALIZE(&f); if (inet_pton(AF_INET, "1.2.3.4", &in) != 1) goto end; @@ -6057,7 +6072,7 @@ static int StreamTcpReassembleTest38 (void) { tcph.th_ack = htonl(20); tcph.th_flags = TH_ACK|TH_PUSH; p->tcph = &tcph; - p->flowflags = FLOW_PKT_TOCLIENT; + p->flowflags = FLOW_PKT_TOSERVER; p->payload = httpbuf2; p->payload_len = httplen2; @@ -6078,7 +6093,7 @@ static int StreamTcpReassembleTest38 (void) { goto end; } - p->flowflags = FLOW_PKT_TOSERVER; + p->flowflags = FLOW_PKT_TOCLIENT; p->payload = httpbuf1; p->payload_len = httplen1; tcph.th_seq = htonl(10); @@ -6091,53 +6106,11 @@ static int StreamTcpReassembleTest38 (void) { } /* Check if we have stream smsgs in queue */ - if (ra_ctx->stream_q->len > 0) { - printf("there shouldn't be any stream smsgs in the queue, as we didn't" - " processed any smsg from toserver side till yet (4): "); - goto end; - } - - p->flowflags = FLOW_PKT_TOCLIENT; - p->payload = httpbuf2; - p->payload_len = httplen2; - tcph.th_seq = htonl(55); - tcph.th_ack = htonl(53); - s = &ssn.server; - if (StreamTcpReassembleHandleSegment(&tv, ra_ctx, &ssn, s, p, &pq) == -1) { - printf("failed in segments reassembly, while processing toserver packet (5): "); - goto end; - } - - /* we should now have a smsg as the http request is complete and triggered - * reassembly */ if (ra_ctx->stream_q->len != 1) { printf("there should one stream smsg in the queue (6): "); goto end; } - p->flowflags = FLOW_PKT_TOSERVER; - p->payload = httpbuf1; - p->payload_len = httplen1; - tcph.th_seq = htonl(53); - tcph.th_ack = htonl(100); - s = &ssn.client; - if (StreamTcpReassembleHandleSegment(&tv, ra_ctx, &ssn, s, p, &pq) == -1) { - printf("failed in segments reassembly, while processing toserver packet (8): "); - goto end; - } - - p->flowflags = FLOW_PKT_TOCLIENT; - p->payload = NULL; - p->payload_len = 0; - tcph.th_seq = htonl(100); - tcph.th_ack = htonl(53); - s = &ssn.server; - - if (StreamTcpReassembleHandleSegment(&tv, ra_ctx, &ssn, s, p, &pq) == -1) { - printf("failed in segments reassembly, while processing toserver packet (9): "); - goto end; - } - ret = 1; end: StreamTcpReassembleFreeThreadCtx(ra_ctx); @@ -6156,205 +6129,590 @@ end: */ static int StreamTcpReassembleTest39 (void) { - SCEnter(); - - int ret = 0; Packet *p = PacketGetFromAlloc(); if (unlikely(p == NULL)) return 0; - Flow *f = NULL; + Flow f; + ThreadVars tv; + StreamTcpThread *stt = NULL; TCPHdr tcph; - TcpSession ssn; PacketQueue pq; memset(&pq,0,sizeof(PacketQueue)); - memset(&tcph, 0, sizeof (TCPHdr)); - memset(&ssn, 0, sizeof(TcpSession)); - ThreadVars tv; + memset (&f, 0, sizeof(Flow)); memset(&tv, 0, sizeof (ThreadVars)); + StreamTcpThreadInit(&tv, NULL, (void **)&stt); + memset(&tcph, 0, sizeof (TCPHdr)); - StreamTcpInitConfig(TRUE); - TcpReassemblyThreadCtx *ra_ctx = StreamTcpReassembleInitThreadCtx(); - StreamMsgQueueSetMinChunkLen(FLOW_PKT_TOSERVER, 7); - StreamMsgQueueSetMinChunkLen(FLOW_PKT_TOCLIENT, 7); - - uint8_t httpbuf1[] = "POST / HTTP/1.0\r\nUser-Agent: Victor/1.0\r\n\r\n"; - uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */ - - uint8_t httpbuf2[] = "HTTP/1.0 200 OK\r\nServer: VictorServer/1.0\r\n\r\n"; - uint32_t httplen2 = sizeof(httpbuf2) - 1; /* minus the \0 */ - - ssn.server.ra_raw_base_seq = ssn.server.ra_app_base_seq = 9; - ssn.server.isn = 9; - ssn.server.last_ack = 160; - ssn.client.ra_raw_base_seq = ssn.client.ra_app_base_seq= 9; - ssn.client.isn = 9; - ssn.client.last_ack = 160; - - f = UTHBuildFlow(AF_INET, "1.2.3.4", "1.2.3.5", 200, 220); - if (f == NULL) - goto end; - f->protoctx = &ssn; - p->flow = f; - - SCLogDebug("check client seg list %p", ssn.client.seg_list); - tcph.th_win = htons(5480); - tcph.th_seq = htonl(10); - tcph.th_ack = htonl(20); - tcph.th_flags = TH_ACK|TH_PUSH; + f.flags = FLOW_IPV4; + p->pkt = (uint8_t *)(p + 1); + p->flow = &f; p->tcph = &tcph; - p->flowflags = FLOW_PKT_TOCLIENT; - p->payload = httpbuf2; - p->payload_len = httplen2; - ssn.state = TCP_ESTABLISHED; - - TcpStream *s = NULL; - s = &ssn.server; - - SCMutexLock(&f->m); - if (StreamTcpReassembleHandleSegment(&tv, ra_ctx, &ssn, s, p, &pq) == -1) { - printf("failed in segments reassembly, while processing toserver packet (1): "); - goto end; - } + SCMutexLock(&f.m); + int ret = 0; - /* Check if we have stream smsgs in queue */ - if (ra_ctx->stream_q->len > 0) { - printf("there shouldn't be any stream smsgs in the queue: (2): "); - goto end; - } + StreamTcpInitConfig(TRUE); - SCLogDebug("check client seg list %p", ssn.client.seg_list); + /* handshake */ + tcph.th_win = htons(5480); + tcph.th_flags = TH_SYN; p->flowflags = FLOW_PKT_TOSERVER; - p->payload = httpbuf1; - p->payload_len = httplen1; - tcph.th_seq = htonl(10); - tcph.th_ack = htonl(55); - s = &ssn.client; - - if (StreamTcpReassembleHandleSegment(&tv, ra_ctx, &ssn, s, p, &pq) == -1) { - printf("failed in segments reassembly, while processing toserver packet (3): "); - goto end; - } - - /* Check if we have stream smsgs in queue */ - if (ra_ctx->stream_q->len == 0) { - printf("there should be stream smsgs in the queue (4): "); - goto end; - } - SCLogDebug("check client seg list %p", ssn.client.seg_list); - - - p->flowflags = FLOW_PKT_TOCLIENT; - p->payload = httpbuf2; - p->payload_len = httplen2; - tcph.th_seq = htonl(55); - tcph.th_ack = htonl(53); - s = &ssn.server; - - if (StreamTcpReassembleHandleSegment(&tv, ra_ctx, &ssn, s, p, &pq) == -1) { - printf("failed in segments reassembly, while processing toserver packet (5): "); + p->payload_len = 0; + p->payload = NULL; + if (StreamTcpPacket(&tv, p, stt, &pq) == -1) goto end; - } - SCLogDebug("check client seg list %p", ssn.client.seg_list); + TcpSession *ssn = (TcpSession *)f.protoctx; - /* Check if we have stream smsgs in queue */ - SCLogDebug("check if we have stream smsgs in queue"); - if (ra_ctx->stream_q->len == 0) { - printf("there should be a stream smsgs in the queue (6): "); - goto end; - } - - SCLogDebug("check client seg list %p", ssn.client.seg_list); - /* Process stream smsgs we may have in queue */ - SCLogDebug("process stream smsgs we may have in queue"); - if (StreamTcpReassembleProcessAppLayer(ra_ctx) < 0) { - printf("failed in processing stream smsgs (7): "); + if (ssn->server.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED || + ssn->client.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED || + f.alproto != ALPROTO_UNKNOWN || + f.alproto_ts != ALPROTO_UNKNOWN || + f.alproto_tc != ALPROTO_UNKNOWN || + f.data_al_so_far[0] != 0 || + f.data_al_so_far[1] != 0 || + f.flags & FLOW_NO_APPLAYER_INSPECTION || + FLOW_IS_PM_DONE(&f, STREAM_TOSERVER) || FLOW_IS_PP_DONE(&f, STREAM_TOSERVER) || + FLOW_IS_PM_DONE(&f, STREAM_TOCLIENT) || FLOW_IS_PP_DONE(&f, STREAM_TOCLIENT) || + ssn->client.seg_list != NULL || + ssn->server.seg_list != NULL || + stt->ra_ctx->stream_q->len != 0 || + ssn->data_first_seen_dir != 0) { + printf("failure 1\n"); goto end; } - SCLogDebug("check client seg list %p", ssn.client.seg_list); - - /* check is have the segment in the list and flagged or not */ -/* - if (ssn.client.seg_list == NULL || - !(ssn.client.seg_list->flags & SEGMENTTCP_FLAG_RAW_PROCESSED)) - { - printf("the list is NULL or the processed segment has not been flaged (8), seg %p, flags %02X: ", - ssn.client.seg_list, ssn.client.seg_list? ssn.client.seg_list->flags:0); -//abort(); - goto end; - } -*/ + /* handshake */ + p->tcph->th_ack = htonl(1); + p->tcph->th_flags = TH_SYN | TH_ACK; + p->flowflags = FLOW_PKT_TOCLIENT; + p->payload_len = 0; + p->payload = NULL; + if (StreamTcpPacket(&tv, p, stt, &pq) == -1) + goto end; + if (ssn->server.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED || + ssn->client.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED || + f.alproto != ALPROTO_UNKNOWN || + f.alproto_ts != ALPROTO_UNKNOWN || + f.alproto_tc != ALPROTO_UNKNOWN || + f.data_al_so_far[0] != 0 || + f.data_al_so_far[1] != 0 || + f.flags & FLOW_NO_APPLAYER_INSPECTION || + FLOW_IS_PM_DONE(&f, STREAM_TOSERVER) || FLOW_IS_PP_DONE(&f, STREAM_TOSERVER) || + FLOW_IS_PM_DONE(&f, STREAM_TOCLIENT) || FLOW_IS_PP_DONE(&f, STREAM_TOCLIENT) || + ssn->client.seg_list != NULL || + ssn->server.seg_list != NULL || + stt->ra_ctx->stream_q->len != 0 || + ssn->data_first_seen_dir != 0) { + printf("failure 2\n"); + goto end; + } + + /* handshake */ + p->tcph->th_ack = htonl(1); + p->tcph->th_seq = htonl(1); + p->tcph->th_flags = TH_ACK; p->flowflags = FLOW_PKT_TOSERVER; - p->payload = httpbuf1; - p->payload_len = httplen1; - tcph.th_seq = htonl(53); - tcph.th_ack = htonl(100); - s = &ssn.client; - - if (StreamTcpReassembleHandleSegment(&tv, ra_ctx, &ssn, s, p, &pq) == -1) { - printf("failed in segments reassembly, while processing toserver packet (9): "); - goto end; - } - - /* Check if we have stream smsgs in queue */ - if (ra_ctx->stream_q->len == 0 && - !(ssn.client.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED)) { - printf("there should be a stream smsgs in the queue, as we have detected" - " the app layer protocol and one smsg from toserver side has " - "been sent (10): "); - goto end; - /* Process stream smsgs we may have in queue */ - } else if (StreamTcpReassembleProcessAppLayer(ra_ctx) < 0) { - printf("failed in processing stream smsgs (11): "); - goto end; - } - + p->payload_len = 0; + p->payload = NULL; + if (StreamTcpPacket(&tv, p, stt, &pq) == -1) + goto end; + if (ssn->server.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED || + ssn->client.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED || + f.alproto != ALPROTO_UNKNOWN || + f.alproto_ts != ALPROTO_UNKNOWN || + f.alproto_tc != ALPROTO_UNKNOWN || + f.data_al_so_far[0] != 0 || + f.data_al_so_far[1] != 0 || + f.flags & FLOW_NO_APPLAYER_INSPECTION || + FLOW_IS_PM_DONE(&f, STREAM_TOSERVER) || FLOW_IS_PP_DONE(&f, STREAM_TOSERVER) || + FLOW_IS_PM_DONE(&f, STREAM_TOCLIENT) || FLOW_IS_PP_DONE(&f, STREAM_TOCLIENT) || + ssn->client.seg_list != NULL || + ssn->server.seg_list != NULL || + stt->ra_ctx->stream_q->len != 0 || + ssn->data_first_seen_dir != 0) { + printf("failure 3\n"); + goto end; + } + + /* partial request */ + uint8_t request1[] = { 0x47, 0x45, }; + p->tcph->th_ack = htonl(1); + p->tcph->th_seq = htonl(1); + p->tcph->th_flags = TH_PUSH | TH_ACK; + p->flowflags = FLOW_PKT_TOSERVER; + p->payload_len = sizeof(request1); + p->payload = request1; + if (StreamTcpPacket(&tv, p, stt, &pq) == -1) + goto end; + if (ssn->server.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED || + ssn->client.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED || + f.alproto != ALPROTO_UNKNOWN || + f.alproto_ts != ALPROTO_UNKNOWN || + f.alproto_tc != ALPROTO_UNKNOWN || + f.data_al_so_far[0] != 0 || + f.data_al_so_far[1] != 0 || + f.flags & FLOW_NO_APPLAYER_INSPECTION || + FLOW_IS_PM_DONE(&f, STREAM_TOSERVER) || FLOW_IS_PP_DONE(&f, STREAM_TOSERVER) || + FLOW_IS_PM_DONE(&f, STREAM_TOCLIENT) || FLOW_IS_PP_DONE(&f, STREAM_TOCLIENT) || + ssn->client.seg_list == NULL || + ssn->client.seg_list->next != NULL || + ssn->server.seg_list != NULL || + stt->ra_ctx->stream_q->len != 0 || + ssn->data_first_seen_dir != STREAM_TOSERVER) { + printf("failure 4\n"); + goto end; + } + + + /* response ack against partial request */ + p->tcph->th_ack = htonl(3); + p->tcph->th_seq = htonl(1); + p->tcph->th_flags = TH_ACK; p->flowflags = FLOW_PKT_TOCLIENT; - p->payload = httpbuf2; - p->payload_len = httplen2; - tcph.th_seq = htonl(100); - tcph.th_ack = htonl(96); - s = &ssn.server; - - if (StreamTcpReassembleHandleSegment(&tv, ra_ctx, &ssn, s, p, &pq) == -1) { - printf("failed in segments reassembly, while processing toserver packet (12): "); - goto end; - } - - SCLogDebug("final check"); - - if (!(ssn.client.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED)) { - printf("STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED flag should have been set (13): "); - goto end; - } - - /* check if the segment in the list is flagged or not */ - if (ssn.client.seg_list == NULL) { - printf("segment list should not be empty (14): "); + p->payload_len = 0; + p->payload = NULL; + if (StreamTcpPacket(&tv, p, stt, &pq) == -1) + goto end; + if (ssn->server.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED || + ssn->client.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED || + f.alproto != ALPROTO_UNKNOWN || + f.alproto_ts != ALPROTO_UNKNOWN || + f.alproto_tc != ALPROTO_UNKNOWN || + f.data_al_so_far[0] != 0 || + f.data_al_so_far[1] != 0 || + f.flags & FLOW_NO_APPLAYER_INSPECTION || + FLOW_IS_PM_DONE(&f, STREAM_TOSERVER) || !FLOW_IS_PP_DONE(&f, STREAM_TOSERVER) || + FLOW_IS_PM_DONE(&f, STREAM_TOCLIENT) || FLOW_IS_PP_DONE(&f, STREAM_TOCLIENT) || + ssn->client.seg_list == NULL || + ssn->client.seg_list->next != NULL || + ssn->server.seg_list != NULL || + stt->ra_ctx->stream_q->len != 0 || + ssn->data_first_seen_dir != STREAM_TOSERVER) { + printf("failure 5\n"); + goto end; + } + + /* complete partial request */ + uint8_t request2[] = { + 0x54, 0x20, 0x2f, 0x69, 0x6e, 0x64, + 0x65, 0x78, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0x20, + 0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, 0x2e, 0x30, + 0x0d, 0x0a, 0x48, 0x6f, 0x73, 0x74, 0x3a, 0x20, + 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x68, 0x6f, 0x73, + 0x74, 0x0d, 0x0a, 0x55, 0x73, 0x65, 0x72, 0x2d, + 0x41, 0x67, 0x65, 0x6e, 0x74, 0x3a, 0x20, 0x41, + 0x70, 0x61, 0x63, 0x68, 0x65, 0x42, 0x65, 0x6e, + 0x63, 0x68, 0x2f, 0x32, 0x2e, 0x33, 0x0d, 0x0a, + 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x3a, 0x20, + 0x2a, 0x2f, 0x2a, 0x0d, 0x0a, 0x0d, 0x0a }; + p->tcph->th_ack = htonl(1); + p->tcph->th_seq = htonl(3); + p->tcph->th_flags = TH_PUSH | TH_ACK; + p->flowflags = FLOW_PKT_TOSERVER; + p->payload_len = sizeof(request2); + p->payload = request2; + if (StreamTcpPacket(&tv, p, stt, &pq) == -1) + goto end; + if (ssn->server.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED || + ssn->client.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED || + f.alproto != ALPROTO_UNKNOWN || + f.alproto_ts != ALPROTO_UNKNOWN || + f.alproto_tc != ALPROTO_UNKNOWN || + f.data_al_so_far[0] != 0 || + f.data_al_so_far[1] != 0 || + f.flags & FLOW_NO_APPLAYER_INSPECTION || + FLOW_IS_PM_DONE(&f, STREAM_TOSERVER) || !FLOW_IS_PP_DONE(&f, STREAM_TOSERVER) || + FLOW_IS_PM_DONE(&f, STREAM_TOCLIENT) || FLOW_IS_PP_DONE(&f, STREAM_TOCLIENT) || + ssn->client.seg_list == NULL || + ssn->client.seg_list->next == NULL || + ssn->client.seg_list->next->next != NULL || + ssn->server.seg_list != NULL || + stt->ra_ctx->stream_q->len != 0 || + ssn->data_first_seen_dir != STREAM_TOSERVER) { + printf("failure 6\n"); + goto end; + } + + /* response - request ack */ + uint8_t response[] = { + 0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, 0x2e, 0x31, + 0x20, 0x32, 0x30, 0x30, 0x20, 0x4f, 0x4b, 0x0d, + 0x0a, 0x44, 0x61, 0x74, 0x65, 0x3a, 0x20, 0x46, + 0x72, 0x69, 0x2c, 0x20, 0x32, 0x33, 0x20, 0x53, + 0x65, 0x70, 0x20, 0x32, 0x30, 0x31, 0x31, 0x20, + 0x30, 0x36, 0x3a, 0x32, 0x39, 0x3a, 0x33, 0x39, + 0x20, 0x47, 0x4d, 0x54, 0x0d, 0x0a, 0x53, 0x65, + 0x72, 0x76, 0x65, 0x72, 0x3a, 0x20, 0x41, 0x70, + 0x61, 0x63, 0x68, 0x65, 0x2f, 0x32, 0x2e, 0x32, + 0x2e, 0x31, 0x35, 0x20, 0x28, 0x55, 0x6e, 0x69, + 0x78, 0x29, 0x20, 0x44, 0x41, 0x56, 0x2f, 0x32, + 0x0d, 0x0a, 0x4c, 0x61, 0x73, 0x74, 0x2d, 0x4d, + 0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, 0x64, 0x3a, + 0x20, 0x54, 0x68, 0x75, 0x2c, 0x20, 0x30, 0x34, + 0x20, 0x4e, 0x6f, 0x76, 0x20, 0x32, 0x30, 0x31, + 0x30, 0x20, 0x31, 0x35, 0x3a, 0x30, 0x34, 0x3a, + 0x34, 0x36, 0x20, 0x47, 0x4d, 0x54, 0x0d, 0x0a, + 0x45, 0x54, 0x61, 0x67, 0x3a, 0x20, 0x22, 0x61, + 0x62, 0x38, 0x39, 0x36, 0x35, 0x2d, 0x32, 0x63, + 0x2d, 0x34, 0x39, 0x34, 0x33, 0x62, 0x37, 0x61, + 0x37, 0x66, 0x37, 0x66, 0x38, 0x30, 0x22, 0x0d, + 0x0a, 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x2d, + 0x52, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x3a, 0x20, + 0x62, 0x79, 0x74, 0x65, 0x73, 0x0d, 0x0a, 0x43, + 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x4c, + 0x65, 0x6e, 0x67, 0x74, 0x68, 0x3a, 0x20, 0x34, + 0x34, 0x0d, 0x0a, 0x43, 0x6f, 0x6e, 0x6e, 0x65, + 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x63, + 0x6c, 0x6f, 0x73, 0x65, 0x0d, 0x0a, 0x43, 0x6f, + 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x54, 0x79, + 0x70, 0x65, 0x3a, 0x20, 0x74, 0x65, 0x78, 0x74, + 0x2f, 0x68, 0x74, 0x6d, 0x6c, 0x0d, 0x0a, 0x58, + 0x2d, 0x50, 0x61, 0x64, 0x3a, 0x20, 0x61, 0x76, + 0x6f, 0x69, 0x64, 0x20, 0x62, 0x72, 0x6f, 0x77, + 0x73, 0x65, 0x72, 0x20, 0x62, 0x75, 0x67, 0x0d, + 0x0a, 0x0d, 0x0a, 0x3c, 0x68, 0x74, 0x6d, 0x6c, + 0x3e, 0x3c, 0x62, 0x6f, 0x64, 0x79, 0x3e, 0x3c, + 0x68, 0x31, 0x3e, 0x49, 0x74, 0x20, 0x77, 0x6f, + 0x72, 0x6b, 0x73, 0x21, 0x3c, 0x2f, 0x68, 0x31, + 0x3e, 0x3c, 0x2f, 0x62, 0x6f, 0x64, 0x79, 0x3e, + 0x3c, 0x2f, 0x68, 0x74, 0x6d, 0x6c, 0x3e }; + p->tcph->th_ack = htonl(88); + p->tcph->th_seq = htonl(1); + p->tcph->th_flags = TH_PUSH | TH_ACK; + p->flowflags = FLOW_PKT_TOCLIENT; + p->payload_len = sizeof(response); + p->payload = response; + if (StreamTcpPacket(&tv, p, stt, &pq) == -1) + goto end; + if (ssn->server.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED || + !(ssn->client.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED) || + f.alproto != ALPROTO_HTTP || + f.alproto_ts != ALPROTO_HTTP || + f.alproto_tc != ALPROTO_UNKNOWN || + f.data_al_so_far[0] != 0 || + f.data_al_so_far[1] != 0 || + f.flags & FLOW_NO_APPLAYER_INSPECTION || + !FLOW_IS_PM_DONE(&f, STREAM_TOSERVER) || !FLOW_IS_PP_DONE(&f, STREAM_TOSERVER) || + FLOW_IS_PM_DONE(&f, STREAM_TOCLIENT) || FLOW_IS_PP_DONE(&f, STREAM_TOCLIENT) || + ssn->client.seg_list == NULL || + ssn->client.seg_list->next == NULL || + ssn->client.seg_list->next->next != NULL || + ssn->server.seg_list == NULL || + ssn->server.seg_list->next != NULL || + ssn->data_first_seen_dir != 0x01) { + printf("failure 7\n"); + goto end; + } + + /* response ack from request */ + p->tcph->th_ack = htonl(328); + p->tcph->th_seq = htonl(88); + p->tcph->th_flags = TH_ACK; + p->flowflags = FLOW_PKT_TOSERVER; + p->payload_len = 0; + p->payload = NULL; + if (StreamTcpPacket(&tv, p, stt, &pq) == -1) + goto end; + if (!(ssn->server.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED) || + !(ssn->client.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED) || + f.alproto != ALPROTO_HTTP || + f.alproto_ts != ALPROTO_HTTP || + f.alproto_tc != ALPROTO_HTTP || + f.data_al_so_far[0] != 0 || + f.data_al_so_far[1] != 0 || + f.flags & FLOW_NO_APPLAYER_INSPECTION || + !FLOW_IS_PM_DONE(&f, STREAM_TOSERVER) || !FLOW_IS_PP_DONE(&f, STREAM_TOSERVER) || + !FLOW_IS_PM_DONE(&f, STREAM_TOCLIENT) || FLOW_IS_PP_DONE(&f, STREAM_TOCLIENT) || + ssn->client.seg_list == NULL || + ssn->client.seg_list->next == NULL || + ssn->client.seg_list->next->next != NULL || + ssn->server.seg_list == NULL || + ssn->server.seg_list->next != NULL || + ssn->data_first_seen_dir != 0x01) { + printf("failure 8\n"); + goto end; + } + + /* response - acking */ + p->tcph->th_ack = htonl(88); + p->tcph->th_seq = htonl(328); + p->tcph->th_flags = TH_PUSH | TH_ACK; + p->flowflags = FLOW_PKT_TOCLIENT; + p->payload_len = 0; + p->payload = NULL; + if (StreamTcpPacket(&tv, p, stt, &pq) == -1) + goto end; + if (!(ssn->server.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED) || + !(ssn->client.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED) || + f.alproto != ALPROTO_HTTP || + f.alproto_ts != ALPROTO_HTTP || + f.alproto_tc != ALPROTO_HTTP || + f.data_al_so_far[0] != 0 || + f.data_al_so_far[1] != 0 || + f.flags & FLOW_NO_APPLAYER_INSPECTION || + !FLOW_IS_PM_DONE(&f, STREAM_TOSERVER) || !FLOW_IS_PP_DONE(&f, STREAM_TOSERVER) || + !FLOW_IS_PM_DONE(&f, STREAM_TOCLIENT) || FLOW_IS_PP_DONE(&f, STREAM_TOCLIENT) || + ssn->client.seg_list == NULL || + ssn->client.seg_list->next != NULL || + ssn->server.seg_list == NULL || + ssn->server.seg_list->next != NULL || + ssn->data_first_seen_dir != 0x01) { + printf("failure 9\n"); + goto end; + } + + /* response ack from request */ + p->tcph->th_ack = htonl(328); + p->tcph->th_seq = htonl(88); + p->tcph->th_flags = TH_ACK; + p->flowflags = FLOW_PKT_TOSERVER; + p->payload_len = 0; + p->payload = NULL; + if (StreamTcpPacket(&tv, p, stt, &pq) == -1) + goto end; + if (!(ssn->server.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED) || + !(ssn->client.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED) || + f.alproto != ALPROTO_HTTP || + f.alproto_ts != ALPROTO_HTTP || + f.alproto_tc != ALPROTO_HTTP || + f.data_al_so_far[0] != 0 || + f.data_al_so_far[1] != 0 || + f.flags & FLOW_NO_APPLAYER_INSPECTION || + !FLOW_IS_PM_DONE(&f, STREAM_TOSERVER) || !FLOW_IS_PP_DONE(&f, STREAM_TOSERVER) || + !FLOW_IS_PM_DONE(&f, STREAM_TOCLIENT) || FLOW_IS_PP_DONE(&f, STREAM_TOCLIENT) || + ssn->client.seg_list == NULL || + ssn->client.seg_list->next != NULL || + ssn->server.seg_list == NULL || + ssn->server.seg_list->next != NULL || + ssn->data_first_seen_dir != 0x01) { + printf("failure 10\n"); + goto end; + } + + /* response - acking the request again*/ + p->tcph->th_ack = htonl(88); + p->tcph->th_seq = htonl(328); + p->tcph->th_flags = TH_PUSH | TH_ACK; + p->flowflags = FLOW_PKT_TOCLIENT; + p->payload_len = 0; + p->payload = NULL; + if (StreamTcpPacket(&tv, p, stt, &pq) == -1) + goto end; + if (!(ssn->server.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED) || + !(ssn->client.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED) || + f.alproto != ALPROTO_HTTP || + f.alproto_ts != ALPROTO_HTTP || + f.alproto_tc != ALPROTO_HTTP || + f.data_al_so_far[0] != 0 || + f.data_al_so_far[1] != 0 || + f.flags & FLOW_NO_APPLAYER_INSPECTION || + !FLOW_IS_PM_DONE(&f, STREAM_TOSERVER) || !FLOW_IS_PP_DONE(&f, STREAM_TOSERVER) || + !FLOW_IS_PM_DONE(&f, STREAM_TOCLIENT) || FLOW_IS_PP_DONE(&f, STREAM_TOCLIENT) || + ssn->client.seg_list == NULL || + ssn->client.seg_list->next != NULL || + ssn->server.seg_list == NULL || + ssn->server.seg_list->next != NULL || + ssn->data_first_seen_dir != 0x01) { + printf("failure 11\n"); + goto end; + } + + /*** New Request ***/ + + /* partial request */ + p->tcph->th_ack = htonl(328); + p->tcph->th_seq = htonl(88); + p->tcph->th_flags = TH_PUSH | TH_ACK; + p->flowflags = FLOW_PKT_TOSERVER; + p->payload_len = sizeof(request1); + p->payload = request1; + if (StreamTcpPacket(&tv, p, stt, &pq) == -1) + goto end; + if (!(ssn->server.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED) || + !(ssn->client.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED) || + f.alproto != ALPROTO_HTTP || + f.alproto_ts != ALPROTO_HTTP || + f.alproto_tc != ALPROTO_HTTP || + f.data_al_so_far[0] != 0 || + f.data_al_so_far[1] != 0 || + f.flags & FLOW_NO_APPLAYER_INSPECTION || + !FLOW_IS_PM_DONE(&f, STREAM_TOSERVER) || !FLOW_IS_PP_DONE(&f, STREAM_TOSERVER) || + !FLOW_IS_PM_DONE(&f, STREAM_TOCLIENT) || FLOW_IS_PP_DONE(&f, STREAM_TOCLIENT) || + ssn->client.seg_list == NULL || + ssn->client.seg_list->next == NULL || + ssn->client.seg_list->next->next != NULL || + ssn->server.seg_list == NULL || + ssn->server.seg_list->next != NULL || + ssn->data_first_seen_dir != 0x01) { + printf("failure 12\n"); + goto end; + } + + + /* response ack against partial request */ + p->tcph->th_ack = htonl(90); + p->tcph->th_seq = htonl(328); + p->tcph->th_flags = TH_ACK; + p->flowflags = FLOW_PKT_TOCLIENT; + p->payload_len = 0; + p->payload = NULL; + if (StreamTcpPacket(&tv, p, stt, &pq) == -1) + goto end; + if (!(ssn->server.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED) || + !(ssn->client.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED) || + f.alproto != ALPROTO_HTTP || + f.alproto_ts != ALPROTO_HTTP || + f.alproto_tc != ALPROTO_HTTP || + f.data_al_so_far[0] != 0 || + f.data_al_so_far[1] != 0 || + f.flags & FLOW_NO_APPLAYER_INSPECTION || + !FLOW_IS_PM_DONE(&f, STREAM_TOSERVER) || !FLOW_IS_PP_DONE(&f, STREAM_TOSERVER) || + !FLOW_IS_PM_DONE(&f, STREAM_TOCLIENT) || FLOW_IS_PP_DONE(&f, STREAM_TOCLIENT) || + ssn->client.seg_list == NULL || + ssn->client.seg_list->next == NULL || + ssn->client.seg_list->next->next != NULL || + ssn->server.seg_list == NULL || + ssn->server.seg_list->next != NULL || + ssn->data_first_seen_dir != 0x01) { + printf("failure 13\n"); + goto end; + } + + /* complete request */ + p->tcph->th_ack = htonl(328); + p->tcph->th_seq = htonl(90); + p->tcph->th_flags = TH_PUSH | TH_ACK; + p->flowflags = FLOW_PKT_TOSERVER; + p->payload_len = sizeof(request2); + p->payload = request2; + if (StreamTcpPacket(&tv, p, stt, &pq) == -1) + goto end; + if (!(ssn->server.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED) || + !(ssn->client.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED) || + f.alproto != ALPROTO_HTTP || + f.alproto_ts != ALPROTO_HTTP || + f.alproto_tc != ALPROTO_HTTP || + f.data_al_so_far[0] != 0 || + f.data_al_so_far[1] != 0 || + f.flags & FLOW_NO_APPLAYER_INSPECTION || + !FLOW_IS_PM_DONE(&f, STREAM_TOSERVER) || !FLOW_IS_PP_DONE(&f, STREAM_TOSERVER) || + !FLOW_IS_PM_DONE(&f, STREAM_TOCLIENT) || FLOW_IS_PP_DONE(&f, STREAM_TOCLIENT) || + ssn->client.seg_list == NULL || + ssn->client.seg_list->next == NULL || + ssn->client.seg_list->next->next == NULL || + ssn->client.seg_list->next->next->next != NULL || + ssn->server.seg_list == NULL || + ssn->server.seg_list->next != NULL || + ssn->data_first_seen_dir != 0x01) { + printf("failure 14\n"); + goto end; + } + + /* response ack against second partial request */ + p->tcph->th_ack = htonl(175); + p->tcph->th_seq = htonl(328); + p->tcph->th_flags = TH_ACK; + p->flowflags = FLOW_PKT_TOCLIENT; + p->payload_len = 0; + p->payload = NULL; + if (StreamTcpPacket(&tv, p, stt, &pq) == -1) + goto end; + if (!(ssn->server.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED) || + !(ssn->client.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED) || + f.alproto != ALPROTO_HTTP || + f.alproto_ts != ALPROTO_HTTP || + f.alproto_tc != ALPROTO_HTTP || + f.data_al_so_far[0] != 0 || + f.data_al_so_far[1] != 0 || + f.flags & FLOW_NO_APPLAYER_INSPECTION || + !FLOW_IS_PM_DONE(&f, STREAM_TOSERVER) || !FLOW_IS_PP_DONE(&f, STREAM_TOSERVER) || + !FLOW_IS_PM_DONE(&f, STREAM_TOCLIENT) || FLOW_IS_PP_DONE(&f, STREAM_TOCLIENT) || + ssn->client.seg_list->next == NULL || + ssn->client.seg_list->next->next == NULL || + ssn->client.seg_list->next->next->next != NULL || + ssn->server.seg_list == NULL || + ssn->server.seg_list->next != NULL || + ssn->data_first_seen_dir != 0x01) { + printf("failure 15\n"); + goto end; + } + + if (ssn->toserver_smsg_head == NULL || + ssn->toserver_smsg_head->next == NULL || + ssn->toserver_smsg_head->next->next != NULL || + ssn->toclient_smsg_head == NULL || + ssn->toclient_smsg_head->next != NULL) { + printf("failure 16\n"); + goto end; + } + + StreamMsgReturnListToPool(ssn->toserver_smsg_head); + ssn->toserver_smsg_head = ssn->toserver_smsg_tail = NULL; + StreamMsgReturnListToPool(ssn->toclient_smsg_head); + ssn->toclient_smsg_head = ssn->toclient_smsg_tail = NULL; + + /* response acking a request */ + p->tcph->th_ack = htonl(175); + p->tcph->th_seq = htonl(328); + p->tcph->th_flags = TH_ACK; + p->flowflags = FLOW_PKT_TOCLIENT; + p->payload_len = 0; + p->payload = NULL; + if (StreamTcpPacket(&tv, p, stt, &pq) == -1) + goto end; + if (!(ssn->server.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED) || + !(ssn->client.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED) || + f.alproto != ALPROTO_HTTP || + f.alproto_ts != ALPROTO_HTTP || + f.alproto_tc != ALPROTO_HTTP || + f.data_al_so_far[0] != 0 || + f.data_al_so_far[1] != 0 || + f.flags & FLOW_NO_APPLAYER_INSPECTION || + !FLOW_IS_PM_DONE(&f, STREAM_TOSERVER) || !FLOW_IS_PP_DONE(&f, STREAM_TOSERVER) || + !FLOW_IS_PM_DONE(&f, STREAM_TOCLIENT) || FLOW_IS_PP_DONE(&f, STREAM_TOCLIENT) || + ssn->client.seg_list != NULL || + ssn->server.seg_list == NULL || + ssn->server.seg_list->next != NULL || + ssn->data_first_seen_dir != 0x01) { + printf("failure 15\n"); + goto end; + } + + /* request acking a response */ + p->tcph->th_ack = htonl(328); + p->tcph->th_seq = htonl(175); + p->tcph->th_flags = TH_ACK; + p->flowflags = FLOW_PKT_TOSERVER; + p->payload_len = 0; + p->payload = NULL; + if (StreamTcpPacket(&tv, p, stt, &pq) == -1) goto end; - } - - SCLogDebug("ssn.client.seg_list->flags %02x, seg %p", ssn.client.seg_list->flags, ssn.client.seg_list); - - if (!(ssn.client.seg_list->flags & SEGMENTTCP_FLAG_APPLAYER_PROCESSED)) { - printf("segment should have flags SEGMENTTCP_FLAG_APPLAYER_PROCESSED set (15): "); + if (!(ssn->server.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED) || + !(ssn->client.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED) || + f.alproto != ALPROTO_HTTP || + f.alproto_ts != ALPROTO_HTTP || + f.alproto_tc != ALPROTO_HTTP || + f.data_al_so_far[0] != 0 || + f.data_al_so_far[1] != 0 || + f.flags & FLOW_NO_APPLAYER_INSPECTION || + !FLOW_IS_PM_DONE(&f, STREAM_TOSERVER) || !FLOW_IS_PP_DONE(&f, STREAM_TOSERVER) || + !FLOW_IS_PM_DONE(&f, STREAM_TOCLIENT) || FLOW_IS_PP_DONE(&f, STREAM_TOCLIENT) || + ssn->client.seg_list != NULL || + ssn->server.seg_list != NULL || + ssn->data_first_seen_dir != 0x01) { + printf("failure 15\n"); goto end; } - if (!(ssn.client.seg_list->flags & SEGMENTTCP_FLAG_RAW_PROCESSED)) { - printf("segment should have flags SEGMENTTCP_FLAG_RAW_PROCESSED set (16): "); - goto end; - } ret = 1; end: - StreamTcpReassembleFreeThreadCtx(ra_ctx); + StreamTcpThreadDeinit(&tv, (void *)stt); + StreamTcpSessionClear(p->flow->protoctx); StreamTcpFreeConfig(TRUE); SCFree(p); - SCMutexUnlock(&f->m); - UTHFreeFlow(f); + SCMutexUnlock(&f.m); return ret; } @@ -6597,197 +6955,6 @@ end: return ret; } -/** - * \test Test to make sure we don't send more than one smsg from toserver to - * app layer until the app layer protocol has not been detected. After - * protocol has been detected the processed segments should be returned - * to pool. - * - * \retval On success it returns 1 and on failure 0. - */ - -static int StreamTcpReassembleTest41 (void) { - int ret = 0; - Packet *p = PacketGetFromAlloc(); - if (unlikely(p == NULL)) - return 0; - Flow *f = NULL; - TCPHdr tcph; - TcpSession ssn; - PacketQueue pq; - memset(&pq,0,sizeof(PacketQueue)); - memset(&tcph, 0, sizeof (TCPHdr)); - memset(&ssn, 0, sizeof(TcpSession)); - ThreadVars tv; - memset(&tv, 0, sizeof (ThreadVars)); - - StreamTcpInitConfig(TRUE); - TcpReassemblyThreadCtx *ra_ctx = StreamTcpReassembleInitThreadCtx(); - - uint8_t httpbuf1[] = "GET / HTTP/1.0\r\nUser-Agent: Victor/1.0" - "W2dyb3VwMV0NCnBob25lMT1wMDB3ODgyMTMxMzAyMTINCmxvZ2lu" - "MT0NCnBhc3N3b3JkMT0NCnBob25lMj1wMDB3ODgyMTMxMzAyMTIN" - "CmxvZ2luMj0NCnBhc3N3b3JkMj0NCnBob25lMz0NCmxvZ2luMz0N" - "CnBhc3N3b3JkMz0NCnBob25lND0NCmxvZ2luND0NCnBhc3N3b3Jk" - "ND0NCnBob25lNT0NCmxvZ2luNT0NCnBhc3N3b3JkNT0NCnBob25l" - "Nj0NCmxvZ2luNj0NCnBhc3N3b3JkNj0NCmNhbGxfdGltZTE9MzIN" - "CmNhbGxfdGltZTI9MjMyDQpkYXlfbGltaXQ9NQ0KbW9udGhfbGlt" - "aXQ9MTUNCltncm91cDJdDQpwaG9uZTE9DQpsb2dpbjE9DQpwYXNz" - "d29yZDE9DQpwaG9uZTI9DQpsb2dpbjI9DQpwYXNzd29yZDI9DQpw" - "aG9uZT"; - uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */ - - uint8_t httpbuf3[] = "psb2dpbjM9DQpwYXNzd29yZDM9DQpwaG9uZTQ9DQps" - "b2dpbjQ9DQpwYXNzd29yZDQ9DQpwaG9uZTU9DQpsb2dpbjU9DQpw" - "YXNzd29yZDU9DQpwaG9uZTY9DQpsb2dpbjY9DQpwYXNzd29yZDY9" - "DQpjYWxsX3RpbWUxPQ0KY2FsbF90aW1lMj0NCmRheV9saW1pdD0N" - "\r\n\r\n"; - uint32_t httplen3 = sizeof(httpbuf3) - 1; /* minus the \0 */ - - uint8_t httpbuf2[] = "HTTP/1.0 200 OK\r\nServer: VictorServer/1.0\r\n\r\n"; - uint32_t httplen2 = sizeof(httpbuf2) - 1; /* minus the \0 */ - - StreamMsgQueueSetMinChunkLen(FLOW_PKT_TOCLIENT, 100); - StreamMsgQueueSetMinChunkLen(FLOW_PKT_TOSERVER, 500); - - ssn.server.ra_raw_base_seq = ssn.server.ra_app_base_seq = 9; - ssn.server.isn = 9; - ssn.server.last_ack = 600; - ssn.client.ra_raw_base_seq = ssn.client.ra_app_base_seq = 9; - ssn.client.isn = 9; - ssn.client.last_ack = 600; - - f = UTHBuildFlow(AF_INET, "1.2.3.4", "1.2.3.5", 200, 220); - if (f == NULL) - goto end; - f->protoctx = &ssn; - p->flow = f; - - tcph.th_win = htons(5480); - tcph.th_seq = htonl(10); - tcph.th_ack = htonl(20); - tcph.th_flags = TH_ACK|TH_PUSH; - p->tcph = &tcph; - p->flowflags = FLOW_PKT_TOCLIENT; - - p->payload = httpbuf2; - p->payload_len = httplen2; - ssn.state = TCP_ESTABLISHED; - - TcpStream *s = NULL; - s = &ssn.server; - - SCMutexLock(&f->m); - if (StreamTcpReassembleHandleSegment(&tv, ra_ctx, &ssn, s, p, &pq) == -1) { - printf("failed in segments reassembly, while processing toserver packet: "); - goto end; - } - - /* Check if we have stream smsgs in queue */ - if (ra_ctx->stream_q->len > 0) { - printf("there shouldn't be any stream smsgs in the queue: "); - goto end; - } - - p->flowflags = FLOW_PKT_TOSERVER; - p->payload = httpbuf1; - p->payload_len = httplen1; - tcph.th_seq = htonl(10); - tcph.th_ack = htonl(55); - s = &ssn.client; - - if (StreamTcpReassembleHandleSegment(&tv, ra_ctx, &ssn, s, p, &pq) == -1) { - printf("failed in segments reassembly, while processing toserver packet: "); - goto end; - } - - p->flowflags = FLOW_PKT_TOSERVER; - p->payload = httpbuf3; - p->payload_len = httplen3; - tcph.th_seq = htonl(522); - tcph.th_ack = htonl(100); - s = &ssn.client; - - if (StreamTcpReassembleHandleSegment(&tv, ra_ctx, &ssn, s, p, &pq) == -1) { - printf("failed in segments reassembly, while processing toserver packet: "); - goto end; - } - - /* Check if we have stream smsgs in queue */ - if (ra_ctx->stream_q->len == 0) { - printf("there should be stream smsgs in the queue: "); - goto end; - } - - if (StreamTcpReassembleProcessAppLayer(ra_ctx) < 0) { - printf("failed in processing stream smsgs: "); - goto end; - } - - p->flowflags = FLOW_PKT_TOCLIENT; - p->payload = httpbuf2; - p->payload_len = httplen2; - tcph.th_seq = htonl(55); - tcph.th_ack = htonl(522); - s = &ssn.server; - - if (StreamTcpReassembleHandleSegment(&tv, ra_ctx, &ssn, s, p, &pq) == -1) { - printf("failed in segments reassembly, while processing toserver packet: "); - goto end; - } - - /* Check if we have stream smsgs in queue */ - if (ra_ctx->stream_q->len == 0) { - printf("there should be a stream smsgs in the queue: "); - goto end; - /* Process stream smsgs we may have in queue */ - } else if (ra_ctx->stream_q->len > 1) { - printf("there should be only one stream smsgs in the queue: "); - goto end; - } else if (StreamTcpReassembleProcessAppLayer(ra_ctx) < 0) { - printf("failed in processing stream smsgs: "); - goto end; - } - - p->flowflags = FLOW_PKT_TOCLIENT; - p->payload = httpbuf2; - p->payload_len = httplen2; - tcph.th_seq = htonl(100); - tcph.th_ack = htonl(522); - s = &ssn.server; - - if (StreamTcpReassembleHandleSegment(&tv, ra_ctx, &ssn, s, p, &pq) == -1) { - printf("failed in segments reassembly, while processing toserver packet: "); - goto end; - } - - /* check if the segment in the list is flagged or not */ - if (ssn.client.seg_list == NULL) { - printf("segment list should not be empty: "); - goto end; - } - - /* last_ack is in the middle of this segment */ - if ((ssn.client.seg_list->flags & SEGMENTTCP_FLAG_APPLAYER_PROCESSED)) { - printf("segment should not have flags SEGMENTTCP_FLAG_APPLAYER_PROCESSED set: "); - goto end; - } - - if (!(ssn.client.seg_list->flags & SEGMENTTCP_FLAG_RAW_PROCESSED)) { - printf("segment should have flags SEGMENTTCP_FLAG_RAW_PROCESSED set: "); - goto end; - } - - ret = 1; -end: - StreamTcpReassembleFreeThreadCtx(ra_ctx); - StreamTcpFreeConfig(TRUE); - SCFree(p); - SCMutexUnlock(&f->m); - UTHFreeFlow(f); - return ret; -} - /** * \retval On success it returns 1 and on failure 0. */ @@ -8713,7 +8880,6 @@ void StreamTcpReassembleRegisterTests(void) { UtRegisterTest("StreamTcpReassembleTest38 -- app proto test", StreamTcpReassembleTest38, 1); UtRegisterTest("StreamTcpReassembleTest39 -- app proto test", StreamTcpReassembleTest39, 1); UtRegisterTest("StreamTcpReassembleTest40 -- app proto test", StreamTcpReassembleTest40, 1); - UtRegisterTest("StreamTcpReassembleTest41 -- app proto test", StreamTcpReassembleTest41, 1); UtRegisterTest("StreamTcpReassembleTest43 -- min smsg size test", StreamTcpReassembleTest43, 1); UtRegisterTest("StreamTcpReassembleTest44 -- Memcap Test", StreamTcpReassembleTest44, 1); UtRegisterTest("StreamTcpReassembleTest45 -- Depth Test", StreamTcpReassembleTest45, 1); diff --git a/src/stream-tcp-reassemble.h b/src/stream-tcp-reassemble.h index d3e54b5cb5..47a06c1891 100644 --- a/src/stream-tcp-reassemble.h +++ b/src/stream-tcp-reassemble.h @@ -72,6 +72,9 @@ void StreamTcpReassembleFree(char); void StreamTcpReassembleRegisterTests(void); TcpReassemblyThreadCtx *StreamTcpReassembleInitThreadCtx(void); void StreamTcpReassembleFreeThreadCtx(TcpReassemblyThreadCtx *); +int StreamTcpReassembleAppLayer (ThreadVars *tv, TcpReassemblyThreadCtx *ra_ctx, + TcpSession *ssn, TcpStream *stream, + Packet *p); int StreamTcpReassembleProcessAppLayer(TcpReassemblyThreadCtx *); void StreamTcpCreateTestPacket(uint8_t *, uint8_t, uint8_t, uint8_t); diff --git a/src/stream-tcp.c b/src/stream-tcp.c index 12d23f2830..db3ae987fb 100644 --- a/src/stream-tcp.c +++ b/src/stream-tcp.c @@ -4139,8 +4139,8 @@ static int StreamTcpPacketIsWindowUpdate(TcpSession *ssn, Packet *p) { } /* flow is and stays locked */ -static int StreamTcpPacket (ThreadVars *tv, Packet *p, StreamTcpThread *stt, - PacketQueue *pq) +int StreamTcpPacket (ThreadVars *tv, Packet *p, StreamTcpThread *stt, + PacketQueue *pq) { SCEnter(); diff --git a/src/stream-tcp.h b/src/stream-tcp.h index 1667fb1161..c9f38fa6a1 100644 --- a/src/stream-tcp.h +++ b/src/stream-tcp.h @@ -202,5 +202,11 @@ static inline int StreamHasUnprocessedSegments(TcpSession *ssn, int direction) } } +TmEcode StreamTcpThreadInit(ThreadVars *, void *, void **); +TmEcode StreamTcpThreadDeinit(ThreadVars *tv, void *data); +int StreamTcpPacket (ThreadVars *tv, Packet *p, StreamTcpThread *stt, + PacketQueue *pq); +void StreamTcpSessionClear(void *ssnptr); + #endif /* __STREAM_TCP_H__ */