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