~ubuntu-branches/ubuntu/utopic/clamav/utopic-security

« back to all changes in this revision

Viewing changes to libclamav/swf.c

  • Committer: Package Import Robot
  • Author(s): Scott Kitterman
  • Date: 2014-02-01 11:06:17 UTC
  • mfrom: (0.35.37 sid)
  • Revision ID: package-import@ubuntu.com-20140201110617-33h2xxk09dep0ui4
Tags: 0.98.1+dfsg-1ubuntu1
* Merge from Debian unstable.  Remaining changes:
  - Drop build-dep on electric-fence (in Universe)
  - Add apparmor profiles for clamd and freshclam along with maintainer
    script changes
  - Add autopkgtest

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 *  Copyright (C) 2011-2013 Sourcefire, Inc.
 
3
 *
 
4
 *  The code is based on Flasm, command line assembler & disassembler of Flash
 
5
 *  ActionScript bytecode Copyright (c) 2001 Opaque Industries, (c) 2002-2007
 
6
 *  Igor Kogan, (c) 2005 Wang Zhen. All rights reserved.
 
7
 *
 
8
 *  Redistribution and use in source and binary forms, with or without modification,
 
9
 *  are permitted provided that the following conditions are met:
 
10
 *
 
11
 *  - Redistributions of source code must retain the above copyright notice, this list
 
12
 *  of conditions and the following disclaimer.
 
13
 *  - Redistributions in binary form must reproduce the above copyright notice, this
 
14
 *  list of conditions and the following disclaimer in the documentation and/or other
 
15
 *  materials provided with the distribution.
 
16
 *  - Neither the name of the Opaque Industries nor the names of its contributors may
 
17
 *  be used to endorse or promote products derived from this software without specific
 
18
 *  prior written permission.
 
19
 *
 
20
 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 
 
21
 *  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 
 
22
 *  OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 
 
23
 *  SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 
 
24
 *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 
 
25
 *  TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 
 
26
 *  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
 
27
 *  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY 
 
28
 *  WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
29
 */
 
30
 
 
31
#if HAVE_CONFIG_H
 
32
#include "clamav-config.h"
 
33
#endif
 
34
 
 
35
#include <stdio.h>
 
36
#include <string.h>
 
37
#include <sys/types.h>
 
38
#include <sys/stat.h>
 
39
#include <fcntl.h>
 
40
#include <sys/stat.h>
 
41
#ifdef  HAVE_UNISTD_H
 
42
#include <unistd.h>
 
43
#endif
 
44
#include <time.h>
 
45
#include <zlib.h>
 
46
 
 
47
#include "cltypes.h"
 
48
#include "swf.h"
 
49
#include "clamav.h"
 
50
#include "scanners.h"
 
51
 
 
52
#define EC16(v) le16_to_host(v)
 
53
#define EC32(v) le32_to_host(v)
 
54
 
 
55
#define INITBITS                                                                \
 
56
{                                                                               \
 
57
    if(fmap_readn(map, &get_c, offset, sizeof(get_c)) == sizeof(get_c)) {       \
 
58
        bitpos = 8;                                                             \
 
59
        bitbuf = (unsigned int) get_c;                                          \
 
60
        offset += sizeof(get_c);                                                \
 
61
    } else {                                                                    \
 
62
        cli_errmsg("cli_scanswf: INITBITS: Can't read file\n");                 \
 
63
        return CL_EFORMAT;                                                      \
 
64
    }                                                                           \
 
65
}
 
66
 
 
67
#define GETBITS(v, n)                                                           \
 
68
{                                                                               \
 
69
    getbits_n = n;                                                              \
 
70
    bits = 0;                                                                   \
 
71
    while(getbits_n > bitpos) {                                                 \
 
72
        getbits_n -= bitpos;                                                    \
 
73
        bits |= bitbuf << getbits_n;                                            \
 
74
        if(fmap_readn(map, &get_c, offset, sizeof(get_c)) == sizeof(get_c)) {   \
 
75
            bitbuf = (unsigned int) get_c;                                      \
 
76
            bitpos = 8;                                                         \
 
77
            offset += sizeof(get_c);                                            \
 
78
        } else {                                                                \
 
79
            cli_errmsg("cli_scanswf: GETBITS: Can't read file\n");              \
 
80
            return CL_EFORMAT;                                                  \
 
81
        }                                                                       \
 
82
    }                                                                           \
 
83
    bitpos -= getbits_n;                                                        \
 
84
    bits |= bitbuf >> bitpos;                                                   \
 
85
    bitbuf &= 0xff >> (8 - bitpos);                                             \
 
86
    v = bits & 0xffff;                                                          \
 
87
}
 
88
 
 
89
#define GETWORD(v)                                                              \
 
90
{                                                                               \
 
91
    if(fmap_readn(map, &get_c, offset, sizeof(get_c)) == sizeof(get_c)) {       \
 
92
        getword_1 = (unsigned int) get_c;                                       \
 
93
        offset += sizeof(get_c);                                                \
 
94
    } else {                                                                    \
 
95
        cli_errmsg("cli_scanswf: GETWORD: Can't read file\n");                  \
 
96
        return CL_EFORMAT;                                                      \
 
97
    }                                                                           \
 
98
    if(fmap_readn(map, &get_c, offset, sizeof(get_c)) == sizeof(get_c)) {       \
 
99
        getword_2 = (unsigned int) get_c;                                       \
 
100
        offset += sizeof(get_c);                                                \
 
101
    } else {                                                                    \
 
102
        cli_errmsg("cli_scanswf: GETWORD: Can't read file\n");                  \
 
103
        return CL_EFORMAT;                                                      \
 
104
    }                                                                           \
 
105
    v = (uint16_t)(getword_1 & 0xff) | ((getword_2 & 0xff) << 8);               \
 
106
}
 
107
 
 
108
#define GETDWORD(v)                                                             \
 
109
{                                                                               \
 
110
    GETWORD(getdword_1);                                                        \
 
111
    GETWORD(getdword_2);                                                        \
 
112
    v = (uint32_t)(getdword_1 | (getdword_2 << 16));                            \
 
113
}
 
114
 
 
115
struct swf_file_hdr {
 
116
    char signature[3];
 
117
    uint8_t version;
 
118
    uint32_t filesize;
 
119
};
 
120
 
 
121
static int scancws(cli_ctx *ctx, struct swf_file_hdr *hdr)
 
122
{
 
123
        z_stream stream;
 
124
        char inbuff[FILEBUFF], outbuff[FILEBUFF];
 
125
        fmap_t *map = *ctx->fmap;
 
126
        int offset = 8, ret, zret, outsize = 8, count;
 
127
        char *tmpname;
 
128
        int fd;
 
129
 
 
130
    if((ret = cli_gentempfd(ctx->engine->tmpdir, &tmpname, &fd)) != CL_SUCCESS) {
 
131
        cli_errmsg("scancws: Can't generate temporary file\n");
 
132
        return ret;
 
133
    }
 
134
 
 
135
    hdr->signature[0] = 'F';
 
136
    if(cli_writen(fd, hdr, sizeof(struct swf_file_hdr)) != sizeof(struct swf_file_hdr)) {
 
137
        cli_errmsg("scancws: Can't write to file %s\n", tmpname);
 
138
        close(fd);
 
139
        if(cli_unlink(tmpname)) {
 
140
            free(tmpname);
 
141
            return CL_EUNLINK;
 
142
        }
 
143
        free(tmpname);
 
144
        return CL_EWRITE;
 
145
    }
 
146
 
 
147
    stream.avail_in = 0;
 
148
    stream.next_in = inbuff;
 
149
    stream.next_out = outbuff;
 
150
    stream.zalloc = (alloc_func) NULL;
 
151
    stream.zfree = (free_func) NULL;
 
152
    stream.opaque = (voidpf) 0;
 
153
    stream.avail_out = FILEBUFF;
 
154
 
 
155
    zret = inflateInit(&stream);
 
156
    if(zret != Z_OK) {
 
157
        cli_errmsg("scancws: inflateInit() failed\n");
 
158
        close(fd);
 
159
        if(cli_unlink(tmpname)) {
 
160
            free(tmpname);
 
161
            return CL_EUNLINK;
 
162
        }
 
163
        free(tmpname);
 
164
        return CL_EUNPACK;
 
165
    }
 
166
 
 
167
    do {
 
168
        if(stream.avail_in == 0) {
 
169
            stream.next_in = inbuff;
 
170
            ret = fmap_readn(map, inbuff, offset, FILEBUFF);
 
171
            if(ret < 0) {
 
172
                cli_errmsg("scancws: Error reading SWF file\n");
 
173
                close(fd);
 
174
                if(cli_unlink(tmpname)) {
 
175
                    free(tmpname);
 
176
                    return CL_EUNLINK;
 
177
                }
 
178
                free(tmpname);
 
179
                return CL_EUNPACK;
 
180
            }
 
181
            if(!ret)
 
182
                break;
 
183
            stream.avail_in = ret;
 
184
            offset += ret;
 
185
        }
 
186
        zret = inflate(&stream, Z_SYNC_FLUSH);
 
187
        count = FILEBUFF - stream.avail_out;
 
188
        if(count) {
 
189
            if(cli_checklimits("SWF", ctx, outsize + count, 0, 0) != CL_SUCCESS)
 
190
                break;
 
191
            if(cli_writen(fd, outbuff, count) != count) {
 
192
                cli_errmsg("scancws: Can't write to file %s\n", tmpname);
 
193
                close(fd);
 
194
                if(cli_unlink(tmpname)) {
 
195
                    free(tmpname);
 
196
                    return CL_EUNLINK;
 
197
                }
 
198
                free(tmpname);
 
199
                return CL_EWRITE;
 
200
            }
 
201
            outsize += count;
 
202
        }
 
203
        stream.next_out = outbuff;
 
204
        stream.avail_out = FILEBUFF;
 
205
    } while(zret == Z_OK);
 
206
 
 
207
    if((zret != Z_STREAM_END && zret != Z_OK) || (zret = inflateEnd(&stream)) != Z_OK) {
 
208
        cli_infomsg(ctx, "scancws: Error decompressing SWF file\n");
 
209
        close(fd);
 
210
        if(cli_unlink(tmpname)) {
 
211
            free(tmpname);
 
212
            return CL_EUNLINK;
 
213
        }
 
214
        free(tmpname);
 
215
        return CL_EUNPACK;
 
216
    }
 
217
    cli_dbgmsg("SWF: Decompressed to %s, size %d\n", tmpname, outsize);
 
218
 
 
219
    ret = cli_magic_scandesc(fd, ctx);
 
220
 
 
221
    close(fd);
 
222
    if(!ctx->engine->keeptmp) {
 
223
        if(cli_unlink(tmpname)) {
 
224
            free(tmpname);
 
225
            return CL_EUNLINK;
 
226
        }
 
227
    }
 
228
    free(tmpname);
 
229
    return ret;
 
230
}
 
231
 
 
232
static const char *tagname(tag_id id)
 
233
{
 
234
        unsigned int i;
 
235
 
 
236
    for(i = 0; tag_names[i].name; i++)
 
237
        if(tag_names[i].id == id)
 
238
            return tag_names[i].name;
 
239
    return NULL;
 
240
}
 
241
 
 
242
int cli_scanswf(cli_ctx *ctx)
 
243
{
 
244
    struct swf_file_hdr file_hdr;
 
245
    fmap_t *map = *ctx->fmap;
 
246
    unsigned int bitpos, bitbuf, getbits_n, nbits, getword_1, getword_2, getdword_1, getdword_2;
 
247
    const char *pt;
 
248
    char get_c;
 
249
    size_t offset = 0;
 
250
    unsigned int val, foo, tag_hdr, tag_type, tag_len;
 
251
    unsigned long int bits;
 
252
 
 
253
    cli_dbgmsg("in cli_scanswf()\n");
 
254
 
 
255
    if(fmap_readn(map, &file_hdr, offset, sizeof(file_hdr)) != sizeof(file_hdr)) {
 
256
        cli_dbgmsg("SWF: Can't read file header\n");
 
257
        return CL_CLEAN;
 
258
    }
 
259
    offset += sizeof(file_hdr);
 
260
 
 
261
    if(!strncmp(file_hdr.signature, "CWS", 3)) {
 
262
        cli_dbgmsg("SWF: Compressed file\n");
 
263
        return scancws(ctx, &file_hdr);
 
264
    } else if(!strncmp(file_hdr.signature, "FWS", 3)) {
 
265
        cli_dbgmsg("SWF: Uncompressed file\n");
 
266
    } else {
 
267
        cli_dbgmsg("SWF: Not a SWF file\n");
 
268
        return CL_CLEAN;
 
269
    }
 
270
 
 
271
    cli_dbgmsg("SWF: Version: %u\n", file_hdr.version);
 
272
    cli_dbgmsg("SWF: File size: %u\n", EC32(file_hdr.filesize));
 
273
 
 
274
    INITBITS;
 
275
 
 
276
    GETBITS(nbits, 5);
 
277
    GETBITS(foo, nbits); /* xMin */
 
278
    GETBITS(foo, nbits); /* xMax */
 
279
    GETBITS(foo, nbits); /* yMin */
 
280
    GETBITS(foo, nbits); /* yMax */
 
281
 
 
282
    GETWORD(foo);
 
283
    GETWORD(val);
 
284
    cli_dbgmsg("SWF: Frames total: %d\n", val);
 
285
 
 
286
    while(offset < map->len) {
 
287
        GETWORD(tag_hdr);
 
288
        tag_type = tag_hdr >> 6;
 
289
        if(tag_type == 0)
 
290
            break;
 
291
        tag_len = tag_hdr & 0x3f;
 
292
        if(tag_len == 0x3f)
 
293
            GETDWORD(tag_len);
 
294
 
 
295
        pt = tagname(tag_type);
 
296
        cli_dbgmsg("SWF: %s\n", pt ? pt : "UNKNOWN TAG");
 
297
        cli_dbgmsg("SWF: Tag length: %u\n", tag_len);
 
298
        if (tag_len > map->len) {
 
299
            cli_warnmsg("SWF: Invalid tag length.\n");
 
300
            return CL_EFORMAT;
 
301
        }
 
302
        if ((offset + tag_len) < offset) {
 
303
            cli_warnmsg("SWF: Tag length too large.\n");
 
304
            break;
 
305
        }
 
306
        if(!pt) {
 
307
            offset += tag_len;
 
308
            continue;
 
309
        }
 
310
 
 
311
        switch(tag_type) {
 
312
            case TAG_SCRIPTLIMITS: {
 
313
                unsigned int recursion, timeout;
 
314
                GETWORD(recursion);
 
315
                GETWORD(timeout);
 
316
                cli_dbgmsg("SWF: scriptLimits recursion %u timeout %u\n", recursion, timeout);
 
317
                break;
 
318
            }
 
319
 
 
320
            case TAG_FILEATTRIBUTES:
 
321
                GETDWORD(val);
 
322
                cli_dbgmsg("SWF: File attributes:\n");
 
323
                if(val & SWF_ATTR_USENETWORK)
 
324
                    cli_dbgmsg("    * Use network\n");
 
325
                if(val & SWF_ATTR_RELATIVEURLS)
 
326
                    cli_dbgmsg("    * Relative URLs\n");
 
327
                if(val & SWF_ATTR_SUPPRESSCROSSDOMAINCACHE)
 
328
                    cli_dbgmsg("    * Suppress cross domain cache\n");
 
329
                if(val & SWF_ATTR_ACTIONSCRIPT3)
 
330
                    cli_dbgmsg("    * ActionScript 3.0\n");
 
331
                if(val & SWF_ATTR_HASMETADATA)
 
332
                    cli_dbgmsg("    * Has metadata\n");
 
333
                if(val & SWF_ATTR_USEDIRECTBLIT)
 
334
                    cli_dbgmsg("    * Use hardware acceleration\n");
 
335
                if(val & SWF_ATTR_USEGPU)
 
336
                    cli_dbgmsg("    * Use GPU\n");
 
337
                break;
 
338
 
 
339
            default:
 
340
                offset += tag_len;
 
341
                continue;
 
342
        }
 
343
    }
 
344
 
 
345
    return CL_CLEAN;
 
346
}