/src/wireshark/wiretap/ber.c
Line | Count | Source (jump to first uncovered line) |
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-int.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 | int8_t ber_class; |
55 | 0 | int8_t ber_tag; |
56 | 0 | bool ber_pc; |
57 | 0 | uint8_t oct, nlb = 0; |
58 | 0 | int len = 0; |
59 | 0 | int64_t file_size; |
60 | 0 | int offset = 0, i; |
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 | | /* it must be constructed and either a SET or a SEQUENCE */ |
75 | | /* or a CONTEXT/APPLICATION less than 32 (arbitrary) */ |
76 | 0 | if(!(ber_pc && |
77 | 0 | (((ber_class == BER_CLASS_UNI) && ((ber_tag == BER_UNI_TAG_SET) || (ber_tag == BER_UNI_TAG_SEQ))) || |
78 | 0 | (((ber_class == BER_CLASS_CON) || (ber_class == BER_CLASS_APP)) && (ber_tag < 32))))) |
79 | 0 | return WTAP_OPEN_NOT_MINE; |
80 | | |
81 | | /* now check the length */ |
82 | 0 | oct = bytes[offset++]; |
83 | |
|
84 | 0 | if(oct != 0x80) { |
85 | | /* not indefinite length encoded */ |
86 | |
|
87 | 0 | if(!(oct & 0x80)) |
88 | | /* length fits into a single byte */ |
89 | 0 | len = oct; |
90 | 0 | else { |
91 | 0 | nlb = oct & 0x7F; /* number of length bytes */ |
92 | |
|
93 | 0 | if((nlb > 0) && (nlb <= (BER_BYTES_TO_CHECK - 2))) { |
94 | | /* not indefinite length and we have read enough bytes to compute the length */ |
95 | 0 | i = nlb; |
96 | 0 | while(i--) { |
97 | 0 | oct = bytes[offset++]; |
98 | 0 | len = (len<<8) + oct; |
99 | 0 | } |
100 | 0 | } |
101 | 0 | } |
102 | |
|
103 | 0 | len += (2 + nlb); /* add back Tag and Length bytes */ |
104 | 0 | file_size = wtap_file_size(wth, err); |
105 | |
|
106 | 0 | if(len != file_size) { |
107 | 0 | return WTAP_OPEN_NOT_MINE; /* not ASN.1 */ |
108 | 0 | } |
109 | 0 | } else { |
110 | | /* Indefinite length encoded - assume it is BER */ |
111 | 0 | } |
112 | | |
113 | | /* seek back to the start of the file */ |
114 | 0 | if (file_seek(wth->fh, 0, SEEK_SET, err) == -1) |
115 | 0 | return WTAP_OPEN_ERROR; |
116 | | |
117 | 0 | wth->file_type_subtype = ber_file_type_subtype; |
118 | 0 | wth->file_encap = WTAP_ENCAP_BER; |
119 | 0 | wth->snapshot_length = 0; |
120 | |
|
121 | 0 | wth->subtype_read = ber_full_file_read; |
122 | 0 | wth->subtype_seek_read = ber_full_file_seek_read; |
123 | 0 | wth->file_tsprec = WTAP_TSPREC_SEC; |
124 | |
|
125 | 0 | return WTAP_OPEN_MINE; |
126 | 0 | } |
127 | | |
128 | | static const struct supported_block_type ber_blocks_supported[] = { |
129 | | /* |
130 | | * These are file formats that we dissect, so we provide only one |
131 | | * "packet" with the file's contents, and don't support any |
132 | | * options. |
133 | | */ |
134 | | { WTAP_BLOCK_PACKET, ONE_BLOCK_SUPPORTED, NO_OPTIONS_SUPPORTED } |
135 | | }; |
136 | | |
137 | | static const struct file_type_subtype_info ber_info = { |
138 | | "ASN.1 Basic Encoding Rules", "ber", NULL, NULL, |
139 | | false, BLOCKS_SUPPORTED(ber_blocks_supported), |
140 | | NULL, NULL, NULL |
141 | | }; |
142 | | |
143 | | void register_ber(void) |
144 | 14 | { |
145 | 14 | ber_file_type_subtype = wtap_register_file_type_subtype(&ber_info); |
146 | | |
147 | | /* |
148 | | * Register name for backwards compatibility with the |
149 | | * wtap_filetypes table in Lua. |
150 | | */ |
151 | 14 | wtap_register_backwards_compatibility_lua_name("BER", ber_file_type_subtype); |
152 | 14 | } |
153 | | |
154 | | /* |
155 | | * Editor modelines - https://www.wireshark.org/tools/modelines.html |
156 | | * |
157 | | * Local Variables: |
158 | | * c-basic-offset: 2 |
159 | | * tab-width: 8 |
160 | | * indent-tabs-mode: nil |
161 | | * End: |
162 | | * |
163 | | * vi: set shiftwidth=2 tabstop=8 expandtab: |
164 | | * :indentSize=2:tabSize=8:noTabs=true: |
165 | | */ |