1146773Ssam/* 2146773Ssam * Copyright (c) 2004 - Michael Richardson <mcr@xelerance.com> 3146773Ssam * 4146773Ssam * Redistribution and use in source and binary forms, with or without 5146773Ssam * modification, are permitted provided that: (1) source code distributions 6146773Ssam * retain the above copyright notice and this paragraph in its entirety, (2) 7146773Ssam * distributions including binary code include the above copyright notice and 8146773Ssam * this paragraph in its entirety in the documentation or other materials 9146773Ssam * provided with the distribution, and (3) all advertising materials mentioning 10146773Ssam * features or use of this software display the following acknowledgement: 11146773Ssam * ``This product includes software developed by the University of California, 12146773Ssam * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of 13146773Ssam * the University nor the names of its contributors may be used to endorse 14146773Ssam * or promote products derived from this software without specific prior 15146773Ssam * written permission. 16146773Ssam * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED 17146773Ssam * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF 18146773Ssam * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 19146773Ssam * 20190207Srpaulo * Format and print EAP packets. 21190207Srpaulo * 22146773Ssam */ 23146773Ssam 24146773Ssam#ifndef lint 25146773Ssamstatic const char rcsid[] _U_ = 26190207Srpaulo "@(#) $Header: /tcpdump/master/tcpdump/print-eap.c,v 1.5 2007-10-04 16:41:33 hannes Exp $"; 27146773Ssam#endif 28146773Ssam 29146773Ssam#ifdef HAVE_CONFIG_H 30146773Ssam#include "config.h" 31146773Ssam#endif 32146773Ssam 33146773Ssam#include <tcpdump-stdinc.h> 34146773Ssam 35146773Ssam#include <stdio.h> 36146773Ssam#include <string.h> 37146773Ssam 38146773Ssam#include "netdissect.h" 39190207Srpaulo#include "interface.h" 40146773Ssam#include "addrtoname.h" 41146773Ssam#include "extract.h" 42146773Ssam#include "ether.h" 43146773Ssam 44190207Srpaulo#define EAP_FRAME_TYPE_PACKET 0 45190207Srpaulo#define EAP_FRAME_TYPE_START 1 46190207Srpaulo#define EAP_FRAME_TYPE_LOGOFF 2 47190207Srpaulo#define EAP_FRAME_TYPE_KEY 3 48190207Srpaulo#define EAP_FRAME_TYPE_ENCAP_ASF_ALERT 4 49190207Srpaulo 50190207Srpaulostruct eap_frame_t { 51190207Srpaulo unsigned char version; 52190207Srpaulo unsigned char type; 53190207Srpaulo unsigned char length[2]; 54190207Srpaulo}; 55190207Srpaulo 56190207Srpaulostatic const struct tok eap_frame_type_values[] = { 57190207Srpaulo { EAP_FRAME_TYPE_PACKET, "EAP packet" }, 58190207Srpaulo { EAP_FRAME_TYPE_START, "EAPOL start" }, 59190207Srpaulo { EAP_FRAME_TYPE_LOGOFF, "EAPOL logoff" }, 60190207Srpaulo { EAP_FRAME_TYPE_KEY, "EAPOL key" }, 61190207Srpaulo { EAP_FRAME_TYPE_ENCAP_ASF_ALERT, "Encapsulated ASF alert" }, 62190207Srpaulo { 0, NULL} 63190207Srpaulo}; 64190207Srpaulo 65190207Srpaulo/* RFC 3748 */ 66146773Ssamstruct eap_packet_t { 67190207Srpaulo unsigned char code; 68190207Srpaulo unsigned char id; 69190207Srpaulo unsigned char length[2]; 70146773Ssam}; 71146773Ssam 72190207Srpaulo#define EAP_REQUEST 1 73190207Srpaulo#define EAP_RESPONSE 2 74190207Srpaulo#define EAP_SUCCESS 3 75190207Srpaulo#define EAP_FAILURE 4 76190207Srpaulo 77190207Srpaulostatic const struct tok eap_code_values[] = { 78190207Srpaulo { EAP_REQUEST, "Request" }, 79190207Srpaulo { EAP_RESPONSE, "Response" }, 80190207Srpaulo { EAP_SUCCESS, "Success" }, 81190207Srpaulo { EAP_FAILURE, "Failure" }, 82190207Srpaulo { 0, NULL} 83190207Srpaulo}; 84190207Srpaulo 85190207Srpaulo#define EAP_TYPE_NO_PROPOSED 0 86190207Srpaulo#define EAP_TYPE_IDENTITY 1 87190207Srpaulo#define EAP_TYPE_NOTIFICATION 2 88190207Srpaulo#define EAP_TYPE_NAK 3 89190207Srpaulo#define EAP_TYPE_MD5_CHALLENGE 4 90190207Srpaulo#define EAP_TYPE_OTP 5 91190207Srpaulo#define EAP_TYPE_GTC 6 92190207Srpaulo#define EAP_TYPE_TLS 13 /* RFC 2716 */ 93190207Srpaulo#define EAP_TYPE_SIM 18 /* RFC 4186 */ 94190207Srpaulo#define EAP_TYPE_TTLS 21 /* draft-funk-eap-ttls-v0-01.txt */ 95190207Srpaulo#define EAP_TYPE_AKA 23 /* RFC 4187 */ 96190207Srpaulo#define EAP_TYPE_FAST 43 /* RFC 4851 */ 97190207Srpaulo#define EAP_TYPE_EXPANDED_TYPES 254 98190207Srpaulo#define EAP_TYPE_EXPERIMENTAL 255 99190207Srpaulo 100190207Srpaulostatic const struct tok eap_type_values[] = { 101190207Srpaulo { EAP_TYPE_NO_PROPOSED, "No proposed" }, 102190207Srpaulo { EAP_TYPE_IDENTITY, "Identity" }, 103190207Srpaulo { EAP_TYPE_NOTIFICATION, "Notification" }, 104190207Srpaulo { EAP_TYPE_NAK, "Nak" }, 105190207Srpaulo { EAP_TYPE_MD5_CHALLENGE, "MD5-challenge" }, 106190207Srpaulo { EAP_TYPE_OTP, "OTP" }, 107190207Srpaulo { EAP_TYPE_GTC, "GTC" }, 108190207Srpaulo { EAP_TYPE_TLS, "TLS" }, 109190207Srpaulo { EAP_TYPE_SIM, "SIM" }, 110190207Srpaulo { EAP_TYPE_TTLS, "TTLS" }, 111190207Srpaulo { EAP_TYPE_AKA, "AKA" }, 112190207Srpaulo { EAP_TYPE_FAST, "FAST" }, 113190207Srpaulo { EAP_TYPE_EXPANDED_TYPES, "Expanded types" }, 114190207Srpaulo { EAP_TYPE_EXPERIMENTAL, "Experimental" }, 115190207Srpaulo { 0, NULL} 116190207Srpaulo}; 117190207Srpaulo 118190207Srpaulo#define EAP_TLS_EXTRACT_BIT_L(x) (((x)&0x80)>>7) 119190207Srpaulo 120190207Srpaulo/* RFC 2716 - EAP TLS bits */ 121190207Srpaulo#define EAP_TLS_FLAGS_LEN_INCLUDED (1 << 7) 122190207Srpaulo#define EAP_TLS_FLAGS_MORE_FRAGMENTS (1 << 6) 123190207Srpaulo#define EAP_TLS_FLAGS_START (1 << 5) 124190207Srpaulo 125190207Srpaulostatic const struct tok eap_tls_flags_values[] = { 126190207Srpaulo { EAP_TLS_FLAGS_LEN_INCLUDED, "L bit" }, 127190207Srpaulo { EAP_TLS_FLAGS_MORE_FRAGMENTS, "More fragments bit"}, 128190207Srpaulo { EAP_TLS_FLAGS_START, "Start bit"}, 129190207Srpaulo { 0, NULL} 130190207Srpaulo}; 131190207Srpaulo 132190207Srpaulo#define EAP_TTLS_VERSION(x) ((x)&0x07) 133190207Srpaulo 134190207Srpaulo/* EAP-AKA and EAP-SIM - RFC 4187 */ 135190207Srpaulo#define EAP_AKA_CHALLENGE 1 136190207Srpaulo#define EAP_AKA_AUTH_REJECT 2 137190207Srpaulo#define EAP_AKA_SYNC_FAILURE 4 138190207Srpaulo#define EAP_AKA_IDENTITY 5 139190207Srpaulo#define EAP_SIM_START 10 140190207Srpaulo#define EAP_SIM_CHALLENGE 11 141190207Srpaulo#define EAP_AKA_NOTIFICATION 12 142190207Srpaulo#define EAP_AKA_REAUTH 13 143190207Srpaulo#define EAP_AKA_CLIENT_ERROR 14 144190207Srpaulo 145190207Srpaulostatic const struct tok eap_aka_subtype_values[] = { 146190207Srpaulo { EAP_AKA_CHALLENGE, "Challenge" }, 147190207Srpaulo { EAP_AKA_AUTH_REJECT, "Auth reject" }, 148190207Srpaulo { EAP_AKA_SYNC_FAILURE, "Sync failure" }, 149190207Srpaulo { EAP_AKA_IDENTITY, "Identity" }, 150190207Srpaulo { EAP_SIM_START, "Start" }, 151190207Srpaulo { EAP_SIM_CHALLENGE, "Challenge" }, 152190207Srpaulo { EAP_AKA_NOTIFICATION, "Notification" }, 153190207Srpaulo { EAP_AKA_REAUTH, "Reauth" }, 154190207Srpaulo { EAP_AKA_CLIENT_ERROR, "Client error" }, 155190207Srpaulo { 0, NULL} 156190207Srpaulo}; 157190207Srpaulo 158146773Ssam/* 159190207Srpaulo * Print EAP requests / responses 160146773Ssam */ 161146773Ssamvoid 162190207Srpauloeap_print(netdissect_options *ndo _U_, 163190207Srpaulo register const u_char *cp, 164190207Srpaulo u_int length _U_) 165146773Ssam{ 166190207Srpaulo const struct eap_frame_t *eap; 167190207Srpaulo const u_char *tptr; 168190207Srpaulo u_int tlen, type, subtype; 169190207Srpaulo int count=0, len; 170190207Srpaulo 171190207Srpaulo tptr = cp; 172190207Srpaulo tlen = length; 173190207Srpaulo eap = (const struct eap_frame_t *)cp; 174190207Srpaulo TCHECK(*eap); 175146773Ssam 176190207Srpaulo /* in non-verbose mode just lets print the basic info */ 177190207Srpaulo if (vflag < 1) { 178190207Srpaulo printf("%s (%u) v%u, len %u", 179190207Srpaulo tok2str(eap_frame_type_values, "unknown", eap->type), 180190207Srpaulo eap->type, 181190207Srpaulo eap->version, 182190207Srpaulo EXTRACT_16BITS(eap->length)); 183190207Srpaulo return; 184190207Srpaulo } 185190207Srpaulo 186190207Srpaulo printf("%s (%u) v%u, len %u", 187190207Srpaulo tok2str(eap_frame_type_values, "unknown", eap->type), 188190207Srpaulo eap->type, 189190207Srpaulo eap->version, 190190207Srpaulo EXTRACT_16BITS(eap->length)); 191146773Ssam 192190207Srpaulo tptr += sizeof(const struct eap_frame_t); 193190207Srpaulo tlen -= sizeof(const struct eap_frame_t); 194146773Ssam 195190207Srpaulo switch (eap->type) { 196190207Srpaulo case EAP_FRAME_TYPE_PACKET: 197190207Srpaulo type = *(tptr); 198190207Srpaulo len = EXTRACT_16BITS(tptr+2); 199190207Srpaulo printf(", %s (%u), id %u, len %u", 200190207Srpaulo tok2str(eap_code_values, "unknown", type), 201190207Srpaulo type, 202190207Srpaulo *(tptr+1), 203190207Srpaulo len); 204146773Ssam 205190207Srpaulo if (!TTEST2(*tptr, len)) 206190207Srpaulo goto trunc; 207190207Srpaulo 208190207Srpaulo if (type <= 2) { /* For EAP_REQUEST and EAP_RESPONSE only */ 209190207Srpaulo subtype = *(tptr+4); 210190207Srpaulo printf("\n\t\t Type %s (%u)", 211190207Srpaulo tok2str(eap_type_values, "unknown", *(tptr+4)), 212190207Srpaulo *(tptr+4)); 213190207Srpaulo 214190207Srpaulo switch (subtype) { 215190207Srpaulo case EAP_TYPE_IDENTITY: 216190207Srpaulo if (len - 5 > 0) { 217190207Srpaulo printf(", Identity: "); 218190207Srpaulo safeputs((const char *)tptr+5, len-5); 219190207Srpaulo } 220190207Srpaulo break; 221190207Srpaulo 222190207Srpaulo case EAP_TYPE_NOTIFICATION: 223190207Srpaulo if (len - 5 > 0) { 224190207Srpaulo printf(", Notification: "); 225190207Srpaulo safeputs((const char *)tptr+5, len-5); 226190207Srpaulo } 227190207Srpaulo break; 228190207Srpaulo 229190207Srpaulo case EAP_TYPE_NAK: 230190207Srpaulo count = 5; 231190207Srpaulo 232190207Srpaulo /* 233190207Srpaulo * one or more octets indicating 234190207Srpaulo * the desired authentication 235190207Srpaulo * type one octet per type 236190207Srpaulo */ 237190207Srpaulo while (count < len) { 238190207Srpaulo printf(" %s (%u),", 239190207Srpaulo tok2str(eap_type_values, "unknown", *(tptr+count)), 240190207Srpaulo *(tptr+count)); 241190207Srpaulo count++; 242190207Srpaulo } 243190207Srpaulo break; 244190207Srpaulo 245190207Srpaulo case EAP_TYPE_TTLS: 246190207Srpaulo printf(" TTLSv%u", 247190207Srpaulo EAP_TTLS_VERSION(*(tptr+5))); /* fall through */ 248190207Srpaulo case EAP_TYPE_TLS: 249190207Srpaulo printf(" flags [%s] 0x%02x,", 250190207Srpaulo bittok2str(eap_tls_flags_values, "none", *(tptr+5)), 251190207Srpaulo *(tptr+5)); 252190207Srpaulo 253190207Srpaulo if (EAP_TLS_EXTRACT_BIT_L(*(tptr+5))) { 254190207Srpaulo printf(" len %u", EXTRACT_32BITS(tptr+6)); 255190207Srpaulo } 256190207Srpaulo break; 257190207Srpaulo 258190207Srpaulo case EAP_TYPE_FAST: 259190207Srpaulo printf(" FASTv%u", 260190207Srpaulo EAP_TTLS_VERSION(*(tptr+5))); 261190207Srpaulo printf(" flags [%s] 0x%02x,", 262190207Srpaulo bittok2str(eap_tls_flags_values, "none", *(tptr+5)), 263190207Srpaulo *(tptr+5)); 264190207Srpaulo 265190207Srpaulo if (EAP_TLS_EXTRACT_BIT_L(*(tptr+5))) { 266190207Srpaulo printf(" len %u", EXTRACT_32BITS(tptr+6)); 267190207Srpaulo } 268190207Srpaulo 269190207Srpaulo /* FIXME - TLV attributes follow */ 270190207Srpaulo break; 271190207Srpaulo 272190207Srpaulo case EAP_TYPE_AKA: 273190207Srpaulo case EAP_TYPE_SIM: 274190207Srpaulo printf(" subtype [%s] 0x%02x,", 275190207Srpaulo tok2str(eap_aka_subtype_values, "unknown", *(tptr+5)), 276190207Srpaulo *(tptr+5)); 277190207Srpaulo 278190207Srpaulo /* FIXME - TLV attributes follow */ 279190207Srpaulo break; 280190207Srpaulo 281190207Srpaulo case EAP_TYPE_MD5_CHALLENGE: 282190207Srpaulo case EAP_TYPE_OTP: 283190207Srpaulo case EAP_TYPE_GTC: 284190207Srpaulo case EAP_TYPE_EXPANDED_TYPES: 285190207Srpaulo case EAP_TYPE_EXPERIMENTAL: 286190207Srpaulo default: 287190207Srpaulo break; 288190207Srpaulo } 289190207Srpaulo } 290190207Srpaulo break; 291190207Srpaulo 292190207Srpaulo case EAP_FRAME_TYPE_LOGOFF: 293190207Srpaulo case EAP_FRAME_TYPE_ENCAP_ASF_ALERT: 294190207Srpaulo default: 295190207Srpaulo break; 296190207Srpaulo } 297190207Srpaulo return; 298190207Srpaulo 299190207Srpaulo trunc: 300190207Srpaulo printf("\n\t[|EAP]"); 301146773Ssam} 302146773Ssam 303190207Srpaulo/* 304190207Srpaulo * Local Variables: 305190207Srpaulo * c-basic-offset: 4 306190207Srpaulo * End: 307190207Srpaulo */ 308