git-svn: trunk@2579
Nigel Horne authored on 2006/12/28 08:15:36... | ... |
@@ -16,7 +16,7 @@ |
16 | 16 |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, |
17 | 17 |
* MA 02110-1301, USA. |
18 | 18 |
*/ |
19 |
-static char const rcsid[] = "$Id: mbox.c,v 1.364 2006/12/22 19:45:34 acab Exp $"; |
|
19 |
+static char const rcsid[] = "$Id: mbox.c,v 1.365 2006/12/27 23:14:27 njh Exp $"; |
|
20 | 20 |
|
21 | 21 |
#ifdef _MSC_VER |
22 | 22 |
#include <winsock.h> /* only needed in CL_EXPERIMENTAL */ |
... | ... |
@@ -110,6 +110,13 @@ typedef enum { FALSE = 0, TRUE = 1 } bool; |
110 | 110 |
#endif |
111 | 111 |
#endif |
112 | 112 |
|
113 |
+typedef enum { |
|
114 |
+ FAIL, |
|
115 |
+ OK, |
|
116 |
+ OK_ATTACHMENTS_NOT_SAVED, |
|
117 |
+ VIRUS |
|
118 |
+} mbox_status; |
|
119 |
+ |
|
113 | 120 |
#ifndef isblank |
114 | 121 |
#define isblank(c) (((c) == ' ') || ((c) == '\t')) |
115 | 122 |
#endif |
... | ... |
@@ -271,7 +278,7 @@ static int cli_parse_mbox(const char *dir, int desc, cli_ctx *ctx); |
271 | 271 |
static message *parseEmailFile(FILE *fin, const table_t *rfc821Table, const char *firstLine, const char *dir); |
272 | 272 |
static message *parseEmailHeaders(message *m, const table_t *rfc821Table); |
273 | 273 |
static int parseEmailHeader(message *m, const char *line, const table_t *rfc821Table); |
274 |
-static int parseEmailBody(message *messageIn, text *textIn, mbox_ctx *mctx, unsigned int recursion_level); |
|
274 |
+static mbox_status parseEmailBody(message *messageIn, text *textIn, mbox_ctx *mctx, unsigned int recursion_level); |
|
275 | 275 |
static int boundaryStart(const char *line, const char *boundary); |
276 | 276 |
static int endOfMessage(const char *line, const char *boundary); |
277 | 277 |
static int initialiseTables(table_t **rfc821Table, table_t **subtypeTable); |
... | ... |
@@ -289,16 +296,16 @@ static char *getline_from_mbox(char *buffer, size_t len, FILE *fin); |
289 | 289 |
static bool isBounceStart(const char *line); |
290 | 290 |
static bool exportBinhexMessage(const char *dir, message *m); |
291 | 291 |
static int exportBounceMessage(text *start, const mbox_ctx *ctx); |
292 |
-static message *do_multipart(message *mainMessage, message **messages, int i, int *rc, mbox_ctx *mctx, message *messageIn, text **tptr, unsigned int recursion_level); |
|
292 |
+static message *do_multipart(message *mainMessage, message **messages, int i, mbox_status *rc, mbox_ctx *mctx, message *messageIn, text **tptr, unsigned int recursion_level); |
|
293 | 293 |
static int count_quotes(const char *buf); |
294 | 294 |
static bool next_is_folded_header(const text *t); |
295 | 295 |
|
296 |
-static void checkURLs(message *m, mbox_ctx *mctx,int *rc, int is_html); |
|
296 |
+static void checkURLs(message *m, mbox_ctx *mctx, mbox_status *rc, int is_html); |
|
297 | 297 |
|
298 | 298 |
#ifdef CL_EXPERIMENTAL |
299 |
-static void do_checkURLs(message *m, const char *dir,tag_arguments_t* hrefs); |
|
300 |
-static blob* getHrefs(message* m,tag_arguments_t* hrefs); |
|
301 |
-static void hrefs_done(blob *b,tag_arguments_t* hrefs); |
|
299 |
+static void do_checkURLs(message *m, const char *dir, tag_arguments_t *hrefs); |
|
300 |
+static blob *getHrefs(message *m, tag_arguments_t *hrefs); |
|
301 |
+static void hrefs_done(blob *b, tag_arguments_t *hrefs); |
|
302 | 302 |
#endif |
303 | 303 |
|
304 | 304 |
#if defined(FOLLOWURLS) && (FOLLOWURLS > 0) |
... | ... |
@@ -1406,12 +1413,12 @@ cli_parse_mbox(const char *dir, int desc, cli_ctx *ctx) |
1406 | 1406 |
messageSetCTX(body, ctx); |
1407 | 1407 |
messageDestroy(m); |
1408 | 1408 |
if(messageGetBody(body)) { |
1409 |
- int rc = parseEmailBody(body, NULL, &mctx, 0); |
|
1410 |
- if(rc == 0) { |
|
1409 |
+ mbox_status rc = parseEmailBody(body, NULL, &mctx, 0); |
|
1410 |
+ if(rc == FAIL) { |
|
1411 | 1411 |
messageReset(body); |
1412 | 1412 |
m = body; |
1413 | 1413 |
continue; |
1414 |
- } else if(rc == 3) { |
|
1414 |
+ } else if(rc == VIRUS) { |
|
1415 | 1415 |
cli_dbgmsg("Message number %d is infected\n", |
1416 | 1416 |
messagenumber); |
1417 | 1417 |
retcode = CL_VIRUS; |
... | ... |
@@ -1488,10 +1495,10 @@ cli_parse_mbox(const char *dir, int desc, cli_ctx *ctx) |
1488 | 1488 |
if((retcode == CL_SUCCESS) && messageGetBody(body)) { |
1489 | 1489 |
messageSetCTX(body, ctx); |
1490 | 1490 |
switch(parseEmailBody(body, NULL, &mctx, 0)) { |
1491 |
- case 0: |
|
1491 |
+ case FAIL: |
|
1492 | 1492 |
retcode = CL_EFORMAT; |
1493 | 1493 |
break; |
1494 |
- case 3: |
|
1494 |
+ case VIRUS: |
|
1495 | 1495 |
retcode = CL_VIRUS; |
1496 | 1496 |
break; |
1497 | 1497 |
} |
... | ... |
@@ -2021,17 +2028,11 @@ parseEmailHeader(message *m, const char *line, const table_t *rfc821) |
2021 | 2021 |
* any headers. First time of calling it'll be |
2022 | 2022 |
* the whole message. Later it'll be parts of a multipart message |
2023 | 2023 |
* textIn is the plain text message being built up so far |
2024 |
- * |
|
2025 |
- * Returns: |
|
2026 |
- * 0 for fail |
|
2027 |
- * 1 for success, attachments saved |
|
2028 |
- * 2 for success, attachments not saved |
|
2029 |
- * 3 for virus found |
|
2030 | 2024 |
*/ |
2031 |
-static int /* success or fail */ |
|
2025 |
+static mbox_status |
|
2032 | 2026 |
parseEmailBody(message *messageIn, text *textIn, mbox_ctx *mctx, unsigned int recursion_level) |
2033 | 2027 |
{ |
2034 |
- int rc = 1; |
|
2028 |
+ mbox_status rc = OK; |
|
2035 | 2029 |
text *aText = textIn; |
2036 | 2030 |
message *mainMessage = messageIn; |
2037 | 2031 |
fileblob *fb; |
... | ... |
@@ -2122,7 +2123,7 @@ parseEmailBody(message *messageIn, text *textIn, mbox_ctx *mctx, unsigned int re |
2122 | 2122 |
* There might be html sent without subtype |
2123 | 2123 |
* html too, so scan them for phishing |
2124 | 2124 |
*/ |
2125 |
- if(rc == 3) |
|
2125 |
+ if(rc == VIRUS) |
|
2126 | 2126 |
infected = TRUE; |
2127 | 2127 |
} |
2128 | 2128 |
#endif |
... | ... |
@@ -2174,7 +2175,7 @@ parseEmailBody(message *messageIn, text *textIn, mbox_ctx *mctx, unsigned int re |
2174 | 2174 |
if(binhexBegin(mainMessage) == t_line) { |
2175 | 2175 |
if(exportBinhexMessage(mctx->dir, mainMessage)) { |
2176 | 2176 |
/* virus found */ |
2177 |
- rc = 3; |
|
2177 |
+ rc = VIRUS; |
|
2178 | 2178 |
infected = TRUE; |
2179 | 2179 |
break; |
2180 | 2180 |
} |
... | ... |
@@ -2498,7 +2499,7 @@ parseEmailBody(message *messageIn, text *textIn, mbox_ctx *mctx, unsigned int re |
2498 | 2498 |
&rc, mctx, messageIn, |
2499 | 2499 |
&aText, recursion_level + 1); |
2500 | 2500 |
--multiparts; |
2501 |
- if(rc == 3) |
|
2501 |
+ if(rc == VIRUS) |
|
2502 | 2502 |
infected = TRUE; |
2503 | 2503 |
break; |
2504 | 2504 |
default: |
... | ... |
@@ -2550,8 +2551,10 @@ parseEmailBody(message *messageIn, text *textIn, mbox_ctx *mctx, unsigned int re |
2550 | 2550 |
/* |
2551 | 2551 |
* FIXME: we could return 2 here when we have |
2552 | 2552 |
* saved stuff earlier |
2553 |
+ * |
|
2554 |
+ * Nothing to do |
|
2553 | 2555 |
*/ |
2554 |
- return (rc == 3) ? 3 : 2; /* Nothing to do */ |
|
2556 |
+ return (rc == VIRUS) ? VIRUS : OK_ATTACHMENTS_NOT_SAVED; |
|
2555 | 2557 |
} |
2556 | 2558 |
|
2557 | 2559 |
cli_dbgmsg("Find out the multipart type (%s)\n", mimeSubtype); |
... | ... |
@@ -2593,7 +2596,7 @@ parseEmailBody(message *messageIn, text *textIn, mbox_ctx *mctx, unsigned int re |
2593 | 2593 |
cli_dbgmsg("No HTML code found to be scanned\n"); |
2594 | 2594 |
else { |
2595 | 2595 |
rc = parseEmailBody(aMessage, aText, mctx, recursion_level + 1); |
2596 |
- if(rc == 1) { |
|
2596 |
+ if(rc == OK) { |
|
2597 | 2597 |
assert(aMessage == messages[htmltextPart]); |
2598 | 2598 |
messageDestroy(aMessage); |
2599 | 2599 |
messages[htmltextPart] = NULL; |
... | ... |
@@ -2674,7 +2677,7 @@ parseEmailBody(message *messageIn, text *textIn, mbox_ctx *mctx, unsigned int re |
2674 | 2674 |
mainMessage = do_multipart(mainMessage, |
2675 | 2675 |
messages, i, &rc, mctx, |
2676 | 2676 |
messageIn, &aText, recursion_level + 1); |
2677 |
- if(rc == 3) { |
|
2677 |
+ if(rc == VIRUS) { |
|
2678 | 2678 |
infected = TRUE; |
2679 | 2679 |
break; |
2680 | 2680 |
} |
... | ... |
@@ -2699,13 +2702,13 @@ parseEmailBody(message *messageIn, text *textIn, mbox_ctx *mctx, unsigned int re |
2699 | 2699 |
rc = parseEmailBody(messages[htmltextPart], aText, mctx, recursion_level + 1); |
2700 | 2700 |
break; |
2701 | 2701 |
case ENCRYPTED: |
2702 |
- rc = 0; |
|
2702 |
+ rc = OK; |
|
2703 | 2703 |
protocol = (char *)messageFindArgument(mainMessage, "protocol"); |
2704 | 2704 |
if(protocol) { |
2705 | 2705 |
if(strcasecmp(protocol, "application/pgp-encrypted") == 0) { |
2706 | 2706 |
/* RFC2015 */ |
2707 | 2707 |
cli_warnmsg("PGP encoded attachment not scanned\n"); |
2708 |
- rc = 2; |
|
2708 |
+ rc = OK_ATTACHMENTS_NOT_SAVED; |
|
2709 | 2709 |
} else |
2710 | 2710 |
cli_warnmsg("Unknown encryption protocol '%s' - if you believe this file contains a virus, submit it to www.clamav.net\n", protocol); |
2711 | 2711 |
free(protocol); |
... | ... |
@@ -2755,7 +2758,7 @@ parseEmailBody(message *messageIn, text *textIn, mbox_ctx *mctx, unsigned int re |
2755 | 2755 |
cli_warnmsg("MIME type 'message' cannot be decoded\n"); |
2756 | 2756 |
break; |
2757 | 2757 |
} |
2758 |
- rc = 0; |
|
2758 |
+ rc = FAIL; |
|
2759 | 2759 |
if((strcasecmp(mimeSubtype, "rfc822") == 0) || |
2760 | 2760 |
(strcasecmp(mimeSubtype, "delivery-status") == 0)) { |
2761 | 2761 |
message *m = parseEmailHeaders(mainMessage, mctx->rfc821Table); |
... | ... |
@@ -2777,16 +2780,15 @@ parseEmailBody(message *messageIn, text *textIn, mbox_ctx *mctx, unsigned int re |
2777 | 2777 |
break; |
2778 | 2778 |
} else if(strcasecmp(mimeSubtype, "disposition-notification") == 0) { |
2779 | 2779 |
/* RFC 2298 - handle like a normal email */ |
2780 |
- rc = 1; |
|
2780 |
+ rc = OK; |
|
2781 | 2781 |
break; |
2782 | 2782 |
} else if(strcasecmp(mimeSubtype, "partial") == 0) { |
2783 | 2783 |
#ifdef PARTIAL_DIR |
2784 | 2784 |
/* RFC1341 message split over many emails */ |
2785 | 2785 |
if(rfc1341(mainMessage, mctx->dir) >= 0) |
2786 |
- rc = 1; |
|
2786 |
+ rc = OK; |
|
2787 | 2787 |
#else |
2788 | 2788 |
cli_warnmsg("Partial message received from MUA/MTA - message cannot be scanned\n"); |
2789 |
- rc = 0; |
|
2790 | 2789 |
#endif |
2791 | 2790 |
} else if(strcasecmp(mimeSubtype, "external-body") == 0) |
2792 | 2791 |
/* TODO */ |
... | ... |
@@ -2967,7 +2969,7 @@ parseEmailBody(message *messageIn, text *textIn, mbox_ctx *mctx, unsigned int re |
2967 | 2967 |
* No attachments - scan the text portions, often files |
2968 | 2968 |
* are hidden in HTML code |
2969 | 2969 |
*/ |
2970 |
- if(mainMessage && (rc != 3)) { |
|
2970 |
+ if(mainMessage && (rc != VIRUS)) { |
|
2971 | 2971 |
text *t_line; |
2972 | 2972 |
|
2973 | 2973 |
/* |
... | ... |
@@ -2976,7 +2978,7 @@ parseEmailBody(message *messageIn, text *textIn, mbox_ctx *mctx, unsigned int re |
2976 | 2976 |
if((encodingLine(mainMessage) != NULL) && |
2977 | 2977 |
((t_line = bounceBegin(mainMessage)) != NULL)) { |
2978 | 2978 |
if(exportBounceMessage(t_line, mctx)) |
2979 |
- rc = 1; |
|
2979 |
+ rc = OK; |
|
2980 | 2980 |
} else { |
2981 | 2981 |
bool saveIt; |
2982 | 2982 |
|
... | ... |
@@ -3024,17 +3026,17 @@ parseEmailBody(message *messageIn, text *textIn, mbox_ctx *mctx, unsigned int re |
3024 | 3024 |
mainMessage = NULL; |
3025 | 3025 |
} else |
3026 | 3026 |
messageReset(mainMessage); |
3027 |
- rc = 1; |
|
3027 |
+ rc = OK; |
|
3028 | 3028 |
} |
3029 | 3029 |
} |
3030 | 3030 |
} else |
3031 |
- rc = 2; /* nothing saved */ |
|
3031 |
+ rc = OK_ATTACHMENTS_NOT_SAVED; /* nothing saved */ |
|
3032 | 3032 |
|
3033 | 3033 |
if(mainMessage && (mainMessage != messageIn)) |
3034 | 3034 |
messageDestroy(mainMessage); |
3035 | 3035 |
|
3036 |
- if((rc != 0) && infected) |
|
3037 |
- rc = 3; |
|
3036 |
+ if((rc != FAIL) && infected) |
|
3037 |
+ rc = VIRUS; |
|
3038 | 3038 |
|
3039 | 3039 |
cli_dbgmsg("parseEmailBody() returning %d\n", rc); |
3040 | 3040 |
|
... | ... |
@@ -3102,16 +3104,16 @@ boundaryStart(const char *line, const char *boundary) |
3102 | 3102 |
* viruses in both types of mails |
3103 | 3103 |
*/ |
3104 | 3104 |
if((strstr(ptr, boundary) != NULL) || (strstr(line, boundary) != NULL)) |
3105 |
- rc = 1; |
|
3105 |
+ rc = OK; |
|
3106 | 3106 |
else if(*ptr++ != '-') |
3107 |
- rc = 0; |
|
3107 |
+ rc = FAIL; |
|
3108 | 3108 |
else |
3109 | 3109 |
rc = (strcasecmp(ptr, boundary) == 0); |
3110 | 3110 |
|
3111 | 3111 |
if(out) |
3112 | 3112 |
free(out); |
3113 | 3113 |
|
3114 |
- if(rc == 1) |
|
3114 |
+ if(rc == OK) |
|
3115 | 3115 |
cli_dbgmsg("boundaryStart: found %s in %s\n", boundary, line); |
3116 | 3116 |
|
3117 | 3117 |
return rc; |
... | ... |
@@ -3238,7 +3240,7 @@ strip(char *buf, int len) |
3238 | 3238 |
return i; |
3239 | 3239 |
ptr = &buf[--len]; |
3240 | 3240 |
|
3241 |
-#if defined(UNIX) || defined(C_LINUX) || defined(C_DARWIN) || defined(C_KFREEBSD_GNU) /* watch - it may be in shared text area */ |
|
3241 |
+#if defined(UNIX) || defined(C_LINUX) || defined(C_DARWIN) /* watch - it may be in shared text area */ |
|
3242 | 3242 |
do |
3243 | 3243 |
if(*ptr) |
3244 | 3244 |
*ptr = '\0'; |
... | ... |
@@ -3904,7 +3906,7 @@ getHrefs(message *m, tag_arguments_t *hrefs) |
3904 | 3904 |
} |
3905 | 3905 |
|
3906 | 3906 |
static void |
3907 |
-checkURLs(message *mainMessage, mbox_ctx *mctx, int *rc, int is_html) |
|
3907 |
+checkURLs(message *mainMessage, mbox_ctx *mctx, mbox_status *rc, int is_html) |
|
3908 | 3908 |
{ |
3909 | 3909 |
tag_arguments_t hrefs; |
3910 | 3910 |
blob *b; |
... | ... |
@@ -3927,14 +3929,14 @@ checkURLs(message *mainMessage, mbox_ctx *mctx, int *rc, int is_html) |
3927 | 3927 |
|
3928 | 3928 |
b = getHrefs(mainMessage, &hrefs); |
3929 | 3929 |
if(b) { |
3930 |
- if(hrefs.scanContents /*!(mctx->ctx->engine->dboptions&CL_DB_NOPHISHING_URLS*/) { |
|
3930 |
+ if(hrefs.scanContents /*mctx->ctx->engine->dboptions&CL_DB_PHISHING_URLS*/) { |
|
3931 | 3931 |
if(phishingScan(mainMessage, mctx->dir, mctx->ctx, &hrefs) == CL_VIRUS) { |
3932 | 3932 |
mainMessage->isInfected = TRUE; |
3933 |
- *rc = 3; |
|
3933 |
+ *rc = VIRUS; |
|
3934 | 3934 |
cli_dbgmsg("PH:Phishing found\n"); |
3935 | 3935 |
} |
3936 | 3936 |
} |
3937 |
- if(is_html && (mctx->ctx->options&CL_SCAN_MAILURL) && (*rc != 3)) |
|
3937 |
+ if(is_html && (mctx->ctx->options&CL_SCAN_MAILURL) && (*rc != VIRUS)) |
|
3938 | 3938 |
do_checkURLs(mainMessage, mctx->dir, &hrefs); |
3939 | 3939 |
} |
3940 | 3940 |
hrefs_done(b,&hrefs); |
... | ... |
@@ -4037,7 +4039,7 @@ do_checkURLs(message *m, const char *dir, tag_arguments_t *hrefs) |
4037 | 4037 |
|
4038 | 4038 |
#if defined(FOLLOWURLS) && (FOLLOWURLS > 0) |
4039 | 4039 |
static void |
4040 |
-checkURLs(message *m, mbox_ctx *mctx, int *rc, int is_html) |
|
4040 |
+checkURLs(message *m, mbox_ctx *mctx, mbox_status *rc, int is_html) |
|
4041 | 4041 |
{ |
4042 | 4042 |
blob *b = messageToBlob(m, 0); |
4043 | 4043 |
size_t len; |
... | ... |
@@ -5108,8 +5110,8 @@ exportBounceMessage(text *start, const mbox_ctx *mctx) |
5108 | 5108 |
* won't be scanned |
5109 | 5109 |
*/ |
5110 | 5110 |
for(t = start; t; t = t->t_next) { |
5111 |
- char cmd[RFC2821LENGTH + 1]; |
|
5112 | 5111 |
const char *txt = lineGetData(t->t_line); |
5112 |
+ char cmd[RFC2821LENGTH + 1]; |
|
5113 | 5113 |
|
5114 | 5114 |
if(txt == NULL) |
5115 | 5115 |
continue; |
... | ... |
@@ -5156,7 +5158,7 @@ exportBounceMessage(text *start, const mbox_ctx *mctx) |
5156 | 5156 |
* Handle the ith element of a number of multiparts, e.g. multipart/alternative |
5157 | 5157 |
*/ |
5158 | 5158 |
static message * |
5159 |
-do_multipart(message *mainMessage, message **messages, int i, int *rc, mbox_ctx *mctx, message *messageIn, text **tptr, unsigned int recursion_level) |
|
5159 |
+do_multipart(message *mainMessage, message **messages, int i, mbox_status *rc, mbox_ctx *mctx, message *messageIn, text **tptr, unsigned int recursion_level) |
|
5160 | 5160 |
{ |
5161 | 5161 |
bool addToText = FALSE; |
5162 | 5162 |
const char *dtype; |