diff --git a/src/app-layer-parser.c b/src/app-layer-parser.c index c79e6142bb..c97929f700 100644 --- a/src/app-layer-parser.c +++ b/src/app-layer-parser.c @@ -725,13 +725,26 @@ static void AppLayerParserTransactionsCleanup(Flow *f) } } +#define IS_DISRUPTED(flags) \ + ((flags) & (STREAM_DEPTH|STREAM_GAP)) + +/** + * \brief get the progress value for a tx/protocol + * + * If the stream is disrupted, we return the 'completion' value. + */ int AppLayerParserGetStateProgress(uint8_t ipproto, AppProto alproto, - void *alstate, uint8_t direction) + void *alstate, uint8_t flags) { SCEnter(); int r = 0; - r = alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto]. - StateGetProgress(alstate, direction); + if (unlikely(IS_DISRUPTED(flags))) { + r = alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto]. + StateGetProgressCompletionStatus(flags); + } else { + r = alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto]. + StateGetProgress(alstate, flags); + } SCReturnInt(r); } diff --git a/src/detect-engine-hcbd.c b/src/detect-engine-hcbd.c index aed137985e..a1e47e6be4 100644 --- a/src/detect-engine-hcbd.c +++ b/src/detect-engine-hcbd.c @@ -160,7 +160,7 @@ static uint8_t *DetectEngineHCBDGetBufferForTX(htp_tx_t *tx, uint64_t tx_id, if ((htp_state->cfg->request_body_limit == 0 || htud->request_body.content_len_so_far < htp_state->cfg->request_body_limit) && htud->request_body.content_len_so_far < htp_state->cfg->request_inspect_min_size && - !(AppLayerParserGetStateProgress(IPPROTO_TCP, ALPROTO_HTTP, tx, STREAM_TOSERVER) > HTP_REQUEST_BODY) && + !(AppLayerParserGetStateProgress(IPPROTO_TCP, ALPROTO_HTTP, tx, flags) > HTP_REQUEST_BODY) && !(flags & STREAM_EOF)) { SCLogDebug("we still haven't seen the entire request body. " "Let's defer body inspection till we see the " @@ -274,7 +274,7 @@ int DetectEngineInspectHttpClientBody(ThreadVars *tv, end: - if (AppLayerParserGetStateProgress(IPPROTO_TCP, ALPROTO_HTTP, tx, STREAM_TOSERVER) > HTP_REQUEST_BODY) + if (AppLayerParserGetStateProgress(IPPROTO_TCP, ALPROTO_HTTP, tx, flags) > HTP_REQUEST_BODY) return DETECT_ENGINE_INSPECT_SIG_CANT_MATCH; else return DETECT_ENGINE_INSPECT_SIG_NO_MATCH; diff --git a/src/detect-engine-hcd.c b/src/detect-engine-hcd.c index 513507e4e1..5fcfa51fd3 100644 --- a/src/detect-engine-hcd.c +++ b/src/detect-engine-hcd.c @@ -142,10 +142,10 @@ int DetectEngineInspectHttpCookie(ThreadVars *tv, end: if (flags & STREAM_TOSERVER) { - if (AppLayerParserGetStateProgress(IPPROTO_TCP, ALPROTO_HTTP, tx, STREAM_TOSERVER) > HTP_REQUEST_HEADERS) + if (AppLayerParserGetStateProgress(IPPROTO_TCP, ALPROTO_HTTP, tx, flags) > HTP_REQUEST_HEADERS) return DETECT_ENGINE_INSPECT_SIG_CANT_MATCH; } else { - if (AppLayerParserGetStateProgress(IPPROTO_TCP, ALPROTO_HTTP, tx, STREAM_TOCLIENT) > HTP_RESPONSE_HEADERS) + if (AppLayerParserGetStateProgress(IPPROTO_TCP, ALPROTO_HTTP, tx, flags) > HTP_RESPONSE_HEADERS) return DETECT_ENGINE_INSPECT_SIG_CANT_MATCH; } return DETECT_ENGINE_INSPECT_SIG_NO_MATCH; diff --git a/src/detect-engine-hhd.c b/src/detect-engine-hhd.c index 82c5b9ce35..baf5cf6672 100644 --- a/src/detect-engine-hhd.c +++ b/src/detect-engine-hhd.c @@ -143,11 +143,11 @@ static uint8_t *DetectEngineHHDGetBufferForTX(htp_tx_t *tx, uint64_t tx_id, htp_table_t *headers; if (flags & STREAM_TOSERVER) { - if (AppLayerParserGetStateProgress(IPPROTO_TCP, ALPROTO_HTTP, tx, STREAM_TOSERVER) <= HTP_REQUEST_HEADERS) + if (AppLayerParserGetStateProgress(IPPROTO_TCP, ALPROTO_HTTP, tx, flags) <= HTP_REQUEST_HEADERS) goto end; headers = tx->request_headers; } else { - if (AppLayerParserGetStateProgress(IPPROTO_TCP, ALPROTO_HTTP, tx, STREAM_TOCLIENT) <= HTP_RESPONSE_HEADERS) + if (AppLayerParserGetStateProgress(IPPROTO_TCP, ALPROTO_HTTP, tx, flags) <= HTP_RESPONSE_HEADERS) goto end; headers = tx->response_headers; } @@ -263,10 +263,10 @@ int DetectEngineInspectHttpHeader(ThreadVars *tv, end: if (flags & STREAM_TOSERVER) { - if (AppLayerParserGetStateProgress(IPPROTO_TCP, ALPROTO_HTTP, tx, STREAM_TOSERVER) > HTP_REQUEST_HEADERS) + if (AppLayerParserGetStateProgress(IPPROTO_TCP, ALPROTO_HTTP, tx, flags) > HTP_REQUEST_HEADERS) return DETECT_ENGINE_INSPECT_SIG_CANT_MATCH; } else { - if (AppLayerParserGetStateProgress(IPPROTO_TCP, ALPROTO_HTTP, tx, STREAM_TOCLIENT) > HTP_RESPONSE_HEADERS) + if (AppLayerParserGetStateProgress(IPPROTO_TCP, ALPROTO_HTTP, tx, flags) > HTP_RESPONSE_HEADERS) return DETECT_ENGINE_INSPECT_SIG_CANT_MATCH; } return DETECT_ENGINE_INSPECT_SIG_NO_MATCH; diff --git a/src/detect-engine-hhhd.c b/src/detect-engine-hhhd.c index 77a9791d83..65aebd070a 100644 --- a/src/detect-engine-hhhd.c +++ b/src/detect-engine-hhhd.c @@ -118,7 +118,7 @@ int DetectEngineInspectHttpHH(ThreadVars *tv, return DETECT_ENGINE_INSPECT_SIG_MATCH; end: - if (AppLayerParserGetStateProgress(IPPROTO_TCP, ALPROTO_HTTP, tx, STREAM_TOSERVER) > HTP_REQUEST_HEADERS) + if (AppLayerParserGetStateProgress(IPPROTO_TCP, ALPROTO_HTTP, tx, flags) > HTP_REQUEST_HEADERS) return DETECT_ENGINE_INSPECT_SIG_CANT_MATCH; else return DETECT_ENGINE_INSPECT_SIG_NO_MATCH; diff --git a/src/detect-engine-hmd.c b/src/detect-engine-hmd.c index c33cfd967d..5a4b7d8ad1 100644 --- a/src/detect-engine-hmd.c +++ b/src/detect-engine-hmd.c @@ -96,7 +96,7 @@ int DetectEngineInspectHttpMethod(ThreadVars *tv, { htp_tx_t *tx = (htp_tx_t *)txv; if (tx->request_method == NULL) { - if (AppLayerParserGetStateProgress(IPPROTO_TCP, ALPROTO_HTTP, tx, STREAM_TOSERVER) > HTP_REQUEST_LINE) + if (AppLayerParserGetStateProgress(IPPROTO_TCP, ALPROTO_HTTP, tx, flags) > HTP_REQUEST_LINE) return DETECT_ENGINE_INSPECT_SIG_CANT_MATCH; else return DETECT_ENGINE_INSPECT_SIG_NO_MATCH; diff --git a/src/detect-engine-hrhd.c b/src/detect-engine-hrhd.c index b6b86a3772..90cf1d5e90 100644 --- a/src/detect-engine-hrhd.c +++ b/src/detect-engine-hrhd.c @@ -71,7 +71,7 @@ int DetectEngineRunHttpRawHeaderMpm(DetectEngineThreadCtx *det_ctx, Flow *f, SCReturnInt(cnt); if (flags & STREAM_TOSERVER) { - if (AppLayerParserGetStateProgress(IPPROTO_TCP, ALPROTO_HTTP, txv, STREAM_TOSERVER) <= HTP_REQUEST_HEADERS) + if (AppLayerParserGetStateProgress(IPPROTO_TCP, ALPROTO_HTTP, txv, flags) <= HTP_REQUEST_HEADERS) SCReturnInt(cnt); if (tx_ud->request_headers_raw != NULL) { @@ -81,7 +81,7 @@ int DetectEngineRunHttpRawHeaderMpm(DetectEngineThreadCtx *det_ctx, Flow *f, flags); } } else { - if (AppLayerParserGetStateProgress(IPPROTO_TCP, ALPROTO_HTTP, txv, STREAM_TOCLIENT) <= HTP_RESPONSE_HEADERS) + if (AppLayerParserGetStateProgress(IPPROTO_TCP, ALPROTO_HTTP, txv, flags) <= HTP_RESPONSE_HEADERS) SCReturnInt(cnt); if (tx_ud->response_headers_raw != NULL) { @@ -120,10 +120,10 @@ int DetectEngineInspectHttpRawHeader(ThreadVars *tv, uint32_t headers_raw_len = 0; if (flags & STREAM_TOSERVER) { - if (AppLayerParserGetStateProgress(IPPROTO_TCP, ALPROTO_HTTP, txv, STREAM_TOSERVER) <= HTP_REQUEST_HEADERS) + if (AppLayerParserGetStateProgress(IPPROTO_TCP, ALPROTO_HTTP, txv, flags) <= HTP_REQUEST_HEADERS) return DETECT_ENGINE_INSPECT_SIG_NO_MATCH; } else { - if (AppLayerParserGetStateProgress(IPPROTO_TCP, ALPROTO_HTTP, txv, STREAM_TOCLIENT) <= HTP_RESPONSE_HEADERS) + if (AppLayerParserGetStateProgress(IPPROTO_TCP, ALPROTO_HTTP, txv, flags) <= HTP_RESPONSE_HEADERS) return DETECT_ENGINE_INSPECT_SIG_NO_MATCH; } @@ -154,10 +154,10 @@ int DetectEngineInspectHttpRawHeader(ThreadVars *tv, end: if (flags & STREAM_TOSERVER) { - if (AppLayerParserGetStateProgress(IPPROTO_TCP, ALPROTO_HTTP, txv, STREAM_TOSERVER) > HTP_REQUEST_HEADERS) + if (AppLayerParserGetStateProgress(IPPROTO_TCP, ALPROTO_HTTP, txv, flags) > HTP_REQUEST_HEADERS) return DETECT_ENGINE_INSPECT_SIG_CANT_MATCH; } else { - if (AppLayerParserGetStateProgress(IPPROTO_TCP, ALPROTO_HTTP, txv, STREAM_TOCLIENT) > HTP_RESPONSE_HEADERS) + if (AppLayerParserGetStateProgress(IPPROTO_TCP, ALPROTO_HTTP, txv, flags) > HTP_RESPONSE_HEADERS) return DETECT_ENGINE_INSPECT_SIG_CANT_MATCH; } return DETECT_ENGINE_INSPECT_SIG_NO_MATCH; diff --git a/src/detect-engine-hrhhd.c b/src/detect-engine-hrhhd.c index 273c8b6d6a..f1acf10018 100644 --- a/src/detect-engine-hrhhd.c +++ b/src/detect-engine-hrhhd.c @@ -145,7 +145,7 @@ int DetectEngineInspectHttpHRH(ThreadVars *tv, return DETECT_ENGINE_INSPECT_SIG_MATCH; end: - if (AppLayerParserGetStateProgress(IPPROTO_TCP, ALPROTO_HTTP, tx, STREAM_TOSERVER) > HTP_REQUEST_HEADERS) + if (AppLayerParserGetStateProgress(IPPROTO_TCP, ALPROTO_HTTP, tx, flags) > HTP_REQUEST_HEADERS) return DETECT_ENGINE_INSPECT_SIG_CANT_MATCH; else return DETECT_ENGINE_INSPECT_SIG_NO_MATCH; diff --git a/src/detect-engine-hrl.c b/src/detect-engine-hrl.c index af1b93f316..5e5c0cb621 100644 --- a/src/detect-engine-hrl.c +++ b/src/detect-engine-hrl.c @@ -72,7 +72,7 @@ int DetectEngineInspectHttpRequestLine(ThreadVars *tv, htp_tx_t *tx = (htp_tx_t *)txv; if (tx->request_line == NULL) { - if (AppLayerParserGetStateProgress(IPPROTO_TCP, ALPROTO_HTTP, txv, STREAM_TOSERVER) > HTP_REQUEST_LINE) + if (AppLayerParserGetStateProgress(IPPROTO_TCP, ALPROTO_HTTP, txv, flags) > HTP_REQUEST_LINE) return DETECT_ENGINE_INSPECT_SIG_CANT_MATCH; else return DETECT_ENGINE_INSPECT_SIG_NO_MATCH; diff --git a/src/detect-engine-hrud.c b/src/detect-engine-hrud.c index 343054b9ad..c715c02926 100644 --- a/src/detect-engine-hrud.c +++ b/src/detect-engine-hrud.c @@ -102,7 +102,7 @@ int DetectEngineInspectHttpRawUri(ThreadVars *tv, { htp_tx_t *tx = (htp_tx_t *)txv; if (tx->request_uri == NULL) { - if (AppLayerParserGetStateProgress(IPPROTO_TCP, ALPROTO_HTTP, tx, STREAM_TOSERVER) > HTP_REQUEST_LINE) + if (AppLayerParserGetStateProgress(IPPROTO_TCP, ALPROTO_HTTP, tx, flags) > HTP_REQUEST_LINE) return DETECT_ENGINE_INSPECT_SIG_CANT_MATCH; else return DETECT_ENGINE_INSPECT_SIG_NO_MATCH; diff --git a/src/detect-engine-hsbd.c b/src/detect-engine-hsbd.c index 9fad1a3af1..a6319db67f 100644 --- a/src/detect-engine-hsbd.c +++ b/src/detect-engine-hsbd.c @@ -286,7 +286,7 @@ static uint8_t *DetectEngineHSBDGetBufferForTX(htp_tx_t *tx, uint64_t tx_id, htud->response_body.content_len_so_far, htp_state->cfg->response_inspect_min_size, flags & STREAM_EOF ? "true" : "false", - (AppLayerParserGetStateProgress(IPPROTO_TCP, ALPROTO_HTTP, tx, STREAM_TOCLIENT) > HTP_RESPONSE_BODY) ? "true" : "false"); + (AppLayerParserGetStateProgress(IPPROTO_TCP, ALPROTO_HTTP, tx, flags) > HTP_RESPONSE_BODY) ? "true" : "false"); if (!htp_state->cfg->http_body_inline) { /* inspect the body if the transfer is complete or we have hit @@ -294,7 +294,7 @@ static uint8_t *DetectEngineHSBDGetBufferForTX(htp_tx_t *tx, uint64_t tx_id, if ((htp_state->cfg->response_body_limit == 0 || htud->response_body.content_len_so_far < htp_state->cfg->response_body_limit) && htud->response_body.content_len_so_far < htp_state->cfg->response_inspect_min_size && - !(AppLayerParserGetStateProgress(IPPROTO_TCP, ALPROTO_HTTP, tx, STREAM_TOCLIENT) > HTP_RESPONSE_BODY) && + !(AppLayerParserGetStateProgress(IPPROTO_TCP, ALPROTO_HTTP, tx, flags) > HTP_RESPONSE_BODY) && !(flags & STREAM_EOF)) { SCLogDebug("we still haven't seen the entire response body. " "Let's defer body inspection till we see the " @@ -368,7 +368,7 @@ int DetectEngineInspectHttpServerBody(ThreadVars *tv, return DETECT_ENGINE_INSPECT_SIG_MATCH; end: - if (AppLayerParserGetStateProgress(IPPROTO_TCP, ALPROTO_HTTP, tx, STREAM_TOCLIENT) > HTP_RESPONSE_BODY) + if (AppLayerParserGetStateProgress(IPPROTO_TCP, ALPROTO_HTTP, tx, flags) > HTP_RESPONSE_BODY) return DETECT_ENGINE_INSPECT_SIG_CANT_MATCH; else return DETECT_ENGINE_INSPECT_SIG_NO_MATCH; diff --git a/src/detect-engine-hscd.c b/src/detect-engine-hscd.c index aa9f6f7dcc..a38562b193 100644 --- a/src/detect-engine-hscd.c +++ b/src/detect-engine-hscd.c @@ -100,7 +100,7 @@ int DetectEngineInspectHttpStatCode(ThreadVars *tv, { htp_tx_t *tx = (htp_tx_t *)txv; if (tx->response_status == NULL) { - if (AppLayerParserGetStateProgress(IPPROTO_TCP, ALPROTO_HTTP, tx, STREAM_TOCLIENT) > HTP_RESPONSE_LINE) + if (AppLayerParserGetStateProgress(IPPROTO_TCP, ALPROTO_HTTP, tx, flags) > HTP_RESPONSE_LINE) return DETECT_ENGINE_INSPECT_SIG_CANT_MATCH; else return DETECT_ENGINE_INSPECT_SIG_NO_MATCH; diff --git a/src/detect-engine-hsmd.c b/src/detect-engine-hsmd.c index 2c5176022a..61c8e2e9b5 100644 --- a/src/detect-engine-hsmd.c +++ b/src/detect-engine-hsmd.c @@ -100,7 +100,7 @@ int DetectEngineInspectHttpStatMsg(ThreadVars *tv, { htp_tx_t *tx = (htp_tx_t *)txv; if (tx->response_message == NULL) { - if (AppLayerParserGetStateProgress(IPPROTO_TCP, ALPROTO_HTTP, tx, STREAM_TOCLIENT) > HTP_RESPONSE_LINE) + if (AppLayerParserGetStateProgress(IPPROTO_TCP, ALPROTO_HTTP, tx, flags) > HTP_RESPONSE_LINE) return DETECT_ENGINE_INSPECT_SIG_CANT_MATCH; else return DETECT_ENGINE_INSPECT_SIG_NO_MATCH; diff --git a/src/detect-engine-hua.c b/src/detect-engine-hua.c index d1bd0c2ff1..8cafa423af 100644 --- a/src/detect-engine-hua.c +++ b/src/detect-engine-hua.c @@ -122,7 +122,7 @@ int DetectEngineInspectHttpUA(ThreadVars *tv, return DETECT_ENGINE_INSPECT_SIG_MATCH; end: - if (AppLayerParserGetStateProgress(IPPROTO_TCP, ALPROTO_HTTP, tx, STREAM_TOSERVER) > HTP_REQUEST_HEADERS) + if (AppLayerParserGetStateProgress(IPPROTO_TCP, ALPROTO_HTTP, tx, flags) > HTP_REQUEST_HEADERS) return DETECT_ENGINE_INSPECT_SIG_CANT_MATCH; else return DETECT_ENGINE_INSPECT_SIG_NO_MATCH; diff --git a/src/detect-engine-uri.c b/src/detect-engine-uri.c index e0df1e0b9e..cd73715784 100644 --- a/src/detect-engine-uri.c +++ b/src/detect-engine-uri.c @@ -73,7 +73,7 @@ int DetectEngineInspectPacketUris(ThreadVars *tv, HtpTxUserData *tx_ud = htp_tx_get_user_data(txv); if (tx_ud == NULL || tx_ud->request_uri_normalized == NULL) { - if (AppLayerParserGetStateProgress(IPPROTO_TCP, ALPROTO_HTTP, txv, STREAM_TOSERVER) > HTP_REQUEST_LINE) + if (AppLayerParserGetStateProgress(IPPROTO_TCP, ALPROTO_HTTP, txv, flags) > HTP_REQUEST_LINE) return DETECT_ENGINE_INSPECT_SIG_CANT_MATCH; else return DETECT_ENGINE_INSPECT_SIG_NO_MATCH; diff --git a/src/detect.c b/src/detect.c index 77de1714ad..868e3ed736 100644 --- a/src/detect.c +++ b/src/detect.c @@ -1335,6 +1335,8 @@ int SigMatchSignatures(ThreadVars *th_v, DetectEngineCtx *de_ctx, DetectEngineTh (p->proto == IPPROTO_UDP) || (p->proto == IPPROTO_SCTP && (p->flowflags & FLOW_PKT_ESTABLISHED))) { + /* update flow flags with knowledge on disruptions */ + flow_flags = FlowGetDisruptionFlags(pflow, flow_flags); has_state = (FlowGetAppState(pflow) != NULL); alproto = FlowGetAppProtocol(pflow); alversion = AppLayerParserGetStateVersion(pflow->alparser); diff --git a/src/flow.c b/src/flow.c index 4e9b684806..42099c3ad5 100644 --- a/src/flow.c +++ b/src/flow.c @@ -870,6 +870,37 @@ void *FlowGetAppState(const Flow *f) return f->alstate; } +/** + * \brief get 'disruption' flags: GAP/DEPTH/PASS + * \param f locked flow + * \param flags existing flags to be ammended + * \retval flags original flags + disrupt flags (if any) + * \TODO handle UDP + */ +uint8_t FlowGetDisruptionFlags(const Flow *f, uint8_t flags) +{ + if (f->proto != IPPROTO_TCP) { + return flags; + } + if (f->protoctx == NULL) { + return flags; + } + + uint8_t newflags = flags; + TcpSession *ssn = f->protoctx; + TcpStream *stream = flags & STREAM_TOSERVER ? &ssn->client : &ssn->server; + + if (stream->flags & STREAMTCP_STREAM_FLAG_DEPTH_REACHED) { + newflags |= STREAM_DEPTH; + } + if (stream->flags & STREAMTCP_STREAM_FLAG_GAP) { + newflags |= STREAM_GAP; + } + /* todo: handle pass case (also for UDP!) */ + + return newflags; +} + /************************************Unittests*******************************/ #ifdef UNITTESTS diff --git a/src/flow.h b/src/flow.h index bc1f65ac88..caa34c6fc8 100644 --- a/src/flow.h +++ b/src/flow.h @@ -568,6 +568,7 @@ int FlowClearMemory(Flow *,uint8_t ); AppProto FlowGetAppProtocol(const Flow *f); void *FlowGetAppState(const Flow *f); +uint8_t FlowGetDisruptionFlags(const Flow *f, uint8_t flags); void FlowHandlePacketUpdateRemove(Flow *f, Packet *p); void FlowHandlePacketUpdate(Flow *f, Packet *p);