diff --git a/src/app-layer-htp.c b/src/app-layer-htp.c index 131e6d5d6a..e497db4823 100644 --- a/src/app-layer-htp.c +++ b/src/app-layer-htp.c @@ -111,6 +111,9 @@ static int HTPHandleRequestData(Flow *f, void *htp_state, AppLayerParserResult *output) { SCEnter(); + int r = -1; + int ret = 1; + HtpState *hstate = (HtpState *)htp_state; /* Open the HTTP connection on receiving the first request */ @@ -123,8 +126,8 @@ static int HTPHandleRequestData(Flow *f, void *htp_state, SCLogDebug("using existing htp handle"); } - if (htp_connp_req_data(hstate->connp, 0, input, input_len) == - STREAM_STATE_ERROR) + r = htp_connp_req_data(hstate->connp, 0, input, input_len); + if(r == STREAM_STATE_ERROR) { if (hstate->connp->last_error != NULL) { SCLogError(SC_ALPARSER_ERR, "Error in parsing HTTP client request: " @@ -134,20 +137,27 @@ static int HTPHandleRequestData(Flow *f, void *htp_state, } else { SCLogError(SC_ALPARSER_ERR, "Error in parsing HTTP client request"); } + hstate->flags |= HTP_FLAG_STATE_ERROR; + hstate->flags &= ~HTP_FLAG_STATE_DATA; + ret = -1; - SCReturnInt(-1); + } else if (r == STREAM_STATE_DATA) { + hstate->flags |= HTP_FLAG_STATE_DATA; + } else { + hstate->flags &= ~HTP_FLAG_STATE_DATA; } /* if we the TCP connection is closed, then close the HTTP connection */ if ((pstate->flags & APP_LAYER_PARSER_EOF) && - ! (hstate->flags & HTP_FLAG_STATE_CLOSED)) + ! (hstate->flags & HTP_FLAG_STATE_CLOSED) && + ! (hstate->flags & HTP_FLAG_STATE_DATA)) { htp_connp_close(hstate->connp, 0); hstate->flags |= HTP_FLAG_STATE_CLOSED; SCLogDebug("stream eof encountered, closing htp handle"); } - SCReturnInt(1); + SCReturnInt(ret); } /** @@ -168,10 +178,13 @@ static int HTPHandleResponseData(Flow *f, void *htp_state, AppLayerParserResult *output) { SCEnter(); + int r = -1; + int ret = 1; + HtpState *hstate = (HtpState *)htp_state; - if (htp_connp_res_data(hstate->connp, 0, input, input_len) == - STREAM_STATE_ERROR) + r = htp_connp_res_data(hstate->connp, 0, input, input_len); + if (r == STREAM_STATE_ERROR) { if (hstate->connp->last_error != NULL) { SCLogError(SC_ALPARSER_ERR, "Error in parsing HTTP server request: " @@ -181,19 +194,25 @@ static int HTPHandleResponseData(Flow *f, void *htp_state, } else { SCLogError(SC_ALPARSER_ERR, "Error in parsing HTTP server request"); } + hstate->flags = HTP_FLAG_STATE_ERROR; + ret = -1; - SCReturnInt(-1); + } else if (r == STREAM_STATE_DATA) { + hstate->flags |= HTP_FLAG_STATE_DATA; + } else { + hstate->flags &= ~HTP_FLAG_STATE_DATA; } /* if we the TCP connection is closed, then close the HTTP connection */ if ((pstate->flags & APP_LAYER_PARSER_EOF) && - ! (hstate->flags & HTP_FLAG_STATE_CLOSED)) + ! (hstate->flags & HTP_FLAG_STATE_CLOSED) && + ! (hstate->flags & HTP_FLAG_STATE_DATA)) { htp_connp_close(hstate->connp, 0); hstate->flags |= HTP_FLAG_STATE_CLOSED; } - SCReturnInt(1); + SCReturnInt(ret); } /** diff --git a/src/app-layer-htp.h b/src/app-layer-htp.h index ecbd6e704a..40bf6eeff3 100644 --- a/src/app-layer-htp.h +++ b/src/app-layer-htp.h @@ -10,10 +10,15 @@ #include -#define HTP_FLAG_STATE_OPEN 0x01 /**< Flag to indicate that HTTP connection - is open */ -#define HTP_FLAG_STATE_CLOSED 0x02 /**< Flag to indicate that HTTP connection - is closed */ +#define HTP_FLAG_STATE_OPEN 0x01 /**< Flag to indicate that HTTP + connection is open */ +#define HTP_FLAG_STATE_CLOSED 0x02 /**< Flag to indicate that HTTP + connection is closed */ +#define HTP_FLAG_STATE_DATA 0x04 /**< Flag to indicate that HTTP + connection needs more data */ +#define HTP_FLAG_STATE_ERROR 0x08 /**< Flag to indicate that an error + has been occured on HTTP + connection */ typedef struct HtpState_ { diff --git a/src/stream-tcp.c b/src/stream-tcp.c index 17394add2d..2d6c0afb8a 100644 --- a/src/stream-tcp.c +++ b/src/stream-tcp.c @@ -1548,6 +1548,12 @@ static int StreamTcpPacketStateFinWait1(ThreadVars *tv, Packet *p, } if (PKT_IS_TOSERVER(p)) { + if (TCP_GET_SEQ(p) != ssn->client.next_seq) { + SCLogDebug("ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32 "" + " != %" PRIu32 " from stream", ssn, + TCP_GET_SEQ(p), ssn->client.next_seq); + return -1; + } SCLogDebug("ssn %p: pkt (%" PRIu32 ") is to server: SEQ " "%" PRIu32 ", ACK %" PRIu32 "", ssn, p->payload_len, TCP_GET_SEQ(p), TCP_GET_ACK(p)); @@ -1563,10 +1569,23 @@ static int StreamTcpPacketStateFinWait1(ThreadVars *tv, Packet *p, if (! (ssn->flags & STREAMTCP_FLAG_NOCLIENT_REASSEMBLY)) StreamTcpReassembleHandleSegment(stt->ra_ctx, ssn, &ssn->client, p); + + if (SEQ_EQ(ssn->client.next_seq, TCP_GET_SEQ(p))) { + ssn->client.next_seq += p->payload_len; + SCLogDebug("ssn %p: ssn->client.next_seq %" PRIu32 "", + ssn, ssn->client.next_seq); + } + SCLogDebug("ssn %p: =+ next SEQ %" PRIu32 ", last ACK " "%" PRIu32 "", ssn, ssn->client.next_seq, ssn->server.last_ack); } else { /* implied to client */ + if (TCP_GET_SEQ(p) != ssn->server.next_seq) { + SCLogDebug("ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32 "" + " != %" PRIu32 " from stream", ssn, + TCP_GET_SEQ(p), ssn->server.next_seq); + return -1; + } SCLogDebug("ssn %p: pkt (%" PRIu32 ") is to client: SEQ " "%" PRIu32 ", ACK %" PRIu32 "", ssn, p->payload_len, TCP_GET_SEQ(p), TCP_GET_ACK(p)); @@ -1581,6 +1600,13 @@ static int StreamTcpPacketStateFinWait1(ThreadVars *tv, Packet *p, if (!(ssn->flags & STREAMTCP_FLAG_NOSERVER_REASSEMBLY)) StreamTcpReassembleHandleSegment(stt->ra_ctx, ssn, &ssn->server, p); + + if (SEQ_EQ(ssn->server.next_seq, TCP_GET_SEQ(p))) { + ssn->server.next_seq += p->payload_len; + SCLogDebug("ssn %p: ssn->server.next_seq %" PRIu32 "", + ssn, ssn->server.next_seq); + } + SCLogDebug("ssn %p: =+ next SEQ %" PRIu32 ", last ACK " "%" PRIu32 "", ssn, ssn->server.next_seq, ssn->client.last_ack); @@ -1621,6 +1647,13 @@ static int StreamTcpPacketStateFinWait1(ThreadVars *tv, Packet *p, if (! (ssn->flags & STREAMTCP_FLAG_NOCLIENT_REASSEMBLY)) StreamTcpReassembleHandleSegment(stt->ra_ctx, ssn, &ssn->client, p); + + if (SEQ_EQ(ssn->client.next_seq, TCP_GET_SEQ(p))) { + ssn->client.next_seq += p->payload_len; + SCLogDebug("ssn %p: ssn->client.next_seq %" PRIu32 "", + ssn, ssn->client.next_seq); + } + SCLogDebug("ssn %p: =+ next SEQ %" PRIu32 ", last ACK " "%" PRIu32 "", ssn, ssn->client.next_seq, ssn->server.last_ack); @@ -1650,6 +1683,13 @@ static int StreamTcpPacketStateFinWait1(ThreadVars *tv, Packet *p, if (!(ssn->flags & STREAMTCP_FLAG_NOSERVER_REASSEMBLY)) StreamTcpReassembleHandleSegment(stt->ra_ctx, ssn, &ssn->server, p); + + if (SEQ_EQ(ssn->server.next_seq, TCP_GET_SEQ(p))) { + ssn->server.next_seq += p->payload_len; + SCLogDebug("ssn %p: ssn->server.next_seq %" PRIu32 "", + ssn, ssn->server.next_seq); + } + SCLogDebug("ssn %p: =+ next SEQ %" PRIu32 ", last ACK " "%" PRIu32 "", ssn, ssn->server.next_seq, ssn->client.last_ack); @@ -1722,6 +1762,13 @@ static int StreamTcpPacketStateFinWait2(ThreadVars *tv, Packet *p, if (! (ssn->flags & STREAMTCP_FLAG_NOCLIENT_REASSEMBLY)) StreamTcpReassembleHandleSegment(stt->ra_ctx, ssn, &ssn->client, p); + + if (SEQ_EQ(ssn->client.next_seq, TCP_GET_SEQ(p))) { + ssn->client.next_seq += p->payload_len; + SCLogDebug("ssn %p: ssn->client.next_seq %" PRIu32 "", + ssn, ssn->client.next_seq); + } + SCLogDebug("ssn %p: =+ next SEQ %" PRIu32 ", last ACK " "%" PRIu32 "", ssn, ssn->client.next_seq, ssn->server.last_ack); @@ -1747,6 +1794,13 @@ static int StreamTcpPacketStateFinWait2(ThreadVars *tv, Packet *p, if (!(ssn->flags & STREAMTCP_FLAG_NOSERVER_REASSEMBLY)) StreamTcpReassembleHandleSegment(stt->ra_ctx, ssn, &ssn->server, p); + + if (SEQ_EQ(ssn->server.next_seq, TCP_GET_SEQ(p))) { + ssn->server.next_seq += p->payload_len; + SCLogDebug("ssn %p: ssn->server.next_seq %" PRIu32 "", + ssn, ssn->server.next_seq); + } + SCLogDebug("ssn %p: =+ next SEQ %" PRIu32 ", last ACK " "%" PRIu32 "", ssn, ssn->server.next_seq, ssn->client.last_ack);