protocol-change: sets event in case of failure

Protocol change can fail if one protocol change is already
occuring.

Ticket: #5509
pull/7767/head
Philippe Antoine 4 years ago committed by Victor Julien
parent e94920b49f
commit 11f849c3ee

@ -87,4 +87,6 @@ alert http any any -> any any (msg:"SURICATA HTTP invalid Range header value"; f
alert http any any -> any any (msg:"SURICATA HTTP file name too long"; flow:established; app-layer-event:http.file_name_too_long; flowint:http.anomaly.count,+,1; classtype:protocol-command-decode; sid:2221052; rev:1;) alert http any any -> any any (msg:"SURICATA HTTP file name too long"; flow:established; app-layer-event:http.file_name_too_long; flowint:http.anomaly.count,+,1; classtype:protocol-command-decode; sid:2221052; rev:1;)
# next sid 2221053 alert http any any -> any any (msg:"SURICATA HTTP failed protocol change"; flow:established; app-layer-event:http.failed_protocol_change; flowint:http.anomaly.count,+,1; classtype:protocol-command-decode; sid:2221053; rev:1;)
# next sid 2221054

@ -30,4 +30,5 @@ alert smtp any any -> any any (msg:"SURICATA SMTP Mime boundary length exceeded"
alert smtp any any -> any any (msg:"SURICATA SMTP duplicate fields"; flow:established,to_server; app-layer-event:smtp.duplicate_fields; flowint:smtp.anomaly.count,+,1; classtype:protocol-command-decode; sid:2220018; rev:1;) alert smtp any any -> any any (msg:"SURICATA SMTP duplicate fields"; flow:established,to_server; app-layer-event:smtp.duplicate_fields; flowint:smtp.anomaly.count,+,1; classtype:protocol-command-decode; sid:2220018; rev:1;)
alert smtp any any -> any any (msg:"SURICATA SMTP unparsable content"; flow:established,to_server; app-layer-event:smtp.unparsable_content; flowint:smtp.anomaly.count,+,1; classtype:protocol-command-decode; sid:2220019; rev:1;) alert smtp any any -> any any (msg:"SURICATA SMTP unparsable content"; flow:established,to_server; app-layer-event:smtp.unparsable_content; flowint:smtp.anomaly.count,+,1; classtype:protocol-command-decode; sid:2220019; rev:1;)
alert smtp any any -> any any (msg:"SURICATA SMTP filename truncated"; flow:established,to_server; app-layer-event:smtp.mime_long_filename; flowint:smtp.anomaly.count,+,1; classtype:protocol-command-decode; sid:2220020; rev:1;) alert smtp any any -> any any (msg:"SURICATA SMTP filename truncated"; flow:established,to_server; app-layer-event:smtp.mime_long_filename; flowint:smtp.anomaly.count,+,1; classtype:protocol-command-decode; sid:2220020; rev:1;)
# next sid 2220021 alert smtp any any -> any any (msg:"SURICATA SMTP failed protocol change"; flow:established; app-layer-event:smtp.failed_protocol_change; flowint:smtp.anomaly.count,+,1; classtype:protocol-command-decode; sid:2220021; rev:1;)
# next sid 2220022

@ -388,7 +388,7 @@ extern {
pp_min_depth: u16, pp_max_depth: u16) -> c_int; pp_min_depth: u16, pp_max_depth: u16) -> c_int;
pub fn AppLayerProtoDetectConfProtoDetectionEnabled(ipproto: *const c_char, proto: *const c_char) -> c_int; pub fn AppLayerProtoDetectConfProtoDetectionEnabled(ipproto: *const c_char, proto: *const c_char) -> c_int;
pub fn AppLayerProtoDetectConfProtoDetectionEnabledDefault(ipproto: *const c_char, proto: *const c_char, default: bool) -> c_int; pub fn AppLayerProtoDetectConfProtoDetectionEnabledDefault(ipproto: *const c_char, proto: *const c_char, default: bool) -> c_int;
pub fn AppLayerRequestProtocolTLSUpgrade(flow: *const Flow); pub fn AppLayerRequestProtocolTLSUpgrade(flow: *const Flow) -> bool;
} }
// Defined in app-layer-parser.h // Defined in app-layer-parser.h

@ -1958,13 +1958,13 @@ void AppLayerProtoDetectRegisterAlias(const char *proto_name, const char *proto_
* \param expect_proto expected protocol. AppLayer event will be set if * \param expect_proto expected protocol. AppLayer event will be set if
* detected protocol differs from this. * detected protocol differs from this.
*/ */
void AppLayerRequestProtocolChange(Flow *f, uint16_t dp, AppProto expect_proto) bool AppLayerRequestProtocolChange(Flow *f, uint16_t dp, AppProto expect_proto)
{ {
if (FlowChangeProto(f)) { if (FlowChangeProto(f)) {
// If we are already changing protocols, from SMTP to TLS for instance, // If we are already changing protocols, from SMTP to TLS for instance,
// and that we do not get TLS but HTTP1, which is requesting whange to HTTP2, // and that we do not get TLS but HTTP1, which is requesting whange to HTTP2,
// we do not proceed the new protocol change // we do not proceed the new protocol change
return; return false;
} }
FlowSetChangeProtoFlag(f); FlowSetChangeProtoFlag(f);
f->protodetect_dp = dp; f->protodetect_dp = dp;
@ -1978,6 +1978,7 @@ void AppLayerRequestProtocolChange(Flow *f, uint16_t dp, AppProto expect_proto)
if (f->alproto_tc == ALPROTO_UNKNOWN) { if (f->alproto_tc == ALPROTO_UNKNOWN) {
f->alproto_tc = f->alproto; f->alproto_tc = f->alproto;
} }
return true;
} }
/** \brief request applayer to wrap up this protocol and rerun protocol /** \brief request applayer to wrap up this protocol and rerun protocol
@ -1988,9 +1989,9 @@ void AppLayerRequestProtocolChange(Flow *f, uint16_t dp, AppProto expect_proto)
* *
* \param f flow to act on * \param f flow to act on
*/ */
void AppLayerRequestProtocolTLSUpgrade(Flow *f) bool AppLayerRequestProtocolTLSUpgrade(Flow *f)
{ {
AppLayerRequestProtocolChange(f, 443, ALPROTO_TLS); return AppLayerRequestProtocolChange(f, 443, ALPROTO_TLS);
} }
void AppLayerProtoDetectReset(Flow *f) void AppLayerProtoDetectReset(Flow *f)

@ -115,8 +115,8 @@ int AppLayerProtoDetectSetup(void);
*/ */
void AppLayerProtoDetectReset(Flow *); void AppLayerProtoDetectReset(Flow *);
void AppLayerRequestProtocolChange(Flow *f, uint16_t dp, AppProto expect_proto); bool AppLayerRequestProtocolChange(Flow *f, uint16_t dp, AppProto expect_proto);
void AppLayerRequestProtocolTLSUpgrade(Flow *f); bool AppLayerRequestProtocolTLSUpgrade(Flow *f);
/** /**
* \brief Cleans up the app layer protocol detection phase. * \brief Cleans up the app layer protocol detection phase.

@ -172,6 +172,7 @@ SCEnumCharMap http_decoder_event_table[] = {
{ "MULTIPART_INVALID_HEADER", HTTP_DECODER_EVENT_MULTIPART_INVALID_HEADER }, { "MULTIPART_INVALID_HEADER", HTTP_DECODER_EVENT_MULTIPART_INVALID_HEADER },
{ "TOO_MANY_WARNINGS", HTTP_DECODER_EVENT_TOO_MANY_WARNINGS }, { "TOO_MANY_WARNINGS", HTTP_DECODER_EVENT_TOO_MANY_WARNINGS },
{ "FAILED_PROTOCOL_CHANGE", HTTP_DECODER_EVENT_FAILED_PROTOCOL_CHANGE },
{ NULL, -1 }, { NULL, -1 },
}; };
@ -968,7 +969,10 @@ static AppLayerResult HTPHandleResponseData(Flow *f, void *htp_state, AppLayerPa
} }
consumed = htp_connp_res_data_consumed(hstate->connp); consumed = htp_connp_res_data_consumed(hstate->connp);
hstate->slice = NULL; hstate->slice = NULL;
AppLayerRequestProtocolChange(hstate->f, dp, ALPROTO_HTTP2); if (!AppLayerRequestProtocolChange(hstate->f, dp, ALPROTO_HTTP2)) {
HTPSetEvent(hstate, NULL, STREAM_TOCLIENT,
HTTP_DECODER_EVENT_FAILED_PROTOCOL_CHANGE);
}
// During HTTP2 upgrade, we may consume the HTTP1 part of the data // During HTTP2 upgrade, we may consume the HTTP1 part of the data
// and we need to parser the remaining part with HTTP2 // and we need to parser the remaining part with HTTP2
if (consumed > 0 && consumed < input_len) { if (consumed > 0 && consumed < input_len) {
@ -2282,7 +2286,10 @@ static int HTPCallbackResponseComplete(htp_tx_t *tx)
dp = (uint16_t)tx->request_port_number; dp = (uint16_t)tx->request_port_number;
} }
// both ALPROTO_HTTP1 and ALPROTO_TLS are normal options // both ALPROTO_HTTP1 and ALPROTO_TLS are normal options
AppLayerRequestProtocolChange(hstate->f, dp, ALPROTO_UNKNOWN); if (!AppLayerRequestProtocolChange(hstate->f, dp, ALPROTO_UNKNOWN)) {
HTPSetEvent(
hstate, htud, STREAM_TOCLIENT, HTTP_DECODER_EVENT_FAILED_PROTOCOL_CHANGE);
}
tx->request_progress = HTP_REQUEST_COMPLETE; tx->request_progress = HTP_REQUEST_COMPLETE;
tx->response_progress = HTP_RESPONSE_COMPLETE; tx->response_progress = HTP_RESPONSE_COMPLETE;
} }

@ -139,6 +139,8 @@ enum {
HTTP_DECODER_EVENT_MULTIPART_INVALID_HEADER, HTTP_DECODER_EVENT_MULTIPART_INVALID_HEADER,
HTTP_DECODER_EVENT_TOO_MANY_WARNINGS, HTTP_DECODER_EVENT_TOO_MANY_WARNINGS,
HTTP_DECODER_EVENT_FAILED_PROTOCOL_CHANGE,
}; };
typedef enum HtpSwfCompressType_ { typedef enum HtpSwfCompressType_ {

@ -145,6 +145,7 @@ SCEnumCharMap smtp_decoder_event_table[] = {
{ "NO_SERVER_WELCOME_MESSAGE", SMTP_DECODER_EVENT_NO_SERVER_WELCOME_MESSAGE }, { "NO_SERVER_WELCOME_MESSAGE", SMTP_DECODER_EVENT_NO_SERVER_WELCOME_MESSAGE },
{ "TLS_REJECTED", SMTP_DECODER_EVENT_TLS_REJECTED }, { "TLS_REJECTED", SMTP_DECODER_EVENT_TLS_REJECTED },
{ "DATA_COMMAND_REJECTED", SMTP_DECODER_EVENT_DATA_COMMAND_REJECTED }, { "DATA_COMMAND_REJECTED", SMTP_DECODER_EVENT_DATA_COMMAND_REJECTED },
{ "FAILED_PROTOCOL_CHANGE", SMTP_DECODER_EVENT_FAILED_PROTOCOL_CHANGE },
/* MIME Events */ /* MIME Events */
{ "MIME_PARSE_FAILED", SMTP_DECODER_EVENT_MIME_PARSE_FAILED }, { "MIME_PARSE_FAILED", SMTP_DECODER_EVENT_MIME_PARSE_FAILED },
@ -944,7 +945,9 @@ static int SMTPProcessReply(SMTPState *state, Flow *f, AppLayerParserState *psta
if (reply_code == SMTP_REPLY_220) { if (reply_code == SMTP_REPLY_220) {
/* we are entering STARRTTLS data mode */ /* we are entering STARRTTLS data mode */
state->parser_state |= SMTP_PARSER_STATE_COMMAND_DATA_MODE; state->parser_state |= SMTP_PARSER_STATE_COMMAND_DATA_MODE;
AppLayerRequestProtocolTLSUpgrade(f); if (!AppLayerRequestProtocolTLSUpgrade(f)) {
SMTPSetEvent(state, SMTP_DECODER_EVENT_FAILED_PROTOCOL_CHANGE);
}
if (state->curr_tx) { if (state->curr_tx) {
SMTPTransactionComplete(state); SMTPTransactionComplete(state);
} }

@ -38,6 +38,7 @@ enum {
SMTP_DECODER_EVENT_NO_SERVER_WELCOME_MESSAGE, SMTP_DECODER_EVENT_NO_SERVER_WELCOME_MESSAGE,
SMTP_DECODER_EVENT_TLS_REJECTED, SMTP_DECODER_EVENT_TLS_REJECTED,
SMTP_DECODER_EVENT_DATA_COMMAND_REJECTED, SMTP_DECODER_EVENT_DATA_COMMAND_REJECTED,
SMTP_DECODER_EVENT_FAILED_PROTOCOL_CHANGE,
/* MIME Events */ /* MIME Events */
SMTP_DECODER_EVENT_MIME_PARSE_FAILED, SMTP_DECODER_EVENT_MIME_PARSE_FAILED,

Loading…
Cancel
Save