Prepare HTTP response body tracking.

remotes/origin/master-1.2.x
Victor Julien 14 years ago
parent 417495e542
commit 66a3cd96a8

@ -74,7 +74,7 @@
* \retval 0 ok * \retval 0 ok
* \retval -1 error * \retval -1 error
*/ */
int HtpBodyAppendChunk(SCHtpTxUserData *htud, HtpBody *body, uint8_t *data, uint32_t len) int HtpBodyAppendChunk(HtpTxUserData *htud, HtpBody *body, uint8_t *data, uint32_t len)
{ {
SCEnter(); SCEnter();
@ -204,15 +204,15 @@ void HtpBodyFree(HtpBody *body)
/** /**
* \brief Free request body chunks that are already fully parsed. * \brief Free request body chunks that are already fully parsed.
* *
* \param htud pointer to the SCHtpTxUserData holding the body * \param htud pointer to the HtpTxUserData holding the body
* *
* \retval none * \retval none
*/ */
void HtpBodyPrune(SCHtpTxUserData *htud) void HtpBodyPrune(HtpTxUserData *htud)
{ {
SCEnter(); SCEnter();
HtpBody *body = &htud->body; HtpBody *body = &htud->request_body;
if (body->nchunks == 0) { if (body->nchunks == 0) {
SCReturn; SCReturn;

@ -28,9 +28,9 @@
#ifndef __APP_LAYER_HTP_BODY_H__ #ifndef __APP_LAYER_HTP_BODY_H__
#define __APP_LAYER_HTP_BODY_H__ #define __APP_LAYER_HTP_BODY_H__
int HtpBodyAppendChunk(SCHtpTxUserData *, HtpBody *, uint8_t *, uint32_t); int HtpBodyAppendChunk(HtpTxUserData *, HtpBody *, uint8_t *, uint32_t);
void HtpBodyPrint(HtpBody *); void HtpBodyPrint(HtpBody *);
void HtpBodyFree(HtpBody *); void HtpBodyFree(HtpBody *);
void HtpBodyPrune(SCHtpTxUserData *); void HtpBodyPrune(HtpTxUserData *);
#endif /* __APP_LAYER_HTP_BODY_H__ */ #endif /* __APP_LAYER_HTP_BODY_H__ */

@ -217,9 +217,9 @@ void HTPStateFree(void *state)
for (i = 0; i < list_size(s->connp->conn->transactions); i++) { for (i = 0; i < list_size(s->connp->conn->transactions); i++) {
htp_tx_t *tx = (htp_tx_t *)list_get(s->connp->conn->transactions, i); htp_tx_t *tx = (htp_tx_t *)list_get(s->connp->conn->transactions, i);
if (tx != NULL) { if (tx != NULL) {
SCHtpTxUserData *htud = (SCHtpTxUserData *) htp_tx_get_user_data(tx); HtpTxUserData *htud = (HtpTxUserData *) htp_tx_get_user_data(tx);
if (htud != NULL) { if (htud != NULL) {
HtpBodyFree(&htud->body); HtpBodyFree(&htud->request_body);
SCFree(htud); SCFree(htud);
} }
htp_tx_set_user_data(tx, NULL); htp_tx_set_user_data(tx, NULL);
@ -817,7 +817,7 @@ static int HTTPParseContentTypeHeader(uint8_t *name, size_t name_len,
* If the request contains a multipart message, this function will * If the request contains a multipart message, this function will
* set the HTP_BOUNDARY_SET in the transaction. * set the HTP_BOUNDARY_SET in the transaction.
*/ */
static int HtpRequestBodySetupMultipart(htp_tx_data_t *d, SCHtpTxUserData *htud) { static int HtpRequestBodySetupMultipart(htp_tx_data_t *d, HtpTxUserData *htud) {
htp_header_t *cl = table_getc(d->tx->request_headers, "content-length"); htp_header_t *cl = table_getc(d->tx->request_headers, "content-length");
if (cl != NULL) if (cl != NULL)
htud->content_len = htp_parse_content_length(cl->value); htud->content_len = htp_parse_content_length(cl->value);
@ -858,7 +858,7 @@ static int HtpRequestBodySetupMultipart(htp_tx_data_t *d, SCHtpTxUserData *htud)
/** /**
* \brief Setup boundary buffers * \brief Setup boundary buffers
*/ */
static int HtpRequestBodySetupBoundary(SCHtpTxUserData *htud, static int HtpRequestBodySetupBoundary(HtpTxUserData *htud,
uint8_t **expected_boundary, uint8_t *expected_boundary_len, uint8_t **expected_boundary, uint8_t *expected_boundary_len,
uint8_t **expected_boundary_end, uint8_t *expected_boundary_end_len) uint8_t **expected_boundary_end, uint8_t *expected_boundary_end_len)
{ {
@ -979,12 +979,12 @@ static void HtpRequestBodyMultipartParseHeader(uint8_t *header, uint32_t header_
* \param chunks_buffers pointer to pass back the buffer to the caller * \param chunks_buffers pointer to pass back the buffer to the caller
* \param chunks_buffer_len pointer to pass back the buffer length to the caller * \param chunks_buffer_len pointer to pass back the buffer length to the caller
*/ */
static void HtpRequestBodyReassemble(SCHtpTxUserData *htud, static void HtpRequestBodyReassemble(HtpTxUserData *htud,
uint8_t **chunks_buffer, uint32_t *chunks_buffer_len) uint8_t **chunks_buffer, uint32_t *chunks_buffer_len)
{ {
uint8_t *buf = NULL; uint8_t *buf = NULL;
uint32_t buf_len = 0; uint32_t buf_len = 0;
HtpBodyChunk *cur = htud->body.first; HtpBodyChunk *cur = htud->request_body.first;
for ( ; cur != NULL; cur = cur->next) { for ( ; cur != NULL; cur = cur->next) {
/* skip body chunks entirely before what we parsed already */ /* skip body chunks entirely before what we parsed already */
@ -1018,7 +1018,7 @@ static void HtpRequestBodyReassemble(SCHtpTxUserData *htud,
*chunks_buffer_len = buf_len; *chunks_buffer_len = buf_len;
} }
int HtpRequestBodyHandleMultipart(HtpState *hstate, SCHtpTxUserData *htud, int HtpRequestBodyHandleMultipart(HtpState *hstate, HtpTxUserData *htud,
uint8_t *chunks_buffer, uint32_t chunks_buffer_len) uint8_t *chunks_buffer, uint32_t chunks_buffer_len)
{ {
int result = 0; int result = 0;
@ -1223,7 +1223,7 @@ end:
/** \brief setup things for put request /** \brief setup things for put request
* \todo really needed? */ * \todo really needed? */
int HtpRequestBodySetupPUT(htp_tx_data_t *d, SCHtpTxUserData *htud) { int HtpRequestBodySetupPUT(htp_tx_data_t *d, HtpTxUserData *htud) {
// if (d->tx->parsed_uri == NULL || d->tx->parsed_uri->path == NULL) { // if (d->tx->parsed_uri == NULL || d->tx->parsed_uri->path == NULL) {
// return -1; // return -1;
// } // }
@ -1233,7 +1233,7 @@ int HtpRequestBodySetupPUT(htp_tx_data_t *d, SCHtpTxUserData *htud) {
return 0; return 0;
} }
int HtpRequestBodyHandlePUT(HtpState *hstate, SCHtpTxUserData *htud, int HtpRequestBodyHandlePUT(HtpState *hstate, HtpTxUserData *htud,
htp_tx_t *tx, uint8_t *data, uint32_t data_len) htp_tx_t *tx, uint8_t *data, uint32_t data_len)
{ {
int result = 0; int result = 0;
@ -1298,22 +1298,22 @@ int HTPCallbackRequestBodyData(htp_tx_data_t *d)
SCLogDebug("New request body data available at %p -> %p -> %p, bodylen " SCLogDebug("New request body data available at %p -> %p -> %p, bodylen "
"%"PRIu32"", hstate, d, d->data, (uint32_t)d->len); "%"PRIu32"", hstate, d, d->data, (uint32_t)d->len);
SCHtpTxUserData *htud = (SCHtpTxUserData *) htp_tx_get_user_data(d->tx); HtpTxUserData *htud = (HtpTxUserData *) htp_tx_get_user_data(d->tx);
if (htud == NULL) { if (htud == NULL) {
htud = SCMalloc(sizeof(SCHtpTxUserData)); htud = SCMalloc(sizeof(HtpTxUserData));
if (htud == NULL) { if (htud == NULL) {
SCReturnInt(HOOK_OK); SCReturnInt(HOOK_OK);
} }
memset(htud, 0, sizeof(SCHtpTxUserData)); memset(htud, 0, sizeof(HtpTxUserData));
htud->body.operation = HTP_BODY_REQUEST; htud->request_body.operation = HTP_BODY_REQUEST;
if (d->tx->request_method_number == M_POST) { if (d->tx->request_method_number == M_POST) {
if (HtpRequestBodySetupMultipart(d, htud) == 0) { if (HtpRequestBodySetupMultipart(d, htud) == 0) {
htud->body.type = HTP_BODY_REQUEST_MULTIPART; htud->request_body.type = HTP_BODY_REQUEST_MULTIPART;
} }
} else if (d->tx->request_method_number == M_PUT) { } else if (d->tx->request_method_number == M_PUT) {
if (HtpRequestBodySetupPUT(d, htud) == 0) { if (HtpRequestBodySetupPUT(d, htud) == 0) {
htud->body.type = HTP_BODY_REQUEST_PUT; htud->request_body.type = HTP_BODY_REQUEST_PUT;
} }
} }
@ -1337,7 +1337,7 @@ int HTPCallbackRequestBodyData(htp_tx_data_t *d)
} }
SCLogDebug("len %u", len); SCLogDebug("len %u", len);
int r = HtpBodyAppendChunk(htud, &htud->body, (uint8_t *)d->data, len); int r = HtpBodyAppendChunk(htud, &htud->request_body, (uint8_t *)d->data, len);
if (r < 0) { if (r < 0) {
htud->flags |= HTP_BODY_COMPLETE; htud->flags |= HTP_BODY_COMPLETE;
} else if (hstate->request_body_limit > 0 && } else if (hstate->request_body_limit > 0 &&
@ -1351,7 +1351,7 @@ int HTPCallbackRequestBodyData(htp_tx_data_t *d)
uint8_t *chunks_buffer = NULL; uint8_t *chunks_buffer = NULL;
uint32_t chunks_buffer_len = 0; uint32_t chunks_buffer_len = 0;
if (htud->body.type == HTP_BODY_REQUEST_MULTIPART) { if (htud->request_body.type == HTP_BODY_REQUEST_MULTIPART) {
/* multi-part body handling starts here */ /* multi-part body handling starts here */
if (!(htud->flags & HTP_BOUNDARY_SET)) { if (!(htud->flags & HTP_BOUNDARY_SET)) {
goto end; goto end;
@ -1367,7 +1367,7 @@ int HTPCallbackRequestBodyData(htp_tx_data_t *d)
if (chunks_buffer != NULL) { if (chunks_buffer != NULL) {
SCFree(chunks_buffer); SCFree(chunks_buffer);
} }
} else if (htud->body.type == HTP_BODY_REQUEST_PUT) { } else if (htud->request_body.type == HTP_BODY_REQUEST_PUT) {
HtpRequestBodyHandlePUT(hstate, htud, d->tx, (uint8_t *)d->data, (uint32_t)d->len); HtpRequestBodyHandlePUT(hstate, htud, d->tx, (uint8_t *)d->data, (uint32_t)d->len);
} }
@ -1437,7 +1437,7 @@ static int HTPCallbackRequest(htp_connp_t *connp) {
SCLogDebug("HTTP request completed"); SCLogDebug("HTTP request completed");
if (connp->in_tx != NULL) { if (connp->in_tx != NULL) {
SCHtpTxUserData *htud = (SCHtpTxUserData *) htp_tx_get_user_data(connp->in_tx); HtpTxUserData *htud = (HtpTxUserData *) htp_tx_get_user_data(connp->in_tx);
if (htud != NULL) { if (htud != NULL) {
if (htud->flags & HTP_FILENAME_SET) { if (htud->flags & HTP_FILENAME_SET) {
SCLogDebug("closing file that was being stored"); SCLogDebug("closing file that was being stored");
@ -1478,9 +1478,9 @@ static int HTPCallbackResponse(htp_connp_t *connp) {
continue; continue;
/* This will remove obsolete body chunks */ /* This will remove obsolete body chunks */
SCHtpTxUserData *htud = (SCHtpTxUserData *) htp_tx_get_user_data(tx); HtpTxUserData *htud = (HtpTxUserData *) htp_tx_get_user_data(tx);
if (htud != NULL) { if (htud != NULL) {
HtpBodyFree(&htud->body); HtpBodyFree(&htud->request_body);
htp_tx_set_user_data(tx, NULL); htp_tx_set_user_data(tx, NULL);
SCFree(htud); SCFree(htud);
} }

@ -119,9 +119,10 @@ typedef struct HtpBody_ {
/** Now the Body Chunks will be stored per transaction, at /** Now the Body Chunks will be stored per transaction, at
* the tx user data */ * the tx user data */
typedef struct SCHtpTxUserData_ { typedef struct HtpTxUserData_ {
/* Body of the request (if any) */ /* Body of the request (if any) */
HtpBody body; HtpBody request_body;
//HtpBody response_body;
/* Holds the length of the htp request body */ /* Holds the length of the htp request body */
uint64_t content_len; uint64_t content_len;
@ -137,7 +138,7 @@ typedef struct SCHtpTxUserData_ {
uint8_t boundary_len; uint8_t boundary_len;
uint8_t flags; uint8_t flags;
} SCHtpTxUserData; } HtpTxUserData;
typedef struct HtpState_ { typedef struct HtpState_ {

@ -372,13 +372,13 @@ static void DetectEngineBufferHttpClientBodies(DetectEngineCtx *de_ctx,
if (tx == NULL) if (tx == NULL)
continue; continue;
SCHtpTxUserData *htud = (SCHtpTxUserData *)htp_tx_get_user_data(tx); HtpTxUserData *htud = (HtpTxUserData *)htp_tx_get_user_data(tx);
if (htud == NULL) if (htud == NULL)
continue; continue;
HtpBodyChunk *cur = htud->body.first; HtpBodyChunk *cur = htud->request_body.first;
if (htud->body.nchunks == 0) { if (htud->request_body.nchunks == 0) {
SCLogDebug("No http chunks to inspect for this transacation"); SCLogDebug("No http chunks to inspect for this transacation");
continue; continue;
} else { } else {
@ -389,7 +389,7 @@ static void DetectEngineBufferHttpClientBodies(DetectEngineCtx *de_ctx,
} }
/* this applies only for the client request body like the keyword name says */ /* this applies only for the client request body like the keyword name says */
if (htud->body.operation != HTP_BODY_REQUEST) { if (htud->request_body.operation != HTP_BODY_REQUEST) {
SCLogDebug("htp chunk not a request chunk"); SCLogDebug("htp chunk not a request chunk");
continue; continue;
} }

@ -1600,10 +1600,10 @@ static int DetectHttpClientBodyTest15(void) {
htp_tx_t *t1 = list_get(htp_state->connp->conn->transactions, 0); htp_tx_t *t1 = list_get(htp_state->connp->conn->transactions, 0);
htp_tx_t *t2 = list_get(htp_state->connp->conn->transactions, 1); htp_tx_t *t2 = list_get(htp_state->connp->conn->transactions, 1);
SCHtpTxUserData *htud = (SCHtpTxUserData *) htp_tx_get_user_data(t1); HtpTxUserData *htud = (HtpTxUserData *) htp_tx_get_user_data(t1);
HtpBodyChunk *cur = htud->body.first; HtpBodyChunk *cur = htud->request_body.first;
if (htud->body.nchunks == 0) { if (htud->request_body.nchunks == 0) {
SCLogDebug("No body data in t1 (it should be removed only when the tx is destroyed): "); SCLogDebug("No body data in t1 (it should be removed only when the tx is destroyed): ");
goto end; goto end;
} }
@ -1613,10 +1613,10 @@ static int DetectHttpClientBodyTest15(void) {
goto end; goto end;
} }
htud = (SCHtpTxUserData *) htp_tx_get_user_data(t2); htud = (HtpTxUserData *) htp_tx_get_user_data(t2);
cur = htud->body.first; cur = htud->request_body.first;
if (htud->body.nchunks == 0) { if (htud->request_body.nchunks == 0) {
SCLogDebug("No body data in t1 (it should be removed only when the tx is destroyed): "); SCLogDebug("No body data in t1 (it should be removed only when the tx is destroyed): ");
goto end; goto end;
} }

@ -2701,14 +2701,14 @@ static int DetectPcreTxBodyChunksTest01(void) {
htp_tx_t *t1 = list_get(htp_state->connp->conn->transactions, 0); htp_tx_t *t1 = list_get(htp_state->connp->conn->transactions, 0);
htp_tx_t *t2 = list_get(htp_state->connp->conn->transactions, 1); htp_tx_t *t2 = list_get(htp_state->connp->conn->transactions, 1);
SCHtpTxUserData *htud = (SCHtpTxUserData *) htp_tx_get_user_data(t1); HtpTxUserData *htud = (HtpTxUserData *) htp_tx_get_user_data(t1);
if (htud == NULL) { if (htud == NULL) {
printf("No body data in t1 (it should be removed only when the tx is destroyed): "); printf("No body data in t1 (it should be removed only when the tx is destroyed): ");
goto end; goto end;
} }
HtpBodyChunk *cur = htud->body.first; HtpBodyChunk *cur = htud->request_body.first;
if (htud->body.nchunks == 0) { if (htud->request_body.nchunks == 0) {
SCLogDebug("No body data in t1 (it should be removed only when the tx is destroyed): "); SCLogDebug("No body data in t1 (it should be removed only when the tx is destroyed): ");
goto end; goto end;
} }
@ -2718,10 +2718,10 @@ static int DetectPcreTxBodyChunksTest01(void) {
goto end; goto end;
} }
htud = (SCHtpTxUserData *) htp_tx_get_user_data(t2); htud = (HtpTxUserData *) htp_tx_get_user_data(t2);
cur = htud->body.first; cur = htud->request_body.first;
if (htud->body.nchunks == 0) { if (htud->request_body.nchunks == 0) {
SCLogDebug("No body data in t1 (it should be removed only when the tx is destroyed): "); SCLogDebug("No body data in t1 (it should be removed only when the tx is destroyed): ");
goto end; goto end;
} }
@ -2922,10 +2922,10 @@ static int DetectPcreTxBodyChunksTest02(void) {
htp_tx_t *t1 = list_get(htp_state->connp->conn->transactions, 0); htp_tx_t *t1 = list_get(htp_state->connp->conn->transactions, 0);
htp_tx_t *t2 = list_get(htp_state->connp->conn->transactions, 1); htp_tx_t *t2 = list_get(htp_state->connp->conn->transactions, 1);
SCHtpTxUserData *htud = (SCHtpTxUserData *) htp_tx_get_user_data(t1); HtpTxUserData *htud = (HtpTxUserData *) htp_tx_get_user_data(t1);
HtpBodyChunk *cur = htud->body.first; HtpBodyChunk *cur = htud->request_body.first;
if (htud->body.nchunks == 0) { if (htud->request_body.nchunks == 0) {
SCLogDebug("No body data in t1 (it should be removed only when the tx is destroyed): "); SCLogDebug("No body data in t1 (it should be removed only when the tx is destroyed): ");
goto end; goto end;
} }
@ -2935,10 +2935,10 @@ static int DetectPcreTxBodyChunksTest02(void) {
goto end; goto end;
} }
htud = (SCHtpTxUserData *) htp_tx_get_user_data(t2); htud = (HtpTxUserData *) htp_tx_get_user_data(t2);
cur = htud->body.first; cur = htud->request_body.first;
if (htud->body.nchunks == 0) { if (htud->request_body.nchunks == 0) {
SCLogDebug("No body data in t1 (it should be removed only when the tx is destroyed): "); SCLogDebug("No body data in t1 (it should be removed only when the tx is destroyed): ");
goto end; goto end;
} }

Loading…
Cancel
Save