]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
http: per tx decoder events
authorVictor Julien <victor@inliniac.net>
Fri, 7 Feb 2014 10:02:41 +0000 (11:02 +0100)
committerVictor Julien <victor@inliniac.net>
Fri, 7 Feb 2014 11:46:56 +0000 (12:46 +0100)
Store HTTP decoder events per TX, so they can be inspected per TX.

Ticket: #839.

src/app-layer-htp-file.c
src/app-layer-htp.c
src/app-layer-htp.h

index 0d08b5fb4da4119c10d7b02a743defa14505419a..7c70689a580f423ac03e99c4856b87c22c61b048 100644 (file)
@@ -1190,7 +1190,7 @@ static int HTPFileParserTest08(void) {
     }
 
     SCMutexLock(&f->m);
-    AppLayerDecoderEvents *decoder_events = AppLayerParserGetDecoderEvents(f->alparser);
+    AppLayerDecoderEvents *decoder_events = AppLayerParserGetEventsByTx(IPPROTO_TCP, ALPROTO_HTTP,f->alstate, 0);
     if (decoder_events == NULL) {
         printf("no app events: ");
         SCMutexUnlock(&f->m);
@@ -1307,7 +1307,7 @@ static int HTPFileParserTest09(void) {
     }
 
     SCMutexLock(&f->m);
-    AppLayerDecoderEvents *decoder_events = AppLayerParserGetDecoderEvents(f->alparser);
+    AppLayerDecoderEvents *decoder_events = AppLayerParserGetEventsByTx(IPPROTO_TCP, ALPROTO_HTTP,f->alstate, 0);
     if (decoder_events == NULL) {
         printf("no app events: ");
         SCMutexUnlock(&f->m);
@@ -1422,7 +1422,7 @@ static int HTPFileParserTest10(void) {
     }
 
     SCMutexLock(&f->m);
-    AppLayerDecoderEvents *decoder_events = AppLayerParserGetDecoderEvents(f->alparser);
+    AppLayerDecoderEvents *decoder_events = AppLayerParserGetEventsByTx(IPPROTO_TCP, ALPROTO_HTTP,f->alstate, 0);
     if (decoder_events != NULL) {
         printf("app events: ");
         SCMutexUnlock(&f->m);
@@ -1555,7 +1555,7 @@ static int HTPFileParserTest11(void) {
     }
 
     SCMutexLock(&f->m);
-    AppLayerDecoderEvents *decoder_events = AppLayerParserGetDecoderEvents(f->alparser);
+    AppLayerDecoderEvents *decoder_events = AppLayerParserGetEventsByTx(IPPROTO_TCP, ALPROTO_HTTP,f->alstate, 0);
     if (decoder_events != NULL) {
         printf("app events: ");
         SCMutexUnlock(&f->m);
index ca64b31e495e380bc7bb8b066b4f9dfe0f333947..dfb02047d2f846ce664b2ea1b45ebfa0fbe7073f 100644 (file)
@@ -229,6 +229,49 @@ static int HTPLookupPersonality(const char *str)
     return -1;
 }
 
+void HTPSetEvent(HtpState *s, HtpTxUserData *htud, uint8_t e)
+{
+    SCLogDebug("setting event %u", e);
+
+    if (htud) {
+        AppLayerDecoderEventsSetEventRaw(&htud->decoder_events, e);
+        s->events++;
+        return;
+    }
+
+    htp_tx_t *tx = HTPStateGetTx(s, s->transaction_cnt);
+    if (tx != NULL) {
+        htud = (HtpTxUserData *) htp_tx_get_user_data(tx);
+        if (htud != NULL) {
+            AppLayerDecoderEventsSetEventRaw(&htud->decoder_events, e);
+            s->events++;
+            return;
+        }
+    }
+    SCLogDebug("couldn't set event %u", e);
+}
+
+static int HTPHasEvents(void *state) {
+    HtpState *htp_state = (HtpState *)state;
+    return (htp_state->events > 0);
+}
+
+static AppLayerDecoderEvents *HTPGetEvents(void *state, uint64_t tx_id)
+{
+    SCLogDebug("get HTTP events for TX %"PRIu64, tx_id);
+
+    HtpState *s = (HtpState *)state;
+    htp_tx_t *tx = HTPStateGetTx(s, tx_id);
+    if (tx != NULL) {
+        HtpTxUserData *htud = (HtpTxUserData *) htp_tx_get_user_data(tx);
+        if (htud != NULL) {
+            SCLogDebug("has htud, htud->decoder_events %p", htud->decoder_events);
+            return htud->decoder_events;
+        }
+    }
+    return NULL;
+}
+
 /** \brief Function to allocates the HTTP state memory and also creates the HTTP
  *         connection parser to be used by the HTP library
  */
@@ -269,6 +312,7 @@ static void HtpTxUserDataFree(HtpTxUserData *htud) {
             HTPFree(htud->request_headers_raw, htud->request_headers_raw_len);
         if (htud->response_headers_raw)
             HTPFree(htud->response_headers_raw, htud->response_headers_raw_len);
+        AppLayerDecoderEventsFreeEvents(&htud->decoder_events);
         if (htud->boundary)
             HTPFree(htud->boundary, htud->boundary_len);
         HTPFree(htud, sizeof(HtpTxUserData));
@@ -517,56 +561,31 @@ static void HTPHandleError(HtpState *s) {
     size_t size = htp_list_size(s->conn->messages);
     size_t msg;
 
-    for (msg = 0; msg < size; msg++) {
+    for (msg = s->htp_messages_offset; msg < size; msg++) {
         htp_log_t *log = htp_list_get(s->conn->messages, msg);
         if (log == NULL)
             continue;
 
+        HtpTxUserData *htud = NULL;
+        htp_tx_t *tx = log->tx; // will be NULL in <=0.5.9
+        if (tx != NULL)
+            htud = (HtpTxUserData *) htp_tx_get_user_data(tx);
+
         SCLogDebug("message %s", log->msg);
 
         int id = HTPHandleErrorGetId(log->msg);
-        if (id > 0) {
-            AppLayerDecoderEventsSetEvent(s->f, id);
-        } else {
+        if (id == 0) {
             id = HTPHandleWarningGetId(log->msg);
-            if (id > 0) {
-                AppLayerDecoderEventsSetEvent(s->f, id);
-            } else {
-                AppLayerDecoderEventsSetEvent(s->f,
-                        HTTP_DECODER_EVENT_UNKNOWN_ERROR);
-            }
+            if (id == 0)
+                id = HTTP_DECODER_EVENT_UNKNOWN_ERROR;
         }
-    }
-}
-
-/**
- *  \internal
- *
- *  \brief Check state for warnings and add any as events
- *
- *  \param s state
- */
-static void HTPHandleWarning(HtpState *s) {
-    if (s == NULL || s->conn == NULL ||
-        s->conn->messages == NULL) {
-        return;
-    }
-
-    size_t size = htp_list_size(s->conn->messages);
-    size_t msg;
-
-    for (msg = 0; msg < size; msg++) {
-        htp_log_t *log = htp_list_get(s->conn->messages, msg);
-        if (log == NULL)
-            continue;
 
-        int id = HTPHandleWarningGetId(log->msg);
         if (id > 0) {
-            AppLayerDecoderEventsSetEvent(s->f, id);
-        } else {
-            AppLayerDecoderEventsSetEvent(s->f, HTTP_DECODER_EVENT_UNKNOWN_ERROR);
+            HTPSetEvent(s, htud, id);
         }
     }
+    s->htp_messages_offset = (uint16_t)msg;
+    SCLogDebug("s->htp_messages_offset %u", s->htp_messages_offset);
 }
 
 static inline void HTPErrorCheckTxRequestFlags(HtpState *s, htp_tx_t *tx)
@@ -578,23 +597,27 @@ static inline void HTPErrorCheckTxRequestFlags(HtpState *s, htp_tx_t *tx)
                         HTP_HOST_MISSING|HTP_HOST_AMBIGUOUS|HTP_HOSTU_INVALID|
                         HTP_HOSTH_INVALID))
     {
+        HtpTxUserData *htud = (HtpTxUserData *) htp_tx_get_user_data(tx);
+        if (htud == NULL)
+            return;
+
         if (tx->flags & HTP_REQUEST_INVALID_T_E)
-            AppLayerDecoderEventsSetEvent(s->f,
+            HTPSetEvent(s, htud,
                     HTTP_DECODER_EVENT_INVALID_TRANSFER_ENCODING_VALUE_IN_REQUEST);
         if (tx->flags & HTP_REQUEST_INVALID_C_L)
-            AppLayerDecoderEventsSetEvent(s->f,
+            HTPSetEvent(s, htud,
                     HTTP_DECODER_EVENT_INVALID_CONTENT_LENGTH_FIELD_IN_REQUEST);
         if (tx->flags & HTP_HOST_MISSING)
-            AppLayerDecoderEventsSetEvent(s->f,
+            HTPSetEvent(s, htud,
                     HTTP_DECODER_EVENT_MISSING_HOST_HEADER);
         if (tx->flags & HTP_HOST_AMBIGUOUS)
-            AppLayerDecoderEventsSetEvent(s->f,
+            HTPSetEvent(s, htud,
                     HTTP_DECODER_EVENT_HOST_HEADER_AMBIGUOUS);
         if (tx->flags & HTP_HOSTU_INVALID)
-            AppLayerDecoderEventsSetEvent(s->f,
+            HTPSetEvent(s, htud,
                     HTTP_DECODER_EVENT_URI_HOST_INVALID);
         if (tx->flags & HTP_HOSTH_INVALID)
-            AppLayerDecoderEventsSetEvent(s->f,
+            HTPSetEvent(s, htud,
                     HTTP_DECODER_EVENT_HEADER_HOST_INVALID);
     }
 }
@@ -775,8 +798,6 @@ static int HTPHandleResponseData(Flow *f, void *htp_state,
     r = htp_connp_res_data(hstate->connp, &ts, input, input_len);
     switch(r) {
         case HTP_STREAM_ERROR:
-            HTPHandleError(hstate);
-
             hstate->flags = HTP_FLAG_STATE_ERROR;
             hstate->flags &= ~HTP_FLAG_STATE_DATA;
             hstate->flags &= ~HTP_FLAG_NEW_BODY_SET;
@@ -784,16 +805,15 @@ static int HTPHandleResponseData(Flow *f, void *htp_state,
             break;
         case HTP_STREAM_DATA:
         case HTP_STREAM_DATA_OTHER:
-            HTPHandleWarning(hstate);
             hstate->flags |= HTP_FLAG_STATE_DATA;
             break;
         case HTP_STREAM_TUNNEL:
             break;
         default:
-            HTPHandleWarning(hstate);
             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) &&
@@ -1078,6 +1098,7 @@ error:
 #define C_T_HDR_LEN 13
 
 static void HtpRequestBodyMultipartParseHeader(HtpState *hstate,
+        HtpTxUserData *htud,
         uint8_t *header, uint32_t header_len,
         uint8_t **filename, uint16_t *filename_len,
         uint8_t **filetype, uint16_t *filetype_len)
@@ -1105,12 +1126,12 @@ static void HtpRequestBodyMultipartParseHeader(HtpState *hstate,
         }
         uint8_t *sc = (uint8_t *)memchr(line, ':', line_len);
         if (sc == NULL) {
-            AppLayerDecoderEventsSetEvent(hstate->f,
+            HTPSetEvent(hstate, htud,
                     HTTP_DECODER_EVENT_MULTIPART_INVALID_HEADER);
             /* if the : we found is the final char, it means we have
              * no value */
         } else if (line_len > 0 && sc == &line[line_len - 1]) {
-            AppLayerDecoderEventsSetEvent(hstate->f,
+            HTPSetEvent(hstate, htud,
                     HTTP_DECODER_EVENT_MULTIPART_INVALID_HEADER);
         } else {
 #ifdef PRINT
@@ -1279,7 +1300,7 @@ int HtpRequestBodyHandleMultipart(HtpState *hstate, HtpTxUserData *htud,
             }
 
             if (filedata_len > chunks_buffer_len) {
-                AppLayerDecoderEventsSetEvent(hstate->f,
+                HTPSetEvent(hstate, htud,
                         HTTP_DECODER_EVENT_MULTIPART_GENERIC_ERROR);
                 goto end;
             }
@@ -1354,7 +1375,7 @@ int HtpRequestBodyHandleMultipart(HtpState *hstate, HtpTxUserData *htud,
             header = header_start + (expected_boundary_len + 2); // + for 0d 0a
         }
 
-        HtpRequestBodyMultipartParseHeader(hstate, header, header_len,
+        HtpRequestBodyMultipartParseHeader(hstate, htud, header, header_len,
                 &filename, &filename_len, &filetype, &filetype_len);
 
         if (filename != NULL) {
@@ -1373,11 +1394,11 @@ int HtpRequestBodyHandleMultipart(HtpState *hstate, HtpTxUserData *htud,
             if (form_end != NULL) {
                 filedata = header_end + 4;
                 if (form_end == filedata) {
-                    AppLayerDecoderEventsSetEvent(hstate->f,
+                    HTPSetEvent(hstate, htud,
                             HTTP_DECODER_EVENT_MULTIPART_NO_FILEDATA);
                     goto end;
                 } else if (form_end < filedata) {
-                    AppLayerDecoderEventsSetEvent(hstate->f,
+                    HTPSetEvent(hstate, htud,
                             HTTP_DECODER_EVENT_MULTIPART_GENERIC_ERROR);
                     goto end;
                 }
@@ -1393,7 +1414,7 @@ int HtpRequestBodyHandleMultipart(HtpState *hstate, HtpTxUserData *htud,
                 }
 
                 if (filedata_len > chunks_buffer_len) {
-                    AppLayerDecoderEventsSetEvent(hstate->f,
+                    HTPSetEvent(hstate, htud,
                             HTTP_DECODER_EVENT_MULTIPART_GENERIC_ERROR);
                     goto end;
                 }
@@ -1427,7 +1448,7 @@ int HtpRequestBodyHandleMultipart(HtpState *hstate, HtpTxUserData *htud,
                 SCLogDebug("filedata_len %u (chunks_buffer_len %u)", filedata_len, chunks_buffer_len);
 
                 if (filedata_len > chunks_buffer_len) {
-                    AppLayerDecoderEventsSetEvent(hstate->f,
+                    HTPSetEvent(hstate, htud,
                             HTTP_DECODER_EVENT_MULTIPART_GENERIC_ERROR);
                     goto end;
                 }
@@ -2569,7 +2590,7 @@ int HTPStateGetEventInfo(const char *event_name,
         return -1;
     }
 
-    *event_type = APP_LAYER_EVENT_TYPE_GENERAL;
+    *event_type = APP_LAYER_EVENT_TYPE_TRANSACTION;
 
     return 0;
 }
@@ -2706,7 +2727,8 @@ void RegisterHTPParsers(void)
         AppLayerParserRegisterGetTx(IPPROTO_TCP, ALPROTO_HTTP, HTPStateGetTx);
         AppLayerParserRegisterGetStateProgressCompletionStatus(IPPROTO_TCP, ALPROTO_HTTP,
                                                                HTPStateGetAlstateProgressCompletionStatus);
-
+        AppLayerParserRegisterHasEventsFunc(IPPROTO_TCP, ALPROTO_HTTP, HTPHasEvents);
+        AppLayerParserRegisterGetEventsFunc(IPPROTO_TCP, ALPROTO_HTTP, HTPGetEvents);
         AppLayerParserRegisterGetEventInfo(IPPROTO_TCP, ALPROTO_HTTP, HTPStateGetEventInfo);
 
         AppLayerParserRegisterTruncateFunc(IPPROTO_TCP, ALPROTO_HTTP, HTPStateTruncate);
@@ -5765,7 +5787,7 @@ libhtp:\n\
     }
 
     SCMutexLock(&f->m);
-    AppLayerDecoderEvents *decoder_events = AppLayerParserGetDecoderEvents(f->alparser);
+    AppLayerDecoderEvents *decoder_events = AppLayerParserGetEventsByTx(IPPROTO_TCP, ALPROTO_HTTP,f->alstate, 0);
     if (decoder_events == NULL) {
         printf("no app events: ");
         SCMutexUnlock(&f->m);
@@ -5894,7 +5916,7 @@ libhtp:\n\
     }
 
     SCMutexLock(&f->m);
-    AppLayerDecoderEvents *decoder_events = AppLayerParserGetDecoderEvents(f->alparser);
+    AppLayerDecoderEvents *decoder_events = AppLayerParserGetEventsByTx(IPPROTO_TCP, ALPROTO_HTTP,f->alstate, 0);
     if (decoder_events != NULL) {
         printf("app events: ");
         SCMutexUnlock(&f->m);
index 864ecaedc0c34d49e5e2e2f3b9507c123088bebf..d71d4edeab508830a9fbd46d6a33423c358fe6a8 100644 (file)
@@ -211,6 +211,8 @@ typedef struct HtpTxUserData_ {
     uint32_t request_headers_raw_len;
     uint32_t response_headers_raw_len;
 
+    AppLayerDecoderEvents *decoder_events;          /**< per tx events */
+
     /** Holds the boundary identificator string if any (used on
      *  multipart/form-data only)
      */
@@ -240,6 +242,8 @@ typedef struct HtpState_ {
     FileContainer *files_tc;
     struct HTPCfgRec_ *cfg;
     uint16_t flags;
+    uint16_t events;
+    uint16_t htp_messages_offset; /**< offset into conn->messages list */
 } HtpState;
 
 /** part of the engine needs the request body (e.g. http_client_body keyword) */