Now honours --max-files

git-svn: trunk@3339
remotes/push_mirror/metadata
Nigel Horne 18 years ago
parent 3470220caa
commit 001ad879f6
  1. 4
      ChangeLog
  2. 154
      libclamav/mbox.c
  3. 2
      libclamav/pdf.c

@ -1,3 +1,7 @@
Tue Oct 30 16:35:41 GMT 2007 (njh)
----------------------------------
* libclamav/mbox.c: Now honours --max-files
Tue Oct 30 15:40:49 GMT 2007 (njh)
----------------------------------
* libclamav/pdf.c: Bug 698

@ -125,7 +125,8 @@ typedef enum {
OK,
OK_ATTACHMENTS_NOT_SAVED,
VIRUS,
MAXREC
MAXREC,
MAXFILES
} mbox_status;
#ifndef isblank
@ -213,6 +214,7 @@ typedef unsigned int in_addr_t;
typedef struct mbox_ctx {
const char *dir;
unsigned int files; /* number of files extracted */
const table_t *rfc821Table;
const table_t *subtypeTable;
cli_ctx *ctx;
@ -229,7 +231,7 @@ 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 saveTextPart(message *m, const char *dir, int destroy_text);
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);
#ifdef PARTIAL_DIR
@ -238,8 +240,8 @@ static int rfc1341(message *m, const char *dir);
static bool usefulHeader(int commandNumber, const char *cmd);
static char *getline_from_mbox(char *buffer, size_t len, FILE *fin);
static bool isBounceStart(const char *line);
static bool exportBinhexMessage(const char *dir, message *m);
static int exportBounceMessage(text *start, const mbox_ctx *ctx);
static bool exportBinhexMessage(mbox_ctx *mctx, message *m);
static int exportBounceMessage(mbox_ctx *ctx, text *start);
static message *do_multipart(message *mainMessage, message **messages, int i, mbox_status *rc, mbox_ctx *mctx, message *messageIn, text **tptr, unsigned int recursion_level);
static int count_quotes(const char *buf);
static bool next_is_folded_header(const text *t);
@ -263,8 +265,6 @@ static void *getURL(void *a);
#else
static void *getURL(struct arg *arg);
#endif
static long nonblock_fcntl(SOCKET sock);
static void restore_fcntl(SOCKET sock, long fcntl_flags);
static int nonblock_connect(const char *url, SOCKET sock, const struct sockaddr *addr);
static int connect_error(const char *url, SOCKET sock);
static int my_r_gethostbyname(const char *hostname, struct hostent *hp, char *buf, size_t len);
@ -1267,6 +1267,7 @@ cli_parse_mbox(const char *dir, int desc, cli_ctx *ctx)
mctx.rfc821Table = rfc821;
mctx.subtypeTable = subtype;
mctx.ctx = ctx;
mctx.files = 0;
/*
* Is it a UNIX style mbox with more than one
@ -1274,9 +1275,8 @@ cli_parse_mbox(const char *dir, int desc, cli_ctx *ctx)
*
* TODO: It would be better if we called cli_scandir here rather than
* in cli_scanmail. Then we could improve the way mailboxes with more
* than one message is handled, e.g. stopping parsing when an infected
* message is stopped, and giving a better indication of which message
* within the mailbox is infected
* than one message is handled, e.g. giving a better indication of
* which message within the mailbox is infected
*/
/*if((strncmp(buffer, "From ", 5) == 0) && isalnum(buffer[5])) {*/
if(strncmp(buffer, "From ", 5) == 0) {
@ -1431,6 +1431,9 @@ cli_parse_mbox(const char *dir, int desc, cli_ctx *ctx)
case MAXREC:
retcode = CL_EMAXREC;
break;
case MAXFILES:
retcode = CL_EMAXFILES;
break;
case VIRUS:
retcode = CL_VIRUS;
break;
@ -1892,13 +1895,12 @@ parseEmailHeaders(message *m, const table_t *rfc821)
static int
parseEmailHeader(message *m, const char *line, const table_t *rfc821)
{
char *cmd;
int ret = -1;
int ret;
#ifdef CL_THREAD_SAFE
char *strptr;
#endif
const char *separater;
char *copy, tokenseparater[2];
char *cmd, *copy, tokenseparater[2];
cli_dbgmsg("parseEmailHeader '%s'\n", line);
@ -1923,6 +1925,8 @@ parseEmailHeader(message *m, const char *line, const table_t *rfc821)
tokenseparater[0] = *separater;
tokenseparater[1] = '\0';
ret = -1;
#ifdef CL_THREAD_SAFE
cmd = strtok_r(copy, tokenseparater, &strptr);
#else
@ -1970,24 +1974,36 @@ parseEmailBody(message *messageIn, text *textIn, mbox_ctx *mctx, unsigned int re
fileblob *fb;
bool infected = FALSE;
const int doPhishingScan = mctx->ctx->engine->dboptions&CL_DB_PHISHING_URLS && (DCONF_PHISHING & PHISHING_CONF_ENGINE);
const struct cl_limits *limits = mctx->ctx->limits;
cli_dbgmsg("in parseEmailBody\n");
cli_dbgmsg("in parseEmailBody, %u files saved so far\n",
mctx->files);
if(mctx->ctx->limits && mctx->ctx->limits->maxmailrec) {
const cli_ctx *ctx = mctx->ctx; /* needed for BLOCKMAX :-( */
if(limits) {
if(limits->maxmailrec) {
const cli_ctx *ctx = mctx->ctx; /* needed for BLOCKMAX :-( */
/*
* This is approximate
*/
if(recursion_level > ctx->limits->maxmailrec) {
/*
* This is approximate
*/
if(recursion_level > limits->maxmailrec) {
cli_warnmsg("parseEmailBody: hit maximum recursion level (%u)\n", recursion_level);
if(BLOCKMAX) {
if(ctx->virname)
*ctx->virname = "MIME.RecursionLimit";
return VIRUS;
} else
return MAXREC;
cli_warnmsg("parseEmailBody: hit maximum recursion level (%u)\n", recursion_level);
if(BLOCKMAX) {
if(ctx->virname)
*ctx->virname = "MIME.RecursionLimit";
return VIRUS;
} else
return MAXREC;
}
}
if(limits->maxfiles && (mctx->files >= limits->maxfiles)) {
/*
* FIXME: This is only approx - it may have already
* been exceeded
*/
cli_dbgmsg("parseEmailBody: number of files exceeded %u\n", limits->maxfiles);
return MAXFILES;
}
}
@ -2106,7 +2122,7 @@ parseEmailBody(message *messageIn, text *textIn, mbox_ctx *mctx, unsigned int re
* TODO: check yEnc
*/
if(binhexBegin(mainMessage) == t_line) {
if(exportBinhexMessage(mctx->dir, mainMessage)) {
if(exportBinhexMessage(mctx, mainMessage)) {
/* virus found */
rc = VIRUS;
infected = TRUE;
@ -2682,6 +2698,7 @@ parseEmailBody(message *messageIn, text *textIn, mbox_ctx *mctx, unsigned int re
(void)textToFileblob(aText, fb, 1);
fileblobDestroy(fb);
mctx->files++;
}
textDestroy(aText);
}
@ -2765,6 +2782,7 @@ parseEmailBody(message *messageIn, text *textIn, mbox_ctx *mctx, unsigned int re
cli_dbgmsg("Saving main message as attachment\n");
if(fileblobScanAndDestroy(fb) == CL_VIRUS)
rc = VIRUS;
mctx->files++;
if(mainMessage != messageIn) {
messageDestroy(mainMessage);
mainMessage = NULL;
@ -2930,6 +2948,7 @@ parseEmailBody(message *messageIn, text *textIn, mbox_ctx *mctx, unsigned int re
if(fileblobScanAndDestroy(fb) == CL_VIRUS)
rc = VIRUS;
mctx->files++;
if(topofbounce)
t = topofbounce;
@ -2950,7 +2969,7 @@ parseEmailBody(message *messageIn, text *textIn, mbox_ctx *mctx, unsigned int re
*/
if((encodingLine(mainMessage) != NULL) &&
((t_line = bounceBegin(mainMessage)) != NULL))
rc = (exportBounceMessage(t_line, mctx) == CL_VIRUS) ? VIRUS : OK;
rc = (exportBounceMessage(mctx, t_line) == CL_VIRUS) ? VIRUS : OK;
else {
bool saveIt;
@ -2981,6 +3000,7 @@ parseEmailBody(message *messageIn, text *textIn, mbox_ctx *mctx, unsigned int re
fileblobSetCTX(fb, mctx->ctx);
if(fileblobScanAndDestroy(textToFileblob(t_line, fb, 1)) == CL_VIRUS)
rc = VIRUS;
mctx->files++;
}
saveIt = FALSE;
} else
@ -2994,7 +3014,7 @@ parseEmailBody(message *messageIn, text *textIn, mbox_ctx *mctx, unsigned int re
if(saveIt) {
cli_dbgmsg("Saving text part to scan, rc = %d\n",
(int)rc);
if(saveTextPart(mainMessage, mctx->dir, 1) == CL_VIRUS)
if(saveTextPart(mctx, mainMessage, 1) == CL_VIRUS)
rc = VIRUS;
if(mainMessage != messageIn) {
@ -3479,17 +3499,18 @@ parseMimeHeader(message *m, const char *cmd, const table_t *rfc821Table, const c
* Save the text portion of the message
*/
static int
saveTextPart(message *m, const char *dir, int destroy_text)
saveTextPart(mbox_ctx *mctx, message *m, int destroy_text)
{
fileblob *fb;
messageAddArgument(m, "filename=textportion");
if((fb = messageToFileblob(m, dir, destroy_text)) != NULL) {
if((fb = messageToFileblob(m, mctx->dir, destroy_text)) != NULL) {
/*
* Save main part to scan that
*/
cli_dbgmsg("Saving main message\n");
mctx->files++;
return fileblobScanAndDestroy(fb);
}
return CL_ETMPFILE;
@ -4277,14 +4298,27 @@ getURL(struct arg *arg)
fclose(fp);
return NULL;
}
#ifdef F_GETFL
flags = fcntl(sd, F_GETFL, 0);
if(flags == -1L)
cli_warnmsg("getfl: %s\n", strerror(errno));
else if(fcntl(sd, F_SETFL, (long)(flags | O_NONBLOCK)) < 0)
cli_warnmsg("setfl: %s\n", strerror(errno));
#else
flags = -1L;
#endif
server.sin_addr.s_addr = ip;
flags = nonblock_fcntl(sd);
if(nonblock_connect(url, sd, (struct sockaddr *)&server) < 0) {
closesocket(sd);
fclose(fp);
return NULL;
}
restore_fcntl(sd, flags);
#ifdef F_SETFL
if(flags != -1L)
if(fcntl(sd, F_SETFL, flags))
cli_warnmsg("f_setfl: %s\n", strerror(errno));
#endif
/*
* TODO: consider HTTP/1.1
@ -4488,40 +4522,6 @@ my_r_gethostbyname(const char *hostname, struct hostent *hp, char *buf, size_t l
* Non-blocking connect, based on an idea by Everton da Silva Marques
* <everton.marques@gmail.com>
*/
/*
* Returns the fcntl flags on the given socket
*/
static long
nonblock_fcntl(SOCKET sock)
{
#ifdef F_GETFL
int fcntl_flags = fcntl(sock, F_GETFL, 0);
if(fcntl_flags == -1)
cli_warnmsg("getfl: %s\n", strerror(errno));
else if(fcntl(sock, F_SETFL, (long)fcntl_flags | O_NONBLOCK) < 0)
cli_warnmsg("setfl: %s\n", strerror(errno));
return (long)fcntl_flags;
#else
return -1L;
#endif
}
/*
* Restores the fcntl flags on the given socket
*/
static void
restore_fcntl(SOCKET sock, long fcntl_flags)
{
#ifdef F_SETFL
if(fcntl_flags != -1L)
if(fcntl(sock, F_SETFL, fcntl_flags))
cli_warnmsg("setfl: %s\n", strerror(errno));
#endif
}
static int
nonblock_connect(const char *url, SOCKET sock, const struct sockaddr *addr)
{
@ -4796,7 +4796,7 @@ isBounceStart(const char *line)
* extract it
*/
static bool
exportBinhexMessage(const char *dir, message *m)
exportBinhexMessage(mbox_ctx *mctx, message *m)
{
bool infected = FALSE;
fileblob *fb;
@ -4804,7 +4804,7 @@ exportBinhexMessage(const char *dir, message *m)
if(messageGetEncoding(m) == NOENCODING)
messageSetEncoding(m, "x-binhex");
fb = messageToFileblob(m, dir, 0);
fb = messageToFileblob(m, mctx->dir, 0);
if(fb) {
cli_dbgmsg("Binhex file decoded to %s\n",
@ -4812,8 +4812,9 @@ exportBinhexMessage(const char *dir, message *m)
if(fileblobScanAndDestroy(fb) == CL_VIRUS)
infected = TRUE;
mctx->files++;
} else
cli_errmsg("Couldn't decode binhex file to %s\n", dir);
cli_errmsg("Couldn't decode binhex file to %s\n", mctx->dir);
return infected;
}
@ -4822,7 +4823,7 @@ exportBinhexMessage(const char *dir, message *m)
* Locate any bounce message and extract it. Return cl_status
*/
static int
exportBounceMessage(text *start, const mbox_ctx *mctx)
exportBounceMessage(mbox_ctx *mctx, text *start)
{
int rc = CL_CLEAN;
text *t;
@ -4886,6 +4887,7 @@ exportBounceMessage(text *start, const mbox_ctx *mctx)
fileblobDestroy(fb);
} else
rc = fileblobScanAndDestroy(fb);
mctx->files++;
} else
cli_dbgmsg("Not found a bounce message\n");
@ -4927,7 +4929,7 @@ do_multipart(message *mainMessage, message **messages, int i, mbox_status *rc, m
if(binhexBegin(aMessage)) {
cli_dbgmsg("Found binhex message in multipart/mixed mainMessage\n");
if(exportBinhexMessage(mctx->dir, mainMessage))
if(exportBinhexMessage(mctx, mainMessage))
*rc = VIRUS;
}
if(mainMessage != messageIn)
@ -4936,7 +4938,7 @@ do_multipart(message *mainMessage, message **messages, int i, mbox_status *rc, m
} else if(aMessage) {
if(binhexBegin(aMessage)) {
cli_dbgmsg("Found binhex message in multipart/mixed non mime part\n");
if(exportBinhexMessage(mctx->dir, aMessage))
if(exportBinhexMessage(mctx, aMessage))
*rc = VIRUS;
assert(aMessage == messages[i]);
messageReset(messages[i]);
@ -5028,7 +5030,7 @@ do_multipart(message *mainMessage, message **messages, int i, mbox_status *rc, m
* Save this embedded message
* to a temporary file
*/
if(saveTextPart(aMessage, mctx->dir, 1) == CL_VIRUS)
if(saveTextPart(mctx, aMessage, 1) == CL_VIRUS)
*rc = VIRUS;
assert(aMessage == messages[i]);
messageDestroy(messages[i]);
@ -5098,9 +5100,11 @@ do_multipart(message *mainMessage, message **messages, int i, mbox_status *rc, m
} else {
fileblob *fb = messageToFileblob(aMessage, mctx->dir, 1);
if(fb)
if(fb) {
if(fileblobScanAndDestroy(fb) == CL_VIRUS)
*rc = VIRUS;
mctx->files++;
}
}
if(messageContainsVirus(aMessage))
*rc = VIRUS;

@ -520,7 +520,7 @@ cli_pdf(const char *dir, int desc, const cli_ctx *ctx)
if(limits && limits->maxfiles && (files >= limits->maxfiles)) {
/* Bug 698 */
cli_dbgmsg("cli_pdf: number of files exceeded %u\n", limits->maxfiles);
break;
rc = CL_EMAXFILES;
}
}

Loading…
Cancel
Save