Coverage Report

Created: 2026-11-12 07:01

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/wireshark/epan/dissectors/file-zip.c
Line
Count
Source
1
/* file-zip.c
2
 *
3
 * Routines for ZIP File dissection
4
 * Copyright 2026, John Thacker <johnthacker@gmail.com>.
5
 *
6
 * Wireshark - Network traffic analyzer
7
 * By Gerald Combs <gerald@wireshark.org>
8
 * Copyright 1998 Gerald Combs
9
 *
10
 * https://pkware.cachefly.net/webdocs/casestudies/APPNOTE.TXT
11
 * https://libzip.org/specifications/
12
 *
13
 * Most ZIP tools scan from the end of the file to find the central directory
14
 * listing, and indeed the specification only truly makes sense considering
15
 * this possibility. It also makes sense in the context of spanning archives
16
 * across multiple removable floppy disks or splitting them into files (where
17
 * the last disk would be the one inserted first for dearchiving, or the last
18
 * file would have the .zip extension), adding or removing files to an archive
19
 * without rewriting everything (which leaves gaps; cf. tar, where gaps are
20
 * not allowed and deletion is more work), etc.
21
 *
22
 * This streams from the beginning (see Mark Adler's sunzip for the approach),
23
 * which probably will fail on some files that other tools will handle,
24
 * although it has the advantage of inherently not falling prey to zip bombs
25
 * that use overlapping files:
26
 * https://www.usenix.org/system/files/woot19-paper_fifield_0.pdf
27
 * https://github.com/madler/sunzip
28
 *
29
 * ISO/IEC 21320-1:2015 specifies a restricted subset of ZIP files, with
30
 * annotations specifically disallowing the spanning/splitting, encryption,
31
 * digital signatures, and patched data features, allowing only compression
32
 * methods 0 ("stored") and 8 ("deflated"), and recommending setting the
33
 * UTF-8 bit.
34
 *
35
 * SPDX-License-Identifier: GPL-2.0-or-later
36
 */
37
38
#include "config.h"
39
#include <epan/packet.h>
40
#include <epan/expert.h>
41
#include <epan/crc32-tvb.h>
42
#include <epan/export_object.h>
43
#include <epan/tfs.h>
44
#include <epan/unit_strings.h>
45
#include <wsutil/array.h>
46
47
#include "packet-smb.h"
48
49
void proto_reg_handoff_zip(void);
50
void proto_register_zip(void);
51
52
static int proto_zip;
53
54
static dissector_handle_t zip_handle;
55
56
static dissector_table_t zip_record_dissector_table;
57
static dissector_table_t zip_extra_dissector_table;
58
59
static int zip_eo_tap;
60
61
// Header fields
62
static int hf_zip_file;
63
static int hf_zip_directory;
64
static int hf_zip_end_of_directory;
65
static int hf_zip64_end_of_directory;
66
static int hf_zip64_end_of_directory_locator;
67
static int hf_zip_record_signature;
68
static int hf_zip_made_by;
69
static int hf_zip_version_made_by;
70
static int hf_zip_host_made_by;
71
static int hf_zip_version_to_extract;
72
73
static int hf_zip_flags;
74
static int hf_zip_flag_encryption;
75
static int hf_zip_flag_deflate_opts;
76
static int hf_zip_flag_lzma_eos;
77
static int hf_zip_flag_data_descriptor;
78
static int hf_zip_flag_patched_data;
79
static int hf_zip_flag_strong_encryption;
80
static int hf_zip_flag_language_encoding;
81
static int hf_zip_flag_central_dir_encryption;
82
83
static int hf_zip_compression_method;
84
static int hf_zip_last_mod_file_date_time;
85
static int hf_zip_last_mod_file_time;
86
static int hf_zip_last_mod_file_date;
87
static int hf_zip_crc32;
88
static int hf_zip_crc32_status;
89
static int hf_zip_file_compressed_size;
90
static int hf_zip_file_uncompressed_size;
91
static int hf_zip_file_name_length;
92
static int hf_zip_extra_fields_length;
93
static int hf_zip_file_name;
94
95
static int hf_zip_extra_fields;
96
static int hf_zip_extra_field;
97
static int hf_zip_extra_id;
98
static int hf_zip_extra_data_size;
99
static int hf_zip_extra_data;
100
static int hf_zip_extra_version;
101
102
static int hf_zip_extra_ntfs_tag;
103
104
static int hf_zip_extra_ut_flags;
105
static int hf_zip_extra_ut_flag_mtime;
106
static int hf_zip_extra_ut_flag_atime;
107
static int hf_zip_extra_ut_flag_ctime;
108
static int hf_zip_extra_ut_mtime;
109
static int hf_zip_extra_ut_atime;
110
static int hf_zip_extra_ut_ctime;
111
112
static int hf_zip_extra_unix_uid_size;
113
static int hf_zip_extra_unix_uid;
114
static int hf_zip_extra_unix_gid_size;
115
static int hf_zip_extra_unix_gid;
116
117
static int hf_zip_encryption_header;
118
static int hf_zip_encrypted_file_data;
119
static int hf_zip_compressed_file_data;
120
static int hf_zip_file_data;
121
122
static int hf_zip_file_comment_length;
123
static int hf_zip_disk_start_number;
124
static int hf_zip_internal_file_attr;
125
static int hf_zip_external_file_attr;
126
static int hf_zip_local_header_offset;
127
static int hf_zip_file_comment;
128
129
static int hf_zip_disk_number;
130
static int hf_zip_directory_disk_start_number;
131
static int hf_zip_directory_entries_disk;
132
static int hf_zip_directory_entries;
133
static int hf_zip_directory_size;
134
static int hf_zip_directory_offset;
135
static int hf_zip_directory_end_size;
136
static int hf_zip_archive_comment;
137
static int hf_zip_extensible_data_sector;
138
static int hf_zip_zip64_directory_end_disk_start_number;
139
static int hf_zip_zip64_directory_end_offset;
140
static int hf_zip_total_disks;
141
142
static int ett_zip;
143
static int ett_zip_record;
144
static int ett_zip_made_by;
145
static int ett_zip_flags;
146
static int ett_zip_extras;
147
static int ett_zip_extra;
148
static int ett_zip_extra_ut_flags;
149
150
static expert_field ei_zip_crc32;
151
static expert_field ei_zip_overflow;
152
static expert_field ei_zip_underflow;
153
static expert_field ei_zip_unsupported;
154
155
// "PK" for Phil Katz; Big Endian for tvb_find_uint16_remaining
156
0
#define ZIP_MAGIC_UINT 0x504b
157
158
/* Officially, the header signatures are Little-Endian like everything
159
 * in the format, though they make more sense to read Big-Endian. */
160
16
#define ZIP_DIRECTORY_RECORD                    0x02014b50
161
16
#define ZIP_FILE_RECORD                         0x04034b50
162
#define ZIP_DIGITAL_SIGNATURE_RECORD            0x05054b50
163
16
#define ZIP_END_OF_DIRECTORY_RECORD             0x06054b50
164
16
#define ZIP64_END_OF_DIRECTORY_RECORD           0x06064b50
165
16
#define ZIP64_END_OF_DIRECTORY_LOCATOR_RECORD   0x07064b50
166
#define ZIP_DATA_DESCRIPTOR_RECORD              0x08074b50
167
168
static const value_string zip_record_vals[] = {
169
    { ZIP_DIRECTORY_RECORD, "Central Directory"},
170
    { ZIP_FILE_RECORD, "File"},
171
    { ZIP_DIGITAL_SIGNATURE_RECORD, "Digital Signature"},
172
    { ZIP_END_OF_DIRECTORY_RECORD, "End of Central Directory"},
173
    { ZIP64_END_OF_DIRECTORY_RECORD, "Zip64 End of Central Directory"},
174
    { ZIP64_END_OF_DIRECTORY_LOCATOR_RECORD, "Zip64 End of Central Directory Locator"},
175
    { ZIP_DATA_DESCRIPTOR_RECORD, "Data Descriptor"},
176
    { 0, NULL}
177
};
178
179
16
#define ZIP_FLAG_ENCRYPTION         0x0001
180
16
#define ZIP_FLAG_LZMA_OPTS          0x0002
181
16
#define ZIP_FLAG_DEFLATE_OPTS       0x0006
182
16
#define ZIP_FLAG_DATA_DESCRIPTOR    0x0008
183
16
#define ZIP_FLAG_PATCHED_DATA       0x0020
184
16
#define ZIP_FLAG_STRONG_ENCRYPTION  0x0040
185
16
#define ZIP_FLAG_LANGUAGE_ENCODING  0x0800
186
16
#define ZIP_FLAG_CENTRAL_DIR_CRYPT  0x2000
187
188
static const value_string zip_host_vals[] = {
189
    { 0, "MS-DOS and OS/2 (FAT/VFAT/FAT32)" },
190
    { 1, "Amiga" },
191
    { 2, "OpenVMS" },
192
    { 3, "UNIX" },
193
    { 4, "VM/CMS" },
194
    { 5, "Atari ST" },
195
    { 6, "OS/2 HPFS" },
196
    { 7, "Macintosh" },
197
    { 8, "Z-System" },
198
    { 9, "CP/M" },
199
    {10, "Windows NTFS" },
200
    {11, "MVS (OS/390 - Z/OS)" },
201
    {12, "VSE" },
202
    {13, "Acorn Risc" },
203
    {14, "VFAT" },
204
    {15, "Alternate MVS" },
205
    {16, "BeOS" },
206
    {17, "Tandem" },
207
    {18, "OS/400" },
208
    {19, "OS X (Darwin)" },
209
    { 0, NULL }
210
};
211
212
static const value_string zip_deflate_opts_vals[] = {
213
    { 0, "Normal (-en)"} ,
214
    { 1, "Maximum (-exx/-ex)"} ,
215
    { 2, "Fast (-ef)"} ,
216
    { 3, "Super Fast (-es)"} ,
217
    { 0, NULL}
218
};
219
220
static const value_string zip_method_vals[] = {
221
    { 0, "Store (no compression)" },
222
    { 1, "Shrink" },
223
    { 2, "Reduce (compression factor 1}" },
224
    { 3, "Reduce (compression factor 2}" },
225
    { 4, "Reduce (compression factor 3}" },
226
    { 5, "Reduce (compression factor 4}" },
227
    { 6, "Implode" },
228
    { 7, "Tokenize (reserved)" },
229
    { 8, "Deflate" },
230
    { 9, "Enhanced Deflating using Deflate64(tm)" },
231
    {10, "PKWARE Data Compression Library Imploding (old IBM TERSE)" },
232
    {11, "Reserved by PKWARE" },
233
    {12, "BZIP2" },
234
    {13, "Reserved by PKWARE" },
235
    {14, "LZMA" },
236
    {15, "Reserved by PKWARE" },
237
    {16, "IBM z/OS CMPSC" },
238
    {17, "Reserved by PKWARE" },
239
    {18, "IBM TERSE (new)" },
240
    {19, "IBM LZ77 z Architecture" },
241
    {20, "Deprecated (use 93 for zstd)" },
242
    {93, "Zstandard (zstd)" },
243
    {94, "MP3" },
244
    {95, "XZ" },
245
    {96, "JPEG variant" },
246
    {97, "WavPack" },
247
    {98, "PPMd version I, Rev 1" },
248
    {99, "AE-x encryption marker" },
249
    { 0, NULL }
250
};
251
252
16
#define ZIP_EXTRA_ZIP64 0x0001
253
16
#define ZIP_EXTRA_NTFS  0x000a
254
32
#define ZIP_EXTRA_UT    0x5455
255
16
#define ZIP_EXTRA_UCOM  0x6375
256
16
#define ZIP_EXTRA_UPATH 0x7075
257
16
#define ZIP_EXTRA_UNIX2 0x7855
258
16
#define ZIP_EXTRA_UNIX3 0x7875
259
260
static const value_string zip_extra_id_vals[] = {
261
    { ZIP_EXTRA_ZIP64, "Zip64"},
262
    { ZIP_EXTRA_NTFS,  "NTFS"},
263
    { ZIP_EXTRA_UT,    "Unix Time"},
264
    { ZIP_EXTRA_UCOM,  "UTF-8 Comment"},
265
    { ZIP_EXTRA_UPATH, "UTF-8 Path"},
266
    { ZIP_EXTRA_UNIX2, "Unix (type 2)"},
267
    { ZIP_EXTRA_UNIX3, "Unix (type 3)"},
268
    { 0, NULL }
269
};
270
271
0
#define ZIP_EXTRA_NTFS_FILETIMES 0x0001
272
273
static const value_string zip_extra_ntfs_tag_vals[] = {
274
    { ZIP_EXTRA_NTFS_FILETIMES, "File Times" },
275
    { 0, NULL },
276
};
277
278
static void
279
decode_zip_version(char *s, uint16_t value)
280
0
{
281
0
    snprintf(s, ITEM_LABEL_LENGTH, "%u.%u", value / 10, value % 10);
282
0
}
283
284
static int* const *
285
0
zip_get_flags_fields(uint16_t method) {
286
0
    static int* const generic_fields[] = { &hf_zip_flag_encryption,
287
0
                                         &hf_zip_flag_data_descriptor,
288
0
                                         &hf_zip_flag_patched_data,
289
0
                                         &hf_zip_flag_strong_encryption,
290
0
                                         &hf_zip_flag_language_encoding,
291
0
                                         &hf_zip_flag_central_dir_encryption,
292
0
                                         NULL };
293
294
0
    static int* const deflate_fields[] = { &hf_zip_flag_encryption,
295
0
                                         &hf_zip_flag_deflate_opts,
296
0
                                         &hf_zip_flag_data_descriptor,
297
0
                                         &hf_zip_flag_patched_data,
298
0
                                         &hf_zip_flag_strong_encryption,
299
0
                                         &hf_zip_flag_language_encoding,
300
0
                                         &hf_zip_flag_central_dir_encryption,
301
0
                                         NULL };
302
303
0
    static int* const lzma_fields[] = { &hf_zip_flag_encryption,
304
0
                                         &hf_zip_flag_lzma_eos,
305
0
                                         &hf_zip_flag_data_descriptor,
306
0
                                         &hf_zip_flag_patched_data,
307
0
                                         &hf_zip_flag_strong_encryption,
308
0
                                         &hf_zip_flag_language_encoding,
309
0
                                         &hf_zip_flag_central_dir_encryption,
310
0
                                         NULL };
311
0
    switch (method) {
312
0
    case 8:
313
0
    case 9:
314
0
        return deflate_fields;
315
0
    case 14:
316
0
        return lzma_fields;
317
0
    default:
318
0
        return generic_fields;
319
0
    }
320
0
}
321
322
static int* const made_by_fields[] = { &hf_zip_version_made_by,
323
                                       &hf_zip_host_made_by,
324
                                       NULL };
325
326
typedef struct _zip_eo_t {
327
    const char *filename;
328
    tvbuff_t *payload;
329
} zip_eo_t;
330
331
static tap_packet_status
332
zip_eo_packet(void *tapdata, packet_info *pinfo, epan_dissect_t *edt _U_, const void *data, tap_flags_t flags _U_)
333
0
{
334
0
        export_object_list_t *object_list = (export_object_list_t *)tapdata;
335
0
        const zip_eo_t *eo_info = (const zip_eo_t *)data;
336
0
        export_object_entry_t *entry;
337
338
0
        if(eo_info) { /* We have data waiting for us */
339
                /* These values will be freed when the Export Object window
340
                 * is closed. */
341
0
                entry = g_new0(export_object_entry_t, 1);
342
343
0
                entry->pkt_num = pinfo->num;
344
345
                /* We could try to preserve the directory structure (the
346
                 * E.O. code percent encodes various directory structures)
347
                 * and expect the user to clean it up, rather than flattening
348
                 * the directory structure. */
349
0
                entry->filename = eo_info->filename ? g_path_get_basename(eo_info->filename) : NULL;
350
0
                entry->payload_len = tvb_captured_length(eo_info->payload);
351
0
                entry->payload_data = (uint8_t *)tvb_memdup(NULL, eo_info->payload, 0, entry->payload_len);
352
353
0
                object_list->add_entry(object_list->gui_data, entry);
354
355
0
                return TAP_PACKET_REDRAW; /* State changed - window should be redrawn */
356
0
        } else {
357
0
                return TAP_PACKET_DONT_REDRAW; /* State unchanged - no window updates needed */
358
0
        }
359
0
}
360
361
typedef struct _zip_info_t {
362
    tvbuff_t *filename_tvb;
363
    tvbuff_t *comment_tvb;
364
    const uint8_t *filename;
365
    uint64_t uncompressed_size;
366
    uint64_t compressed_size;
367
    uint64_t local_header_offset;
368
    uint32_t disk_start_number;
369
    bool central_directory;
370
} zip_info_t;
371
372
static int
373
dissect_zip_extra_zip64(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, void *data)
374
0
{
375
0
    zip_info_t *extra_info = (zip_info_t*)data;
376
377
0
    unsigned offset = 0;
378
0
    if (extra_info->uncompressed_size == UINT32_MAX) {
379
0
        proto_tree_add_item(tree, hf_zip_file_uncompressed_size, tvb, offset, 8, ENC_LITTLE_ENDIAN);
380
0
        offset += 8;
381
0
    }
382
0
    if (extra_info->compressed_size == UINT32_MAX) {
383
0
        proto_tree_add_item_ret_uint64(tree, hf_zip_file_compressed_size, tvb, offset, 8, ENC_LITTLE_ENDIAN, &extra_info->compressed_size);
384
0
        offset += 8;
385
0
    }
386
0
    if (extra_info->local_header_offset == UINT32_MAX) {
387
0
        proto_tree_add_item(tree, hf_zip_local_header_offset, tvb, offset, 8, ENC_LITTLE_ENDIAN);
388
0
        offset += 8;
389
0
    }
390
0
    if (extra_info->disk_start_number == UINT16_MAX) {
391
0
        proto_tree_add_item(tree, hf_zip_disk_start_number, tvb, offset, 4, ENC_LITTLE_ENDIAN);
392
0
        offset += 4;
393
0
    }
394
395
0
    return offset;
396
0
}
397
398
static int
399
dissect_zip_extra_ntfs(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, void *data _U_)
400
0
{
401
0
    unsigned offset = 0;
402
0
    uint16_t tag, size;
403
404
0
    offset += 4;
405
0
    while (tvb_reported_length_remaining(tvb, offset)) {
406
0
        proto_tree_add_item_ret_uint16(tree, hf_zip_extra_ntfs_tag, tvb, offset, 2, ENC_LITTLE_ENDIAN, &tag);
407
0
        offset += 2;
408
0
        proto_tree_add_item_ret_uint16(tree, hf_zip_extra_data_size, tvb, offset, 2, ENC_LITTLE_ENDIAN, &size);
409
0
        offset += 2;
410
0
        if (tag == ZIP_EXTRA_NTFS_FILETIMES) {
411
0
            proto_tree_add_item(tree, hf_zip_extra_ut_mtime, tvb, offset, 8, ENC_TIME_WINDOWS|ENC_LITTLE_ENDIAN);
412
0
            proto_tree_add_item(tree, hf_zip_extra_ut_atime, tvb, offset + 8, 8, ENC_TIME_WINDOWS|ENC_LITTLE_ENDIAN);
413
0
            proto_tree_add_item(tree, hf_zip_extra_ut_ctime, tvb, offset + 16, 8, ENC_TIME_WINDOWS|ENC_LITTLE_ENDIAN);
414
0
        }
415
0
        offset += size;
416
0
    }
417
418
0
    return offset;
419
0
}
420
421
static int
422
dissect_zip_extra_utf8_comment(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, void *data)
423
0
{
424
0
    _U_ zip_info_t *extra_info = (zip_info_t*)data;
425
426
0
    unsigned offset = 0;
427
0
    uint8_t version;
428
429
0
    proto_tree_add_item_ret_uint8(tree, hf_zip_extra_version, tvb, offset, 1, ENC_NA, &version);
430
0
    offset += 1;
431
0
    if (version != 1) {
432
0
        return offset;
433
0
    }
434
435
0
    uint32_t computed_crc32 = crc32_ccitt_tvb(extra_info->comment_tvb, tvb_reported_length(extra_info->comment_tvb));
436
0
    proto_tree_add_checksum(tree, tvb, offset, hf_zip_crc32, hf_zip_crc32_status, &ei_zip_crc32, pinfo, computed_crc32, ENC_LITTLE_ENDIAN, PROTO_CHECKSUM_VERIFY);
437
0
    offset += 4;
438
0
    proto_tree_add_item(tree, hf_zip_file_comment, tvb, offset, tvb_reported_length_remaining(tvb, offset), ENC_UTF_8);
439
440
0
    return offset;
441
0
}
442
443
static int
444
dissect_zip_extra_utf8_path(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, void *data)
445
0
{
446
0
    zip_info_t *extra_info = (zip_info_t*)data;
447
448
0
    unsigned offset = 0;
449
0
    uint32_t crc32;
450
0
    uint8_t version;
451
452
0
    proto_tree_add_item_ret_uint8(tree, hf_zip_extra_version, tvb, offset, 1, ENC_NA, &version);
453
0
    offset += 1;
454
0
    if (version != 1) {
455
0
        return offset;
456
0
    }
457
458
0
    uint32_t computed_crc32 = crc32_ccitt_tvb(extra_info->filename_tvb, tvb_reported_length(extra_info->filename_tvb));
459
0
    proto_tree_add_checksum(tree, tvb, offset, hf_zip_crc32, hf_zip_crc32_status, &ei_zip_crc32, pinfo, computed_crc32, ENC_LITTLE_ENDIAN, PROTO_CHECKSUM_VERIFY);
460
0
    crc32 = tvb_get_letohl(tvb, offset);
461
0
    offset += 4;
462
0
    if (crc32 != computed_crc32) {
463
0
        proto_tree_add_item(tree, hf_zip_file_name, tvb, offset, tvb_reported_length_remaining(tvb, offset), ENC_UTF_8);
464
0
    } else {
465
0
        proto_tree_add_item_ret_string(tree, hf_zip_file_name, tvb, offset, tvb_reported_length_remaining(tvb, offset), ENC_UTF_8, pinfo->pool, &extra_info->filename);
466
0
    }
467
468
0
    return offset;
469
0
}
470
471
static int
472
dissect_zip_extra_unix_time(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, void *data)
473
0
{
474
0
    static int* const ut_flags_fields[] = { &hf_zip_extra_ut_flag_mtime,
475
0
                                            &hf_zip_extra_ut_flag_atime,
476
0
                                            &hf_zip_extra_ut_flag_ctime,
477
0
                                            NULL };
478
479
0
    uint64_t flags;
480
0
    zip_info_t *extra_info = (zip_info_t*)data;
481
482
0
    unsigned offset = 0;
483
0
    proto_tree_add_bitmask_ret_uint64(tree, tvb, offset, hf_zip_extra_ut_flags, ett_zip_extra_ut_flags, ut_flags_fields, ENC_NA, &flags);
484
0
    if (extra_info->central_directory) {
485
0
        flags &= 0x1;
486
0
    }
487
0
    offset += 1;
488
0
    if (flags & 1) {
489
0
        proto_tree_add_item(tree, hf_zip_extra_ut_mtime, tvb, offset, 4, ENC_TIME_SECS|ENC_LITTLE_ENDIAN);
490
0
        offset += 4;
491
0
    }
492
0
    if (flags & 2) {
493
0
        proto_tree_add_item(tree, hf_zip_extra_ut_atime, tvb, offset, 4, ENC_TIME_SECS|ENC_LITTLE_ENDIAN);
494
0
        offset += 4;
495
0
    }
496
0
    if (flags & 4) {
497
0
        proto_tree_add_item(tree, hf_zip_extra_ut_ctime, tvb, offset, 4, ENC_TIME_SECS|ENC_LITTLE_ENDIAN);
498
0
        offset += 4;
499
0
    }
500
501
0
    return offset;
502
0
}
503
504
static int
505
dissect_zip_extra_unix2(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, void *data)
506
0
{
507
0
    zip_info_t *extra_info = (zip_info_t*)data;
508
0
    unsigned offset = 0;
509
510
0
    if (extra_info->central_directory) {
511
0
        return offset;
512
0
    }
513
514
0
    proto_tree_add_item(tree, hf_zip_extra_unix_uid, tvb, offset, 2, ENC_LITTLE_ENDIAN);
515
0
    offset += 2;
516
0
    proto_tree_add_item(tree, hf_zip_extra_unix_gid, tvb, offset, 2, ENC_LITTLE_ENDIAN);
517
0
    offset += 2;
518
519
0
    return offset;
520
0
}
521
522
static int
523
dissect_zip_extra_unix3(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, void *data _U_)
524
0
{
525
0
    unsigned offset = 0;
526
0
    uint8_t version, size;
527
528
0
    proto_tree_add_item_ret_uint8(tree, hf_zip_extra_version, tvb, offset, 1, ENC_NA, &version);
529
0
    offset += 1;
530
0
    if (version != 1) {
531
0
        return offset;
532
0
    }
533
0
    proto_tree_add_item_ret_uint8(tree, hf_zip_extra_unix_uid_size, tvb, offset, 1, ENC_NA, &size);
534
0
    offset += 1;
535
0
    proto_tree_add_item(tree, hf_zip_extra_unix_uid, tvb, offset, size, ENC_LITTLE_ENDIAN);
536
0
    offset += size;
537
0
    proto_tree_add_item_ret_uint8(tree, hf_zip_extra_unix_gid_size, tvb, offset, 1, ENC_NA, &size);
538
0
    offset += 1;
539
0
    proto_tree_add_item(tree, hf_zip_extra_unix_gid, tvb, offset, size, ENC_LITTLE_ENDIAN);
540
0
    offset += size;
541
542
0
    return offset;
543
0
}
544
545
static void
546
dissect_zip_extra_fields(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, zip_info_t *extra_info)
547
0
{
548
0
    proto_tree *extras_tree, *extra_tree;
549
0
    proto_item *ti, *extra_ti;
550
551
0
    tvbuff_t *next_tvb;
552
0
    unsigned offset = 0;
553
0
    uint16_t id, size;
554
555
0
    ti = proto_tree_add_item(tree, hf_zip_extra_fields, tvb, offset, tvb_reported_length(tvb), ENC_NA);
556
0
    extras_tree = proto_item_add_subtree(ti, ett_zip_extras);
557
558
0
    while (tvb_reported_length_remaining(tvb, offset)) {
559
0
        extra_ti = proto_tree_add_item(extras_tree, hf_zip_extra_field, tvb, offset, 4, ENC_NA);
560
0
        extra_tree = proto_item_add_subtree(extra_ti, ett_zip_extra);
561
0
        proto_tree_add_item_ret_uint16(extra_tree, hf_zip_extra_id, tvb, offset, 2, ENC_LITTLE_ENDIAN, &id);
562
0
        proto_item_append_text(extra_ti, ": %s", val_to_str_const(id, zip_extra_id_vals, "Unknown"));
563
0
        offset += 2;
564
0
        proto_tree_add_item_ret_uint16(extra_tree, hf_zip_extra_data_size, tvb, offset, 2, ENC_LITTLE_ENDIAN, &size);
565
0
        offset += 2;
566
0
        if (size) {
567
0
            next_tvb = tvb_new_subset_length(tvb, offset, size);
568
0
            if (!dissector_try_uint_with_data(zip_extra_dissector_table, id, next_tvb, pinfo, extra_tree, false, extra_info)) {
569
0
                proto_tree_add_item(extra_tree, hf_zip_extra_data, tvb, offset, size, ENC_NA);
570
0
            }
571
0
            offset += size;
572
0
        }
573
0
        proto_item_set_end(extra_ti, tvb, offset);
574
0
    }
575
0
}
576
577
static int
578
dissect_zip_file(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
579
0
{
580
0
    proto_tree *record_tree;
581
0
    proto_item *ti, *crc_ti, *crc_status_ti, *size_ti, *flags_ti;
582
583
0
    uint64_t flags;
584
0
    uint32_t crc32;
585
0
    uint16_t file_name_length, extra_fields_length;
586
0
    uint16_t method;
587
0
    unsigned offset = 0;
588
0
    int encoding;
589
0
    bool encrypted = false;
590
0
    zip_info_t extra_info = {0};
591
592
0
    ti = proto_tree_add_item(tree, hf_zip_file, tvb, offset, 50, ENC_NA);
593
0
    record_tree = proto_item_add_subtree(ti, ett_zip_record);
594
595
0
    proto_tree_add_item(record_tree, hf_zip_record_signature, tvb, offset, 4, ENC_LITTLE_ENDIAN);
596
0
    offset += 4;
597
0
    proto_tree_add_item(record_tree, hf_zip_version_to_extract, tvb, offset, 2, ENC_LITTLE_ENDIAN);
598
0
    offset += 2;
599
    /* The meaning of the flags depends on the compression method. */
600
0
    method = tvb_get_letohs(tvb, offset + 2);
601
0
    int* const *flags_fields = zip_get_flags_fields(method);
602
0
    flags_ti = proto_tree_add_bitmask_ret_uint64(record_tree, tvb, offset, hf_zip_flags, ett_zip_flags, flags_fields, ENC_LITTLE_ENDIAN, &flags);
603
0
    if (flags & ZIP_FLAG_LANGUAGE_ENCODING) {
604
0
        encoding = ENC_UTF_8;
605
0
    } else {
606
        /* According to the specification, if this bit is not set, the encoding
607
         * shall be ENC_CP437. In practice, it's more like the SSID element in
608
         * 802.11, viz., if the bit is absent the filename and comment are
609
         * opaque byte strings and the encoding is whatever was used by
610
         * the tool that made the archive. In such case, some tools will
611
         * include appropriate extra fields that are UTF-8 translations of
612
         * the filename and comment, at least if they contain octets which
613
         * are not in the ASCII/ISO/IEC 646 invariant set. So we could have
614
         * a pref here for default encoding. */
615
0
        encoding = ENC_CP437;
616
0
    }
617
0
    offset += 2;
618
0
    proto_tree_add_item(record_tree, hf_zip_compression_method, tvb, offset, 2, ENC_LITTLE_ENDIAN);
619
0
    offset += 2;
620
0
    offset = dissect_smb_datetime(tvb, record_tree, offset, hf_zip_last_mod_file_date_time, hf_zip_last_mod_file_date, hf_zip_last_mod_file_time, true);
621
0
    crc_ti = proto_tree_add_item_ret_uint(record_tree, hf_zip_crc32, tvb, offset, 4, ENC_LITTLE_ENDIAN, &crc32);
622
0
    offset += 4;
623
0
    size_ti = proto_tree_add_item_ret_uint64(record_tree, hf_zip_file_compressed_size, tvb, offset, 4, ENC_LITTLE_ENDIAN, &extra_info.compressed_size);
624
0
    offset += 4;
625
0
    proto_tree_add_item_ret_uint64(record_tree, hf_zip_file_uncompressed_size, tvb, offset, 4, ENC_LITTLE_ENDIAN, &extra_info.uncompressed_size);
626
0
    offset += 4;
627
0
    proto_tree_add_item_ret_uint16(record_tree, hf_zip_file_name_length, tvb, offset, 2, ENC_LITTLE_ENDIAN, &file_name_length);
628
0
    offset += 2;
629
0
    proto_tree_add_item_ret_uint16(record_tree, hf_zip_extra_fields_length, tvb, offset, 2, ENC_LITTLE_ENDIAN, &extra_fields_length);
630
0
    offset += 2;
631
0
    proto_tree_add_item_ret_string(record_tree, hf_zip_file_name, tvb, offset, file_name_length, encoding, pinfo->pool, &extra_info.filename);
632
0
    extra_info.filename_tvb = tvb_new_subset_length(tvb, offset, file_name_length);
633
0
    offset += file_name_length;
634
0
    if (extra_fields_length) {
635
0
        dissect_zip_extra_fields(tvb_new_subset_length(tvb, offset, extra_fields_length), pinfo, record_tree, &extra_info);
636
0
        offset += extra_fields_length;
637
0
    }
638
0
    proto_item_append_text(ti, ": %s", extra_info.filename);
639
    /* The Zip64 extra info has the real size if the compressed size is
640
     * UINT32_MAX. For various reasons to do with streaming or writing to
641
     * pipes, it's possible that the Zip64 header is used but the size is
642
     * not larger than UINT32_MAX, so we check. */
643
0
    if (extra_info.compressed_size > UINT32_MAX) {
644
0
        expert_add_info_format(pinfo, size_ti, &ei_zip_overflow, "Compressed size unsupported (%" PRIu64 " bytes is too large)", extra_info.compressed_size);
645
0
        return tvb_reported_length(tvb);
646
0
    }
647
0
    if (flags & ZIP_FLAG_DATA_DESCRIPTOR) {
648
        /* Right now we don't handle the data descriptor. The standard way
649
         * many programs handle them is to read the central directory
650
         * listing first. If the file is not encrypted, and it's compressed
651
         * with deflate, then we could just throw everything that's left
652
         * in the tvb at zlib, and if that returned a success (Z_END_STREAM)
653
         * check how many total bytes were consumed. We'll need a version
654
         * of tvb_child_uncompress_zlib that returns how many bytes were
655
         * consumed (and possibly the return value, to distinguish between
656
         * end of stream and unexpected end) to do that.
657
         */
658
0
        expert_add_info_format(pinfo, flags_ti, &ei_zip_unsupported, "%s", "Data descriptors are not supported yet");
659
0
        return offset;
660
0
    }
661
0
    if (flags & ZIP_FLAG_ENCRYPTION) {
662
0
        if (!(flags & ZIP_FLAG_STRONG_ENCRYPTION)) {
663
0
            proto_tree_add_item(record_tree, hf_zip_encryption_header, tvb, offset, 12, ENC_NA);
664
0
            offset += 12;
665
0
            if (ckd_sub(&extra_info.compressed_size, extra_info.compressed_size, 12)) {
666
0
                expert_add_info_format(pinfo, size_ti, &ei_zip_underflow, "Compressed size is too small to include the indicated encryption header");
667
0
                return offset;
668
0
            }
669
0
        }
670
0
        proto_tree_add_item(record_tree, hf_zip_encrypted_file_data, tvb, offset, (uint32_t)extra_info.compressed_size, ENC_NA);
671
0
        encrypted = true;
672
0
    }
673
674
0
    tvbuff_t *decompr_tvb = NULL;
675
0
    if (!encrypted) {
676
0
        switch (method) {
677
0
        case 0:
678
0
            decompr_tvb = tvb_new_subset_length(tvb, offset, (uint32_t)extra_info.compressed_size);
679
0
            break;
680
0
        case 8:
681
0
            proto_tree_add_item(record_tree, hf_zip_compressed_file_data, tvb, offset, (uint32_t)extra_info.compressed_size, ENC_NA);
682
0
            if (flags & ZIP_FLAG_DATA_DESCRIPTOR) {
683
0
                decompr_tvb = tvb_child_uncompress_zlib(tvb, tvb, offset, tvb_captured_length_remaining(tvb, offset));
684
0
            } else {
685
0
                decompr_tvb = tvb_child_uncompress_zlib(tvb, tvb, offset, (uint32_t)extra_info.compressed_size);
686
0
            }
687
0
            break;
688
0
        }
689
0
    }
690
    /* We reconstruct what proto_tree_add_checksum does down here because the
691
     * checksum comes much earlier, and also the check is after the DOS date
692
     * and time in the tree, and the SMB function to compute that doesn't
693
     * return the proto_item, so it's harder to use proto_tree_move_item. */
694
0
    if (decompr_tvb) {
695
0
        add_new_data_source(pinfo, decompr_tvb, "Decompressed file");
696
0
        proto_tree_add_item(record_tree, hf_zip_file_data, decompr_tvb, 0, tvb_reported_length(decompr_tvb), ENC_NA);
697
0
        uint32_t computed_crc32 = crc32_ccitt_tvb(decompr_tvb, tvb_reported_length(decompr_tvb));
698
0
        if (crc32 == computed_crc32) {
699
0
            proto_item_append_text(crc_ti, " [correct]");
700
0
            crc_status_ti = proto_tree_add_uint(record_tree, hf_zip_crc32_status, tvb, 0, 0, PROTO_CHECKSUM_E_GOOD);
701
0
        } else {
702
0
            proto_item_append_text(crc_ti, " incorrect, should be 0x%08x", computed_crc32);
703
0
            crc_status_ti = proto_tree_add_uint(record_tree, hf_zip_crc32_status, tvb, 0, 0, PROTO_CHECKSUM_E_BAD);
704
0
            expert_add_info_format(pinfo, crc_ti, &ei_zip_crc32, "%s [should be 0x%08x]", expert_get_summary(&ei_zip_crc32), computed_crc32);
705
0
        }
706
        /* We could wait to actually tap until the central directory listing,
707
         * e.g. if we wanted to use the file comment if present as the
708
         * Export Objects "hostname" field. */
709
0
        if (have_tap_listener(zip_eo_tap)) {
710
0
            zip_eo_t *eo_info = wmem_new0(pinfo->pool, zip_eo_t);
711
0
            eo_info->filename = (const char*)extra_info.filename;
712
0
            eo_info->payload = decompr_tvb;
713
714
0
            tap_queue_packet(zip_eo_tap, pinfo, eo_info);
715
0
        }
716
        /* Theoretically we could send the decompressed file data to all the
717
         * media type heuristic dissectors, but that's how you get ZIP bombs. */
718
0
    } else {
719
0
        proto_item_append_text(crc_ti, " [unverified]");
720
0
        crc_status_ti = proto_tree_add_uint(record_tree, hf_zip_crc32_status, tvb, 0, 0, PROTO_CHECKSUM_E_UNVERIFIED);
721
0
    }
722
0
    proto_tree_move_item(record_tree, crc_ti, crc_status_ti);
723
0
    proto_item_set_generated(crc_status_ti);
724
725
0
    if (ckd_add(&offset, offset, extra_info.compressed_size)) {
726
0
        offset = tvb_reported_length(tvb);
727
0
    }
728
0
    proto_item_set_end(ti, tvb, offset);
729
730
#if 0
731
    // TODO
732
    if (flags & ZIP_FLAG_DATA_DESCRIPTOR) {
733
734
    }
735
#endif
736
737
0
    return offset;
738
0
}
739
740
static int
741
dissect_zip_directory(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, void *data _U_)
742
0
{
743
0
    proto_item *ti;
744
0
    proto_tree *record_tree;
745
746
0
    uint64_t flags;
747
0
    uint16_t file_name_length, extra_fields_length, file_comment_length;
748
0
    unsigned offset = 0;
749
0
    int encoding;
750
0
    zip_info_t extra_info = {.central_directory = true};
751
752
0
    ti = proto_tree_add_item(tree, hf_zip_directory, tvb, offset, 50, ENC_NA);
753
0
    record_tree = proto_item_add_subtree(ti, ett_zip_record);
754
755
0
    proto_tree_add_item(record_tree, hf_zip_record_signature, tvb, offset, 4, ENC_LITTLE_ENDIAN);
756
0
    offset += 4;
757
0
    proto_tree_add_bitmask(record_tree, tvb, offset, hf_zip_made_by, ett_zip_made_by, made_by_fields, ENC_LITTLE_ENDIAN);
758
0
    offset += 2;
759
0
    proto_tree_add_item(record_tree, hf_zip_version_to_extract, tvb, offset, 2, ENC_LITTLE_ENDIAN);
760
0
    offset += 2;
761
0
    int* const *flags_fields = zip_get_flags_fields(tvb_get_letohs(tvb, offset + 2));
762
0
    proto_tree_add_bitmask_ret_uint64(record_tree, tvb, offset, hf_zip_flags, ett_zip_flags, flags_fields, ENC_LITTLE_ENDIAN, &flags);
763
0
    if (flags & ZIP_FLAG_LANGUAGE_ENCODING) {
764
0
        encoding = ENC_UTF_8;
765
0
    } else {
766
0
        encoding = ENC_CP437;
767
0
    }
768
0
    offset += 2;
769
0
    proto_tree_add_item(record_tree, hf_zip_compression_method, tvb, offset, 2, ENC_LITTLE_ENDIAN);
770
0
    offset += 2;
771
0
    offset = dissect_smb_datetime(tvb, record_tree, offset, hf_zip_last_mod_file_date_time, hf_zip_last_mod_file_date, hf_zip_last_mod_file_time, true);
772
0
    proto_tree_add_item(record_tree, hf_zip_crc32, tvb, offset, 4, ENC_LITTLE_ENDIAN);
773
0
    offset += 4;
774
0
    proto_tree_add_item_ret_uint64(record_tree, hf_zip_file_compressed_size, tvb, offset, 4, ENC_LITTLE_ENDIAN, &extra_info.compressed_size);
775
0
    offset += 4;
776
0
    proto_tree_add_item_ret_uint64(record_tree, hf_zip_file_uncompressed_size, tvb, offset, 4, ENC_LITTLE_ENDIAN, &extra_info.uncompressed_size);
777
0
    offset += 4;
778
0
    proto_tree_add_item_ret_uint16(record_tree, hf_zip_file_name_length, tvb, offset, 2, ENC_LITTLE_ENDIAN, &file_name_length);
779
0
    offset += 2;
780
0
    proto_tree_add_item_ret_uint16(record_tree, hf_zip_extra_fields_length, tvb, offset, 2, ENC_LITTLE_ENDIAN, &extra_fields_length);
781
0
    offset += 2;
782
0
    proto_tree_add_item_ret_uint16(record_tree, hf_zip_file_comment_length, tvb, offset, 2, ENC_LITTLE_ENDIAN, &file_comment_length);
783
0
    offset += 2;
784
0
    proto_tree_add_item_ret_uint(record_tree, hf_zip_disk_start_number, tvb, offset, 2, ENC_LITTLE_ENDIAN, &extra_info.disk_start_number);
785
0
    offset += 2;
786
0
    proto_tree_add_item(record_tree, hf_zip_internal_file_attr, tvb, offset, 2, ENC_LITTLE_ENDIAN);
787
0
    offset += 2;
788
0
    proto_tree_add_item(record_tree, hf_zip_external_file_attr, tvb, offset, 4, ENC_LITTLE_ENDIAN);
789
0
    offset += 4;
790
0
    proto_tree_add_item_ret_uint64(record_tree, hf_zip_local_header_offset, tvb, offset, 4, ENC_LITTLE_ENDIAN, &extra_info.local_header_offset);
791
0
    offset += 4;
792
0
    proto_tree_add_item_ret_string(record_tree, hf_zip_file_name, tvb, offset, file_name_length, encoding, pinfo->pool, &extra_info.filename);
793
0
    extra_info.filename_tvb = tvb_new_subset_length(tvb, offset, file_name_length);
794
0
    offset += file_name_length;
795
0
    if (extra_fields_length) {
796
0
        dissect_zip_extra_fields(tvb_new_subset_length(tvb, offset, extra_fields_length), pinfo, record_tree, &extra_info);
797
0
        offset += extra_fields_length;
798
0
    }
799
0
    proto_item_append_text(ti, ": %s", extra_info.filename);
800
0
    if (file_comment_length) {
801
0
        proto_tree_add_item(record_tree, hf_zip_file_comment, tvb, offset, file_comment_length, encoding);
802
0
        offset += file_comment_length;
803
0
    }
804
805
0
    proto_item_set_end(ti, tvb, offset);
806
807
0
    return offset;
808
0
}
809
810
static int
811
dissect_zip_end_of_directory(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, void *data _U_)
812
0
{
813
0
    proto_item *ti;
814
0
    proto_tree *record_tree;
815
816
0
    unsigned offset = 0, comment_length;
817
818
0
    ti = proto_tree_add_item(tree, hf_zip_end_of_directory, tvb, offset, 50, ENC_NA);
819
0
    record_tree = proto_item_add_subtree(ti, ett_zip_record);
820
821
0
    proto_tree_add_item(record_tree, hf_zip_record_signature, tvb, offset, 4, ENC_LITTLE_ENDIAN);
822
0
    offset += 4;
823
0
    proto_tree_add_item(record_tree, hf_zip_disk_number, tvb, offset, 2, ENC_LITTLE_ENDIAN);
824
0
    offset += 2;
825
0
    proto_tree_add_item(record_tree, hf_zip_directory_disk_start_number, tvb, offset, 2, ENC_LITTLE_ENDIAN);
826
0
    offset += 2;
827
0
    proto_tree_add_item(record_tree, hf_zip_directory_entries_disk, tvb, offset, 2, ENC_LITTLE_ENDIAN);
828
0
    offset += 2;
829
0
    proto_tree_add_item(record_tree, hf_zip_directory_entries, tvb, offset, 2, ENC_LITTLE_ENDIAN);
830
0
    offset += 2;
831
0
    proto_tree_add_item(record_tree, hf_zip_directory_size, tvb, offset, 4, ENC_LITTLE_ENDIAN);
832
0
    offset += 4;
833
0
    proto_tree_add_item(record_tree, hf_zip_directory_offset, tvb, offset, 4, ENC_LITTLE_ENDIAN);
834
0
    offset += 4;
835
0
    proto_tree_add_item_ret_length(record_tree, hf_zip_archive_comment, tvb, offset, 2, ENC_LITTLE_ENDIAN|ENC_CP437, &comment_length);
836
0
    offset += comment_length;
837
0
    proto_item_set_end(ti, tvb, offset);
838
839
0
    return offset;
840
0
}
841
842
static int
843
dissect_zip64_end_of_directory(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, void *data _U_)
844
0
{
845
0
    proto_item *ti, *size_ti;
846
0
    proto_tree *record_tree;
847
848
0
    unsigned offset = 0, end_offset;
849
0
    uint64_t size;
850
851
0
    ti = proto_tree_add_item(tree, hf_zip64_end_of_directory, tvb, offset, 50, ENC_NA);
852
0
    record_tree = proto_item_add_subtree(ti, ett_zip_record);
853
854
0
    proto_tree_add_item(record_tree, hf_zip_record_signature, tvb, offset, 4, ENC_LITTLE_ENDIAN);
855
0
    offset += 4;
856
0
    size_ti = proto_tree_add_item_ret_uint64(record_tree, hf_zip_directory_end_size, tvb, offset, 8, ENC_LITTLE_ENDIAN, &size);
857
0
    offset += 8;
858
0
    if (ckd_add(&end_offset, offset, size)) {
859
0
        expert_add_info(pinfo, size_ti, &ei_zip_overflow);
860
0
        return tvb_reported_length(tvb);
861
0
    }
862
0
    proto_tree_add_bitmask(record_tree, tvb, offset, hf_zip_made_by, ett_zip_made_by, made_by_fields, ENC_LITTLE_ENDIAN);
863
0
    offset += 2;
864
0
    proto_tree_add_item(record_tree, hf_zip_version_to_extract, tvb, offset, 2, ENC_LITTLE_ENDIAN);
865
0
    offset += 2;
866
0
    proto_tree_add_item(record_tree, hf_zip_disk_number, tvb, offset, 4, ENC_LITTLE_ENDIAN);
867
0
    offset += 4;
868
0
    proto_tree_add_item(record_tree, hf_zip_directory_disk_start_number, tvb, offset, 4, ENC_LITTLE_ENDIAN);
869
0
    offset += 4;
870
0
    proto_tree_add_item(record_tree, hf_zip_directory_entries_disk, tvb, offset, 8, ENC_LITTLE_ENDIAN);
871
0
    offset += 8;
872
0
    proto_tree_add_item(record_tree, hf_zip_directory_entries, tvb, offset, 8, ENC_LITTLE_ENDIAN);
873
0
    offset += 8;
874
0
    proto_tree_add_item(record_tree, hf_zip_directory_size, tvb, offset, 8, ENC_LITTLE_ENDIAN);
875
0
    offset += 8;
876
0
    proto_tree_add_item(record_tree, hf_zip_directory_offset, tvb, offset, 8, ENC_LITTLE_ENDIAN);
877
0
    offset += 8;
878
0
    if (offset < end_offset) {
879
0
        proto_tree_add_item(record_tree, hf_zip_extensible_data_sector, tvb, offset, end_offset - offset, ENC_NA);
880
0
        offset = end_offset;
881
0
    }
882
0
    proto_item_set_end(ti, tvb, offset);
883
884
0
    return offset;
885
0
}
886
887
static int
888
dissect_zip64_end_of_directory_locator(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, void *data _U_)
889
0
{
890
0
    proto_item *ti;
891
0
    proto_tree *record_tree;
892
893
0
    unsigned offset = 0;
894
895
0
    ti = proto_tree_add_item(tree, hf_zip64_end_of_directory_locator, tvb, offset, 20, ENC_NA);
896
0
    record_tree = proto_item_add_subtree(ti, ett_zip_record);
897
898
0
    proto_tree_add_item(record_tree, hf_zip_record_signature, tvb, offset, 4, ENC_LITTLE_ENDIAN);
899
0
    offset += 4;
900
0
    proto_tree_add_item(record_tree, hf_zip_zip64_directory_end_disk_start_number, tvb, offset, 4, ENC_LITTLE_ENDIAN);
901
0
    offset += 4;
902
0
    proto_tree_add_item(record_tree, hf_zip_zip64_directory_end_offset, tvb, offset, 8, ENC_LITTLE_ENDIAN);
903
0
    offset += 8;
904
0
    proto_tree_add_item(record_tree, hf_zip_total_disks, tvb, offset, 4, ENC_LITTLE_ENDIAN);
905
0
    offset += 4;
906
907
0
    return offset;
908
0
}
909
910
static int
911
0
dissect_zip(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, void *data _U_) {
912
0
    unsigned offset = 0;
913
0
    proto_tree *zip_tree;
914
0
    proto_item *ti;
915
916
0
    col_set_str(pinfo->cinfo, COL_PROTOCOL, "ZIP_FILE");
917
0
    ti = proto_tree_add_item(tree, proto_zip, tvb, offset, -1, ENC_NA);
918
0
    zip_tree = proto_item_add_subtree(ti, ett_zip);
919
920
0
    int dissected;
921
0
    while (tvb_find_uint16_remaining(tvb, offset, ZIP_MAGIC_UINT, &offset) &&
922
0
           tvb_reported_length_remaining(tvb, offset) >= 4) {
923
0
        uint32_t signature = tvb_get_letohl(tvb, offset);
924
0
        tvbuff_t *next_tvb = tvb_new_subset_remaining(tvb, offset);
925
0
        if (!(dissected = dissector_try_uint_with_data(zip_record_dissector_table, signature, next_tvb, pinfo, zip_tree, false, data))) {
926
0
            proto_tree_add_item(zip_tree, hf_zip_record_signature, tvb, offset, 4, ENC_LITTLE_ENDIAN);
927
0
            break;
928
0
        }
929
0
        offset += dissected;
930
0
    }
931
932
0
    return tvb_reported_length(tvb);
933
0
}
934
935
void
936
proto_register_zip(void)
937
16
{
938
16
    static hf_register_info hf[] = {
939
16
        { &hf_zip_file,
940
16
            { "Local File", "zipfile.file",
941
16
            FT_NONE, BASE_NONE, NULL,
942
16
            0x0, NULL, HFILL }
943
16
        },
944
16
        { &hf_zip_directory,
945
16
            { "Central Directory", "zipfile.directory",
946
16
            FT_NONE, BASE_NONE, NULL,
947
16
            0x0, NULL, HFILL }
948
16
        },
949
16
        { &hf_zip_end_of_directory,
950
16
            { "End of Central Directory", "zipfile.directory.end",
951
16
            FT_NONE, BASE_NONE, NULL,
952
16
            0x0, NULL, HFILL }
953
16
        },
954
16
        { &hf_zip64_end_of_directory,
955
16
            { "Zip64 End of Central Directory", "zipfile.directory.end.zip64",
956
16
            FT_NONE, BASE_NONE, NULL,
957
16
            0x0, NULL, HFILL }
958
16
        },
959
16
        { &hf_zip64_end_of_directory_locator,
960
16
            { "Zip64 End of Central Directory Locator", "zipfile.directory.end.zip64.locator",
961
16
            FT_NONE, BASE_NONE, NULL,
962
16
            0x0, NULL, HFILL }
963
16
        },
964
16
        { &hf_zip_record_signature,
965
16
            { "Signature", "zipfile.signature",
966
16
            FT_UINT32, BASE_HEX, VALS(zip_record_vals),
967
16
            0x0, NULL, HFILL }
968
16
        },
969
16
        { &hf_zip_made_by,
970
16
            { "Made By", "zipfile.made_by",
971
16
            FT_UINT16, BASE_HEX, NULL,
972
16
            0x0, NULL, HFILL }
973
16
        },
974
16
        { &hf_zip_version_made_by,
975
16
            { "Version", "zipfile.made_by.version",
976
16
            FT_UINT16, BASE_CUSTOM, CF_FUNC(decode_zip_version),
977
16
            0x00FF, "Supposedly the ZIP specification version supported by the creating software, but often the software's own version", HFILL }
978
16
        },
979
16
        { &hf_zip_host_made_by,
980
16
            { "Host System", "zipfile.made_by.host",
981
16
            FT_UINT16, BASE_DEC, VALS(zip_host_vals),
982
16
            0xFF00, "Indicates compatibility of external file attributes", HFILL }
983
16
        },
984
16
        { &hf_zip_version_to_extract,
985
16
            { "Version to Extract", "zipfile.version_to_extract",
986
16
            FT_UINT16, BASE_CUSTOM, CF_FUNC(decode_zip_version),
987
16
            0x0, "Minimum supported ZIP specification version needed to extract", HFILL }
988
16
        },
989
16
        { &hf_zip_flags,
990
16
            { "Flags", "zipfile.flags",
991
16
            FT_UINT16, BASE_DEC, NULL,
992
16
            0x0, NULL, HFILL }
993
16
        },
994
16
        { &hf_zip_flag_encryption,
995
16
            { "Encryption", "zipfile.flag.encryption",
996
16
            FT_BOOLEAN, 16, TFS(&tfs_used_notused),
997
16
            ZIP_FLAG_ENCRYPTION, NULL, HFILL }
998
16
        },
999
16
        { &hf_zip_flag_lzma_eos,
1000
16
            { "LZMA EOS marker", "zipfile.flag.lzma.eos",
1001
16
            FT_BOOLEAN, 16, TFS(&tfs_present_absent),
1002
16
            ZIP_FLAG_LZMA_OPTS, NULL, HFILL }
1003
16
        },
1004
16
        { &hf_zip_flag_deflate_opts,
1005
16
            { "DEFLATE options", "zipfile.flag.deflate_opts",
1006
16
            FT_UINT16, BASE_HEX, VALS(zip_deflate_opts_vals),
1007
16
            ZIP_FLAG_DEFLATE_OPTS, NULL, HFILL }
1008
16
        },
1009
16
        { &hf_zip_flag_data_descriptor,
1010
16
            { "Data Descriptor", "zipfile.flag.data_descriptor",
1011
16
            FT_BOOLEAN, 16, TFS(&tfs_present_absent),
1012
16
            ZIP_FLAG_DATA_DESCRIPTOR,
1013
16
            "Seeking was not possible when producing file; CRC-32 and sizes are zero in header", HFILL }
1014
16
        },
1015
16
        { &hf_zip_flag_patched_data,
1016
16
            { "Patched Data", "zipfile.flag.patched_data",
1017
16
            FT_BOOLEAN, 16, TFS(&tfs_set_notset),
1018
16
            ZIP_FLAG_PATCHED_DATA, NULL, HFILL }
1019
16
        },
1020
16
        { &hf_zip_flag_strong_encryption,
1021
16
            { "Strong Encryption", "zipfile.flag.encrypted.strong",
1022
16
            FT_BOOLEAN, 16, TFS(&tfs_used_notused),
1023
16
            ZIP_FLAG_STRONG_ENCRYPTION, NULL, HFILL }
1024
16
        },
1025
16
        { &hf_zip_flag_language_encoding,
1026
16
            { "UTF-8", "zipfile.flag.language_encoding",
1027
16
            FT_BOOLEAN, 16, TFS(&tfs_used_notused),
1028
16
            ZIP_FLAG_LANGUAGE_ENCODING,
1029
16
            "Filename and comment fields for this file are in UTF-8", HFILL }
1030
16
        },
1031
16
        { &hf_zip_flag_central_dir_encryption,
1032
16
            { "Central Directory Encryption", "zipfile.flag.encrypted.central_directory",
1033
16
            FT_BOOLEAN, 16, TFS(&tfs_used_notused),
1034
16
            ZIP_FLAG_CENTRAL_DIR_CRYPT, NULL, HFILL }
1035
16
        },
1036
16
        { &hf_zip_compression_method,
1037
16
            { "Compression Method", "zipfile.file.compression_method",
1038
16
            FT_UINT16, BASE_DEC, VALS(zip_method_vals),
1039
16
            0x0, NULL, HFILL }
1040
16
        },
1041
16
        { &hf_zip_last_mod_file_date_time,
1042
16
            { "Last Mod File Date and Time", "zipfile.file.last_mod_file_date_time",
1043
16
            FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL, NULL,
1044
16
            0x0, NULL, HFILL }
1045
16
        },
1046
16
        { &hf_zip_last_mod_file_time,
1047
16
            { "Last Mod File Time", "zipfile.file.last_mod_file_time",
1048
16
            FT_UINT16, BASE_HEX, NULL,
1049
16
            0x0, NULL, HFILL }
1050
16
        },
1051
16
        { &hf_zip_last_mod_file_date,
1052
16
            { "Last Mod File Date", "zipfile.file.last_mod_file_date",
1053
16
            FT_UINT16, BASE_HEX, NULL,
1054
16
            0x0, NULL, HFILL }
1055
16
        },
1056
16
        { &hf_zip_crc32,
1057
16
            { "CRC", "zipfile.file.crc32",
1058
16
            FT_UINT32, BASE_HEX, NULL,
1059
16
            0x0, NULL, HFILL }
1060
16
        },
1061
16
        { &hf_zip_crc32_status,
1062
16
            { "CRC Status", "zipfile.file.crc32.status",
1063
16
            FT_UINT8, BASE_NONE, VALS(proto_checksum_vals),
1064
16
            0x0, NULL, HFILL }
1065
16
        },
1066
16
        { &hf_zip_file_compressed_size,
1067
16
            { "File Compressed Size", "zipfile.file.size",
1068
16
            FT_UINT64, BASE_DEC|BASE_UNIT_STRING, UNS(&units_byte_bytes),
1069
16
            0x0, NULL, HFILL }
1070
16
        },
1071
16
        { &hf_zip_file_uncompressed_size,
1072
16
            { "File Uncompressed Size", "zipfile.file.size.uncompressed",
1073
16
            FT_UINT64, BASE_DEC|BASE_UNIT_STRING, UNS(&units_byte_bytes),
1074
16
            0x0, NULL, HFILL }
1075
16
        },
1076
16
        { &hf_zip_file_name_length,
1077
16
            { "File Name Length", "zipfile.file.name.length",
1078
16
            FT_UINT16, BASE_DEC, NULL,
1079
16
            0x0, NULL, HFILL }
1080
16
        },
1081
16
        { &hf_zip_extra_fields_length,
1082
16
            { "Extra Fields Length", "zipfile.extras.length",
1083
16
            FT_UINT16, BASE_DEC, NULL,
1084
16
            0x0, NULL, HFILL }
1085
16
        },
1086
16
        { &hf_zip_extra_fields,
1087
16
            { "Extra Fields", "zipfile.extras",
1088
16
            FT_NONE, BASE_NONE, NULL,
1089
16
            0x0, NULL, HFILL }
1090
16
        },
1091
16
        { &hf_zip_extra_field,
1092
16
            { "Extra Field", "zipfile.extra",
1093
16
            FT_NONE, BASE_NONE, NULL,
1094
16
            0x0, NULL, HFILL }
1095
16
        },
1096
16
        { &hf_zip_extra_id,
1097
16
            { "ID", "zipfile.extra.id",
1098
16
            FT_UINT16, BASE_HEX, VALS(zip_extra_id_vals),
1099
16
            0x0, NULL, HFILL }
1100
16
        },
1101
16
        { &hf_zip_extra_data_size,
1102
16
            { "Data Size", "zipfile.extra.data.size",
1103
16
            FT_UINT16, BASE_DEC, NULL,
1104
16
            0x0, NULL, HFILL }
1105
16
        },
1106
16
        { &hf_zip_extra_data,
1107
16
            { "Data", "zipfile.extra.data",
1108
16
            FT_BYTES, BASE_NONE, NULL,
1109
16
            0x0, NULL, HFILL }
1110
16
        },
1111
16
        { &hf_zip_extra_version,
1112
16
            { "Version", "zipfile.extra.version",
1113
16
            FT_UINT8, BASE_DEC, NULL,
1114
16
            0x0, NULL, HFILL },
1115
16
        },
1116
1117
16
        { &hf_zip_extra_ntfs_tag,
1118
16
            { "Tag", "zipfile.extra.ntfs.tag",
1119
16
            FT_UINT16, BASE_HEX, VALS(zip_extra_ntfs_tag_vals),
1120
16
            0x0, NULL, HFILL },
1121
16
        },
1122
1123
16
        { &hf_zip_extra_ut_flags,
1124
16
            { "Flags", "zipfile.extra.ut.flags",
1125
16
            FT_UINT8, BASE_HEX, NULL,
1126
16
            0x0, NULL, HFILL },
1127
16
        },
1128
16
        { &hf_zip_extra_ut_flag_mtime,
1129
16
            { "Modification Time", "zipfile.extra.ut.flag.mtime",
1130
16
            FT_BOOLEAN, 8, TFS(&tfs_present_absent),
1131
16
            0x1, NULL, HFILL },
1132
16
        },
1133
16
        { &hf_zip_extra_ut_flag_atime,
1134
16
            { "Access Time", "zipfile.extra.ut.flag.atime",
1135
16
            FT_BOOLEAN, 8, TFS(&tfs_present_absent),
1136
16
            0x2, NULL, HFILL },
1137
16
        },
1138
16
        { &hf_zip_extra_ut_flag_ctime,
1139
16
            { "Creation Time", "zipfile.extra.ut.flag.ctime",
1140
16
            FT_BOOLEAN, 8, TFS(&tfs_present_absent),
1141
16
            0x4, NULL, HFILL },
1142
16
        },
1143
16
        { &hf_zip_extra_ut_mtime,
1144
16
            { "Modification Time", "zipfile.extra.ut.mtime",
1145
16
            FT_ABSOLUTE_TIME, ABSOLUTE_TIME_UTC, NULL,
1146
16
            0x0, NULL, HFILL },
1147
16
        },
1148
16
        { &hf_zip_extra_ut_atime,
1149
16
            { "Access Time", "zipfile.extra.ut.atime",
1150
16
            FT_ABSOLUTE_TIME, ABSOLUTE_TIME_UTC, NULL,
1151
16
            0x0, NULL, HFILL },
1152
16
        },
1153
16
        { &hf_zip_extra_ut_ctime,
1154
16
            { "Creation Time", "zipfile.extra.ut.ctime",
1155
16
            FT_ABSOLUTE_TIME, ABSOLUTE_TIME_UTC, NULL,
1156
16
            0x0, NULL, HFILL },
1157
16
        },
1158
16
        { &hf_zip_extra_unix_uid_size,
1159
16
            { "User ID size", "zipfile.extra.unix.uid_size",
1160
16
            FT_UINT8, BASE_DEC|BASE_UNIT_STRING, UNS(&units_byte_bytes),
1161
16
            0x0, NULL, HFILL },
1162
16
        },
1163
16
        { &hf_zip_extra_unix_uid,
1164
16
            { "User ID", "zipfile.extra.unix.uid",
1165
16
            FT_UINT16, BASE_DEC, NULL,
1166
16
            0x0, NULL, HFILL },
1167
16
        },
1168
16
        { &hf_zip_extra_unix_gid_size,
1169
16
            { "Group ID size", "zipfile.extra.unix.gid_size",
1170
16
            FT_UINT8, BASE_DEC|BASE_UNIT_STRING, UNS(&units_byte_bytes),
1171
16
            0x0, NULL, HFILL },
1172
16
        },
1173
16
        { &hf_zip_extra_unix_gid,
1174
16
            { "Group ID", "zipfile.extra.unix.gid",
1175
16
            FT_UINT16, BASE_DEC, NULL,
1176
16
            0x0, NULL, HFILL },
1177
16
        },
1178
1179
16
        { &hf_zip_file_comment_length,
1180
16
            { "File Comment Length", "zipfile.file.file_comment.length",
1181
16
            FT_UINT16, BASE_DEC, NULL,
1182
16
            0x0, NULL, HFILL }
1183
16
        },
1184
16
        { &hf_zip_disk_start_number,
1185
16
            { "Disk Number Start", "zipfile.file.disk_start_number",
1186
16
            FT_UINT32, BASE_DEC, NULL,
1187
16
            0x0, NULL, HFILL }
1188
16
        },
1189
16
        { &hf_zip_internal_file_attr,
1190
16
            { "Internal File Attributes", "zipfile.file.internal_file_attr",
1191
16
            FT_UINT16, BASE_HEX, NULL,
1192
16
            0x0, NULL, HFILL }
1193
16
        },
1194
16
        { &hf_zip_external_file_attr,
1195
16
            { "External File Attributes", "zipfile.file.external_file_attr",
1196
16
            FT_UINT32, BASE_HEX, NULL,
1197
16
            0x0, NULL, HFILL }
1198
16
        },
1199
16
        { &hf_zip_local_header_offset,
1200
16
            { "Local Header Offset", "zipfile.file.local_header_offset",
1201
16
            FT_UINT64, BASE_DEC_HEX, NULL,
1202
16
            0x0, NULL, HFILL }
1203
16
        },
1204
16
        { &hf_zip_file_name,
1205
16
            { "File Name", "zipfile.file.name",
1206
16
            FT_STRING, BASE_NONE, NULL,
1207
16
            0x0, NULL, HFILL }
1208
16
        },
1209
16
        { &hf_zip_file_comment,
1210
16
            { "File Comment", "zipfile.file.comment",
1211
16
            FT_STRING, BASE_NONE, NULL,
1212
16
            0x0, NULL, HFILL }
1213
16
        },
1214
16
        { &hf_zip_encryption_header,
1215
16
            { "Encryption Header", "zipfile.file.encryption_header",
1216
16
            FT_BYTES, BASE_NONE, NULL,
1217
16
            0x0, NULL, HFILL }
1218
16
        },
1219
16
        { &hf_zip_encrypted_file_data,
1220
16
            { "Encrypted File Data", "zipfile.file.data.encrypted",
1221
16
            FT_BYTES, BASE_NONE, NULL,
1222
16
            0x0, NULL, HFILL }
1223
16
        },
1224
16
        { &hf_zip_compressed_file_data,
1225
16
            { "Compressed File Data", "zipfile.file.data.compressed",
1226
16
            FT_BYTES, BASE_NONE, NULL,
1227
16
            0x0, NULL, HFILL }
1228
16
        },
1229
16
        { &hf_zip_file_data,
1230
16
            { "File Data", "zipfile.file.data",
1231
16
            FT_BYTES, BASE_NONE, NULL,
1232
16
            0x0, NULL, HFILL }
1233
16
        },
1234
16
        { &hf_zip_disk_number,
1235
16
            { "Disk Number", "zipfile.directory.disk_number",
1236
16
            FT_UINT32, BASE_DEC, NULL,
1237
16
            0x0, NULL, HFILL }
1238
16
        },
1239
16
        { &hf_zip_directory_disk_start_number,
1240
16
            { "Start of Central Directory Disk Number", "zipfile.directory.disk_start_number",
1241
16
            FT_UINT32, BASE_DEC, NULL,
1242
16
            0x0, NULL, HFILL }
1243
16
        },
1244
16
        { &hf_zip_directory_entries_disk,
1245
16
            { "Total Number of Entries on This Disk", "zipfile.directory.disk_entries",
1246
16
            FT_UINT64, BASE_DEC, NULL,
1247
16
            0x0, NULL, HFILL }
1248
16
        },
1249
16
        { &hf_zip_directory_entries,
1250
16
            { "Total Number of Entries", "zipfile.directory.entries",
1251
16
            FT_UINT64, BASE_DEC, NULL,
1252
16
            0x0, NULL, HFILL }
1253
16
        },
1254
16
        { &hf_zip_directory_size,
1255
16
            { "Central Directory Size", "zipfile.directory.size",
1256
16
            FT_UINT64, BASE_DEC|BASE_UNIT_STRING, UNS(&units_byte_bytes),
1257
16
            0x0, NULL, HFILL }
1258
16
        },
1259
16
        { &hf_zip_directory_offset,
1260
16
            { "Central Directory Offset", "zipfile.directory.offset",
1261
16
            FT_UINT64, BASE_DEC|BASE_UNIT_STRING, UNS(&units_byte_bytes),
1262
16
            0x0, "Offset with respect to starting disk/file for spanned/split archives", HFILL }
1263
16
        },
1264
16
        { &hf_zip_directory_end_size,
1265
16
            { "Zip64 End of Central Directory Size", "zipfile.zip64.directory.end.size",
1266
16
            FT_UINT64, BASE_DEC|BASE_UNIT_STRING, UNS(&units_byte_bytes),
1267
16
            0x0, NULL, HFILL }
1268
16
        },
1269
16
        { &hf_zip_archive_comment,
1270
16
            { "ZIP Archive Comment", "zipfile.archive_comment",
1271
16
            FT_UINT_STRING, BASE_NONE, NULL,
1272
16
            0x0, NULL, HFILL }
1273
16
        },
1274
16
        { &hf_zip_extensible_data_sector,
1275
16
            { "Extensible Data Sector", "zipfile.zip64.directory.end.extensible_data_sector",
1276
16
            FT_BYTES, BASE_NONE, NULL,
1277
16
            0x0, NULL, HFILL }
1278
16
        },
1279
16
        { &hf_zip_zip64_directory_end_disk_start_number,
1280
16
            { "Start of Zip64 End of Central Directory Disk Number", "zipfile.zip64.directory.end.disk_start_number",
1281
16
            FT_UINT32, BASE_DEC, NULL,
1282
16
            0x0, NULL, HFILL }
1283
16
        },
1284
16
        { &hf_zip_zip64_directory_end_offset,
1285
16
            { "Zip64 End of Central Directory Offset", "zipfile.zip64.directory.end.offset",
1286
16
            FT_UINT64, BASE_DEC|BASE_UNIT_STRING, UNS(&units_byte_bytes),
1287
16
            0x0, "Offset with respect to starting disk/file for spanned/split archives", HFILL }
1288
16
        },
1289
16
        { &hf_zip_total_disks,
1290
16
            { "Total Number of Disks", "zipfile.total_disks",
1291
16
            FT_UINT32, BASE_DEC, NULL,
1292
16
            0x0, NULL, HFILL }
1293
16
        },
1294
16
    };
1295
1296
16
    static int *ett[] = {
1297
16
        &ett_zip,
1298
16
        &ett_zip_record,
1299
16
        &ett_zip_made_by,
1300
16
        &ett_zip_flags,
1301
16
        &ett_zip_extras,
1302
16
        &ett_zip_extra,
1303
16
        &ett_zip_extra_ut_flags,
1304
16
    };
1305
1306
16
    proto_zip = proto_register_protocol("ZIP File Format", "ZIP_FILE", "zipfile");
1307
1308
16
    zip_handle = register_dissector("zipfile", dissect_zip, proto_zip);
1309
16
    proto_register_field_array(proto_zip, hf, array_length(hf));
1310
16
    proto_register_subtree_array(ett, array_length(ett));
1311
1312
16
    static ei_register_info ei[] = {
1313
16
        { &ei_zip_crc32, { "zipfile.file.crc32.bad", PI_CHECKSUM, PI_WARN, "Bad CRC32", EXPFILL }},
1314
16
        { &ei_zip_unsupported, { "zipfile.unsupported", PI_UNDECODED, PI_WARN, "Unsupported feature", EXPFILL }},
1315
16
        { &ei_zip_overflow, { "zipfile.overflow", PI_UNDECODED, PI_WARN, "Too large values are unsupported", EXPFILL }},
1316
16
        { &ei_zip_underflow, { "zipfile.underflow", PI_MALFORMED, PI_ERROR, "Too small value is bogus", EXPFILL }},
1317
16
    };
1318
1319
16
    expert_module_t *expert_zip = expert_register_protocol(proto_zip);
1320
16
    expert_register_field_array(expert_zip, ei, array_length(ei));
1321
1322
16
    zip_record_dissector_table = register_dissector_table("zip.record",
1323
16
        "ZIP Record", proto_zip, FT_UINT32, BASE_HEX);
1324
16
    zip_extra_dissector_table = register_dissector_table("zip.extra",
1325
16
        "ZIP Extra Field", proto_zip, FT_UINT16, BASE_HEX);
1326
1327
16
    zip_eo_tap = register_export_object(proto_zip, zip_eo_packet, NULL);
1328
16
}
1329
1330
static bool
1331
dissect_zip_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
1332
0
{
1333
    // Reject if we don't have enough room for the heuristics
1334
0
    if (tvb_captured_length(tvb) < 4) {
1335
0
        return false;
1336
0
    }
1337
1338
    // For heuristics, we're not going to try to handle self-extracting
1339
    // archives with executable code at the beginning (or anything else
1340
    // at the start); let some other Fileshark dissector take those.
1341
0
    switch (tvb_get_letohl(tvb, 0)) {
1342
0
    case ZIP_FILE_RECORD:
1343
0
    case ZIP_END_OF_DIRECTORY_RECORD: // Degenerate empty case
1344
0
        break;
1345
0
    default:
1346
0
        return false;
1347
0
    }
1348
1349
0
    return dissect_zip(tvb, pinfo, tree, data) > 0;
1350
0
}
1351
1352
void
1353
proto_reg_handoff_zip(void)
1354
16
{
1355
16
    dissector_add_uint("zip.record", ZIP_FILE_RECORD, create_dissector_handle(dissect_zip_file, proto_zip));
1356
16
    dissector_add_uint("zip.record", ZIP_DIRECTORY_RECORD, create_dissector_handle(dissect_zip_directory, proto_zip));
1357
16
    dissector_add_uint("zip.record", ZIP_END_OF_DIRECTORY_RECORD, create_dissector_handle(dissect_zip_end_of_directory, proto_zip));
1358
16
    dissector_add_uint("zip.record", ZIP64_END_OF_DIRECTORY_RECORD, create_dissector_handle(dissect_zip64_end_of_directory, proto_zip));
1359
16
    dissector_add_uint("zip.record", ZIP64_END_OF_DIRECTORY_LOCATOR_RECORD, create_dissector_handle(dissect_zip64_end_of_directory_locator, proto_zip));
1360
1361
16
    dissector_add_uint("zip.extra", ZIP_EXTRA_ZIP64, create_dissector_handle(dissect_zip_extra_zip64, proto_zip));
1362
16
    dissector_add_uint("zip.extra", ZIP_EXTRA_NTFS, create_dissector_handle(dissect_zip_extra_ntfs, proto_zip));
1363
16
    dissector_add_uint("zip.extra", ZIP_EXTRA_UT, create_dissector_handle(dissect_zip_extra_unix_time, proto_zip));
1364
16
    dissector_add_uint("zip.extra", ZIP_EXTRA_UCOM, create_dissector_handle(dissect_zip_extra_utf8_comment, proto_zip));
1365
16
    dissector_add_uint("zip.extra", ZIP_EXTRA_UPATH, create_dissector_handle(dissect_zip_extra_utf8_path, proto_zip));
1366
16
    dissector_add_uint("zip.extra", ZIP_EXTRA_UT, create_dissector_handle(dissect_zip_extra_unix_time, proto_zip));
1367
16
    dissector_add_uint("zip.extra", ZIP_EXTRA_UNIX2, create_dissector_handle(dissect_zip_extra_unix2, proto_zip));
1368
16
    dissector_add_uint("zip.extra", ZIP_EXTRA_UNIX3, create_dissector_handle(dissect_zip_extra_unix3, proto_zip));
1369
1370
    // Register some media types to handle in a generic way
1371
16
    dissector_add_string("media_type", "application/zip", zip_handle);
1372
16
    dissector_add_string("media_type", "application/java-archive", zip_handle); // Unofficial types abound
1373
1374
16
    dissector_add_string("media_type.suffix", "zip", zip_handle);
1375
1376
    // Register the ZIP heuristic dissector
1377
16
    heur_dissector_add("wtap_file", dissect_zip_heur, "ZIP file", "zip_wtap", proto_zip, HEURISTIC_ENABLE);
1378
16
}