http: logs content range

Fixes #2485
pull/3810/head
Philippe Antoine 6 years ago committed by Victor Julien
parent 43e205fc32
commit bef190f767

@ -150,6 +150,111 @@ end:
SCReturnInt(retval);
}
/**
* Performs parsing of the content-range value
*
* @param[in] rawvalue
* @param[out] range
*
* @return HTP_OK on success, HTP_ERROR on failure.
*/
int HTPParseContentRange(bstr * rawvalue, HtpContentRange *range)
{
unsigned char *data = bstr_ptr(rawvalue);
size_t len = bstr_len(rawvalue);
size_t pos = 0;
size_t last_pos;
// skip spaces and units
while (pos < len && data[pos] == ' ')
pos++;
while (pos < len && data[pos] != ' ')
pos++;
while (pos < len && data[pos] == ' ')
pos++;
// initialize to unseen
range->start = -1;
range->end = -1;
range->size = -1;
if (pos == len) {
// missing data
return -1;
}
if (data[pos] == '*') {
// case with size only
if (len < pos + 1 || data[pos+1] != '/') {
range->size = -1;
return -1;
}
pos += 2;
range->size = bstr_util_mem_to_pint(data + pos, len - pos, 10, &last_pos);
} else {
// case with start and end
range->start = bstr_util_mem_to_pint(data + pos, len - pos, 10, &last_pos);
pos += last_pos;
if (len < pos || data[pos] != '-') {
return -1;
}
pos++;
range->end = bstr_util_mem_to_pint(data + pos, len - pos, 10, &last_pos);
pos += last_pos;
if (len < pos || data[pos] != '/') {
return -1;
}
pos++;
if (data[pos] != '*') {
// case with size
range->size = bstr_util_mem_to_pint(data + pos, len - pos, 10, &last_pos);
}
}
return 0;
}
/**
* \brief Sets range for a file
*
* \param s http state
* \param rawvalue raw header value
*
* \retval 0 ok
* \retval -1 error
* \retval -2 error parsing
* \retval -3 error negative end in range
*/
int HTPFileSetRange(HtpState *s, bstr *rawvalue)
{
SCEnter();
if (s == NULL) {
SCReturnInt(-1);
}
FileContainer * files = s->files_tc;
if (files == NULL) {
SCLogDebug("no files in state");
SCReturnInt(-1);
}
HtpContentRange crparsed;
if (HTPParseContentRange(rawvalue, &crparsed) != 0) {
SCLogDebug("parsing range failed");
SCReturnInt(-2);
}
if (crparsed.end <= 0) {
SCLogDebug("negative end in range");
SCReturnInt(-3);
}
int retval = FileSetRange(files, crparsed.start, crparsed.end);
if (retval == -1) {
SCLogDebug("set range failed");
}
SCReturnInt(retval);
}
/**
* \brief Store a chunk of data in the flow
*

@ -25,7 +25,15 @@
#ifndef __APP_LAYER_HTP_FILE_H__
#define __APP_LAYER_HTP_FILE_H__
typedef struct HtpContentRange_ {
int64_t start;
int64_t end;
int64_t size;
} HtpContentRange;
int HTPFileOpen(HtpState *, const uint8_t *, uint16_t, const uint8_t *, uint32_t, uint64_t, uint8_t);
int HTPParseContentRange(bstr * rawvalue, HtpContentRange *range);
int HTPFileSetRange(HtpState *, bstr *rawvalue);
int HTPFileStoreChunk(HtpState *, const uint8_t *, uint32_t, uint8_t);
int HTPFileClose(HtpState *, const uint8_t *, uint32_t, uint8_t, uint8_t);

@ -1633,6 +1633,11 @@ static int HtpResponseBodyHandle(HtpState *hstate, HtpTxUserData *htud,
htud->tcflags |= HTP_FILENAME_SET;
htud->tcflags &= ~HTP_DONTSTORE;
}
//set range if present
htp_header_t *h_content_range = htp_table_get_c(tx->response_headers, "content-range");
if (h_content_range != NULL) {
HTPFileSetRange(hstate, h_content_range->value);
}
}
}
else

@ -217,6 +217,10 @@ json_t *JsonBuildFileInfoRecord(const Packet *p, const File *ff,
json_object_set_new(fjs, "file_id", json_integer(ff->file_store_id));
}
json_object_set_new(fjs, "size", json_integer(FileTrackedSize(ff)));
if (ff->end > 0) {
json_object_set_new(fjs, "start", json_integer(ff->start));
json_object_set_new(fjs, "end", json_integer(ff->end));
}
json_object_set_new(fjs, "tx_id", json_integer(ff->txid));
/* xff header */

@ -40,6 +40,7 @@
#include "output.h"
#include "app-layer-htp.h"
#include "app-layer-htp-file.h"
#include "app-layer-htp-xff.h"
#include "app-layer.h"
#include "app-layer-parser.h"
@ -261,6 +262,26 @@ static void JsonHttpLogJSONBasic(json_t *js, htp_tx_t *tx)
*p = '\0';
json_object_set_new(js, "http_content_type", SCJsonString(string));
}
htp_header_t *h_content_range = htp_table_get_c(tx->response_headers, "content-range");
if (h_content_range != NULL) {
const size_t size = bstr_len(h_content_range->value) * 2 + 1;
char string[size];
BytesToStringBuffer(bstr_ptr(h_content_range->value), bstr_len(h_content_range->value), string, size);
json_t *crjs = json_object();
if (crjs != NULL) {
json_object_set_new(crjs, "raw", SCJsonString(string));
HtpContentRange crparsed;
if (HTPParseContentRange(h_content_range->value, &crparsed) == 0) {
if (crparsed.start >= 0)
json_object_set_new(crjs, "start", json_integer(crparsed.start));
if (crparsed.end >= 0)
json_object_set_new(crjs, "end", json_integer(crparsed.end));
if (crparsed.size >= 0)
json_object_set_new(crjs, "size", json_integer(crparsed.size));
}
json_object_set_new(js, "content_range", crjs);
}
}
}
}

@ -738,6 +738,28 @@ int FileAppendGAPById(FileContainer *ffc, uint32_t track_id,
SCReturnInt(-1);
}
/**
* \brief Sets the offset range for a file.
*
* \param ffc the container
* \param start start offset
* \param end end offset
*
* \retval 0 ok
* \retval -1 error
*/
int FileSetRange(FileContainer *ffc, uint64_t start, uint64_t end)
{
SCEnter();
if (ffc == NULL || ffc->tail == NULL) {
SCReturnInt(-1);
}
ffc->tail->start = start;
ffc->tail->end = end;
SCReturnInt(0);
}
/**
* \brief Open a new File
*

@ -89,6 +89,8 @@ typedef struct File_ {
* flag is set */
uint64_t content_stored;
uint64_t size;
uint64_t start;
uint64_t end;
uint32_t *sid; /* signature id of a rule that triggered the filestore event */
uint32_t sid_cnt;
@ -169,6 +171,18 @@ int FileAppendDataById(FileContainer *, uint32_t track_id,
int FileAppendGAPById(FileContainer *ffc, uint32_t track_id,
const uint8_t *data, uint32_t data_len);
/**
* \brief Sets the offset range for a file.
*
* \param ffc the container
* \param start start offset
* \param end end offset
*
* \retval 0 ok
* \retval -1 error
*/
int FileSetRange(FileContainer *, uint64_t start, uint64_t end);
/**
* \brief Tag a file for storing
*

Loading…
Cancel
Save