Example #1
0
fileblob *
textToFileblob(text *t, fileblob *fb, int destroy)
{
    assert(fb != NULL);
    assert(t != NULL);

    if(fb == NULL) {
        cli_dbgmsg("textToFileBlob, destroy = %d\n", destroy);
        fb = fileblobCreate();

        if(fb == NULL)
            return NULL;
    } else {
        cli_dbgmsg("textToFileBlob to %s, destroy = %d\n",
                   fileblobGetFilename(fb), destroy);

        fb->ctx = NULL;	/* no need to scan */
    }

    fb = textIterate(t, addToFileblob, fb, destroy);
    if(destroy && t->t_next) {
        textDestroy(t->t_next);
        t->t_next = NULL;
    }
    return fb;
}
Example #2
0
int
cli_tnef(const char *dir, cli_ctx *ctx)
{
	uint32_t i32;
	uint16_t i16;
	fileblob *fb;
	int ret, alldone;
	off_t fsize, pos = 0;
	STATBUF statb;


	fsize = ctx->fmap[0]->len;

	if(fsize < (off_t) MIN_SIZE) {
		cli_dbgmsg("cli_tngs: file too small, ignoring\n");
		return CL_CLEAN;
	}

	if (fmap_readn(*ctx->fmap, &i32, pos, sizeof(uint32_t)) != sizeof(uint32_t)) {
		/* The file is at least MIN_SIZE bytes, so it "can't" fail */
		return CL_EREAD;
	}
	pos += sizeof(uint32_t);

	if(host32(i32) != TNEF_SIGNATURE) {
		return CL_EFORMAT;
	}

	if(fmap_readn(*ctx->fmap, &i16, pos, sizeof(uint16_t)) != sizeof(uint16_t)) {
		/* The file is at least MIN_SIZE bytes, so it "can't" fail */
		return CL_EREAD;
	}
	pos += sizeof(uint16_t);

	fb = NULL;
	ret = CL_CLEAN;	/* we don't know if it's clean or not :-) */
	alldone = 0;

	do {
		uint8_t part = 0;
		uint16_t type = 0, tag = 0;
		int32_t length = 0;

		switch(tnef_header(*ctx->fmap, &pos, &part, &type, &tag, &length)) {
			case 0:
				alldone = 1;
				break;
			case 1:
				break;
			default:
				/*
				 * Assume truncation, not file I/O error
				 */
				cli_warnmsg("cli_tnef: file truncated, returning CLEAN\n");
				ret = CL_CLEAN;
				alldone = 1;
				break;
		}
		if(length == 0)
			continue;
		if(length < 0) {
			cli_warnmsg("Corrupt TNEF header detected - length %d\n",
				(int)length);
			ret = CL_EFORMAT;
			break;
		}
		if(alldone)
			break;
		switch(part) {
			case LVL_MESSAGE:
				cli_dbgmsg("TNEF - found message\n");
				if(fb != NULL) {
					fileblobDestroy(fb);
					fb = NULL;
				}
				fb = fileblobCreate();
				if(tnef_message(*ctx->fmap, &pos, type, tag, length, fsize) != 0) {
					cli_dbgmsg("TNEF: Error reading TNEF message\n");
					ret = CL_EFORMAT;
					alldone = 1;
				}
				break;
			case LVL_ATTACHMENT:
				cli_dbgmsg("TNEF - found attachment\n");
				if(tnef_attachment(*ctx->fmap, &pos, type, tag, length, dir, &fb, fsize) != 0) {
					cli_dbgmsg("TNEF: Error reading TNEF attachment\n");
					ret = CL_EFORMAT;
					alldone = 1;
				}
				break;
			case 0:
				break;
			default:
				cli_warnmsg("TNEF - unknown level %d tag 0x%x\n", (int)part, (int)tag);

				/*
				 * Dump the file incase it was part of an
				 * email that's about to be deleted
				 */
				if(cli_debug_flag) {
					int fout = -1;
					char *filename = cli_gentemp(ctx->engine->tmpdir);
					char buffer[BUFSIZ];

					if(filename)
						fout = open(filename, O_WRONLY|O_CREAT|O_EXCL|O_TRUNC|O_BINARY, 0600);

					if(fout >= 0) {
						int count;

						cli_warnmsg("Saving dump to %s:  refer to http://www.clamav.net/bugs\n", filename);

						pos = 0;
						while ((count = fmap_readn(*ctx->fmap, buffer, pos, sizeof(buffer))) > 0) {
						        pos += count;
							cli_writen(fout, buffer, count);
						}
						close(fout);
					}
					free(filename);
				}
				ret = CL_EFORMAT;
				alldone = 1;
				break;
		}
	} while(!alldone);

	if(fb) {
		cli_dbgmsg("cli_tnef: flushing final data\n");
		if(fileblobGetFilename(fb) == NULL) {
			cli_dbgmsg("Saving TNEF portion with an unknown name\n");
			fileblobSetFilename(fb, dir, "tnef");
		}
		fileblobDestroy(fb);
		fb = NULL;
	}

	cli_dbgmsg("cli_tnef: returning %d\n", ret);
	return ret;
}
Example #3
0
int
cli_binhex(const char *dir, int desc)
{
#ifndef HAVE_MMAP
	cli_warnmsg("File not decoded - binhex decoding needs mmap() (for now)\n");
	return CL_CLEAN;
#else
	struct stat statb;
	char *buf, *start, *line;
	size_t size;
	long bytesleft;
	message *m;
	fileblob *fb;

	if(fstat(desc, &statb) < 0)
		return CL_EOPEN;

	size = (size_t)statb.st_size;

	if(size == 0)
		return CL_CLEAN;

	m = messageCreate();
	if(m == NULL)
		return CL_EMEM;

	start = buf = mmap(NULL, size, PROT_READ, MAP_PRIVATE, desc, 0);
	if(buf == MAP_FAILED) {
		messageDestroy(m);
		return CL_EMEM;
	}

	cli_dbgmsg("mmap'ed binhex file\n");

	bytesleft = (long)size;
	line = NULL;

	while(bytesleft > 0) {
		int length = 0;
		char *ptr, *newline;

		/*printf("%d: ", bytesleft);*/

		for(ptr = buf; bytesleft && (*ptr != '\n') && (*ptr != '\r'); ptr++) {
			length++;
			--bytesleft;
		}

		/*printf("%d: ", length);*/

		newline = cli_realloc(line, (size_t)(length + 1));
		if(newline == NULL)
			break;

		line = newline;

		memcpy(line, buf, length);
		line[length] = '\0';

		/*puts(line);*/

		if(messageAddStr(m, line) < 0)
			break;

		if((bytesleft > 0) && (*ptr == '\r')) {
			ptr++;
			bytesleft--;
		}
		buf = ++ptr;
		bytesleft--;
	}
	munmap(start, size);

	if(line)
		free(line);

	if(binhexBegin(m) == NULL) {
		messageDestroy(m);
		cli_errmsg("No binhex line found\n");
		return CL_EFORMAT;
	}

	/* similar to binhexMessage */
	messageSetEncoding(m, "x-binhex");

	fb = messageToFileblob(m, dir, 1);
	if(fb) {
		cli_dbgmsg("Binhex file decoded to %s\n", fileblobGetFilename(fb));
		fileblobDestroy(fb);
	} else
		cli_errmsg("Couldn't decode binhex file to %s\n", dir);
	messageDestroy(m);

	if(fb)
		return CL_CLEAN;	/* a lie - but it gets things going */
	return CL_EIO;	/* probably CL_EMEM, but we can't tell at this layer */
#endif
}