decode-mime: fix body md5 computation

Previous code was wrongly supposing the lines are ending with CRLF.
But this is not the case so we must propagate the length of end of
line delimiter to be able to compute the md5 of the mail body.
pull/1671/head
Eric Leblond 11 years ago
parent 53419b93c8
commit 2ecab3f765

@ -813,7 +813,8 @@ static int SMTPProcessCommandDATA(SMTPState *state, Flow *f,
if (smtp_config.decode_mime && state->curr_tx->mime_state) { if (smtp_config.decode_mime && state->curr_tx->mime_state) {
int ret = MimeDecParseLine((const uint8_t *) state->current_line, int ret = MimeDecParseLine((const uint8_t *) state->current_line,
state->current_line_len, state->curr_tx->mime_state); state->current_line_len, state->current_line_delimiter_len,
state->curr_tx->mime_state);
if (ret != MIME_DEC_OK) { if (ret != MIME_DEC_OK) {
SCLogDebug("MimeDecParseLine() function returned an error code: %d", ret); SCLogDebug("MimeDecParseLine() function returned an error code: %d", ret);
} }

@ -2040,6 +2040,13 @@ static int ProcessBodyComplete(MimeDecParseState *state)
} }
} }
#ifdef HAVE_NSS
if (state->md5_ctx) {
unsigned int len = 0;
HASH_End(state->md5_ctx, state->md5, &len, sizeof(state->md5));
}
#endif
/* Invoke pre-processor and callback with remaining data */ /* Invoke pre-processor and callback with remaining data */
ret = ProcessDecodedDataChunk(state->data_chunk, state->data_chunk_len, state); ret = ProcessDecodedDataChunk(state->data_chunk, state->data_chunk_len, state);
if (ret != MIME_DEC_OK) { if (ret != MIME_DEC_OK) {
@ -2209,12 +2216,14 @@ static int ProcessMimeBody(const uint8_t *buf, uint32_t len,
uint32_t tlen; uint32_t tlen;
#ifdef HAVE_NSS #ifdef HAVE_NSS
if (MimeDecGetConfig()->body_md5 && state->body_begin == 1 && (state->md5_ctx == NULL)) { if (MimeDecGetConfig()->body_md5) {
state->md5_ctx = HASH_Create(HASH_AlgMD5); if (state->body_begin == 1) {
if (state->md5_ctx != NULL) { if (state->md5_ctx == NULL) {
HASH_Begin(state->md5_ctx); state->md5_ctx = HASH_Create(HASH_AlgMD5);
HASH_Update(state->md5_ctx, buf, len + 2); /* plus 2 to add CRLF */ HASH_Begin(state->md5_ctx);
}
} }
HASH_Update(state->md5_ctx, buf, len + state->current_line_delimiter_len);
} }
#endif #endif
@ -2474,13 +2483,6 @@ int MimeDecParseComplete(MimeDecParseState *state)
return ret; return ret;
} }
#ifdef HAVE_NSS
if (state->md5_ctx) {
unsigned int len = 0;
HASH_End(state->md5_ctx, state->md5, &len, sizeof(state->md5));
}
#endif
if (state->stack->top == NULL) { if (state->stack->top == NULL) {
state->msg->anomaly_flags |= ANOM_MALFORMED_MSG; state->msg->anomaly_flags |= ANOM_MALFORMED_MSG;
SCLogDebug("Error: Message is malformed"); SCLogDebug("Error: Message is malformed");
@ -2513,12 +2515,13 @@ int MimeDecParseComplete(MimeDecParseState *state)
* *
* \param line A string representing the line (w/out CRLF) * \param line A string representing the line (w/out CRLF)
* \param len The length of the line * \param len The length of the line
* \param delim_len The length of the line end delimiter
* \param state The parser state * \param state The parser state
* *
* \return MIME_DEC_OK on success, otherwise < 0 on failure * \return MIME_DEC_OK on success, otherwise < 0 on failure
*/ */
int MimeDecParseLine(const uint8_t *line, const uint32_t len, int MimeDecParseLine(const uint8_t *line, const uint32_t len,
MimeDecParseState *state) const uint8_t delim_len, MimeDecParseState *state)
{ {
int ret = MIME_DEC_OK; int ret = MIME_DEC_OK;
@ -2529,11 +2532,7 @@ int MimeDecParseLine(const uint8_t *line, const uint32_t len,
SCLogDebug("SMTP LINE - EMPTY"); SCLogDebug("SMTP LINE - EMPTY");
} }
#ifdef HAVE_NSS state->current_line_delimiter_len = delim_len;
if (state->md5_ctx) {
HASH_Update(state->md5_ctx, line, len + 2);
}
#endif
/* Process the entity */ /* Process the entity */
ret = ProcessMimeEntity(line, len, state); ret = ProcessMimeEntity(line, len, state);
if (ret != MIME_DEC_OK) { if (ret != MIME_DEC_OK) {
@ -2581,8 +2580,10 @@ MimeDecEntity * MimeDecParseFullMsg(const uint8_t *buf, uint32_t blen, void *dat
line = tok; line = tok;
state->current_line_delimiter_len = (remainPtr - tok) - tokLen;
/* Parse the line */ /* Parse the line */
ret = MimeDecParseLine(line, tokLen, state); ret = MimeDecParseLine(line, tokLen,
(remainPtr - tok) - tokLen, state);
if (ret != MIME_DEC_OK) { if (ret != MIME_DEC_OK) {
SCLogDebug("Error: MimeDecParseLine() function failed: %d", SCLogDebug("Error: MimeDecParseLine() function failed: %d",
ret); ret);
@ -2669,25 +2670,25 @@ static int MimeDecParseLineTest01(void)
TestDataChunkCallback); TestDataChunkCallback);
char *str = "From: Sender1"; char *str = "From: Sender1";
ret |= MimeDecParseLine((uint8_t *)str, strlen(str), state); ret |= MimeDecParseLine((uint8_t *)str, strlen(str), 1, state);
str = "To: Recipient1"; str = "To: Recipient1";
ret |= MimeDecParseLine((uint8_t *)str, strlen(str), state); ret |= MimeDecParseLine((uint8_t *)str, strlen(str), 1, state);
str = "Content-Type: text/plain"; str = "Content-Type: text/plain";
ret |= MimeDecParseLine((uint8_t *)str, strlen(str), state); ret |= MimeDecParseLine((uint8_t *)str, strlen(str), 1, state);
str = ""; str = "";
ret |= MimeDecParseLine((uint8_t *)str, strlen(str), state); ret |= MimeDecParseLine((uint8_t *)str, strlen(str), 1, state);
str = "A simple message line 1"; str = "A simple message line 1";
ret |= MimeDecParseLine((uint8_t *)str, strlen(str), state); ret |= MimeDecParseLine((uint8_t *)str, strlen(str), 1, state);
str = "A simple message line 2"; str = "A simple message line 2";
ret |= MimeDecParseLine((uint8_t *)str, strlen(str), state); ret |= MimeDecParseLine((uint8_t *)str, strlen(str), 1, state);
str = "A simple message line 3"; str = "A simple message line 3";
ret |= MimeDecParseLine((uint8_t *)str, strlen(str), state); ret |= MimeDecParseLine((uint8_t *)str, strlen(str), 1, state);
if (ret != MIME_DEC_OK) { if (ret != MIME_DEC_OK) {
return ret; return ret;
@ -2737,23 +2738,23 @@ static int MimeDecParseLineTest02(void)
TestDataChunkCallback); TestDataChunkCallback);
char *str = "From: Sender1"; char *str = "From: Sender1";
ret |= MimeDecParseLine((uint8_t *)str, strlen(str), state); ret |= MimeDecParseLine((uint8_t *)str, strlen(str), 1, state);
str = "To: Recipient1"; str = "To: Recipient1";
ret |= MimeDecParseLine((uint8_t *)str, strlen(str), state); ret |= MimeDecParseLine((uint8_t *)str, strlen(str), 1, state);
str = "Content-Type: text/plain"; str = "Content-Type: text/plain";
ret |= MimeDecParseLine((uint8_t *)str, strlen(str), state); ret |= MimeDecParseLine((uint8_t *)str, strlen(str), 1, state);
str = ""; str = "";
ret |= MimeDecParseLine((uint8_t *)str, strlen(str), state); ret |= MimeDecParseLine((uint8_t *)str, strlen(str), 1, state);
str = "A simple message line 1"; str = "A simple message line 1";
ret |= MimeDecParseLine((uint8_t *)str, strlen(str), state); ret |= MimeDecParseLine((uint8_t *)str, strlen(str), 1, state);
str = "A simple message line 2 click on http://www.test.com/malware.exe?" str = "A simple message line 2 click on http://www.test.com/malware.exe?"
"hahah hopefully you click this link"; "hahah hopefully you click this link";
ret |= MimeDecParseLine((uint8_t *)str, strlen(str), state); ret |= MimeDecParseLine((uint8_t *)str, strlen(str), 1, state);
if (ret != MIME_DEC_OK) { if (ret != MIME_DEC_OK) {
return ret; return ret;

@ -207,6 +207,7 @@ typedef struct MimeDecParseState {
int found_child; /**< Flag indicating a child entity was found */ int found_child; /**< Flag indicating a child entity was found */
int body_begin; /**< Currently at beginning of body */ int body_begin; /**< Currently at beginning of body */
int body_end; /**< Currently at end of body */ int body_end; /**< Currently at end of body */
uint8_t current_line_delimiter_len; /**< Length of line delimiter */
void *data; /**< Pointer to data specific to the caller */ void *data; /**< Pointer to data specific to the caller */
int (*DataChunkProcessorFunc) (const uint8_t *chunk, uint32_t len, int (*DataChunkProcessorFunc) (const uint8_t *chunk, uint32_t len,
struct MimeDecParseState *state); /**< Data chunk processing function callback */ struct MimeDecParseState *state); /**< Data chunk processing function callback */
@ -236,7 +237,7 @@ MimeDecParseState * MimeDecInitParser(void *data, int (*dcpfunc)(const uint8_t *
uint32_t len, MimeDecParseState *state)); uint32_t len, MimeDecParseState *state));
void MimeDecDeInitParser(MimeDecParseState *state); void MimeDecDeInitParser(MimeDecParseState *state);
int MimeDecParseComplete(MimeDecParseState *state); int MimeDecParseComplete(MimeDecParseState *state);
int MimeDecParseLine(const uint8_t *line, const uint32_t len, MimeDecParseState *state); int MimeDecParseLine(const uint8_t *line, const uint32_t len, const uint8_t delim_len, MimeDecParseState *state);
MimeDecEntity * MimeDecParseFullMsg(const uint8_t *buf, uint32_t blen, void *data, MimeDecEntity * MimeDecParseFullMsg(const uint8_t *buf, uint32_t blen, void *data,
int (*DataChunkProcessorFunc)(const uint8_t *chunk, uint32_t len, MimeDecParseState *state)); int (*DataChunkProcessorFunc)(const uint8_t *chunk, uint32_t len, MimeDecParseState *state));
const char *MimeDecParseStateGetStatus(MimeDecParseState *state); const char *MimeDecParseStateGetStatus(MimeDecParseState *state);

Loading…
Cancel
Save