git-svn: trunk@3203
Nigel Horne authored on 2007/09/04 18:43:40... | ... |
@@ -1,7 +1,11 @@ |
1 |
+Tue Sep 4 09:52:10 BST 2007 (njh) |
|
2 |
+---------------------------------- |
|
3 |
+ * libclamav/mbox.c: Partial dir: plug leak on error and code tidy |
|
4 |
+ |
|
1 | 5 |
Tue Sep 4 01:31:23 CEST 2007 (acab) |
2 | 6 |
------------------------------------ |
3 | 7 |
* libclamav:pe.c General "tidy" and some algo hacks. Old and inefficient |
4 |
- sue cryptor replaced with a signature. |
|
8 |
+ sue cryptor replaced with a signature. |
|
5 | 9 |
|
6 | 10 |
Sun Sep 2 12:41:46 BST 2007 (njh) |
7 | 11 |
---------------------------------- |
... | ... |
@@ -156,8 +156,9 @@ typedef enum { |
156 | 156 |
#endif |
157 | 157 |
#endif |
158 | 158 |
|
159 |
-#ifndef C_WINDOWS |
|
159 |
+#if (!defined(C_WINDOWS)) && !defined(C_BEOS) |
|
160 | 160 |
#define closesocket(s) close(s) |
161 |
+#define SOCKET int |
|
161 | 162 |
#endif |
162 | 163 |
|
163 | 164 |
#include <fcntl.h> |
... | ... |
@@ -221,7 +222,7 @@ static int initialiseTables(table_t **rfc821Table, table_t **subtypeTable); |
221 | 221 |
static int getTextPart(message *const messages[], size_t size); |
222 | 222 |
static size_t strip(char *buf, int len); |
223 | 223 |
static int parseMimeHeader(message *m, const char *cmd, const table_t *rfc821Table, const char *arg); |
224 |
-static void saveTextPart(message *m, const char *dir, int destroy_text); |
|
224 |
+static int saveTextPart(message *m, const char *dir, int destroy_text); |
|
225 | 225 |
static char *rfc2047(const char *in); |
226 | 226 |
static char *rfc822comments(const char *in, char *out); |
227 | 227 |
#ifdef PARTIAL_DIR |
... | ... |
@@ -255,14 +256,14 @@ static void *getURL(void *a); |
255 | 255 |
#else |
256 | 256 |
static void *getURL(struct arg *arg); |
257 | 257 |
#endif |
258 |
-static long nonblock_fcntl(int sock); |
|
259 |
-static void restore_fcntl(int sock, long fcntl_flags); |
|
260 |
-static int nonblock_connect(const char *url, int sock, const struct sockaddr *addr); |
|
261 |
-static int connect_error(const char *url, int sock); |
|
258 |
+static long nonblock_fcntl(SOCKET sock); |
|
259 |
+static void restore_fcntl(SOCKET sock, long fcntl_flags); |
|
260 |
+static int nonblock_connect(const char *url, SOCKET sock, const struct sockaddr *addr); |
|
261 |
+static int connect_error(const char *url, SOCKET sock); |
|
262 | 262 |
static int my_r_gethostbyname(const char *hostname, struct hostent *hp, char *buf, size_t len); |
263 | 263 |
|
264 | 264 |
#define NONBLOCK_SELECT_MAX_FAILURES 3 |
265 |
-#define NONBLOCK_MAX_BOGUS_LOOPS 10 |
|
265 |
+#define NONBLOCK_MAX_ATTEMPTS 10 |
|
266 | 266 |
|
267 | 267 |
#endif |
268 | 268 |
|
... | ... |
@@ -1313,7 +1314,7 @@ cli_parse_mbox(const char *dir, int desc, cli_ctx *ctx) |
1313 | 1313 |
cli_chomp(buffer); |
1314 | 1314 |
/*if(lastLineWasEmpty && (strncmp(buffer, "From ", 5) == 0) && isalnum(buffer[5])) {*/ |
1315 | 1315 |
if(lastLineWasEmpty && (strncmp(buffer, "From ", 5) == 0)) { |
1316 |
- cli_dbgmsg("Deal with email number %d\n", messagenumber++); |
|
1316 |
+ cli_dbgmsg("Deal with message number %d\n", messagenumber++); |
|
1317 | 1317 |
/* |
1318 | 1318 |
* End of a message in the mail box |
1319 | 1319 |
*/ |
... | ... |
@@ -2908,11 +2909,6 @@ parseEmailBody(message *messageIn, text *textIn, mbox_ctx *mctx, unsigned int re |
2908 | 2908 |
|
2909 | 2909 |
if(topofbounce) |
2910 | 2910 |
t = topofbounce; |
2911 |
- /* |
|
2912 |
- * Don't do this - it slows bugs.txt |
|
2913 |
- */ |
|
2914 |
- /*if(mainMessage) |
|
2915 |
- mainMessage->bounce = NULL;*/ |
|
2916 | 2911 |
} |
2917 | 2912 |
textDestroy(aText); |
2918 | 2913 |
aText = NULL; |
... | ... |
@@ -2929,10 +2925,9 @@ parseEmailBody(message *messageIn, text *textIn, mbox_ctx *mctx, unsigned int re |
2929 | 2929 |
* Look for uu-encoded main file |
2930 | 2930 |
*/ |
2931 | 2931 |
if((encodingLine(mainMessage) != NULL) && |
2932 |
- ((t_line = bounceBegin(mainMessage)) != NULL)) { |
|
2933 |
- if(exportBounceMessage(t_line, mctx)) |
|
2934 |
- rc = OK; |
|
2935 |
- } else { |
|
2932 |
+ ((t_line = bounceBegin(mainMessage)) != NULL)) |
|
2933 |
+ rc = (exportBounceMessage(t_line, mctx) == CL_VIRUS) ? VIRUS : OK; |
|
2934 |
+ else { |
|
2936 | 2935 |
bool saveIt; |
2937 | 2936 |
|
2938 | 2937 |
if(messageGetMimeType(mainMessage) == MESSAGE) |
... | ... |
@@ -2959,8 +2954,9 @@ parseEmailBody(message *messageIn, text *textIn, mbox_ctx *mctx, unsigned int re |
2959 | 2959 |
(const unsigned char *)"Received: by clamd (bounce)\n", |
2960 | 2960 |
28); |
2961 | 2961 |
|
2962 |
- /*fileblobSetCTX(fb, ctx);*/ |
|
2963 |
- fileblobDestroy(textToFileblob(t_line, fb, 1)); |
|
2962 |
+ fileblobSetCTX(fb, mctx->ctx); |
|
2963 |
+ if(fileblobScanAndDestroy(textToFileblob(t_line, fb, 1)) == CL_VIRUS) |
|
2964 |
+ rc = VIRUS; |
|
2964 | 2965 |
} |
2965 | 2966 |
saveIt = FALSE; |
2966 | 2967 |
} else |
... | ... |
@@ -2972,14 +2968,16 @@ parseEmailBody(message *messageIn, text *textIn, mbox_ctx *mctx, unsigned int re |
2972 | 2972 |
saveIt = TRUE; |
2973 | 2973 |
|
2974 | 2974 |
if(saveIt) { |
2975 |
- cli_dbgmsg("Saving text part to scan\n"); |
|
2976 |
- saveTextPart(mainMessage, mctx->dir, 1); |
|
2975 |
+ cli_dbgmsg("Saving text part to scan, rc = %d\n", |
|
2976 |
+ rc); |
|
2977 |
+ if(saveTextPart(mainMessage, mctx->dir, 1) == CL_VIRUS) |
|
2978 |
+ rc = VIRUS; |
|
2979 |
+ |
|
2977 | 2980 |
if(mainMessage != messageIn) { |
2978 | 2981 |
messageDestroy(mainMessage); |
2979 | 2982 |
mainMessage = NULL; |
2980 | 2983 |
} else |
2981 | 2984 |
messageReset(mainMessage); |
2982 |
- rc = OK; |
|
2983 | 2985 |
} |
2984 | 2986 |
} |
2985 | 2987 |
} /*else |
... | ... |
@@ -3439,7 +3437,7 @@ parseMimeHeader(message *m, const char *cmd, const table_t *rfc821Table, const c |
3439 | 3439 |
/* |
3440 | 3440 |
* Save the text portion of the message |
3441 | 3441 |
*/ |
3442 |
-static void |
|
3442 |
+static int |
|
3443 | 3443 |
saveTextPart(message *m, const char *dir, int destroy_text) |
3444 | 3444 |
{ |
3445 | 3445 |
fileblob *fb; |
... | ... |
@@ -3451,8 +3449,9 @@ saveTextPart(message *m, const char *dir, int destroy_text) |
3451 | 3451 |
*/ |
3452 | 3452 |
cli_dbgmsg("Saving main message\n"); |
3453 | 3453 |
|
3454 |
- fileblobDestroy(fb); |
|
3454 |
+ return fileblobScanAndDestroy(fb); |
|
3455 | 3455 |
} |
3456 |
+ return CL_ETMPFILE; |
|
3456 | 3457 |
} |
3457 | 3458 |
|
3458 | 3459 |
/* |
... | ... |
@@ -3672,13 +3671,16 @@ rfc1341(message *m, const char *dir) |
3672 | 3672 |
snprintf(pdir, sizeof(pdir) - 1, "%s/clamav-partial", tmpdir); |
3673 | 3673 |
|
3674 | 3674 |
if((mkdir(pdir, 0700) < 0) && (errno != EEXIST)) { |
3675 |
+ free(id); |
|
3675 | 3676 |
cli_errmsg("Can't create the directory '%s'\n", pdir); |
3676 | 3677 |
return -1; |
3677 |
- } else { |
|
3678 |
+ } else if(errno == EEXIST) { |
|
3678 | 3679 |
struct stat statb; |
3679 | 3680 |
|
3680 | 3681 |
if(stat(pdir, &statb) < 0) { |
3681 |
- cli_errmsg("Can't stat the directory '%s'\n", pdir); |
|
3682 |
+ free(id); |
|
3683 |
+ cli_errmsg("partial directory %s: %s\n", pdir, |
|
3684 |
+ strerror(errno)); |
|
3682 | 3685 |
return -1; |
3683 | 3686 |
} |
3684 | 3687 |
if(statb.st_mode & 077) |
... | ... |
@@ -3889,7 +3891,7 @@ getHrefs(message *m, tag_arguments_t *hrefs) |
3889 | 3889 |
} |
3890 | 3890 |
|
3891 | 3891 |
/* |
3892 |
- * Experimental: validate URLs for phishes |
|
3892 |
+ * validate URLs for phishes |
|
3893 | 3893 |
* followurls: see if URLs point to malware |
3894 | 3894 |
*/ |
3895 | 3895 |
static void |
... | ... |
@@ -3898,6 +3900,9 @@ checkURLs(message *mainMessage, mbox_ctx *mctx, mbox_status *rc, int is_html) |
3898 | 3898 |
blob *b; |
3899 | 3899 |
tag_arguments_t hrefs; |
3900 | 3900 |
|
3901 |
+ if(*rc == VIRUS) |
|
3902 |
+ return; |
|
3903 |
+ |
|
3901 | 3904 |
hrefs.scanContents = mctx->ctx->engine->dboptions&CL_DB_PHISHING_URLS && (DCONF_PHISHING & PHISHING_CONF_ENGINE); |
3902 | 3905 |
|
3903 | 3906 |
#if (!defined(FOLLOWURLS)) || (FOLLOWURLS <= 0) |
... | ... |
@@ -3928,7 +3933,6 @@ checkURLs(message *mainMessage, mbox_ctx *mctx, mbox_status *rc, int is_html) |
3928 | 3928 |
hrefs_done(b,&hrefs); |
3929 | 3929 |
} |
3930 | 3930 |
|
3931 |
- |
|
3932 | 3931 |
#if defined(FOLLOWURLS) && (FOLLOWURLS > 0) |
3933 | 3932 |
static void |
3934 | 3933 |
do_checkURLs(const char *dir, tag_arguments_t *hrefs) |
... | ... |
@@ -4034,11 +4038,6 @@ do_checkURLs(const char *dir, tag_arguments_t *hrefs) |
4034 | 4034 |
*/ |
4035 | 4035 |
|
4036 | 4036 |
/* |
4037 |
- * Removing the reliance on libcurl |
|
4038 |
- * Includes some of the freshclam hacks by Everton da Silva Marques |
|
4039 |
- * everton.marques@gmail.com> |
|
4040 |
- */ |
|
4041 |
-/* |
|
4042 | 4037 |
* Simple implementation of a subset of RFC1945 (HTTP/1.0) |
4043 | 4038 |
* TODO: HTTP/1.1 (RFC2068) |
4044 | 4039 |
*/ |
... | ... |
@@ -4056,11 +4055,7 @@ getURL(struct arg *arg) |
4056 | 4056 |
const char *url = arg->url; |
4057 | 4057 |
const char *dir = arg->dir; |
4058 | 4058 |
const char *filename = arg->filename; |
4059 |
-#ifdef C_WINDOWS |
|
4060 | 4059 |
SOCKET sd; |
4061 |
-#else |
|
4062 |
- int sd; |
|
4063 |
-#endif |
|
4064 | 4060 |
struct sockaddr_in server; |
4065 | 4061 |
#ifdef HAVE_IN_ADDR_T |
4066 | 4062 |
in_addr_t ip; |
... | ... |
@@ -4255,7 +4250,7 @@ getURL(struct arg *arg) |
4255 | 4255 |
tv.tv_sec = 30; /* FIXME: make this customisable */ |
4256 | 4256 |
tv.tv_usec = 0; |
4257 | 4257 |
|
4258 |
- if(select(sd + 1, &set, NULL, NULL, &tv) < 0) { |
|
4258 |
+ if(select((int)sd + 1, &set, NULL, NULL, &tv) < 0) { |
|
4259 | 4259 |
if(errno == EINTR) |
4260 | 4260 |
continue; |
4261 | 4261 |
closesocket(sd); |
... | ... |
@@ -4414,18 +4409,24 @@ my_r_gethostbyname(const char *hostname, struct hostent *hp, char *buf, size_t l |
4414 | 4414 |
return 0; |
4415 | 4415 |
} |
4416 | 4416 |
|
4417 |
+/* |
|
4418 |
+ * Non-blocking connect, based on an idea by Everton da Silva Marques |
|
4419 |
+ * <everton.marques@gmail.com> |
|
4420 |
+ */ |
|
4421 |
+ |
|
4422 |
+/* |
|
4423 |
+ * Returns the fcntl flags on the given socket |
|
4424 |
+ */ |
|
4417 | 4425 |
static long |
4418 |
-nonblock_fcntl(int sock) |
|
4426 |
+nonblock_fcntl(SOCKET sock) |
|
4419 | 4427 |
{ |
4420 | 4428 |
#ifdef F_GETFL |
4421 |
- int fcntl_flags = fcntl(sock, F_GETFL, 0); /* Save fcntl() flags */ |
|
4429 |
+ int fcntl_flags = fcntl(sock, F_GETFL, 0); |
|
4422 | 4430 |
|
4423 |
- if(fcntl_flags < 0) |
|
4424 |
- cli_warnmsg("nonblock_fcntl: saving: fcntl(%d, F_GETFL): errno=%d: %s\n", |
|
4425 |
- sock, errno, strerror(errno)); |
|
4431 |
+ if(fcntl_flags == -1) |
|
4432 |
+ cli_warnmsg("getfl: %s\n", strerror(errno)); |
|
4426 | 4433 |
else if(fcntl(sock, F_SETFL, (long)fcntl_flags | O_NONBLOCK) < 0) |
4427 |
- cli_warnmsg("nonblock_fcntl: fcntl(%d, F_SETFL, O_NONBLOCK): errno=%d: %s\n", |
|
4428 |
- sock, errno, strerror(errno)); |
|
4434 |
+ cli_warnmsg("setfl: %s\n", strerror(errno)); |
|
4429 | 4435 |
|
4430 | 4436 |
return (long)fcntl_flags; |
4431 | 4437 |
#else |
... | ... |
@@ -4433,28 +4434,28 @@ nonblock_fcntl(int sock) |
4433 | 4433 |
#endif |
4434 | 4434 |
} |
4435 | 4435 |
|
4436 |
+/* |
|
4437 |
+ * Restores the fcntl flags on the given socket |
|
4438 |
+ */ |
|
4436 | 4439 |
static void |
4437 |
-restore_fcntl(int sock, long fcntl_flags) |
|
4440 |
+restore_fcntl(SOCKET sock, long fcntl_flags) |
|
4438 | 4441 |
{ |
4439 | 4442 |
#ifdef F_SETFL |
4440 | 4443 |
if(fcntl_flags != -1L) |
4441 |
- if(fcntl(sock, F_SETFL, fcntl_flags)) { |
|
4442 |
- cli_warnmsg("restore_fcntl: restoring: fcntl(%d, F_SETFL): errno=%d: %s\n", |
|
4443 |
- sock, errno, strerror(errno)); |
|
4444 |
- } |
|
4444 |
+ if(fcntl(sock, F_SETFL, fcntl_flags)) |
|
4445 |
+ cli_warnmsg("setfl: %s\n", strerror(errno)); |
|
4445 | 4446 |
#endif |
4446 | 4447 |
} |
4447 | 4448 |
|
4448 | 4449 |
static int |
4449 |
-nonblock_connect(const char *url, int sock, const struct sockaddr *addr) |
|
4450 |
+nonblock_connect(const char *url, SOCKET sock, const struct sockaddr *addr) |
|
4450 | 4451 |
{ |
4451 | 4452 |
int select_failures; /* Max. of unexpected select() failures */ |
4452 |
- int bogus_loops; /* Max. of useless loops */ |
|
4453 |
+ int attempts; |
|
4453 | 4454 |
struct timeval timeout; /* When we should time out */ |
4454 | 4455 |
int numfd; /* Highest fdset fd plus 1 */ |
4455 | 4456 |
|
4456 |
- /* Calculate into 'timeout' when we should time out */ |
|
4457 |
- gettimeofday(&timeout, 0); |
|
4457 |
+ gettimeofday(&timeout, 0); /* store when we started to connect */ |
|
4458 | 4458 |
|
4459 | 4459 |
if(connect(sock, addr, sizeof(struct sockaddr_in)) != 0) |
4460 | 4460 |
switch(errno) { |
... | ... |
@@ -4471,9 +4472,9 @@ nonblock_connect(const char *url, int sock, const struct sockaddr *addr) |
4471 | 4471 |
else |
4472 | 4472 |
return connect_error(url, sock); |
4473 | 4473 |
|
4474 |
- numfd = sock + 1; /* Highest fdset fd plus 1 */ |
|
4474 |
+ numfd = (int)sock + 1; |
|
4475 | 4475 |
select_failures = NONBLOCK_SELECT_MAX_FAILURES; |
4476 |
- bogus_loops = NONBLOCK_MAX_BOGUS_LOOPS; |
|
4476 |
+ attempts = 1; |
|
4477 | 4477 |
timeout.tv_sec += URL_TIMEOUT; |
4478 | 4478 |
|
4479 | 4479 |
for (;;) { |
... | ... |
@@ -4510,7 +4511,7 @@ nonblock_connect(const char *url, int sock, const struct sockaddr *addr) |
4510 | 4510 |
cli_warnmsg("%s: select attempt %d %s\n", |
4511 | 4511 |
url, select_failures, strerror(errno)); |
4512 | 4512 |
if(--select_failures >= 0) |
4513 |
- continue; /* keep waiting */ |
|
4513 |
+ continue; /* not timed-out, try again */ |
|
4514 | 4514 |
break; /* failed */ |
4515 | 4515 |
} |
4516 | 4516 |
|
... | ... |
@@ -4520,19 +4521,17 @@ nonblock_connect(const char *url, int sock, const struct sockaddr *addr) |
4520 | 4520 |
return connect_error(url, sock); |
4521 | 4521 |
|
4522 | 4522 |
/* timeout */ |
4523 |
- if(--bogus_loops < 0) { |
|
4524 |
- cli_warnmsg("%s: giving up due to excessive bogus loops\n", |
|
4525 |
- url); |
|
4526 |
- break; /* failed */ |
|
4523 |
+ if(attempts++ == NONBLOCK_MAX_ATTEMPTS) { |
|
4524 |
+ cli_warnmsg("timeout connecting to %s\n", url); |
|
4525 |
+ break; |
|
4527 | 4526 |
} |
4528 |
- |
|
4529 |
- } /* for loop: keep waiting */ |
|
4527 |
+ } |
|
4530 | 4528 |
|
4531 | 4529 |
return -1; /* failed */ |
4532 | 4530 |
} |
4533 | 4531 |
|
4534 | 4532 |
static int |
4535 |
-connect_error(const char *url, int sock) |
|
4533 |
+connect_error(const char *url, SOCKET sock) |
|
4536 | 4534 |
{ |
4537 | 4535 |
#ifdef SO_ERROR |
4538 | 4536 |
int optval; |
... | ... |
@@ -4734,12 +4733,12 @@ exportBinhexMessage(const char *dir, message *m) |
4734 | 4734 |
} |
4735 | 4735 |
|
4736 | 4736 |
/* |
4737 |
- * Locate any bounce message and extract it. Return 1 if anything found |
|
4737 |
+ * Locate any bounce message and extract it. Return cl_status |
|
4738 | 4738 |
*/ |
4739 | 4739 |
static int |
4740 | 4740 |
exportBounceMessage(text *start, const mbox_ctx *mctx) |
4741 | 4741 |
{ |
4742 |
- int rc = 0; |
|
4742 |
+ int rc = CL_CLEAN; |
|
4743 | 4743 |
text *t; |
4744 | 4744 |
fileblob *fb; |
4745 | 4745 |
|
... | ... |
@@ -4795,12 +4794,12 @@ exportBounceMessage(text *start, const mbox_ctx *mctx) |
4795 | 4795 |
if(t && ((fb = fileblobCreate()) != NULL)) { |
4796 | 4796 |
cli_dbgmsg("Found a bounce message\n"); |
4797 | 4797 |
fileblobSetFilename(fb, mctx->dir, "bounce"); |
4798 |
- /*fileblobSetCTX(fb, mctx->ctx);*/ |
|
4799 |
- if(textToFileblob(start, fb, 1) == NULL) |
|
4798 |
+ fileblobSetCTX(fb, mctx->ctx); |
|
4799 |
+ if(textToFileblob(start, fb, 1) == NULL) { |
|
4800 | 4800 |
cli_dbgmsg("Nothing new to save in the bounce message\n"); |
4801 |
- else |
|
4802 |
- rc = 1; |
|
4803 |
- fileblobDestroy(fb); |
|
4801 |
+ fileblobDestroy(fb); |
|
4802 |
+ } else |
|
4803 |
+ rc = fileblobScanAndDestroy(fb); |
|
4804 | 4804 |
} else |
4805 | 4805 |
cli_dbgmsg("Not found a bounce message\n"); |
4806 | 4806 |
|
... | ... |
@@ -4819,7 +4818,6 @@ do_multipart(message *mainMessage, message **messages, int i, mbox_status *rc, m |
4819 | 4819 |
message *body; |
4820 | 4820 |
#endif |
4821 | 4821 |
message *aMessage = messages[i]; |
4822 |
- |
|
4823 | 4822 |
const int doPhishingScan = mctx->ctx->engine->dboptions&CL_DB_PHISHING_URLS && (DCONF_PHISHING&PHISHING_CONF_ENGINE); |
4824 | 4823 |
|
4825 | 4824 |
if(aMessage == NULL) |
... | ... |
@@ -4955,7 +4953,8 @@ do_multipart(message *mainMessage, message **messages, int i, mbox_status *rc, m |
4955 | 4955 |
* Save this embedded message |
4956 | 4956 |
* to a temporary file |
4957 | 4957 |
*/ |
4958 |
- saveTextPart(aMessage, mctx->dir, 1); |
|
4958 |
+ if(saveTextPart(aMessage, mctx->dir, 1) == CL_VIRUS) |
|
4959 |
+ *rc = VIRUS; |
|
4959 | 4960 |
assert(aMessage == messages[i]); |
4960 | 4961 |
messageDestroy(messages[i]); |
4961 | 4962 |
messages[i] = NULL; |