Add support for extracting PUT files.

remotes/origin/master-1.2.x
Victor Julien 14 years ago
parent 59cda9a358
commit 403b2788d6

@ -1017,82 +1017,9 @@ static void HtpRequestBodyReassemble(SCHtpTxUserData *htud,
*chunks_buffer_len = buf_len;
}
/**
* \brief Function callback to append chunks for Requests
* \param d pointer to the htp_tx_data_t structure (a chunk from htp lib)
* \retval int HOOK_OK if all goes well
*/
int HTPCallbackRequestBodyData(htp_tx_data_t *d)
int HtpRequestBodyHandleMultipart(HtpState *hstate, SCHtpTxUserData *htud,
uint8_t *chunks_buffer, uint32_t chunks_buffer_len)
{
SCEnter();
uint8_t *expected_boundary = NULL;
uint8_t *expected_boundary_end = NULL;
uint8_t *chunks_buffer = NULL;
uint32_t chunks_buffer_len = 0;
HtpState *hstate = (HtpState *)d->tx->connp->user_data;
if (hstate == NULL) {
SCReturnInt(HOOK_ERROR);
}
SCLogDebug("New response body data available at %p -> %p -> %p, bodylen "
"%"PRIu32"", hstate, d, d->data, (uint32_t)d->len);
SCHtpTxUserData *htud = (SCHtpTxUserData *) htp_tx_get_user_data(d->tx);
if (htud == NULL) {
htud = SCMalloc(sizeof(SCHtpTxUserData));
if (htud == NULL) {
SCReturnInt(HOOK_OK);
}
memset(htud, 0, sizeof(SCHtpTxUserData));
htud->body.operation = HTP_BODY_NONE;
HtpRequestBodySetupMultipart(d, htud);
/* Set the user data for handling body chunks on this transaction */
htp_tx_set_user_data(d->tx, htud);
}
htud->body.operation = HTP_BODY_REQUEST;
SCLogDebug("htud->content_len_so_far %"PRIu64, htud->content_len_so_far);
SCLogDebug("hstate->request_body_limit %u", hstate->request_body_limit);
/* within limits, add the body chunk to the state. */
if (hstate->request_body_limit == 0 || htud->content_len_so_far < hstate->request_body_limit)
{
uint32_t len = (uint32_t)d->len;
if (hstate->request_body_limit > 0 &&
(htud->content_len_so_far + len) > hstate->request_body_limit)
{
len = hstate->request_body_limit - htud->content_len_so_far;
BUG_ON(len > (uint32_t)d->len);
}
SCLogDebug("len %u", len);
int r = HtpBodyAppendChunk(htud, &htud->body, (uint8_t *)d->data, len);
if (r < 0) {
htud->flags |= HTP_BODY_COMPLETE;
} else if (hstate->request_body_limit > 0 &&
htud->content_len_so_far >= hstate->request_body_limit)
{
htud->flags |= HTP_BODY_COMPLETE;
} else if (htud->content_len_so_far == htud->content_len) {
htud->flags |= HTP_BODY_COMPLETE;
}
/* multi-part body handling starts here */
if (!(htud->flags & HTP_BOUNDARY_SET)) {
goto end;
}
HtpRequestBodyReassemble(htud, &chunks_buffer, &chunks_buffer_len);
if (chunks_buffer == NULL) {
goto end;
}
#ifdef PRINT
printf("CHUNK START: \n");
PrintRawDataFp(stdout, chunks_buffer, chunks_buffer_len);
@ -1265,22 +1192,159 @@ int HTPCallbackRequestBodyData(htp_tx_data_t *d)
(uint8_t *) "\r\n\r\n", 4);
}
}
}
end:
/* see if we can get rid of htp body chunks */
HtpBodyPrune(htud);
if (expected_boundary != NULL) {
SCFree(expected_boundary);
}
if (expected_boundary_end != NULL) {
SCFree(expected_boundary_end);
}
return 0;
}
/** \brief setup things for put request
* \todo really needed? */
int HtpRequestBodySetupPUT(htp_tx_data_t *d, SCHtpTxUserData *htud) {
// if (d->tx->parsed_uri == NULL || d->tx->parsed_uri->path == NULL) {
// return -1;
// }
/* filename is d->tx->parsed_uri->path */
return 0;
}
int HtpRequestBodyHandlePUT(HtpState *hstate, SCHtpTxUserData *htud,
htp_tx_t *tx, uint8_t *data, uint32_t data_len)
{
/* 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);
}
if (HTPFileOpen(hstate->f, filename, filename_len,
data, data_len) == -1) {
goto end;
}
htud->flags |= HTP_FILENAME_SET;
}
else
{
/* otherwise, just store the data */
if (HTPFileStoreChunk(hstate->f, data, data_len) == -1) {
goto end;
}
}
return 0;
end:
return -1;
}
/**
* \brief Function callback to append chunks for Requests
* \param d pointer to the htp_tx_data_t structure (a chunk from htp lib)
* \retval int HOOK_OK if all goes well
*/
int HTPCallbackRequestBodyData(htp_tx_data_t *d)
{
SCEnter();
HtpState *hstate = (HtpState *)d->tx->connp->user_data;
if (hstate == NULL) {
SCReturnInt(HOOK_ERROR);
}
SCLogDebug("New response body data available at %p -> %p -> %p, bodylen "
"%"PRIu32"", hstate, d, d->data, (uint32_t)d->len);
SCHtpTxUserData *htud = (SCHtpTxUserData *) htp_tx_get_user_data(d->tx);
if (htud == NULL) {
htud = SCMalloc(sizeof(SCHtpTxUserData));
if (htud == NULL) {
SCReturnInt(HOOK_OK);
}
memset(htud, 0, sizeof(SCHtpTxUserData));
htud->body.operation = HTP_BODY_NONE;
if (d->tx->request_method_number == M_POST) {
if (HtpRequestBodySetupMultipart(d, htud) == 0) {
htud->body.operation = HTP_BODY_REQUEST_MULTIPART;
}
} else if (d->tx->request_method_number == M_PUT) {
if (HtpRequestBodySetupPUT(d, htud) == 0) {
htud->body.operation = HTP_BODY_REQUEST_PUT;
}
}
/* Set the user data for handling body chunks on this transaction */
htp_tx_set_user_data(d->tx, htud);
}
SCLogDebug("htud->content_len_so_far %"PRIu64, htud->content_len_so_far);
SCLogDebug("hstate->request_body_limit %u", hstate->request_body_limit);
/* within limits, add the body chunk to the state. */
if (hstate->request_body_limit == 0 || htud->content_len_so_far < hstate->request_body_limit)
{
uint32_t len = (uint32_t)d->len;
if (hstate->request_body_limit > 0 &&
(htud->content_len_so_far + len) > hstate->request_body_limit)
{
len = hstate->request_body_limit - htud->content_len_so_far;
BUG_ON(len > (uint32_t)d->len);
}
SCLogDebug("len %u", len);
int r = HtpBodyAppendChunk(htud, &htud->body, (uint8_t *)d->data, len);
if (r < 0) {
htud->flags |= HTP_BODY_COMPLETE;
} else if (hstate->request_body_limit > 0 &&
htud->content_len_so_far >= hstate->request_body_limit)
{
htud->flags |= HTP_BODY_COMPLETE;
} else if (htud->content_len_so_far == htud->content_len) {
htud->flags |= HTP_BODY_COMPLETE;
}
uint8_t *chunks_buffer = NULL;
uint32_t chunks_buffer_len = 0;
if (htud->body.operation == HTP_BODY_REQUEST_MULTIPART) {
/* multi-part body handling starts here */
if (!(htud->flags & HTP_BOUNDARY_SET)) {
goto end;
}
HtpRequestBodyReassemble(htud, &chunks_buffer, &chunks_buffer_len);
if (chunks_buffer == NULL) {
goto end;
}
HtpRequestBodyHandleMultipart(hstate, htud, chunks_buffer, chunks_buffer_len);
if (chunks_buffer != NULL) {
SCFree(chunks_buffer);
}
} else if (htud->body.operation == HTP_BODY_REQUEST_PUT) {
HtpRequestBodyHandlePUT(hstate, htud, d->tx, (uint8_t *)d->data, (uint32_t)d->len);
}
}
end:
/* see if we can get rid of htp body chunks */
HtpBodyPrune(htud);
/* set the new chunk flag */
hstate->flags |= HTP_FLAG_NEW_BODY_SET;
@ -1341,6 +1405,17 @@ static int HTPCallbackRequest(htp_connp_t *connp) {
SCLogDebug("HTTP request completed");
if (connp->in_tx != NULL) {
SCHtpTxUserData *htud = (SCHtpTxUserData *) htp_tx_get_user_data(connp->in_tx);
if (htud != NULL) {
if (htud->flags & HTP_FILENAME_SET) {
SCLogDebug("closing file that was being stored");
(void)HTPFileClose(hstate->f, NULL, 0, 0);
htud->flags &= ~HTP_FILENAME_SET;
}
}
}
SCReturnInt(HOOK_OK);
}

@ -60,6 +60,8 @@ enum {
operation */
HTP_BODY_REQUEST, /**< Flag to indicate that the
current operation is a request */
HTP_BODY_REQUEST_MULTIPART,
HTP_BODY_REQUEST_PUT,
HTP_BODY_RESPONSE /**< Flag to indicate that the current
* operation is a response */
};

Loading…
Cancel
Save