app-layer: improve EOF handling

On receiving TCP end of stream packets (e.g. RST, but also sometimes FIN
packets), in some cases the AppLayer parser would not be notified. This
could happen in IDS mode, but would especially be an issue in IPS mode.

This patch changes the logic of the AppLayer API to handle this. When no
new data is available, and the stream ends, the AppLayer API now gets
called with a NULL/0 input, but with the EOF flag set.

This allows the AppLayer parser to call it's final routines still in the
context of a real packet.
pull/1561/head
Victor Julien 10 years ago
parent df79c1019f
commit cf9ff6adbd

@ -739,28 +739,30 @@ static int HTPHandleRequestData(Flow *f, void *htp_state,
htp_time_t ts = { f->lastts.tv_sec, f->lastts.tv_usec };
/* pass the new data to the htp parser */
r = htp_connp_req_data(hstate->connp, &ts, input, input_len);
if (input_len > 0) {
r = htp_connp_req_data(hstate->connp, &ts, input, input_len);
switch(r) {
case HTP_STREAM_ERROR:
switch(r) {
case HTP_STREAM_ERROR:
hstate->flags |= HTP_FLAG_STATE_ERROR;
hstate->flags &= ~HTP_FLAG_STATE_DATA;
hstate->flags &= ~HTP_FLAG_NEW_BODY_SET;
ret = -1;
break;
case HTP_STREAM_DATA:
case HTP_STREAM_DATA_OTHER:
hstate->flags |= HTP_FLAG_STATE_ERROR;
hstate->flags &= ~HTP_FLAG_STATE_DATA;
hstate->flags &= ~HTP_FLAG_NEW_BODY_SET;
ret = -1;
break;
case HTP_STREAM_DATA:
case HTP_STREAM_DATA_OTHER:
hstate->flags |= HTP_FLAG_STATE_DATA;
break;
case HTP_STREAM_TUNNEL:
break;
default:
hstate->flags &= ~HTP_FLAG_STATE_DATA;
hstate->flags &= ~HTP_FLAG_NEW_BODY_SET;
hstate->flags |= HTP_FLAG_STATE_DATA;
break;
case HTP_STREAM_TUNNEL:
break;
default:
hstate->flags &= ~HTP_FLAG_STATE_DATA;
hstate->flags &= ~HTP_FLAG_NEW_BODY_SET;
}
HTPHandleError(hstate);
}
HTPHandleError(hstate);
/* if the TCP connection is closed, then close the HTTP connection */
if (AppLayerParserStateIssetFlag(pstate, APP_LAYER_PARSER_EOF) &&
@ -815,25 +817,27 @@ static int HTPHandleResponseData(Flow *f, void *htp_state,
hstate->flags &=~ HTP_FLAG_NEW_BODY_SET;
htp_time_t ts = { f->lastts.tv_sec, f->lastts.tv_usec };
r = htp_connp_res_data(hstate->connp, &ts, input, input_len);
switch(r) {
case HTP_STREAM_ERROR:
hstate->flags = HTP_FLAG_STATE_ERROR;
hstate->flags &= ~HTP_FLAG_STATE_DATA;
hstate->flags &= ~HTP_FLAG_NEW_BODY_SET;
ret = -1;
break;
case HTP_STREAM_DATA:
case HTP_STREAM_DATA_OTHER:
hstate->flags |= HTP_FLAG_STATE_DATA;
break;
case HTP_STREAM_TUNNEL:
break;
default:
hstate->flags &= ~HTP_FLAG_STATE_DATA;
hstate->flags &= ~HTP_FLAG_NEW_BODY_SET;
}
HTPHandleError(hstate);
if (input_len > 0) {
r = htp_connp_res_data(hstate->connp, &ts, input, input_len);
switch(r) {
case HTP_STREAM_ERROR:
hstate->flags = HTP_FLAG_STATE_ERROR;
hstate->flags &= ~HTP_FLAG_STATE_DATA;
hstate->flags &= ~HTP_FLAG_NEW_BODY_SET;
ret = -1;
break;
case HTP_STREAM_DATA:
case HTP_STREAM_DATA_OTHER:
hstate->flags |= HTP_FLAG_STATE_DATA;
break;
case HTP_STREAM_TUNNEL:
break;
default:
hstate->flags &= ~HTP_FLAG_STATE_DATA;
hstate->flags &= ~HTP_FLAG_NEW_BODY_SET;
}
HTPHandleError(hstate);
}
/* if we the TCP connection is closed, then close the HTTP connection */
if (AppLayerParserStateIssetFlag(pstate, APP_LAYER_PARSER_EOF) &&

@ -890,7 +890,7 @@ int AppLayerParserParse(AppLayerParserThreadCtx *alp_tctx, Flow *f, AppProto alp
}
/* invoke the recursive parser, but only on data. We may get empty msgs on EOF */
if (input_len > 0) {
if (input_len > 0 || (flags & STREAM_EOF)) {
/* invoke the parser */
if (p->Parser[(flags & STREAM_TOSERVER) ? 0 : 1](f, alstate, pstate,
input, input_len,

Loading…
Cancel
Save