From: Victor Julien Date: Tue, 16 Jun 2020 08:23:49 +0000 (+0200) Subject: app-layer: split EOF flag per direction X-Git-Tag: suricata-6.0.0-beta1~97 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=4f73943df915832b8aadad853b2c593f7100aa4d;p=thirdparty%2Fsuricata.git app-layer: split EOF flag per direction --- diff --git a/src/app-layer-enip.c b/src/app-layer-enip.c index f6bf450309..52c6c5dab3 100644 --- a/src/app-layer-enip.c +++ b/src/app-layer-enip.c @@ -327,7 +327,7 @@ static AppLayerResult ENIPParse(Flow *f, void *state, AppLayerParserState *pstat ENIPTransaction *tx; if (input == NULL && AppLayerParserStateIssetFlag(pstate, - APP_LAYER_PARSER_EOF)) + APP_LAYER_PARSER_EOF_TS|APP_LAYER_PARSER_EOF_TC)) { SCReturnStruct(APP_LAYER_OK); } else if (input == NULL && input_len != 0) { diff --git a/src/app-layer-ftp.c b/src/app-layer-ftp.c index 2810475d2b..1a3e91cb27 100644 --- a/src/app-layer-ftp.c +++ b/src/app-layer-ftp.c @@ -559,7 +559,7 @@ static AppLayerResult FTPParseRequest(Flow *f, void *ftp_state, FtpState *state = (FtpState *)ftp_state; void *ptmp; - if (input == NULL && AppLayerParserStateIssetFlag(pstate, APP_LAYER_PARSER_EOF)) { + if (input == NULL && AppLayerParserStateIssetFlag(pstate, APP_LAYER_PARSER_EOF_TS)) { SCReturnStruct(APP_LAYER_OK); } else if (input == NULL || input_len == 0) { SCReturnStruct(APP_LAYER_ERROR); @@ -1113,7 +1113,10 @@ static AppLayerResult FTPDataParse(Flow *f, FtpDataState *ftpdata_state, } } - if (input_len && AppLayerParserStateIssetFlag(pstate, APP_LAYER_PARSER_EOF)) { + const bool eof_flag = flags & STREAM_TOSERVER ? + AppLayerParserStateIssetFlag(pstate, APP_LAYER_PARSER_EOF_TS) != 0 : + AppLayerParserStateIssetFlag(pstate, APP_LAYER_PARSER_EOF_TC) != 0; + if (input_len && eof_flag) { ret = FileCloseFile(ftpdata_state->files, (uint8_t *) NULL, 0, flags); ftpdata_state->state = FTPDATA_STATE_FINISHED; } diff --git a/src/app-layer-htp.c b/src/app-layer-htp.c index 9d8e163d87..e19d2bf758 100644 --- a/src/app-layer-htp.c +++ b/src/app-layer-htp.c @@ -897,7 +897,7 @@ static AppLayerResult HTPHandleRequestData(Flow *f, void *htp_state, } /* if the TCP connection is closed, then close the HTTP connection */ - if (AppLayerParserStateIssetFlag(pstate, APP_LAYER_PARSER_EOF) && + if (AppLayerParserStateIssetFlag(pstate, APP_LAYER_PARSER_EOF_TS) && !(hstate->flags & HTP_FLAG_STATE_CLOSED_TS)) { htp_connp_req_close(hstate->connp, &ts); @@ -960,7 +960,7 @@ static AppLayerResult HTPHandleResponseData(Flow *f, void *htp_state, } /* if we the TCP connection is closed, then close the HTTP connection */ - if (AppLayerParserStateIssetFlag(pstate, APP_LAYER_PARSER_EOF) && + if (AppLayerParserStateIssetFlag(pstate, APP_LAYER_PARSER_EOF_TC) && !(hstate->flags & HTP_FLAG_STATE_CLOSED_TC)) { htp_connp_close(hstate->connp, &ts); diff --git a/src/app-layer-modbus.c b/src/app-layer-modbus.c index 3aecf25ceb..f5908e7fc9 100644 --- a/src/app-layer-modbus.c +++ b/src/app-layer-modbus.c @@ -1274,7 +1274,7 @@ static AppLayerResult ModbusParseRequest(Flow *f, ModbusTransaction *tx; ModbusHeader header; - if (input == NULL && AppLayerParserStateIssetFlag(pstate, APP_LAYER_PARSER_EOF)) { + if (input == NULL && AppLayerParserStateIssetFlag(pstate, APP_LAYER_PARSER_EOF_TS)) { SCReturnStruct(APP_LAYER_OK); } else if (input == NULL || input_len == 0) { SCReturnStruct(APP_LAYER_ERROR); @@ -1339,7 +1339,7 @@ static AppLayerResult ModbusParseResponse(Flow *f, ModbusState *modbus = (ModbusState *) state; ModbusTransaction *tx; - if (input == NULL && AppLayerParserStateIssetFlag(pstate, APP_LAYER_PARSER_EOF)) { + if (input == NULL && AppLayerParserStateIssetFlag(pstate, APP_LAYER_PARSER_EOF_TC)) { SCReturnStruct(APP_LAYER_OK); } else if (input == NULL || input_len == 0) { SCReturnStruct(APP_LAYER_ERROR); diff --git a/src/app-layer-parser.c b/src/app-layer-parser.c index 22636d6fc1..0be1ab07e1 100644 --- a/src/app-layer-parser.c +++ b/src/app-layer-parser.c @@ -1160,6 +1160,17 @@ void AppLayerParserApplyTxConfig(uint8_t ipproto, AppProto alproto, /***** General *****/ +static inline void SetEOFFlags(AppLayerParserState *pstate, const uint8_t flags) +{ + if ((flags & (STREAM_EOF|STREAM_TOSERVER)) == (STREAM_EOF|STREAM_TOSERVER)) { + SCLogDebug("setting APP_LAYER_PARSER_EOF_TS"); + AppLayerParserStateSetFlag(pstate, APP_LAYER_PARSER_EOF_TS); + } else if ((flags & (STREAM_EOF|STREAM_TOCLIENT)) == (STREAM_EOF|STREAM_TOCLIENT)) { + SCLogDebug("setting APP_LAYER_PARSER_EOF_TC"); + AppLayerParserStateSetFlag(pstate, APP_LAYER_PARSER_EOF_TC); + } +} + /** \retval int -1 in case of unrecoverable error. App-layer tracking stops for this flow. * \retval int 0 ok: we did not update app_progress * \retval int 1 ok: we updated app_progress */ @@ -1199,8 +1210,7 @@ int AppLayerParserParse(ThreadVars *tv, AppLayerParserThreadCtx *alp_tctx, Flow goto error; } - if (flags & STREAM_EOF) - AppLayerParserStateSetFlag(pstate, APP_LAYER_PARSER_EOF); + SetEOFFlags(pstate, flags); alstate = f->alstate; if (alstate == NULL) { @@ -1333,7 +1343,7 @@ void AppLayerParserSetEOF(AppLayerParserState *pstate) if (pstate == NULL) goto end; - AppLayerParserStateSetFlag(pstate, APP_LAYER_PARSER_EOF); + AppLayerParserStateSetFlag(pstate, APP_LAYER_PARSER_EOF_TS|APP_LAYER_PARSER_EOF_TC); end: SCReturn; diff --git a/src/app-layer-parser.h b/src/app-layer-parser.h index 85623d3a4e..19201d6a4e 100644 --- a/src/app-layer-parser.h +++ b/src/app-layer-parser.h @@ -33,11 +33,13 @@ #include "util-config.h" /* Flags for AppLayerParserState. */ -#define APP_LAYER_PARSER_EOF BIT_U8(0) +// flag available BIT_U8(0) #define APP_LAYER_PARSER_NO_INSPECTION BIT_U8(1) #define APP_LAYER_PARSER_NO_REASSEMBLY BIT_U8(2) #define APP_LAYER_PARSER_NO_INSPECTION_PAYLOAD BIT_U8(3) #define APP_LAYER_PARSER_BYPASS_READY BIT_U8(4) +#define APP_LAYER_PARSER_EOF_TS BIT_U8(5) +#define APP_LAYER_PARSER_EOF_TC BIT_U8(6) /* Flags for AppLayerParserProtoCtx. */ #define APP_LAYER_PARSER_OPT_ACCEPT_GAPS BIT_U32(0) diff --git a/src/app-layer-smtp.c b/src/app-layer-smtp.c index 49685cbddf..2de623d34a 100644 --- a/src/app-layer-smtp.c +++ b/src/app-layer-smtp.c @@ -1376,7 +1376,9 @@ static AppLayerResult SMTPParse(int direction, Flow *f, SMTPState *state, { SCEnter(); - if (input == NULL && AppLayerParserStateIssetFlag(pstate, APP_LAYER_PARSER_EOF)) { + if (input == NULL && + ((direction == 0 && AppLayerParserStateIssetFlag(pstate, APP_LAYER_PARSER_EOF_TS)) || + (direction == 1 && AppLayerParserStateIssetFlag(pstate, APP_LAYER_PARSER_EOF_TC)))) { SCReturnStruct(APP_LAYER_OK); } else if (input == NULL || input_len == 0) { SCReturnStruct(APP_LAYER_ERROR); diff --git a/src/app-layer-ssl.c b/src/app-layer-ssl.c index 82163af8f7..557253058e 100644 --- a/src/app-layer-ssl.c +++ b/src/app-layer-ssl.c @@ -2501,7 +2501,8 @@ static AppLayerResult SSLDecode(Flow *f, uint8_t direction, void *alstate, AppLa ssl_state->f = f; if (input == NULL && - AppLayerParserStateIssetFlag(pstate, APP_LAYER_PARSER_EOF)) { + ((direction == 0 && AppLayerParserStateIssetFlag(pstate, APP_LAYER_PARSER_EOF_TS)) || + (direction == 1 && AppLayerParserStateIssetFlag(pstate, APP_LAYER_PARSER_EOF_TC)))) { /* flag session as finished if APP_LAYER_PARSER_EOF is set */ ssl_state->flags |= SSL_AL_FLAG_STATE_FINISHED; SCReturnStruct(APP_LAYER_OK); @@ -2606,7 +2607,8 @@ static AppLayerResult SSLDecode(Flow *f, uint8_t direction, void *alstate, AppLa } /* flag session as finished if APP_LAYER_PARSER_EOF is set */ - if (AppLayerParserStateIssetFlag(pstate, APP_LAYER_PARSER_EOF)) { + if (AppLayerParserStateIssetFlag(pstate, APP_LAYER_PARSER_EOF_TS) && + AppLayerParserStateIssetFlag(pstate, APP_LAYER_PARSER_EOF_TC)) { SCLogDebug("SSL_AL_FLAG_STATE_FINISHED"); ssl_state->flags |= SSL_AL_FLAG_STATE_FINISHED; } diff --git a/src/app-layer-template.c b/src/app-layer-template.c index 198fb432be..83eab5fa3d 100644 --- a/src/app-layer-template.c +++ b/src/app-layer-template.c @@ -246,7 +246,7 @@ static AppLayerResult TemplateParseRequest(Flow *f, void *statev, SCLogNotice("Parsing template request: len=%"PRIu32, input_len); if (input == NULL) { - if (AppLayerParserStateIssetFlag(pstate, APP_LAYER_PARSER_EOF)) { + if (AppLayerParserStateIssetFlag(pstate, APP_LAYER_PARSER_EOF_TS)) { /* This is a signal that the stream is done. Do any * cleanup if needed. Usually nothing is required here. */ SCReturnStruct(APP_LAYER_OK); @@ -322,7 +322,7 @@ static AppLayerResult TemplateParseResponse(Flow *f, void *statev, AppLayerParse /* Likely connection closed, we can just return here. */ if ((input == NULL || input_len == 0) && - AppLayerParserStateIssetFlag(pstate, APP_LAYER_PARSER_EOF)) { + AppLayerParserStateIssetFlag(pstate, APP_LAYER_PARSER_EOF_TC)) { SCReturnStruct(APP_LAYER_OK); } diff --git a/src/app-layer-tftp.c b/src/app-layer-tftp.c index 821f91bc7c..f5ec69e7f6 100644 --- a/src/app-layer-tftp.c +++ b/src/app-layer-tftp.c @@ -104,7 +104,7 @@ static AppLayerResult TFTPParseRequest(Flow *f, void *state, /* Likely connection closed, we can just return here. */ if ((input == NULL || input_len == 0) && - AppLayerParserStateIssetFlag(pstate, APP_LAYER_PARSER_EOF)) { + AppLayerParserStateIssetFlag(pstate, APP_LAYER_PARSER_EOF_TS)) { SCReturnStruct(APP_LAYER_OK); } diff --git a/src/flow-timeout.c b/src/flow-timeout.c index c5dafb06f8..f21f3fe9eb 100644 --- a/src/flow-timeout.c +++ b/src/flow-timeout.c @@ -248,8 +248,6 @@ static inline Packet *FlowForceReassemblyPseudoPacketSetup(Packet *p, memset(&p->ts, 0, sizeof(struct timeval)); TimeGet(&p->ts); - AppLayerParserSetEOF(f->alparser); - return p; error: diff --git a/src/output-tx.c b/src/output-tx.c index 5974168890..4294d40f4c 100644 --- a/src/output-tx.c +++ b/src/output-tx.c @@ -260,8 +260,15 @@ static TmEcode OutputTxLog(ThreadVars *tv, Packet *p, void *thread_data) if ((tx_logged_old & (1<logger_id)) == 0) { SCLogDebug("alproto match %d, logging tx_id %"PRIu64, logger->alproto, tx_id); - if (!(AppLayerParserStateIssetFlag(f->alparser, - APP_LAYER_PARSER_EOF))) { + const bool ts_eof = AppLayerParserStateIssetFlag(f->alparser, + APP_LAYER_PARSER_EOF_TS) != 0; + const bool tc_eof = AppLayerParserStateIssetFlag(f->alparser, + APP_LAYER_PARSER_EOF_TC) != 0; + SCLogDebug("pcap_cnt %"PRIu64", tx_id %"PRIu64" logger %d. EOFs TS %s TC %s", + p->pcap_cnt, tx_id, logger->logger_id, + ts_eof ? "true" : "false", tc_eof ? "true" : "false"); + + if (!(ts_eof && tc_eof)) { if (logger->LogCondition) { int r = logger->LogCondition(tv, p, alstate, tx, tx_id); if (r == FALSE) { diff --git a/src/tests/fuzz/fuzz_applayerparserparse.c b/src/tests/fuzz/fuzz_applayerparserparse.c index ae9beaaf8c..c319c22223 100644 --- a/src/tests/fuzz/fuzz_applayerparserparse.c +++ b/src/tests/fuzz/fuzz_applayerparserparse.c @@ -125,7 +125,11 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) (void) AppLayerParserParse(NULL, alp_tctx, f, f->alproto, flags, isolatedBuffer, alnext - albuffer); free(isolatedBuffer); flags &= ~(STREAM_START); - if (f->alparser && AppLayerParserStateIssetFlag(f->alparser, APP_LAYER_PARSER_EOF)) { + if (f->alparser && + (((flags & STREAM_TOSERVER) != 0 && + AppLayerParserStateIssetFlag(f->alparser, APP_LAYER_PARSER_EOF_TS)) || + ((flags & STREAM_TOCLIENT) != 0 && + AppLayerParserStateIssetFlag(f->alparser, APP_LAYER_PARSER_EOF_TC)))) { //no final chunk alsize = 0; break;