1 /* packet-eap.c
2 * Routines for EAP Extensible Authentication Protocol dissection
3 * RFC 2284, RFC 3748
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 #include "config.h"
13
14 #include <stdio.h>
15
16 #include <epan/packet.h>
17 #include <epan/conversation.h>
18 #include <epan/ppptypes.h>
19 #include <epan/reassemble.h>
20 #include <epan/eap.h>
21 #include <epan/expert.h>
22 #include <epan/proto_data.h>
23
24 #include "packet-eapol.h"
25 #include "packet-wps.h"
26 #include "packet-e212.h"
27 #include "packet-tls-utils.h"
28
29 void proto_register_eap(void);
30 void proto_reg_handoff_eap(void);
31
32 static int proto_eap = -1;
33 static int hf_eap_code = -1;
34 static int hf_eap_identifier = -1;
35 static int hf_eap_len = -1;
36 static int hf_eap_type = -1;
37 static int hf_eap_type_nak = -1;
38
39 static int hf_eap_identity = -1;
40 static int hf_eap_identity_full = -1;
41 static int hf_eap_identity_actual_len = -1;
42 static int hf_eap_identity_prefix = -1;
43 static int hf_eap_identity_type = -1;
44 static int hf_eap_identity_mcc = -1;
45 static int hf_eap_identity_mcc_mnc_2digits = -1;
46 static int hf_eap_identity_mcc_mnc_3digits = -1;
47 static int hf_eap_identity_padding = -1;
48
49 static int hf_eap_notification = -1;
50
51 static int hf_eap_md5_value_size = -1;
52 static int hf_eap_md5_value = -1;
53 static int hf_eap_md5_extra_data = -1;
54
55 static int hf_eap_sim_subtype = -1;
56 static int hf_eap_sim_reserved = -1;
57 static int hf_eap_sim_subtype_attribute = -1;
58 static int hf_eap_sim_subtype_type = -1;
59 static int hf_eap_sim_subtype_length = -1;
60 static int hf_eap_sim_notification_type = -1;
61 static int hf_eap_sim_error_code_type = -1;
62 static int hf_eap_sim_subtype_value = -1;
63
64 static int hf_eap_aka_subtype = -1;
65 static int hf_eap_aka_reserved = -1;
66 static int hf_eap_aka_subtype_attribute = -1;
67 static int hf_eap_aka_subtype_type = -1;
68 static int hf_eap_aka_subtype_length = -1;
69 static int hf_eap_aka_notification_type = -1;
70 static int hf_eap_aka_error_code_type = -1;
71 static int hf_eap_aka_subtype_value = -1;
72
73 static int hf_eap_leap_version = -1;
74 static int hf_eap_leap_reserved = -1;
75 static int hf_eap_leap_count = -1;
76 static int hf_eap_leap_peer_challenge = -1;
77 static int hf_eap_leap_peer_response = -1;
78 static int hf_eap_leap_ap_challenge = -1;
79 static int hf_eap_leap_ap_response = -1;
80 static int hf_eap_leap_data = -1;
81 static int hf_eap_leap_name = -1;
82
83 static int hf_eap_ms_chap_v2_opcode = -1;
84 static int hf_eap_ms_chap_v2_id = -1;
85 static int hf_eap_ms_chap_v2_length = -1;
86 static int hf_eap_ms_chap_v2_value_size = -1;
87 static int hf_eap_ms_chap_v2_challenge = -1;
88 static int hf_eap_ms_chap_v2_name = -1;
89 static int hf_eap_ms_chap_v2_peer_challenge = -1;
90 static int hf_eap_ms_chap_v2_reserved = -1;
91 static int hf_eap_ms_chap_v2_nt_response = -1;
92 static int hf_eap_ms_chap_v2_flags = -1;
93 static int hf_eap_ms_chap_v2_response = -1;
94 static int hf_eap_ms_chap_v2_message = -1;
95 static int hf_eap_ms_chap_v2_failure_request = -1;
96 static int hf_eap_ms_chap_v2_data = -1;
97
98 static int hf_eap_pax_opcode = -1;
99 static int hf_eap_pax_flags = -1;
100 static int hf_eap_pax_flags_mf = -1;
101 static int hf_eap_pax_flags_ce = -1;
102 static int hf_eap_pax_flags_ai = -1;
103 static int hf_eap_pax_flags_reserved = -1;
104 static int hf_eap_pax_mac_id = -1;
105 static int hf_eap_pax_dh_group_id = -1;
106 static int hf_eap_pax_public_key_id = -1;
107 static int hf_eap_pax_a_len = -1;
108 static int hf_eap_pax_a = -1;
109 static int hf_eap_pax_b_len = -1;
110 static int hf_eap_pax_b = -1;
111 static int hf_eap_pax_cid_len = -1;
112 static int hf_eap_pax_cid = -1;
113 static int hf_eap_pax_mac_ck_len = -1;
114 static int hf_eap_pax_mac_ck = -1;
115 static int hf_eap_pax_ade_len = -1;
116 static int hf_eap_pax_ade = -1;
117 static int hf_eap_pax_mac_icv = -1;
118
119 static int hf_eap_psk_flags = -1;
120 static int hf_eap_psk_flags_t = -1;
121 static int hf_eap_psk_flags_reserved = -1;
122 static int hf_eap_psk_rand_p = -1;
123 static int hf_eap_psk_rand_s = -1;
124 static int hf_eap_psk_mac_p = -1;
125 static int hf_eap_psk_mac_s = -1;
126 static int hf_eap_psk_id_p = -1;
127 static int hf_eap_psk_id_s = -1;
128 static int hf_eap_psk_pchannel = -1;
129
130 static int hf_eap_sake_version = -1;
131 static int hf_eap_sake_session_id = -1;
132 static int hf_eap_sake_subtype = -1;
133 static int hf_eap_sake_attr_type = -1;
134 static int hf_eap_sake_attr_len = -1;
135 static int hf_eap_sake_attr_value = -1;
136 static int hf_eap_sake_attr_value_str = -1;
137 static int hf_eap_sake_attr_value_uint48 = -1;
138
139 static int hf_eap_gpsk_opcode = -1;
140 static int hf_eap_gpsk_id_server_len = -1;
141 static int hf_eap_gpsk_id_server = -1;
142 static int hf_eap_gpsk_id_peer_len = -1;
143 static int hf_eap_gpsk_id_peer = -1;
144 static int hf_eap_gpsk_rand_server = -1;
145 static int hf_eap_gpsk_rand_peer = -1;
146 static int hf_eap_gpsk_csuite_list_len = -1;
147 static int hf_eap_gpsk_csuite_vendor = -1;
148 static int hf_eap_gpsk_csuite_specifier = -1;
149 static int hf_eap_gpsk_pd_payload_len = -1;
150 static int hf_eap_gpsk_pd_payload = -1;
151 static int hf_eap_gpsk_payload_mac = -1;
152 static int hf_eap_gpsk_failure_code = -1;
153
154 static int hf_eap_data = -1;
155
156 static gint ett_eap = -1;
157 static gint ett_eap_pax_flags = -1;
158 static gint ett_eap_psk_flags = -1;
159 static gint ett_eap_sake_attr = -1;
160 static gint ett_eap_gpsk_csuite_list = -1;
161 static gint ett_eap_gpsk_csuite = -1;
162 static gint ett_eap_gpsk_csuite_sel = -1;
163
164 static expert_field ei_eap_ms_chap_v2_length = EI_INIT;
165 static expert_field ei_eap_mitm_attacks = EI_INIT;
166 static expert_field ei_eap_md5_value_size_overflow = EI_INIT;
167 static expert_field ei_eap_dictionary_attacks = EI_INIT;
168 static expert_field ei_eap_identity_invalid = EI_INIT;
169 static expert_field ei_eap_retransmission = EI_INIT;
170 static expert_field ei_eap_bad_length = EI_INIT;
171
172 static dissector_table_t eap_expanded_type_dissector_table;
173
174 static dissector_handle_t eap_handle;
175
176 static dissector_handle_t tls_handle;
177 static dissector_handle_t diameter_avps_handle;
178 static dissector_handle_t teap_handle;
179
180 const value_string eap_code_vals[] = {
181 { EAP_REQUEST, "Request" },
182 { EAP_RESPONSE, "Response" },
183 { EAP_SUCCESS, "Success" },
184 { EAP_FAILURE, "Failure" },
185 { EAP_INITIATE, "Initiate" }, /* [RFC5296] */
186 { EAP_FINISH, "Finish" }, /* [RFC5296] */
187 { 0, NULL }
188 };
189
190 /*
191 References:
192 1) https://www.iana.org/assignments/ppp-numbers PPP EAP REQUEST/RESPONSE TYPES
193 2) https://tools.ietf.org/html/draft-ietf-pppext-rfc2284bis-02
194 3) RFC2284
195 4) RFC3748
196 5) https://www.iana.org/assignments/eap-numbers EAP registry (updated 2011-02-22)
197 6) https://tools.ietf.org/html/draft-bersani-eap-synthesis-sharedkeymethods-00
198 */
199
200 static const value_string eap_type_vals[] = {
201 { 1, "Identity" },
202 { 2, "Notification" },
203 { 3, "Legacy Nak (Response Only)" },
204 { 4, "MD5-Challenge EAP (EAP-MD5-CHALLENGE)" },
205 { 5, "One-Time Password EAP (EAP-OTP)" },
206 { 6, "Generic Token Card EAP (EAP-GTC)" },
207 { 7, "Allocated" },
208 { 8, "Allocated" },
209 { 9, "RSA Public Key Authentication EAP (EAP-RSA-PKA)" },
210 { 10, "DSS Unilateral EAP (EAP-DSS)" },
211 { 11, "KEA EAP (EAP-KEA)" },
212 { 12, "KEA Validate EAP (EAP-KEA-VALIDATE)" },
213 { 13, "TLS EAP (EAP-TLS)" },
214 { 14, "Defender Token EAP (EAP-AXENT)" },
215 { 15, "RSA Security SecurID EAP (EAP-RSA-SECURID)" },
216 { 16, "Arcot Systems EAP (EAP-ARCOT-SYSTEMS)" },
217 { 17, "Cisco Wireless EAP / Lightweight EAP (EAP-LEAP)" },
218 { 18, "GSM Subscriber Identity Modules EAP (EAP-SIM)" },
219 { 19, "Secure Remote Password SHA1 Part 1 EAP (EAP-SRP-SHA1-PART1)" },
220 { 20, "Secure Remote Password SHA1 Part 2 EAP (EAP-SRP-SHA1-PART2)" },
221 { 21, "Tunneled TLS EAP (EAP-TTLS)" },
222 { 22, "Remote Access Service EAP (EAP-RAS)" },
223 { 23, "UMTS Authentication and Key Agreement EAP (EAP-AKA)" },
224 { 24, "3Com Wireless EAP (EAP-3COM-WIRELESS)" },
225 { 25, "Protected EAP (EAP-PEAP)" },
226 { 26, "MS-Authentication EAP (EAP-MS-AUTH)" },
227 { 27, "Mutual Authentication w/Key Exchange EAP (EAP-MAKE)" },
228 { 28, "CRYPTOCard EAP (EAP-CRYPTOCARD)" },
229 { 29, "MS-CHAP-v2 EAP (EAP-MS-CHAP-V2)" },
230 { 30, "DynamID EAP (EAP-DYNAMID)" },
231 { 31, "Rob EAP (EAP-ROB)" },
232 { 32, "Protected One-Time Password EAP (EAP-POTP)" },
233 { 33, "MS-Authentication TLV EAP (EAP-MS-AUTH-TLV)" },
234 { 34, "SentriNET (EAP-SENTRINET)" },
235 { 35, "Actiontec Wireless EAP (EAP-ACTIONTEC-WIRELESS)" },
236 { 36, "Cogent Systems Biometrics Authentication EAP (EAP-COGENT-BIOMETRIC)" },
237 { 37, "AirFortress EAP (EAP-AIRFORTRESS)" },
238 { 38, "HTTP Digest EAP (EAP-HTTP-DIGEST)" },
239 { 39, "SecureSuite EAP (EAP-SECURESUITE)" },
240 { 40, "DeviceConnect EAP (EAP-DEVICECONNECT)" },
241 { 41, "Simple Password Exponential Key Exchange EAP (EAP-SPEKE)" },
242 { 42, "MOBAC EAP (EAP-MOBAC)" },
243 { 43, "Flexible Authentication via Secure Tunneling EAP (EAP-FAST)" },
244 { 44, "ZoneLabs EAP (EAP-ZLXEAP)" },
245 { 45, "Link EAP (EAP-LINK)" },
246 { 46, "Password Authenticated eXchange EAP (EAP-PAX)" },
247 { 47, "Pre-Shared Key EAP (EAP-PSK)" },
248 { 48, "Shared-secret Authentication and Key Establishment EAP (EAP-SAKE)" },
249 { 49, "Internet Key Exchange v2 EAP (EAP-IKEv2)" },
250 { 50, "UMTS Authentication and Key Agreement' EAP (EAP-AKA')" },
251 { 51, "Generalized Pre-Shared Key EAP (EAP-GPSK)" },
252 { 52, "Password EAP (EAP-pwd)" },
253 { 53, "Encrypted Key Exchange v1 EAP (EAP-EKEv1)" },
254 { 55, "Tunneled EAP protocol" },
255 { 254, "Expanded Type" },
256 { 255, "Experimental" },
257 { 0, NULL }
258 };
259 value_string_ext eap_type_vals_ext = VALUE_STRING_EXT_INIT(eap_type_vals);
260
261 static const value_string eap_identity_prefix_vals[] = {
262 { 0x00, "Encrypted IMSI" },
263 { '0', "EAP-AKA Permanent" },
264 { '1', "EAP-SIM Permanent" },
265 { '2', "EAP-AKA Pseudonym" },
266 { '3', "EAP-SIM Pseudonym" },
267 { '4', "EAP-AKA Reauth ID" },
268 { '5', "EAP-SIM Reauth ID" },
269 { '6', "EAP-AKA Prime Permanent" },
270 { '7', "EAP-AKA Prime Pseudonym" },
271 { '8', "EAP-AKA Prime Reauth ID" },
272 { 'C', "Conservative Peer" },
273 { 'a', "Anonymous Identity" },
274 { 0, NULL }
275 };
276
277 const value_string eap_sim_subtype_vals[] = {
278 { SIM_START, "Start" },
279 { SIM_CHALLENGE, "Challenge" },
280 { SIM_NOTIFICATION, "Notification" },
281 { SIM_RE_AUTHENTICATION, "Re-authentication" },
282 { SIM_CLIENT_ERROR, "Client-Error" },
283 { 0, NULL }
284 };
285
286 const value_string eap_aka_subtype_vals[] = {
287 { AKA_CHALLENGE, "AKA-Challenge" },
288 { AKA_AUTHENTICATION_REJECT, "AKA-Authentication-Reject" },
289 { AKA_SYNCHRONIZATION_FAILURE, "AKA-Synchronization-Failure" },
290 { AKA_IDENTITY, "AKA-Identity" },
291 { AKA_NOTIFICATION, "Notification" },
292 { AKA_REAUTHENTICATION, "Re-authentication" },
293 { AKA_CLIENT_ERROR, "Client-Error" },
294 { 0, NULL }
295 };
296
297 /*
298 References:
299 1) http://www.iana.org/assignments/eapsimaka-numbers/eapsimaka-numbers.xml
300 3) RFC4186
301 3) RFC4187
302 4) RFC5448
303 5) 3GPP TS 24.302
304 */
305
306 #define AT_NOTIFICATION 12
307 #define AT_IDENTITY 14
308 #define AT_CLIENT_ERROR_CODE 22
309
310 static const value_string eap_sim_aka_attribute_vals[] = {
311 { 1, "AT_RAND" },
312 { 2, "AT_AUTN" },
313 { 3, "AT_RES" },
314 { 4, "AT_AUTS" },
315 { 6, "AT_PADDING" },
316 { 7, "AT_NONCE_MT" },
317 { 10, "AT_PERMANENT_ID_REQ" },
318 { 11, "AT_MAC" },
319 { 12, "AT_NOTIFICATION" },
320 { 13, "AT_ANY_ID_REQ" },
321 { 14, "AT_IDENTITY" },
322 { 15, "AT_VERSION_LIST" },
323 { 16, "AT_SELECTED_VERSION" },
324 { 17, "AT_FULLAUTH_ID_REQ" },
325 { 19, "AT_COUNTER" },
326 { 20, "AT_COUNTER_TOO_SMALL" },
327 { 21, "AT_NONCE_S" },
328 { 22, "AT_CLIENT_ERROR_CODE" },
329 { 23, "AT_KDF_INPUT"},
330 { 24, "AT_KDF"},
331 { 128, "Unassigned" },
332 { 129, "AT_IV" },
333 { 130, "AT_ENCR_DATA" },
334 { 131, "Unassigned" },
335 { 132, "AT_NEXT_PSEUDONYM" },
336 { 133, "AT_NEXT_REAUTH_ID" },
337 { 134, "AT_CHECKCODE" },
338 { 135, "AT_RESULT_IND" },
339 { 136, "AT_BIDDING" },
340 { 137, "AT_IPMS_IND" },
341 { 138, "AT_IPMS_RES" },
342 { 139, "AT_TRUST_IND" },
343 { 140, "AT_SHORT_NAME_FOR_NETWORK" },
344 { 141, "AT_FULL_NAME_FOR_NETWORK" },
345 { 142, "AT_RQSI_IND" },
346 { 143, "AT_RQSI_RES" },
347 { 144, "AT_TWAN_CONN_MODE" },
348 { 145, "AT_VIRTUAL_NETWORK_ID" },
349 { 146, "AT_VIRTUAL_NETWORK_REQ" },
350 { 147, "AT_CONNECTIVITY_TYPE" },
351 { 148, "AT_HANDOVER_INDICATION" },
352 { 149, "AT_HANDOVER_SESSION_ID" },
353 { 150, "AT_MN_SERIAL_ID" },
354 { 151, "AT_DEVICE_IDENTITY" },
355 { 0, NULL }
356 };
357 static value_string_ext eap_sim_aka_attribute_vals_ext = VALUE_STRING_EXT_INIT(eap_sim_aka_attribute_vals);
358
359 static const value_string eap_sim_aka_notification_vals[] = {
360 { 0, "General Failure after Authentication" },
361 { 1026, "User has been temporarily denied access" },
362 { 1031, "User has not subscribed to the requested service" },
363 { 8192, "Failure to Terminate the Authentication Exchange" },
364 {16384, "General Failure" },
365 {32768, "Success" },
366 {0, NULL }
367 };
368
369 static const value_string eap_sim_aka_client_error_codes[] = {
370 { 0, "Unable to process packet" },
371 { 1, "Unsupported version" },
372 { 2, "Insufficient number of challenges" },
373 { 3, "RANDs are not fresh" },
374 { 0, NULL }
375 };
376
377 const value_string eap_ms_chap_v2_opcode_vals[] = {
378 { MS_CHAP_V2_CHALLENGE, "Challenge" },
379 { MS_CHAP_V2_RESPONSE, "Response" },
380 { MS_CHAP_V2_SUCCESS, "Success" },
381 { MS_CHAP_V2_FAILURE, "Failure" },
382 { MS_CHAP_V2_CHANGE_PASSWORD, "Change-Password" },
383 { 0, NULL }
384 };
385
386 #define PAX_STD_1 0x01
387 #define PAX_STD_2 0x02
388 #define PAX_STD_3 0x03
389 #define PAX_SEC_1 0x11
390 #define PAX_SEC_2 0x12
391 #define PAX_SEC_3 0x13
392 #define PAX_SEC_4 0x14
393 #define PAX_SEC_5 0x15
394 #define PAX_ACK 0x21
395
396 static const value_string eap_pax_opcode_vals[] = {
397 { PAX_STD_1, "STD-1" },
398 { PAX_STD_2, "STD-2" },
399 { PAX_STD_3, "STD-3" },
400 { PAX_SEC_1, "SEC-1" },
401 { PAX_SEC_2, "SEC-2" },
402 { PAX_SEC_3, "SEC-3" },
403 { PAX_SEC_4, "SEC-4" },
404 { PAX_SEC_5, "SEC-5" },
405 { PAX_ACK, "ACK" },
406 { 0, NULL }
407 };
408
409 #define EAP_PAX_FLAG_MF 0x01 /* more fragments */
410 #define EAP_PAX_FLAG_CE 0x02 /* certificate enabled */
411 #define EAP_PAX_FLAG_AI 0x04 /* ADE included */
412 #define EAP_PAX_FLAG_RESERVED 0xF8 /* reserved */
413
414 #define PAX_MAC_ID_HMAC_SHA1_128 0x01
415 #define PAX_MAC_ID_HMAC_SHA256_128 0x02
416
417 static const value_string eap_pax_mac_id_vals[] = {
418 { PAX_MAC_ID_HMAC_SHA1_128, "HMAC_SHA1_128" },
419 { PAX_MAC_ID_HMAC_SHA256_128, "HMAXĆ_SHA256_128" },
420 { 0, NULL }
421 };
422
423 #define PAX_DH_GROUP_ID_NONE 0x00
424 #define PAX_DH_GROUP_ID_DH_14 0x01
425 #define PAX_DH_GROUP_ID_DH_15 0x02
426 #define PAX_DH_GROUP_ID_ECC_P256 0x03
427
428 static const value_string eap_pax_dh_group_id_vals[] = {
429 { PAX_DH_GROUP_ID_NONE, "NONE" },
430 { PAX_DH_GROUP_ID_DH_14, "2048-bit MODP Group (IANA DH Group 14)" },
431 { PAX_DH_GROUP_ID_DH_15, "3072-bit MODP Group (IANA DH Group 15)" },
432 { PAX_DH_GROUP_ID_ECC_P256, "NIST ECC Group P-256" },
433 { 0, NULL }
434 };
435
436 #define PAX_PUBLIC_KEY_ID_NONE 0x00
437 #define PAX_PUBLIC_KEY_ID_RSAES_OAEP 0x01
438 #define PAX_PUBLIC_KEY_ID_RSA_PKCS1_V1_5 0x02
439 #define PAX_PUBLIC_KEY_ID_EL_GAMAL_ECC_P256 0x03
440
441 static const value_string eap_pax_public_key_id_vals[] = {
442 { PAX_PUBLIC_KEY_ID_NONE, "NONE" },
443 { PAX_PUBLIC_KEY_ID_RSAES_OAEP, "RSAES-OAEP" },
444 { PAX_PUBLIC_KEY_ID_RSA_PKCS1_V1_5, "RSA-PKCS1-V1_5" },
445 { PAX_PUBLIC_KEY_ID_EL_GAMAL_ECC_P256, "El-Gamal Over NIST ECC Group P-256" },
446 { 0, NULL }
447 };
448
449 #define EAP_PSK_FLAGS_T_MASK 0xC0
450
451 #define SAKE_CHALLENGE 1
452 #define SAKE_CONFIRM 2
453 #define SAKE_AUTH_REJECT 3
454 #define SAKE_IDENTITY 4
455
456 static const value_string eap_sake_subtype_vals[] = {
457 { SAKE_CHALLENGE, "SAKE/Challenge" },
458 { SAKE_CONFIRM, "SAKE/Confirm" },
459 { SAKE_AUTH_REJECT, "SAKE/Auth-Reject" },
460 { SAKE_IDENTITY, "SAKE/Identity" },
461 { 0, NULL }
462 };
463
464 #define SAKE_AT_RAND_S 1
465 #define SAKE_AT_RAND_P 2
466 #define SAKE_AT_MIC_S 3
467 #define SAKE_AT_MIC_P 4
468 #define SAKE_AT_SERVERID 5
469 #define SAKE_AT_PEERID 6
470 #define SAKE_AT_SPI_S 7
471 #define SAKE_AT_SPI_P 8
472 #define SAKE_AT_ANY_ID_REQ 9
473 #define SAKE_AT_PERM_ID_REQ 10
474 #define SAKE_AT_ENCR_DATA 128
475 #define SAKE_AT_IV 129
476 #define SAKE_AT_PADDING 130
477 #define SAKE_AT_NEXT_TMPID 131
478 #define SAKE_AT_MSK_LIFE 132
479
480 static const value_string eap_sake_attr_type_vals[] = {
481 { SAKE_AT_RAND_S, "Server Nonce RAND_S" },
482 { SAKE_AT_RAND_P, "Peer Nonce RAND_P" },
483 { SAKE_AT_MIC_S, "Server MIC" },
484 { SAKE_AT_MIC_P, "Peer MIC" },
485 { SAKE_AT_SERVERID, "Server FQDN" },
486 { SAKE_AT_PEERID, "Peer NAI (tmp, perm)" },
487 { SAKE_AT_SPI_S, "Server chosen SPI SPI_S" },
488 { SAKE_AT_SPI_P, "Peer SPI list SPI_P" },
489 { SAKE_AT_ANY_ID_REQ, "Requires any Peer Id (tmp, perm)" },
490 { SAKE_AT_PERM_ID_REQ, "Requires Peer's permanent Id/NAI" },
491 { SAKE_AT_ENCR_DATA, "Contains encrypted attributes" },
492 { SAKE_AT_IV, "IV for encrypted attributes" },
493 { SAKE_AT_PADDING, "Padding for encrypted attributes" },
494 { SAKE_AT_NEXT_TMPID, "TempID for next EAP-SAKE phase" },
495 { SAKE_AT_MSK_LIFE, "MSK Lifetime" },
496 { 0, NULL }
497 };
498
499 #define GPSK_RESERVED 0
500 #define GPSK_GPSK_1 1
501 #define GPSK_GPSK_2 2
502 #define GPSK_GPSK_3 3
503 #define GPSK_GPSK_4 4
504 #define GPSK_FAIL 5
505 #define GPSK_PROTECTED_FAIL 6
506
507 static const value_string eap_gpsk_opcode_vals[] = {
508 { GPSK_RESERVED, "Reserved" },
509 { GPSK_GPSK_1, "GPSK-1" },
510 { GPSK_GPSK_2, "GPSK-2" },
511 { GPSK_GPSK_3, "GPSK-3" },
512 { GPSK_GPSK_4, "GPSK-4" },
513 { GPSK_FAIL, "Fail" },
514 { GPSK_PROTECTED_FAIL, "Protected Fail" },
515 { 0, NULL }
516 };
517
518 static const value_string eap_gpsk_failure_code_vals[] = {
519 { 0x00000000, "Reserved" },
520 { 0x00000001, "PSK Not Found" },
521 { 0x00000002, "Authentication Failure" },
522 { 0x00000003, "Authorization Failure" },
523 { 0, NULL }
524 };
525
526 /*
527 * State information for EAP-TLS (RFC2716) and Lightweight EAP:
528 *
529 * http://www.missl.cs.umd.edu/wireless/ethereal/leap.txt
530 *
531 * Attach to all conversations:
532 *
533 * a sequence number to be handed to "fragment_add_seq()" as
534 * the fragment sequence number - if it's -1, no reassembly
535 * is in progress, but if it's not, it's the sequence number
536 * to use for the current fragment;
537 *
538 * a value to be handed to "fragment_add_seq()" as the
539 * reassembly ID - when a reassembly is started, it's set to
540 * the frame number of the current frame, i.e. the frame
541 * that starts the reassembly;
542 *
543 * an indication of the current state of LEAP negotiation,
544 * with -1 meaning no LEAP negotiation is in progress.
545 *
546 * Attach to frames containing fragments of EAP-TLS messages the
547 * reassembly ID for those fragments, so we can find the reassembled
548 * data after the first pass through the packets.
549 *
550 * Attach to LEAP frames the state of the LEAP negotiation when the
551 * frame was processed, so we can properly dissect
552 * the LEAP message after the first pass through the packets.
553 *
554 * Attach to all conversations both pieces of information, to keep
555 * track of EAP-TLS reassembly and the LEAP state machine.
556 */
557
558 typedef struct {
559 int eap_tls_seq;
560 guint32 eap_reass_cookie;
561 int leap_state;
562 gint16 last_eap_id_req; /* Last ID of the request from the authenticator. */
563 gint16 last_eap_id_resp; /* Last ID of the response from the peer. */
564 } conv_state_t;
565
566 typedef struct {
567 int info; /* interpretation depends on EAP message type */
568 } frame_state_t;
569
570 /*********************************************************************
571 EAP-TLS
572 RFC2716
573 **********************************************************************/
574
575 /*
576 from RFC2716, pg 17
577
578 Flags
579
580 0 1 2 3 4 5 6 7 8
581 +-+-+-+-+-+-+-+-+
582 |L M S R R Vers |
583 +-+-+-+-+-+-+-+-+
584
585 L = Length included
586 M = More fragments
587 S = EAP-TLS start
588 R = Reserved
589 Vers = PEAP version (Reserved for TLS and TTLS)
590 */
591
592 #define EAP_TLS_FLAG_L 0x80 /* Length included */
593 #define EAP_TLS_FLAG_M 0x40 /* More fragments */
594 #define EAP_TLS_FLAG_S 0x20 /* EAP-TLS start */
595
596 #define EAP_TLS_FLAGS_VERSION 0x07 /* Version mask for PEAP, TTLS, FAST */
597
598 /*
599 * reassembly of EAP-TLS
600 */
601 static reassembly_table eap_tls_reassembly_table;
602
603 static int hf_eap_tls_flags = -1;
604 static int hf_eap_tls_flag_l = -1;
605 static int hf_eap_tls_flag_m = -1;
606 static int hf_eap_tls_flag_s = -1;
607 static int hf_eap_tls_flags_version = -1;
608 static int hf_eap_tls_len = -1;
609 static int hf_eap_tls_fragment = -1;
610 static int hf_eap_tls_fragments = -1;
611 static int hf_eap_tls_fragment_overlap = -1;
612 static int hf_eap_tls_fragment_overlap_conflict = -1;
613 static int hf_eap_tls_fragment_multiple_tails = -1;
614 static int hf_eap_tls_fragment_too_long_fragment = -1;
615 static int hf_eap_tls_fragment_error = -1;
616 static int hf_eap_tls_fragment_count = -1;
617 static int hf_eap_tls_reassembled_length = -1;
618 static int hf_eap_fast_type = -1;
619 static int hf_eap_fast_length = -1;
620 static int hf_eap_fast_aidd = -1;
621 static gint ett_eap_tls_fragment = -1;
622 static gint ett_eap_tls_fragments = -1;
623 static gint ett_eap_sim_attr = -1;
624 static gint ett_eap_aka_attr = -1;
625 static gint ett_eap_exp_attr = -1;
626 static gint ett_eap_tls_flags = -1;
627 static gint ett_identity = -1;
628
629 static const fragment_items eap_tls_frag_items = {
630 &ett_eap_tls_fragment,
631 &ett_eap_tls_fragments,
632 &hf_eap_tls_fragments,
633 &hf_eap_tls_fragment,
634 &hf_eap_tls_fragment_overlap,
635 &hf_eap_tls_fragment_overlap_conflict,
636 &hf_eap_tls_fragment_multiple_tails,
637 &hf_eap_tls_fragment_too_long_fragment,
638 &hf_eap_tls_fragment_error,
639 &hf_eap_tls_fragment_count,
640 NULL,
641 &hf_eap_tls_reassembled_length,
642 /* Reassembled data field */
643 NULL,
644 "fragments"
645 };
646
647 /**********************************************************************
648 Support for EAP Expanded Type.
649
650 Currently this is limited to WifiProtectedSetup. Maybe we need
651 a generic method to support EAP extended types ?
652 *********************************************************************/
653 static int hf_eap_ext_vendor_id = -1;
654 static int hf_eap_ext_vendor_type = -1;
655
656 static const value_string eap_ext_vendor_id_vals[] = {
657 { WFA_VENDOR_ID, "WFA" },
658 { 0, NULL }
659 };
660
661 static const value_string eap_ext_vendor_type_vals[] = {
662 { WFA_SIMPLECONFIG_TYPE, "SimpleConfig" },
663 { 0, NULL }
664 };
665
666 static void
667 dissect_exteap(proto_tree *eap_tree, tvbuff_t *tvb, int offset,
668 gint size _U_, packet_info* pinfo, guint8 eap_code, guint8 eap_identifier)
669 {
670 tvbuff_t *next_tvb;
671 guint32 vendor_id;
672 guint32 vendor_type;
673 eap_vendor_context *vendor_context;
674
675 vendor_context = wmem_new(pinfo->pool, eap_vendor_context);
676
677 proto_tree_add_item_ret_uint(eap_tree, hf_eap_ext_vendor_id, tvb, offset, 3, ENC_BIG_ENDIAN, &vendor_id);
678 offset += 3;
679
680 proto_tree_add_item_ret_uint(eap_tree, hf_eap_ext_vendor_type, tvb, offset, 4, ENC_BIG_ENDIAN, &vendor_type);
681 offset += 4;
682
683 vendor_context->eap_code = eap_code;
684 vendor_context->eap_identifier = eap_identifier;
685 vendor_context->vendor_id = vendor_id;
686 vendor_context->vendor_type = vendor_type;
687
688 next_tvb = tvb_new_subset_remaining(tvb, offset);
689 if (!dissector_try_uint_new(eap_expanded_type_dissector_table,
690 vendor_id, next_tvb, pinfo, eap_tree,
691 FALSE, vendor_context)) {
692 call_data_dissector(next_tvb, pinfo, eap_tree);
693 }
694 }
695 /* *********************************************************************
696 ********************************************************************* */
697
698 static gboolean
699 test_flag(unsigned char flag, unsigned char mask)
700 {
701 return ( ( flag & mask ) != 0 );
702 }
703
704 static void
705 dissect_eap_mschapv2(proto_tree *eap_tree, tvbuff_t *tvb, packet_info *pinfo, int offset,
706 gint size)
707 {
708 proto_item *item;
709 gint left = size;
710 gint ms_len;
711 guint8 value_size;
712 guint8 opcode;
713
714 /* OpCode (1 byte), MS-CHAPv2-ID (1 byte), MS-Length (2 bytes), Data */
715 opcode = tvb_get_guint8(tvb, offset);
716 proto_tree_add_item(eap_tree, hf_eap_ms_chap_v2_opcode, tvb, offset, 1, ENC_BIG_ENDIAN);
717 offset += 1;
718 left -= 1;
719 if (left <= 0)
720 return;
721
722 proto_tree_add_item(eap_tree, hf_eap_ms_chap_v2_id, tvb, offset, 1, ENC_BIG_ENDIAN);
723 offset += 1;
724 left -= 1;
725 if (left <= 0)
726 return;
727
728 item = proto_tree_add_item(eap_tree, hf_eap_ms_chap_v2_length, tvb, offset, 2, ENC_BIG_ENDIAN);
729 ms_len = tvb_get_ntohs(tvb, offset);
730 if (ms_len != size)
731 expert_add_info(pinfo, item, &ei_eap_ms_chap_v2_length);
732 offset += 2;
733 left -= 2;
734
735 switch (opcode) {
736 case MS_CHAP_V2_CHALLENGE:
737 if (left <= 0)
738 break;
739 value_size = tvb_get_guint8(tvb, offset);
740 proto_tree_add_item(eap_tree, hf_eap_ms_chap_v2_value_size,
741 tvb, offset, 1, ENC_BIG_ENDIAN);
742 offset += 1;
743 left -= 1;
744 proto_tree_add_item(eap_tree, hf_eap_ms_chap_v2_challenge,
745 tvb, offset, value_size, ENC_NA);
746 offset += value_size;
747 left -= value_size;
748 if (left <= 0)
749 break;
750 proto_tree_add_item(eap_tree, hf_eap_ms_chap_v2_name,
751 tvb, offset, left, ENC_ASCII|ENC_NA);
752 break;
753 case MS_CHAP_V2_RESPONSE:
754 if (left <= 0)
755 break;
756 value_size = tvb_get_guint8(tvb, offset);
757 proto_tree_add_item(eap_tree, hf_eap_ms_chap_v2_value_size,
758 tvb, offset, 1, ENC_BIG_ENDIAN);
759 offset += 1;
760 left -= 1;
761 if (value_size == 49) {
762 proto_tree_add_item(eap_tree, hf_eap_ms_chap_v2_peer_challenge,
763 tvb, offset, 16, ENC_NA);
764 offset += 16;
765 proto_tree_add_item(eap_tree, hf_eap_ms_chap_v2_reserved,
766 tvb, offset, 8, ENC_NA);
767 offset += 8;
768 proto_tree_add_item(eap_tree, hf_eap_ms_chap_v2_nt_response,
769 tvb, offset, 24, ENC_NA);
770 offset += 24;
771 proto_tree_add_item(eap_tree, hf_eap_ms_chap_v2_flags,
772 tvb, offset, 1, ENC_BIG_ENDIAN);
773 offset += 1;
774 left -= value_size;
775 } else {
776 proto_tree_add_item(eap_tree, hf_eap_ms_chap_v2_response, tvb, offset, value_size, ENC_NA);
777 offset += value_size;
778 left -= value_size;
779 }
780 if (left <= 0)
781 break;
782 proto_tree_add_item(eap_tree, hf_eap_ms_chap_v2_name, tvb, offset, left, ENC_ASCII|ENC_NA);
783 break;
784 case MS_CHAP_V2_SUCCESS:
785 if (left <= 0)
786 break;
787 proto_tree_add_item(eap_tree, hf_eap_ms_chap_v2_message,
788 tvb, offset, left, ENC_ASCII|ENC_NA);
789 break;
790 case MS_CHAP_V2_FAILURE:
791 if (left <= 0)
792 break;
793 proto_tree_add_item(eap_tree, hf_eap_ms_chap_v2_failure_request,
794 tvb, offset, left, ENC_ASCII|ENC_NA);
795 break;
796 default:
797 proto_tree_add_item(eap_tree, hf_eap_ms_chap_v2_data, tvb, offset, left, ENC_NA);
798 break;
799 }
800 }
801
802 /* Dissect the WLAN identity */
803 static gboolean
804 dissect_eap_identity_wlan(tvbuff_t *tvb, packet_info* pinfo, proto_tree* tree, int offset, gint size)
805 {
806 guint mnc = 0;
807 guint mcc = 0;
808 guint mcc_mnc = 0;
809 proto_tree* eap_identity_tree = NULL;
810 guint8 eap_identity_prefix = 0;
811 const gchar* eap_identity_value;
812 guint8* identity = NULL;
813 gchar** tokens = NULL;
814 gchar** realm_tokens = NULL;
815 guint ntokens = 0;
816 guint nrealm_tokens = 0;
817 gboolean ret = TRUE;
818 int hf_eap_identity_mcc_mnc;
819 proto_item* item;
820
821 identity = tvb_get_string_enc(pinfo->pool, tvb, offset, size, ENC_ASCII);
822
823 /* Split the Identity and the NAI Realm first */
824 tokens = g_strsplit_set(identity, "@", -1);
825
826 while(tokens[ntokens])
827 ntokens++;
828
829 /* tokens[0] is the identity, tokens[1] is the NAI Realm */
830 if (ntokens != 2) {
831 ret = FALSE;
832 proto_tree_add_item(tree, hf_eap_identity, tvb, offset, size, ENC_ASCII|ENC_NA);
833 goto end;
834 }
835
836 realm_tokens = g_strsplit_set(tokens[1], ".", -1);
837
838 while(realm_tokens[nrealm_tokens])
839 nrealm_tokens++;
840
841 /* The WLAN identity must have the form of
842 <imsi>@wlan.mnc<mnc>.mcc<mcc>.3gppnetwork.org
843 If not, we don't have a wlan identity
844 */
845 if (ntokens != 2 || nrealm_tokens != 5 || g_ascii_strncasecmp(realm_tokens[0], "wlan", 4) ||
846 g_ascii_strncasecmp(realm_tokens[3], "3gppnetwork", 11) ||
847 g_ascii_strncasecmp(realm_tokens[4], "org", 3)) {
848 ret = FALSE;
849 goto end;
850 }
851
852 /* It is very likely that we have a WLAN identity (EAP-AKA/EAP-SIM) */
853 /* Go on with the dissection */
854 eap_identity_tree = proto_item_add_subtree(tree, ett_identity);
855 proto_tree_add_item(eap_identity_tree, hf_eap_identity_prefix, tvb, offset, 1, ENC_NA);
856 eap_identity_prefix = tvb_get_guint8(tvb, offset);
857 eap_identity_value = try_val_to_str(eap_identity_prefix, eap_identity_prefix_vals);
858 item = proto_tree_add_string(eap_identity_tree, hf_eap_identity_type,
859 tvb, offset, 1, eap_identity_value ? eap_identity_value : "Unknown");
860
861 switch(eap_identity_prefix) {
862 case 0x00: /* Encrypted IMSI */
863 proto_tree_add_item(eap_identity_tree, hf_eap_identity_full, tvb, offset + 1, size - 1, ENC_ASCII || ENC_NA);
864 proto_tree_add_item(eap_identity_tree, hf_eap_identity, tvb, offset + 1, (guint)strlen(tokens[0]), ENC_ASCII || ENC_NA);
865 break;
866 case '0': /* EAP-AKA Permanent */
867 case '1': /* EAP-SIM Permanent */
868 case '6': /* EAP-AKA' Permanent */
869 proto_tree_add_item(eap_identity_tree, hf_eap_identity_full, tvb, offset + 1, size - 1, ENC_ASCII || ENC_NA);
870 dissect_e212_utf8_imsi(tvb, pinfo, eap_identity_tree, offset + 1, (guint)strlen(tokens[0]) - 1);
871 break;
872 case '2': /* EAP-AKA Pseudonym */
873 case '3': /* EAP-SIM Pseudonym */
874 case '7': /* EAP-AKA' Pseudonym */
875 proto_tree_add_item(eap_identity_tree, hf_eap_identity_full, tvb, offset + 1, size - 1, ENC_ASCII || ENC_NA);
876 proto_tree_add_item(eap_identity_tree, hf_eap_identity, tvb, offset + 1, (guint)strlen(tokens[0]) - 1, ENC_ASCII|ENC_NA);
877 break;
878 case '4': /* EAP-AKA Reauth ID */
879 case '5': /* EAP-SIM Reauth ID */
880 case '8': /* EAP-AKA' Reauth ID */
881 proto_tree_add_item(eap_identity_tree, hf_eap_identity_full, tvb, offset + 1, size - 1, ENC_ASCII || ENC_NA);
882 proto_tree_add_item(eap_identity_tree, hf_eap_identity, tvb, offset + 1, (guint)strlen(tokens[0]) - 1, ENC_ASCII|ENC_NA);
883 break;
884 case 'C': /* Conservative Peer */
885 proto_tree_add_item(eap_identity_tree, hf_eap_identity_full, tvb, offset + 1, size - 1, ENC_ASCII || ENC_NA);
886 proto_tree_add_item(eap_identity_tree, hf_eap_identity, tvb, offset + 1, (guint)strlen(tokens[0]) - 1, ENC_ASCII|ENC_NA);
887 break;
888 case 'a': /* Anonymous User */
889 proto_tree_add_item(eap_identity_tree, hf_eap_identity_full, tvb, offset, size, ENC_ASCII || ENC_NA);
890 proto_tree_add_item(eap_identity_tree, hf_eap_identity, tvb, offset, (guint)strlen(tokens[0]), ENC_ASCII|ENC_NA);
891 break;
892 case 'G': /* TODO: 'G' Unknown */
893 case 'I': /* TODO: 'I' Unknown */
894 default:
895 proto_tree_add_item(eap_identity_tree, hf_eap_identity_full, tvb, offset + 1, size - 1, ENC_ASCII || ENC_NA);
896 proto_tree_add_item(eap_identity_tree, hf_eap_identity, tvb, offset + 1, (guint)strlen(tokens[0]) - 1, ENC_ASCII|ENC_NA);
897 expert_add_info(pinfo, item, &ei_eap_identity_invalid);
898 }
899
900 /* EAP identities do not always equate to IMSIs. We should
901 * still add the MCC and MNC values for non-permanent EAP
902 * identities. */
903 if (!sscanf(realm_tokens[1] + 3, "%u", &mnc) || !sscanf(realm_tokens[2] + 3, "%u", &mcc)) {
904 ret = FALSE;
905 goto end;
906 }
907
908 if (!try_val_to_str_ext(mcc * 100 + mnc, &mcc_mnc_2digits_codes_ext)) {
909 /* May have
910 * (1) an invalid 2-digit MNC so it won't resolve,
911 * (2) an invalid 3-digit MNC so it won't resolve, or
912 * (3) a valid 3-digit MNC.
913 * For all cases we treat as 3-digit MNC and continue. */
914 mcc_mnc = 1000 * mcc + mnc;
915 hf_eap_identity_mcc_mnc = hf_eap_identity_mcc_mnc_3digits;
916 } else {
917 /* We got a 2-digit MNC match */
918 mcc_mnc = 100 * mcc + mnc;
919 hf_eap_identity_mcc_mnc = hf_eap_identity_mcc_mnc_2digits;
920 }
921
922 proto_tree_add_uint(eap_identity_tree, hf_eap_identity_mcc_mnc,
923 tvb, offset + (guint)strlen(tokens[0]) + (guint)strlen("@wlan.") +
924 (guint)strlen("mnc"), (guint)strlen(realm_tokens[1]) - (guint)strlen("mnc"),
925 mcc_mnc);
926
927 proto_tree_add_uint(eap_identity_tree, hf_eap_identity_mcc,
928 tvb, offset + (guint)(strlen(tokens[0]) + strlen("@wlan.") +
929 strlen(realm_tokens[1]) + 1 + strlen("mcc")),
930 (guint)(strlen(realm_tokens[2]) - strlen("mcc")), mcc);
931 end:
932 g_strfreev(tokens);
933 g_strfreev(realm_tokens);
934
935 return ret;
936 }
937
938 static void
939 dissect_eap_identity(tvbuff_t *tvb, packet_info* pinfo, proto_tree* tree, int offset, gint size)
940 {
941 /* Try to dissect as WLAN identity */
942 if (dissect_eap_identity_wlan(tvb, pinfo, tree, offset, size))
943 return;
944 }
945
946 static void
947 dissect_eap_sim(proto_tree *eap_tree, tvbuff_t *tvb, packet_info* pinfo, int offset, gint size)
948 {
949 gint left = size;
950
951 proto_tree_add_item(eap_tree, hf_eap_sim_subtype, tvb, offset, 1, ENC_BIG_ENDIAN);
952
953 offset += 1;
954 left -= 1;
955
956 if (left < 2)
957 return;
958 proto_tree_add_item(eap_tree, hf_eap_sim_reserved, tvb, offset, 2, ENC_BIG_ENDIAN);
959 offset += 2;
960 left -= 2;
961
962 /* Rest of EAP-SIM data is in Type-Len-Value format. */
963 while (left >= 2) {
964 guint8 type, length;
965 gint padding;
966 proto_item *pi;
967 proto_tree *attr_tree;
968 int aoffset;
969 gint aleft;
970
971 aoffset = offset;
972 type = tvb_get_guint8(tvb, aoffset);
973 length = tvb_get_guint8(tvb, aoffset + 1);
974 aleft = 4 * length;
975
976 pi = proto_tree_add_none_format(eap_tree, hf_eap_sim_subtype_attribute, tvb,
977 aoffset, aleft, "EAP-SIM Attribute: %s (%d)",
978 val_to_str_ext_const(type,
979 &eap_sim_aka_attribute_vals_ext,
980 "Unknown"),
981 type);
982 attr_tree = proto_item_add_subtree(pi, ett_eap_sim_attr);
983 proto_tree_add_uint(attr_tree, hf_eap_sim_subtype_type, tvb, aoffset, 1, type);
984 aoffset += 1;
985 aleft -= 1;
986
987 if (aleft <= 0)
988 break;
989 proto_tree_add_item(attr_tree, hf_eap_sim_subtype_length, tvb, aoffset, 1, ENC_BIG_ENDIAN);
990 aoffset += 1;
991 aleft -= 1;
992
993 switch(type){
994 case AT_IDENTITY:
995 proto_tree_add_item(attr_tree, hf_eap_identity_actual_len, tvb, aoffset, 2, ENC_BIG_ENDIAN);
996 dissect_eap_identity(tvb, pinfo, attr_tree, aoffset + 2, tvb_get_ntohs(tvb, aoffset));
997 /* If we have a disparity between the EAP-SIM length (minus the
998 * first 4 bytes of header fields) * 4 and the Identity Actual
999 * Length then it's padding and we need to adjust for that
1000 * accurately before looking at the next EAP-SIM attribute. */
1001 padding = ((length - 1) * 4) - tvb_get_ntohs(tvb, aoffset);
1002 if (padding != 0) {
1003 proto_tree_add_item(attr_tree, hf_eap_identity_padding, tvb,
1004 aoffset + 2 + tvb_get_ntohs(tvb, aoffset), padding, ENC_NA);
1005 }
1006 break;
1007 case AT_NOTIFICATION:
1008 proto_tree_add_item(attr_tree, hf_eap_sim_notification_type, tvb, aoffset, 2, ENC_BIG_ENDIAN);
1009 break;
1010 case AT_CLIENT_ERROR_CODE:
1011 proto_tree_add_item(attr_tree, hf_eap_sim_error_code_type, tvb, aoffset, 2, ENC_BIG_ENDIAN);
1012 break;
1013 default:
1014 proto_tree_add_item(attr_tree, hf_eap_sim_subtype_value, tvb, aoffset, aleft, ENC_NA);
1015 }
1016
1017 offset += 4 * length;
1018 left -= 4 * length;
1019 }
1020 }
1021
1022 static void
1023 dissect_eap_aka(proto_tree *eap_tree, tvbuff_t *tvb, packet_info* pinfo, int offset, gint size)
1024 {
1025 gint left = size;
1026
1027 proto_tree_add_item(eap_tree, hf_eap_aka_subtype, tvb, offset, 1, ENC_BIG_ENDIAN);
1028
1029 offset += 1;
1030 left -= 1;
1031
1032 if (left < 2)
1033 return;
1034 proto_tree_add_item(eap_tree, hf_eap_aka_reserved, tvb, offset, 2, ENC_BIG_ENDIAN);
1035 offset += 2;
1036 left -= 2;
1037
1038 /* Rest of EAP-AKA data is in Type-Len-Value format. */
1039 while (left >= 2) {
1040 guint8 type, length;
1041 gint padding;
1042 proto_item *pi;
1043 proto_tree *attr_tree;
1044 int aoffset;
1045 gint aleft;
1046
1047 aoffset = offset;
1048 type = tvb_get_guint8(tvb, aoffset);
1049 length = tvb_get_guint8(tvb, aoffset + 1);
1050 aleft = 4 * length;
1051
1052 pi = proto_tree_add_none_format(eap_tree, hf_eap_aka_subtype_attribute, tvb,
1053 aoffset, aleft, "EAP-AKA Attribute: %s (%d)",
1054 val_to_str_ext_const(type,
1055 &eap_sim_aka_attribute_vals_ext,
1056 "Unknown"),
1057 type);
1058 attr_tree = proto_item_add_subtree(pi, ett_eap_aka_attr);
1059 proto_tree_add_uint(attr_tree, hf_eap_aka_subtype_type, tvb, aoffset, 1, type);
1060 aoffset += 1;
1061 aleft -= 1;
1062
1063 if (aleft <= 0)
1064 break;
1065 proto_tree_add_item(attr_tree, hf_eap_aka_subtype_length, tvb, aoffset, 1, ENC_BIG_ENDIAN);
1066 aoffset += 1;
1067 aleft -= 1;
1068
1069 switch(type){
1070 case AT_IDENTITY:
1071 proto_tree_add_item(attr_tree, hf_eap_identity_actual_len, tvb, aoffset, 2, ENC_BIG_ENDIAN);
1072 dissect_eap_identity(tvb, pinfo, attr_tree, aoffset + 2, tvb_get_ntohs(tvb, aoffset));
1073 /* If we have a disparity between the EAP-AKA length (minus the
1074 * first 4 bytes of header fields) * 4 and the Identity Actual
1075 * Length then it's padding and we need to adjust for that
1076 * accurately before looking at the next EAP-AKA attribute. */
1077 padding = ((length - 1) * 4) - tvb_get_ntohs(tvb, aoffset);
1078 if (padding != 0) {
1079 proto_tree_add_item(attr_tree, hf_eap_identity_padding, tvb,
1080 aoffset + 2 + tvb_get_ntohs(tvb, aoffset), padding, ENC_NA);
1081 }
1082 break;
1083 case AT_NOTIFICATION:
1084 proto_tree_add_item(attr_tree, hf_eap_aka_notification_type, tvb, aoffset, 2, ENC_BIG_ENDIAN);
1085 break;
1086 case AT_CLIENT_ERROR_CODE:
1087 proto_tree_add_item(attr_tree, hf_eap_aka_error_code_type, tvb, aoffset, 2, ENC_BIG_ENDIAN);
1088 break;
1089 default:
1090 proto_tree_add_item(attr_tree, hf_eap_aka_subtype_value, tvb, aoffset, aleft, ENC_NA);
1091 }
1092
1093 offset += 4 * length;
1094 left -= 4 * length;
1095 }
1096 }
1097
1098 static int
1099 dissect_eap_pax(proto_tree *eap_tree, tvbuff_t *tvb, packet_info *pinfo, int offset, gint size)
1100 {
1101 static int * const pax_flags[] = {
1102 &hf_eap_pax_flags_mf,
1103 &hf_eap_pax_flags_ce,
1104 &hf_eap_pax_flags_ai,
1105 &hf_eap_pax_flags_reserved,
1106 NULL
1107 };
1108 guint32 opcode;
1109 guint64 flags;
1110 guint32 len;
1111
1112 proto_tree_add_item_ret_uint(eap_tree, hf_eap_pax_opcode, tvb, offset, 1, ENC_NA, &opcode);
1113 offset++;
1114
1115 col_append_fstr(pinfo->cinfo, COL_INFO, " %s",
1116 val_to_str(opcode, eap_pax_opcode_vals, "Unknown opcode (0x%02X)"));
1117
1118 proto_tree_add_bitmask_ret_uint64(eap_tree, tvb, offset, hf_eap_pax_flags, ett_eap_pax_flags,
1119 pax_flags, ENC_BIG_ENDIAN, &flags);
1120 offset++;
1121
1122 proto_tree_add_item(eap_tree, hf_eap_pax_mac_id, tvb, offset, 1, ENC_NA);
1123 offset++;
1124
1125 proto_tree_add_item(eap_tree, hf_eap_pax_dh_group_id, tvb, offset, 1, ENC_NA);
1126 offset++;
1127
1128 proto_tree_add_item(eap_tree, hf_eap_pax_public_key_id, tvb, offset, 1, ENC_NA);
1129 offset++;
1130
1131 switch (opcode) {
1132 case PAX_STD_1:
1133 proto_tree_add_item_ret_uint(eap_tree, hf_eap_pax_a_len, tvb, offset, 2, ENC_BIG_ENDIAN, &len);
1134 offset += 2;
1135 proto_tree_add_item(eap_tree, hf_eap_pax_a, tvb, offset, len, ENC_NA);
1136 offset += len;
1137 len = 5 + size - offset;
1138 proto_tree_add_item(eap_tree, hf_eap_pax_mac_icv, tvb, offset, len, ENC_NA);
1139 offset += len;
1140 break;
1141 case PAX_STD_2:
1142 proto_tree_add_item_ret_uint(eap_tree, hf_eap_pax_b_len, tvb, offset, 2, ENC_BIG_ENDIAN, &len);
1143 offset += 2;
1144 proto_tree_add_item(eap_tree, hf_eap_pax_b, tvb, offset, len, ENC_NA);
1145 offset += len;
1146 proto_tree_add_item_ret_uint(eap_tree, hf_eap_pax_cid_len, tvb, offset, 2, ENC_BIG_ENDIAN, &len);
1147 offset += 2;
1148 proto_tree_add_item(eap_tree, hf_eap_pax_cid, tvb, offset, len, ENC_ASCII | ENC_NA);
1149 offset += len;
1150 proto_tree_add_item_ret_uint(eap_tree, hf_eap_pax_mac_ck_len, tvb, offset, 2, ENC_BIG_ENDIAN, &len);
1151 offset += 2;
1152 proto_tree_add_item(eap_tree, hf_eap_pax_mac_ck, tvb, offset, len, ENC_NA);
1153 offset += len;
1154 if (flags & EAP_PAX_FLAG_AI) {
1155 proto_tree_add_item_ret_uint(eap_tree, hf_eap_pax_ade_len, tvb, offset, 2, ENC_BIG_ENDIAN, &len);
1156 offset += 2;
1157 proto_tree_add_item(eap_tree, hf_eap_pax_ade, tvb, offset, len, ENC_NA);
1158 offset += len;
1159 }
1160 len = 5 + size - offset;
1161 proto_tree_add_item(eap_tree, hf_eap_pax_mac_icv, tvb, offset, len, ENC_NA);
1162 offset += len;
1163 break;
1164 case PAX_STD_3:
1165 proto_tree_add_item_ret_uint(eap_tree, hf_eap_pax_mac_ck_len, tvb, offset, 2, ENC_BIG_ENDIAN, &len);
1166 offset += 2;
1167 proto_tree_add_item(eap_tree, hf_eap_pax_mac_ck, tvb, offset, len, ENC_NA);
1168 offset += len;
1169 if (flags & EAP_PAX_FLAG_AI) {
1170 proto_tree_add_item_ret_uint(eap_tree, hf_eap_pax_ade_len, tvb, offset, 2, ENC_BIG_ENDIAN, &len);
1171 offset += 2;
1172 proto_tree_add_item(eap_tree, hf_eap_pax_ade, tvb, offset, len, ENC_NA);
1173 offset += len;
1174 }
1175 len = 5 + size - offset;
1176 proto_tree_add_item(eap_tree, hf_eap_pax_mac_icv, tvb, offset, len, ENC_NA);
1177 offset += len;
1178 break;
1179 case PAX_ACK:
1180 if (flags & EAP_PAX_FLAG_AI) {
1181 proto_tree_add_item_ret_uint(eap_tree, hf_eap_pax_ade_len, tvb, offset, 2, ENC_BIG_ENDIAN, &len);
1182 offset += 2;
1183 proto_tree_add_item(eap_tree, hf_eap_pax_ade, tvb, offset, len, ENC_NA);
1184 offset += len;
1185 }
1186 len = 5 + size - offset;
1187 proto_tree_add_item(eap_tree, hf_eap_pax_mac_icv, tvb, offset, len, ENC_NA);
1188 offset += len;
1189 break;
1190 case PAX_SEC_1:
1191 case PAX_SEC_2:
1192 case PAX_SEC_3:
1193 case PAX_SEC_4:
1194 case PAX_SEC_5:
1195 /* TODO implement */
1196 default:
1197 break;
1198 }
1199
1200 return offset;
1201 }
1202
1203 static int
1204 dissect_eap_psk_pchannel(proto_tree *eap_tree, tvbuff_t *tvb, int offset, gint size)
1205 {
1206 /* The protected channel (PCHANNEL) content is encrypted so for now just present
1207 * it as a binary blob */
1208 proto_tree_add_item(eap_tree, hf_eap_psk_pchannel, tvb, offset, size, ENC_NA);
1209 offset += size;
1210 return offset;
e1ap_MaxPacketLossRate_fmt(gchar * s,guint32 v)1211 }
1212
1213 static int
1214 dissect_eap_psk(proto_tree *eap_tree, tvbuff_t *tvb, packet_info *pinfo, int offset, gint size)
1215 {
1216 static int * const psk_flags[] = {
1217 &hf_eap_psk_flags_t,
1218 &hf_eap_psk_flags_reserved,
1219 NULL
1220 };
1221 guint64 flags;
1222
1223 proto_tree_add_bitmask_ret_uint64(eap_tree, tvb, offset, hf_eap_psk_flags, ett_eap_psk_flags,
1224 psk_flags, ENC_NA, &flags);
1225 offset++;
1226
1227 switch (flags & EAP_PSK_FLAGS_T_MASK) {
1228 case 0x00: /* T == 0 - EAP-PSK First Message */
1229 col_append_str(pinfo->cinfo, COL_INFO, " First Message");
1230 proto_tree_add_item(eap_tree, hf_eap_psk_rand_s, tvb, offset, 16, ENC_NA);
1231 offset += 16;
1232 proto_tree_add_item(eap_tree, hf_eap_psk_id_s, tvb, offset, size + 5 - offset, ENC_ASCII | ENC_NA);
1233 offset = size;
1234 break;
1235 case 0x40: /* T == 1 - EAP-PSK Second Message */
1236 col_append_str(pinfo->cinfo, COL_INFO, " Second Message");
1237 proto_tree_add_item(eap_tree, hf_eap_psk_rand_s, tvb, offset, 16, ENC_NA);
1238 offset += 16;
1239 proto_tree_add_item(eap_tree, hf_eap_psk_rand_p, tvb, offset, 16, ENC_NA);
1240 offset += 16;
1241 proto_tree_add_item(eap_tree, hf_eap_psk_mac_p, tvb, offset, 16, ENC_NA);
1242 offset += 16;
1243 proto_tree_add_item(eap_tree, hf_eap_psk_id_p, tvb, offset, size + 5 - offset, ENC_ASCII | ENC_NA);
1244 offset = size;
1245 break;
1246 case 0x80: /* T == 2 - EAP-PSK Third Message */
1247 col_append_str(pinfo->cinfo, COL_INFO, " Third Message");
1248 proto_tree_add_item(eap_tree, hf_eap_psk_rand_s, tvb, offset, 16, ENC_NA);
1249 offset += 16;
1250 proto_tree_add_item(eap_tree, hf_eap_psk_mac_s, tvb, offset, 16, ENC_NA);
1251 offset += 16;
1252 offset = dissect_eap_psk_pchannel(eap_tree, tvb, offset, size + 5 - offset);
1253 break;
1254 case 0xC0: /* T == 3 - EAP-PSK Fourth Message */
1255 col_append_str(pinfo->cinfo, COL_INFO, " Fourth Message");
1256 proto_tree_add_item(eap_tree, hf_eap_psk_rand_s, tvb, offset, 16, ENC_NA);
1257 offset += 16;
1258 offset = dissect_eap_psk_pchannel(eap_tree, tvb, offset, size + 5 - offset);
1259 break;
1260 default:
1261 break;
1262 }
1263
1264 return offset;
1265 }
1266
1267 static gint
1268 dissect_eap_gpsk_csuite_sel(proto_tree *eap_tree, tvbuff_t *tvb, int offset)
1269 {
1270 proto_tree *csuite_tree;
1271 csuite_tree = proto_tree_add_subtree(eap_tree, tvb, offset, 6, ett_eap_gpsk_csuite_sel,
dissect_e1ap_T_global(tvbuff_t * tvb _U_,int offset _U_,asn1_ctx_t * actx _U_,proto_tree * tree _U_,int hf_index _U_)1272 NULL, "EAP-GPSK CSuite_Sel");
1273 proto_tree_add_item(csuite_tree, hf_eap_gpsk_csuite_vendor, tvb, offset, 4, ENC_BIG_ENDIAN);
1274 offset += 4;
1275 proto_tree_add_item(csuite_tree, hf_eap_gpsk_csuite_specifier, tvb, offset, 2, ENC_BIG_ENDIAN);
1276 offset += 2;
1277 return offset;
1278 }
1279
1280 static gint
1281 dissect_eap_gpsk_csuite_list(proto_tree *eap_tree, tvbuff_t *tvb, int offset)
1282 {
1283 gint start_offset = offset;
1284 guint16 len;
1285 proto_tree *list_tree, *csuite_tree;
1286
1287 len = tvb_get_ntohs(tvb, offset) + 2;
1288 list_tree = proto_tree_add_subtree(eap_tree, tvb, offset, len, ett_eap_gpsk_csuite_list,
1289 NULL, "EAP-GPSK CSuite List");
1290 proto_tree_add_item(list_tree, hf_eap_gpsk_csuite_list_len, tvb, offset, 2, ENC_BIG_ENDIAN);
1291 offset += 2;
1292
1293 while (offset < start_offset + len) {
1294 csuite_tree = proto_tree_add_subtree(list_tree, tvb, offset, 6, ett_eap_gpsk_csuite,
1295 NULL, "CSuite");
1296 proto_tree_add_item(csuite_tree, hf_eap_gpsk_csuite_vendor, tvb, offset, 4, ENC_BIG_ENDIAN);
dissect_e1ap_PrivateIE_ID(tvbuff_t * tvb _U_,int offset _U_,asn1_ctx_t * actx _U_,proto_tree * tree _U_,int hf_index _U_)1297 offset += 4;
1298 proto_tree_add_item(csuite_tree, hf_eap_gpsk_csuite_specifier, tvb, offset, 2, ENC_BIG_ENDIAN);
1299 offset += 2;
1300 }
1301 return offset;
1302 }
1303
1304 static gint
1305 dissect_eap_sake_attribute(proto_tree *eap_tree, tvbuff_t *tvb, int offset, gint size)
1306 {
1307 gint start_offset = offset;
1308 guint8 type;
1309 guint8 len;
1310 proto_tree *attr_tree;
1311
1312 type = tvb_get_guint8(tvb, offset);
1313 len = tvb_get_guint8(tvb, offset + 1);
1314
1315 if (len < 2 || len > size) {
1316 return -1;
1317 }
1318 attr_tree = proto_tree_add_subtree_format(eap_tree, tvb, offset, len, ett_eap_sake_attr, NULL,
1319 "EAP-SAKE Attribute: %s",
1320 val_to_str(type, eap_sake_attr_type_vals,
1321 "Unknown (%d)"));
1322
1323 proto_tree_add_item(attr_tree, hf_eap_sake_attr_type, tvb, offset, 1, ENC_NA);
1324 offset++;
1325 proto_tree_add_item(attr_tree, hf_eap_sake_attr_len, tvb, offset, 1, ENC_NA);
1326 offset++;
1327 len -= 2;
1328
1329 switch (type) {
1330 case SAKE_AT_SERVERID:
1331 case SAKE_AT_PEERID:
1332 proto_tree_add_item(attr_tree, hf_eap_sake_attr_value_str, tvb, offset, len, ENC_ASCII | ENC_NA);
1333 offset += len;
1334 break;
1335 case SAKE_AT_MSK_LIFE:
1336 proto_tree_add_item(attr_tree, hf_eap_sake_attr_value_uint48, tvb, offset, len,
1337 ENC_BIG_ENDIAN);
1338 offset += len;
1339 break;
1340 case SAKE_AT_RAND_S:
1341 case SAKE_AT_RAND_P:
1342 case SAKE_AT_MIC_S:
1343 case SAKE_AT_MIC_P:
1344 case SAKE_AT_SPI_S:
1345 case SAKE_AT_SPI_P:
1346 case SAKE_AT_ANY_ID_REQ:
dissect_e1ap_ProcedureCode(tvbuff_t * tvb _U_,int offset _U_,asn1_ctx_t * actx _U_,proto_tree * tree _U_,int hf_index _U_)1347 case SAKE_AT_PERM_ID_REQ:
1348 case SAKE_AT_ENCR_DATA:
1349 case SAKE_AT_IV:
1350 case SAKE_AT_PADDING:
1351 case SAKE_AT_NEXT_TMPID:
1352 default:
1353 proto_tree_add_item(attr_tree, hf_eap_sake_attr_value, tvb, offset, len, ENC_NA);
1354 offset += len;
1355 break;
1356 }
1357 return offset - start_offset;
1358 }
1359
1360 static void
1361 dissect_eap_sake_attributes(proto_tree *eap_tree, tvbuff_t *tvb, int offset, gint size)
1362 {
1363 gint attr_size;
1364 while (offset < size) {
1365 attr_size = dissect_eap_sake_attribute(eap_tree, tvb, offset, size);
1366 if (attr_size == -1) {
1367 break;
1368 }
1369 offset += attr_size;
1370 }
1371 }
1372
1373 static void
1374 dissect_eap_sake(proto_tree *eap_tree, tvbuff_t *tvb, packet_info *pinfo _U_, int offset, gint size)
1375 {
1376 guint32 version;
1377 guint32 subtype;
1378
1379 proto_tree_add_item_ret_uint(eap_tree, hf_eap_sake_version, tvb, offset, 1, ENC_NA, &version);
1380 offset++;
1381 if (version != 2) {
1382 /* RFC 4763 specify version 2. Everything else is unsupported */
1383 return;
1384 }
1385 proto_tree_add_item(eap_tree, hf_eap_sake_session_id, tvb, offset, 1, ENC_NA);
1386 offset++;
1387 proto_tree_add_item_ret_uint(eap_tree, hf_eap_sake_subtype, tvb, offset, 1, ENC_NA, &subtype);
1388 offset++;
1389
1390 switch (subtype) {
1391 case SAKE_CHALLENGE:
1392 case SAKE_CONFIRM:
1393 case SAKE_AUTH_REJECT:
1394 case SAKE_IDENTITY:
1395 dissect_eap_sake_attributes(eap_tree, tvb, offset, size + 5 - offset);
1396 break;
1397 default:
1398 break;
1399 }
1400 }
1401
1402 static int
1403 dissect_eap_gpsk(proto_tree *eap_tree, tvbuff_t *tvb, packet_info *pinfo, int offset, gint size)
1404 {
1405 guint32 opcode;
1406 guint32 len;
1407
1408 proto_tree_add_item_ret_uint(eap_tree, hf_eap_gpsk_opcode, tvb, offset, 1, ENC_NA, &opcode);
1409 offset++;
1410 col_append_fstr(pinfo->cinfo, COL_INFO, " %s",
1411 val_to_str(opcode, eap_gpsk_opcode_vals, "Unknown opcode (0x%02X)"));
1412
1413 switch (opcode) {
1414 case GPSK_GPSK_1:
1415 proto_tree_add_item_ret_uint(eap_tree, hf_eap_gpsk_id_server_len, tvb, offset, 2, ENC_BIG_ENDIAN, &len);
1416 offset += 2;
1417 proto_tree_add_item(eap_tree, hf_eap_gpsk_id_server, tvb, offset, len, ENC_ASCII | ENC_NA);
1418 offset += len;
1419 proto_tree_add_item(eap_tree, hf_eap_gpsk_rand_server, tvb, offset, 32, ENC_NA);
1420 offset += 32;
1421 offset = dissect_eap_gpsk_csuite_list(eap_tree, tvb, offset);
1422 break;
1423 case GPSK_GPSK_2:
1424 proto_tree_add_item_ret_uint(eap_tree, hf_eap_gpsk_id_peer_len, tvb, offset, 2, ENC_BIG_ENDIAN, &len);
1425 offset += 2;
1426 proto_tree_add_item(eap_tree, hf_eap_gpsk_id_peer, tvb, offset, len, ENC_ASCII | ENC_NA);
1427 offset += len;
1428 proto_tree_add_item_ret_uint(eap_tree, hf_eap_gpsk_id_server_len, tvb, offset, 2, ENC_BIG_ENDIAN, &len);
1429 offset += 2;
1430 proto_tree_add_item(eap_tree, hf_eap_gpsk_id_server, tvb, offset, len, ENC_ASCII | ENC_NA);
1431 offset += len;
1432 proto_tree_add_item(eap_tree, hf_eap_gpsk_rand_peer, tvb, offset, 32, ENC_NA);
1433 offset += 32;
1434 proto_tree_add_item(eap_tree, hf_eap_gpsk_rand_server, tvb, offset, 32, ENC_NA);
1435 offset += 32;
1436 offset = dissect_eap_gpsk_csuite_list(eap_tree, tvb, offset);
1437 offset = dissect_eap_gpsk_csuite_sel(eap_tree, tvb, offset);
1438 proto_tree_add_item_ret_uint(eap_tree, hf_eap_gpsk_pd_payload_len, tvb, offset, 2, ENC_BIG_ENDIAN, &len);
1439 offset += 2;
1440 if (len > 0) {
1441 proto_tree_add_item(eap_tree, hf_eap_gpsk_pd_payload, tvb, offset, len, ENC_NA);
1442 offset += len;
1443 }
1444 len = size + 5 - offset;
1445 proto_tree_add_item(eap_tree, hf_eap_gpsk_payload_mac, tvb, offset, len, ENC_NA);
1446 offset += len;
1447 break;
1448 case GPSK_GPSK_3:
1449 proto_tree_add_item(eap_tree, hf_eap_gpsk_rand_peer, tvb, offset, 32, ENC_NA);
1450 offset += 32;
1451 proto_tree_add_item(eap_tree, hf_eap_gpsk_rand_server, tvb, offset, 32, ENC_NA);
1452 offset += 32;
1453 proto_tree_add_item_ret_uint(eap_tree, hf_eap_gpsk_id_server_len, tvb, offset, 2, ENC_BIG_ENDIAN, &len);
1454 offset += 2;
1455 proto_tree_add_item(eap_tree, hf_eap_gpsk_id_server, tvb, offset, len, ENC_ASCII | ENC_NA);
1456 offset += len;
1457 offset = dissect_eap_gpsk_csuite_sel(eap_tree, tvb, offset);
1458 proto_tree_add_item_ret_uint(eap_tree, hf_eap_gpsk_pd_payload_len, tvb, offset, 2, ENC_BIG_ENDIAN, &len);
1459 offset += 2;
1460 if (len > 0) {
1461 proto_tree_add_item(eap_tree, hf_eap_gpsk_pd_payload, tvb, offset, len, ENC_NA);
1462 offset += len;
1463 }
1464 len = size + 5 - offset;
1465 proto_tree_add_item(eap_tree, hf_eap_gpsk_payload_mac, tvb, offset, len, ENC_NA);
1466 offset += len;
1467 break;
1468 case GPSK_GPSK_4:
1469 proto_tree_add_item_ret_uint(eap_tree, hf_eap_gpsk_pd_payload_len, tvb, offset, 2, ENC_BIG_ENDIAN, &len);
1470 offset += 2;
1471 if (len > 0) {
1472 proto_tree_add_item(eap_tree, hf_eap_gpsk_pd_payload, tvb, offset, len, ENC_NA);
1473 offset += len;
1474 }
1475 len = size + 5 - offset;
1476 proto_tree_add_item(eap_tree, hf_eap_gpsk_payload_mac, tvb, offset, len, ENC_NA);
1477 offset += len;
1478 break;
1479 case GPSK_FAIL:
1480 proto_tree_add_item(eap_tree, hf_eap_gpsk_failure_code, tvb, offset, 4, ENC_BIG_ENDIAN);
1481 offset += 4;
1482 break;
1483 case GPSK_PROTECTED_FAIL:
1484 proto_tree_add_item(eap_tree, hf_eap_gpsk_failure_code, tvb, offset, 4, ENC_BIG_ENDIAN);
1485 offset += 4;
1486 len = size + 5 - offset;
1487 proto_tree_add_item(eap_tree, hf_eap_gpsk_payload_mac, tvb, offset, len, ENC_NA);
1488 offset += len;
1489 break;
1490 default:
1491 break;
1492 }
1493
1494 return offset;
1495 }
1496
1497 static int
1498 dissect_eap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
1499 {
1500 guint8 eap_code;
1501 guint8 eap_identifier;
1502 guint16 eap_len;
1503 guint8 eap_type;
1504 gint len;
1505 conversation_t *conversation = NULL;
1506 conv_state_t *conversation_state = NULL;
dissect_e1ap_ProtocolIE_ID(tvbuff_t * tvb _U_,int offset _U_,asn1_ctx_t * actx _U_,proto_tree * tree _U_,int hf_index _U_)1507 frame_state_t *packet_state;
1508 int leap_state;
1509 proto_tree *ti, *ti_id, *ti_len;
1510 proto_tree *eap_tree;
1511 proto_tree *eap_tls_flags_tree;
1512 proto_item *eap_type_item;
1513
1514 col_set_str(pinfo->cinfo, COL_PROTOCOL, "EAP");
1515 col_clear(pinfo->cinfo, COL_INFO);
1516
1517 eap_code = tvb_get_guint8(tvb, 0);
1518 eap_identifier = tvb_get_guint8(tvb, 1);
1519
1520 col_add_str(pinfo->cinfo, COL_INFO,
1521 val_to_str(eap_code, eap_code_vals, "Unknown code (0x%02X)"));
1522
1523 /*
1524 * Find a conversation to which we belong; create one if we don't find it.
1525 *
1526 * If this is an EAP-Message (RFC 2869) encapsulated in Tunneled TLS EAP
1527 * (EAP-TTLS), then we should not attempt to create a conversation to detect
1528 * retransmitted messages, try TLS reassembly and so on.
1529 *
1530 * EAP runs over RADIUS (which runs over UDP), EAPOL (802.1X Authentication)
1531 * or other transports. In case of RADIUS, a single "session" may consist
1532 * of two UDP associations (one for authorization, one for accounting) which
1533 * results in two separate conversations. This wastes memory, but won't affect
1534 * the use cases below. In case of EAPOL, there are no ports. In any case,
1535 * force a new conversation when the EAP-Request/Identity message is found.
dissect_e1ap_TriggeringMessage(tvbuff_t * tvb _U_,int offset _U_,asn1_ctx_t * actx _U_,proto_tree * tree _U_,int hf_index _U_)1536 *
1537 * Conversation tracking is required for 1) EAP-TLS reassembly and 2) tracking
1538 * the stage in the LEAP protocol. In both cases, the protocol starts with an
1539 * EAP-Request/Identity message which cannot be found in the middle of the
1540 * session. Use it as a signal to start a new conversation. This ensures that
1541 * the TLS dissector associates new TLS messages with a unique TLS session.
1542 */
1543 if (!proto_is_frame_protocol(pinfo->layers, "tls")) {
1544 if (PINFO_FD_VISITED(pinfo) || !(eap_code == EAP_REQUEST && tvb_get_guint8(tvb, 4) == EAP_TYPE_ID)) {
1545 conversation = find_conversation_pinfo(pinfo, 0);
1546 }
1547 if (conversation == NULL) {
1548 conversation = conversation_new(pinfo->num, &pinfo->src,
1549 &pinfo->dst, conversation_pt_to_endpoint_type(pinfo->ptype),
1550 pinfo->srcport, pinfo->destport, 0);
1551 }
1552
1553 /*
1554 * Get the state information for the conversation; attach some if
1555 * we don't find it.
1556 */
1557 conversation_state = (conv_state_t *)conversation_get_proto_data(conversation, proto_eap);
1558 if (conversation_state == NULL) {
1559 /*
1560 * Attach state information to the conversation.
1561 */
1562 conversation_state = wmem_new(wmem_file_scope(), conv_state_t);
1563 conversation_state->eap_tls_seq = -1;
1564 conversation_state->eap_reass_cookie = 0;
1565 conversation_state->leap_state = -1;
1566 conversation_state->last_eap_id_req = -1;
1567 conversation_state->last_eap_id_resp = -1;
1568 conversation_add_proto_data(conversation, proto_eap, conversation_state);
1569 }
1570
1571 /*
1572 * Set this now, so that it gets remembered even if we throw an exception
1573 * later.
1574 */
1575 if (eap_code == EAP_FAILURE)
1576 conversation_state->leap_state = -1;
1577 }
1578
1579 eap_len = tvb_get_ntohs(tvb, 2);
1580 len = eap_len;
1581
1582 ti = proto_tree_add_item(tree, proto_eap, tvb, 0, len, ENC_NA);
1583 eap_tree = proto_item_add_subtree(ti, ett_eap);
1584
dissect_e1ap_ProtocolIE_SingleContainer(tvbuff_t * tvb _U_,int offset _U_,asn1_ctx_t * actx _U_,proto_tree * tree _U_,int hf_index _U_)1585 proto_tree_add_item(eap_tree, hf_eap_code, tvb, 0, 1, ENC_BIG_ENDIAN);
1586 ti_id = proto_tree_add_item(eap_tree, hf_eap_identifier, tvb, 1, 1, ENC_BIG_ENDIAN);
1587 ti_len = proto_tree_add_item(eap_tree, hf_eap_len, tvb, 2, 2, ENC_BIG_ENDIAN);
1588 if (len < 4 || (guint)len > tvb_reported_length(tvb)) {
1589 expert_add_info(pinfo, ti_len, &ei_eap_bad_length);
1590 }
1591
1592 /* Detect message retransmissions. Since the protocol proceeds in lock-step,
1593 * reordering is not expected. If retransmissions somehow occur, we would have
dissect_e1ap_T_extensionValue(tvbuff_t * tvb _U_,int offset _U_,asn1_ctx_t * actx _U_,proto_tree * tree _U_,int hf_index _U_)1594 * to detect retransmissions via a bitmap. */
1595 gboolean is_duplicate_id = FALSE;
1596 if (conversation_state) {
1597 if (eap_code == EAP_REQUEST || eap_code == EAP_RESPONSE ||
1598 eap_code == EAP_INITIATE || eap_code == EAP_FINISH) {
1599 if (!PINFO_FD_VISITED(pinfo)) {
1600 gint16 *last_eap_id = eap_code == EAP_REQUEST || eap_code == EAP_INITIATE ?
1601 &conversation_state->last_eap_id_req :
1602 &conversation_state->last_eap_id_resp;
1603 is_duplicate_id = *last_eap_id == eap_identifier;
1604 *last_eap_id = eap_identifier;
1605 if (is_duplicate_id) {
1606 // Use a dummy value to remember that this packet is a duplicate.
1607 p_add_proto_data(wmem_file_scope(), pinfo, proto_eap, 1, GINT_TO_POINTER(1));
1608 }
dissect_e1ap_ProtocolExtensionField(tvbuff_t * tvb _U_,int offset _U_,asn1_ctx_t * actx _U_,proto_tree * tree _U_,int hf_index _U_)1609 } else {
1610 is_duplicate_id = !!p_get_proto_data(wmem_file_scope(), pinfo, proto_eap, 1);
1611 }
1612 if (is_duplicate_id) {
1613 expert_add_info(pinfo, ti_id, &ei_eap_retransmission);
1614 }
1615 }
1616 }
1617
1618 switch (eap_code) {
1619
1620 case EAP_SUCCESS:
1621 case EAP_FAILURE:
dissect_e1ap_ProtocolExtensionContainer(tvbuff_t * tvb _U_,int offset _U_,asn1_ctx_t * actx _U_,proto_tree * tree _U_,int hf_index _U_)1622 break;
1623
1624 case EAP_REQUEST:
1625 case EAP_RESPONSE:
1626 eap_type = tvb_get_guint8(tvb, 4);
1627
1628 col_append_fstr(pinfo->cinfo, COL_INFO, ", %s",
1629 val_to_str_ext(eap_type, &eap_type_vals_ext,
1630 "Unknown type (0x%02x)"));
1631 eap_type_item = proto_tree_add_item(eap_tree, hf_eap_type, tvb, 4, 1, ENC_BIG_ENDIAN);
1632
dissect_e1ap_T_value(tvbuff_t * tvb _U_,int offset _U_,asn1_ctx_t * actx _U_,proto_tree * tree _U_,int hf_index _U_)1633 if ((len > 5) || ((len == 5) && (eap_type == EAP_TYPE_ID))) {
1634 int offset = 5;
1635 gint size = len - offset;
1636
1637 switch (eap_type) {
1638 /*********************************************************************
1639 **********************************************************************/
1640 case EAP_TYPE_ID:
1641 if (size > 0) {
1642 dissect_eap_identity(tvb, pinfo, eap_tree, offset, size);
1643 }
1644 if (conversation_state && !PINFO_FD_VISITED(pinfo)) {
1645 conversation_state->leap_state = 0;
1646 conversation_state->eap_tls_seq = -1;
1647 }
1648 break;
1649
1650 /*********************************************************************
1651 **********************************************************************/
1652 case EAP_TYPE_NOTIFY:
1653 proto_tree_add_item(eap_tree, hf_eap_notification, tvb,
1654 offset, size, ENC_ASCII|ENC_NA);
1655 break;
1656
1657 /*********************************************************************
1658 **********************************************************************/
1659 case EAP_TYPE_NAK:
1660 proto_tree_add_item(eap_tree, hf_eap_type_nak, tvb,
1661 offset, 1, ENC_BIG_ENDIAN);
1662 break;
1663 /*********************************************************************
1664 **********************************************************************/
1665 case EAP_TYPE_MD5:
1666 {
1667 guint8 value_size = tvb_get_guint8(tvb, offset);
1668 gint extra_len = size - 1 - value_size;
1669 proto_item *item;
1670
1671 /* Warn that this is an insecure EAP type. */
1672 expert_add_info(pinfo, eap_type_item, &ei_eap_mitm_attacks);
1673
1674 item = proto_tree_add_item(eap_tree, hf_eap_md5_value_size, tvb, offset, 1, ENC_BIG_ENDIAN);
1675 if (value_size > (size - 1))
1676 {
1677 expert_add_info(pinfo, item, &ei_eap_md5_value_size_overflow);
1678 value_size = size - 1;
1679 }
1680
1681 offset += 1;
1682 proto_tree_add_item(eap_tree, hf_eap_md5_value, tvb, offset, value_size, ENC_NA);
1683 offset += value_size;
1684 if (extra_len > 0) {
1685 proto_tree_add_item(eap_tree, hf_eap_md5_extra_data, tvb, offset, extra_len, ENC_NA);
1686 }
1687 }
1688 break;
1689
1690 /*********************************************************************
1691 EAP-TLS
1692 **********************************************************************/
1693 case EAP_TYPE_FAST:
1694 case EAP_TYPE_PEAP:
1695 case EAP_TYPE_TTLS:
1696 case EAP_TYPE_TLS:
1697 case EAP_TYPE_TEAP:
1698 {
1699 guint8 flags = tvb_get_guint8(tvb, offset);
1700 gboolean more_fragments;
1701 gboolean has_length;
1702 gboolean is_start;
1703 int eap_tls_seq = -1;
1704 guint32 eap_reass_cookie = 0;
1705 gboolean needs_reassembly = FALSE;
1706
1707 if (!conversation_state) {
1708 // XXX expert info? There cannot be another EAP-TTLS message within
1709 // the EAP-Message inside EAP-TTLS.
1710 break;
1711 }
1712
1713 more_fragments = test_flag(flags,EAP_TLS_FLAG_M);
1714 has_length = test_flag(flags,EAP_TLS_FLAG_L);
1715 is_start = test_flag(flags,EAP_TLS_FLAG_S);
1716
1717 if (is_start)
1718 conversation_state->eap_tls_seq = -1;
1719
1720 /* Flags field, 1 byte */
1721 ti = proto_tree_add_item(eap_tree, hf_eap_tls_flags, tvb, offset, 1, ENC_BIG_ENDIAN);
1722 eap_tls_flags_tree = proto_item_add_subtree(ti, ett_eap_tls_flags);
1723 proto_tree_add_item(eap_tls_flags_tree, hf_eap_tls_flag_l, tvb, offset, 1, ENC_BIG_ENDIAN);
1724 proto_tree_add_item(eap_tls_flags_tree, hf_eap_tls_flag_m, tvb, offset, 1, ENC_BIG_ENDIAN);
1725 proto_tree_add_item(eap_tls_flags_tree, hf_eap_tls_flag_s, tvb, offset, 1, ENC_BIG_ENDIAN);
1726
1727 if ((eap_type == EAP_TYPE_PEAP) || (eap_type == EAP_TYPE_TTLS) ||
1728 (eap_type == EAP_TYPE_FAST) || (eap_type == EAP_TYPE_TEAP)) {
1729 proto_tree_add_item(eap_tls_flags_tree, hf_eap_tls_flags_version, tvb, offset, 1, ENC_BIG_ENDIAN);
1730 }
1731 size -= 1;
1732 offset += 1;
1733
1734 /* Length field, 4 bytes, OPTIONAL. */
1735 if (has_length) {
1736 proto_tree_add_item(eap_tree, hf_eap_tls_len, tvb, offset, 4, ENC_BIG_ENDIAN);
1737 size -= 4;
1738 offset += 4;
1739 }
1740
1741 /* 4.1.1 Authority ID Data https://datatracker.ietf.org/doc/html/rfc4851#section-4.1.1 */
1742 if (eap_type == EAP_TYPE_FAST && is_start) {
1743 guint32 length, type;
1744
1745 proto_tree_add_item_ret_uint(eap_tree, hf_eap_fast_type, tvb, offset, 2, ENC_BIG_ENDIAN, &type);
1746 size -= 2;
1747 offset += 2;
1748
1749 proto_tree_add_item_ret_uint(eap_tree, hf_eap_fast_length, tvb, offset, 2, ENC_BIG_ENDIAN, &length);
1750 size -= 2;
1751 offset += 2;
1752
1753 proto_tree_add_item(eap_tree, hf_eap_data, tvb, offset, length, ENC_NA);
1754
1755 switch (type) {
1756 case 4:
1757 proto_tree_add_item(eap_tree, hf_eap_fast_aidd, tvb, offset, length, ENC_NA);
1758 break;
1759 }
1760 size -= length;
1761 offset += length;
1762
1763 }
1764
1765 if (size > 0) {
1766
1767 tvbuff_t *next_tvb = NULL;
1768 gint tvb_len;
1769 gboolean save_fragmented;
1770
1771 tvb_len = tvb_captured_length_remaining(tvb, offset);
1772 if (size < tvb_len)
1773 tvb_len = size;
1774
1775 /* If this is a retransmission, do not save the fragment. */
1776 if (is_duplicate_id) {
1777 next_tvb = tvb_new_subset_length_caplen(tvb, offset, tvb_len, size);
1778 call_data_dissector(next_tvb, pinfo, eap_tree);
1779 break;
1780 }
1781
1782 /*
1783 EAP/TLS is weird protocol (it comes from
1784 Microsoft after all).
1785
1786 If we have series of fragmented packets,
1787 then there's no way of knowing that from
1788 the packet itself, if it is the last packet
1789 in series, that is that the packet part of
1790 bigger fragmented set of data.
1791
1792 The only way to know is, by knowing
1793 that we are already in defragmentation
1794 "mode" and we are expecing packet
1795 carrying fragment of data. (either
1796 because we have not received expected
1797 amount of data, or because the packet before
1798 had "F"ragment flag set.)
1799
1800 The situation is alleviated by fact that it
1801 is simple ack/nack protcol so there's no
1802 place for out-of-order packets like it is
1803 possible with IP.
1804
1805 Anyway, point of this lengthy essay is that
1806 we have to keep state information in the
1807 conversation, so that we can put ourselves in
1808 defragmenting mode and wait for the last packet,
1809 and have to attach state to frames as well, so
1810 that we can handle defragmentation after the
1811 first pass through the capture.
1812 */
1813 /* See if we have a remembered defragmentation EAP ID. */
1814 packet_state = (frame_state_t *)p_get_proto_data(wmem_file_scope(), pinfo, proto_eap, 0);
1815 if (packet_state == NULL) {
1816 /*
1817 * We haven't - does this message require reassembly?
1818 */
1819 if (!pinfo->fd->visited) {
1820 /*
1821 * This is the first time we've looked at this frame,
1822 * so it wouldn't have any remembered information.
1823 *
1824 * Therefore, we check whether this conversation has
1825 * a reassembly operation in progress, or whether
1826 * this frame has the Fragment flag set.
1827 */
1828 if (conversation_state->eap_tls_seq != -1) {
1829 /*
1830 * There's a reassembly in progress; the sequence number
1831 * of the previous fragment is
1832 * "conversation_state->eap_tls_seq", and the reassembly
1833 * ID is "conversation_state->eap_reass_cookie".
1834 *
1835 * We must include this frame in the reassembly.
1836 * We advance the sequence number, giving us the
1837 * sequence number for this fragment.
1838 */
1839 needs_reassembly = TRUE;
1840 conversation_state->eap_tls_seq++;
1841
1842 eap_reass_cookie = conversation_state->eap_reass_cookie;
1843 eap_tls_seq = conversation_state->eap_tls_seq;
1844 } else if (more_fragments && has_length) {
1845 /*
1846 * This message has the Fragment flag set, so it requires
1847 * reassembly. It's the message containing the first
1848 * fragment (if it's a later fragment, the sequence
1849 * number in the conversation state would not be -1).
1850 *
1851 * If it doesn't include a length, however, we can't
1852 * do reassembly (either the message is in error, as
1853 * the first fragment *must* contain a length, or we
1854 * didn't capture the first fragment, and this just
1855 * happens to be the first fragment we saw), so we
1856 * also check that we have a length;
1857 */
1858 needs_reassembly = TRUE;
1859 conversation_state->eap_reass_cookie = pinfo->num;
1860
1861 /*
1862 * Start the reassembly sequence number at 0.
1863 */
1864 conversation_state->eap_tls_seq = 0;
1865
1866 eap_tls_seq = conversation_state->eap_tls_seq;
1867 eap_reass_cookie = conversation_state->eap_reass_cookie;
1868 }
1869
1870 if (needs_reassembly) {
1871 /*
1872 * This frame requires reassembly; remember the reassembly
1873 * ID for subsequent accesses to it.
1874 */
1875 packet_state = wmem_new(wmem_file_scope(), frame_state_t);
1876 packet_state->info = eap_reass_cookie;
1877 p_add_proto_data(wmem_file_scope(), pinfo, proto_eap, 0, packet_state);
1878 }
1879 }
1880 } else {
1881 /*
1882 * This frame has a reassembly cookie associated with it, so
1883 * it requires reassembly. We've already done the
1884 * reassembly in the first pass, so "fragment_add_seq()"
1885 * won't look at the sequence number; set it to 0.
1886 *
1887 * XXX - a frame isn't supposed to have more than one
1888 * EAP message in it, but if it includes both an EAP-TLS
1889 * message and a LEAP message, we might be mistakenly
1890 * concluding it requires reassembly because the "info"
1891 * field isn't -1. We could, I guess, pack both EAP-TLS
1892 * ID and LEAP state into the structure, but that doesn't
1893 * work if you have multiple EAP-TLS or LEAP messages in
1894 * the frame.
1895 *
1896 * But it's not clear how much work we should do to handle
1897 * a bogus message such as that; as long as we don't crash
1898 * or do something else equally horrible, we may not
1899 * have to worry about this at all.
1900 */
1901 needs_reassembly = TRUE;
1902 eap_reass_cookie = packet_state->info;
1903 eap_tls_seq = 0;
1904 }
1905
1906 /*
1907 We test here to see whether EAP-TLS packet
1908 carry fragmented of TLS data.
1909
1910 If this is the case, we do reasembly below,
1911 otherwise we just call dissector.
1912 */
1913 if (needs_reassembly) {
1914 fragment_head *fd_head;
1915
1916 /*
1917 * Yes, this frame contains a fragment that requires
1918 * reassembly.
1919 */
1920 save_fragmented = pinfo->fragmented;
1921 pinfo->fragmented = TRUE;
1922 fd_head = fragment_add_seq(&eap_tls_reassembly_table,
1923 tvb, offset,
1924 pinfo, eap_reass_cookie, NULL,
1925 eap_tls_seq,
1926 size,
1927 more_fragments, 0);
1928
1929 if (fd_head != NULL && fd_head->reassembled_in == pinfo->num) {
1930 /* Reassembled */
1931 proto_item *frag_tree_item;
1932
1933 next_tvb = tvb_new_chain(tvb, fd_head->tvb_data);
1934 add_new_data_source(pinfo, next_tvb, "Reassembled EAP-TLS");
1935
1936 show_fragment_seq_tree(fd_head, &eap_tls_frag_items,
1937 eap_tree, pinfo, next_tvb, &frag_tree_item);
1938
1939 /*
1940 * We're finished reassembing this frame.
1941 * Reinitialize the reassembly state.
1942 */
1943 if (!pinfo->fd->visited)
1944 conversation_state->eap_tls_seq = -1;
1945 }
1946
1947 pinfo->fragmented = save_fragmented;
1948
1949 } else { /* this data is NOT fragmented */
1950 next_tvb = tvb_new_subset_length_caplen(tvb, offset, tvb_len, size);
1951 }
1952
1953 if (next_tvb) {
1954 switch (eap_type) {
1955 case EAP_TYPE_TTLS:
1956 tls_set_appdata_dissector(tls_handle, pinfo, diameter_avps_handle);
1957 break;
1958 case EAP_TYPE_PEAP:
1959 tls_set_appdata_dissector(tls_handle, pinfo, eap_handle);
1960 break;
1961 case EAP_TYPE_TEAP:
1962 tls_set_appdata_dissector(tls_handle, pinfo, teap_handle);
1963 break;
1964 }
1965 call_dissector(tls_handle, next_tvb, pinfo, eap_tree);
1966 }
1967 }
1968 }
1969 break; /* EAP_TYPE_TLS */
1970
1971 /*********************************************************************
1972 Cisco's Lightweight EAP (LEAP)
1973 https://web.archive.org/web/20070623090417if_/http://www.missl.cs.umd.edu/wireless/ethereal/leap.txt
1974 **********************************************************************/
1975 case EAP_TYPE_LEAP:
1976 {
1977 guint8 count, namesize;
1978
1979 /* Warn that this is an insecure EAP type. */
1980 expert_add_info(pinfo, eap_type_item, &ei_eap_dictionary_attacks);
1981
1982 /* Version (byte) */
1983 proto_tree_add_item(eap_tree, hf_eap_leap_version, tvb, offset, 1, ENC_BIG_ENDIAN);
1984 offset += 1;
1985
1986 /* Unused (byte) */
1987 proto_tree_add_item(eap_tree, hf_eap_leap_reserved, tvb, offset, 1, ENC_BIG_ENDIAN);
1988 offset += 1;
1989
1990 /* Count (byte) */
1991 count = tvb_get_guint8(tvb, offset);
1992 proto_tree_add_item(eap_tree, hf_eap_leap_count, tvb, offset, 1, ENC_BIG_ENDIAN);
1993 offset += 1;
1994
1995 /* Data (byte*Count) */
1996 /* This part is state-dependent. */
1997
1998 if (!conversation_state) {
1999 // XXX expert info? LEAP is not expected within the EAP-Message within EAP-TTLS.
2000 break;
2001 }
2002 /* XXX - are duplicates possible (is_duplicate_id)?
2003 * If so, should we stop here to avoid modifying conversation_state? */
2004
2005 /* See if we've already remembered the state. */
2006 packet_state = (frame_state_t *)p_get_proto_data(wmem_file_scope(), pinfo, proto_eap, 0);
2007 if (packet_state == NULL) {
2008 /*
2009 * We haven't - compute the state based on the current
2010 * state in the conversation.
2011 */
2012 leap_state = conversation_state->leap_state;
2013
2014 /* Advance the state machine. */
2015 if (leap_state==0) leap_state = 1; else
2016 if (leap_state==1) leap_state = 2; else
2017 if (leap_state==2) leap_state = 3; else
2018 if (leap_state==3) leap_state = 4; else
2019 if (leap_state==4) leap_state = -1;
2020
2021 /*
2022 * Remember the state for subsequent accesses to this
2023 * frame.
2024 */
2025 packet_state = wmem_new(wmem_file_scope(), frame_state_t);
2026 packet_state->info = leap_state;
2027 p_add_proto_data(wmem_file_scope(), pinfo, proto_eap, 0, packet_state);
2028
2029 /*
2030 * Update the conversation's state.
2031 */
2032 conversation_state->leap_state = leap_state;
2033 }
2034
2035 /* Get the remembered state. */
2036 leap_state = packet_state->info;
2037
2038 switch (leap_state) {
2039 case 1:
2040 proto_tree_add_item(eap_tree, hf_eap_leap_peer_challenge, tvb, offset, count, ENC_NA);
2041 break;
2042
2043 case 2:
2044 proto_tree_add_item(eap_tree, hf_eap_leap_peer_response, tvb, offset, count, ENC_NA);
2045 break;
2046
2047 case 3:
2048 proto_tree_add_item(eap_tree, hf_eap_leap_ap_challenge, tvb, offset, count, ENC_NA);
2049 break;
2050
2051 case 4:
2052 proto_tree_add_item(eap_tree, hf_eap_leap_ap_response, tvb, offset, count, ENC_NA);
2053 break;
2054
2055 default:
2056 proto_tree_add_item(eap_tree, hf_eap_leap_data, tvb, offset, count, ENC_NA);
2057 break;
2058 }
2059
2060 offset += count;
2061
2062 /* Name (Length-(8+Count)) */
2063 namesize = eap_len - (8+count);
2064 proto_tree_add_item(eap_tree, hf_eap_leap_name, tvb, offset, namesize, ENC_ASCII|ENC_NA);
2065 }
2066
2067 break; /* EAP_TYPE_LEAP */
2068
2069 /*********************************************************************
2070 EAP-MSCHAPv2 - draft-kamath-pppext-eap-mschapv2-00.txt
2071 **********************************************************************/
2072 case EAP_TYPE_MSCHAPV2:
2073 dissect_eap_mschapv2(eap_tree, tvb, pinfo, offset, size);
2074 break; /* EAP_TYPE_MSCHAPV2 */
2075
2076 /*********************************************************************
2077 EAP-SIM - draft-haverinen-pppext-eap-sim-13.txt
2078 **********************************************************************/
2079 case EAP_TYPE_SIM:
2080 dissect_eap_sim(eap_tree, tvb, pinfo, offset, size);
2081 break; /* EAP_TYPE_SIM */
2082
2083 /*********************************************************************
2084 EAP-AKA - draft-arkko-pppext-eap-aka-12.txt
2085 **********************************************************************/
2086 case EAP_TYPE_AKA:
2087 case EAP_TYPE_AKA_PRIME:
2088 dissect_eap_aka(eap_tree, tvb, pinfo, offset, size);
2089 break; /* EAP_TYPE_AKA */
2090
2091 /*********************************************************************
2092 EAP Expanded Type
2093 **********************************************************************/
2094 case EAP_TYPE_EXT:
2095 {
2096 proto_tree *exptree;
2097
2098 exptree = proto_tree_add_subtree(eap_tree, tvb, offset, size, ett_eap_exp_attr, NULL, "Expanded Type");
2099 dissect_exteap(exptree, tvb, offset, size, pinfo, eap_code, eap_identifier);
2100 }
2101 break;
2102
2103 /*********************************************************************
2104 EAP-PAX - RFC 4746
2105 **********************************************************************/
2106 case EAP_TYPE_PAX:
2107 dissect_eap_pax(eap_tree, tvb, pinfo, offset, size);
2108 break; /* EAP_TYPE_PAX */
2109
2110 /*********************************************************************
2111 EAP-PSK - RFC 4764
2112 **********************************************************************/
2113 case EAP_TYPE_PSK:
2114 dissect_eap_psk(eap_tree, tvb, pinfo, offset, size);
2115 break; /* EAP_TYPE_PSK */
2116
2117 /*********************************************************************
2118 EAP-SAKE - RFC 4763
2119 **********************************************************************/
2120 case EAP_TYPE_SAKE:
2121 dissect_eap_sake(eap_tree, tvb, pinfo, offset, size);
2122 break; /* EAP_TYPE_SAKE */
2123
2124 /*********************************************************************
2125 EAP-GPSK - RFC 5433
2126 **********************************************************************/
2127 case EAP_TYPE_GPSK:
2128 dissect_eap_gpsk(eap_tree, tvb, pinfo, offset, size);
2129 break; /* EAP_TYPE_GPSK */
2130
2131 /*********************************************************************
2132 **********************************************************************/
2133 default:
2134 proto_tree_add_item(eap_tree, hf_eap_data, tvb, offset, size, ENC_NA);
2135 break;
2136 /*********************************************************************
2137 **********************************************************************/
2138 } /* switch (eap_type) */
2139
2140 }
2141
dissect_e1ap_Cause(tvbuff_t * tvb _U_,int offset _U_,asn1_ctx_t * actx _U_,proto_tree * tree _U_,int hf_index _U_)2142 } /* switch (eap_code) */
2143
2144 return tvb_captured_length(tvb);
2145 }
2146
2147 void
2148 proto_register_eap(void)
2149 {
2150 static hf_register_info hf[] = {
2151 { &hf_eap_code, {
2152 "Code", "eap.code",
dissect_e1ap_Cell_Group_ID(tvbuff_t * tvb _U_,int offset _U_,asn1_ctx_t * actx _U_,proto_tree * tree _U_,int hf_index _U_)2153 FT_UINT8, BASE_DEC, VALS(eap_code_vals), 0x0,
2154 NULL, HFILL }},
2155
2156 { &hf_eap_identifier, {
2157 "Id", "eap.id",
2158 FT_UINT8, BASE_DEC, NULL, 0x0,
2159 NULL, HFILL }},
2160
2161 { &hf_eap_len, {
2162 "Length", "eap.len",
2163 FT_UINT16, BASE_DEC, NULL, 0x0,
2164 NULL, HFILL }},
2165
2166 { &hf_eap_type, {
2167 "Type", "eap.type",
2168 FT_UINT8, BASE_DEC|BASE_EXT_STRING, &eap_type_vals_ext, 0x0,
2169 NULL, HFILL }},
dissect_e1ap_UL_Configuration(tvbuff_t * tvb _U_,int offset _U_,asn1_ctx_t * actx _U_,proto_tree * tree _U_,int hf_index _U_)2170
2171 { &hf_eap_type_nak, {
2172 "Desired Auth Type", "eap.desired_type",
2173 FT_UINT8, BASE_DEC|BASE_EXT_STRING, &eap_type_vals_ext, 0x0,
2174 NULL, HFILL }},
2175
2176 { &hf_eap_identity, {
2177 "Identity", "eap.identity",
2178 FT_STRING, BASE_NONE, NULL, 0x0,
2179 NULL, HFILL }},
2180
2181 { &hf_eap_identity_prefix, {
2182 "Identity Prefix", "eap.identity.prefix",
2183 FT_CHAR, BASE_HEX, NULL, 0x0,
2184 NULL, HFILL }},
2185
dissect_e1ap_DL_TX_Stop(tvbuff_t * tvb _U_,int offset _U_,asn1_ctx_t * actx _U_,proto_tree * tree _U_,int hf_index _U_)2186 { &hf_eap_identity_type, {
2187 "Identity Type", "eap.identity.type",
2188 FT_STRING, BASE_NONE, NULL, 0x0,
2189 NULL, HFILL }},
2190
2191 { &hf_eap_identity_full, {
2192 "Identity (Full)", "eap.identity.full",
2193 FT_STRING, BASE_NONE, NULL, 0x0,
2194 NULL, HFILL }},
2195
2196 { &hf_eap_identity_mcc, {
2197 "Identity Mobile Country Code", "eap.identity.mcc",
2198 FT_UINT16, BASE_DEC|BASE_EXT_STRING, &E212_codes_ext, 0x0, NULL, HFILL }},
2199
2200 { &hf_eap_identity_mcc_mnc_2digits, {
2201 "Identity Mobile Network Code", "eap.identity.mnc",
dissect_e1ap_RAT_Type(tvbuff_t * tvb _U_,int offset _U_,asn1_ctx_t * actx _U_,proto_tree * tree _U_,int hf_index _U_)2202 FT_UINT16, BASE_DEC|BASE_EXT_STRING, &mcc_mnc_2digits_codes_ext, 0x0, NULL, HFILL }},
2203
2204 { &hf_eap_identity_mcc_mnc_3digits, {
2205 "Identity Mobile Network Code", "eap.identity.mnc",
2206 FT_UINT16, BASE_DEC|BASE_EXT_STRING, &mcc_mnc_3digits_codes_ext, 0x0, NULL, HFILL }},
2207
2208 { &hf_eap_identity_padding, {
2209 "Padding", "eap.identity.padding",
2210 FT_BYTES, BASE_NONE, NULL, 0x0,
2211 NULL, HFILL }},
2212
2213 { &hf_eap_identity_actual_len, {
2214 "Identity Actual Length", "eap.identity.actual_len",
2215 FT_UINT16, BASE_DEC, NULL, 0x0,
2216 NULL, HFILL }},
2217
2218 { &hf_eap_notification, {
2219 "Notification", "eap.notification",
dissect_e1ap_Cell_Group_Information_Item(tvbuff_t * tvb _U_,int offset _U_,asn1_ctx_t * actx _U_,proto_tree * tree _U_,int hf_index _U_)2220 FT_STRING, BASE_NONE, NULL, 0x0,
2221 NULL, HFILL }},
2222
2223 { &hf_eap_md5_value_size, {
2224 "EAP-MD5 Value-Size", "eap.md5.value_size",
2225 FT_UINT8, BASE_DEC, NULL, 0x0,
2226 NULL, HFILL }},
2227
2228 { &hf_eap_md5_value, {
2229 "EAP-MD5 Value", "eap.md5.value",
2230 FT_BYTES, BASE_NONE, NULL, 0x0,
2231 NULL, HFILL }},
2232
dissect_e1ap_Cell_Group_Information(tvbuff_t * tvb _U_,int offset _U_,asn1_ctx_t * actx _U_,proto_tree * tree _U_,int hf_index _U_)2233 { &hf_eap_md5_extra_data, {
2234 "EAP-MD5 Extra Data", "eap.md5.extra_data",
2235 FT_BYTES, BASE_NONE, NULL, 0x0,
2236 NULL, HFILL }},
2237
2238 { &hf_eap_tls_flags, {
2239 "EAP-TLS Flags", "eap.tls.flags",
2240 FT_UINT8, BASE_HEX, NULL, 0x0,
2241 NULL, HFILL }},
2242
2243 { &hf_eap_tls_flag_l, {
2244 "Length Included", "eap.tls.flags.len_included",
2245 FT_BOOLEAN, 8, NULL, EAP_TLS_FLAG_L,
2246 NULL, HFILL }},
2247
2248 { &hf_eap_tls_flag_m, {
dissect_e1ap_CHOInitiation(tvbuff_t * tvb _U_,int offset _U_,asn1_ctx_t * actx _U_,proto_tree * tree _U_,int hf_index _U_)2249 "More Fragments", "eap.tls.flags.more_fragments",
2250 FT_BOOLEAN, 8, NULL, EAP_TLS_FLAG_M,
2251 NULL, HFILL }},
2252
2253 { &hf_eap_tls_flag_s, {
2254 "Start", "eap.tls.flags.start",
2255 FT_BOOLEAN, 8, NULL, EAP_TLS_FLAG_S,
2256 NULL, HFILL }},
2257
2258 { &hf_eap_tls_flags_version, {
dissect_e1ap_Number_of_tunnels(tvbuff_t * tvb _U_,int offset _U_,asn1_ctx_t * actx _U_,proto_tree * tree _U_,int hf_index _U_)2259 "Version", "eap.tls.flags.version",
2260 FT_UINT8, BASE_DEC, NULL, EAP_TLS_FLAGS_VERSION,
2261 NULL, HFILL }},
2262
2263 { &hf_eap_tls_len, {
2264 "EAP-TLS Length", "eap.tls.len",
2265 FT_UINT32, BASE_DEC, NULL, 0x0,
2266 NULL, HFILL }},
2267
2268 { &hf_eap_tls_fragment, {
2269 "EAP-TLS Fragment", "eap.tls.fragment",
2270 FT_FRAMENUM, BASE_NONE, NULL, 0x0,
2271 NULL, HFILL }},
2272
2273 { &hf_eap_tls_fragments, {
2274 "EAP-TLS Fragments", "eap.tls.fragments",
2275 FT_NONE, BASE_NONE, NULL, 0x0,
2276 NULL, HFILL }},
dissect_e1ap_CipheringAlgorithm(tvbuff_t * tvb _U_,int offset _U_,asn1_ctx_t * actx _U_,proto_tree * tree _U_,int hf_index _U_)2277
2278 { &hf_eap_tls_fragment_overlap, {
2279 "Fragment Overlap", "eap.tls.fragment.overlap",
2280 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
2281 "Fragment overlaps with other fragments", HFILL }},
2282
2283 { &hf_eap_tls_fragment_overlap_conflict, {
2284 "Conflicting Data In Fragment Overlap", "eap.tls.fragment.overlap_conflict",
2285 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
2286 "Overlapping fragments contained conflicting data", HFILL }},
2287
2288 { &hf_eap_tls_fragment_multiple_tails, {
2289 "Multiple Tail Fragments Found", "eap.tls.fragment.multiple_tails",
2290 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
2291 "Several tails were found when defragmenting the packet", HFILL }},
2292
2293 { &hf_eap_tls_fragment_too_long_fragment,{
dissect_e1ap_CNSupport(tvbuff_t * tvb _U_,int offset _U_,asn1_ctx_t * actx _U_,proto_tree * tree _U_,int hf_index _U_)2294 "Fragment Too Long", "eap.tls.fragment.fragment.too_long",
2295 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
2296 "Fragment contained data past end of packet", HFILL }},
2297
2298 { &hf_eap_tls_fragment_error, {
2299 "Defragmentation Error", "eap.tls.fragment.error",
2300 FT_FRAMENUM, BASE_NONE, NULL, 0x0,
2301 "Defragmentation error due to illegal fragments", HFILL }},
2302
2303 { &hf_eap_tls_fragment_count, {
dissect_e1ap_CommonNetworkInstance(tvbuff_t * tvb _U_,int offset _U_,asn1_ctx_t * actx _U_,proto_tree * tree _U_,int hf_index _U_)2304 "Fragment Count", "eap.tls.fragment.count",
2305 FT_UINT32, BASE_DEC, NULL, 0x0,
2306 "Total length of the reassembled payload", HFILL }},
2307
2308 { &hf_eap_tls_reassembled_length, {
2309 "Reassembled EAP-TLS Length", "eap.tls.reassembled.len",
2310 FT_UINT32, BASE_DEC, NULL, 0x0,
2311 "Total length of the reassembled payload", HFILL }},
2312
2313 { &hf_eap_sim_subtype, {
2314 "EAP-SIM Subtype", "eap.sim.subtype",
2315 FT_UINT8, BASE_DEC, VALS(eap_sim_subtype_vals), 0x0,
2316 NULL, HFILL }},
2317
2318 { &hf_eap_sim_reserved, {
2319 "EAP-SIM Reserved", "eap.sim.reserved",
2320 FT_UINT16, BASE_HEX, NULL, 0x0,
dissect_e1ap_ConfidentialityProtectionIndication(tvbuff_t * tvb _U_,int offset _U_,asn1_ctx_t * actx _U_,proto_tree * tree _U_,int hf_index _U_)2321 NULL, HFILL }},
2322
2323 { &hf_eap_sim_subtype_attribute, {
2324 "EAP-SIM Attribute", "eap.sim.subtype.attribute",
2325 FT_NONE, BASE_NONE, NULL, 0x0,
2326 NULL, HFILL }},
2327
2328 { &hf_eap_sim_subtype_type, {
2329 "EAP-SIM Type", "eap.sim.subtype.type",
2330 FT_UINT8, BASE_DEC|BASE_EXT_STRING, &eap_sim_aka_attribute_vals_ext, 0x0,
2331 NULL, HFILL }},
2332
2333 { &hf_eap_sim_subtype_length, {
2334 "EAP-SIM Length", "eap.sim.subtype.len",
2335 FT_UINT8, BASE_DEC, NULL, 0x0,
2336 NULL, HFILL }},
dissect_e1ap_ConfidentialityProtectionResult(tvbuff_t * tvb _U_,int offset _U_,asn1_ctx_t * actx _U_,proto_tree * tree _U_,int hf_index _U_)2337
2338 { &hf_eap_sim_notification_type, {
2339 "EAP-SIM Notification Type", "eap.sim.notification_type",
2340 FT_UINT16, BASE_DEC, VALS(eap_sim_aka_notification_vals), 0x0,
2341 NULL, HFILL }},
2342
2343 { &hf_eap_sim_error_code_type, {
2344 "EAP-SIM Error Code", "eap.sim.error_code",
2345 FT_UINT16, BASE_DEC, VALS(eap_sim_aka_client_error_codes), 0x0,
2346 NULL, HFILL }},
dissect_e1ap_TransportLayerAddress(tvbuff_t * tvb _U_,int offset _U_,asn1_ctx_t * actx _U_,proto_tree * tree _U_,int hf_index _U_)2347
2348 { &hf_eap_sim_subtype_value, {
2349 "EAP-SIM Value", "eap.sim.subtype.value",
2350 FT_BYTES, BASE_NONE, NULL, 0x0,
2351 NULL, HFILL }},
2352
2353 { &hf_eap_aka_subtype, {
2354 "EAP-AKA Subtype", "eap.aka.subtype",
2355 FT_UINT8, BASE_DEC, VALS(eap_aka_subtype_vals), 0x0,
2356 NULL, HFILL }},
2357
2358 { &hf_eap_aka_reserved, {
2359 "EAP-AKA Reserved", "eap.aka.reserved",
2360 FT_UINT16, BASE_HEX, NULL, 0x0,
2361 NULL, HFILL }},
2362
2363 { &hf_eap_aka_subtype_attribute, {
2364 "EAP-AKA Attribute", "eap.aka.subtype.attribute",
2365 FT_NONE, BASE_NONE, NULL, 0x0,
2366 NULL, HFILL }},
2367
2368 { &hf_eap_aka_subtype_type, {
2369 "EAP-AKA Type", "eap.aka.subtype.type",
2370 FT_UINT8, BASE_DEC|BASE_EXT_STRING, &eap_sim_aka_attribute_vals_ext, 0x0,
2371 NULL, HFILL }},
2372
2373 { &hf_eap_aka_subtype_length, {
2374 "EAP-AKA Length", "eap.aka.subtype.len",
2375 FT_UINT8, BASE_DEC, NULL, 0x0,
2376 NULL, HFILL }},
2377
2378 { &hf_eap_aka_notification_type, {
2379 "EAP-AKA Notification Type", "eap.aka.notification_type",
2380 FT_UINT16, BASE_DEC, VALS(eap_sim_aka_notification_vals), 0x0,
2381 NULL, HFILL }},
2382
2383 { &hf_eap_aka_error_code_type, {
2384 "EAP-AKA Error Code", "eap.aka.error_code",
2385 FT_UINT16, BASE_DEC, VALS(eap_sim_aka_client_error_codes), 0x0,
2386 NULL, HFILL }},
2387
2388 { &hf_eap_aka_subtype_value, {
2389 "EAP-AKA Value", "eap.aka.subtype.value",
2390 FT_BYTES, BASE_NONE, NULL, 0x0,
2391 NULL, HFILL }},
dissect_e1ap_CP_TNL_Information(tvbuff_t * tvb _U_,int offset _U_,asn1_ctx_t * actx _U_,proto_tree * tree _U_,int hf_index _U_)2392
2393 { &hf_eap_leap_version, {
2394 "EAP-LEAP Version", "eap.leap.version",
2395 FT_UINT8, BASE_DEC, NULL, 0x0,
2396 NULL, HFILL }},
2397
2398 { &hf_eap_leap_reserved, {
2399 "EAP-LEAP Reserved", "eap.leap.reserved",
2400 FT_UINT8, BASE_HEX, NULL, 0x0,
2401 NULL, HFILL }},
2402
dissect_e1ap_TransactionID(tvbuff_t * tvb _U_,int offset _U_,asn1_ctx_t * actx _U_,proto_tree * tree _U_,int hf_index _U_)2403 { &hf_eap_leap_count, {
2404 "EAP-LEAP Count", "eap.leap.count",
2405 FT_UINT8, BASE_DEC, NULL, 0x0,
2406 NULL, HFILL }},
2407
2408 { &hf_eap_leap_peer_challenge, {
2409 "EAP-LEAP Peer-Challenge", "eap.leap.peer_challenge",
2410 FT_BYTES, BASE_NONE, NULL, 0x0,
2411 NULL, HFILL }},
2412
2413 { &hf_eap_leap_peer_response, {
2414 "EAP-LEAP Peer-Response", "eap.leap.peer_response",
2415 FT_BYTES, BASE_NONE, NULL, 0x0,
2416 NULL, HFILL }},
2417
2418 { &hf_eap_leap_ap_challenge, {
dissect_e1ap_TypeOfError(tvbuff_t * tvb _U_,int offset _U_,asn1_ctx_t * actx _U_,proto_tree * tree _U_,int hf_index _U_)2419 "EAP-LEAP AP-Challenge", "eap.leap.ap_challenge",
2420 FT_BYTES, BASE_NONE, NULL, 0x0,
2421 NULL, HFILL }},
2422
2423 { &hf_eap_leap_ap_response, {
2424 "EAP-LEAP AP-Response", "eap.leap.ap_response",
2425 FT_BYTES, BASE_NONE, NULL, 0x0,
2426 NULL, HFILL }},
2427
2428 { &hf_eap_leap_data, {
2429 "EAP-LEAP Data", "eap.leap.data",
2430 FT_BYTES, BASE_NONE, NULL, 0x0,
2431 NULL, HFILL }},
2432
2433 { &hf_eap_leap_name, {
2434 "EAP-LEAP Name", "eap.leap.name",
2435 FT_STRING, BASE_NONE, NULL, 0x0,
dissect_e1ap_CriticalityDiagnostics_IE_List_item(tvbuff_t * tvb _U_,int offset _U_,asn1_ctx_t * actx _U_,proto_tree * tree _U_,int hf_index _U_)2436 NULL, HFILL }},
2437
2438 { &hf_eap_ms_chap_v2_opcode, {
2439 "EAP-MS-CHAP-v2 OpCode", "eap.ms_chap_v2.opcode",
2440 FT_UINT8, BASE_DEC, VALS(eap_ms_chap_v2_opcode_vals), 0x0,
2441 NULL, HFILL }},
2442
2443 { &hf_eap_ms_chap_v2_id, {
2444 "EAP-MS-CHAP-v2 Id", "eap.ms_chap_v2.id",
2445 FT_UINT8, BASE_DEC, NULL, 0x0,
2446 NULL, HFILL }},
2447
2448 { &hf_eap_ms_chap_v2_length, {
dissect_e1ap_CriticalityDiagnostics_IE_List(tvbuff_t * tvb _U_,int offset _U_,asn1_ctx_t * actx _U_,proto_tree * tree _U_,int hf_index _U_)2449 "EAP-MS-CHAP-v2 Length", "eap.ms_chap_v2.length",
2450 FT_UINT16, BASE_DEC, NULL, 0x0,
2451 NULL, HFILL }},
2452
2453 { &hf_eap_ms_chap_v2_value_size, {
2454 "EAP-MS-CHAP-v2 Value-Size", "eap.ms_chap_v2.value_size",
2455 FT_UINT8, BASE_DEC, NULL, 0x0,
2456 NULL, HFILL }},
2457
2458 { &hf_eap_ms_chap_v2_challenge, {
2459 "EAP-MS-CHAP-v2 Challenge", "eap.ms_chap_v2.challenge",
2460 FT_BYTES, BASE_NONE, NULL, 0x0,
2461 NULL, HFILL }},
2462
2463 { &hf_eap_ms_chap_v2_name, {
2464 "EAP-MS-CHAP-v2 Name", "eap.ms_chap_v2.name",
2465 FT_STRING, BASE_NONE, NULL, 0x0,
2466 NULL, HFILL }},
2467
2468 { &hf_eap_ms_chap_v2_peer_challenge, {
dissect_e1ap_CriticalityDiagnostics(tvbuff_t * tvb _U_,int offset _U_,asn1_ctx_t * actx _U_,proto_tree * tree _U_,int hf_index _U_)2469 "EAP-MS-CHAP-v2 Peer-Challenge", "eap.ms_chap_v2.peer_challenge",
2470 FT_BYTES, BASE_NONE, NULL, 0x0,
2471 NULL, HFILL }},
2472
2473 { &hf_eap_ms_chap_v2_reserved, {
2474 "EAP-MS-CHAP-v2 Reserved", "eap.ms_chap_v2.reserved",
2475 FT_BYTES, BASE_NONE, NULL, 0x0,
2476 NULL, HFILL }},
2477
2478 { &hf_eap_ms_chap_v2_nt_response, {
2479 "EAP-MS-CHAP-v2 NT-Response", "eap.ms_chap_v2.nt_response",
2480 FT_BYTES, BASE_NONE, NULL, 0x0,
2481 NULL, HFILL }},
2482
2483 { &hf_eap_ms_chap_v2_flags, {
dissect_e1ap_T_dapsIndicator(tvbuff_t * tvb _U_,int offset _U_,asn1_ctx_t * actx _U_,proto_tree * tree _U_,int hf_index _U_)2484 "EAP-MS-CHAP-v2 Flags", "eap.ms_chap_v2.flags",
2485 FT_UINT8, BASE_HEX, NULL, 0x0,
2486 NULL, HFILL }},
2487
2488 { &hf_eap_ms_chap_v2_response, {
2489 "EAP-MS-CHAP-v2 Response (Unknown Length)", "eap.ms_chap_v2.response",
2490 FT_BYTES, BASE_NONE, NULL, 0x0,
2491 NULL, HFILL }},
2492
2493 { &hf_eap_ms_chap_v2_message, {
2494 "EAP-MS-CHAP-v2 Message", "eap.ms_chap_v2.message",
2495 FT_STRING, BASE_NONE, NULL, 0x0,
2496 NULL, HFILL }},
2497
2498 { &hf_eap_ms_chap_v2_failure_request, {
dissect_e1ap_DAPSRequestInfo(tvbuff_t * tvb _U_,int offset _U_,asn1_ctx_t * actx _U_,proto_tree * tree _U_,int hf_index _U_)2499 "EAP-MS-CHAP-v2 Failure-Request", "eap.ms_chap_v2.failure_request",
2500 FT_STRING, BASE_NONE, NULL, 0x0,
2501 NULL, HFILL }},
2502
2503 { &hf_eap_ms_chap_v2_data, {
2504 "EAP-MS-CHAP-v2 Data", "eap.ms_chap_v2.data",
2505 FT_BYTES, BASE_NONE, NULL, 0x0,
2506 NULL, HFILL }},
2507
2508 { &hf_eap_pax_opcode, {
2509 "EAP-PAX OP-Code", "eap.pax.opcode",
2510 FT_UINT8, BASE_HEX, VALS(eap_pax_opcode_vals), 0x0,
2511 NULL, HFILL }},
2512
2513 { &hf_eap_pax_flags, {
2514 "EAP-PAX Flags", "eap.pax.flags",
2515 FT_UINT8, BASE_HEX, NULL, 0x0,
dissect_e1ap_Data_Forwarding_Request(tvbuff_t * tvb _U_,int offset _U_,asn1_ctx_t * actx _U_,proto_tree * tree _U_,int hf_index _U_)2516 NULL, HFILL }},
2517
2518 { &hf_eap_pax_flags_mf, {
2519 "more fragments", "eap.pax.flags.mf",
2520 FT_BOOLEAN, 8, NULL, EAP_PAX_FLAG_MF,
2521 NULL, HFILL }},
2522
2523 { &hf_eap_pax_flags_ce, {
2524 "certificate enabled", "eap.pax.flags.ce",
2525 FT_BOOLEAN, 8, NULL, EAP_PAX_FLAG_CE,
dissect_e1ap_QoS_Flow_Identifier(tvbuff_t * tvb _U_,int offset _U_,asn1_ctx_t * actx _U_,proto_tree * tree _U_,int hf_index _U_)2526 NULL, HFILL }},
2527
2528 { &hf_eap_pax_flags_ai, {
2529 "ADE Included", "eap.pax.flags.ai",
2530 FT_BOOLEAN, 8, NULL, EAP_PAX_FLAG_AI,
2531 NULL, HFILL }},
2532
2533 { &hf_eap_pax_flags_reserved, {
2534 "reserved", "eap.pax.flags.reserved",
2535 FT_BOOLEAN, 8, NULL, EAP_PAX_FLAG_RESERVED,
2536 NULL, HFILL }},
2537
2538 { &hf_eap_pax_mac_id, {
2539 "EAP-PAX MAC ID", "eap.pax.mac_id",
2540 FT_UINT8, BASE_HEX, VALS(eap_pax_mac_id_vals), 0x0,
2541 NULL, HFILL }},
dissect_e1ap_QoS_Flow_Mapping_Indication(tvbuff_t * tvb _U_,int offset _U_,asn1_ctx_t * actx _U_,proto_tree * tree _U_,int hf_index _U_)2542
2543 { &hf_eap_pax_dh_group_id, {
2544 "EAP-PAX DH Group ID", "eap.pax.dh_group_id",
2545 FT_UINT8, BASE_HEX, VALS(eap_pax_dh_group_id_vals), 0x0,
2546 NULL, HFILL }},
2547
2548 { &hf_eap_pax_public_key_id, {
2549 "EAP-PAX Public Key ID", "eap.pax.public_key_id",
2550 FT_UINT8, BASE_HEX, VALS(eap_pax_public_key_id_vals), 0x0,
2551 NULL, HFILL }},
2552
2553 { &hf_eap_pax_a_len, {
2554 "EAP-PAX A len", "eap.pax.a.len",
2555 FT_UINT16, BASE_DEC, NULL, 0x0,
2556 NULL, HFILL }},
2557
dissect_e1ap_QoS_Flow_Mapping_Item(tvbuff_t * tvb _U_,int offset _U_,asn1_ctx_t * actx _U_,proto_tree * tree _U_,int hf_index _U_)2558 { &hf_eap_pax_a, {
2559 "EAP-PAX A", "eap.pax.a",
2560 FT_BYTES, BASE_NONE, NULL, 0x0,
2561 NULL, HFILL }},
2562
2563 { &hf_eap_pax_b_len, {
2564 "EAP-PAX B len", "eap.pax.b.len",
2565 FT_UINT16, BASE_DEC, NULL, 0x0,
2566 NULL, HFILL }},
2567
2568 { &hf_eap_pax_b, {
2569 "EAP-PAX B", "eap.pax.b",
2570 FT_BYTES, BASE_NONE, NULL, 0x0,
dissect_e1ap_QoS_Flow_Mapping_List(tvbuff_t * tvb _U_,int offset _U_,asn1_ctx_t * actx _U_,proto_tree * tree _U_,int hf_index _U_)2571 NULL, HFILL }},
2572
2573 { &hf_eap_pax_cid_len, {
2574 "EAP-PAX CID len", "eap.pax.cid.len",
2575 FT_UINT16, BASE_DEC, NULL, 0x0,
2576 NULL, HFILL }},
2577
2578 { &hf_eap_pax_cid, {
2579 "EAP-PAX CID", "eap.pax.cid",
2580 FT_STRING, BASE_NONE, NULL, 0x0,
2581 NULL, HFILL }},
2582
2583 { &hf_eap_pax_mac_ck_len, {
2584 "EAP-PAX MAC_CK len", "eap.pax.mac_ck.len",
2585 FT_UINT16, BASE_DEC, NULL, 0x0,
2586 NULL, HFILL }},
2587
dissect_e1ap_Data_Forwarding_Information_Request(tvbuff_t * tvb _U_,int offset _U_,asn1_ctx_t * actx _U_,proto_tree * tree _U_,int hf_index _U_)2588 { &hf_eap_pax_mac_ck, {
2589 "EAP-PAX MAC_CK", "eap.pax.mac_ck",
2590 FT_BYTES, BASE_NONE, NULL, 0x0,
2591 NULL, HFILL }},
2592
2593 { &hf_eap_pax_ade_len, {
2594 "EAP-PAX ADE len", "eap.pax.ade.len",
2595 FT_UINT16, BASE_DEC, NULL, 0x0,
2596 NULL, HFILL }},
2597
dissect_e1ap_GTP_TEID(tvbuff_t * tvb _U_,int offset _U_,asn1_ctx_t * actx _U_,proto_tree * tree _U_,int hf_index _U_)2598 { &hf_eap_pax_ade, {
2599 "EAP-PAX ADE", "eap.pax.ade",
2600 FT_BYTES, BASE_NONE, NULL, 0x0,
2601 NULL, HFILL }},
2602
2603 { &hf_eap_pax_mac_icv, {
2604 "EAP-PAX ICV", "eap.pax.icv",
2605 FT_BYTES, BASE_NONE, NULL, 0x0,
2606 NULL, HFILL }},
2607
2608 { &hf_eap_psk_flags, {
2609 "EAP-PSK Flags", "eap.psk.flags",
2610 FT_UINT8, BASE_HEX, NULL, 0x0,
2611 NULL, HFILL }},
2612
2613 { &hf_eap_psk_flags_t, {
dissect_e1ap_GTPTunnel(tvbuff_t * tvb _U_,int offset _U_,asn1_ctx_t * actx _U_,proto_tree * tree _U_,int hf_index _U_)2614 "T", "eap.psk.flags.t",
2615 FT_UINT8, BASE_HEX, NULL, EAP_PSK_FLAGS_T_MASK,
2616 NULL, HFILL }},
2617
2618 { &hf_eap_psk_flags_reserved, {
2619 "Reserved", "eap.psk.flags.reserved",
2620 FT_UINT8, BASE_HEX, NULL, 0x3F,
2621 NULL, HFILL }},
2622
2623 { &hf_eap_psk_rand_p, {
2624 "EAP-PSK RAND_P", "eap.psk.rand_p",
2625 FT_BYTES, BASE_NONE, NULL, 0x0,
2626 NULL, HFILL }},
2627
2628 { &hf_eap_psk_rand_s, {
2629 "EAP-PSK RAND_S", "eap.psk.rand_s",
2630 FT_BYTES, BASE_NONE, NULL, 0x0,
2631 NULL, HFILL }},
2632
2633 { &hf_eap_psk_mac_p, {
2634 "EAP-PSK MAC_P", "eap.psk.mac_p",
dissect_e1ap_UP_TNL_Information(tvbuff_t * tvb _U_,int offset _U_,asn1_ctx_t * actx _U_,proto_tree * tree _U_,int hf_index _U_)2635 FT_BYTES, BASE_NONE, NULL, 0x0,
2636 NULL, HFILL }},
2637
2638 { &hf_eap_psk_mac_s, {
2639 "EAP-PSK MAC_S", "eap.psk.mac_s",
2640 FT_BYTES, BASE_NONE, NULL, 0x0,
2641 NULL, HFILL }},
2642
2643 { &hf_eap_psk_id_p, {
2644 "EAP-PSK ID_P", "eap.psk.id_p",
2645 FT_STRING, BASE_NONE, NULL, 0x0,
2646 NULL, HFILL }},
2647
2648 { &hf_eap_psk_id_s, {
2649 "EAP-PSK ID_S", "eap.psk.id_s",
2650 FT_STRING, BASE_NONE, NULL, 0x0,
2651 NULL, HFILL }},
dissect_e1ap_Data_Forwarding_Information(tvbuff_t * tvb _U_,int offset _U_,asn1_ctx_t * actx _U_,proto_tree * tree _U_,int hf_index _U_)2652
2653 { &hf_eap_psk_pchannel, {
2654 "EAP-PSK Protected Channel (encrypted)", "eap.psk.pchannel",
2655 FT_BYTES, BASE_NONE, NULL, 0x0,
2656 NULL, HFILL }},
2657
2658 { &hf_eap_sake_version, {
2659 "EAP-SAKE Version", "eap.sake.version",
2660 FT_UINT8, BASE_HEX, NULL, 0x0,
2661 NULL, HFILL }},
2662
2663 { &hf_eap_sake_session_id, {
2664 "EAP-SAKE Session ID", "eap.sake.session_id",
2665 FT_UINT8, BASE_HEX, NULL, 0x0,
2666 NULL, HFILL }},
dissect_e1ap_QoS_Flows_to_be_forwarded_Item(tvbuff_t * tvb _U_,int offset _U_,asn1_ctx_t * actx _U_,proto_tree * tree _U_,int hf_index _U_)2667
2668 { &hf_eap_sake_subtype, {
2669 "EAP-SAKE Subtype", "eap.sake.subtype",
2670 FT_UINT8, BASE_HEX, VALS(eap_sake_subtype_vals), 0x0,
2671 NULL, HFILL }},
2672
2673 { &hf_eap_sake_attr_type, {
2674 "Attribute Type", "eap.sake.attr.type",
2675 FT_UINT8, BASE_HEX, VALS(eap_sake_attr_type_vals), 0x0,
2676 NULL, HFILL }},
2677
2678 { &hf_eap_sake_attr_len, {
2679 "Attribute Length", "eap.sake.attr.len",
dissect_e1ap_QoS_Flows_to_be_forwarded_List(tvbuff_t * tvb _U_,int offset _U_,asn1_ctx_t * actx _U_,proto_tree * tree _U_,int hf_index _U_)2680 FT_UINT8, BASE_DEC, NULL, 0x0,
2681 NULL, HFILL }},
2682
2683 { &hf_eap_sake_attr_value, {
2684 "Attribute Value", "eap.sake.attr.val",
2685 FT_BYTES, BASE_NONE, NULL, 0x0,
2686 NULL, HFILL }},
2687
2688 { &hf_eap_sake_attr_value_str, {
2689 "Attribute Value", "eap.sake.attr.val_str",
2690 FT_STRING, BASE_NONE, NULL, 0x0,
2691 NULL, HFILL }},
2692
2693 { &hf_eap_sake_attr_value_uint48, {
2694 "Attribute Value", "eap.sake.attr.val_uint48",
2695 FT_UINT48, BASE_DEC, NULL, 0x0,
2696 NULL, HFILL }},
dissect_e1ap_DataForwardingtoE_UTRANInformationListItem(tvbuff_t * tvb _U_,int offset _U_,asn1_ctx_t * actx _U_,proto_tree * tree _U_,int hf_index _U_)2697
2698 { &hf_eap_gpsk_opcode, {
2699 "EAP-GPSK OP-Code", "eap.gpsk.opcode",
2700 FT_UINT8, BASE_HEX, VALS(eap_gpsk_opcode_vals), 0x0,
2701 NULL, HFILL }},
2702
2703 { &hf_eap_gpsk_id_server_len, {
2704 "EAP-GPSK ID_Server len", "eap.gpsk.id_server.len",
2705 FT_UINT16, BASE_DEC, NULL, 0x0,
2706 NULL, HFILL }},
2707
2708 { &hf_eap_gpsk_id_server, {
2709 "EAP-GPSK ID_Server", "eap.gpsk.id_server",
dissect_e1ap_DataForwardingtoE_UTRANInformationList(tvbuff_t * tvb _U_,int offset _U_,asn1_ctx_t * actx _U_,proto_tree * tree _U_,int hf_index _U_)2710 FT_STRING, BASE_NONE, NULL, 0x0,
2711 NULL, HFILL }},
2712
2713 { &hf_eap_gpsk_id_peer_len, {
2714 "EAP-GPSK ID_Peer len", "eap.gpsk.id_peer.len",
2715 FT_UINT16, BASE_DEC, NULL, 0x0,
2716 NULL, HFILL }},
2717
2718 { &hf_eap_gpsk_id_peer, {
2719 "EAP-GPSK ID_Peer", "eap.gpsk.id_peer",
2720 FT_STRING, BASE_NONE, NULL, 0x0,
2721 NULL, HFILL }},
2722
2723 { &hf_eap_gpsk_rand_server, {
2724 "EAP-GPSK Rand_Server", "eap.gpsk.rand_server",
2725 FT_BYTES, BASE_NONE, NULL, 0x0,
2726 NULL, HFILL }},
dissect_e1ap_T_secondaryRATType(tvbuff_t * tvb _U_,int offset _U_,asn1_ctx_t * actx _U_,proto_tree * tree _U_,int hf_index _U_)2727
2728 { &hf_eap_gpsk_rand_peer, {
2729 "EAP-GPSK Rand_Peer", "eap.gpsk.rand_peer",
2730 FT_BYTES, BASE_NONE, NULL, 0x0,
2731 NULL, HFILL }},
2732
2733 { &hf_eap_gpsk_csuite_list_len, {
2734 "Len", "eap.gpsk.csuite_list_len",
2735 FT_UINT16, BASE_DEC, NULL, 0x0,
2736 NULL, HFILL }},
dissect_e1ap_T_startTimeStamp_01(tvbuff_t * tvb _U_,int offset _U_,asn1_ctx_t * actx _U_,proto_tree * tree _U_,int hf_index _U_)2737
2738 { &hf_eap_gpsk_csuite_vendor, {
2739 "Vendor", "eap.gpsk.csuite.vendor",
2740 FT_UINT32, BASE_HEX, NULL, 0x0,
2741 NULL, HFILL }},
2742
2743 { &hf_eap_gpsk_csuite_specifier, {
2744 "Specifier", "eap.gpsk.csuite.specifier",
2745 FT_UINT16, BASE_HEX, NULL, 0x0,
2746 NULL, HFILL }},
2747
2748 { &hf_eap_gpsk_pd_payload_len, {
2749 "EAP-GPSK PD_Payload len", "eap.gpsk.pd_payload.len",
2750 FT_UINT16, BASE_DEC, NULL, 0x0,
2751 NULL, HFILL }},
2752
2753 { &hf_eap_gpsk_pd_payload, {
2754 "EAP-GPSK PD_Payload", "eap.gpsk.pd_payload",
2755 FT_BYTES, BASE_NONE, NULL, 0x0,
2756 NULL, HFILL }},
2757
dissect_e1ap_T_endTimeStamp_01(tvbuff_t * tvb _U_,int offset _U_,asn1_ctx_t * actx _U_,proto_tree * tree _U_,int hf_index _U_)2758 { &hf_eap_gpsk_payload_mac, {
2759 "EAP-GPSK Payload MAC", "eap.gpsk.payload_mac",
2760 FT_BYTES, BASE_NONE, NULL, 0x0,
2761 NULL, HFILL }},
2762
2763 { &hf_eap_gpsk_failure_code, {
2764 "EAP-GPSK Failure code", "eap.gpsk.failure_code",
2765 FT_UINT32, BASE_HEX, VALS(eap_gpsk_failure_code_vals), 0x0,
2766 NULL, HFILL }},
2767
2768 { &hf_eap_data, {
2769 "EAP Data", "eap.data",
2770 FT_BYTES, BASE_NONE, NULL, 0x0,
2771 NULL, HFILL }},
2772
2773 { &hf_eap_fast_type, {
2774 "EAP-FAST Type", "eap.fast.type",
2775 FT_UINT16, BASE_DEC, NULL, 0x0,
2776 NULL, HFILL }},
2777
2778 { &hf_eap_fast_length, {
dissect_e1ap_INTEGER_0_18446744073709551615(tvbuff_t * tvb _U_,int offset _U_,asn1_ctx_t * actx _U_,proto_tree * tree _U_,int hf_index _U_)2779 "EAP-FAST Length", "eap.fast.length",
2780 FT_UINT16, BASE_DEC, NULL, 0x0,
2781 NULL, HFILL }},
2782
2783 { &hf_eap_fast_aidd, {
2784 "Authority ID Data", "eap.fast.authority_id_data",
2785 FT_BYTES, BASE_NONE, NULL, 0x0,
2786 NULL, HFILL }},
2787
2788 /* Expanded type fields */
2789 { &hf_eap_ext_vendor_id, {
2790 "EAP-EXT Vendor Id", "eap.ext.vendor_id",
2791 FT_UINT16, BASE_HEX, VALS(eap_ext_vendor_id_vals), 0x0,
2792 NULL, HFILL }},
2793
2794 { &hf_eap_ext_vendor_type, {
2795 "EAP-EXT Vendor Type", "eap.ext.vendor_type",
2796 FT_UINT8, BASE_HEX, VALS(eap_ext_vendor_type_vals), 0x0,
dissect_e1ap_MRDC_Data_Usage_Report_Item(tvbuff_t * tvb _U_,int offset _U_,asn1_ctx_t * actx _U_,proto_tree * tree _U_,int hf_index _U_)2797 NULL, HFILL }}
2798 };
2799 static gint *ett[] = {
2800 &ett_eap,
2801 &ett_eap_pax_flags,
2802 &ett_eap_psk_flags,
2803 &ett_eap_gpsk_csuite_list,
2804 &ett_eap_gpsk_csuite,
2805 &ett_eap_gpsk_csuite_sel,
2806 &ett_eap_sake_attr,
2807 &ett_eap_tls_fragment,
2808 &ett_eap_tls_fragments,
2809 &ett_eap_sim_attr,
dissect_e1ap_SEQUENCE_SIZE_1_maxnooftimeperiods_OF_MRDC_Data_Usage_Report_Item(tvbuff_t * tvb _U_,int offset _U_,asn1_ctx_t * actx _U_,proto_tree * tree _U_,int hf_index _U_)2810 &ett_eap_aka_attr,
2811 &ett_eap_exp_attr,
2812 &ett_eap_tls_flags,
2813 &ett_identity
2814 };
2815 static ei_register_info ei[] = {
2816 { &ei_eap_ms_chap_v2_length, { "eap.ms_chap_v2.length.invalid", PI_PROTOCOL, PI_WARN, "Invalid Length", EXPFILL }},
2817 { &ei_eap_mitm_attacks, { "eap.mitm_attacks", PI_SECURITY, PI_WARN, "Vulnerable to MITM attacks. If possible, change EAP type.", EXPFILL }},
2818 { &ei_eap_md5_value_size_overflow, { "eap.md5.value_size.overflow", PI_PROTOCOL, PI_WARN, "Overflow", EXPFILL }},
2819 { &ei_eap_dictionary_attacks, { "eap.dictionary_attacks", PI_SECURITY, PI_WARN,
2820 "Vulnerable to dictionary attacks. If possible, change EAP type."
2821 " See http://www.cisco.com/warp/public/cc/pd/witc/ao350ap/prodlit/2331_pp.pdf", EXPFILL }},
2822 { &ei_eap_identity_invalid, { "eap.identity.invalid", PI_PROTOCOL, PI_WARN, "Invalid identity code", EXPFILL }},
2823 { &ei_eap_retransmission, { "eap.retransmission", PI_SEQUENCE, PI_NOTE, "This packet is a retransmission", EXPFILL }},
2824 { &ei_eap_bad_length, { "eap.bad_length", PI_PROTOCOL, PI_WARN, "Bad length (too small or too large)", EXPFILL }},
2825 };
2826
dissect_e1ap_Data_Usage_per_PDU_Session_Report(tvbuff_t * tvb _U_,int offset _U_,asn1_ctx_t * actx _U_,proto_tree * tree _U_,int hf_index _U_)2827 expert_module_t* expert_eap;
2828
2829 proto_eap = proto_register_protocol("Extensible Authentication Protocol",
2830 "EAP", "eap");
2831 proto_register_field_array(proto_eap, hf, array_length(hf));
2832 proto_register_subtree_array(ett, array_length(ett));
2833 expert_eap = expert_register_protocol(proto_eap);
2834 expert_register_field_array(expert_eap, ei, array_length(ei));
2835
2836 eap_handle = register_dissector("eap", dissect_eap, proto_eap);
2837
2838 reassembly_table_register(&eap_tls_reassembly_table,
2839 &addresses_reassembly_table_functions);
2840
2841 eap_expanded_type_dissector_table = register_dissector_table("eap.ext.vendor_id",
2842 "EAP-EXT Vendor Id",
dissect_e1ap_T_secondaryRATType_01(tvbuff_t * tvb _U_,int offset _U_,asn1_ctx_t * actx _U_,proto_tree * tree _U_,int hf_index _U_)2843 proto_eap, FT_UINT24,
2844 BASE_HEX);
2845
2846 }
2847
2848 void
2849 proto_reg_handoff_eap(void)
2850 {
2851 /*
2852 * Get a handle for the SSL/TLS dissector.
2853 */
2854 tls_handle = find_dissector_add_dependency("tls", proto_eap);
2855 diameter_avps_handle = find_dissector_add_dependency("diameter_avps", proto_eap);
2856 teap_handle = find_dissector_add_dependency("teap", proto_eap);
2857
2858 dissector_add_uint("ppp.protocol", PPP_EAP, eap_handle);
2859 dissector_add_uint("eapol.type", EAPOL_EAP, eap_handle);
dissect_e1ap_Data_Usage_per_QoS_Flow_Item(tvbuff_t * tvb _U_,int offset _U_,asn1_ctx_t * actx _U_,proto_tree * tree _U_,int hf_index _U_)2860 }
2861 /*
2862 * Editor modelines
2863 *
2864 * Local Variables:
2865 * c-basic-offset: 2
2866 * tab-width: 8
2867 * indent-tabs-mode: nil
2868 * End:
2869 *
2870 * ex: set shiftwidth=2 tabstop=8 expandtab:
2871 * :indentSize=2:tabSize=8:noTabs=true:
2872 */
2873