/src/wireshark/epan/dissectors/packet-igap.c
Line | Count | Source |
1 | | /* packet-igap.c |
2 | | * Routines for IGMP/IGAP packet disassembly |
3 | | * 2003, Endoh Akria (see AUTHORS for email) |
4 | | * |
5 | | * Wireshark - Network traffic analyzer |
6 | | * By Gerald Combs <gerald@wireshark.org> |
7 | | * Copyright 1998 Gerald Combs |
8 | | * |
9 | | * SPDX-License-Identifier: GPL-2.0-or-later |
10 | | */ |
11 | | |
12 | | /* |
13 | | IGAP "Internet Group membership Authentication Protocol" |
14 | | is defined in draft-hayashi-igap-03.txt. |
15 | | |
16 | | (Author's memo) |
17 | | Type Subtype Message Msize |
18 | | ----------------------------------------------------- |
19 | | ---- 0x02 User password variable |
20 | | ---- 0x03 ---- 00 |
21 | | ---- 0x04 Result of MD5 calculation 16 |
22 | | 0x41 0x23 Challenge value ?? |
23 | | 0x41 0x24 Authentication result code 1 |
24 | | 0x41 0x25 Accounting status code 1 |
25 | | ---- 0x42 User password variable |
26 | | ---- 0x43 ---- 00 |
27 | | ---- 0x44 Result of MD5 calculation 16 |
28 | | |
29 | | */ |
30 | | |
31 | | #include "config.h" |
32 | | |
33 | | #include <epan/packet.h> |
34 | | #include <epan/expert.h> |
35 | | #include "packet-igmp.h" |
36 | | |
37 | | void proto_register_igap(void); |
38 | | void proto_reg_handoff_igap(void); |
39 | | |
40 | | static dissector_handle_t igap_handle; |
41 | | |
42 | | static int proto_igap; |
43 | | static int hf_type; |
44 | | static int hf_max_resp; |
45 | | static int hf_checksum; |
46 | | static int hf_checksum_status; |
47 | | static int hf_maddr; |
48 | | static int hf_version; |
49 | | static int hf_subtype; |
50 | | static int hf_challengeid; |
51 | | static int hf_asize; |
52 | | static int hf_msize; |
53 | | static int hf_account; |
54 | | |
55 | | /* Generated from convert_proto_tree_add_text.pl */ |
56 | | static int hf_igap_challenge; |
57 | | static int hf_igap_user_password; |
58 | | static int hf_igap_authentication_result; |
59 | | static int hf_igap_result_of_md5_calculation; |
60 | | static int hf_igap_accounting_status; |
61 | | static int hf_igap_unknown_message; |
62 | | |
63 | | static int ett_igap; |
64 | | |
65 | | static expert_field ei_checksum; |
66 | | |
67 | | static const value_string igap_types[] = { |
68 | | {IGMP_IGAP_JOIN, "Membership Report (Join)"}, |
69 | | {IGMP_IGAP_QUERY, "Membership Query"}, |
70 | | {IGMP_IGAP_LEAVE, "Leave Group"}, |
71 | | {0, NULL} |
72 | | }; |
73 | | |
74 | | #define IGAP_VERSION_1 0x10 |
75 | | static const value_string igap_version[] = { |
76 | | {IGAP_VERSION_1, "1"}, |
77 | | {0, NULL} |
78 | | }; |
79 | | |
80 | 1 | #define IGAP_SUBTYPE_PASSWORD_JOIN 0x02 |
81 | | #define IGAP_SUBTYPE_CHALLENGE_REQUEST_JOIN 0x03 |
82 | 1 | #define IGAP_SUBTYPE_CHALLENGE_RESPONSE_JOIN 0x04 |
83 | | #define IGAP_SUBTYPE_BASIC_QUERY 0x21 |
84 | 2 | #define IGAP_SUBTYPE_CHALLENGE 0x23 |
85 | 1 | #define IGAP_SUBTYPE_AUTH_MESSAGE 0x24 |
86 | 0 | #define IGAP_SUBTYPE_ACCOUNTING_MESSAGE 0x25 |
87 | | #define IGAP_SUBTYPE_BASIC_LEAVE 0x41 |
88 | 3 | #define IGAP_SUBTYPE_PASSWORD_LEAVE 0x42 |
89 | | #define IGAP_SUBTYPE_CHALLENGE_REQUEST_LEAVE 0x43 |
90 | 1 | #define IGAP_SUBTYPE_CHALLENGE_RESPONSE_LEAVE 0x44 |
91 | | static const value_string igap_subtypes[] = { |
92 | | {IGAP_SUBTYPE_PASSWORD_JOIN, "Password Mechanism Join (Password-Join)"}, |
93 | | {IGAP_SUBTYPE_CHALLENGE_REQUEST_JOIN, "Challenge-Response Mechanism Join Request (Challenge-Request-Join)"}, |
94 | | {IGAP_SUBTYPE_CHALLENGE_RESPONSE_JOIN, "Challenge-Response Mechanism Join Response (Challenge-Response-Join)"}, |
95 | | {IGAP_SUBTYPE_BASIC_QUERY, "Basic Query"}, |
96 | | {IGAP_SUBTYPE_CHALLENGE, "Challenge-Response Mechanism Challenge (Challenge)"}, |
97 | | {IGAP_SUBTYPE_AUTH_MESSAGE, "Authentication Message"}, |
98 | | {IGAP_SUBTYPE_ACCOUNTING_MESSAGE, "Accounting Message"}, |
99 | | {IGAP_SUBTYPE_BASIC_LEAVE, "Basic Leave"}, |
100 | | {IGAP_SUBTYPE_PASSWORD_LEAVE, "Password Mechanism Leave (Password-Leave)"}, |
101 | | {IGAP_SUBTYPE_CHALLENGE_REQUEST_LEAVE, "Challenge-Response Mechanism Leave Challenge Request (Challenge-Request-Leave)"}, |
102 | | {IGAP_SUBTYPE_CHALLENGE_RESPONSE_LEAVE, "Challenge-Response Mechanism Response (Challenge-Response-Leave)"}, |
103 | | {0, NULL} |
104 | | }; |
105 | | |
106 | | #define IGAP_AUTH_SUCCESS 0x11 |
107 | | #define IGAP_AUTH_FAIL 0x21 |
108 | | static const value_string igap_auth_result[] = { |
109 | | {IGAP_AUTH_SUCCESS, "Authentication success"}, |
110 | | {IGAP_AUTH_FAIL, "Authentication failure"}, |
111 | | {0, NULL} |
112 | | }; |
113 | | |
114 | | #define IGAP_ACCOUNT_START 0x11 |
115 | | #define IGAP_ACCOUNT_STOP 0x21 |
116 | | static const value_string igap_account_status[] = { |
117 | | {IGAP_ACCOUNT_START, "Accounting start"}, |
118 | | {IGAP_ACCOUNT_STOP, "Accounting stop"}, |
119 | | {0, NULL} |
120 | | }; |
121 | | |
122 | 25 | #define ACCOUNT_SIZE 16 |
123 | 20 | #define MESSAGE_SIZE 64 |
124 | | |
125 | | /* This function is only called from the IGMP dissector */ |
126 | | static int |
127 | | dissect_igap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, void* data _U_) |
128 | 11 | { |
129 | 11 | proto_tree *tree; |
130 | 11 | proto_item *item; |
131 | 11 | uint8_t type, tsecs, subtype, asize, msize; |
132 | 11 | uint8_t authentication_result, accounting_status; |
133 | 11 | unsigned offset = 0; |
134 | | |
135 | 11 | item = proto_tree_add_item(parent_tree, proto_igap, tvb, offset, -1, ENC_NA); |
136 | 11 | tree = proto_item_add_subtree(item, ett_igap); |
137 | | |
138 | 11 | col_set_str(pinfo->cinfo, COL_PROTOCOL, "IGAP"); |
139 | 11 | col_clear(pinfo->cinfo, COL_INFO); |
140 | | |
141 | 11 | type = tvb_get_uint8(tvb, offset); |
142 | 11 | col_add_str(pinfo->cinfo, COL_INFO, |
143 | 11 | val_to_str(pinfo->pool, type, igap_types, "Unknown Type: 0x%02x")); |
144 | 11 | proto_tree_add_uint(tree, hf_type, tvb, offset, 1, type); |
145 | 11 | offset += 1; |
146 | | |
147 | 11 | tsecs = tvb_get_uint8(tvb, offset); |
148 | 11 | proto_tree_add_uint_format_value(tree, hf_max_resp, tvb, offset, 1, tsecs, |
149 | 11 | "%.1f sec (0x%02x)", tsecs * 0.1, tsecs); |
150 | 11 | offset += 1; |
151 | | |
152 | 11 | igmp_checksum(tree, tvb, hf_checksum, hf_checksum_status, &ei_checksum, pinfo, 0); |
153 | 11 | offset += 2; |
154 | | |
155 | 11 | proto_tree_add_item(tree, hf_maddr, tvb, offset, 4, ENC_BIG_ENDIAN); |
156 | 11 | offset += 4; |
157 | | |
158 | 11 | proto_tree_add_item(tree, hf_version, tvb, offset, 1, ENC_NA); |
159 | 11 | offset += 1; |
160 | | |
161 | 11 | subtype = tvb_get_uint8(tvb, offset); |
162 | 11 | proto_tree_add_uint(tree, hf_subtype, tvb, offset, 1, subtype); |
163 | 11 | offset += 2; |
164 | | |
165 | 11 | proto_tree_add_item(tree, hf_challengeid, tvb, offset, 1, ENC_NA); |
166 | 11 | offset += 1; |
167 | | |
168 | 11 | asize = tvb_get_uint8(tvb, offset); |
169 | 11 | proto_tree_add_uint(tree, hf_asize, tvb, offset, 1, asize); |
170 | 11 | offset += 1; |
171 | | |
172 | 11 | msize = tvb_get_uint8(tvb, offset); |
173 | 11 | proto_tree_add_uint(tree, hf_msize, tvb, offset, 1, msize); |
174 | 11 | offset += 3; |
175 | | |
176 | 11 | if (asize > 0) { |
177 | 8 | if (asize > ACCOUNT_SIZE) { |
178 | | /* Bogus account size. |
179 | | XXX - flag this? */ |
180 | 6 | asize = ACCOUNT_SIZE; |
181 | 6 | } |
182 | | /* XXX - encoding? */ |
183 | 8 | proto_tree_add_item(tree, hf_account, tvb, offset, asize, ENC_ASCII); |
184 | 8 | } |
185 | 11 | offset += ACCOUNT_SIZE; |
186 | | |
187 | 11 | if (msize > 0) { |
188 | 9 | if (msize > MESSAGE_SIZE) { |
189 | | /* Bogus message size. |
190 | | XXX - flag this? */ |
191 | 5 | msize = MESSAGE_SIZE; |
192 | 5 | } |
193 | 9 | switch (subtype) { |
194 | 1 | case IGAP_SUBTYPE_PASSWORD_JOIN: |
195 | 3 | case IGAP_SUBTYPE_PASSWORD_LEAVE: |
196 | | /* Challenge field is user's password */ |
197 | | /* XXX - encoding? */ |
198 | 3 | proto_tree_add_item(tree, hf_igap_user_password, tvb, offset, msize, ENC_ASCII); |
199 | 3 | break; |
200 | 1 | case IGAP_SUBTYPE_CHALLENGE_RESPONSE_JOIN: |
201 | 1 | case IGAP_SUBTYPE_CHALLENGE_RESPONSE_LEAVE: |
202 | | /* Challenge field is the results of MD5 calculation */ |
203 | 1 | proto_tree_add_item(tree, hf_igap_result_of_md5_calculation, tvb, offset, msize, ENC_NA); |
204 | 1 | break; |
205 | 2 | case IGAP_SUBTYPE_CHALLENGE: |
206 | | /* Challenge field is the challenge value */ |
207 | 2 | proto_tree_add_item(tree, hf_igap_challenge, tvb, offset, msize, ENC_NA); |
208 | 2 | break; |
209 | 1 | case IGAP_SUBTYPE_AUTH_MESSAGE: |
210 | | /* Challenge field indicates the result of the authentication */ |
211 | | /* XXX - what if the length isn't 1? */ |
212 | 1 | authentication_result = tvb_get_uint8(tvb, offset); |
213 | 1 | proto_tree_add_uint(tree, hf_igap_authentication_result, tvb, offset, msize, authentication_result); |
214 | 1 | break; |
215 | 0 | case IGAP_SUBTYPE_ACCOUNTING_MESSAGE: |
216 | | /* Challenge field indicates the accounting status */ |
217 | | /* XXX - what if the length isn't 1? */ |
218 | 0 | accounting_status = tvb_get_uint8(tvb, offset); |
219 | 0 | proto_tree_add_uint(tree, hf_igap_accounting_status, tvb, offset, msize, accounting_status); |
220 | 0 | break; |
221 | 2 | default: |
222 | 2 | proto_tree_add_item(tree, hf_igap_unknown_message, tvb, offset, msize, ENC_NA); |
223 | 9 | } |
224 | 9 | } |
225 | 6 | offset += MESSAGE_SIZE; |
226 | | |
227 | 6 | if (item) proto_item_set_len(item, offset); |
228 | 6 | return offset; |
229 | 11 | } |
230 | | |
231 | | |
232 | | void |
233 | | proto_register_igap(void) |
234 | 14 | { |
235 | 14 | static hf_register_info hf[] = { |
236 | 14 | { &hf_type, |
237 | 14 | { "Type", "igap.type", |
238 | 14 | FT_UINT8, BASE_HEX, VALS(igap_types), 0, |
239 | 14 | "IGAP Packet Type", HFILL } |
240 | 14 | }, |
241 | 14 | { &hf_max_resp, |
242 | 14 | { "Max Response Time", "igap.max_resp", |
243 | 14 | FT_UINT8, BASE_DEC, NULL, 0, |
244 | 14 | NULL, HFILL } |
245 | 14 | }, |
246 | 14 | { &hf_checksum, |
247 | 14 | { "Checksum", "igap.checksum", |
248 | 14 | FT_UINT16, BASE_HEX, NULL, 0, |
249 | 14 | NULL, HFILL } |
250 | 14 | }, |
251 | 14 | { &hf_checksum_status, |
252 | 14 | { "Checksum Status", "igap.checksum.status", |
253 | 14 | FT_UINT8, BASE_NONE, VALS(proto_checksum_vals), 0x0, |
254 | 14 | NULL, HFILL } |
255 | 14 | }, |
256 | 14 | { &hf_maddr, |
257 | 14 | { "Multicast group address", "igap.maddr", |
258 | 14 | FT_IPv4, BASE_NONE, NULL, 0, |
259 | 14 | NULL, HFILL } |
260 | 14 | }, |
261 | 14 | { &hf_version, |
262 | 14 | { "Version", "igap.version", |
263 | 14 | FT_UINT8, BASE_HEX, VALS(igap_version), 0, |
264 | 14 | "IGAP protocol version", HFILL } |
265 | 14 | }, |
266 | 14 | { &hf_subtype, |
267 | 14 | { "Subtype", "igap.subtype", |
268 | 14 | FT_UINT8, BASE_HEX, VALS(igap_subtypes), 0, |
269 | 14 | NULL, HFILL } |
270 | 14 | }, |
271 | 14 | { &hf_challengeid, |
272 | 14 | { "Challenge ID", "igap.challengeid", |
273 | 14 | FT_UINT8, BASE_HEX, NULL, 0, |
274 | 14 | NULL, HFILL } |
275 | 14 | }, |
276 | 14 | { &hf_asize, |
277 | 14 | { "Account Size", "igap.asize", |
278 | 14 | FT_UINT8, BASE_DEC, NULL, 0, |
279 | 14 | "Length of the User Account field", HFILL } |
280 | 14 | }, |
281 | 14 | { &hf_msize, |
282 | 14 | { "Message Size", "igap.msize", |
283 | 14 | FT_UINT8, BASE_DEC, NULL, 0, |
284 | 14 | "Length of the Message field", HFILL } |
285 | 14 | }, |
286 | 14 | { &hf_account, |
287 | 14 | { "User Account", "igap.account", |
288 | 14 | FT_STRING, BASE_NONE, NULL, 0, |
289 | 14 | NULL, HFILL } |
290 | 14 | }, |
291 | | |
292 | | /* Generated from convert_proto_tree_add_text.pl */ |
293 | 14 | { &hf_igap_user_password, |
294 | 14 | { "User password", "igap.user_password", |
295 | 14 | FT_STRING, BASE_NONE, NULL, 0x0, |
296 | 14 | NULL, HFILL } |
297 | 14 | }, |
298 | 14 | { &hf_igap_result_of_md5_calculation, |
299 | 14 | { "Result of MD5 calculation", "igap.result_of_md5_calculation", |
300 | 14 | FT_BYTES, BASE_NONE, NULL, 0x0, |
301 | 14 | NULL, HFILL } |
302 | 14 | }, |
303 | 14 | { &hf_igap_challenge, |
304 | 14 | { "Challenge", "igap.challenge", |
305 | 14 | FT_BYTES, BASE_NONE, NULL, 0x0, |
306 | 14 | NULL, HFILL } |
307 | 14 | }, |
308 | 14 | { &hf_igap_authentication_result, |
309 | 14 | { "Authentication result", "igap.authentication_result", |
310 | 14 | FT_UINT8, BASE_HEX, VALS(igap_auth_result), 0x0, |
311 | 14 | NULL, HFILL } |
312 | 14 | }, |
313 | 14 | { &hf_igap_accounting_status, |
314 | 14 | { "Accounting status", "igap.accounting_status", |
315 | 14 | FT_UINT8, BASE_HEX, VALS(igap_account_status), 0x0, |
316 | 14 | NULL, HFILL } |
317 | 14 | }, |
318 | 14 | { &hf_igap_unknown_message, |
319 | 14 | { "Unknown message", "igap.unknown_message", |
320 | 14 | FT_BYTES, BASE_NONE, NULL, 0x0, |
321 | 14 | NULL, HFILL } |
322 | 14 | }, |
323 | 14 | }; |
324 | | |
325 | 14 | static ei_register_info ei[] = { |
326 | 14 | { &ei_checksum, { "igap.bad_checksum", PI_CHECKSUM, PI_ERROR, "Bad checksum", EXPFILL }}, |
327 | 14 | }; |
328 | | |
329 | 14 | expert_module_t* expert_igap; |
330 | | |
331 | 14 | static int *ett[] = { |
332 | 14 | &ett_igap |
333 | 14 | }; |
334 | | |
335 | 14 | proto_igap = proto_register_protocol("Internet Group membership Authentication Protocol", "IGAP", "igap"); |
336 | 14 | proto_register_field_array(proto_igap, hf, array_length(hf)); |
337 | 14 | proto_register_subtree_array(ett, array_length(ett)); |
338 | 14 | expert_igap = expert_register_protocol(proto_igap); |
339 | 14 | expert_register_field_array(expert_igap, ei, array_length(ei)); |
340 | | |
341 | 14 | igap_handle = register_dissector("igap", dissect_igap, proto_igap); |
342 | 14 | } |
343 | | |
344 | | void |
345 | | proto_reg_handoff_igap(void) |
346 | 14 | { |
347 | 14 | dissector_add_uint("igmp.type", IGMP_IGAP_JOIN, igap_handle); |
348 | 14 | dissector_add_uint("igmp.type", IGMP_IGAP_QUERY, igap_handle); |
349 | 14 | dissector_add_uint("igmp.type", IGMP_IGAP_LEAVE, igap_handle); |
350 | 14 | } |
351 | | |
352 | | /* |
353 | | * Editor modelines - https://www.wireshark.org/tools/modelines.html |
354 | | * |
355 | | * Local variables: |
356 | | * c-basic-offset: 4 |
357 | | * tab-width: 8 |
358 | | * indent-tabs-mode: nil |
359 | | * End: |
360 | | * |
361 | | * vi: set shiftwidth=4 tabstop=8 expandtab: |
362 | | * :indentSize=4:tabSize=8:noTabs=true: |
363 | | */ |