~ubuntu-branches/ubuntu/saucy/clamav/saucy

« back to all changes in this revision

Viewing changes to libclamav/vba_extract.c

  • Committer: Bazaar Package Importer
  • Author(s): Scott Kitterman
  • Date: 2007-12-18 15:18:53 UTC
  • mfrom: (0.25.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20071218151853-ag6bdjbq6budh353
Tags: 0.92~dfsg-0build1
Fake sync to get the new clamav into the NEW queue

Show diffs side-by-side

added added

removed removed

Lines of Context:
4
4
 *  Copyright (C) 2004-2005 trog@uncon.org
5
5
 *
6
6
 *  This code is based on the OpenOffice and libgsf sources.
7
 
 *                  
 
7
 *
8
8
 *  This program is free software; you can redistribute it and/or modify
9
9
 *  it under the terms of the GNU General Public License as published by
10
10
 *  the Free Software Foundation; either version 2 of the License, or
20
20
 *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
21
21
 *  MA 02110-1301, USA.
22
22
 */
 
23
#if HAVE_CONFIG_H
 
24
#include "clamav-config.h"
 
25
#endif
23
26
 
24
27
#include <stdio.h>
25
28
#include <string.h>
35
38
 
36
39
#include "clamav.h"
37
40
 
38
 
#if HAVE_CONFIG_H
39
 
#include "clamav-config.h"
40
 
#endif
41
 
 
42
41
#include "vba_extract.h"
43
42
#include "others.h"
 
43
#ifdef  CL_DEBUG
 
44
#include "mbox.h"
 
45
#endif
 
46
#include "blob.h"
44
47
 
45
48
#ifndef O_BINARY
46
49
#define O_BINARY        0
47
50
#endif
48
51
 
 
52
#ifndef HAVE_ATTRIB_PACKED
 
53
#define __attribute__(x)
 
54
#endif
 
55
 
 
56
#define PPT_LZW_BUFFSIZE 8192
 
57
#define NUM_VBA_VERSIONS 14
 
58
#define VBA_COMPRESSION_WINDOW 4096
 
59
 
 
60
#ifdef HAVE_PRAGMA_PACK
 
61
#pragma pack(1)
 
62
#endif
 
63
 
 
64
#ifdef HAVE_PRAGMA_PACK_HPPA
 
65
#pragma pack 1
 
66
#endif
 
67
 
 
68
struct vba56_header {
 
69
        unsigned char magic[2];
 
70
        unsigned char version[4];
 
71
        uint16_t ooff __attribute__ ((packed)); /* 0x00FF */
 
72
        uint32_t LidA __attribute__ ((packed));  /* Language identifiers */
 
73
        uint32_t LidB __attribute__ ((packed));
 
74
        uint16_t CharSet __attribute__ ((packed));
 
75
        uint16_t LenA __attribute__ ((packed));
 
76
        uint32_t UnknownB __attribute__ ((packed));
 
77
        uint32_t UnknownC __attribute__ ((packed));
 
78
        uint16_t LenB __attribute__ ((packed));
 
79
        uint16_t LenC __attribute__ ((packed));
 
80
        uint16_t LenD __attribute__ ((packed));
 
81
};
 
82
 
 
83
#ifdef HAVE_PRAGMA_PACK
 
84
#pragma pack()
 
85
#endif
 
86
 
 
87
#ifdef HAVE_PRAGMA_PACK_HPPA
 
88
#pragma pack
 
89
#endif
 
90
 
49
91
typedef struct vba_version_tag {
50
92
        unsigned char signature[4];
51
93
        const char *name;
52
 
        int vba_version;
53
94
        int is_mac;
54
95
} vba_version_t;
55
96
 
56
 
 
57
97
static uint16_t vba_endian_convert_16(uint16_t value, int is_mac)
58
98
{
59
99
        if (is_mac)
60
 
                return be16_to_host(value);
 
100
                return (uint16_t)be16_to_host(value);
61
101
        else
62
102
                return le16_to_host(value);
63
103
}
64
 
 
 
104
 
65
105
static uint32_t vba_endian_convert_32(uint32_t value, int is_mac)
66
106
{
67
107
        if (is_mac)
70
110
                return le32_to_host(value);
71
111
}
72
112
 
73
 
typedef struct byte_array_tag {
74
 
        unsigned int length;
75
 
        unsigned char *data;
76
 
} byte_array_t;
77
 
 
78
 
#define NUM_VBA_VERSIONS 14
79
 
vba_version_t vba_version[] = {
80
 
        { { 0x5e, 0x00, 0x00, 0x01 }, "Office 97",              5, FALSE},
81
 
        { { 0x5f, 0x00, 0x00, 0x01 }, "Office 97 SR1",          5, FALSE },
82
 
        { { 0x65, 0x00, 0x00, 0x01 }, "Office 2000 alpha?",     6, FALSE },
83
 
        { { 0x6b, 0x00, 0x00, 0x01 }, "Office 2000 beta?",      6, FALSE },
84
 
        { { 0x6d, 0x00, 0x00, 0x01 }, "Office 2000",            6, FALSE },
85
 
        { { 0x6f, 0x00, 0x00, 0x01 }, "Office 2000",            6, FALSE },
86
 
        { { 0x70, 0x00, 0x00, 0x01 }, "Office XP beta 1/2",     6, FALSE },
87
 
        { { 0x73, 0x00, 0x00, 0x01 }, "Office XP",              6, FALSE },
88
 
        { { 0x76, 0x00, 0x00, 0x01 }, "Office 2003",            6, FALSE },
89
 
        { { 0x79, 0x00, 0x00, 0x01 }, "Office 2003",            6, FALSE },
90
 
        { { 0x60, 0x00, 0x00, 0x0e }, "MacOffice 98",           5, TRUE },
91
 
        { { 0x62, 0x00, 0x00, 0x0e }, "MacOffice 2001",         5, TRUE },
92
 
        { { 0x63, 0x00, 0x00, 0x0e }, "MacOffice X",            6, TRUE },
93
 
        { { 0x64, 0x00, 0x00, 0x0e }, "MacOffice 2004",         6, TRUE },
 
113
static const vba_version_t vba_version[NUM_VBA_VERSIONS] = {
 
114
        { { 0x5e, 0x00, 0x00, 0x01 }, "Office 97",              FALSE},
 
115
        { { 0x5f, 0x00, 0x00, 0x01 }, "Office 97 SR1",          FALSE },
 
116
        { { 0x65, 0x00, 0x00, 0x01 }, "Office 2000 alpha?",     FALSE },
 
117
        { { 0x6b, 0x00, 0x00, 0x01 }, "Office 2000 beta?",      FALSE },
 
118
        { { 0x6d, 0x00, 0x00, 0x01 }, "Office 2000",            FALSE },
 
119
        { { 0x6f, 0x00, 0x00, 0x01 }, "Office 2000",            FALSE },
 
120
        { { 0x70, 0x00, 0x00, 0x01 }, "Office XP beta 1/2",     FALSE },
 
121
        { { 0x73, 0x00, 0x00, 0x01 }, "Office XP",              FALSE },
 
122
        { { 0x76, 0x00, 0x00, 0x01 }, "Office 2003",            FALSE },
 
123
        { { 0x79, 0x00, 0x00, 0x01 }, "Office 2003",            FALSE },
 
124
        { { 0x60, 0x00, 0x00, 0x0e }, "MacOffice 98",           TRUE },
 
125
        { { 0x62, 0x00, 0x00, 0x0e }, "MacOffice 2001",         TRUE },
 
126
        { { 0x63, 0x00, 0x00, 0x0e }, "MacOffice X",            TRUE },
 
127
        { { 0x64, 0x00, 0x00, 0x0e }, "MacOffice 2004",         TRUE },
94
128
};
95
129
 
96
 
#define VBA56_DIRENT_RECORD_COUNT (2 + /* magic */              \
97
 
                                   4 + /* version */            \
98
 
                                   2 + /* 0x00 0xff */          \
99
 
                                  22)  /* unknown */
100
 
#define VBA56_DIRENT_HEADER_SIZE (VBA56_DIRENT_RECORD_COUNT +   \
101
 
                                  2 +  /* type1 record count */ \
102
 
                                  2)   /* unknown */
103
 
 
104
 
static char *get_unicode_name(char *name, int size, int is_mac)
 
130
static char *
 
131
get_unicode_name(const char *name, int size, int is_mac)
105
132
{
106
 
        int i, j;
107
 
        char *newname;
108
 
 
109
 
        if (!name || *name == 0 || size <= 0) {
110
 
                return NULL;
111
 
        }
112
 
 
113
 
        newname = (char *) cli_malloc(size*7);
114
 
        if (!newname) {
115
 
                return NULL;
116
 
        }
117
 
        j=0;
118
 
        for (i=0 ; i < size; i += (is_mac ? 1 : 2) ) {
119
 
                if (isprint(name[i])) {
120
 
                        newname[j++] = name[i];
121
 
                } else {
122
 
                        if (name[i] < 10 && name[i] >= 0) {
123
 
                                newname[j++] = '_';
124
 
                                newname[j++] = name[i] + '0';
125
 
                        }
126
 
                        else {
127
 
                                const uint16_t x = (((uint16_t)name[i]) << 8) | name[i+1];
128
 
                                newname[j++] = '_';
129
 
                                newname[j++] = 'a'+((x&0xF));
130
 
                                newname[j++] = 'a'+((x>>4)&0xF);
131
 
                                newname[j++] = 'a'+((x>>8)&0xF);
132
 
                                newname[j++] = 'a'+((x>>16)&0xF);
133
 
                                newname[j++] = 'a'+((x>>24)&0xF);
 
133
        int i, increment;
 
134
        char *newname, *ret;
 
135
 
 
136
        if((name == NULL) || (*name == '\0') || (size <= 0))
 
137
                return NULL;
 
138
 
 
139
        newname = (char *)cli_malloc(size * 7);
 
140
        if(newname == NULL)
 
141
                return NULL;
 
142
 
 
143
        if((!is_mac) && (size & 0x1)) {
 
144
                cli_dbgmsg("get_unicode_name: odd number of bytes %d\n", size);
 
145
                --size;
 
146
        }
 
147
 
 
148
        increment = (is_mac) ? 1 : 2;
 
149
        ret = newname;
 
150
 
 
151
        for(i = 0; i < size; i += increment) {
 
152
                if(isprint(name[i]))
 
153
                        *ret++ = name[i];
 
154
                else {
 
155
                        if(name[i] < 10 && name[i] >= 0) {
 
156
                                *ret++ = '_';
 
157
                                *ret++ = (char)(name[i] + '0');
 
158
                        } else {
 
159
                                const uint16_t x = (uint16_t)(((name[i]) << 8) | name[i + 1]);
 
160
 
 
161
                                *ret++ = '_';
 
162
                                *ret++ = (char)('a'+((x&0xF)));
 
163
                                *ret++ = (char)('a'+((x>>4)&0xF));
 
164
                                *ret++ = (char)('a'+((x>>8)&0xF));
 
165
#if     0
 
166
                                *ret++ = (char)('a'+((x>>16)&0xF));     /* FIXME: x>>16 MUST == 0 */
 
167
                                *ret++ = (char)('a'+((x>>24)&0xF));     /* FIXME: x>>24 MUST == 0 */
 
168
#endif
134
169
                        }
135
 
                        newname[j++] = '_';
136
 
                }
137
 
        }
138
 
        newname[j] = '\0';
 
170
                        *ret++ = '_';
 
171
                }
 
172
        }
 
173
 
 
174
        *ret = '\0';
139
175
        return newname;
140
176
}
141
177
 
150
186
        };
151
187
        /* MS Office middle */
152
188
        static const uint8_t middle2_str[20] = {
153
 
                0x00, 0x00, 0xe1, 0x2e, 0x45, 0x0d, 0x8f, 0xe0, 0x1a, 0x10, 
 
189
                0x00, 0x00, 0xe1, 0x2e, 0x45, 0x0d, 0x8f, 0xe0, 0x1a, 0x10,
154
190
                0x85, 0x2e, 0x02, 0x60, 0x8c, 0x4d, 0x0b, 0xb4, 0x00, 0x00
155
191
        };
156
192
 
157
 
        if (cli_readn(fd, &test_middle, 20) != 20) {
158
 
                return;
159
 
        }
 
193
        if(cli_readn(fd, &test_middle, 20) != 20) {
 
194
                return;
 
195
        }
160
196
 
161
197
        if ((memcmp(test_middle, middle1_str, 20) != 0) &&
162
198
                (memcmp(test_middle, middle2_str, 20) != 0)) {
163
199
                cli_dbgmsg("middle not found\n");
164
 
                lseek(fd, -20, SEEK_CUR);
 
200
                lseek(fd, -20, SEEK_CUR);
165
201
        } else {
166
202
                cli_dbgmsg("middle found\n");
167
203
        }
168
204
        return;
169
205
}
170
206
 
171
 
static int vba_read_project_strings(int fd, int is_mac)
 
207
static int
 
208
vba_read_project_strings(int fd, int is_mac)
172
209
{
173
 
        uint16_t length;
174
 
        unsigned char *buff, *name;
175
 
        uint32_t offset;
176
 
 
177
210
        for (;;) {
 
211
                uint32_t offset;
 
212
                uint16_t length;
 
213
                unsigned char *buff;
 
214
                char *name;
 
215
 
178
216
                if (cli_readn(fd, &length, 2) != 2) {
179
217
                        return FALSE;
180
218
                }
183
221
                        lseek(fd, -2, SEEK_CUR);
184
222
                        break;
185
223
                }
186
 
                cli_dbgmsg ("length: %d, ", length);
187
224
                buff = (unsigned char *) cli_malloc(length);
188
225
                if (!buff) {
189
226
                        cli_errmsg("cli_malloc failed\n");
190
227
                        return FALSE;
191
228
                }
192
229
                offset = lseek(fd, 0, SEEK_CUR);
193
 
                if (cli_readn(fd, buff, length) != length) {
 
230
 
 
231
                if (cli_readn(fd, buff, length) != (int)length) {
194
232
                        cli_dbgmsg("read name failed - rewinding\n");
195
233
                        lseek(fd, offset, SEEK_SET);
196
234
                        free(buff);
197
235
                        break;
198
236
                }
199
 
                name = get_unicode_name(buff, length, is_mac);
200
 
                if (name) {
201
 
                        cli_dbgmsg("name: %s\n", name);
202
 
                } else {
203
 
                        cli_dbgmsg("name: [null]\n");
204
 
                }
 
237
                name = get_unicode_name((const char *)buff, length, is_mac);
 
238
                if (name)
 
239
                        cli_dbgmsg("length: %d, name: %s\n", length, name);
 
240
                else
 
241
                        cli_dbgmsg("length: %d, name: [null]\n", length);
205
242
                free(buff);
206
243
 
207
244
                /* Ignore twelve bytes from entries of type 'G'.
208
245
                   Type 'C' entries come in pairs, the second also
209
246
                   having a 12 byte trailer */
210
247
                /* TODO: Need to check if types H(same as G) and D(same as C) exist */
211
 
                if (name && (!strncmp ("*\\G", name, 3) || !strncmp ("*\\H", name, 3)
212
 
                                || !strncmp("*\\C", name, 3) || !strncmp("*\\D", name, 3))) {
213
 
                        if (cli_readn(fd, &length, 2) != 2) {
214
 
                                return FALSE;
215
 
                        }
216
 
                        length = vba_endian_convert_16(length, is_mac);
217
 
                        if ((length != 0) && (length != 65535)) {
218
 
                                lseek(fd, -2, SEEK_CUR);
219
 
                                free(name);
220
 
                                continue;
221
 
                        }
222
 
                        buff = (unsigned char *) cli_malloc(10);
223
 
                        if (!buff) {
224
 
                                free(name);
225
 
                                close(fd);
226
 
                                return FALSE;
227
 
                        }
228
 
                        if (cli_readn(fd, buff, 10) != 10) {
229
 
                                cli_errmsg("failed to read blob\n");
230
 
                                free(buff);
231
 
                                free(name);
232
 
                                close(fd);
233
 
                                return FALSE;
234
 
                        }
235
 
                        free(buff);
236
 
                } else {
 
248
                if((name == NULL) || (memcmp("*\\", name, 2) != 0) ||
 
249
                   (strchr("GCHD", name[2]) == NULL)) {
237
250
                        /* Unknown type - probably ran out of strings - rewind */
238
251
                        lseek(fd, -(length+2), SEEK_CUR);
239
 
                        if (name) {
 
252
                        if(name)
240
253
                                free(name);
241
 
                        }
242
254
                        break;
243
255
                }
244
256
                free(name);
245
 
                offset = lseek(fd, 0, SEEK_CUR);
 
257
 
 
258
                if (cli_readn(fd, &length, 2) != 2)
 
259
                        return FALSE;
 
260
 
 
261
                length = vba_endian_convert_16(length, is_mac);
 
262
                if ((length != 0) && (length != 65535)) {
 
263
                        lseek(fd, -2, SEEK_CUR);
 
264
                        continue;
 
265
                }
 
266
                offset = lseek(fd, 10, SEEK_CUR);
246
267
                cli_dbgmsg("offset: %u\n", offset);
247
268
                vba56_test_middle(fd);
248
269
        }
251
272
 
252
273
vba_project_t *vba56_dir_read(const char *dir)
253
274
{
254
 
        unsigned char magic[2];
255
 
        unsigned char version[4];
256
275
        unsigned char *buff;
257
 
        unsigned char vba56_signature[] = { 0xcc, 0x61 };
 
276
        const unsigned char vba56_signature[] = { 0xcc, 0x61 };
258
277
        uint16_t record_count, length;
259
 
        uint16_t ooff;
 
278
        uint16_t ffff;
260
279
        uint16_t byte_count;
261
280
        uint32_t offset;
262
 
        uint32_t LidA;  /* Language identifiers */
263
 
        uint32_t LidB;
264
 
        uint16_t CharSet;
265
 
        uint16_t LenA;
266
 
        uint32_t UnknownB;
267
 
        uint32_t UnknownC;
268
 
        uint16_t LenB;
269
 
        uint16_t LenC;
270
 
        uint16_t LenD;
271
 
        int i, j, fd, is_mac;
 
281
        int i, fd, is_mac;
272
282
        vba_project_t *vba_project;
273
 
        char *fullname;
 
283
        struct vba56_header v56h;
 
284
        char fullname[NAME_MAX + 1];
274
285
 
275
286
        cli_dbgmsg("in vba56_dir_read()\n");
276
287
 
277
 
        fullname = (char *) cli_malloc(strlen(dir) + 14);
278
 
        if (!fullname) {
279
 
                return NULL;
280
 
        }
281
 
        sprintf(fullname, "%s/_VBA_PROJECT", dir);
 
288
        snprintf(fullname, sizeof(fullname) - 1, "%s/_VBA_PROJECT", dir);
282
289
        fd = open(fullname, O_RDONLY|O_BINARY);
283
290
 
284
291
        if (fd == -1) {
285
292
                cli_dbgmsg("Can't open %s\n", fullname);
286
 
                free(fullname);
287
293
                /* vba56_old_dir_read(dir); */
288
294
                return NULL;
289
295
        }
290
 
        free(fullname);
291
 
 
292
 
        if (cli_readn(fd, &magic, 2) != 2) {
293
 
                close(fd);
294
 
                return NULL;
295
 
        }
296
 
        if (memcmp(magic, vba56_signature, 2) != 0) {
297
 
                close(fd);
298
 
                return NULL;
299
 
        }
300
 
 
301
 
        if (cli_readn(fd, &version, 4) != 4) {
302
 
                close(fd);
303
 
                return NULL;
304
 
        }
305
 
        for (i=0 ; i < NUM_VBA_VERSIONS ; i++) {
306
 
                if (memcmp(version, vba_version[i].signature, 4) == 0) {
 
296
 
 
297
        if(cli_readn(fd, &v56h, sizeof(struct vba56_header)) != sizeof(struct vba56_header)) {
 
298
                close(fd);
 
299
                return NULL;
 
300
        }
 
301
        if (memcmp(v56h.magic, vba56_signature, sizeof(v56h.magic)) != 0) {
 
302
                close(fd);
 
303
                return NULL;
 
304
        }
 
305
 
 
306
        for(i = 0; i < NUM_VBA_VERSIONS; i++)
 
307
                if(memcmp(v56h.version, vba_version[i].signature, sizeof(vba_version[i].signature)) == 0)
307
308
                        break;
308
 
                }
309
 
        }
310
309
 
311
310
        if (i == NUM_VBA_VERSIONS) {
312
311
                cli_warnmsg("Unknown VBA version signature %x %x %x %x\n",
313
 
                        version[0], version[1], version[2], version[3]);
314
 
                if (version[3] == 0x01) {
315
 
                        cli_warnmsg("Guessing little-endian\n");
316
 
                        is_mac = FALSE;
317
 
                } else if (version[3] == 0x0e) {
318
 
                        cli_warnmsg("Guessing big-endian\n");
319
 
                        is_mac = TRUE;
320
 
                } else {
321
 
                        cli_warnmsg("Unable to guess VBA type\n");
322
 
                        close(fd);
323
 
                        return NULL;
324
 
                }       
 
312
                        v56h.version[0], v56h.version[1],
 
313
                        v56h.version[2], v56h.version[3]);
 
314
                switch(v56h.version[3]) {
 
315
                        case 0x01:
 
316
                                cli_warnmsg("Guessing little-endian\n");
 
317
                                is_mac = FALSE;
 
318
                                break;
 
319
                        case 0x0E:
 
320
                                cli_warnmsg("Guessing big-endian\n");
 
321
                                is_mac = TRUE;
 
322
                                break;
 
323
                        default:
 
324
                                cli_warnmsg("Unable to guess VBA type\n");
 
325
                                close(fd);
 
326
                                return NULL;
 
327
                }
325
328
        } else {
326
 
                cli_dbgmsg("VBA Project: %s, VBA Version=%d\n", vba_version[i].name,
327
 
                                vba_version[i].vba_version);
 
329
                cli_dbgmsg("VBA Project: %s\n", vba_version[i].name);
328
330
                is_mac = vba_version[i].is_mac;
329
331
        }
330
332
 
331
 
        /*****************************************/
332
 
 
333
 
        /* two bytes, should be equal to 0x00ff */
334
 
        if (cli_readn(fd, &ooff, 2) != 2) {
335
 
                close(fd);
336
 
                return NULL;
337
 
        }
338
 
 
339
 
        if (cli_readn(fd, &LidA, 4) != 4) {
340
 
                close(fd);
341
 
                return NULL;
342
 
        }
343
 
 
344
 
        if (cli_readn(fd, &LidB, 4) != 4) {
345
 
                close(fd);
346
 
                return NULL;
347
 
        }
348
 
 
349
 
        if (cli_readn(fd, &CharSet, 2) != 2) {
350
 
                close(fd);
351
 
                return NULL;
352
 
        }
353
 
        if (cli_readn(fd, &LenA, 2) != 2) {
354
 
                close(fd);
355
 
                return NULL;
356
 
        }
357
 
 
358
 
        if (cli_readn(fd, &UnknownB, 4) != 4) {
359
 
                close(fd);
360
 
                return NULL;
361
 
        }
362
 
        if (cli_readn(fd, &UnknownC, 4) != 4) {
363
 
                close(fd);
364
 
                return NULL;
365
 
        }
366
 
 
367
 
        if (cli_readn(fd, &LenB, 2) != 2) {
368
 
                close(fd);
369
 
                return NULL;
370
 
        }
371
 
        if (cli_readn(fd, &LenC, 2) != 2) {
372
 
                close(fd);
373
 
                return NULL;
374
 
        }
375
 
        if (cli_readn(fd, &LenD, 2) != 2) {
376
 
                close(fd);
377
 
                return NULL;
378
 
        }
379
 
 
380
 
        LidA = vba_endian_convert_32(LidA, is_mac);
381
 
        LidB = vba_endian_convert_32(LidB, is_mac);
382
 
        CharSet = vba_endian_convert_16(CharSet, is_mac);
383
 
        LenA = vba_endian_convert_16(LenA, is_mac);
384
 
        LenB = vba_endian_convert_16(LenB, is_mac);
385
 
        LenC = vba_endian_convert_16(LenC, is_mac);
386
 
        LenD = vba_endian_convert_16(LenD, is_mac);
387
 
 
388
 
        cli_dbgmsg(" LidA: %d\n LidB: %d\n CharSet: %d\n", LidA, LidB, CharSet);
389
 
        cli_dbgmsg(" LenA: %d\n UnknownB: %d\n UnknownC: %d\n", LenA, UnknownB, UnknownC);
390
 
        cli_dbgmsg(" LenB: %d\n LenC: %d\n LenD: %d\n", LenB, LenC, LenD);
391
 
 
392
 
        record_count = LenC;
393
 
 
394
333
        if (!vba_read_project_strings(fd, is_mac)) {
395
334
                close(fd);
396
335
                return NULL;
397
336
        }
398
 
        
 
337
 
399
338
        /* junk some more stuff */
400
339
        do {
401
 
                if (cli_readn(fd, &ooff, 2) != 2) {
 
340
                if (cli_readn(fd, &ffff, 2) != 2) {
402
341
                        close(fd);
403
342
                        return NULL;
404
343
                }
405
 
        } while(ooff != 0xFFFF);
 
344
        } while(ffff != 0xFFFF);
406
345
 
407
346
        /* check for alignment error */
408
347
        lseek(fd, -3, SEEK_CUR);
409
 
        if (cli_readn(fd, &ooff, 2) != 2) {
410
 
                close(fd);
 
348
        if (cli_readn(fd, &ffff, 2) != 2) {
 
349
                close(fd);
411
350
                return NULL;
412
351
        }
413
 
        if (ooff != 0xFFFF) {
 
352
        if (ffff != 0xFFFF) {
414
353
                lseek(fd, 1, SEEK_CUR);
415
354
        }
416
 
        
417
 
        if (cli_readn(fd, &ooff, 2) != 2) {
 
355
 
 
356
        if (cli_readn(fd, &ffff, 2) != 2) {
418
357
                close(fd);
419
358
                return NULL;
420
359
        }
421
360
 
422
361
        /* no idea what this stuff is */
423
 
        if (ooff != 0xFFFF) {
424
 
                ooff = vba_endian_convert_16(ooff, is_mac);
425
 
                lseek(fd, ooff, SEEK_CUR);
 
362
        if (ffff != 0xFFFF) {
 
363
                ffff = vba_endian_convert_16(ffff, is_mac);
 
364
                lseek(fd, ffff, SEEK_CUR);
426
365
        }
427
 
        if (cli_readn(fd, &ooff, 2) != 2) {
 
366
        if (cli_readn(fd, &ffff, 2) != 2) {
428
367
                close(fd);
429
368
                return NULL;
430
369
        }
431
 
        if (ooff != 0xFFFF) {
432
 
                ooff = vba_endian_convert_16(ooff, is_mac);
433
 
                lseek(fd, ooff, SEEK_CUR);
 
370
        if (ffff != 0xFFFF) {
 
371
                ffff = vba_endian_convert_16(ffff, is_mac);
 
372
                lseek(fd, ffff, SEEK_CUR);
434
373
        }
435
374
        lseek(fd, 100, SEEK_CUR);
436
375
 
442
381
        cli_dbgmsg("\nVBA Record count: %d\n", record_count);
443
382
        if (record_count == 0) {
444
383
                close(fd);
445
 
                return NULL;
446
 
        }
 
384
                return NULL;
 
385
        }
447
386
        if (record_count > 1000) {
448
387
                /* Almost certainly an error */
449
388
                cli_dbgmsg("\nVBA Record count too big");
450
389
                close(fd);
451
390
                return NULL;
452
391
        }
453
 
        
 
392
 
454
393
        vba_project = (vba_project_t *) cli_malloc(sizeof(struct vba_project_tag));
455
394
        if (!vba_project) {
456
395
                close(fd);
473
412
                return NULL;
474
413
        }
475
414
        vba_project->count = record_count;
476
 
        for (i=0 ; i < record_count ; i++) {
477
 
                if (cli_readn(fd, &length, 2) != 2) {
478
 
                        goto out_error;
479
 
                }
 
415
        for(i = 0; i < record_count; i++) {
 
416
                if(cli_readn(fd, &length, 2) != 2)
 
417
                        break;
 
418
 
480
419
                length = vba_endian_convert_16(length, is_mac);
481
420
                if (length == 0) {
482
421
                        cli_dbgmsg("zero name length\n");
483
 
                        goto out_error;
484
 
                }
 
422
                        break;
 
423
                }
485
424
                buff = (unsigned char *) cli_malloc(length);
486
425
                if (!buff) {
487
426
                        cli_dbgmsg("cli_malloc failed\n");
488
 
                        goto out_error;
 
427
                        break;
489
428
                }
490
429
                if (cli_readn(fd, buff, length) != length) {
491
430
                        cli_dbgmsg("read name failed\n");
492
431
                        free(buff);
493
 
                        goto out_error;
 
432
                        break;
494
433
                }
495
 
                vba_project->name[i] = get_unicode_name(buff, length, is_mac);
 
434
                vba_project->name[i] = get_unicode_name((const char *)buff, length, is_mac);
 
435
                free(buff);
496
436
                if (!vba_project->name[i]) {
497
437
                        offset = lseek(fd, 0, SEEK_CUR);
498
438
                        vba_project->name[i] = (char *) cli_malloc(18);
499
 
                        snprintf(vba_project->name[i], 18, "clamav-%.10d", offset);
 
439
                        if(vba_project->name[i] == NULL) {
 
440
                                break;
 
441
                        }
 
442
                        snprintf(vba_project->name[i], 18, "clamav-%.10d", (int)offset);
500
443
                }
501
444
                cli_dbgmsg("project name: %s, ", vba_project->name[i]);
502
 
                free(buff);
503
445
 
504
446
                /* some kind of string identifier ?? */
505
447
                if (cli_readn(fd, &length, 2) != 2) {
506
448
                        free(vba_project->name[i]);
507
 
                        goto out_error;
 
449
                        break;
508
450
                }
509
451
                length = vba_endian_convert_16(length, is_mac);
510
452
                lseek(fd, length, SEEK_CUR);
511
453
 
512
454
                /* unknown stuff */
513
 
                if (cli_readn(fd, &ooff, 2) != 2) {
 
455
                if (cli_readn(fd, &ffff, 2) != 2) {
514
456
                        free(vba_project->name[i]);
515
 
                        goto out_error;
 
457
                        break;
516
458
                }
517
 
                ooff = vba_endian_convert_16(ooff, is_mac);
518
 
                if (ooff == 0xFFFF) {
 
459
                ffff = vba_endian_convert_16(ffff, is_mac);
 
460
                if (ffff == 0xFFFF) {
519
461
                        lseek(fd, 2, SEEK_CUR);
520
 
                        if (cli_readn(fd, &ooff, 2) != 2) {
 
462
                        if (cli_readn(fd, &ffff, 2) != 2) {
521
463
                                free(vba_project->name[i]);
522
 
                                goto out_error;
 
464
                                break;
523
465
                        }
524
 
                        ooff = vba_endian_convert_16(ooff, is_mac);
525
 
                        lseek(fd, ooff, SEEK_CUR);
 
466
                        ffff = vba_endian_convert_16(ffff, is_mac);
 
467
                        lseek(fd, ffff, SEEK_CUR);
526
468
                } else {
527
 
                        lseek(fd, 2 + ooff, SEEK_CUR);
 
469
                        lseek(fd, 2 + ffff, SEEK_CUR);
528
470
                }
529
471
 
530
472
                lseek(fd, 8, SEEK_CUR);
531
473
                if (cli_readn(fd, &byte_count, 2) != 2) {
532
474
                        free(vba_project->name[i]);
533
 
                        goto out_error;
 
475
                        break;
534
476
                }
535
477
                byte_count = vba_endian_convert_16(byte_count, is_mac);
536
 
                for (j=0 ; j<byte_count; j++) {
537
 
                        lseek(fd, 8, SEEK_CUR);
538
 
                }
539
 
                lseek(fd, 5, SEEK_CUR);
 
478
                lseek(fd, (8 * byte_count) + 5, SEEK_CUR);
540
479
                if (cli_readn(fd, &offset, 4) != 4) {
541
480
                        free(vba_project->name[i]);
542
 
                        goto out_error;
 
481
                        break;
543
482
                }
544
483
                offset = vba_endian_convert_32(offset, is_mac);
545
484
                vba_project->offset[i] = offset;
546
485
                cli_dbgmsg("offset:%u\n", offset);
547
486
                lseek(fd, 2, SEEK_CUR);
548
487
        }
549
 
        
550
 
        
551
 
        { /* There appears to be some code in here */
552
 
        
553
 
        off_t foffset;
554
488
 
555
 
                foffset = lseek(fd, 0, SEEK_CUR);
556
 
                cli_dbgmsg("\nOffset: 0x%x\n", (unsigned int)foffset);
557
 
        }
558
489
        close(fd);
 
490
 
 
491
        if(i < record_count) {
 
492
                /* above loop failed */
 
493
                while(--i >= 0)
 
494
                        free(vba_project->name[i]);
 
495
 
 
496
                free(vba_project->name);
 
497
                free(vba_project->dir);
 
498
                free(vba_project->offset);
 
499
                free(vba_project);
 
500
                return NULL;
 
501
        }
 
502
 
559
503
        return vba_project;
560
 
 
561
 
out_error:
562
 
        /* Note: only to be called from the above loop
563
 
           when i == number of allocated stings */
564
 
        for (j=0 ; j<i ; j++) {
565
 
                free(vba_project->name[j]);
566
 
        }
567
 
        free(vba_project->name);
568
 
        free(vba_project->dir);
569
 
        free(vba_project->offset);
570
 
        free(vba_project);
571
 
        close(fd);
572
 
        return NULL;
573
 
}
574
 
 
575
 
#define VBA_COMPRESSION_WINDOW 4096
576
 
 
577
 
static void byte_array_append(byte_array_t *array, unsigned char *src, unsigned int len)
578
 
{
579
 
        if (array->length == 0) {
580
 
                array->data = (unsigned char *) cli_malloc(len);
581
 
                if (!array->data) {
582
 
                        return;
583
 
                }
584
 
                array->length = len;
585
 
                memcpy(array->data, src, len);
586
 
        } else {
587
 
                array->data = realloc(array->data, array->length+len);
588
 
                if (!array->data) {
589
 
                        return;
590
 
                }       
591
 
                memcpy(array->data+array->length, src, len);
592
 
                array->length += len;
593
 
        }
594
504
}
595
505
 
596
506
unsigned char *vba_decompress(int fd, uint32_t offset, int *size)
598
508
        unsigned int i, pos=0, shift, win_pos, clean=TRUE, mask, distance;
599
509
        uint8_t flag;
600
510
        uint16_t token, len;
 
511
        size_t s;
 
512
        blob *b;
 
513
        unsigned char *ret;
601
514
        unsigned char buffer[VBA_COMPRESSION_WINDOW];
602
 
        byte_array_t result;
603
 
        
604
 
        result.length=0;
605
 
        result.data=NULL;
606
 
        
607
 
        lseek(fd, offset+3, SEEK_SET); /* 1byte ?? , 2byte length ?? */ 
608
 
        
 
515
 
 
516
        b = blobCreate();
 
517
 
 
518
        if(b == NULL)
 
519
                return NULL;
 
520
 
 
521
        lseek(fd, offset+3, SEEK_SET); /* 1byte ?? , 2byte length ?? */
 
522
 
609
523
        while (cli_readn(fd, &flag, 1) == 1) {
610
524
                for (mask = 1; mask < 0x100; mask<<=1) {
611
525
                        if (flag & mask) {
612
526
                                if (cli_readn(fd, &token, 2) != 2) {
613
 
                                        if (result.data) {
614
 
                                                free(result.data);
615
 
                                        }
 
527
                                        blobDestroy(b);
616
528
                                        if (size) {
617
529
                                                *size = 0;
618
530
                                        }
635
547
                                                shift = 4;
636
548
                                        }
637
549
                                }
638
 
                                len = (token & ((1 << shift) -1)) + 3;
 
550
                                len = (uint16_t)((token & ((1 << shift) -1)) + 3);
639
551
                                distance = token >> shift;
640
552
                                clean = TRUE;
641
 
                                
 
553
 
642
554
                                for (i=0 ; i < len; i++) {
643
555
                                        unsigned int srcpos;
644
556
                                        unsigned char c;
645
 
                                        
 
557
 
646
558
                                        srcpos = (pos - distance - 1) % VBA_COMPRESSION_WINDOW;
647
559
                                        c = buffer[srcpos];
648
560
                                        buffer[pos++ % VBA_COMPRESSION_WINDOW]= c;
650
562
                        } else {
651
563
                                if ((pos != 0) &&
652
564
                                        ((pos % VBA_COMPRESSION_WINDOW) == 0) && clean) {
653
 
                                        
 
565
 
654
566
                                        if (cli_readn(fd, &token, 2) != 2) {
655
 
                                                if (result.data) {
656
 
                                                        free(result.data);
657
 
                                                }
658
 
                                                if (size) {
659
 
                                                       *size = 0;
660
 
                                                }
 
567
                                                blobDestroy(b);
 
568
                                                if(size)
 
569
                                                       *size = 0;
661
570
                                                return NULL;
662
571
                                        }
663
572
                                        clean = FALSE;
664
 
                                        byte_array_append(&result, buffer, VBA_COMPRESSION_WINDOW);
 
573
                                        (void)blobAddData(b, buffer, VBA_COMPRESSION_WINDOW);
665
574
                                        break;
666
575
                                }
667
576
                                if (cli_readn(fd, buffer+(pos%VBA_COMPRESSION_WINDOW), 1) == 1){
671
580
                        }
672
581
                }
673
582
        }
674
 
                        
675
 
        if (pos % VBA_COMPRESSION_WINDOW) {
676
 
                byte_array_append(&result, buffer, pos % VBA_COMPRESSION_WINDOW);
677
 
        }
678
 
        if (size) {
679
 
                *size = result.length;
680
 
        }
681
 
        return result.data;
682
583
 
 
584
        if (pos % VBA_COMPRESSION_WINDOW)
 
585
                if(blobAddData(b, buffer, pos%VBA_COMPRESSION_WINDOW) < 0) {
 
586
                        if(size)
 
587
                               *size = 0;
 
588
                        blobDestroy(b);
 
589
                        return NULL;
 
590
                }
 
591
        s = blobGetDataSize(b);
 
592
        ret = cli_malloc(s);
 
593
        if(ret == NULL) {
 
594
                blobDestroy(b);
 
595
                if(size)
 
596
                       *size = 0;
 
597
                return NULL;
 
598
        }
 
599
        if(size)
 
600
                *size = (int)s;
 
601
        memcpy(ret, blobGetData(b), s);
 
602
        blobDestroy(b);
 
603
        return ret;
683
604
}
684
605
 
685
606
static uint32_t ole_copy_file_data(int ifd, int ofd, uint32_t len)
686
607
{
687
 
        unsigned char data[8192];
688
608
        unsigned int count, rem;
689
 
        unsigned int todo;
 
609
        unsigned char data[FILEBUFF];
690
610
 
691
611
        rem = len;
692
612
 
693
613
        while (rem > 0) {
694
 
                todo = MIN(8192, rem);
 
614
                unsigned int todo = MIN(sizeof(data), rem);
 
615
 
695
616
                count = cli_readn(ifd, data, todo);
696
617
                if (count != todo) {
697
618
                        return len-rem;
698
619
                }
699
 
                if (cli_writen(ofd, data, count) != count) {
 
620
                if((unsigned int)cli_writen(ofd, data, count) != count)
700
621
                        return len-rem-count;
701
 
                }
702
622
                rem -= count;
703
623
        }
704
624
        return len;
708
628
{
709
629
        int ofd;
710
630
        struct stat statbuf;
711
 
        char ch, *fullname;
 
631
        char ch;
712
632
        uint32_t object_size;
 
633
        char fullname[NAME_MAX + 1];
713
634
 
714
635
        if (fstat(fd, &statbuf) == -1) {
715
636
                return -1;
716
637
        }
717
 
        
 
638
 
718
639
        if (cli_readn(fd, &object_size, 4) != 4) {
719
640
                return -1;
720
641
        }
725
646
                if (lseek(fd, 2, SEEK_CUR) == -1) {
726
647
                        return -1;
727
648
                }
728
 
                
 
649
 
729
650
                /* Skip attachment name */
730
651
                do {
731
652
                        if (cli_readn(fd, &ch, 1) != 1) {
732
653
                                return -1;
733
654
                        }
734
655
                } while (ch);
735
 
                
 
656
 
736
657
                /* Skip attachment full path */
737
658
                do {
738
659
                        if (cli_readn(fd, &ch, 1) != 1) {
739
660
                                return -1;
740
661
                        }
741
662
                } while (ch);
742
 
                
 
663
 
743
664
                /* Skip unknown data */
744
665
                if (lseek(fd, 8, SEEK_CUR) == -1) {
745
666
                        return -1;
746
667
                }
747
 
                
 
668
 
748
669
                /* Skip attachment full path */
749
670
                do {
750
671
                        if (cli_readn(fd, &ch, 1) != 1) {
751
672
                                return -1;
752
673
                        }
753
674
                } while (ch);
754
 
                
 
675
 
755
676
                if (cli_readn(fd, &object_size, 4) != 4) {
756
677
                        return -1;
757
678
                }
758
679
                object_size = vba_endian_convert_32(object_size, FALSE);
759
680
        }
760
 
        fullname = cli_malloc(strlen(dir) + 18);
761
 
        sprintf(fullname, "%s/_clam_ole_object", dir);
 
681
        snprintf(fullname, sizeof(fullname) - 1, "%s/_clam_ole_object", dir);
762
682
        ofd = open(fullname, O_RDWR|O_CREAT|O_TRUNC|O_BINARY, 0600);
763
 
        free(fullname);
764
 
        if (ofd < 0) {
 
683
        if (ofd < 0) {
765
684
                return -1;
766
685
        }
767
686
        ole_copy_file_data(fd, ofd, object_size);
790
709
                return FALSE;
791
710
        }
792
711
        atom_header->ver_inst = vba_endian_convert_16(atom_header->ver_inst, FALSE);
793
 
        atom_header->version = atom_header->ver_inst & 0x000f;
794
 
        atom_header->instance = atom_header->ver_inst >> 4;
795
 
        if (cli_readn(fd, &atom_header->type, 2) != 2) {
 
712
        atom_header->version = (uint8_t)(atom_header->ver_inst & 0x000f);
 
713
        atom_header->instance = (uint16_t)(atom_header->ver_inst >> 4);
 
714
        if(cli_readn(fd, &atom_header->type, sizeof(uint16_t)) != sizeof(uint16_t)) {
796
715
                cli_dbgmsg("read ppt_current_user failed\n");
797
716
                return FALSE;
798
717
        }
814
733
        cli_dbgmsg("  Length: 0x%.8x\n", atom_header->length);
815
734
}
816
735
 
817
 
#define PPT_LZW_BUFFSIZE 8192
818
736
static int ppt_unlzw(const char *dir, int fd, uint32_t length)
819
737
{
820
738
        int ofd, retval;
821
739
        unsigned char inbuff[PPT_LZW_BUFFSIZE], outbuff[PPT_LZW_BUFFSIZE];
822
 
        char *fullname;
823
740
        uint32_t bufflen;
824
741
        z_stream stream;
825
 
        
826
 
        fullname = cli_malloc(strlen(dir) + 17);
827
 
        if (!fullname) {
828
 
                return FALSE;
829
 
        }
830
 
        sprintf(fullname, "%s/ppt%.8lx.doc", dir, lseek(fd, 0, SEEK_CUR));
831
 
        
 
742
        char fullname[NAME_MAX + 1];
 
743
 
 
744
        snprintf(fullname, sizeof(fullname) - 1, "%s/ppt%.8lx.doc",
 
745
                dir, (long)lseek(fd, 0L, SEEK_CUR));
 
746
 
832
747
        ofd = open(fullname, O_WRONLY|O_CREAT|O_TRUNC|O_BINARY, 0600);
833
 
        free(fullname);
834
 
        if (ofd == -1) {
835
 
                cli_dbgmsg("ppt_unlzw Open outfile failed\n");
836
 
                return FALSE;
837
 
        }
838
 
        
 
748
        if (ofd == -1) {
 
749
                cli_dbgmsg("ppt_unlzw Open outfile failed\n");
 
750
                return FALSE;
 
751
        }
 
752
 
839
753
        stream.zalloc = Z_NULL;
840
754
        stream.zfree = Z_NULL;
841
755
        stream.opaque = (void *)0;
842
 
        
 
756
 
843
757
        stream.next_in = inbuff;
844
758
        bufflen = stream.avail_in = MIN(length, PPT_LZW_BUFFSIZE);
845
 
        
 
759
 
846
760
        if (cli_readn(fd, inbuff, stream.avail_in) != (int64_t)stream.avail_in) {
847
761
                close(ofd);
 
762
                unlink(fullname);
848
763
                return FALSE;
849
764
        }
850
765
        length -= stream.avail_in;
851
 
        
 
766
 
852
767
        retval = inflateInit(&stream);
853
768
        if (retval != Z_OK) {
854
769
                cli_dbgmsg(" ppt_unlzw !Z_OK: %d\n", retval);
855
770
        }
856
 
        
 
771
 
857
772
        stream.next_out = outbuff;
858
773
        stream.avail_out = PPT_LZW_BUFFSIZE;
859
 
        
 
774
 
860
775
        do {
861
776
                if (stream.avail_out == 0) {
862
777
                        if (cli_writen(ofd, outbuff, PPT_LZW_BUFFSIZE)
880
795
                }
881
796
                retval = inflate(&stream, Z_NO_FLUSH);
882
797
        } while (retval == Z_OK);
883
 
        
 
798
 
884
799
        if (cli_writen(ofd, outbuff, bufflen) != (int64_t)bufflen) {
885
800
                close(ofd);
886
801
                inflateEnd(&stream);
887
802
                return FALSE;
888
803
        }
889
804
        inflateEnd(&stream);
890
 
        close(ofd);
891
 
        return TRUE;
 
805
        return close(ofd);
892
806
}
893
807
 
894
808
static char *ppt_stream_iter(int fd)
895
809
{
896
 
        atom_header_t atom_header;
897
810
        uint32_t ole_id;
898
811
        char *out_dir;
899
812
        off_t offset;
900
 
        
 
813
        atom_header_t atom_header;
 
814
 
901
815
        /* Create a directory to store the extracted OLE2 objects */
902
816
        out_dir = cli_gentemp(NULL);
903
817
        if(mkdir(out_dir, 0700)) {
904
 
            printf("ScanOLE2 -> Can't create temporary directory %s\n", out_dir);
905
 
            free(out_dir);
906
 
            close(fd);
907
 
            return NULL;
 
818
                cli_errmsg("ScanOLE2 -> Can't create temporary directory %s\n", out_dir);
 
819
                free(out_dir);
 
820
                return NULL;
908
821
        }
909
822
 
910
 
        while (1) {
911
 
                if (!ppt_read_atom_header(fd, &atom_header)) {
912
 
                        break;
913
 
                }
 
823
        while(ppt_read_atom_header(fd, &atom_header)) {
914
824
                ppt_print_atom_header(&atom_header);
915
825
 
916
826
                if (atom_header.length == 0) {
928
838
                        }
929
839
                        ole_id = vba_endian_convert_32(ole_id, FALSE);
930
840
                        cli_dbgmsg("OleID: %d, length: %d\n",
931
 
                                        ole_id, atom_header.length-4);
 
841
                                        (int)ole_id, (int)atom_header.length-4);
932
842
                        if (!ppt_unlzw(out_dir, fd, atom_header.length-4)) {
933
843
                                cli_dbgmsg("ppt_unlzw failed\n");
934
844
                                cli_rmdirs(out_dir);
953
863
 
954
864
char *ppt_vba_read(const char *dir)
955
865
{
956
 
        char *fullname, *out_dir;
 
866
        char *out_dir;
957
867
        int fd;
 
868
        char fullname[NAME_MAX + 1];
958
869
 
959
 
        fullname = (char *) cli_malloc(strlen(dir) + 21);
960
 
        if (!fullname) {
961
 
                return NULL;
962
 
        }
963
 
        sprintf(fullname, "%s/PowerPoint Document", dir);
 
870
        snprintf(fullname, sizeof(fullname) - 1, "%s/PowerPoint Document", dir);
964
871
        fd = open(fullname, O_RDONLY|O_BINARY);
965
 
        free(fullname);
966
872
        if (fd == -1) {
967
 
                cli_dbgmsg("Open  PowerPoint Document failed\n");
 
873
                cli_dbgmsg("Open PowerPoint Document failed\n");
968
874
                return NULL;
969
875
        }
970
 
        
 
876
 
971
877
        out_dir = ppt_stream_iter(fd);
972
878
        close(fd);
973
879
        return out_dir;
979
885
/* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
980
886
 
981
887
typedef struct mso_fib_tag {
982
 
        uint16_t magic;
983
 
        uint16_t version;
984
 
        uint16_t product;
985
 
        uint16_t lid;
986
 
        uint16_t next;
987
 
        uint16_t status;
988
 
        /* block of 268 bytes - ignore */
 
888
        char ununsed[sizeof(uint16_t) + sizeof(uint16_t) +
 
889
                sizeof(uint16_t) + sizeof(uint16_t) + sizeof(uint16_t) +
 
890
                sizeof(uint16_t)];
989
891
        uint32_t macro_offset;
990
892
        uint32_t macro_len;
991
893
} mso_fib_t;
1007
909
        struct macro_entry_tag *macro_entry;
1008
910
} macro_info_t;
1009
911
 
1010
 
typedef struct macro_extname_tag {
1011
 
        uint8_t length;
1012
 
        unsigned char *extname;
1013
 
        uint16_t numref;
1014
 
} macro_extname_t;
1015
 
 
1016
 
typedef struct macro_extnames_tag {
1017
 
        uint16_t count;
1018
 
        struct macro_extname_tag *macro_extname;
1019
 
} macro_extnames_t;
1020
 
 
1021
 
typedef struct macro_intnames_tag {
1022
 
        uint16_t count;
1023
 
        struct macro_intname_tag *macro_intname;
1024
 
} macro_intnames_t;
1025
 
 
1026
 
typedef struct macro_intname_tag {
1027
 
        uint16_t id;
1028
 
        uint8_t length;
1029
 
        unsigned char *intname;
1030
 
} macro_intname_t;
1031
 
 
1032
 
typedef struct menu_entry_tag {
1033
 
        uint16_t context;
1034
 
        uint16_t menu;
1035
 
        uint16_t extname_i;
1036
 
        uint16_t unknown;
1037
 
        uint16_t intname_i;
1038
 
        uint16_t pos;
1039
 
} menu_entry_t;
1040
 
 
1041
 
typedef struct menu_info_tag {
1042
 
        uint16_t count;
1043
 
        struct menu_entry_tag *menu_entry;
1044
 
} menu_info_t;
1045
 
 
1046
 
typedef struct mac_token_tag {
1047
 
        unsigned char token;
1048
 
        unsigned char *str;
1049
 
} mac_token_t;
1050
 
 
1051
 
typedef struct mac_token2_tag {
1052
 
        uint16_t token;
1053
 
        unsigned char *str;
1054
 
 
1055
 
} mac_token2_t;
 
912
static  void    wm_free_macro_info(macro_info_t *macro_info);
1056
913
 
1057
914
static void wm_print_fib(mso_fib_t *fib)
1058
915
{
1059
 
        cli_dbgmsg("magic: 0x%.4x\n", fib->magic);
1060
 
        cli_dbgmsg("version: 0x%.4x\n", fib->version);
1061
 
        cli_dbgmsg("product: 0x%.4x\n", fib->product);
1062
 
        cli_dbgmsg("lid: 0x%.4x\n", fib->lid);
1063
916
        cli_dbgmsg("macro offset: 0x%.4x\n", fib->macro_offset);
1064
917
        cli_dbgmsg("macro len: 0x%.4x\n\n", fib->macro_len);
1065
918
}
1066
 
        
 
919
 
1067
920
static int wm_read_fib(int fd, mso_fib_t *fib)
1068
921
{
1069
 
        if (cli_readn(fd, &fib->magic, 2) != 2) {
1070
 
                cli_dbgmsg("read wm_fib failed\n");
1071
 
                return FALSE;
1072
 
        }
1073
 
        if (cli_readn(fd, &fib->version, 2) != 2) {
1074
 
                cli_dbgmsg("read wm_fib failed\n");
1075
 
                return FALSE;
1076
 
        }
1077
 
        if (cli_readn(fd, &fib->product, 2) != 2) {
1078
 
                cli_dbgmsg("read wm_fib failed\n");
1079
 
                return FALSE;
1080
 
        }
1081
 
        if (cli_readn(fd, &fib->lid, 2) != 2) {
1082
 
                cli_dbgmsg("read wm_fib failed\n");
1083
 
                return FALSE;
1084
 
        }       
1085
 
        if (cli_readn(fd, &fib->next, 2) != 2) {
1086
 
                cli_dbgmsg("read wm_fib failed\n");
1087
 
                return FALSE;
1088
 
        }
1089
 
        if (cli_readn(fd, &fib->status, 2) != 2) {
1090
 
                cli_dbgmsg("read wm_fib failed\n");
1091
 
                return FALSE;
1092
 
        }
1093
 
        
1094
922
        /* don't need the information is this block, so seek forward */
1095
923
        if (lseek(fd, 0x118, SEEK_SET) != 0x118) {
1096
924
                cli_dbgmsg("lseek wm_fib failed\n");
1097
925
                return FALSE;
1098
926
        }
1099
 
        
 
927
 
1100
928
        if (cli_readn(fd, &fib->macro_offset, 4) != 4) {
1101
929
                cli_dbgmsg("read wm_fib failed\n");
1102
930
                return FALSE;
1105
933
                cli_dbgmsg("read wm_fib failed\n");
1106
934
                return FALSE;
1107
935
        }
1108
 
        fib->magic = vba_endian_convert_16(fib->magic, FALSE);
1109
 
        fib->version = vba_endian_convert_16(fib->version, FALSE);
1110
 
        fib->product = vba_endian_convert_16(fib->product, FALSE);
1111
 
        fib->lid = vba_endian_convert_16(fib->lid, FALSE);
1112
 
        fib->next = vba_endian_convert_16(fib->next, FALSE);
1113
 
        fib->status = vba_endian_convert_16(fib->status, FALSE);
1114
936
        fib->macro_offset = vba_endian_convert_32(fib->macro_offset, FALSE);
1115
937
        fib->macro_len = vba_endian_convert_32(fib->macro_len, FALSE);
1116
 
        
 
938
 
1117
939
        return TRUE;
1118
940
}
1119
941
 
1130
952
        if (cli_readn(fd, &macro_entry->intname_i, 2) != 2) {
1131
953
                cli_dbgmsg("read macro_entry failed\n");
1132
954
                return FALSE;
1133
 
        }       
 
955
        }
1134
956
        if (cli_readn(fd, &macro_entry->extname_i, 2) != 2) {
1135
957
                cli_dbgmsg("read macro_entry failed\n");
1136
958
                return FALSE;
1155
977
                cli_dbgmsg("read macro_entry failed\n");
1156
978
                return FALSE;
1157
979
        }
1158
 
        
 
980
 
1159
981
        macro_entry->intname_i = vba_endian_convert_16(macro_entry->intname_i, FALSE);
1160
982
        macro_entry->extname_i = vba_endian_convert_16(macro_entry->extname_i, FALSE);
1161
983
        macro_entry->xname_i = vba_endian_convert_16(macro_entry->xname_i, FALSE);
1190
1012
        for (i=0 ; i < macro_info->count ; i++) {
1191
1013
                if (!wm_read_macro_entry(fd,
1192
1014
                                &macro_info->macro_entry[i])) {
1193
 
                        free(macro_info->macro_entry);
1194
 
                        free(macro_info);
 
1015
                        wm_free_macro_info(macro_info);
1195
1016
                        return NULL;
1196
1017
                }
1197
1018
        }
1198
1019
        return macro_info;
1199
1020
}
1200
1021
 
1201
 
static void wm_free_macro_info(macro_info_t *macro_info)
 
1022
static  void
 
1023
wm_free_macro_info(macro_info_t *macro_info)
1202
1024
{
1203
1025
        if (macro_info) {
1204
1026
                free(macro_info->macro_entry);
1205
1027
                free(macro_info);
1206
1028
        }
1207
 
        return;
1208
1029
}
1209
1030
 
1210
1031
static int wm_read_oxo3(int fd)
1220
1041
                return FALSE;
1221
1042
        }
1222
1043
        cli_dbgmsg("oxo3 records1: %d\n", count);
1223
 
        
 
1044
 
1224
1045
        if (cli_readn(fd, &count, 1) != 1) {
1225
1046
                cli_dbgmsg("read oxo3 record2 failed\n");
1226
1047
                return FALSE;
1244
1065
                        cli_dbgmsg("lseek oxo3 failed\n");
1245
1066
                        return FALSE;
1246
1067
                }
1247
 
        }                               
 
1068
        }
1248
1069
        cli_dbgmsg("oxo3 records2: %d\n", count);
1249
1070
        return TRUE;
1250
1071
}
1251
1072
 
1252
 
static menu_info_t *wm_read_menu_info(int fd)
 
1073
static int
 
1074
wm_skip_menu_info(int fd)
1253
1075
{
1254
 
        int i;
1255
 
        menu_info_t *menu_info;
1256
 
        menu_entry_t *menu_entry;
1257
 
        
1258
 
        menu_info = (menu_info_t *) cli_malloc(sizeof(menu_info_t));
1259
 
        if (!menu_info) {
1260
 
                return NULL;
1261
 
        }
1262
 
        
1263
 
        if (cli_readn(fd, &menu_info->count, 2) != 2) {
 
1076
        uint16_t count;
 
1077
 
 
1078
        if (cli_readn(fd, &count, sizeof(uint16_t)) != sizeof(uint16_t)) {
1264
1079
                cli_dbgmsg("read menu_info failed\n");
1265
 
                free(menu_info);
1266
 
                return NULL;
1267
 
        }
1268
 
        menu_info->count = vba_endian_convert_16(menu_info->count, FALSE);
1269
 
        cli_dbgmsg("menu_info count: %d\n", menu_info->count);
1270
 
        
1271
 
        menu_info->menu_entry =
1272
 
                (menu_entry_t *) cli_malloc(sizeof(menu_entry_t) * menu_info->count);
1273
 
        if (!menu_info->menu_entry) {
1274
 
                free(menu_info);
1275
 
                return NULL;
1276
 
        }
1277
 
        
1278
 
        for (i=0 ; i < menu_info->count ; i++) {
1279
 
                menu_entry = &menu_info->menu_entry[i];
1280
 
                if (cli_readn(fd, &menu_entry->context, 2) != 2) {
1281
 
                        goto abort;
1282
 
                }
1283
 
                if (cli_readn(fd, &menu_entry->menu, 2) != 2) {
1284
 
                        goto abort;
1285
 
                }
1286
 
                if (cli_readn(fd, &menu_entry->extname_i, 2) != 2) {
1287
 
                        goto abort;
1288
 
                }
1289
 
                if (cli_readn(fd, &menu_entry->unknown, 2) != 2) {
1290
 
                        goto abort;
1291
 
                }
1292
 
                if (cli_readn(fd, &menu_entry->intname_i, 2) != 2) {
1293
 
                        goto abort;
1294
 
                }
1295
 
                if (cli_readn(fd, &menu_entry->pos, 2) != 2) {
1296
 
                        goto abort;
1297
 
                }
1298
 
                menu_entry->context = vba_endian_convert_16(menu_entry->context, FALSE);
1299
 
                menu_entry->menu = vba_endian_convert_16(menu_entry->menu, FALSE);
1300
 
                menu_entry->extname_i = vba_endian_convert_16(menu_entry->extname_i, FALSE);
1301
 
                menu_entry->intname_i = vba_endian_convert_16(menu_entry->intname_i, FALSE);
1302
 
                menu_entry->pos = vba_endian_convert_16(menu_entry->pos, FALSE);
1303
 
                cli_dbgmsg("menu entry: %d.%d\n", menu_entry->menu, menu_entry->pos);
1304
 
        }
1305
 
        return menu_info;
1306
 
        
1307
 
abort:
1308
 
        cli_dbgmsg("read menu_entry failed\n");
1309
 
        free(menu_info->menu_entry);
1310
 
        free(menu_info);
1311
 
        return NULL;
1312
 
}
1313
 
 
1314
 
static void wm_free_menu_info(menu_info_t *menu_info)
1315
 
{
1316
 
        if (menu_info) {
1317
 
                free(menu_info->menu_entry);
1318
 
                free(menu_info);
1319
 
        }
1320
 
        return;
1321
 
}
1322
 
 
1323
 
static macro_extnames_t *wm_read_macro_extnames(int fd)
1324
 
{
1325
 
        int i, is_unicode=0;
 
1080
                return FALSE;
 
1081
        }
 
1082
        count = vba_endian_convert_16(count, FALSE);
 
1083
        cli_dbgmsg("menu_info count: %d\n", count);
 
1084
 
 
1085
        if(count)
 
1086
                if(lseek(fd, count * 12, SEEK_CUR) == -1)
 
1087
                        return FALSE;
 
1088
        return TRUE;
 
1089
}
 
1090
 
 
1091
static int
 
1092
wm_skip_macro_extnames(int fd)
 
1093
{
 
1094
        int is_unicode;
1326
1095
        int16_t size;
1327
 
        off_t offset_end;       
1328
 
        macro_extnames_t *macro_extnames;
1329
 
        macro_extname_t *macro_extname;
1330
 
        unsigned char *name_tmp;
1331
 
        
1332
 
        macro_extnames = (macro_extnames_t *) cli_malloc(sizeof(macro_extnames_t));
1333
 
        if (!macro_extnames) {
1334
 
                return NULL;
1335
 
        }
1336
 
        macro_extnames->count = 0;
1337
 
        macro_extnames->macro_extname = NULL;
1338
 
        
1339
 
        offset_end = lseek(fd, 0, SEEK_CUR);
1340
 
        if (cli_readn(fd, &size, 2) != 2) {
 
1096
        off_t offset_end = lseek(fd, 0, SEEK_CUR);
 
1097
 
 
1098
        if(cli_readn(fd, &size, sizeof(int16_t)) != sizeof(int16_t)) {
1341
1099
                cli_dbgmsg("read macro_extnames failed\n");
1342
 
                free(macro_extnames);
1343
 
                return NULL;
 
1100
                return FALSE;
1344
1101
        }
1345
1102
        size = vba_endian_convert_16(size, FALSE);
1346
1103
        if (size == -1) { /* Unicode flag */
1347
 
                is_unicode=1;
1348
 
                if (cli_readn(fd, &size, 2) != 2) {
 
1104
                if(cli_readn(fd, &size, sizeof(int16_t)) != sizeof(int16_t)) {
1349
1105
                        cli_dbgmsg("read macro_extnames failed\n");
1350
 
                        free(macro_extnames);
1351
 
                        return NULL;
 
1106
                        return FALSE;
1352
1107
                }
1353
1108
                size = vba_endian_convert_16(size, FALSE);
1354
 
        }
 
1109
                is_unicode = 1;
 
1110
        } else
 
1111
                is_unicode = 0;
 
1112
 
1355
1113
        cli_dbgmsg("ext names size: 0x%x\n", size);
1356
1114
 
1357
1115
        offset_end += size;
1358
 
        while (lseek(fd, 0, SEEK_CUR) < offset_end) {
1359
 
                macro_extnames->count++;
1360
 
                macro_extnames->macro_extname = (macro_extname_t *)
1361
 
                        cli_realloc2(macro_extnames->macro_extname,
1362
 
                                sizeof(macro_extname_t) * macro_extnames->count);
1363
 
                if (macro_extnames->macro_extname == NULL) {
1364
 
                        cli_dbgmsg("read macro_extnames failed\n");
1365
 
                        goto abort;;
1366
 
                }
1367
 
 
1368
 
                macro_extname = &macro_extnames->macro_extname[macro_extnames->count-1];
1369
 
                if (is_unicode) {
1370
 
                        if (cli_readn(fd, &macro_extname->length, 1) != 1) {
1371
 
                                cli_dbgmsg("read macro_extnames failed\n");
1372
 
                                goto abort;
1373
 
                        }
1374
 
                        lseek(fd, 1, SEEK_CUR);
1375
 
                        if (macro_extname->length > 0) {
1376
 
                            name_tmp = (char *) cli_malloc(macro_extname->length*2);
1377
 
                            if (name_tmp == NULL) {
1378
 
                                goto abort;
1379
 
                            }
1380
 
                            if (cli_readn(fd, name_tmp, macro_extname->length*2) != 
1381
 
                                                macro_extname->length*2) {
1382
 
                                cli_dbgmsg("read macro_extnames failed\n");
1383
 
                                free(name_tmp);
1384
 
                                goto abort;
1385
 
                            }
1386
 
                            macro_extname->extname =
1387
 
                                get_unicode_name(name_tmp, macro_extname->length*2, FALSE);
1388
 
                            free(name_tmp);
1389
 
                        } else {
1390
 
                            macro_extname->extname = cli_strdup("[no name]");
1391
 
                            macro_extname->length = 10;
1392
 
                        }
1393
 
                } else {
1394
 
                        if (cli_readn(fd, &macro_extname->length, 1) != 1) {
1395
 
                                cli_dbgmsg("read macro_extnames failed\n");
1396
 
                                goto abort;
1397
 
                        }
1398
 
                        if (macro_extname->length > 0) {
1399
 
                            macro_extname->extname = (char *) cli_malloc(macro_extname->length+1);
1400
 
                            if (!macro_extname->extname) {
1401
 
                                goto abort;
1402
 
                            }
1403
 
                            if (cli_readn(fd, macro_extname->extname, macro_extname->length) != 
1404
 
                                                macro_extname->length) {
1405
 
                                cli_dbgmsg("read macro_extnames failed\n");
1406
 
                                free(macro_extname->extname);
1407
 
                                goto abort;
1408
 
                            }
1409
 
                            macro_extname->extname[macro_extname->length] = '\0';
1410
 
                        } else {
1411
 
                            macro_extname->extname = cli_strdup("[no name]");
1412
 
                            macro_extname->length = 10;
1413
 
                        }
1414
 
                }
1415
 
                if (cli_readn(fd, &macro_extname->numref, 2) != 2) {
1416
 
                        cli_dbgmsg("read macro_extnames failed\n");
1417
 
                        return NULL;
1418
 
                }       
1419
 
                macro_extname->numref = vba_endian_convert_16(macro_extname->numref, FALSE);
1420
 
                cli_dbgmsg("ext name: %s\n", macro_extname->extname);
1421
 
        }
1422
 
        return macro_extnames;
1423
 
        
1424
 
abort:
1425
 
        if (macro_extnames->macro_extname != NULL) {
1426
 
                for (i=0 ; i < macro_extnames->count-1 ; i++) {
1427
 
                        free(macro_extnames->macro_extname[i].extname);
1428
 
                }
1429
 
                free(macro_extnames->macro_extname);
1430
 
        }
1431
 
        free(macro_extnames);
1432
 
        return NULL;
1433
 
}
1434
 
 
1435
 
static void wm_free_extnames(macro_extnames_t *macro_extnames)
1436
 
{
1437
 
        int i;
1438
 
        
1439
 
        if (macro_extnames) {
1440
 
                for (i=0 ; i < macro_extnames->count ; i++) {
1441
 
                        free(macro_extnames->macro_extname[i].extname);
1442
 
                }
1443
 
                free(macro_extnames->macro_extname);
1444
 
                free(macro_extnames);
1445
 
        }
1446
 
        return;
1447
 
}
1448
 
 
1449
 
static macro_intnames_t *wm_read_macro_intnames(int fd)
1450
 
{
1451
 
        int i;
1452
 
        macro_intnames_t *macro_intnames;
1453
 
        macro_intname_t *macro_intname;
1454
 
        uint16_t junk;
1455
 
        
1456
 
        macro_intnames = (macro_intnames_t *) cli_malloc(sizeof(macro_intnames_t));
1457
 
        if (!macro_intnames) {
1458
 
                return NULL;
1459
 
        }
1460
 
        
1461
 
        if (cli_readn(fd, &macro_intnames->count, 2) != 2) {
 
1116
        while(lseek(fd, 0, SEEK_CUR) < offset_end) {
 
1117
                uint8_t length;
 
1118
                off_t offset;
 
1119
 
 
1120
                if (cli_readn(fd, &length, 1) != 1) {
 
1121
                        cli_dbgmsg("read macro_extnames failed\n");
 
1122
                        return FALSE;
 
1123
                }
 
1124
 
 
1125
                if(is_unicode)
 
1126
                        offset = (off_t)length * 2 + 1;
 
1127
                else
 
1128
                        offset = (off_t)length;
 
1129
 
 
1130
                offset += sizeof(uint16_t);     /* numref */
 
1131
                if(lseek(fd, offset, SEEK_CUR) == -1) {
 
1132
                        cli_dbgmsg("read macro_extnames failed to seek\n");
 
1133
                        return FALSE;
 
1134
                }
 
1135
        }
 
1136
        return TRUE;
 
1137
}
 
1138
 
 
1139
static int
 
1140
wm_skip_macro_intnames(int fd)
 
1141
{
 
1142
        uint16_t i, count;
 
1143
 
 
1144
        if (cli_readn(fd, &count, sizeof(uint16_t)) != sizeof(uint16_t)) {
1462
1145
                cli_dbgmsg("read macro_intnames failed\n");
1463
 
                return NULL;
1464
 
        }
1465
 
        macro_intnames->count = vba_endian_convert_16(macro_intnames->count, FALSE);
1466
 
        cli_dbgmsg("int names count: %d\n", macro_intnames->count);
1467
 
        
1468
 
        macro_intnames->macro_intname =
1469
 
                (macro_intname_t *) cli_malloc(sizeof(macro_intname_t) * macro_intnames->count);
1470
 
        if (!macro_intnames->macro_intname) {
1471
 
                free(macro_intnames);
1472
 
                return NULL;
1473
 
        }
1474
 
        for (i=0 ; i < macro_intnames->count ; i++) {
1475
 
                macro_intname = &macro_intnames->macro_intname[i];
1476
 
                if (cli_readn(fd, &macro_intname->id, 2) != 2) {
1477
 
                        cli_dbgmsg("read macro_intnames failed\n");
1478
 
                        macro_intnames->count = i;
1479
 
                        goto abort;
1480
 
                }
1481
 
                macro_intname->id = vba_endian_convert_16(macro_intname->id, FALSE);
1482
 
                if (cli_readn(fd, &macro_intname->length, 1) != 1) {
1483
 
                        cli_dbgmsg("read macro_intnames failed\n");
1484
 
                        macro_intnames->count = i;
1485
 
                        goto abort;;
1486
 
                }       
1487
 
                macro_intname->intname = (char *) cli_malloc(macro_intname->length+1);
1488
 
                if (!macro_intname->intname) {
1489
 
                        macro_intnames->count = i;
1490
 
                        goto abort;
1491
 
                }
1492
 
                if (cli_readn(fd, macro_intname->intname, macro_intname->length) != macro_intname->length) {
1493
 
                        cli_dbgmsg("read macro_intnames failed\n");
1494
 
                        macro_intnames->count = i+1;
1495
 
                        goto abort;
1496
 
                }
1497
 
                macro_intname->intname[macro_intname->length] = '\0';
1498
 
                if (cli_readn(fd, &junk, 1) != 1) {
1499
 
                        cli_dbgmsg("read macro_intnames failed\n");
1500
 
                        macro_intnames->count = i+1;
1501
 
                        goto abort;
1502
 
                }
1503
 
                cli_dbgmsg("int name: %s\n", macro_intname->intname);
1504
 
        }
1505
 
        return macro_intnames;
1506
 
abort:
1507
 
        for (i=0 ; i < macro_intnames->count ; i++) {
1508
 
                free(macro_intnames->macro_intname[i].intname);
1509
 
        }
1510
 
        free(macro_intnames->macro_intname);
1511
 
        free(macro_intnames);
1512
 
        return NULL;
1513
 
}
1514
 
 
1515
 
static void wm_free_intnames(macro_intnames_t *macro_intnames)
1516
 
{
1517
 
        int i;
1518
 
        
1519
 
        if (macro_intnames) {
1520
 
                for (i=0 ; i < macro_intnames->count ; i++) {
1521
 
                        free(macro_intnames->macro_intname[i].intname);
1522
 
                }
1523
 
                free(macro_intnames->macro_intname);
1524
 
                free(macro_intnames);
1525
 
        }
1526
 
        return;
 
1146
                return FALSE;
 
1147
        }
 
1148
        count = vba_endian_convert_16(count, FALSE);
 
1149
        cli_dbgmsg("int names count: %u\n", count);
 
1150
 
 
1151
        for(i = 0; i < count; i++) {
 
1152
                uint8_t length;
 
1153
 
 
1154
                /* id */
 
1155
                if(lseek(fd, sizeof(uint16_t), SEEK_CUR) == -1) {
 
1156
                        cli_dbgmsg("skip_macro_intnames failed\n");
 
1157
                        return FALSE;
 
1158
                }
 
1159
 
 
1160
                if(cli_readn(fd, &length, sizeof(uint8_t)) != sizeof(uint8_t)) {
 
1161
                        cli_dbgmsg("skip_macro_intnames failed\n");
 
1162
                        return FALSE;
 
1163
                }
 
1164
 
 
1165
                /* Internal name, plus one byte of unknown data */
 
1166
                if(lseek(fd, length + 1, SEEK_CUR) == -1) {
 
1167
                        cli_dbgmsg("skip_macro_intnames failed\n");
 
1168
                        return FALSE;
 
1169
                }
 
1170
        }
 
1171
        return TRUE;
1527
1172
}
1528
1173
 
1529
1174
vba_project_t *wm_dir_read(const char *dir)
1530
1175
{
1531
 
        int fd, done=FALSE, i;
1532
 
        mso_fib_t fib;
 
1176
        int fd, done;
1533
1177
        off_t end_offset;
1534
 
        unsigned char start_id, info_id;
 
1178
        unsigned char info_id;
1535
1179
        macro_info_t *macro_info=NULL;
1536
 
        menu_info_t *menu_info=NULL;
1537
 
        macro_extnames_t *macro_extnames=NULL;
1538
 
        macro_intnames_t *macro_intnames=NULL;
1539
 
        vba_project_t *vba_project=NULL;
1540
 
        char *fullname;
1541
 
        
1542
 
        fullname = (char *) cli_malloc(strlen(dir) + 14);
1543
 
        if (!fullname) {
1544
 
                return NULL;
1545
 
        }
1546
 
        sprintf(fullname, "%s/WordDocument", dir);
 
1180
        vba_project_t *vba_project;
 
1181
        mso_fib_t fib;
 
1182
        char fullname[NAME_MAX + 1];
 
1183
 
 
1184
        snprintf(fullname, sizeof(fullname) - 1, "%s/WordDocument", dir);
1547
1185
        fd = open(fullname, O_RDONLY|O_BINARY);
1548
 
        free(fullname);
1549
1186
        if (fd == -1) {
1550
1187
                cli_dbgmsg("Open WordDocument failed\n");
1551
1188
                return NULL;
1552
1189
        }
1553
 
        
 
1190
 
1554
1191
        if (!wm_read_fib(fd, &fib)) {
1555
1192
                close(fd);
1556
1193
                return NULL;
1557
1194
        }
 
1195
        if(fib.macro_len == 0) {
 
1196
                cli_dbgmsg("No macros detected\n");
 
1197
                /* Must be clean */
 
1198
                close(fd);
 
1199
                return NULL;
 
1200
        }
1558
1201
        wm_print_fib(&fib);
1559
 
        
1560
 
        if (lseek(fd, fib.macro_offset, SEEK_SET) != (int64_t)fib.macro_offset) {
 
1202
 
 
1203
        /* Go one past the start to ignore start_id */
 
1204
        if (lseek(fd, fib.macro_offset + 1, SEEK_SET) != (off_t)(fib.macro_offset + 1)) {
1561
1205
                cli_dbgmsg("lseek macro_offset failed\n");
1562
1206
                close(fd);
1563
1207
                return NULL;
1564
1208
        }
1565
 
        
 
1209
 
1566
1210
        end_offset = fib.macro_offset + fib.macro_len;
1567
 
        
1568
 
        if (cli_readn(fd, &start_id, 1) != 1) {
1569
 
                cli_dbgmsg("read start_id failed\n");
1570
 
                close(fd);
1571
 
                return NULL;
1572
 
        }
1573
 
        cli_dbgmsg("start_id: %d\n", start_id);
1574
 
        
 
1211
        done = FALSE;
 
1212
 
1575
1213
        while ((lseek(fd, 0, SEEK_CUR) < end_offset) && !done) {
1576
1214
                if (cli_readn(fd, &info_id, 1) != 1) {
1577
1215
                        cli_dbgmsg("read macro_info failed\n");
1580
1218
                }
1581
1219
                switch (info_id) {
1582
1220
                        case 0x01:
 
1221
                                if(macro_info)
 
1222
                                        wm_free_macro_info(macro_info);
1583
1223
                                macro_info = wm_read_macro_info(fd);
1584
 
                                if (macro_info == NULL) {
 
1224
                                if(macro_info == NULL)
1585
1225
                                        done = TRUE;
1586
 
                                }
1587
1226
                                break;
1588
1227
                        case 0x03:
1589
 
                                if (!wm_read_oxo3(fd)) {
 
1228
                                if(!wm_read_oxo3(fd))
1590
1229
                                        done = TRUE;
1591
 
                                }
1592
1230
                                break;
1593
1231
                        case 0x05:
1594
 
                                menu_info = wm_read_menu_info(fd);
1595
 
                                if (menu_info == NULL) {
 
1232
                                if(!wm_skip_menu_info(fd))
1596
1233
                                        done = TRUE;
1597
 
                                }
1598
1234
                                break;
1599
1235
                        case 0x10:
1600
 
                                macro_extnames = wm_read_macro_extnames(fd);
1601
 
                                if (macro_extnames == NULL) {
 
1236
                                if(!wm_skip_macro_extnames(fd))
1602
1237
                                        done = TRUE;
1603
 
                                }
1604
1238
                                break;
1605
1239
                        case 0x11:
1606
 
                                macro_intnames = wm_read_macro_intnames(fd);
1607
 
                                if (macro_intnames == NULL) {
 
1240
                                if(!wm_skip_macro_intnames(fd))
1608
1241
                                        done = TRUE;
1609
 
                                }                               
1610
1242
                                break;
1611
1243
                        case 0x12:
1612
1244
                                /* No sure about these, always seems to
1613
1245
                                come after the macros though, so finish
1614
1246
                                */
1615
 
                                done = 1;
 
1247
                                done = TRUE;
1616
1248
                                break;
1617
1249
                        case 0x40:
1618
1250
                                /* end marker */
1619
 
                                done = 1;
 
1251
                                done = TRUE;
1620
1252
                                break;
1621
1253
                        default:
1622
 
                                cli_dbgmsg("\nunknown type: 0x%x\n", info_id);
1623
 
                                done = 1;
 
1254
                                cli_dbgmsg("unknown type: 0x%x\n", info_id);
 
1255
                                done = TRUE;
1624
1256
                }
1625
1257
        }
1626
 
        
 
1258
 
 
1259
        close(fd);
 
1260
 
1627
1261
        if (macro_info) {
1628
1262
                vba_project = (vba_project_t *) cli_malloc(sizeof(struct vba_project_tag));
1629
1263
                if (!vba_project) {
1640
1274
                                        macro_info->count);
1641
1275
                if (!vba_project->offset) {
1642
1276
                        free(vba_project->name);
1643
 
                        free(vba_project->dir);
 
1277
                        if(vba_project->dir)
 
1278
                                free(vba_project->dir);
1644
1279
                        free(vba_project);
1645
1280
                        vba_project = NULL;
1646
1281
                        goto abort;
1664
1299
                        free(vba_project->dir);
1665
1300
                        free(vba_project);
1666
1301
                        vba_project = NULL;
1667
 
                        goto abort;
1668
 
                }
1669
 
                vba_project->count = macro_info->count;
1670
 
                for (i=0 ; i < macro_info->count ; i++) {
1671
 
                        vba_project->name[i] = cli_strdup("WordDocument");
1672
 
                        vba_project->offset[i] = macro_info->macro_entry[i].offset;
1673
 
                        vba_project->length[i] = macro_info->macro_entry[i].len;
1674
 
                        vba_project->key[i] = macro_info->macro_entry[i].key;
1675
 
                }
1676
 
        }
1677
 
        /* Fall through */
 
1302
                } else {
 
1303
                        int i;
 
1304
 
 
1305
                        vba_project->count = macro_info->count;
 
1306
                        for(i = 0; i < macro_info->count; i++) {
 
1307
                                vba_project->name[i] = cli_strdup("WordDocument");
 
1308
                                vba_project->offset[i] = macro_info->macro_entry[i].offset;
 
1309
                                vba_project->length[i] = macro_info->macro_entry[i].len;
 
1310
                                vba_project->key[i] = macro_info->macro_entry[i].key;
 
1311
                        }
 
1312
                }
1678
1313
abort:
1679
 
        if (macro_info) {
1680
1314
                wm_free_macro_info(macro_info);
1681
 
        }
1682
 
        if (menu_info) {
1683
 
                wm_free_menu_info(menu_info);
1684
 
        }
1685
 
        if (macro_extnames) {
1686
 
                wm_free_extnames(macro_extnames);
1687
 
        }
1688
 
        if (macro_intnames) {
1689
 
                wm_free_intnames(macro_intnames);
1690
 
        }
1691
 
        close(fd);
 
1315
                /* Fall through */
 
1316
        } else
 
1317
                vba_project = NULL;
 
1318
 
1692
1319
        return vba_project;
1693
1320
}
1694
1321
 
1697
1324
{
1698
1325
        unsigned char *buff;
1699
1326
        uint32_t i;
1700
 
        
 
1327
 
1701
1328
        if (lseek(fd, offset, SEEK_SET) != (int64_t)offset) {
1702
1329
                return NULL;
1703
1330
        }
1706
1333
                return NULL;
1707
1334
        }
1708
1335
 
1709
 
        if (cli_readn(fd, buff, len) != (int64_t)len) {
 
1336
        if (cli_readn(fd, buff, len) != (int)len) {
1710
1337
                free(buff);
1711
1338
                return NULL;
1712
1339
        }
1713
 
        if (key != 0) {
1714
 
                for (i=0 ; i < len; i++) {
1715
 
                        buff[i] = buff[i] ^ key;
1716
 
                }
1717
 
        }
 
1340
        if (key != 0)
 
1341
                for (i=0 ; i < len; i++)
 
1342
                        buff[i] ^= key;
1718
1343
        return buff;
1719
1344
}