11de50e9fSSam Leffler /* 21de50e9fSSam Leffler * Copyright (c) 2004 - Michael Richardson <mcr@xelerance.com> 31de50e9fSSam Leffler * 41de50e9fSSam Leffler * Redistribution and use in source and binary forms, with or without 51de50e9fSSam Leffler * modification, are permitted provided that: (1) source code distributions 61de50e9fSSam Leffler * retain the above copyright notice and this paragraph in its entirety, (2) 71de50e9fSSam Leffler * distributions including binary code include the above copyright notice and 81de50e9fSSam Leffler * this paragraph in its entirety in the documentation or other materials 91de50e9fSSam Leffler * provided with the distribution, and (3) all advertising materials mentioning 101de50e9fSSam Leffler * features or use of this software display the following acknowledgement: 111de50e9fSSam Leffler * ``This product includes software developed by the University of California, 121de50e9fSSam Leffler * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of 131de50e9fSSam Leffler * the University nor the names of its contributors may be used to endorse 141de50e9fSSam Leffler * or promote products derived from this software without specific prior 151de50e9fSSam Leffler * written permission. 161de50e9fSSam Leffler * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED 171de50e9fSSam Leffler * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF 181de50e9fSSam Leffler * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 191de50e9fSSam Leffler */ 201de50e9fSSam Leffler 213340d773SGleb Smirnoff /* \summary: Extensible Authentication Protocol (EAP) printer */ 223340d773SGleb Smirnoff 23ee67461eSJoseph Mingrone #include <config.h> 241de50e9fSSam Leffler 25ee67461eSJoseph Mingrone #include "netdissect-stdinc.h" 261de50e9fSSam Leffler 273340d773SGleb Smirnoff #include "netdissect.h" 281de50e9fSSam Leffler #include "extract.h" 291de50e9fSSam Leffler 30a5779b6eSRui Paulo #define EAP_FRAME_TYPE_PACKET 0 31a5779b6eSRui Paulo #define EAP_FRAME_TYPE_START 1 32a5779b6eSRui Paulo #define EAP_FRAME_TYPE_LOGOFF 2 33a5779b6eSRui Paulo #define EAP_FRAME_TYPE_KEY 3 34a5779b6eSRui Paulo #define EAP_FRAME_TYPE_ENCAP_ASF_ALERT 4 35a5779b6eSRui Paulo 36a5779b6eSRui Paulo struct eap_frame_t { 37ee67461eSJoseph Mingrone nd_uint8_t version; 38ee67461eSJoseph Mingrone nd_uint8_t type; 39ee67461eSJoseph Mingrone nd_uint16_t length; 40a5779b6eSRui Paulo }; 41a5779b6eSRui Paulo 42a5779b6eSRui Paulo static const struct tok eap_frame_type_values[] = { 43a5779b6eSRui Paulo { EAP_FRAME_TYPE_PACKET, "EAP packet" }, 44a5779b6eSRui Paulo { EAP_FRAME_TYPE_START, "EAPOL start" }, 45a5779b6eSRui Paulo { EAP_FRAME_TYPE_LOGOFF, "EAPOL logoff" }, 46a5779b6eSRui Paulo { EAP_FRAME_TYPE_KEY, "EAPOL key" }, 47a5779b6eSRui Paulo { EAP_FRAME_TYPE_ENCAP_ASF_ALERT, "Encapsulated ASF alert" }, 48a5779b6eSRui Paulo { 0, NULL} 49a5779b6eSRui Paulo }; 50a5779b6eSRui Paulo 51a5779b6eSRui Paulo /* RFC 3748 */ 521de50e9fSSam Leffler struct eap_packet_t { 53ee67461eSJoseph Mingrone nd_uint8_t code; 54ee67461eSJoseph Mingrone nd_uint8_t id; 55ee67461eSJoseph Mingrone nd_uint16_t length; 56a5779b6eSRui Paulo }; 57a5779b6eSRui Paulo 58a5779b6eSRui Paulo #define EAP_REQUEST 1 59a5779b6eSRui Paulo #define EAP_RESPONSE 2 60a5779b6eSRui Paulo #define EAP_SUCCESS 3 61a5779b6eSRui Paulo #define EAP_FAILURE 4 62a5779b6eSRui Paulo 63a5779b6eSRui Paulo static const struct tok eap_code_values[] = { 64a5779b6eSRui Paulo { EAP_REQUEST, "Request" }, 65a5779b6eSRui Paulo { EAP_RESPONSE, "Response" }, 66a5779b6eSRui Paulo { EAP_SUCCESS, "Success" }, 67a5779b6eSRui Paulo { EAP_FAILURE, "Failure" }, 68a5779b6eSRui Paulo { 0, NULL} 69a5779b6eSRui Paulo }; 70a5779b6eSRui Paulo 71a5779b6eSRui Paulo #define EAP_TYPE_NO_PROPOSED 0 72a5779b6eSRui Paulo #define EAP_TYPE_IDENTITY 1 73a5779b6eSRui Paulo #define EAP_TYPE_NOTIFICATION 2 74a5779b6eSRui Paulo #define EAP_TYPE_NAK 3 75a5779b6eSRui Paulo #define EAP_TYPE_MD5_CHALLENGE 4 76a5779b6eSRui Paulo #define EAP_TYPE_OTP 5 77a5779b6eSRui Paulo #define EAP_TYPE_GTC 6 78ee67461eSJoseph Mingrone #define EAP_TYPE_TLS 13 /* RFC 5216 */ 79a5779b6eSRui Paulo #define EAP_TYPE_SIM 18 /* RFC 4186 */ 80ee67461eSJoseph Mingrone #define EAP_TYPE_TTLS 21 /* RFC 5281, draft-funk-eap-ttls-v0-01.txt */ 81a5779b6eSRui Paulo #define EAP_TYPE_AKA 23 /* RFC 4187 */ 82a5779b6eSRui Paulo #define EAP_TYPE_FAST 43 /* RFC 4851 */ 83a5779b6eSRui Paulo #define EAP_TYPE_EXPANDED_TYPES 254 84a5779b6eSRui Paulo #define EAP_TYPE_EXPERIMENTAL 255 85a5779b6eSRui Paulo 86a5779b6eSRui Paulo static const struct tok eap_type_values[] = { 87a5779b6eSRui Paulo { EAP_TYPE_NO_PROPOSED, "No proposed" }, 88a5779b6eSRui Paulo { EAP_TYPE_IDENTITY, "Identity" }, 89a5779b6eSRui Paulo { EAP_TYPE_NOTIFICATION, "Notification" }, 90a5779b6eSRui Paulo { EAP_TYPE_NAK, "Nak" }, 91a5779b6eSRui Paulo { EAP_TYPE_MD5_CHALLENGE, "MD5-challenge" }, 92a5779b6eSRui Paulo { EAP_TYPE_OTP, "OTP" }, 93a5779b6eSRui Paulo { EAP_TYPE_GTC, "GTC" }, 94a5779b6eSRui Paulo { EAP_TYPE_TLS, "TLS" }, 95a5779b6eSRui Paulo { EAP_TYPE_SIM, "SIM" }, 96a5779b6eSRui Paulo { EAP_TYPE_TTLS, "TTLS" }, 97a5779b6eSRui Paulo { EAP_TYPE_AKA, "AKA" }, 98a5779b6eSRui Paulo { EAP_TYPE_FAST, "FAST" }, 99a5779b6eSRui Paulo { EAP_TYPE_EXPANDED_TYPES, "Expanded types" }, 100a5779b6eSRui Paulo { EAP_TYPE_EXPERIMENTAL, "Experimental" }, 101a5779b6eSRui Paulo { 0, NULL} 102a5779b6eSRui Paulo }; 103a5779b6eSRui Paulo 104a5779b6eSRui Paulo #define EAP_TLS_EXTRACT_BIT_L(x) (((x)&0x80)>>7) 105a5779b6eSRui Paulo 106ee67461eSJoseph Mingrone /* RFC 5216 - EAP TLS bits */ 107a5779b6eSRui Paulo #define EAP_TLS_FLAGS_LEN_INCLUDED (1 << 7) 108a5779b6eSRui Paulo #define EAP_TLS_FLAGS_MORE_FRAGMENTS (1 << 6) 109a5779b6eSRui Paulo #define EAP_TLS_FLAGS_START (1 << 5) 110a5779b6eSRui Paulo 111a5779b6eSRui Paulo static const struct tok eap_tls_flags_values[] = { 112a5779b6eSRui Paulo { EAP_TLS_FLAGS_LEN_INCLUDED, "L bit" }, 113a5779b6eSRui Paulo { EAP_TLS_FLAGS_MORE_FRAGMENTS, "More fragments bit"}, 114a5779b6eSRui Paulo { EAP_TLS_FLAGS_START, "Start bit"}, 115a5779b6eSRui Paulo { 0, NULL} 116a5779b6eSRui Paulo }; 117a5779b6eSRui Paulo 118a5779b6eSRui Paulo #define EAP_TTLS_VERSION(x) ((x)&0x07) 119a5779b6eSRui Paulo 120a5779b6eSRui Paulo /* EAP-AKA and EAP-SIM - RFC 4187 */ 121a5779b6eSRui Paulo #define EAP_AKA_CHALLENGE 1 122a5779b6eSRui Paulo #define EAP_AKA_AUTH_REJECT 2 123a5779b6eSRui Paulo #define EAP_AKA_SYNC_FAILURE 4 124a5779b6eSRui Paulo #define EAP_AKA_IDENTITY 5 125a5779b6eSRui Paulo #define EAP_SIM_START 10 126a5779b6eSRui Paulo #define EAP_SIM_CHALLENGE 11 127a5779b6eSRui Paulo #define EAP_AKA_NOTIFICATION 12 128a5779b6eSRui Paulo #define EAP_AKA_REAUTH 13 129a5779b6eSRui Paulo #define EAP_AKA_CLIENT_ERROR 14 130a5779b6eSRui Paulo 131a5779b6eSRui Paulo static const struct tok eap_aka_subtype_values[] = { 132a5779b6eSRui Paulo { EAP_AKA_CHALLENGE, "Challenge" }, 133a5779b6eSRui Paulo { EAP_AKA_AUTH_REJECT, "Auth reject" }, 134a5779b6eSRui Paulo { EAP_AKA_SYNC_FAILURE, "Sync failure" }, 135a5779b6eSRui Paulo { EAP_AKA_IDENTITY, "Identity" }, 136a5779b6eSRui Paulo { EAP_SIM_START, "Start" }, 137a5779b6eSRui Paulo { EAP_SIM_CHALLENGE, "Challenge" }, 138a5779b6eSRui Paulo { EAP_AKA_NOTIFICATION, "Notification" }, 139a5779b6eSRui Paulo { EAP_AKA_REAUTH, "Reauth" }, 140a5779b6eSRui Paulo { EAP_AKA_CLIENT_ERROR, "Client error" }, 141a5779b6eSRui Paulo { 0, NULL} 1421de50e9fSSam Leffler }; 1431de50e9fSSam Leffler 1441de50e9fSSam Leffler /* 145a5779b6eSRui Paulo * Print EAP requests / responses 1461de50e9fSSam Leffler */ 1471de50e9fSSam Leffler void 1483c602fabSXin LI eap_print(netdissect_options *ndo, 149ee67461eSJoseph Mingrone const u_char *cp, 1503340d773SGleb Smirnoff u_int length) 1511de50e9fSSam Leffler { 152ee67461eSJoseph Mingrone u_int type, subtype, len; 153ee67461eSJoseph Mingrone u_int count; 154ee67461eSJoseph Mingrone const char *sep; 1551de50e9fSSam Leffler 156*0a7e5f1fSJoseph Mingrone ndo->ndo_protocol = "eap"; 157ee67461eSJoseph Mingrone type = GET_U_1(cp); 158ee67461eSJoseph Mingrone len = GET_BE_U_2(cp + 2); 159ee67461eSJoseph Mingrone if (len != length) { 160ee67461eSJoseph Mingrone /* 161ee67461eSJoseph Mingrone * Probably a fragment; in some cases the fragmentation might 162ee67461eSJoseph Mingrone * not put an EAP header on every packet, if reassembly can 163ee67461eSJoseph Mingrone * be done without that (e.g., fragmentation to make a message 164ee67461eSJoseph Mingrone * fit in multiple TLVs in a RADIUS packet). 165ee67461eSJoseph Mingrone */ 166ee67461eSJoseph Mingrone ND_PRINT("EAP fragment?"); 167ee67461eSJoseph Mingrone return; 168ee67461eSJoseph Mingrone } 169ee67461eSJoseph Mingrone ND_PRINT("%s (%u), id %u, len %u", 170ee67461eSJoseph Mingrone tok2str(eap_code_values, "unknown", type), 171ee67461eSJoseph Mingrone type, 172ee67461eSJoseph Mingrone GET_U_1((cp + 1)), 173ee67461eSJoseph Mingrone len); 174ee67461eSJoseph Mingrone if (len < 4) { 175ee67461eSJoseph Mingrone ND_PRINT(" (too short for EAP header)"); 176a5779b6eSRui Paulo return; 177a5779b6eSRui Paulo } 1781de50e9fSSam Leffler 179ee67461eSJoseph Mingrone ND_TCHECK_LEN(cp, len); 180a5779b6eSRui Paulo 181ee67461eSJoseph Mingrone if (type == EAP_REQUEST || type == EAP_RESPONSE) { 182ee67461eSJoseph Mingrone /* RFC 3748 Section 4.1 */ 183ee67461eSJoseph Mingrone if (len < 5) { 184ee67461eSJoseph Mingrone ND_PRINT(" (too short for EAP request/response)"); 185ee67461eSJoseph Mingrone return; 186ee67461eSJoseph Mingrone } 187ee67461eSJoseph Mingrone subtype = GET_U_1(cp + 4); 188ee67461eSJoseph Mingrone ND_PRINT("\n\t\t Type %s (%u)", 1890bff6a5aSEd Maste tok2str(eap_type_values, "unknown", subtype), 190ee67461eSJoseph Mingrone subtype); 191a5779b6eSRui Paulo 192a5779b6eSRui Paulo switch (subtype) { 193a5779b6eSRui Paulo case EAP_TYPE_IDENTITY: 194ee67461eSJoseph Mingrone /* According to RFC 3748, the message is optional */ 195ee67461eSJoseph Mingrone if (len > 5) { 196ee67461eSJoseph Mingrone ND_PRINT(", Identity: "); 197ee67461eSJoseph Mingrone nd_printjnp(ndo, cp + 5, len - 5); 198a5779b6eSRui Paulo } 199a5779b6eSRui Paulo break; 200a5779b6eSRui Paulo 201a5779b6eSRui Paulo case EAP_TYPE_NOTIFICATION: 202ee67461eSJoseph Mingrone /* According to RFC 3748, there must be at least one octet of message */ 203ee67461eSJoseph Mingrone if (len < 6) { 204ee67461eSJoseph Mingrone ND_PRINT(" (too short for EAP Notification request/response)"); 205ee67461eSJoseph Mingrone return; 206a5779b6eSRui Paulo } 207ee67461eSJoseph Mingrone ND_PRINT(", Notification: "); 208ee67461eSJoseph Mingrone nd_printjnp(ndo, cp + 5, len - 5); 209a5779b6eSRui Paulo break; 210a5779b6eSRui Paulo 211a5779b6eSRui Paulo case EAP_TYPE_NAK: 212a5779b6eSRui Paulo /* 213a5779b6eSRui Paulo * one or more octets indicating 214a5779b6eSRui Paulo * the desired authentication 215a5779b6eSRui Paulo * type one octet per type 216a5779b6eSRui Paulo */ 217ee67461eSJoseph Mingrone if (len < 6) { 218ee67461eSJoseph Mingrone ND_PRINT(" (too short for EAP Legacy NAK request/response)"); 219ee67461eSJoseph Mingrone return; 220ee67461eSJoseph Mingrone } 221ee67461eSJoseph Mingrone sep = ""; 222ee67461eSJoseph Mingrone for (count = 5; count < len; count++) { 223ee67461eSJoseph Mingrone ND_PRINT("%s %s (%u)", sep, 224ee67461eSJoseph Mingrone tok2str(eap_type_values, "unknown", GET_U_1((cp + count))), 225ee67461eSJoseph Mingrone GET_U_1(cp + count)); 226ee67461eSJoseph Mingrone sep = ","; 227a5779b6eSRui Paulo } 228a5779b6eSRui Paulo break; 229a5779b6eSRui Paulo 230a5779b6eSRui Paulo case EAP_TYPE_TTLS: 231a5779b6eSRui Paulo case EAP_TYPE_TLS: 232ee67461eSJoseph Mingrone if (len < 6) { 233ee67461eSJoseph Mingrone ND_PRINT(" (too short for EAP TLS/TTLS request/response)"); 234ee67461eSJoseph Mingrone return; 235ee67461eSJoseph Mingrone } 2360bff6a5aSEd Maste if (subtype == EAP_TYPE_TTLS) 237ee67461eSJoseph Mingrone ND_PRINT(" TTLSv%u", 238ee67461eSJoseph Mingrone EAP_TTLS_VERSION(GET_U_1((cp + 5)))); 239ee67461eSJoseph Mingrone ND_PRINT(" flags [%s] 0x%02x", 240ee67461eSJoseph Mingrone bittok2str(eap_tls_flags_values, "none", GET_U_1((cp + 5))), 241ee67461eSJoseph Mingrone GET_U_1(cp + 5)); 242a5779b6eSRui Paulo 243ee67461eSJoseph Mingrone if (EAP_TLS_EXTRACT_BIT_L(GET_U_1(cp + 5))) { 244ee67461eSJoseph Mingrone if (len < 10) { 245ee67461eSJoseph Mingrone ND_PRINT(" (too short for EAP TLS/TTLS request/response with length)"); 246ee67461eSJoseph Mingrone return; 247ee67461eSJoseph Mingrone } 248ee67461eSJoseph Mingrone ND_PRINT(", len %u", GET_BE_U_4(cp + 6)); 249a5779b6eSRui Paulo } 250a5779b6eSRui Paulo break; 251a5779b6eSRui Paulo 252a5779b6eSRui Paulo case EAP_TYPE_FAST: 253ee67461eSJoseph Mingrone if (len < 6) { 254ee67461eSJoseph Mingrone ND_PRINT(" (too short for EAP FAST request/response)"); 255ee67461eSJoseph Mingrone return; 256ee67461eSJoseph Mingrone } 257ee67461eSJoseph Mingrone ND_PRINT(" FASTv%u", 258ee67461eSJoseph Mingrone EAP_TTLS_VERSION(GET_U_1((cp + 5)))); 259ee67461eSJoseph Mingrone ND_PRINT(" flags [%s] 0x%02x", 260ee67461eSJoseph Mingrone bittok2str(eap_tls_flags_values, "none", GET_U_1((cp + 5))), 261ee67461eSJoseph Mingrone GET_U_1(cp + 5)); 262a5779b6eSRui Paulo 263ee67461eSJoseph Mingrone if (EAP_TLS_EXTRACT_BIT_L(GET_U_1(cp + 5))) { 264ee67461eSJoseph Mingrone if (len < 10) { 265ee67461eSJoseph Mingrone ND_PRINT(" (too short for EAP FAST request/response with length)"); 266ee67461eSJoseph Mingrone return; 267ee67461eSJoseph Mingrone } 268ee67461eSJoseph Mingrone ND_PRINT(", len %u", GET_BE_U_4(cp + 6)); 269a5779b6eSRui Paulo } 270a5779b6eSRui Paulo 271a5779b6eSRui Paulo /* FIXME - TLV attributes follow */ 272a5779b6eSRui Paulo break; 273a5779b6eSRui Paulo 274a5779b6eSRui Paulo case EAP_TYPE_AKA: 275a5779b6eSRui Paulo case EAP_TYPE_SIM: 276ee67461eSJoseph Mingrone if (len < 6) { 277ee67461eSJoseph Mingrone ND_PRINT(" (too short for EAP SIM/AKA request/response)"); 278ee67461eSJoseph Mingrone return; 279ee67461eSJoseph Mingrone } 280ee67461eSJoseph Mingrone ND_PRINT(" subtype [%s] 0x%02x", 281ee67461eSJoseph Mingrone tok2str(eap_aka_subtype_values, "unknown", GET_U_1((cp + 5))), 282ee67461eSJoseph Mingrone GET_U_1(cp + 5)); 283a5779b6eSRui Paulo 284a5779b6eSRui Paulo /* FIXME - TLV attributes follow */ 285a5779b6eSRui Paulo break; 286a5779b6eSRui Paulo 287a5779b6eSRui Paulo case EAP_TYPE_MD5_CHALLENGE: 288a5779b6eSRui Paulo case EAP_TYPE_OTP: 289a5779b6eSRui Paulo case EAP_TYPE_GTC: 290a5779b6eSRui Paulo case EAP_TYPE_EXPANDED_TYPES: 291a5779b6eSRui Paulo case EAP_TYPE_EXPERIMENTAL: 292a5779b6eSRui Paulo default: 293a5779b6eSRui Paulo break; 294a5779b6eSRui Paulo } 295a5779b6eSRui Paulo } 296ee67461eSJoseph Mingrone return; 297ee67461eSJoseph Mingrone trunc: 298ee67461eSJoseph Mingrone nd_print_trunc(ndo); 299ee67461eSJoseph Mingrone } 300a5779b6eSRui Paulo 301ee67461eSJoseph Mingrone void 302ee67461eSJoseph Mingrone eapol_print(netdissect_options *ndo, 303ee67461eSJoseph Mingrone const u_char *cp) 304ee67461eSJoseph Mingrone { 305ee67461eSJoseph Mingrone const struct eap_frame_t *eap; 306ee67461eSJoseph Mingrone u_int eap_type, eap_len; 307ee67461eSJoseph Mingrone 308ee67461eSJoseph Mingrone ndo->ndo_protocol = "eap"; 309ee67461eSJoseph Mingrone eap = (const struct eap_frame_t *)cp; 310ee67461eSJoseph Mingrone ND_TCHECK_SIZE(eap); 311ee67461eSJoseph Mingrone eap_type = GET_U_1(eap->type); 312ee67461eSJoseph Mingrone 313ee67461eSJoseph Mingrone ND_PRINT("%s (%u) v%u, len %u", 314ee67461eSJoseph Mingrone tok2str(eap_frame_type_values, "unknown", eap_type), 315ee67461eSJoseph Mingrone eap_type, 316ee67461eSJoseph Mingrone GET_U_1(eap->version), 317ee67461eSJoseph Mingrone GET_BE_U_2(eap->length)); 318ee67461eSJoseph Mingrone if (ndo->ndo_vflag < 1) 319ee67461eSJoseph Mingrone return; 320ee67461eSJoseph Mingrone 321ee67461eSJoseph Mingrone cp += sizeof(struct eap_frame_t); 322ee67461eSJoseph Mingrone eap_len = GET_BE_U_2(eap->length); 323ee67461eSJoseph Mingrone 324ee67461eSJoseph Mingrone switch (eap_type) { 325ee67461eSJoseph Mingrone case EAP_FRAME_TYPE_PACKET: 326ee67461eSJoseph Mingrone if (eap_len == 0) 327ee67461eSJoseph Mingrone goto trunc; 328ee67461eSJoseph Mingrone ND_PRINT(", "); 329ee67461eSJoseph Mingrone eap_print(ndo, cp, eap_len); 330ee67461eSJoseph Mingrone return; 331a5779b6eSRui Paulo case EAP_FRAME_TYPE_LOGOFF: 332a5779b6eSRui Paulo case EAP_FRAME_TYPE_ENCAP_ASF_ALERT: 333a5779b6eSRui Paulo default: 334a5779b6eSRui Paulo break; 335a5779b6eSRui Paulo } 3361de50e9fSSam Leffler return; 3371de50e9fSSam Leffler 3381de50e9fSSam Leffler trunc: 339ee67461eSJoseph Mingrone nd_print_trunc(ndo); 3401de50e9fSSam Leffler } 341