Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
openSUSE:Leap:15.3:Update
clamav.13406
clamav-CVE-2019-15961.patch
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File clamav-CVE-2019-15961.patch of Package clamav.13406
--- libclamav/mbox.c.orig +++ libclamav/mbox.c @@ -206,9 +205,9 @@ typedef struct mbox_ctx { #endif static int cli_parse_mbox(const char *dir, cli_ctx *ctx); -static message *parseEmailFile(fmap_t *map, size_t *at, const table_t *rfc821Table, const char *firstLine, const char *dir); -static message *parseEmailHeaders(message *m, const table_t *rfc821Table); -static int parseEmailHeader(message *m, const char *line, const table_t *rfc821Table); +static message *parseEmailFile(fmap_t *map, size_t *at, const table_t *rfc821Table, const char *firstLine, const char *dir, cli_ctx *ctx, bool *heuristicFound); +static message *parseEmailHeaders(message *m, const table_t *rfc821Table, bool *heuristicFound); +static int parseEmailHeader(message *m, const char *line, const table_t *rfc821, cli_ctx *ctx, bool *heuristicFound); static int parseMHTMLComment(const char *comment, cli_ctx *ctx, void *wrkjobj, void *cbdata); static mbox_status parseRootMHTML(mbox_ctx *mctx, message *m, text *t); static mbox_status parseEmailBody(message *messageIn, text *textIn, mbox_ctx *mctx, unsigned int recursion_level); @@ -217,7 +216,7 @@ static int boundaryEnd(const char *line, static int initialiseTables(table_t **rfc821Table, table_t **subtypeTable); static int getTextPart(message *const messages[], size_t size); static size_t strip(char *buf, int len); -static int parseMimeHeader(message *m, const char *cmd, const table_t *rfc821Table, const char *arg); +static int parseMimeHeader(message *m, const char *cmd, const table_t *rfc821Table, const char *arg, cli_ctx *ctx, bool *heuristicFound); static int saveTextPart(mbox_ctx *mctx, message *m, int destroy_text); static char *rfc2047(const char *in); static char *rfc822comments(const char *in, char *out); @@ -238,6 +237,12 @@ static blob *getHrefs(message *m, tag_ar static void hrefs_done(blob *b, tag_arguments_t *hrefs); static void checkURLs(message *m, mbox_ctx *mctx, mbox_status *rc, int is_html); +static bool haveTooManyMIMEPartsPerMessage(size_t mimePartCnt, cli_ctx *ctx); +static bool hitLineFoldCnt(const char *const line, size_t *lineFoldCnt, cli_ctx *ctx); +static bool haveTooManyHeaderBytes(size_t totalLen, cli_ctx *ctx); +static bool haveTooManyEmailHeaders(size_t totalHeaderCnt, cli_ctx *ctx); +static bool haveTooManyMIMEArguments(size_t argCnt, cli_ctx *ctx); + /* Maximum line length according to RFC2821 */ #define RFC2821LENGTH 1000 @@ -286,6 +291,12 @@ static void checkURLs(message *m, mbox_c */ #define KNOWBOT 14 /* Unknown and undocumented format? */ +#define HEURISTIC_EMAIL_MAX_LINE_FOLDS_PER_HEADER (256 * 1024) +#define HEURISTIC_EMAIL_MAX_HEADER_BYTES (1024 * 256) +#define HEURISTIC_EMAIL_MAX_HEADERS 1024 +#define HEURISTIC_EMAIL_MAX_MIME_PARTS_PER_MESSAGE 1024 +#define HEURISTIC_EMAIL_MAX_ARGUMENTS_PER_HEADER 256 + static const struct tableinit { const char *key; int value; @@ -468,9 +479,14 @@ cli_parse_mbox(const char *dir, cli_ctx /* * End of a message in the mail box */ - body = parseEmailHeaders(m, rfc821); + bool heuristicFound = FALSE; + body = parseEmailHeaders(m, rfc821, &heuristicFound); if(body == NULL) { messageReset(m); + if (heuristicFound) { + retcode = CL_VIRUS; + break; + } continue; } messageSetCTX(body, ctx); @@ -521,7 +537,11 @@ cli_parse_mbox(const char *dir, cli_ctx if(retcode == CL_SUCCESS) { cli_dbgmsg("Extract attachments from email %d\n", messagenumber); - body = parseEmailHeaders(m, rfc821); + bool heuristicFound = FALSE; + body = parseEmailHeaders(m, rfc821, &heuristicFound); + if (heuristicFound) { + retcode = CL_VIRUS; + } } if(m) messageDestroy(m); @@ -548,7 +568,11 @@ cli_parse_mbox(const char *dir, cli_ctx buffer[sizeof(buffer) - 1] = '\0'; - body = parseEmailFile(map, &at, rfc821, buffer, dir); + bool heuristicFound = FALSE; + body = parseEmailFile(map, &at, rfc821, buffer, dir, ctx, &heuristicFound); + if (heuristicFound) { + retcode = CL_VIRUS; + } } if(body) { @@ -604,6 +628,253 @@ cli_parse_mbox(const char *dir, cli_ctx return retcode; } +/*TODO: move these to a header.*/ +#define DO_STRDUP(buf, var) \ + do { \ + var = strdup(buf); \ + if (NULL == var) { \ + goto done; \ + } \ + } while (0) + +#define DO_FREE(var) \ + do { \ + if (NULL != var) { \ + free(var); \ + var = NULL; \ + } \ + } while (0) + +#define DO_MALLOC(var, size) \ + do { \ + var = malloc(size); \ + if (NULL == var) { \ + goto done; \ + } \ + } while (0) + +#define DO_CALLOC(var, size) \ + do { \ + (var) = calloc((size), sizeof *(var)); \ + if (NULL == var) { \ + goto done; \ + } \ + } while (0) + +#define DO_VERIFY_POINTER(ptr) \ + do { \ + if (NULL == ptr) { \ + goto done; \ + } \ + } while (0) + +#define READ_STRUCT_BUFFER_LEN 1024 +typedef struct _ReadStruct { + char buffer[READ_STRUCT_BUFFER_LEN + 1]; + + size_t bufferLen; + + struct _ReadStruct *next; + +} ReadStruct; + +static ReadStruct * +appendReadStruct(ReadStruct *rs, const char *const buffer) +{ + if (NULL == rs) { + assert(rs && "Invalid argument"); + goto done; + } + + size_t spaceLeft = (READ_STRUCT_BUFFER_LEN - rs->bufferLen); + + if (strlen(buffer) > spaceLeft) { + ReadStruct *next = NULL; + int part = spaceLeft; + strncpy(&(rs->buffer[rs->bufferLen]), buffer, part); + rs->bufferLen += part; + + DO_CALLOC(next, 1); + + rs->next = next; + strcpy(next->buffer, &(buffer[part])); + next->bufferLen = strlen(&(buffer[part])); + + rs = next; + } else { + strcpy(&(rs->buffer[rs->bufferLen]), buffer); + rs->bufferLen += strlen(buffer); + } + +done: + return rs; +} + +static char * +getMallocedBufferFromList(const ReadStruct *head) +{ + + const ReadStruct *rs = head; + int bufferLen = 1; + char *working = NULL; + char *ret = NULL; + + while (rs) { + bufferLen += rs->bufferLen; + rs = rs->next; + } + + DO_MALLOC(working, bufferLen); + + rs = head; + bufferLen = 0; + while (rs) { + memcpy(&(working[bufferLen]), rs->buffer, rs->bufferLen); + bufferLen += rs->bufferLen; + working[bufferLen] = 0; + rs = rs->next; + } + + ret = working; +done: + if (NULL == ret) { + DO_FREE(working); + } + + return ret; +} + +static void +freeList(ReadStruct *head) +{ + while (head) { + ReadStruct *rs = head->next; + DO_FREE(head); + head = rs; + } +} + +#ifndef FREELIST_REALLOC +#define FREELIST_REALLOC(head, curr) \ + do { \ + if (curr != head) { \ + freeList(head->next); \ + } \ + head->bufferLen = 0; \ + head->next = 0; \ + curr = head; \ + } while (0) +#endif /*FREELIST_REALLOC*/ + +/*Check if we have repeated blank lines with only a semicolon at the end. Semicolon is a delimiter for parameters, + * but if there is no data, it isn't a parameter. Allow the first one because it may be continuation of a previous line + * that actually had data in it.*/ +static bool +doContinueMultipleEmptyOptions(const char *const line, bool *lastWasOnlySemi) +{ + if (line) { + size_t i = 0; + int doCont = 1; + for (; i < strlen(line); i++) { + if (isblank(line[i])) { + } else if (';' == line[i]) { + } else { + doCont = 0; + break; + } + } + + if (1 == doCont) { + if (*lastWasOnlySemi) { + return TRUE; + } + *lastWasOnlySemi = TRUE; + } else { + *lastWasOnlySemi = FALSE; + } + } + return FALSE; +} + +static bool +hitLineFoldCnt(const char *const line, size_t *lineFoldCnt, cli_ctx *ctx) +{ + + if (line) { + if (isblank(line[0])) { + (*lineFoldCnt)++; + } else { + (*lineFoldCnt) = 0; + } + + if ((*lineFoldCnt) >= HEURISTIC_EMAIL_MAX_LINE_FOLDS_PER_HEADER) { + if (ctx->options & CL_SCAN_ALGORITHMIC) { + cli_append_virus(ctx, "Heuristics.Email.ExceedsMaxLineFoldCnt"); + } + + return TRUE; + } + } + return FALSE; +} + +static bool +haveTooManyHeaderBytes(size_t totalLen, cli_ctx *ctx) +{ + + if (totalLen > HEURISTIC_EMAIL_MAX_HEADER_BYTES) { + if (ctx->options & CL_SCAN_ALGORITHMIC) { + cli_append_virus(ctx, "Heuristics.Email.ExceedsMaxHeaderBytes"); + } + + return TRUE; + } + return FALSE; +} + +static bool +haveTooManyEmailHeaders(size_t totalHeaderCnt, cli_ctx *ctx) +{ + + if (totalHeaderCnt > HEURISTIC_EMAIL_MAX_HEADERS) { + if (ctx->options & CL_SCAN_ALGORITHMIC) { + cli_append_virus(ctx, "Heuristics.Email.ExceedsMaxEmailHeaders"); + } + + return TRUE; + } + return FALSE; +} + +static bool +haveTooManyMIMEPartsPerMessage(size_t mimePartCnt, cli_ctx *ctx) +{ + + if (mimePartCnt >= HEURISTIC_EMAIL_MAX_MIME_PARTS_PER_MESSAGE) { + if (ctx->options & CL_SCAN_ALGORITHMIC) { + cli_append_virus(ctx, "Heuristics.Email.ExceedsMaxMIMEPartsPerMessage"); + } + + return TRUE; + } + return FALSE; +} + +static bool +haveTooManyMIMEArguments(size_t argCnt, cli_ctx *ctx) +{ + + if (argCnt >= HEURISTIC_EMAIL_MAX_ARGUMENTS_PER_HEADER) { + if (ctx->options & CL_SCAN_ALGORITHMIC) { + cli_append_virus(ctx, "Heuristics.Email.ExceedsMaxMIMEArguments"); + } + + return TRUE; + } + + return FALSE; +} + /* * Read in an email message from fin, parse it, and return the message * @@ -611,7 +882,7 @@ cli_parse_mbox(const char *dir, cli_ctx * handled ungracefully... */ static message * -parseEmailFile(fmap_t *map, size_t *at, const table_t *rfc821, const char *firstLine, const char *dir) +parseEmailFile(fmap_t *map, size_t *at, const table_t *rfc821, const char *firstLine, const char *dir, cli_ctx *ctx, bool *heuristicFound) { bool inHeader = TRUE; bool bodyIsEmpty = TRUE; @@ -619,9 +890,21 @@ parseEmailFile(fmap_t *map, size_t *at, message *ret; bool anyHeadersFound = FALSE; int commandNumber = -1; - char *fullline = NULL, *boundary = NULL; - size_t fulllinelength = 0; + char *boundary = NULL; char buffer[RFC2821LENGTH + 1]; + bool lastWasOnlySemi = FALSE; + int err = 1; + size_t totalHeaderBytes = 0; + size_t totalHeaderCnt = 0; + + size_t lineFoldCnt = 0; + + *heuristicFound = FALSE; + + ReadStruct *head = NULL; + ReadStruct *curr = NULL; + DO_CALLOC(head, 1); + curr = head; cli_dbgmsg("parseEmailFile\n"); @@ -640,6 +923,15 @@ parseEmailFile(fmap_t *map, size_t *at, else line = buffer; + if (doContinueMultipleEmptyOptions(line, &lastWasOnlySemi)) { + continue; + } + + if (hitLineFoldCnt(line, &lineFoldCnt, ctx)) { + *heuristicFound = TRUE; + break; + } + /* * Don't blank lines which are only spaces from headers, * otherwise they'll be treated as the end of header marker @@ -652,8 +944,8 @@ parseEmailFile(fmap_t *map, size_t *at, } } if(inHeader) { - cli_dbgmsg("parseEmailFile: check '%s' fullline %p\n", - buffer, fullline); + cli_dbgmsg("parseEmailFile: check '%s'\n", buffer); + /* * Ensure wide characters are handled where * sizeof(char) > 1 @@ -677,13 +969,29 @@ parseEmailFile(fmap_t *map, size_t *at, * content-type line. So we just have * to make a best guess. Sigh. */ - if(fullline) { - if(parseEmailHeader(ret, fullline, rfc821) < 0) + if (head->bufferLen) { + char *header = getMallocedBufferFromList(head); + int needContinue = 0; + DO_VERIFY_POINTER(header); + + totalHeaderCnt++; + if (haveTooManyEmailHeaders(totalHeaderCnt, ctx)) { + *heuristicFound = TRUE; + break; + } + needContinue = (parseEmailHeader(ret, header, rfc821, ctx, heuristicFound) < 0); + if (*heuristicFound) { + DO_FREE(header); + break; + } + DO_FREE(header); + FREELIST_REALLOC(head, curr); + + if (needContinue) { continue; - - free(fullline); - fullline = NULL; + } } + if(boundary || ((boundary = (char *)messageFindArgument(ret, "boundary")) != NULL)) { lastWasBlank = TRUE; @@ -691,7 +999,7 @@ parseEmailFile(fmap_t *map, size_t *at, } } } - if((line == NULL) && (fullline == NULL)) { /* empty line */ + if((line == NULL) && (0 == head->bufferLen)) { /* empty line */ /* * A blank line signifies the end of * the header and the start of the text @@ -706,8 +1014,9 @@ parseEmailFile(fmap_t *map, size_t *at, } else { char *ptr; const char *lookahead; + bool lineAdded = TRUE; - if(fullline == NULL) { + if(0 == head->bufferLen) { char cmd[RFC2821LENGTH + 1], out[RFC2821LENGTH + 1]; /* @@ -740,23 +1049,26 @@ parseEmailFile(fmap_t *map, size_t *at, anyHeadersFound = usefulHeader(commandNumber, cmd); continue; } - fullline = cli_strdup(line); - fulllinelength = strlen(line) + 1; - if(!fullline) { - if(ret) + curr = appendReadStruct(curr, line); + if (NULL == curr) { + if (ret) { ret->isTruncated = TRUE; + } break; } } else if(line != NULL) { - fulllinelength += strlen(line) + 1; - ptr = cli_realloc(fullline, fulllinelength); - if(ptr == NULL) - continue; - fullline = ptr; - cli_strlcat(fullline, line, fulllinelength); + curr = appendReadStruct(curr, line); + } else { + lineAdded = FALSE; } - assert(fullline != NULL); + if (lineAdded) { + totalHeaderBytes += strlen(line); + if (haveTooManyHeaderBytes(totalHeaderBytes, ctx)) { + *heuristicFound = TRUE; + break; + } + } if((lookahead = fmap_need_off_once(map, *at, 1))) { /* @@ -774,24 +1086,35 @@ parseEmailFile(fmap_t *map, size_t *at, * Handle broken headers, where the next * line isn't indented by whitespace */ - if(fullline[strlen(fullline) - 1] == ';') - /* Add arguments to this line */ - continue; + { + char *header = getMallocedBufferFromList(head); /*This is the issue */ + int needContinue = 0; + needContinue = (header[strlen(header) - 1] == ';'); + if (0 == needContinue) { + needContinue = (line && (count_quotes(header) & 1)); + } - if(line && (count_quotes(fullline) & 1)) - continue; + if (0 == needContinue) { + totalHeaderCnt++; + if (haveTooManyEmailHeaders(totalHeaderCnt, ctx)) { + *heuristicFound = TRUE; + break; + } + needContinue = (parseEmailHeader(ret, header, rfc821, ctx, heuristicFound) < 0); + if (*heuristicFound) { + DO_FREE(header); + break; + } + /*Check total headers here;*/ + } - ptr = rfc822comments(fullline, NULL); - if(ptr) { - free(fullline); - fullline = ptr; + DO_FREE(header); + if (needContinue) { + continue; + } + FREELIST_REALLOC(head, curr); } - if(parseEmailHeader(ret, fullline, rfc821) < 0) - continue; - - free(fullline); - fullline = NULL; } } else if(line && isuuencodebegin(line)) { /* @@ -835,19 +1158,17 @@ parseEmailFile(fmap_t *map, size_t *at, } } while(getline_from_mbox(buffer, sizeof(buffer) - 1, map, at) != NULL); - if(boundary) - free(boundary); - - if(fullline) { - if(*fullline) switch(commandNumber) { - case CONTENT_TRANSFER_ENCODING: - case CONTENT_DISPOSITION: - case CONTENT_TYPE: - cli_dbgmsg("parseEmailFile: Fullline unparsed '%s'\n", fullline); - } - free(fullline); + err = 0; + done: + if (err) { + cli_errmsg("parseEmailFile: ERROR parsing file\n"); + ret->isTruncated = TRUE; } + DO_FREE(boundary); + + freeList(head); + if(!anyHeadersFound) { /* * False positive in believing we have an e-mail when we don't @@ -857,6 +1178,12 @@ parseEmailFile(fmap_t *map, size_t *at, return NULL; } + if (*heuristicFound) { + messageDestroy(ret); + cli_dbgmsg("parseEmailFile: found heuristic\n"); + return NULL; + } + cli_dbgmsg("parseEmailFile: return\n"); return ret; @@ -871,7 +1198,7 @@ parseEmailFile(fmap_t *map, size_t *at, * TODO: remove the duplication with parseEmailFile */ static message * -parseEmailHeaders(message *m, const table_t *rfc821) +parseEmailHeaders(message *m, const table_t *rfc821, bool *heuristicFound) { bool inHeader = TRUE; bool bodyIsEmpty = TRUE; @@ -881,9 +1208,14 @@ parseEmailHeaders(message *m, const tabl int commandNumber = -1; char *fullline = NULL; size_t fulllinelength = 0; + bool lastWasOnlySemi = FALSE; + size_t lineFoldCnt = 0; + size_t totalHeaderCnt = 0; cli_dbgmsg("parseEmailHeaders\n"); + *heuristicFound = FALSE; + if(m == NULL) return NULL; @@ -897,6 +1229,15 @@ parseEmailHeaders(message *m, const tabl else line = NULL; + if (doContinueMultipleEmptyOptions(line, &lastWasOnlySemi)) { + continue; + } + + if (hitLineFoldCnt(line, &lineFoldCnt, m->ctx)) { + *heuristicFound = TRUE; + break; + } + if(inHeader) { cli_dbgmsg("parseEmailHeaders: check '%s'\n", line ? line : ""); @@ -914,6 +1255,7 @@ parseEmailHeaders(message *m, const tabl bodyIsEmpty = TRUE; } else { char *ptr; + bool lineAdded = TRUE; if(fullline == NULL) { char cmd[RFC2821LENGTH + 1]; @@ -959,8 +1301,21 @@ parseEmailHeaders(message *m, const tabl continue; fullline = ptr; cli_strlcat(fullline, line, fulllinelength); + } else { + lineAdded = FALSE; } assert(fullline != NULL); + /*continue doesn't seem right here, but that is what is done everywhere else when a malloc fails.*/ + if (NULL == fullline) { + continue; + } + + if (lineAdded) { + if (haveTooManyHeaderBytes(fulllinelength, m->ctx)) { + *heuristicFound = TRUE; + break; + } + } if(next_is_folded_header(t)) /* Add arguments to this line */ @@ -978,8 +1333,17 @@ parseEmailHeaders(message *m, const tabl fullline = ptr; } - if(parseEmailHeader(ret, fullline, rfc821) < 0) + totalHeaderCnt++; + if (haveTooManyEmailHeaders(totalHeaderCnt, m->ctx)) { + *heuristicFound = TRUE; + break; + } + if (parseEmailHeader(ret, fullline, rfc821, m->ctx, heuristicFound) < 0) { continue; + } + if (*heuristicFound) { + break; + } free(fullline); fullline = NULL; @@ -1025,6 +1389,11 @@ parseEmailHeaders(message *m, const tabl cli_dbgmsg("parseEmailHeaders: no headers found, assuming it isn't an email\n"); return NULL; } + if (*heuristicFound) { + messageDestroy(ret); + cli_dbgmsg("parseEmailHeaders: found a heuristic, delete message and stop parsing.\n"); + return NULL; + } cli_dbgmsg("parseEmailHeaders: return\n"); @@ -1035,9 +1404,9 @@ parseEmailHeaders(message *m, const tabl * Handle a header line of an email message */ static int -parseEmailHeader(message *m, const char *line, const table_t *rfc821) +parseEmailHeader(message *m, const char *line, const table_t *rfc821, cli_ctx *ctx, bool *heuristicFound) { - int ret; + int ret = -1; #ifdef CL_THREAD_SAFE char *strptr; #endif @@ -1060,15 +1429,17 @@ parseEmailHeader(message *m, const char return -1; copy = rfc2047(line); - if(copy == NULL) + if(copy == NULL) { /* an RFC checker would return -1 here */ copy = cli_strdup(line); + if (NULL == copy) { + goto done; + } + } tokenseparator[0] = *separator; tokenseparator[1] = '\0'; - ret = -1; - #ifdef CL_THREAD_SAFE cmd = strtok_r(copy, tokenseparator, &strptr); #else @@ -1082,7 +1453,7 @@ parseEmailHeader(message *m, const char char *arg = strtok(NULL, ""); #endif - if(arg) + if(arg) { /* * Found a header such as * Content-Type: multipart/mixed; @@ -1090,9 +1461,12 @@ parseEmailHeader(message *m, const char * "multipart/mixed" and cmd to * be "Content-Type" */ - ret = parseMimeHeader(m, cmd, rfc821, arg); + ret = parseMimeHeader(m, cmd, rfc821, arg, ctx, heuristicFound); + } } - free(copy); +done: + DO_FREE(copy); + return ret; } @@ -1145,9 +1519,6 @@ parseMHTMLComment(const char *comment, c #if HAVE_LIBXML2 const char *xmlsrt, *xmlend; xmlTextReaderPtr reader; -#if HAVE_JSON - json_object *thisjobj = (json_object *)wrkjobj; -#endif int ret = CL_SUCCESS; UNUSEDPARAM(cbdata); @@ -1340,6 +1711,7 @@ parseEmailBody(message *messageIn, text #if HAVE_JSON json_object *saveobj = mctx->wrkobj; #endif + bool heuristicFound = FALSE; cli_dbgmsg("in parseEmailBody, %u files saved so far\n", mctx->files); @@ -1636,7 +2008,11 @@ parseEmailBody(message *messageIn, text * Content-Type: application/octet-stream; * Content-Transfer-Encoding: base64 */ - parseEmailHeader(aMessage, line, mctx->rfc821Table); + parseEmailHeader(aMessage, line, mctx->rfc821Table, mctx->ctx, &heuristicFound); + if (heuristicFound) { + rc = VIRUS; + break; + } while(isspace((int)*line)) line++; @@ -1781,8 +2157,11 @@ parseEmailBody(message *messageIn, text cli_dbgmsg("Multipart %d: About to parse folded header '%s'\n", multiparts, fullline); - parseEmailHeader(aMessage, fullline, mctx->rfc821Table); + parseEmailHeader(aMessage, fullline, mctx->rfc821Table, mctx->ctx, &heuristicFound); free(fullline); + if (heuristicFound) { + rc = VIRUS; + } } else if(boundaryEnd(line, boundary)) { /* * Some viruses put information @@ -1859,6 +2238,12 @@ parseEmailBody(message *messageIn, text free((char *)boundary); + if (haveTooManyMIMEPartsPerMessage(multiparts, mctx->ctx)) { + DO_FREE(messages); + rc = VIRUS; + break; + } + /* * Preprocess. Anything special to be done before * we handle the multiparts? @@ -2109,7 +2499,7 @@ parseEmailBody(message *messageIn, text rc = FAIL; if((strcasecmp(mimeSubtype, "rfc822") == 0) || (strcasecmp(mimeSubtype, "delivery-status") == 0)) { - message *m = parseEmailHeaders(mainMessage, mctx->rfc821Table); + message *m = parseEmailHeaders(mainMessage, mctx->rfc821Table, &heuristicFound); if(m) { cli_dbgmsg("Decode rfc822\n"); @@ -2124,6 +2514,8 @@ parseEmailBody(message *messageIn, text rc = parseEmailBody(m, NULL, mctx, recursion_level + 1); messageDestroy(m); + } else if (heuristicFound) { + rc = VIRUS; } break; } else if(strcasecmp(mimeSubtype, "disposition-notification") == 0) { @@ -2762,11 +3155,14 @@ strstrip(char *s) * Returns 0 for OK, -1 for error */ static int -parseMimeHeader(message *m, const char *cmd, const table_t *rfc821Table, const char *arg) +parseMimeHeader(message *m, const char *cmd, const table_t *rfc821Table, const char *arg, cli_ctx *ctx, bool *heuristicFound) { char *copy, *p, *buf; const char *ptr; int commandNumber; + size_t argCnt = 0; + + *heuristicFound = FALSE; cli_dbgmsg("parseMimeHeader: cmd='%s', arg='%s'\n", cmd, arg); @@ -2917,6 +3313,11 @@ parseMimeHeader(message *m, const char * while(cli_strtokbuf(ptr, i++, ";", buf) != NULL) { cli_dbgmsg("mimeArgs = '%s'\n", buf); + argCnt++; + if (haveTooManyMIMEArguments(argCnt, ctx)) { + *heuristicFound = TRUE; + break; + } messageAddArguments(m, buf); } } @@ -3866,7 +4269,6 @@ do_multipart(message *mainMessage, messa message *aMessage = messages[i]; const int doPhishingScan = mctx->ctx->engine->dboptions&CL_DB_PHISHING_URLS && (DCONF_PHISHING&PHISHING_CONF_ENGINE); #if HAVE_JSON - const char *mtype = NULL; json_object *thisobj = NULL, *saveobj = mctx->wrkobj; if (mctx->wrkobj != NULL) { @@ -4245,5 +4647,7 @@ newline_in_header(const char *line) if(strncmp(line, "Date: ", 6) == 0) return TRUE; + cli_dbgmsg("newline_in_header, returning \"%s\"\n", line); + return FALSE; }
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor