git-svn-id: file:///var/lib/svn/clamav-devel/trunk/clamav-devel@158 77e5149b-7576-45b1-b177-96237e5ba77b
Nigel Horne authored on 2003/12/15 03:08:29... | ... |
@@ -1,3 +1,7 @@ |
1 |
+Sun Dec 14 18:07:44 GMT 2003 (njh) |
|
2 |
+---------------------------------- |
|
3 |
+ * libclamav: not all viruses were being found in embedded RFC822 messages |
|
4 |
+ |
|
1 | 5 |
Sat Dec 13 16:45:44 GMT 2003 (njh) |
2 | 6 |
---------------------------------- |
3 | 7 |
* libclamav: use new cl_chomp() and fixed memory leak |
... | ... |
@@ -17,6 +17,9 @@ |
17 | 17 |
* |
18 | 18 |
* Change History: |
19 | 19 |
* $Log: mbox.c,v $ |
20 |
+ * Revision 1.23 2003/12/14 18:07:01 nigelhorne |
|
21 |
+ * Some viruses in embedded messages were not being found |
|
22 |
+ * |
|
20 | 23 |
* Revision 1.22 2003/12/13 16:42:23 nigelhorne |
21 | 24 |
* call new cli_chomp |
22 | 25 |
* |
... | ... |
@@ -57,7 +60,7 @@ |
57 | 57 |
* Compilable under SCO; removed duplicate code with message.c |
58 | 58 |
* |
59 | 59 |
*/ |
60 |
-static char const rcsid[] = "$Id: mbox.c,v 1.22 2003/12/13 16:42:23 nigelhorne Exp $"; |
|
60 |
+static char const rcsid[] = "$Id: mbox.c,v 1.23 2003/12/14 18:07:01 nigelhorne Exp $"; |
|
61 | 61 |
|
62 | 62 |
#ifndef CL_DEBUG |
63 | 63 |
/*#define NDEBUG /* map CLAMAV debug onto standard */ |
... | ... |
@@ -109,7 +112,7 @@ static char const rcsid[] = "$Id: mbox.c,v 1.22 2003/12/13 16:42:23 nigelhorne E |
109 | 109 |
|
110 | 110 |
typedef enum { FALSE = 0, TRUE = 1 } bool; |
111 | 111 |
|
112 |
-static void parseEmailHeaders(message *m, table_t *rfc821Table); |
|
112 |
+static message *parseEmailHeaders(const message *m, const table_t *rfc821Table); |
|
113 | 113 |
static int parseEmailBody(message *mainMessage, blob **blobsIn, int nBlobs, text *textIn, const char *dir, table_t *rfc821Table, table_t *subtypeTable); |
114 | 114 |
static int boundaryStart(const char *line, const char *boundary); |
115 | 115 |
static int endOfMessage(const char *line, const char *boundary); |
... | ... |
@@ -342,12 +345,16 @@ cl_mbox(const char *dir, int desc) |
342 | 342 |
/* |
343 | 343 |
* It's a single message, parse the headers then the body |
344 | 344 |
*/ |
345 |
+ message *body; |
|
346 |
+ |
|
345 | 347 |
do { |
346 | 348 |
cli_chomp(buffer); |
347 | 349 |
messageAddLine(m, buffer); |
348 | 350 |
} while(fgets(buffer, sizeof(buffer), fd) != NULL); |
349 | 351 |
|
350 |
- parseEmailHeaders(m, rfc821Table); |
|
352 |
+ body = parseEmailHeaders(m, rfc821Table); |
|
353 |
+ messageDestroy(m); |
|
354 |
+ m = body; |
|
351 | 355 |
} |
352 | 356 |
|
353 | 357 |
fclose(fd); |
... | ... |
@@ -379,12 +386,16 @@ cl_mbox(const char *dir, int desc) |
379 | 379 |
* The given message contains a raw e-mail. |
380 | 380 |
* |
381 | 381 |
* This function parses the headers of m and sets the message's arguments |
382 |
+ * |
|
383 |
+ * Returns the message's body with the correct arguments set |
|
382 | 384 |
*/ |
383 |
-static void |
|
384 |
-parseEmailHeaders(message *m, table_t *rfc821Table) |
|
385 |
+static message * |
|
386 |
+parseEmailHeaders(const message *m, const table_t *rfc821Table) |
|
385 | 387 |
{ |
386 | 388 |
bool inContinuationHeader = FALSE; |
389 |
+ bool inHeader = TRUE; |
|
387 | 390 |
text *t, *msgText = messageToText(m); |
391 |
+ message *ret = messageCreate(); |
|
388 | 392 |
|
389 | 393 |
t = msgText; |
390 | 394 |
assert(t != NULL); |
... | ... |
@@ -401,7 +412,7 @@ parseEmailHeaders(message *m, table_t *rfc821Table) |
401 | 401 |
* Section B.2 of RFC822 says TAB or SPACE means |
402 | 402 |
* a continuation of the previous entry. |
403 | 403 |
*/ |
404 |
- if((buffer[0] == '\t') || (buffer[0] == ' ')) |
|
404 |
+ if(inHeader && ((buffer[0] == '\t') || (buffer[0] == ' '))) |
|
405 | 405 |
inContinuationHeader = TRUE; |
406 | 406 |
|
407 | 407 |
if(inContinuationHeader) { |
... | ... |
@@ -414,8 +425,8 @@ parseEmailHeaders(message *m, table_t *rfc821Table) |
414 | 414 |
* Add all the arguments on the line |
415 | 415 |
*/ |
416 | 416 |
for(ptr = strtok_r(buffer, ";", &strptr); ptr; ptr = strtok_r(NULL, ":", &strptr)) |
417 |
- messageAddArgument(m, ptr); |
|
418 |
- } else { |
|
417 |
+ messageAddArgument(ret, ptr); |
|
418 |
+ } else if(inHeader) { |
|
419 | 419 |
cli_dbgmsg("Deal with header %s\n", buffer); |
420 | 420 |
|
421 | 421 |
/* |
... | ... |
@@ -423,26 +434,28 @@ parseEmailHeaders(message *m, table_t *rfc821Table) |
423 | 423 |
* the start of the text |
424 | 424 |
*/ |
425 | 425 |
if(strstrip(buffer) == 0) { |
426 |
- free(buffer); |
|
427 | 426 |
cli_dbgmsg("End of header information\n"); |
428 |
- break; |
|
427 |
+ inHeader = FALSE; |
|
429 | 428 |
} else { |
430 | 429 |
const bool isLastLine = !continuationMarker(buffer); |
431 | 430 |
const char *cmd = strtok_r(buffer, " \t", &strptr); |
432 | 431 |
|
433 |
- if (cmd && *cmd) { |
|
432 |
+ if(cmd && *cmd) { |
|
434 | 433 |
const char *arg = strtok_r(NULL, "", &strptr); |
435 | 434 |
|
436 | 435 |
if(arg) |
437 |
- if(parseMimeHeader(m, cmd, rfc821Table, arg) == CONTENT_TYPE) |
|
436 |
+ if(parseMimeHeader(ret, cmd, rfc821Table, arg) == CONTENT_TYPE) |
|
438 | 437 |
inContinuationHeader = !isLastLine; |
439 | 438 |
} |
440 | 439 |
} |
441 |
- } |
|
440 |
+ } else |
|
441 |
+ messageAddLine(ret, buffer); |
|
442 | 442 |
free(buffer); |
443 | 443 |
} while((t = t->t_next) != NULL); |
444 | 444 |
|
445 | 445 |
textDestroy(msgText); |
446 |
+ |
|
447 |
+ return ret; |
|
446 | 448 |
} |
447 | 449 |
|
448 | 450 |
/* |
... | ... |
@@ -450,7 +463,8 @@ parseEmailHeaders(message *m, table_t *rfc821Table) |
450 | 450 |
* |
451 | 451 |
* This function parses the body of mainMessage and saves its attachments in dir |
452 | 452 |
* |
453 |
- * mainMessage is the buffer to be parsed, it contains an e-mail's body. First |
|
453 |
+ * mainMessage is the buffer to be parsed, it contains an e-mail's body, without |
|
454 |
+ * any headers. First |
|
454 | 455 |
* time of calling it'll be |
455 | 456 |
* the whole message. Later it'll be parts of a multipart message |
456 | 457 |
* textIn is the plain text message being built up so far |
... | ... |
@@ -565,6 +579,10 @@ parseEmailBody(message *mainMessage, blob **blobsIn, int nBlobs, text *textIn, c |
565 | 565 |
inhead = 1; |
566 | 566 |
inMimeHead = 0; |
567 | 567 |
|
568 |
+ /* |
|
569 |
+ * This looks like parseEmailHeaders() - maybe there's |
|
570 |
+ * some duplication of code to be cleaned up |
|
571 |
+ */ |
|
568 | 572 |
for(multiparts = 0; t_line && (multiparts < MAXALTERNATIVE); multiparts++) { |
569 | 573 |
aMessage = messages[multiparts] = messageCreate(); |
570 | 574 |
|
... | ... |
@@ -574,10 +592,12 @@ parseEmailBody(message *mainMessage, blob **blobsIn, int nBlobs, text *textIn, c |
574 | 574 |
while((t_line = t_line->t_next)) { |
575 | 575 |
const char *line = t_line->t_text; |
576 | 576 |
|
577 |
- /*cli_dbgmsg("inMimeHead %d inhead %d boundary %s line %s\n", |
|
578 |
- inMimeHead, inhead, boundary, line);*/ |
|
577 |
+ /*cli_dbgmsg("inMimeHead %d inhead %d boundary %s line '%s' next '%s'\n", |
|
578 |
+ inMimeHead, inhead, boundary, line, t_line->t_next ? t_line->t_next->t_text : "(null)");*/ |
|
579 | 579 |
|
580 | 580 |
if(inMimeHead) { |
581 |
+ cli_dbgmsg("About to add mime Argument '%s'\n", |
|
582 |
+ line); |
|
581 | 583 |
while(isspace((int)*line)) |
582 | 584 |
line++; |
583 | 585 |
|
... | ... |
@@ -585,8 +605,6 @@ parseEmailBody(message *mainMessage, blob **blobsIn, int nBlobs, text *textIn, c |
585 | 585 |
inhead = inMimeHead = 0; |
586 | 586 |
continue; |
587 | 587 |
} |
588 |
- cli_dbgmsg("About to add mime Argument '%s'\n", |
|
589 |
- line); |
|
590 | 588 |
/* |
591 | 589 |
* This may cause a trailing ';' |
592 | 590 |
* to be added if this test |
... | ... |
@@ -705,6 +723,7 @@ parseEmailBody(message *mainMessage, blob **blobsIn, int nBlobs, text *textIn, c |
705 | 705 |
|
706 | 706 |
switch(tableFind(subtypeTable, mimeSubtype)) { |
707 | 707 |
case RELATED: |
708 |
+ cli_dbgmsg("Multipart related handler\n"); |
|
708 | 709 |
/* |
709 | 710 |
* Have a look to see if there's HTML code |
710 | 711 |
* which will need scanning |
... | ... |
@@ -811,9 +830,7 @@ parseEmailBody(message *mainMessage, blob **blobsIn, int nBlobs, text *textIn, c |
811 | 811 |
if(aText) |
812 | 812 |
mainMessage = NULL; |
813 | 813 |
|
814 |
-#ifdef CL_DEBUG |
|
815 | 814 |
cli_dbgmsg("Mixed message with %d parts\n", multiparts); |
816 |
-#endif |
|
817 | 815 |
for(i = 0; i < multiparts; i++) { |
818 | 816 |
bool addAttachment = FALSE; |
819 | 817 |
bool addToText = FALSE; |
... | ... |
@@ -827,10 +844,8 @@ parseEmailBody(message *mainMessage, blob **blobsIn, int nBlobs, text *textIn, c |
827 | 827 |
dtype = messageGetDispositionType(aMessage); |
828 | 828 |
cptr = messageGetMimeSubtype(aMessage); |
829 | 829 |
|
830 |
-#ifdef CL_DEBUG |
|
831 | 830 |
cli_dbgmsg("Mixed message part %d is of type %d\n", |
832 | 831 |
i, messageGetMimeType(aMessage)); |
833 |
-#endif |
|
834 | 832 |
|
835 | 833 |
switch(messageGetMimeType(aMessage)) { |
836 | 834 |
case APPLICATION: |
... | ... |
@@ -1020,7 +1035,7 @@ parseEmailBody(message *mainMessage, blob **blobsIn, int nBlobs, text *textIn, c |
1020 | 1020 |
* ensure t is correctly freed |
1021 | 1021 |
*/ |
1022 | 1022 |
text *t, *msgText = messageToText(mainMessage); |
1023 |
- message *m; |
|
1023 |
+ message *m, *body; |
|
1024 | 1024 |
|
1025 | 1025 |
t = msgText; |
1026 | 1026 |
assert(t != NULL); |
... | ... |
@@ -1040,7 +1055,10 @@ parseEmailBody(message *mainMessage, blob **blobsIn, int nBlobs, text *textIn, c |
1040 | 1040 |
|
1041 | 1041 |
textDestroy(msgText); |
1042 | 1042 |
|
1043 |
- parseEmailHeaders(m, rfc821Table); |
|
1043 |
+ body = parseEmailHeaders(m, rfc821Table); |
|
1044 |
+ |
|
1045 |
+ messageDestroy(m); |
|
1046 |
+ m = body; |
|
1044 | 1047 |
|
1045 | 1048 |
messageClean(m); |
1046 | 1049 |
if(messageGetBody(m)) |
... | ... |
@@ -1106,6 +1124,7 @@ parseEmailBody(message *mainMessage, blob **blobsIn, int nBlobs, text *textIn, c |
1106 | 1106 |
} |
1107 | 1107 |
|
1108 | 1108 |
cli_dbgmsg("%d attachments found\n", nBlobs); |
1109 |
+ rc = 1; |
|
1109 | 1110 |
|
1110 | 1111 |
if(nBlobs == 0) { |
1111 | 1112 |
blob *b; |
... | ... |
@@ -1114,19 +1133,14 @@ parseEmailBody(message *mainMessage, blob **blobsIn, int nBlobs, text *textIn, c |
1114 | 1114 |
* No attachments - scan the text portions, often files |
1115 | 1115 |
* are hidden in HTML code |
1116 | 1116 |
*/ |
1117 |
- |
|
1118 |
-#ifdef CL_DEBUG |
|
1119 | 1117 |
cli_dbgmsg("%d multiparts found\n", multiparts); |
1120 |
-#endif |
|
1121 | 1118 |
for(i = 0; i < multiparts; i++) { |
1122 | 1119 |
b = messageToBlob(messages[i]); |
1123 | 1120 |
|
1124 | 1121 |
assert(b != NULL); |
1125 | 1122 |
|
1126 |
-#ifdef CL_DEBUG |
|
1127 | 1123 |
cli_dbgmsg("Saving multipart %d, encoded with scheme %d\n", |
1128 | 1124 |
i, messageGetEncoding(messages[i])); |
1129 |
-#endif |
|
1130 | 1125 |
|
1131 | 1126 |
(void)saveFile(b, dir); |
1132 | 1127 |
|
... | ... |
@@ -1171,7 +1185,8 @@ parseEmailBody(message *mainMessage, blob **blobsIn, int nBlobs, text *textIn, c |
1171 | 1171 |
blobDestroy(b); |
1172 | 1172 |
} |
1173 | 1173 |
} |
1174 |
- } |
|
1174 |
+ } else |
|
1175 |
+ rc = (multiparts) ? 1 : 2; /* anything saved? */ |
|
1175 | 1176 |
} else { |
1176 | 1177 |
short attachmentNumber; |
1177 | 1178 |
|
... | ... |
@@ -1194,9 +1209,9 @@ parseEmailBody(message *mainMessage, blob **blobsIn, int nBlobs, text *textIn, c |
1194 | 1194 |
if(blobs && (blobsIn == NULL)) |
1195 | 1195 |
blobArrayDestroy(blobs, nBlobs); |
1196 | 1196 |
|
1197 |
- cli_dbgmsg("parseEmailBody() returning 1\n"); |
|
1197 |
+ cli_dbgmsg("parseEmailBody() returning %d\n", rc); |
|
1198 | 1198 |
|
1199 |
- return 1; |
|
1199 |
+ return rc; |
|
1200 | 1200 |
} |
1201 | 1201 |
|
1202 | 1202 |
/* |
... | ... |
@@ -1461,6 +1476,9 @@ parseMimeHeader(message *m, const char *cmd, const table_t *rfc821Table, const c |
1461 | 1461 |
return type; |
1462 | 1462 |
} |
1463 | 1463 |
|
1464 |
+/* |
|
1465 |
+ * Save some data as a unique file in the given directory. |
|
1466 |
+ */ |
|
1464 | 1467 |
static bool |
1465 | 1468 |
saveFile(const blob *b, const char *dir) |
1466 | 1469 |
{ |