]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
app-layer: support changing flow alproto
authorMats Klepsland <mats.klepsland@gmail.com>
Tue, 31 Jan 2017 13:34:30 +0000 (14:34 +0100)
committerVictor Julien <victor@inliniac.net>
Mon, 8 May 2017 08:43:36 +0000 (10:43 +0200)
Support changing the application level protocol for a flow. This is
needed by STARTTLS and HTTP CONNECT to switch from the original
alproto to tls.

This commit allows a flag to be set 'FLOW_CHANGE_PROTO', which
triggers a new protocol detection on the next packet for a flow.

src/app-layer-detect-proto.c
src/app-layer-detect-proto.h
src/app-layer.c
src/flow.c
src/flow.h

index 9a2460bce6c951d1869bf8a1cf2d466ee49229ea..209c266e561c096fc7683420abd410f3f715b656 100644 (file)
@@ -1614,6 +1614,24 @@ void AppLayerProtoDetectRegisterProtocol(AppProto alproto, const char *alproto_n
     SCReturn;
 }
 
+void AppLayerProtoDetectReset(Flow *f)
+{
+    FlowUnsetChangeProtoFlag(f);
+    FLOW_RESET_PM_DONE(f, STREAM_TOSERVER);
+    FLOW_RESET_PM_DONE(f, STREAM_TOCLIENT);
+    FLOW_RESET_PP_DONE(f, STREAM_TOSERVER);
+    FLOW_RESET_PP_DONE(f, STREAM_TOCLIENT);
+    f->probing_parser_toserver_alproto_masks = 0;
+    f->probing_parser_toclient_alproto_masks = 0;
+
+    AppLayerParserStateCleanup(f->proto, f->alproto, f->alstate, f->alparser);
+    f->alstate = NULL;
+    f->alparser = NULL;
+    f->alproto    = ALPROTO_UNKNOWN;
+    f->alproto_ts = ALPROTO_UNKNOWN;
+    f->alproto_tc = ALPROTO_UNKNOWN;
+}
+
 int AppLayerProtoDetectConfProtoDetectionEnabled(const char *ipproto,
                                                  const char *alproto)
 {
index f9a02236ecfd85e34fdd802918bd9b5efcb80b4e..6b68fe4c3b57ce7026de4df08042006af740d614 100644 (file)
@@ -106,6 +106,11 @@ int AppLayerProtoDetectPMRegisterPatternCI(uint8_t ipproto, AppProto alproto,
  */
 int AppLayerProtoDetectSetup(void);
 
+/**
+ * \brief Reset proto detect for flow
+ */
+void AppLayerProtoDetectReset(Flow *);
+
 /**
  * \brief Cleans up the app layer protocol detection phase.
  */
index 737b1861c9c159acb375e448f752fb9b6a85347d..73d74167c28d8286ac9961537560dbf447f38e32 100644 (file)
@@ -562,6 +562,14 @@ int AppLayerHandleTCPData(ThreadVars *tv, TcpReassemblyThreadCtx *ra_ctx,
                            data, data_len, flags) != 0) {
             goto failure;
         }
+    } else if (alproto != ALPROTO_UNKNOWN && FlowChangeProto(f)) {
+        f->alproto_orig = f->alproto;
+        AppLayerProtoDetectReset(f);
+        /* rerun protocol detection */
+        if (TCPProtoDetect(tv, ra_ctx, app_tctx, p, f, ssn, stream,
+                           data, data_len, flags) != 0) {
+            goto failure;
+        }
     } else {
         SCLogDebug("stream data (len %" PRIu32 " alproto "
                    "%"PRIu16" (flow %p)", data_len, f->alproto, f);
index 589f733ee98a3eee446a4eb7ec6d0e750a00b305..50075d975f01c273d3262890d1eb7665338fb992 100644 (file)
@@ -181,6 +181,38 @@ int FlowHasAlerts(const Flow *f)
     return 0;
 }
 
+/** \brief Set flag to indicate to change proto for the flow
+ *
+ * \param f flow
+ */
+void FlowSetChangeProtoFlag(Flow *f)
+{
+    f->flags |= FLOW_CHANGE_PROTO;
+}
+
+/** \brief Unset flag to indicate to change proto for the flow
+ *
+ * \param f flow
+ */
+void FlowUnsetChangeProtoFlag(Flow *f)
+{
+    f->flags &= ~FLOW_CHANGE_PROTO;
+}
+
+/** \brief Check if change proto flag is set for flow
+ * \param f flow
+ * \retval 1 change proto flag is set
+ * \retval 0 change proto flag is not set
+ */
+int FlowChangeProto(Flow *f)
+{
+    if (f->flags & FLOW_CHANGE_PROTO) {
+        return 1;
+    }
+
+    return 0;
+}
+
 /**
  *  \brief determine the direction of the packet compared to the flow
  *  \retval 0 to_server
index a490a82427cbec9564665f5a3af8dc83ea24d0d7..5224defd6895c491cebbfa368d6466460050c297 100644 (file)
@@ -93,6 +93,8 @@ typedef struct AppLayerParserState_ AppLayerParserState;
 #define FLOW_PROTO_DETECT_TS_DONE       BIT_U32(20)
 #define FLOW_PROTO_DETECT_TC_DONE       BIT_U32(21)
 
+/** Indicate that alproto detection for flow should be done again */
+#define FLOW_CHANGE_PROTO               BIT_U32(22)
 
 /* File flags */
 
@@ -384,6 +386,10 @@ typedef struct Flow_
     AppProto alproto_ts;
     AppProto alproto_tc;
 
+    /** original application level protocol. Used to indicate the previous
+       protocol when changing to another protocol , e.g. with STARTTLS. */
+    AppProto alproto_orig;
+
     /** 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
      *  stored sgh ptrs are reset. */
@@ -455,6 +461,9 @@ void FlowShutdown(void);
 void FlowSetIPOnlyFlag(Flow *, int);
 void FlowSetHasAlertsFlag(Flow *);
 int FlowHasAlerts(const Flow *);
+void FlowSetChangeProtoFlag(Flow *);
+void FlowUnsetChangeProtoFlag(Flow *);
+int FlowChangeProto(Flow *);
 
 void FlowRegisterTests (void);
 int FlowSetProtoTimeout(uint8_t ,uint32_t ,uint32_t ,uint32_t);