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