alert ip any any -> any any (msg:"SURICATA Applayer Wrong direction first Data"; flow:established; app-layer-event:applayer_wrong_direction_first_data; flowint:applayer.anomaly.count,+,1; classtype:protocol-command-decode; sid:2260001; rev:1;)
alert ip any any -> any any (msg:"SURICATA Applayer Detect protocol only one direction"; flow:established; app-layer-event:applayer_detect_protocol_only_one_direction; flowint:applayer.anomaly.count,+,1; classtype:protocol-command-decode; sid:2260002; rev:1;)
alert ip any any -> any any (msg:"SURICATA Applayer Protocol detection skipped"; flow:established; app-layer-event:applayer_proto_detection_skipped; flowint:applayer.anomaly.count,+,1; classtype:protocol-command-decode; sid:2260003; rev:1;)
-alert ip any any -> any any (msg:"SURICATA Applayer No TLS after STARTTLS"; flow:established; app-layer-event:applayer_no_tls_after_starttls; flowint:applayer.anomaly.count,+,1; classtype:protocol-command-decode; sid:226004; rev:1;)
+# alert if STARTTLS was not followed by actual SSL/TLS
+alert tcp any any -> any any (msg:"SURICATA Applayer No TLS after STARTTLS"; flow:established; app-layer-event:applayer_no_tls_after_starttls; flowint:applayer.anomaly.count,+,1; classtype:protocol-command-decode; sid:2260004; rev:2;)
+# unexpected protocol in protocol upgrade
+alert tcp any any -> any any (msg:"SURICATA Applayer Unexpected protocol"; flow:established; app-layer-event:applayer_unexpected_protocol; flowint:applayer.anomaly.count,+,1; classtype:protocol-command-decode; sid:2260005; rev:1;)
-#next sid is 2260005
+#next sid is 2260006
uint32_t *alproto_masks;
uint32_t mask = 0;
+ const uint16_t dp = f->protodetect_dp ? f->protodetect_dp : f->dp;
+ const uint16_t sp = f->sp;
+
if (direction & STREAM_TOSERVER) {
/* first try the destination port */
- pp_port_dp = AppLayerProtoDetectGetProbingParsers(alpd_ctx.ctx_pp, ipproto, f->dp);
+ pp_port_dp = AppLayerProtoDetectGetProbingParsers(alpd_ctx.ctx_pp, ipproto, dp);
alproto_masks = &f->probing_parser_toserver_alproto_masks;
if (pp_port_dp != NULL) {
- SCLogDebug("toserver - Probing parser found for destination port %"PRIu16, f->dp);
+ SCLogDebug("toserver - Probing parser found for destination port %"PRIu16, dp);
/* found based on destination port, so use dp registration */
pe1 = pp_port_dp->dp;
} else {
- SCLogDebug("toserver - No probing parser registered for dest port %"PRIu16,
- f->dp);
+ SCLogDebug("toserver - No probing parser registered for dest port %"PRIu16, dp);
}
- pp_port_sp = AppLayerProtoDetectGetProbingParsers(alpd_ctx.ctx_pp, ipproto, f->sp);
+ pp_port_sp = AppLayerProtoDetectGetProbingParsers(alpd_ctx.ctx_pp, ipproto, sp);
if (pp_port_sp != NULL) {
- SCLogDebug("toserver - Probing parser found for source port %"PRIu16, f->sp);
+ SCLogDebug("toserver - Probing parser found for source port %"PRIu16, sp);
/* found based on source port, so use sp registration */
pe2 = pp_port_sp->sp;
} else {
- SCLogDebug("toserver - No probing parser registered for source port %"PRIu16,
- f->sp);
+ SCLogDebug("toserver - No probing parser registered for source port %"PRIu16, sp);
}
} else {
/* first try the destination port */
- pp_port_dp = AppLayerProtoDetectGetProbingParsers(alpd_ctx.ctx_pp, ipproto, f->dp);
+ pp_port_dp = AppLayerProtoDetectGetProbingParsers(alpd_ctx.ctx_pp, ipproto, dp);
alproto_masks = &f->probing_parser_toclient_alproto_masks;
if (pp_port_dp != NULL) {
- SCLogDebug("toclient - Probing parser found for destination port %"PRIu16, f->dp);
+ SCLogDebug("toclient - Probing parser found for destination port %"PRIu16, dp);
/* found based on destination port, so use dp registration */
pe1 = pp_port_dp->dp;
} else {
- SCLogDebug("toclient - No probing parser registered for dest port %"PRIu16,
- f->dp);
+ SCLogDebug("toclient - No probing parser registered for dest port %"PRIu16, dp);
}
- pp_port_sp = AppLayerProtoDetectGetProbingParsers(alpd_ctx.ctx_pp, ipproto, f->sp);
+ pp_port_sp = AppLayerProtoDetectGetProbingParsers(alpd_ctx.ctx_pp, ipproto, sp);
if (pp_port_sp != NULL) {
- SCLogDebug("toclient - Probing parser found for source port %"PRIu16, f->sp);
+ SCLogDebug("toclient - Probing parser found for source port %"PRIu16, sp);
pe2 = pp_port_sp->sp;
} else {
- SCLogDebug("toclient - No probing parser registered for source port %"PRIu16,
- f->sp);
+ SCLogDebug("toclient - No probing parser registered for source port %"PRIu16, sp);
}
}
SCReturn;
}
+/** \brief request applayer to wrap up this protocol and rerun protocol
+ * detection.
+ *
+ * When this is called, the old session is reset unconditionally. A
+ * 'detect/log' flush packet is generated for both direction before
+ * the reset, so allow for final detection and logging.
+ *
+ * \param f flow to act on
+ * \param dp destination port to use in protocol detection. Set to 443
+ * for start tls, set to the HTTP uri port for CONNECT and
+ * set to 0 to not use it.
+ * \param expect_proto expected protocol. AppLayer event will be set if
+ * detected protocol differs from this.
+ */
+void AppLayerRequestProtocolChange(Flow *f, uint16_t dp, AppProto expect_proto)
+{
+ FlowSetChangeProtoFlag(f);
+ f->protodetect_dp = dp;
+ f->alproto_expect = expect_proto;
+}
+
+/** \brief request applayer to wrap up this protocol and rerun protocol
+ * detection with expectation of TLS. Used by STARTTLS.
+ *
+ * Sets detection port to 443 to make port based TLS detection work for
+ * SMTP, FTP etc as well.
+ *
+ * \param f flow to act on
+ */
+void AppLayerRequestProtocolTLSUpgrade(Flow *f)
+{
+ AppLayerRequestProtocolChange(f, 443, ALPROTO_TLS);
+}
+
void AppLayerProtoDetectReset(Flow *f)
{
FlowUnsetChangeProtoFlag(f);
*/
void AppLayerProtoDetectReset(Flow *);
+void AppLayerRequestProtocolChange(Flow *f, uint16_t dp, AppProto expect_proto);
+void AppLayerRequestProtocolTLSUpgrade(Flow *f);
+
/**
* \brief Cleans up the app layer protocol detection phase.
*/
APPLAYER_PROTO_DETECTION_SKIPPED },
{ "APPLAYER_NO_TLS_AFTER_STARTTLS",
APPLAYER_NO_TLS_AFTER_STARTTLS },
+ { "APPLAYER_UNEXPECTED_PROTOCOL",
+ APPLAYER_UNEXPECTED_PROTOCOL },
{ NULL,
-1 },
};
APPLAYER_DETECT_PROTOCOL_ONLY_ONE_DIRECTION,
APPLAYER_PROTO_DETECTION_SKIPPED,
APPLAYER_NO_TLS_AFTER_STARTTLS,
+ APPLAYER_UNEXPECTED_PROTOCOL,
};
/* the event types for app events */
if (state->command == FTP_COMMAND_AUTH_TLS) {
if (input_len >= 4 && SCMemcmp("234 ", input, 4) == 0) {
- FlowSetChangeProtoFlag(f);
+ AppLayerRequestProtocolTLSUpgrade(f);
}
}
if ((tx->response_status_number >= 200) &&
(tx->response_status_number < 300) &&
(hstate->transaction_cnt == 1)) {
- FlowSetChangeProtoFlag(hstate->f);
+ uint16_t dp = 0;
+ if (tx->request_port_number != -1) {
+ dp = (uint16_t)tx->request_port_number;
+ }
+ // both ALPROTO_HTTP and ALPROTO_TLS are normal options
+ AppLayerRequestProtocolChange(hstate->f, dp, ALPROTO_UNKNOWN);
tx->request_progress = HTP_REQUEST_COMPLETE;
tx->response_progress = HTP_RESPONSE_COMPLETE;
}
if (reply_code == SMTP_REPLY_220) {
/* we are entering STARRTTLS data mode */
state->parser_state |= SMTP_PARSER_STATE_COMMAND_DATA_MODE;
- FlowSetChangeProtoFlag(f);
+ AppLayerRequestProtocolTLSUpgrade(f);
state->curr_tx->done = 1;
} else {
/* decoder event */
}
SCLogDebug("protocol change, old %s, new %s",
AppProtoToString(f->alproto_orig), AppProtoToString(f->alproto));
- if (f->alproto != ALPROTO_TLS) {
+
+ if (f->alproto_expect != ALPROTO_UNKNOWN &&
+ f->alproto != f->alproto_expect)
+ {
AppLayerDecoderEventsSetEventRaw(&p->app_layer_events,
- APPLAYER_NO_TLS_AFTER_STARTTLS);
+ APPLAYER_UNEXPECTED_PROTOCOL);
+
+ if (f->alproto_expect == ALPROTO_TLS && f->alproto != ALPROTO_TLS) {
+ AppLayerDecoderEventsSetEventRaw(&p->app_layer_events,
+ APPLAYER_NO_TLS_AFTER_STARTTLS);
+
+ }
}
} else {
SCLogDebug("stream data (len %" PRIu32 " alproto "
(f)->probing_parser_toclient_alproto_masks = 0; \
(f)->flags = 0; \
(f)->file_flags = 0; \
+ (f)->protodetect_dp = 0; \
(f)->lastts.tv_sec = 0; \
(f)->lastts.tv_usec = 0; \
FLOWLOCK_INIT((f)); \
(f)->alproto = 0; \
(f)->alproto_ts = 0; \
(f)->alproto_tc = 0; \
+ (f)->alproto_orig = 0; \
+ (f)->alproto_expect = 0; \
(f)->de_ctx_version = 0; \
(f)->thread_id = 0; \
(f)->alparser = NULL; \
(f)->probing_parser_toclient_alproto_masks = 0; \
(f)->flags = 0; \
(f)->file_flags = 0; \
+ (f)->protodetect_dp = 0; \
(f)->lastts.tv_sec = 0; \
(f)->lastts.tv_usec = 0; \
(f)->protoctx = NULL; \
(f)->alproto = 0; \
(f)->alproto_ts = 0; \
(f)->alproto_tc = 0; \
+ (f)->alproto_orig = 0; \
+ (f)->alproto_expect = 0; \
(f)->de_ctx_version = 0; \
(f)->thread_id = 0; \
(f)->sgh_toserver = NULL; \
uint16_t file_flags; /**< file tracking/extraction flags */
/* coccinelle: Flow:file_flags:FLOWFILE_ */
+ /** destination port to be used in protocol detection. This is meant
+ * for use with STARTTLS and HTTP CONNECT detection */
+ uint16_t protodetect_dp; /**< 0 if not used */
+
#ifdef FLOWLOCK_RWLOCK
SCRWLock r;
#elif defined FLOWLOCK_MUTEX
/** original application level protocol. Used to indicate the previous
protocol when changing to another protocol , e.g. with STARTTLS. */
AppProto alproto_orig;
+ /** expected app protocol: used in protocol change/upgrade like in
+ * STARTTLS. */
+ AppProto alproto_expect;
/** detection engine ctx version used to inspect this flow. Set at initial
* inspection. If it doesn't match the currently in use de_ctx, the