/src/wireshark/wiretap/ber.c
Line | Count | Source |
1 | | /* ber.c |
2 | | * |
3 | | * Basic Encoding Rules (BER) file reading |
4 | | * |
5 | | * SPDX-License-Identifier: GPL-2.0-or-later |
6 | | */ |
7 | | |
8 | | #include "config.h" |
9 | | #include "ber.h" |
10 | | |
11 | | #include "wtap_module.h" |
12 | | #include "file_wrappers.h" |
13 | | #include <wsutil/buffer.h> |
14 | | |
15 | 0 | #define BER_CLASS_UNI 0 |
16 | 0 | #define BER_CLASS_APP 1 |
17 | 0 | #define BER_CLASS_CON 2 |
18 | | |
19 | 0 | #define BER_UNI_TAG_SEQ 16 /* SEQUENCE, SEQUENCE OF */ |
20 | 0 | #define BER_UNI_TAG_SET 17 /* SET, SET OF */ |
21 | | |
22 | | static int ber_file_type_subtype = -1; |
23 | | |
24 | | void register_ber(void); |
25 | | |
26 | | static bool ber_full_file_read(wtap *wth, wtap_rec *rec, |
27 | | int *err, char **err_info, |
28 | | int64_t *data_offset) |
29 | 0 | { |
30 | 0 | if (!wtap_full_file_read(wth, rec, err, err_info, data_offset)) |
31 | 0 | return false; |
32 | | |
33 | | /* Pass the file name. */ |
34 | 0 | rec->rec_header.packet_header.pseudo_header.ber.pathname = wth->pathname; |
35 | 0 | return true; |
36 | 0 | } |
37 | | |
38 | | static bool ber_full_file_seek_read(wtap *wth, int64_t seek_off, wtap_rec *rec, |
39 | | int *err, char **err_info) |
40 | 0 | { |
41 | 0 | if (!wtap_full_file_seek_read(wth, seek_off, rec, err, err_info)) |
42 | 0 | return false; |
43 | | |
44 | | /* Pass the file name. */ |
45 | 0 | rec->rec_header.packet_header.pseudo_header.ber.pathname = wth->pathname; |
46 | 0 | return true; |
47 | 0 | } |
48 | | |
49 | | wtap_open_return_val ber_open(wtap *wth, int *err, char **err_info) |
50 | 0 | { |
51 | 0 | #define BER_BYTES_TO_CHECK 8 |
52 | 0 | uint8_t bytes[BER_BYTES_TO_CHECK]; |
53 | 0 | uint8_t ber_id; |
54 | 0 | uint8_t ber_class; |
55 | 0 | uint8_t ber_tag; |
56 | 0 | bool ber_pc; |
57 | 0 | uint8_t oct, ntb = 0, nlb = 0; |
58 | 0 | int64_t len = 0; |
59 | 0 | int64_t file_size; |
60 | 0 | size_t offset = 0; |
61 | |
|
62 | 0 | if (!wtap_read_bytes(wth->fh, &bytes, BER_BYTES_TO_CHECK, err, err_info)) { |
63 | 0 | if (*err != WTAP_ERR_SHORT_READ) |
64 | 0 | return WTAP_OPEN_ERROR; |
65 | 0 | return WTAP_OPEN_NOT_MINE; |
66 | 0 | } |
67 | | |
68 | 0 | ber_id = bytes[offset++]; |
69 | |
|
70 | 0 | ber_class = (ber_id>>6) & 0x03; |
71 | 0 | ber_pc = (ber_id>>5) & 0x01; |
72 | 0 | ber_tag = ber_id & 0x1F; |
73 | |
|
74 | 0 | if (ber_tag == 0x1F) { |
75 | 0 | ber_tag = bytes[offset++]; |
76 | 0 | ntb = 1; /* number of tag bytes */ |
77 | 0 | } |
78 | | |
79 | | /* it must be constructed and either a SET or a SEQUENCE */ |
80 | | /* or a CONTEXT/APPLICATION less than 32 (arbitrary) */ |
81 | 0 | if(!(ber_pc && |
82 | 0 | (((ber_class == BER_CLASS_UNI) && ((ber_tag == BER_UNI_TAG_SET) || (ber_tag == BER_UNI_TAG_SEQ))) || |
83 | 0 | (((ber_class == BER_CLASS_CON) || (ber_class == BER_CLASS_APP)) && (ber_tag < 0xFF))))) |
84 | 0 | return WTAP_OPEN_NOT_MINE; |
85 | | |
86 | | /* now check the length */ |
87 | 0 | oct = bytes[offset++]; |
88 | |
|
89 | 0 | if(oct != 0x80) { |
90 | | /* not indefinite length encoded */ |
91 | |
|
92 | 0 | if(!(oct & 0x80)) |
93 | | /* length fits into a single byte */ |
94 | 0 | len = oct; |
95 | 0 | else { |
96 | 0 | nlb = oct & 0x7F; /* number of length bytes */ |
97 | |
|
98 | 0 | if(nlb > 0) { |
99 | 0 | if (nlb + offset >= sizeof(bytes)) { |
100 | | /* This limits us to 1 or 256 TiB, depending on tag length. */ |
101 | 0 | return WTAP_OPEN_NOT_MINE; |
102 | 0 | } |
103 | | /* not indefinite length and we have read enough bytes to compute the length */ |
104 | 0 | for(int i = 0; i < nlb; i++) { |
105 | 0 | oct = bytes[offset++]; |
106 | 0 | if (ckd_mul(&len, len, 256)) { |
107 | | /* Can't happen, unless we increase BER_BYTES_TO_CHECK */ |
108 | 0 | return WTAP_OPEN_NOT_MINE; |
109 | 0 | } |
110 | 0 | len += oct; |
111 | 0 | } |
112 | 0 | } |
113 | 0 | } |
114 | | |
115 | | /* add back Tag and Length bytes */ |
116 | 0 | if (ckd_add(&len, len, 2 + ntb + nlb)) { |
117 | 0 | return WTAP_OPEN_NOT_MINE; |
118 | 0 | } |
119 | 0 | file_size = wtap_file_size(wth, err); |
120 | |
|
121 | 0 | if(len != file_size) { |
122 | 0 | return WTAP_OPEN_NOT_MINE; /* not ASN.1 */ |
123 | 0 | } |
124 | 0 | } else { |
125 | | /* Indefinite length encoded - assume it is BER */ |
126 | 0 | } |
127 | | |
128 | | /* seek back to the start of the file */ |
129 | 0 | if (file_seek(wth->fh, 0, SEEK_SET, err) == -1) |
130 | 0 | return WTAP_OPEN_ERROR; |
131 | | |
132 | 0 | wth->file_type_subtype = ber_file_type_subtype; |
133 | 0 | wth->file_encap = WTAP_ENCAP_BER; |
134 | 0 | wth->snapshot_length = 0; |
135 | |
|
136 | 0 | wth->subtype_read = ber_full_file_read; |
137 | 0 | wth->subtype_seek_read = ber_full_file_seek_read; |
138 | 0 | wth->file_tsprec = WTAP_TSPREC_SEC; |
139 | |
|
140 | 0 | return WTAP_OPEN_MINE; |
141 | 0 | } |
142 | | |
143 | | static const struct supported_block_type ber_blocks_supported[] = { |
144 | | /* |
145 | | * These are file formats that we dissect, so we provide only one |
146 | | * "packet" with the file's contents, and don't support any |
147 | | * options. |
148 | | */ |
149 | | { WTAP_BLOCK_PACKET, ONE_BLOCK_SUPPORTED, NO_OPTIONS_SUPPORTED } |
150 | | }; |
151 | | |
152 | | static const struct file_type_subtype_info ber_info = { |
153 | | "ASN.1 Basic Encoding Rules", "ber", NULL, NULL, |
154 | | false, BLOCKS_SUPPORTED(ber_blocks_supported), |
155 | | NULL, NULL, NULL |
156 | | }; |
157 | | |
158 | | void register_ber(void) |
159 | 15 | { |
160 | 15 | ber_file_type_subtype = wtap_register_file_type_subtype(&ber_info); |
161 | | |
162 | | /* |
163 | | * Register name for backwards compatibility with the |
164 | | * wtap_filetypes table in Lua. |
165 | | */ |
166 | 15 | wtap_register_backwards_compatibility_lua_name("BER", ber_file_type_subtype); |
167 | 15 | } |
168 | | |
169 | | /* |
170 | | * Editor modelines - https://www.wireshark.org/tools/modelines.html |
171 | | * |
172 | | * Local Variables: |
173 | | * c-basic-offset: 2 |
174 | | * tab-width: 8 |
175 | | * indent-tabs-mode: nil |
176 | | * End: |
177 | | * |
178 | | * vi: set shiftwidth=2 tabstop=8 expandtab: |
179 | | * :indentSize=2:tabSize=8:noTabs=true: |
180 | | */ |