]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
file-inspection: support POST requests that do not use multipart.
authorVictor Julien <victor@inliniac.net>
Wed, 22 Feb 2012 16:55:24 +0000 (17:55 +0100)
committerVictor Julien <victor@inliniac.net>
Wed, 22 Feb 2012 16:55:24 +0000 (17:55 +0100)
src/app-layer-htp-file.c
src/app-layer-htp.c
src/app-layer-htp.h

index 89ce9df1085d662078995d3dc8c488711a5ba431..c50ba19429db8dc607fdaf0ac0d819582dff441f 100644 (file)
@@ -924,6 +924,92 @@ end:
     return result;
 }
 
+/** \test POST, but not multipart */
+static int HTPFileParserTest07(void) {
+    int result = 0;
+    Flow *f = NULL;
+    uint8_t httpbuf1[] = "POST /filename HTTP/1.1\r\n"
+                         "Host: www.server.lan\r\n"
+                         "Content-Length: 11\r\n"
+                         "\r\n";
+    uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
+    uint8_t httpbuf2[] = "FILECONTENT";
+    uint32_t httplen2 = sizeof(httpbuf2) - 1; /* minus the \0 */
+
+    TcpSession ssn;
+    HtpState *http_state = NULL;
+
+    memset(&ssn, 0, sizeof(ssn));
+
+    f = UTHBuildFlow(AF_INET, "1.2.3.4", "1.2.3.5", 1024, 80);
+    if (f == NULL)
+        goto end;
+    f->protoctx = &ssn;
+
+    StreamTcpInitConfig(TRUE);
+
+    SCLogDebug("\n>>>> processing chunk 1 size %u <<<<\n", httplen1);
+    int r = AppLayerParse(NULL, f, ALPROTO_HTTP, STREAM_TOSERVER|STREAM_START, httpbuf1, httplen1);
+    if (r != 0) {
+        printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
+        result = 0;
+        goto end;
+    }
+
+    SCLogDebug("\n>>>> processing chunk 2 size %u <<<<\n", httplen2);
+    r = AppLayerParse(NULL, f, ALPROTO_HTTP, STREAM_TOSERVER|STREAM_EOF, httpbuf2, httplen2);
+    if (r != 0) {
+        printf("toserver chunk 2 returned %" PRId32 ", expected 0: ", r);
+        result = 0;
+        goto end;
+    }
+
+    http_state = f->alstate;
+    if (http_state == NULL) {
+        printf("no http state: ");
+        result = 0;
+        goto end;
+    }
+
+    htp_tx_t *tx = list_get(http_state->connp->conn->transactions, 0);
+    if (tx == NULL) {
+        goto end;
+    }
+
+    if (tx->request_method == NULL || memcmp(bstr_tocstr(tx->request_method), "POST", 4) != 0)
+    {
+        printf("expected method POST, got %s \n", bstr_tocstr(tx->request_method));
+        goto end;
+    }
+
+    if (http_state->files_ts == NULL || http_state->files_ts->tail == NULL ||
+            http_state->files_ts->tail->state != FILE_STATE_CLOSED) {
+        printf("state != FILE_STATE_CLOSED");
+        goto end;
+    }
+
+    if (http_state->files_ts->head->chunks_head->len != 11) {
+        printf("expected 11 but file is %u bytes instead: ",
+                http_state->files_ts->head->chunks_head->len);
+        PrintRawDataFp(stdout, http_state->files_ts->head->chunks_head->data,
+                http_state->files_ts->head->chunks_head->len);
+        goto end;
+    }
+
+    if (memcmp("FILECONTENT", http_state->files_ts->head->chunks_head->data,
+                http_state->files_ts->head->chunks_head->len) != 0) {
+        goto end;
+    }
+
+    result = 1;
+end:
+    StreamTcpFreeConfig(TRUE);
+    if (http_state != NULL)
+        HTPStateFree(http_state);
+    UTHFreeFlow(f);
+    return result;
+}
+
 #endif /* UNITTESTS */
 
 void HTPFileParserRegisterTests(void) {
@@ -934,5 +1020,6 @@ void HTPFileParserRegisterTests(void) {
     UtRegisterTest("HTPFileParserTest04", HTPFileParserTest04, 1);
     UtRegisterTest("HTPFileParserTest05", HTPFileParserTest05, 1);
     UtRegisterTest("HTPFileParserTest06", HTPFileParserTest06, 1);
+    UtRegisterTest("HTPFileParserTest07", HTPFileParserTest07, 1);
 #endif /* UNITTESTS */
 }
index 304dcad6f1c62540c834d4733dbbb9c118c76b60..5fa02318446abc874d49e0551f7e8ab2da620373 100644 (file)
@@ -1004,7 +1004,8 @@ static int HTTPParseContentTypeHeader(uint8_t *name, size_t name_len,
  *  \param d HTTP transaction
  *  \param htud transaction userdata
  *
- *  \retval 0 ok
+ *  \retval 1 ok, multipart set up
+ *  \retval 0 ok, not multipart though
  *  \retval -1 error: problem with the boundary
  *
  *  If the request contains a multipart message, this function will
@@ -1044,8 +1045,9 @@ static int HtpRequestBodySetupMultipart(htp_tx_data_t *d, HtpTxUserData *htud) {
                 return -1;
             }
         }
+        SCReturnInt(1);
     }
-    return 0;
+    SCReturnInt(0);
 }
 
 /**
@@ -1490,7 +1492,61 @@ int HtpRequestBodySetupPUT(htp_tx_data_t *d, HtpTxUserData *htud) {
     return 0;
 }
 
-int HtpRequestBodyHandlePUT(HtpState *hstate, HtpTxUserData *htud,
+/** \internal
+ *  \brief Handle POST, no multipart body data
+ */
+static int HtpRequestBodyHandlePOST(HtpState *hstate, HtpTxUserData *htud,
+        htp_tx_t *tx, uint8_t *data, uint32_t data_len)
+{
+    int result = 0;
+
+    /* see if we need to open the file */
+    if (!(htud->flags & HTP_FILENAME_SET))
+    {
+        uint8_t *filename = NULL;
+        uint32_t filename_len = 0;
+
+        /* get the name */
+        if (tx->parsed_uri != NULL && tx->parsed_uri->path != NULL) {
+            filename = (uint8_t *)bstr_ptr(tx->parsed_uri->path);
+            filename_len = bstr_len(tx->parsed_uri->path);
+        }
+
+        result = HTPFileOpen(hstate, filename, filename_len, data, data_len,
+                hstate->transaction_cnt, STREAM_TOSERVER);
+        if (result == -1) {
+            goto end;
+        } else if (result == -2) {
+            htud->flags |= HTP_DONTSTORE;
+        } else {
+            htud->flags |= HTP_FILENAME_SET;
+            htud->flags &= ~HTP_DONTSTORE;
+        }
+    }
+    else
+    {
+        /* otherwise, just store the data */
+
+        if (!(htud->flags & HTP_DONTSTORE)) {
+            result = HTPFileStoreChunk(hstate, data, data_len, STREAM_TOSERVER);
+            if (result == -1) {
+                goto end;
+            } else if (result == -2) {
+                /* we know for sure we're not storing the file */
+                htud->flags |= HTP_DONTSTORE;
+            }
+        }
+    }
+
+    return 0;
+end:
+    return -1;
+}
+
+/** \internal
+ *  \brief Handle PUT body data
+ */
+static int HtpRequestBodyHandlePUT(HtpState *hstate, HtpTxUserData *htud,
         htp_tx_t *tx, uint8_t *data, uint32_t data_len)
 {
     int result = 0;
@@ -1637,8 +1693,13 @@ int HTPCallbackRequestBodyData(htp_tx_data_t *d)
         htud->operation = HTP_BODY_REQUEST;
 
         if (d->tx->request_method_number == M_POST) {
-            if (HtpRequestBodySetupMultipart(d, htud) == 0) {
+            SCLogDebug("POST");
+            int r = HtpRequestBodySetupMultipart(d, htud);
+            if (r == 1) {
                 htud->request_body.type = HTP_BODY_REQUEST_MULTIPART;
+            } else if (r == 0) {
+                htud->request_body.type = HTP_BODY_REQUEST_POST;
+                SCLogDebug("not multipart");
             }
         } else if (d->tx->request_method_number == M_PUT) {
             if (HtpRequestBodySetupPUT(d, htud) == 0) {
@@ -1691,9 +1752,9 @@ int HTPCallbackRequestBodyData(htp_tx_data_t *d)
                 goto end;
             }
 #ifdef PRINT
-    printf("REASSCHUNK START: \n");
-    PrintRawDataFp(stdout, chunks_buffer, chunks_buffer_len);
-    printf("REASSCHUNK END: \n");
+            printf("REASSCHUNK START: \n");
+            PrintRawDataFp(stdout, chunks_buffer, chunks_buffer_len);
+            printf("REASSCHUNK END: \n");
 #endif
 
             HtpRequestBodyHandleMultipart(hstate, htud, chunks_buffer, chunks_buffer_len);
@@ -1701,6 +1762,8 @@ int HTPCallbackRequestBodyData(htp_tx_data_t *d)
             if (chunks_buffer != NULL) {
                 SCFree(chunks_buffer);
             }
+        } else if (htud->request_body.type == HTP_BODY_REQUEST_POST) {
+            HtpRequestBodyHandlePOST(hstate, htud, d->tx, (uint8_t *)d->data, (uint32_t)d->len);
         } else if (htud->request_body.type == HTP_BODY_REQUEST_PUT) {
             HtpRequestBodyHandlePUT(hstate, htud, d->tx, (uint8_t *)d->data, (uint32_t)d->len);
         }
index 9f7505a6ac5ba102b794ed3e29e6a71348dd8b66..ac27f9034df648b0e945d37f188a6b8074ba6490 100644 (file)
@@ -77,7 +77,8 @@ enum {
 
 enum {
     HTP_BODY_REQUEST_NONE = 0,
-    HTP_BODY_REQUEST_MULTIPART,
+    HTP_BODY_REQUEST_MULTIPART, /* POST, MP */
+    HTP_BODY_REQUEST_POST,      /* POST, no MP */
     HTP_BODY_REQUEST_PUT,
 };