Use fileblob

git-svn: trunk@778
remotes/push_mirror/metadata
Nigel Horne 22 years ago
parent 3e92581eb9
commit 0e5a0129a0
  1. 6
      clamav-devel/ChangeLog
  2. 151
      clamav-devel/libclamav/blob.c
  3. 22
      clamav-devel/libclamav/blob.h
  4. 111
      clamav-devel/libclamav/mbox.c
  5. 57
      clamav-devel/libclamav/message.c
  6. 5
      clamav-devel/libclamav/message.h
  7. 31
      clamav-devel/libclamav/text.c
  8. 4
      clamav-devel/libclamav/text.h

@ -1,3 +1,9 @@
Sun Aug 22 11:35:30 BST 2004 (njh)
----------------------------------
* libclamav: Save email attachments to disc earlier (as the attachment is
decoded rather than after decoding has finished), this
saves memory at a small speed penalty
Sun Aug 22 02:07:13 CEST 2004 (tk)
----------------------------------
* freshclam: Support version verification through DNS (DNSDatabaseInfo).

@ -16,6 +16,9 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* $Log: blob.c,v $
* Revision 1.15 2004/08/22 10:34:24 nigelhorne
* Use fileblob
*
* Revision 1.14 2004/08/01 08:20:58 nigelhorne
* Scan pathnames in Cygwin
*
@ -44,17 +47,23 @@
* Change LOG to Log
*
*/
static char const rcsid[] = "$Id: blob.c,v 1.14 2004/08/01 08:20:58 nigelhorne Exp $";
static char const rcsid[] = "$Id: blob.c,v 1.15 2004/08/22 10:34:24 nigelhorne Exp $";
#if HAVE_CONFIG_H
#include "clamav-config.h"
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <sys/param.h> /* for NAME_MAX */
#if C_DARWIN
#include <sys/types.h>
#endif
#include "mbox.h"
#include "blob.h"
#include "others.h"
@ -148,7 +157,7 @@ blobGetFilename(const blob *b)
assert(b != NULL);
assert(b->magic == BLOB);
return(b->name);
return b->name;
}
void
@ -286,3 +295,141 @@ blobGrow(blob *b, size_t len)
}
}
}
fileblob *
fileblobCreate(void)
{
#ifdef CL_DEBUG
fileblob *fb = (fileblob *)cli_calloc(1, sizeof(fileblob));
if(fb)
fb->b.magic = BLOB;
cli_dbgmsg("blobCreate\n");
return fb;
#else
return (fileblob *)cli_calloc(1, sizeof(fileblob));
#endif
}
void
fileblobDestroy(fileblob *fb)
{
assert(fb != NULL);
if(fb->b.name) {
assert(fb->fp != NULL);
fclose(fb->fp);
free(fb->b.name);
assert(fb->b.data == NULL);
} else if(fb->b.data) {
cli_errmsg("fileblobDestroy: file not saved: report to bugs@clamav.net\n");
free(fb->b.data);
}
free(fb);
}
void
fileblobSetFilename(fileblob *fb, const char *dir, const char *filename)
{
int fd;
const char *suffix;
size_t suffixLen = 0;
char fullname[NAME_MAX + 1];
if(fb->b.name)
return;
/*
* Some programs are broken and use an idea of a ".suffix"
* to determine the file type rather than looking up the
* magic number. CPM has a lot to answer for...
* FIXME: the suffix now appears twice in the filename...
*/
suffix = strrchr(filename, '.');
if(suffix == NULL)
suffix = "";
else {
suffixLen = strlen(suffix);
if(suffixLen > 4) {
/* Found a full stop which isn't a suffix */
suffix = "";
suffixLen = 0;
}
}
blobSetFilename(&fb->b, filename);
/*
* Reload the filename, it may be different from the one we've
* asked for, e.g. '/'s taken out
*/
filename = blobGetFilename(&fb->b);
snprintf(fullname, sizeof(fullname) - 1 - suffixLen, "%s/%.*sXXXXXX", dir,
(int)(sizeof(fullname) - 9 - suffixLen - strlen(dir)), filename);
#if defined(C_LINUX) || defined(C_BSD) || defined(HAVE_MKSTEMP) || defined(C_SOLARIS) || defined(C_CYGWIN)
fd = mkstemp(fullname);
#else
(void)mktemp(fullname);
fd = open(fullname, O_WRONLY|O_CREAT|O_EXCL|O_TRUNC|O_BINARY, 0600);
#endif
if(fd < 0) {
cli_errmsg("Can't create temporary file %s: %s\n", fullname, strerror(errno));
cli_dbgmsg("%lu %d %d\n", suffixLen, sizeof(fullname), strlen(fullname));
return;
}
cli_dbgmsg("Saving attachment as %s\n", fullname);
fb->fp = fdopen(fd, "wb");
if(fb->fp == NULL) {
cli_errmsg("Can't create file %s: %s\n", fullname, strerror(errno));
cli_dbgmsg("%lu %d %d\n", suffixLen, sizeof(fullname), strlen(fullname));
close(fd);
return;
}
if(fb->b.data) {
if(fwrite(fb->b.data, fb->b.len, 1, fb->fp) != 1)
cli_errmsg("fileblobSetFilename: Can't write to temporary file %s: %s\n", fb->b.name, strerror(errno));
free(fb->b.data);
fb->b.data = NULL;
fb->b.len = fb->b.size = 0;
}
/*
* Add the suffix back to the end of the filename. Tut-tut, filenames
* should be independant of their usage on UNIX type systems.
*/
if(suffixLen > 1) {
char stub[NAME_MAX + 1];
snprintf(stub, sizeof(stub), "%s%s", fullname, suffix);
#ifdef C_LINUX
rename(stub, fullname);
#else
link(stub, fullname);
unlink(stub);
#endif
}
}
void
fileblobAddData(fileblob *fb, const unsigned char *data, size_t len)
{
if(len == 0)
return;
if(fb->fp) {
if(fwrite(data, len, 1, fb->fp) != 1)
cli_errmsg("fileblobAddData: Can't write %u bytes to temporary file %s: %s\n", len, fb->b.name, strerror(errno));
} else
blobAddData(&(fb->b), data, len);
}
const char *
fileblobGetFilename(const fileblob *fb)
{
return blobGetFilename(&(fb->b));
}

@ -18,6 +18,12 @@
* $LOG$
*/
#ifndef __BLOB_H
#define __BLOB_H
/*
* Resizable chunk of memory
*/
typedef struct blob {
char *name; /* filename */
unsigned char *data; /* the stuff itself */
@ -40,3 +46,19 @@ unsigned long blobGetDataSize(const blob *b);
void blobClose(blob *b);
int blobcmp(const blob *b1, const blob *b2);
void blobGrow(blob *b, size_t len);
/*
* Like a blob, but associated with a file
*/
typedef struct fileblob {
FILE *fp;
blob b;
} fileblob;
fileblob *fileblobCreate(void);
void fileblobDestroy(fileblob *fb);
void fileblobSetFilename(fileblob *fb, const char *dir, const char *filename);
const char *fileblobGetFilename(const fileblob *fb);
void fileblobAddData(fileblob *fb, const unsigned char *data, size_t len);
#endif /*_BLOB_H*/

@ -17,6 +17,9 @@
*
* Change History:
* $Log: mbox.c,v $
* Revision 1.109 2004/08/22 10:34:24 nigelhorne
* Use fileblob
*
* Revision 1.108 2004/08/21 11:57:57 nigelhorne
* Use line.[ch]
*
@ -312,7 +315,7 @@
* Compilable under SCO; removed duplicate code with message.c
*
*/
static char const rcsid[] = "$Id: mbox.c,v 1.108 2004/08/21 11:57:57 nigelhorne Exp $";
static char const rcsid[] = "$Id: mbox.c,v 1.109 2004/08/22 10:34:24 nigelhorne Exp $";
#if HAVE_CONFIG_H
#include "clamav-config.h"
@ -1314,17 +1317,14 @@ parseEmailBody(message *messageIn, blob **blobsIn, int nBlobs, text *textIn, con
if(mainMessage) {
const text *u_line = uuencodeBegin(mainMessage);
if(u_line) {
blob *aBlob;
fileblob *fb;
cli_dbgmsg("Found uuencoded message in multipart/mixed mainMessage\n");
messageSetEncoding(mainMessage, "x-uuencode");
aBlob = messageToBlob(mainMessage);
fb = messageToFileblob(mainMessage, dir);
if(aBlob) {
assert(blobGetFilename(aBlob) != NULL);
blobClose(aBlob);
blobList[numberOfAttachments++] = aBlob;
}
if(fb)
fileblobDestroy(fb);
}
if(mainMessage != messageIn)
messageDestroy(mainMessage);
@ -1491,13 +1491,10 @@ parseEmailBody(message *messageIn, blob **blobsIn, int nBlobs, text *textIn, con
*/
aText = textAdd(aText, messageGetBody(aMessage));
} else {
blob *aBlob = messageToBlob(aMessage);
fileblob *fb = messageToFileblob(aMessage, dir);
if(aBlob) {
assert(blobGetFilename(aBlob) != NULL);
blobClose(aBlob);
blobList[numberOfAttachments++] = aBlob;
}
if(fb)
fileblobDestroy(fb);
}
assert(aMessage == messages[i]);
messageDestroy(messages[i]);
@ -1520,6 +1517,12 @@ parseEmailBody(message *messageIn, blob **blobsIn, int nBlobs, text *textIn, con
#ifdef CL_DEBUG
assert(blobs[i]->magic == BLOB);
#endif
/*
* TODO: Now that fileblob is used
* this checking doesn't happen,
* need another means to save scanning
* two attachments that are the same
*/
for(j = 0; j < numberOfAttachments; j++)
if(blobcmp(blobs[i], blobList[j]) == 0)
break;
@ -1673,26 +1676,11 @@ parseEmailBody(message *messageIn, blob **blobsIn, int nBlobs, text *textIn, con
/*if((strcasecmp(cptr, "octet-stream") == 0) ||
(strcasecmp(cptr, "x-msdownload") == 0)) {*/
{
blob *aBlob = messageToBlob(mainMessage);
fileblob *fb = messageToFileblob(mainMessage, dir);
if(aBlob) {
cli_dbgmsg("Saving main message as attachment %d\n", nBlobs);
assert(blobGetFilename(aBlob) != NULL);
/*
* It's likely that we won't have built
* a set of attachments
*/
if(blobs == NULL)
blobs = blobList;
for(i = 0; i < nBlobs; i++)
if(blobs[i] == NULL)
break;
blobClose(aBlob);
blobs[i] = aBlob;
if(i == nBlobs) {
nBlobs++;
assert(nBlobs < MAX_ATTACHMENTS);
}
if(fb) {
cli_dbgmsg("Saving main message as attachment\n");
fileblobDestroy(fb);
}
} /*else
cli_warnmsg("Discarded application not sent as attachment\n");*/
@ -1717,7 +1705,7 @@ parseEmailBody(message *messageIn, blob **blobsIn, int nBlobs, text *textIn, con
cli_dbgmsg("%d attachments found\n", nBlobs);
if(nBlobs == 0) {
blob *b;
fileblob *fb;
/*
* No attachments - scan the text portions, often files
@ -1725,16 +1713,14 @@ parseEmailBody(message *messageIn, blob **blobsIn, int nBlobs, text *textIn, con
*/
cli_dbgmsg("%d multiparts found\n", multiparts);
for(i = 0; i < multiparts; i++) {
b = messageToBlob(messages[i]);
assert(b != NULL);
fb = messageToFileblob(messages[i], dir);
cli_dbgmsg("Saving multipart %d, encoded with scheme %d\n",
i, messageGetEncoding(messages[i]));
if(fb) {
cli_dbgmsg("Saving multipart %d, encoded with scheme %d\n",
i, messageGetEncoding(messages[i]));
(void)saveFile(b, dir);
blobDestroy(b);
fileblobDestroy(fb);
}
}
if(mainMessage) {
@ -1751,13 +1737,10 @@ parseEmailBody(message *messageIn, blob **blobsIn, int nBlobs, text *textIn, con
*/
messageSetEncoding(mainMessage, "x-uuencode");
if((b = messageToBlob(mainMessage)) != NULL) {
if((cptr = blobGetFilename(b)) != NULL) {
if((fb = messageToFileblob(mainMessage, dir)) != NULL) {
if((cptr = fileblobGetFilename(fb)) != NULL)
cli_dbgmsg("Found uuencoded message %s\n", cptr);
(void)saveFile(b, dir);
}
blobDestroy(b);
fileblobDestroy(fb);
}
} else if((encodingLine(mainMessage) != NULL) &&
((t_line = bounceBegin(mainMessage)) != NULL)) {
@ -1790,12 +1773,11 @@ parseEmailBody(message *messageIn, blob **blobsIn, int nBlobs, text *textIn, con
(strstr(txt, "8bit") == NULL))
break;
}
if(t && ((b = textToBlob(t_line, NULL)) != NULL)) {
if(t && ((fb = fileblobCreate()) != NULL)) {
cli_dbgmsg("Found a bounce message\n");
saveFile(b, dir);
blobDestroy(b);
fileblobSetFilename(fb, dir, "bounce");
fb = textToFileblob(t_line, fb);
fileblobDestroy(fb);
}
} else {
bool saveIt;
@ -1817,16 +1799,17 @@ parseEmailBody(message *messageIn, blob **blobsIn, int nBlobs, text *textIn, con
* Unfortunately this generates a
* lot of false positives that a bounce
* has been found when it hasn't.
*
* TODO: use fileblobCreate here
*/
if((b = blobCreate()) != NULL) {
if((fb = fileblobCreate()) != NULL) {
cli_dbgmsg("Found a bounce message with no header\n");
blobAddData(b, "Received: by clamd\n", 19);
b = textToBlob(t_line, b);
fileblobSetFilename(fb, dir, "bounce");
fileblobAddData(fb, "Received: by clamd\n", 19);
saveFile(b, dir);
fb = textToFileblob(t_line, fb);
blobDestroy(b);
fileblobDestroy(fb);
}
saveIt = FALSE;
} else
@ -2183,19 +2166,17 @@ parseMimeHeader(message *m, const char *cmd, const table_t *rfc821Table, const c
static void
saveTextPart(message *m, const char *dir)
{
blob *b;
fileblob *fb;
messageAddArgument(m, "filename=textportion");
if((b = messageToBlob(m)) != NULL) {
if((fb = messageToFileblob(m, dir)) != NULL) {
/*
* Save main part to scan that
*/
cli_dbgmsg("Saving main message, encoded with scheme %d\n",
messageGetEncoding(m));
(void)saveFile(b, dir);
blobDestroy(b);
fileblobDestroy(fb);
}
}
@ -2206,6 +2187,8 @@ saveTextPart(message *m, const char *dir)
* OLE2 files if that is disabled or pattern match --exclude, but
* we need access to the command line options/clamav.conf here to
* be able to do that
*
* FIXME: duplicated code with fileblobSetFilename()
*/
static bool
saveFile(const blob *b, const char *dir)

@ -17,6 +17,9 @@
*
* Change History:
* $Log: message.c,v $
* Revision 1.73 2004/08/22 10:34:24 nigelhorne
* Use fileblob
*
* Revision 1.72 2004/08/21 11:57:57 nigelhorne
* Use line.[ch]
*
@ -213,7 +216,7 @@
* uuencodebegin() no longer static
*
*/
static char const rcsid[] = "$Id: message.c,v 1.72 2004/08/21 11:57:57 nigelhorne Exp $";
static char const rcsid[] = "$Id: message.c,v 1.73 2004/08/22 10:34:24 nigelhorne Exp $";
#if HAVE_CONFIG_H
#include "clamav-config.h"
@ -973,18 +976,18 @@ messageClean(message *m)
* Decode and transfer the contents of the message into a blob
* The caller must free the returned blob
*/
blob *
messageToBlob(message *m)
fileblob *
messageToFileblob(message *m, const char *dir)
{
blob *b;
fileblob *fb;
const text *t_line = NULL;
char *filename;
assert(m != NULL);
b = blobCreate();
fb = fileblobCreate();
if(b == NULL)
if(fb == NULL)
return NULL;
/*
@ -995,7 +998,7 @@ messageToBlob(message *m)
if(t_line == NULL) {
/*cli_warnmsg("UUENCODED attachment is missing begin statement\n");*/
blobDestroy(b);
fileblobDestroy(fb);
return NULL;
}
@ -1003,14 +1006,14 @@ messageToBlob(message *m)
if(filename == NULL) {
cli_dbgmsg("UUencoded attachment sent with no filename\n");
blobDestroy(b);
fileblobDestroy(fb);
return NULL;
}
cli_chomp(filename);
cli_dbgmsg("Set uuencode filename to \"%s\"\n", filename);
blobSetFilename(b, filename);
fileblobSetFilename(fb, dir, filename);
t_line = t_line->t_next;
} else if((t_line = binhexBegin(m)) != NULL) {
unsigned char byte;
@ -1039,7 +1042,7 @@ messageToBlob(message *m)
tmp = blobCreate();
if(tmp == NULL) {
blobDestroy(b);
fileblobDestroy(fb);
return NULL;
}
@ -1061,7 +1064,7 @@ messageToBlob(message *m)
if(data == NULL) {
cli_warnmsg("Couldn't locate the binhex message that was claimed to be there\n");
blobDestroy(tmp);
blobDestroy(b);
fileblobDestroy(fb);
return NULL;
}
if(data[0] != ':') {
@ -1072,7 +1075,7 @@ messageToBlob(message *m)
*/
cli_warnmsg("8 bit binhex code is not yet supported\n");
blobDestroy(tmp);
blobDestroy(b);
fileblobDestroy(fb);
return NULL;
}
@ -1089,7 +1092,7 @@ messageToBlob(message *m)
uptr = cli_malloc(len);
if(uptr == NULL) {
blobDestroy(tmp);
blobDestroy(b);
fileblobDestroy(fb);
return NULL;
}
memcpy(uptr, data, len);
@ -1158,7 +1161,7 @@ messageToBlob(message *m)
blob *u = blobCreate(); /* uncompressed data */
if(u == NULL) {
blobDestroy(b);
fileblobDestroy(fb);
blobDestroy(tmp);
return NULL;
}
@ -1205,7 +1208,7 @@ messageToBlob(message *m)
}
if(len == 0) {
cli_warnmsg("Discarding empty binHex attachment\n");
blobDestroy(b);
fileblobDestroy(fb);
blobDestroy(tmp);
return NULL;
}
@ -1222,19 +1225,19 @@ messageToBlob(message *m)
*/
byte = data[0];
if(byte >= len) {
blobDestroy(b);
fileblobDestroy(fb);
blobDestroy(tmp);
return NULL;
}
filename = cli_malloc(byte + 1);
if(filename == NULL) {
blobDestroy(b);
fileblobDestroy(fb);
blobDestroy(tmp);
return NULL;
}
memcpy(filename, &data[1], byte);
filename[byte] = '\0';
blobSetFilename(b, filename);
fileblobSetFilename(fb, dir, filename);
/*ptr = cli_malloc(strlen(filename) + 6);*/
ptr = cli_malloc(byte + 6);
if(ptr) {
@ -1273,11 +1276,11 @@ messageToBlob(message *m)
len, l);
len = l;
}
blobAddData(b, &data[byte], len);
fileblobAddData(fb, &data[byte], len);
blobDestroy(tmp);
return b;
return fb;
} else {
filename = (char *)messageFindArgument(m, "filename");
if(filename == NULL) {
@ -1295,7 +1298,7 @@ messageToBlob(message *m)
messageSetEncoding(m, "base64");
}
blobSetFilename(b, filename);
fileblobSetFilename(fb, dir, filename);
t_line = messageGetBody(m);
}
@ -1306,7 +1309,7 @@ messageToBlob(message *m)
*/
if(t_line == NULL) {
cli_warnmsg("Empty attachment not saved\n");
blobDestroy(b);
fileblobDestroy(fb);
return NULL;
}
@ -1314,7 +1317,7 @@ messageToBlob(message *m)
/*
* Fast copy
*/
return textToBlob(t_line, b);
return textToFileblob(t_line, fb);
do {
unsigned char data[1024];
@ -1338,7 +1341,9 @@ messageToBlob(message *m)
assert(uptr <= &data[sizeof(data)]);
blobAddData(b, data, (size_t)(uptr - data));
if(uptr != data)
fileblobAddData(fb, data, (size_t)(uptr - data));
/*
* According to RFC1521, '=' is used to pad out
* the last byte and should be used as evidence
@ -1359,11 +1364,11 @@ messageToBlob(message *m)
ptr = decode(m, NULL, data, base64, FALSE);
if(ptr)
blobAddData(b, data, (size_t)(ptr - data));
fileblobAddData(fb, data, (size_t)(ptr - data));
m->base64chars = 0;
}
return b;
return fb;
}
/*

@ -16,6 +16,9 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* $Log: message.h,v $
* Revision 1.14 2004/08/22 10:34:24 nigelhorne
* Use fileblob
*
* Revision 1.13 2004/08/21 11:57:57 nigelhorne
* Use line.[ch]
*
@ -91,7 +94,7 @@ int messageAddStr(message *m, const char *data);
int messageAddStrAtTop(message *m, const char *data);
const text *messageGetBody(const message *m);
void messageClean(message *m);
blob *messageToBlob(message *m);
fileblob *messageToFileblob(message *m, const char *dir);
text *messageToText(message *m);
const text *uuencodeBegin(const message *m);
const text *binhexBegin(const message *m);

@ -16,6 +16,9 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* $Log: text.c,v $
* Revision 1.10 2004/08/22 10:34:24 nigelhorne
* Use fileblob
*
* Revision 1.9 2004/08/21 11:57:57 nigelhorne
* Use line.[ch]
*
@ -36,7 +39,7 @@
*
*/
static char const rcsid[] = "$Id: text.c,v 1.9 2004/08/21 11:57:57 nigelhorne Exp $";
static char const rcsid[] = "$Id: text.c,v 1.10 2004/08/22 10:34:24 nigelhorne Exp $";
#if HAVE_CONFIG_H
#include "clamav-config.h"
@ -56,6 +59,7 @@ static char const rcsid[] = "$Id: text.c,v 1.9 2004/08/21 11:57:57 nigelhorne Ex
#include <string.h>
#include <ctype.h>
#include <assert.h>
#include <stdio.h>
#include "line.h"
#include "mbox.h"
@ -272,3 +276,28 @@ textToBlob(const text *t, blob *b)
return b;
}
fileblob *
textToFileblob(const text *t, fileblob *fb)
{
assert(fb != NULL);
assert(t != NULL);
if(fb == NULL) {
fb = fileblobCreate();
if(fb == NULL)
return NULL;
}
do {
if(t->t_line) {
const char *l = lineGetData(t->t_line);
fileblobAddData(fb, (unsigned char *)l, strlen(l));
}
fileblobAddData(fb, (unsigned char *)"\n", 1);
} while((t = t->t_next) != NULL);
return fb;
}

@ -16,6 +16,9 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* $Log: text.h,v $
* Revision 1.6 2004/08/22 10:34:24 nigelhorne
* Use fileblob
*
* Revision 1.5 2004/08/21 11:57:57 nigelhorne
* Use line.[ch]
*
@ -40,3 +43,4 @@ text *textCopy(const text *t_head);
text *textAdd(text *t_head, const text *t);
text *textAddMessage(text *aText, message *aMessage);
blob *textToBlob(const text *t, blob *b);
fileblob *textToFileblob(const text *t, fileblob *fb);

Loading…
Cancel
Save