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