~ubuntu-branches/ubuntu/oneiric/clamav/oneiric-security

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
/*
 *  Copyright (C) 2007-2008 Sourcefire, Inc.
 *
 *  Authors: Nigel Horne
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License version 2 as
 *  published by the Free Software Foundation.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 *  MA 02110-1301, USA.
 */

static	char	const	rcsid[] = "$Id: uuencode.c,v 1.8 2006/12/11 11:55:11 njh Exp $";

#include "clamav.h"

#if	HAVE_CONFIG_H
#include "clamav-config.h"
#endif

#ifdef	HAVE_UNISTD_H
#include <unistd.h>
#endif

#include <stdio.h>
#include <memory.h>
#include <sys/stat.h>
#ifdef	HAVE_STRINGS_H
#include <strings.h>
#endif
#include "others.h"
#include "str.h"

#include "mbox.h"
#include "uuencode.h"

/* Maximum line length according to RFC821 */
#define	RFC2821LENGTH	1000

int
cli_uuencode(const char *dir, fmap_t *map)
{
	message *m;
	char buffer[RFC2821LENGTH + 1];
	size_t at = 0;

	if(!fmap_gets(map, buffer, &at, sizeof(buffer) - 1)) {
		/* empty message */
		return CL_CLEAN;
	}
	if(!isuuencodebegin(buffer)) {
		cli_dbgmsg("Message is not in uuencoded format\n");
		return CL_EFORMAT;
	}

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

	cli_dbgmsg("found uuencode file\n");

	if(uudecodeFile(m, buffer, dir, map, &at) < 0) {
		messageDestroy(m);
		cli_dbgmsg("Message is not in uuencoded format\n");
		return CL_EFORMAT;
	}
	messageDestroy(m);

	return CL_CLEAN;	/* a lie - but it gets things going */
}

/*
 * Save the uuencoded part of the file as it is read in since there's no need
 * to include it in the parse tree. Saves memory and parse time.
 * Return < 0 for failure
 */
int
uudecodeFile(message *m, const char *firstline, const char *dir, fmap_t *map, size_t *at)
{
	fileblob *fb;
	char buffer[RFC2821LENGTH + 1];
	char *filename = cli_strtok(firstline, 2, " ");

	if(filename == NULL)
		return -1;

	fb = fileblobCreate();
	if(fb == NULL) {
		free(filename);
		return -1;
	}

	fileblobSetFilename(fb, dir, filename);
	cli_dbgmsg("uudecode %s\n", filename);
	free(filename);

	while(fmap_gets(map, buffer, at, sizeof(buffer) - 1)) {
		unsigned char data[1024];
		const unsigned char *uptr;
		size_t len;

		cli_chomp(buffer);
		if(strcasecmp(buffer, "end") == 0)
			break;
		if(buffer[0] == '\0')
			break;

		uptr = decodeLine(m, UUENCODE, buffer, data, sizeof(data));
		if(uptr == NULL)
			break;

		len = (size_t)(uptr - data);
		if((len > 62) || (len == 0))
			break;

		if(fileblobAddData(fb, data, len) < 0)
			break;
	}

	fileblobDestroy(fb);

	return 1;
}