http/multipart: process incomplete file data

Start processing multipart data as soon as it is available to
allow inspection sooner.
pull/4431/head
Victor Julien 6 years ago
parent fcfb679893
commit 54d93e1eb9

@ -1311,14 +1311,16 @@ static int HtpRequestBodyHandleMultipart(HtpState *hstate, HtpTxUserData *htud,
HtpRequestBodySetupBoundary(htud, boundary, htud->boundary_len + 4);
/* search for the header start, header end and form end */
uint8_t *header_start = Bs2bmSearch(chunks_buffer, chunks_buffer_len,
const uint8_t *header_start = Bs2bmSearch(chunks_buffer, chunks_buffer_len,
boundary, expected_boundary_len);
/* end marker belonging to header_start */
uint8_t *header_end = NULL;
if (header_start != NULL) {
header_end = Bs2bmSearch(header_start, chunks_buffer_len - (header_start - chunks_buffer),
(uint8_t *)"\r\n\r\n", 4);
}
uint8_t *form_end = Bs2bmSearch(chunks_buffer, chunks_buffer_len,
/* end of the multipart form */
const uint8_t *form_end = Bs2bmSearch(chunks_buffer, chunks_buffer_len,
boundary, expected_boundary_end_len);
SCLogDebug("header_start %p, header_end %p, form_end %p", header_start,
@ -1329,20 +1331,27 @@ static int HtpRequestBodyHandleMultipart(HtpState *hstate, HtpTxUserData *htud,
tx_progress = AppLayerParserGetStateProgress(IPPROTO_TCP, ALPROTO_HTTP, tx, STREAM_TOSERVER);
/* if we're in the file storage process, deal with that now */
if (htud->tsflags & HTP_FILENAME_SET) {
if (header_start != NULL || form_end != NULL || (tx_progress > HTP_REQUEST_BODY)) {
if (header_start != NULL || (tx_progress > HTP_REQUEST_BODY)) {
SCLogDebug("reached the end of the file");
const uint8_t *filedata = chunks_buffer;
uint32_t filedata_len = 0;
uint8_t flags = 0;
if (header_start < form_end || (header_start != NULL && form_end == NULL)) {
filedata_len = header_start - filedata - 2; /* 0d 0a */
} else if (form_end != NULL && form_end < header_start) {
filedata_len = form_end - filedata;
} else if (form_end != NULL && form_end == header_start) {
filedata_len = form_end - filedata - 2; /* 0d 0a */
} else if (tx_progress > HTP_REQUEST_BODY) {
if (header_start != NULL) {
if (header_start == filedata + 2) {
/* last chunk had all data, but not the boundary */
SCLogDebug("last chunk had all data, but not the boundary");
filedata_len = 0;
} else if (header_start > filedata + 2) {
SCLogDebug("some data from last file before the boundary");
/* some data from last file before the boundary */
filedata_len = header_start - filedata - 2;
}
}
/* body parsing done, we did not get our form end. Use all data
* we still have and signal to files API we have an issue. */
if (tx_progress > HTP_REQUEST_BODY) {
filedata_len = chunks_buffer_len;
flags = FILE_TRUNCATED;
}
@ -1413,14 +1422,14 @@ static int HtpRequestBodyHandleMultipart(HtpState *hstate, HtpTxUserData *htud,
uint32_t header_len = header_end - header_start;
SCLogDebug("header_len %u", header_len);
uint8_t *header = header_start;
uint8_t *header = (uint8_t *)header_start;
/* skip empty records */
if (expected_boundary_len == header_len) {
goto next;
} else if ((uint32_t)(expected_boundary_len + 2) <= header_len) {
header_len -= (expected_boundary_len + 2);
header = header_start + (expected_boundary_len + 2); // + for 0d 0a
header = (uint8_t *)header_start + (expected_boundary_len + 2); // + for 0d 0a
}
HtpRequestBodyMultipartParseHeader(hstate, htud, header, header_len,
@ -1440,6 +1449,8 @@ static int HtpRequestBodyHandleMultipart(HtpState *hstate, HtpTxUserData *htud,
/* everything until the final boundary is the file */
if (form_end != NULL) {
SCLogDebug("have form_end");
filedata = header_end + 4;
if (form_end == filedata) {
HTPSetEvent(hstate, htud, STREAM_TOSERVER,
@ -1507,23 +1518,27 @@ static int HtpRequestBodyHandleMultipart(HtpState *hstate, HtpTxUserData *htud,
PrintRawDataFp(stdout, filedata, filedata_len);
printf("FILEDATA END: \n");
#endif
/* form doesn't end in this chunk, but part might. Lets
/* form doesn't end in this chunk, but the part might. Lets
* see if have another coming up */
uint8_t *header_next = Bs2bmSearch(filedata, filedata_len,
boundary, expected_boundary_len);
SCLogDebug("header_next %p", header_next);
if (header_next == NULL) {
/* no, but we'll handle the file data when we see the
* form_end */
SCLogDebug("more file data to come");
uint32_t offset = (header_end + 4) - chunks_buffer;
SCLogDebug("offset %u", offset);
htud->request_body.body_parsed += offset;
if (filedata_len >= (uint32_t)(expected_boundary_len + 2)) {
filedata_len -= (uint32_t)(expected_boundary_len + 2 - 1);
SCLogDebug("opening file with partial data");
} else {
filedata = NULL;
filedata_len = 0;
}
result = HTPFileOpen(hstate, filename, filename_len,
NULL, 0, HtpGetActiveRequestTxID(hstate),
filedata, filedata_len, HtpGetActiveRequestTxID(hstate),
STREAM_TOSERVER);
if (result == -1) {
goto end;
@ -1531,6 +1546,8 @@ static int HtpRequestBodyHandleMultipart(HtpState *hstate, HtpTxUserData *htud,
htud->tsflags |= HTP_DONTSTORE;
}
FlagDetectStateNewFile(htud, STREAM_TOSERVER);
htud->request_body.body_parsed += filedata_len;
SCLogDebug("htud->request_body.body_parsed %"PRIu64, htud->request_body.body_parsed);
} else if (header_next - filedata > 2) {
filedata_len = header_next - filedata - 2;

Loading…
Cancel
Save