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 * Format and print EAP packets. 21 * 22 */ 23 24 #define NETDISSECT_REWORKED 25 #ifdef HAVE_CONFIG_H 26 #include "config.h" 27 #endif 28 29 #include <tcpdump-stdinc.h> 30 31 #include "interface.h" 32 #include "extract.h" 33 34 #define EAP_FRAME_TYPE_PACKET 0 35 #define EAP_FRAME_TYPE_START 1 36 #define EAP_FRAME_TYPE_LOGOFF 2 37 #define EAP_FRAME_TYPE_KEY 3 38 #define EAP_FRAME_TYPE_ENCAP_ASF_ALERT 4 39 40 struct eap_frame_t { 41 unsigned char version; 42 unsigned char type; 43 unsigned char length[2]; 44 }; 45 46 static const struct tok eap_frame_type_values[] = { 47 { EAP_FRAME_TYPE_PACKET, "EAP packet" }, 48 { EAP_FRAME_TYPE_START, "EAPOL start" }, 49 { EAP_FRAME_TYPE_LOGOFF, "EAPOL logoff" }, 50 { EAP_FRAME_TYPE_KEY, "EAPOL key" }, 51 { EAP_FRAME_TYPE_ENCAP_ASF_ALERT, "Encapsulated ASF alert" }, 52 { 0, NULL} 53 }; 54 55 /* RFC 3748 */ 56 struct eap_packet_t { 57 unsigned char code; 58 unsigned char id; 59 unsigned char length[2]; 60 }; 61 62 #define EAP_REQUEST 1 63 #define EAP_RESPONSE 2 64 #define EAP_SUCCESS 3 65 #define EAP_FAILURE 4 66 67 static const struct tok eap_code_values[] = { 68 { EAP_REQUEST, "Request" }, 69 { EAP_RESPONSE, "Response" }, 70 { EAP_SUCCESS, "Success" }, 71 { EAP_FAILURE, "Failure" }, 72 { 0, NULL} 73 }; 74 75 #define EAP_TYPE_NO_PROPOSED 0 76 #define EAP_TYPE_IDENTITY 1 77 #define EAP_TYPE_NOTIFICATION 2 78 #define EAP_TYPE_NAK 3 79 #define EAP_TYPE_MD5_CHALLENGE 4 80 #define EAP_TYPE_OTP 5 81 #define EAP_TYPE_GTC 6 82 #define EAP_TYPE_TLS 13 /* RFC 2716 */ 83 #define EAP_TYPE_SIM 18 /* RFC 4186 */ 84 #define EAP_TYPE_TTLS 21 /* draft-funk-eap-ttls-v0-01.txt */ 85 #define EAP_TYPE_AKA 23 /* RFC 4187 */ 86 #define EAP_TYPE_FAST 43 /* RFC 4851 */ 87 #define EAP_TYPE_EXPANDED_TYPES 254 88 #define EAP_TYPE_EXPERIMENTAL 255 89 90 static const struct tok eap_type_values[] = { 91 { EAP_TYPE_NO_PROPOSED, "No proposed" }, 92 { EAP_TYPE_IDENTITY, "Identity" }, 93 { EAP_TYPE_NOTIFICATION, "Notification" }, 94 { EAP_TYPE_NAK, "Nak" }, 95 { EAP_TYPE_MD5_CHALLENGE, "MD5-challenge" }, 96 { EAP_TYPE_OTP, "OTP" }, 97 { EAP_TYPE_GTC, "GTC" }, 98 { EAP_TYPE_TLS, "TLS" }, 99 { EAP_TYPE_SIM, "SIM" }, 100 { EAP_TYPE_TTLS, "TTLS" }, 101 { EAP_TYPE_AKA, "AKA" }, 102 { EAP_TYPE_FAST, "FAST" }, 103 { EAP_TYPE_EXPANDED_TYPES, "Expanded types" }, 104 { EAP_TYPE_EXPERIMENTAL, "Experimental" }, 105 { 0, NULL} 106 }; 107 108 #define EAP_TLS_EXTRACT_BIT_L(x) (((x)&0x80)>>7) 109 110 /* RFC 2716 - EAP TLS bits */ 111 #define EAP_TLS_FLAGS_LEN_INCLUDED (1 << 7) 112 #define EAP_TLS_FLAGS_MORE_FRAGMENTS (1 << 6) 113 #define EAP_TLS_FLAGS_START (1 << 5) 114 115 static const struct tok eap_tls_flags_values[] = { 116 { EAP_TLS_FLAGS_LEN_INCLUDED, "L bit" }, 117 { EAP_TLS_FLAGS_MORE_FRAGMENTS, "More fragments bit"}, 118 { EAP_TLS_FLAGS_START, "Start bit"}, 119 { 0, NULL} 120 }; 121 122 #define EAP_TTLS_VERSION(x) ((x)&0x07) 123 124 /* EAP-AKA and EAP-SIM - RFC 4187 */ 125 #define EAP_AKA_CHALLENGE 1 126 #define EAP_AKA_AUTH_REJECT 2 127 #define EAP_AKA_SYNC_FAILURE 4 128 #define EAP_AKA_IDENTITY 5 129 #define EAP_SIM_START 10 130 #define EAP_SIM_CHALLENGE 11 131 #define EAP_AKA_NOTIFICATION 12 132 #define EAP_AKA_REAUTH 13 133 #define EAP_AKA_CLIENT_ERROR 14 134 135 static const struct tok eap_aka_subtype_values[] = { 136 { EAP_AKA_CHALLENGE, "Challenge" }, 137 { EAP_AKA_AUTH_REJECT, "Auth reject" }, 138 { EAP_AKA_SYNC_FAILURE, "Sync failure" }, 139 { EAP_AKA_IDENTITY, "Identity" }, 140 { EAP_SIM_START, "Start" }, 141 { EAP_SIM_CHALLENGE, "Challenge" }, 142 { EAP_AKA_NOTIFICATION, "Notification" }, 143 { EAP_AKA_REAUTH, "Reauth" }, 144 { EAP_AKA_CLIENT_ERROR, "Client error" }, 145 { 0, NULL} 146 }; 147 148 /* 149 * Print EAP requests / responses 150 */ 151 void 152 eap_print(netdissect_options *ndo, 153 register const u_char *cp, 154 u_int length _U_) 155 { 156 const struct eap_frame_t *eap; 157 const u_char *tptr; 158 u_int tlen, type, subtype; 159 int count=0, len; 160 161 tptr = cp; 162 tlen = length; 163 eap = (const struct eap_frame_t *)cp; 164 ND_TCHECK(*eap); 165 166 /* in non-verbose mode just lets print the basic info */ 167 if (ndo->ndo_vflag < 1) { 168 ND_PRINT((ndo, "%s (%u) v%u, len %u", 169 tok2str(eap_frame_type_values, "unknown", eap->type), 170 eap->type, 171 eap->version, 172 EXTRACT_16BITS(eap->length))); 173 return; 174 } 175 176 ND_PRINT((ndo, "%s (%u) v%u, len %u", 177 tok2str(eap_frame_type_values, "unknown", eap->type), 178 eap->type, 179 eap->version, 180 EXTRACT_16BITS(eap->length))); 181 182 tptr += sizeof(const struct eap_frame_t); 183 tlen -= sizeof(const struct eap_frame_t); 184 185 switch (eap->type) { 186 case EAP_FRAME_TYPE_PACKET: 187 type = *(tptr); 188 len = EXTRACT_16BITS(tptr+2); 189 ND_PRINT((ndo, ", %s (%u), id %u, len %u", 190 tok2str(eap_code_values, "unknown", type), 191 type, 192 *(tptr+1), 193 len)); 194 195 ND_TCHECK2(*tptr, len); 196 197 if (type <= 2) { /* For EAP_REQUEST and EAP_RESPONSE only */ 198 subtype = *(tptr+4); 199 ND_PRINT((ndo, "\n\t\t Type %s (%u)", 200 tok2str(eap_type_values, "unknown", *(tptr+4)), 201 *(tptr + 4))); 202 203 switch (subtype) { 204 case EAP_TYPE_IDENTITY: 205 if (len - 5 > 0) { 206 ND_PRINT((ndo, ", Identity: ")); 207 safeputs(ndo, tptr + 5, len - 5); 208 } 209 break; 210 211 case EAP_TYPE_NOTIFICATION: 212 if (len - 5 > 0) { 213 ND_PRINT((ndo, ", Notification: ")); 214 safeputs(ndo, tptr + 5, len - 5); 215 } 216 break; 217 218 case EAP_TYPE_NAK: 219 count = 5; 220 221 /* 222 * one or more octets indicating 223 * the desired authentication 224 * type one octet per type 225 */ 226 while (count < len) { 227 ND_PRINT((ndo, " %s (%u),", 228 tok2str(eap_type_values, "unknown", *(tptr+count)), 229 *(tptr + count))); 230 count++; 231 } 232 break; 233 234 case EAP_TYPE_TTLS: 235 ND_PRINT((ndo, " TTLSv%u", 236 EAP_TTLS_VERSION(*(tptr + 5)))); /* fall through */ 237 case EAP_TYPE_TLS: 238 ND_PRINT((ndo, " flags [%s] 0x%02x,", 239 bittok2str(eap_tls_flags_values, "none", *(tptr+5)), 240 *(tptr + 5))); 241 242 if (EAP_TLS_EXTRACT_BIT_L(*(tptr+5))) { 243 ND_PRINT((ndo, " len %u", EXTRACT_32BITS(tptr + 6))); 244 } 245 break; 246 247 case EAP_TYPE_FAST: 248 ND_PRINT((ndo, " FASTv%u", 249 EAP_TTLS_VERSION(*(tptr + 5)))); 250 ND_PRINT((ndo, " flags [%s] 0x%02x,", 251 bittok2str(eap_tls_flags_values, "none", *(tptr+5)), 252 *(tptr + 5))); 253 254 if (EAP_TLS_EXTRACT_BIT_L(*(tptr+5))) { 255 ND_PRINT((ndo, " len %u", EXTRACT_32BITS(tptr + 6))); 256 } 257 258 /* FIXME - TLV attributes follow */ 259 break; 260 261 case EAP_TYPE_AKA: 262 case EAP_TYPE_SIM: 263 ND_PRINT((ndo, " subtype [%s] 0x%02x,", 264 tok2str(eap_aka_subtype_values, "unknown", *(tptr+5)), 265 *(tptr + 5))); 266 267 /* FIXME - TLV attributes follow */ 268 break; 269 270 case EAP_TYPE_MD5_CHALLENGE: 271 case EAP_TYPE_OTP: 272 case EAP_TYPE_GTC: 273 case EAP_TYPE_EXPANDED_TYPES: 274 case EAP_TYPE_EXPERIMENTAL: 275 default: 276 break; 277 } 278 } 279 break; 280 281 case EAP_FRAME_TYPE_LOGOFF: 282 case EAP_FRAME_TYPE_ENCAP_ASF_ALERT: 283 default: 284 break; 285 } 286 return; 287 288 trunc: 289 ND_PRINT((ndo, "\n\t[|EAP]")); 290 } 291 292 /* 293 * Local Variables: 294 * c-basic-offset: 4 295 * End: 296 */ 297