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