eapol_test.c revision c55524ad84d13014e8019491c2b17e5dcf13545a
1/*
2 * WPA Supplicant - test code
3 * Copyright (c) 2003-2011, Jouni Malinen <j@w1.fi>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation.
8 *
9 * Alternatively, this software may be distributed under the terms of BSD
10 * license.
11 *
12 * See README and COPYING for more details.
13 *
14 * IEEE 802.1X Supplicant test code (to be used in place of wpa_supplicant.c.
15 * Not used in production version.
16 */
17
18#include "includes.h"
19#include <assert.h>
20
21#include "common.h"
22#include "config.h"
23#include "eapol_supp/eapol_supp_sm.h"
24#include "eap_peer/eap.h"
25#include "eap_server/eap_methods.h"
26#include "eloop.h"
27#include "rsn_supp/wpa.h"
28#include "eap_peer/eap_i.h"
29#include "wpa_supplicant_i.h"
30#include "radius/radius.h"
31#include "radius/radius_client.h"
32#include "common/wpa_ctrl.h"
33#include "ctrl_iface.h"
34#include "pcsc_funcs.h"
35
36
37extern int wpa_debug_level;
38extern int wpa_debug_show_keys;
39
40struct wpa_driver_ops *wpa_drivers[] = { NULL };
41
42
43struct extra_radius_attr {
44	u8 type;
45	char syntax;
46	char *data;
47	struct extra_radius_attr *next;
48};
49
50struct eapol_test_data {
51	struct wpa_supplicant *wpa_s;
52
53	int eapol_test_num_reauths;
54	int no_mppe_keys;
55	int num_mppe_ok, num_mppe_mismatch;
56
57	u8 radius_identifier;
58	struct radius_msg *last_recv_radius;
59	struct in_addr own_ip_addr;
60	struct radius_client_data *radius;
61	struct hostapd_radius_servers *radius_conf;
62
63	u8 *last_eap_radius; /* last received EAP Response from Authentication
64			      * Server */
65	size_t last_eap_radius_len;
66
67	u8 authenticator_pmk[PMK_LEN];
68	size_t authenticator_pmk_len;
69	int radius_access_accept_received;
70	int radius_access_reject_received;
71	int auth_timed_out;
72
73	u8 *eap_identity;
74	size_t eap_identity_len;
75
76	char *connect_info;
77	u8 own_addr[ETH_ALEN];
78	struct extra_radius_attr *extra_attrs;
79};
80
81static struct eapol_test_data eapol_test;
82
83
84static void send_eap_request_identity(void *eloop_ctx, void *timeout_ctx);
85
86
87static void hostapd_logger_cb(void *ctx, const u8 *addr, unsigned int module,
88			      int level, const char *txt, size_t len)
89{
90	if (addr)
91		wpa_printf(MSG_DEBUG, "STA " MACSTR ": %s\n",
92			   MAC2STR(addr), txt);
93	else
94		wpa_printf(MSG_DEBUG, "%s", txt);
95}
96
97
98static int add_extra_attr(struct radius_msg *msg,
99			  struct extra_radius_attr *attr)
100{
101	size_t len;
102	char *pos;
103	u32 val;
104	char buf[128];
105
106	switch (attr->syntax) {
107	case 's':
108		os_snprintf(buf, sizeof(buf), "%s", attr->data);
109		len = os_strlen(buf);
110		break;
111	case 'n':
112		buf[0] = '\0';
113		len = 1;
114		break;
115	case 'x':
116		pos = attr->data;
117		if (pos[0] == '0' && pos[1] == 'x')
118			pos += 2;
119		len = os_strlen(pos);
120		if ((len & 1) || (len / 2) > sizeof(buf)) {
121			printf("Invalid extra attribute hexstring\n");
122			return -1;
123		}
124		len /= 2;
125		if (hexstr2bin(pos, (u8 *) buf, len) < 0) {
126			printf("Invalid extra attribute hexstring\n");
127			return -1;
128		}
129		break;
130	case 'd':
131		val = htonl(atoi(attr->data));
132		os_memcpy(buf, &val, 4);
133		len = 4;
134		break;
135	default:
136		printf("Incorrect extra attribute syntax specification\n");
137		return -1;
138	}
139
140	if (!radius_msg_add_attr(msg, attr->type, (u8 *) buf, len)) {
141		printf("Could not add attribute %d\n", attr->type);
142		return -1;
143	}
144
145	return 0;
146}
147
148
149static int add_extra_attrs(struct radius_msg *msg,
150			   struct extra_radius_attr *attrs)
151{
152	struct extra_radius_attr *p;
153	for (p = attrs; p; p = p->next) {
154		if (add_extra_attr(msg, p) < 0)
155			return -1;
156	}
157	return 0;
158}
159
160
161static struct extra_radius_attr *
162find_extra_attr(struct extra_radius_attr *attrs, u8 type)
163{
164	struct extra_radius_attr *p;
165	for (p = attrs; p; p = p->next) {
166		if (p->type == type)
167			return p;
168	}
169	return NULL;
170}
171
172
173static void ieee802_1x_encapsulate_radius(struct eapol_test_data *e,
174					  const u8 *eap, size_t len)
175{
176	struct radius_msg *msg;
177	char buf[128];
178	const struct eap_hdr *hdr;
179	const u8 *pos;
180
181	wpa_printf(MSG_DEBUG, "Encapsulating EAP message into a RADIUS "
182		   "packet");
183
184	e->radius_identifier = radius_client_get_id(e->radius);
185	msg = radius_msg_new(RADIUS_CODE_ACCESS_REQUEST,
186			     e->radius_identifier);
187	if (msg == NULL) {
188		printf("Could not create net RADIUS packet\n");
189		return;
190	}
191
192	radius_msg_make_authenticator(msg, (u8 *) e, sizeof(*e));
193
194	hdr = (const struct eap_hdr *) eap;
195	pos = (const u8 *) (hdr + 1);
196	if (len > sizeof(*hdr) && hdr->code == EAP_CODE_RESPONSE &&
197	    pos[0] == EAP_TYPE_IDENTITY) {
198		pos++;
199		os_free(e->eap_identity);
200		e->eap_identity_len = len - sizeof(*hdr) - 1;
201		e->eap_identity = os_malloc(e->eap_identity_len);
202		if (e->eap_identity) {
203			os_memcpy(e->eap_identity, pos, e->eap_identity_len);
204			wpa_hexdump(MSG_DEBUG, "Learned identity from "
205				    "EAP-Response-Identity",
206				    e->eap_identity, e->eap_identity_len);
207		}
208	}
209
210	if (e->eap_identity &&
211	    !radius_msg_add_attr(msg, RADIUS_ATTR_USER_NAME,
212				 e->eap_identity, e->eap_identity_len)) {
213		printf("Could not add User-Name\n");
214		goto fail;
215	}
216
217	if (!find_extra_attr(e->extra_attrs, RADIUS_ATTR_NAS_IP_ADDRESS) &&
218	    !radius_msg_add_attr(msg, RADIUS_ATTR_NAS_IP_ADDRESS,
219				 (u8 *) &e->own_ip_addr, 4)) {
220		printf("Could not add NAS-IP-Address\n");
221		goto fail;
222	}
223
224	os_snprintf(buf, sizeof(buf), RADIUS_802_1X_ADDR_FORMAT,
225		    MAC2STR(e->wpa_s->own_addr));
226	if (!find_extra_attr(e->extra_attrs, RADIUS_ATTR_CALLING_STATION_ID)
227	    &&
228	    !radius_msg_add_attr(msg, RADIUS_ATTR_CALLING_STATION_ID,
229				 (u8 *) buf, os_strlen(buf))) {
230		printf("Could not add Calling-Station-Id\n");
231		goto fail;
232	}
233
234	/* TODO: should probably check MTU from driver config; 2304 is max for
235	 * IEEE 802.11, but use 1400 to avoid problems with too large packets
236	 */
237	if (!find_extra_attr(e->extra_attrs, RADIUS_ATTR_FRAMED_MTU) &&
238	    !radius_msg_add_attr_int32(msg, RADIUS_ATTR_FRAMED_MTU, 1400)) {
239		printf("Could not add Framed-MTU\n");
240		goto fail;
241	}
242
243	if (!find_extra_attr(e->extra_attrs, RADIUS_ATTR_NAS_PORT_TYPE) &&
244	    !radius_msg_add_attr_int32(msg, RADIUS_ATTR_NAS_PORT_TYPE,
245				       RADIUS_NAS_PORT_TYPE_IEEE_802_11)) {
246		printf("Could not add NAS-Port-Type\n");
247		goto fail;
248	}
249
250	os_snprintf(buf, sizeof(buf), "%s", e->connect_info);
251	if (!find_extra_attr(e->extra_attrs, RADIUS_ATTR_CONNECT_INFO) &&
252	    !radius_msg_add_attr(msg, RADIUS_ATTR_CONNECT_INFO,
253				 (u8 *) buf, os_strlen(buf))) {
254		printf("Could not add Connect-Info\n");
255		goto fail;
256	}
257
258	if (add_extra_attrs(msg, e->extra_attrs) < 0)
259		goto fail;
260
261	if (eap && !radius_msg_add_eap(msg, eap, len)) {
262		printf("Could not add EAP-Message\n");
263		goto fail;
264	}
265
266	/* State attribute must be copied if and only if this packet is
267	 * Access-Request reply to the previous Access-Challenge */
268	if (e->last_recv_radius &&
269	    radius_msg_get_hdr(e->last_recv_radius)->code ==
270	    RADIUS_CODE_ACCESS_CHALLENGE) {
271		int res = radius_msg_copy_attr(msg, e->last_recv_radius,
272					       RADIUS_ATTR_STATE);
273		if (res < 0) {
274			printf("Could not copy State attribute from previous "
275			       "Access-Challenge\n");
276			goto fail;
277		}
278		if (res > 0) {
279			wpa_printf(MSG_DEBUG, "  Copied RADIUS State "
280				   "Attribute");
281		}
282	}
283
284	radius_client_send(e->radius, msg, RADIUS_AUTH, e->wpa_s->own_addr);
285	return;
286
287 fail:
288	radius_msg_free(msg);
289}
290
291
292static int eapol_test_eapol_send(void *ctx, int type, const u8 *buf,
293				 size_t len)
294{
295	/* struct wpa_supplicant *wpa_s = ctx; */
296	printf("WPA: eapol_test_eapol_send(type=%d len=%lu)\n",
297	       type, (unsigned long) len);
298	if (type == IEEE802_1X_TYPE_EAP_PACKET) {
299		wpa_hexdump(MSG_DEBUG, "TX EAP -> RADIUS", buf, len);
300		ieee802_1x_encapsulate_radius(&eapol_test, buf, len);
301	}
302	return 0;
303}
304
305
306static void eapol_test_set_config_blob(void *ctx,
307				       struct wpa_config_blob *blob)
308{
309	struct wpa_supplicant *wpa_s = ctx;
310	wpa_config_set_blob(wpa_s->conf, blob);
311}
312
313
314static const struct wpa_config_blob *
315eapol_test_get_config_blob(void *ctx, const char *name)
316{
317	struct wpa_supplicant *wpa_s = ctx;
318	return wpa_config_get_blob(wpa_s->conf, name);
319}
320
321
322static void eapol_test_eapol_done_cb(void *ctx)
323{
324	printf("WPA: EAPOL processing complete\n");
325}
326
327
328static void eapol_sm_reauth(void *eloop_ctx, void *timeout_ctx)
329{
330	struct eapol_test_data *e = eloop_ctx;
331	printf("\n\n\n\n\neapol_test: Triggering EAP reauthentication\n\n");
332	e->radius_access_accept_received = 0;
333	send_eap_request_identity(e->wpa_s, NULL);
334}
335
336
337static int eapol_test_compare_pmk(struct eapol_test_data *e)
338{
339	u8 pmk[PMK_LEN];
340	int ret = 1;
341
342	if (eapol_sm_get_key(e->wpa_s->eapol, pmk, PMK_LEN) == 0) {
343		wpa_hexdump(MSG_DEBUG, "PMK from EAPOL", pmk, PMK_LEN);
344		if (os_memcmp(pmk, e->authenticator_pmk, PMK_LEN) != 0) {
345			printf("WARNING: PMK mismatch\n");
346			wpa_hexdump(MSG_DEBUG, "PMK from AS",
347				    e->authenticator_pmk, PMK_LEN);
348		} else if (e->radius_access_accept_received)
349			ret = 0;
350	} else if (e->authenticator_pmk_len == 16 &&
351		   eapol_sm_get_key(e->wpa_s->eapol, pmk, 16) == 0) {
352		wpa_hexdump(MSG_DEBUG, "LEAP PMK from EAPOL", pmk, 16);
353		if (os_memcmp(pmk, e->authenticator_pmk, 16) != 0) {
354			printf("WARNING: PMK mismatch\n");
355			wpa_hexdump(MSG_DEBUG, "PMK from AS",
356				    e->authenticator_pmk, 16);
357		} else if (e->radius_access_accept_received)
358			ret = 0;
359	} else if (e->radius_access_accept_received && e->no_mppe_keys) {
360		/* No keying material expected */
361		ret = 0;
362	}
363
364	if (ret && !e->no_mppe_keys)
365		e->num_mppe_mismatch++;
366	else if (!e->no_mppe_keys)
367		e->num_mppe_ok++;
368
369	return ret;
370}
371
372
373static void eapol_sm_cb(struct eapol_sm *eapol, int success, void *ctx)
374{
375	struct eapol_test_data *e = ctx;
376	printf("eapol_sm_cb: success=%d\n", success);
377	e->eapol_test_num_reauths--;
378	if (e->eapol_test_num_reauths < 0)
379		eloop_terminate();
380	else {
381		eapol_test_compare_pmk(e);
382		eloop_register_timeout(0, 100000, eapol_sm_reauth, e, NULL);
383	}
384}
385
386
387static void eapol_test_cert_cb(void *ctx, int depth, const char *subject,
388			       const char *cert_hash,
389			       const struct wpabuf *cert)
390{
391	struct eapol_test_data *e = ctx;
392
393	wpa_msg(e->wpa_s, MSG_INFO, WPA_EVENT_EAP_PEER_CERT
394		"depth=%d subject='%s'%s%s",
395		depth, subject,
396		cert_hash ? " hash=" : "",
397		cert_hash ? cert_hash : "");
398
399	if (cert) {
400		char *cert_hex;
401		size_t len = wpabuf_len(cert) * 2 + 1;
402		cert_hex = os_malloc(len);
403		if (cert_hex) {
404			wpa_snprintf_hex(cert_hex, len, wpabuf_head(cert),
405					 wpabuf_len(cert));
406			wpa_msg_ctrl(e->wpa_s, MSG_INFO,
407				     WPA_EVENT_EAP_PEER_CERT
408				     "depth=%d subject='%s' cert=%s",
409				     depth, subject, cert_hex);
410			os_free(cert_hex);
411		}
412	}
413}
414
415
416static int test_eapol(struct eapol_test_data *e, struct wpa_supplicant *wpa_s,
417		      struct wpa_ssid *ssid)
418{
419	struct eapol_config eapol_conf;
420	struct eapol_ctx *ctx;
421
422	ctx = os_zalloc(sizeof(*ctx));
423	if (ctx == NULL) {
424		printf("Failed to allocate EAPOL context.\n");
425		return -1;
426	}
427	ctx->ctx = wpa_s;
428	ctx->msg_ctx = wpa_s;
429	ctx->scard_ctx = wpa_s->scard;
430	ctx->cb = eapol_sm_cb;
431	ctx->cb_ctx = e;
432	ctx->eapol_send_ctx = wpa_s;
433	ctx->preauth = 0;
434	ctx->eapol_done_cb = eapol_test_eapol_done_cb;
435	ctx->eapol_send = eapol_test_eapol_send;
436	ctx->set_config_blob = eapol_test_set_config_blob;
437	ctx->get_config_blob = eapol_test_get_config_blob;
438	ctx->opensc_engine_path = wpa_s->conf->opensc_engine_path;
439	ctx->pkcs11_engine_path = wpa_s->conf->pkcs11_engine_path;
440	ctx->pkcs11_module_path = wpa_s->conf->pkcs11_module_path;
441	ctx->cert_cb = eapol_test_cert_cb;
442
443	wpa_s->eapol = eapol_sm_init(ctx);
444	if (wpa_s->eapol == NULL) {
445		os_free(ctx);
446		printf("Failed to initialize EAPOL state machines.\n");
447		return -1;
448	}
449
450	wpa_s->current_ssid = ssid;
451	os_memset(&eapol_conf, 0, sizeof(eapol_conf));
452	eapol_conf.accept_802_1x_keys = 1;
453	eapol_conf.required_keys = 0;
454	eapol_conf.fast_reauth = wpa_s->conf->fast_reauth;
455	eapol_conf.workaround = ssid->eap_workaround;
456	eapol_sm_notify_config(wpa_s->eapol, &ssid->eap, &eapol_conf);
457	eapol_sm_register_scard_ctx(wpa_s->eapol, wpa_s->scard);
458
459
460	eapol_sm_notify_portValid(wpa_s->eapol, FALSE);
461	/* 802.1X::portControl = Auto */
462	eapol_sm_notify_portEnabled(wpa_s->eapol, TRUE);
463
464	return 0;
465}
466
467
468static void test_eapol_clean(struct eapol_test_data *e,
469			     struct wpa_supplicant *wpa_s)
470{
471	struct extra_radius_attr *p, *prev;
472
473	radius_client_deinit(e->radius);
474	os_free(e->last_eap_radius);
475	radius_msg_free(e->last_recv_radius);
476	e->last_recv_radius = NULL;
477	os_free(e->eap_identity);
478	e->eap_identity = NULL;
479	eapol_sm_deinit(wpa_s->eapol);
480	wpa_s->eapol = NULL;
481	if (e->radius_conf && e->radius_conf->auth_server) {
482		os_free(e->radius_conf->auth_server->shared_secret);
483		os_free(e->radius_conf->auth_server);
484	}
485	os_free(e->radius_conf);
486	e->radius_conf = NULL;
487	scard_deinit(wpa_s->scard);
488	if (wpa_s->ctrl_iface) {
489		wpa_supplicant_ctrl_iface_deinit(wpa_s->ctrl_iface);
490		wpa_s->ctrl_iface = NULL;
491	}
492	wpa_config_free(wpa_s->conf);
493
494	p = e->extra_attrs;
495	while (p) {
496		prev = p;
497		p = p->next;
498		os_free(prev);
499	}
500}
501
502
503static void send_eap_request_identity(void *eloop_ctx, void *timeout_ctx)
504{
505	struct wpa_supplicant *wpa_s = eloop_ctx;
506	u8 buf[100], *pos;
507	struct ieee802_1x_hdr *hdr;
508	struct eap_hdr *eap;
509
510	hdr = (struct ieee802_1x_hdr *) buf;
511	hdr->version = EAPOL_VERSION;
512	hdr->type = IEEE802_1X_TYPE_EAP_PACKET;
513	hdr->length = htons(5);
514
515	eap = (struct eap_hdr *) (hdr + 1);
516	eap->code = EAP_CODE_REQUEST;
517	eap->identifier = 0;
518	eap->length = htons(5);
519	pos = (u8 *) (eap + 1);
520	*pos = EAP_TYPE_IDENTITY;
521
522	printf("Sending fake EAP-Request-Identity\n");
523	eapol_sm_rx_eapol(wpa_s->eapol, wpa_s->bssid, buf,
524			  sizeof(*hdr) + 5);
525}
526
527
528static void eapol_test_timeout(void *eloop_ctx, void *timeout_ctx)
529{
530	struct eapol_test_data *e = eloop_ctx;
531	printf("EAPOL test timed out\n");
532	e->auth_timed_out = 1;
533	eloop_terminate();
534}
535
536
537static char *eap_type_text(u8 type)
538{
539	switch (type) {
540	case EAP_TYPE_IDENTITY: return "Identity";
541	case EAP_TYPE_NOTIFICATION: return "Notification";
542	case EAP_TYPE_NAK: return "Nak";
543	case EAP_TYPE_TLS: return "TLS";
544	case EAP_TYPE_TTLS: return "TTLS";
545	case EAP_TYPE_PEAP: return "PEAP";
546	case EAP_TYPE_SIM: return "SIM";
547	case EAP_TYPE_GTC: return "GTC";
548	case EAP_TYPE_MD5: return "MD5";
549	case EAP_TYPE_OTP: return "OTP";
550	case EAP_TYPE_FAST: return "FAST";
551	case EAP_TYPE_SAKE: return "SAKE";
552	case EAP_TYPE_PSK: return "PSK";
553	default: return "Unknown";
554	}
555}
556
557
558static void ieee802_1x_decapsulate_radius(struct eapol_test_data *e)
559{
560	u8 *eap;
561	size_t len;
562	struct eap_hdr *hdr;
563	int eap_type = -1;
564	char buf[64];
565	struct radius_msg *msg;
566
567	if (e->last_recv_radius == NULL)
568		return;
569
570	msg = e->last_recv_radius;
571
572	eap = radius_msg_get_eap(msg, &len);
573	if (eap == NULL) {
574		/* draft-aboba-radius-rfc2869bis-20.txt, Chap. 2.6.3:
575		 * RADIUS server SHOULD NOT send Access-Reject/no EAP-Message
576		 * attribute */
577		wpa_printf(MSG_DEBUG, "could not extract "
578			       "EAP-Message from RADIUS message");
579		os_free(e->last_eap_radius);
580		e->last_eap_radius = NULL;
581		e->last_eap_radius_len = 0;
582		return;
583	}
584
585	if (len < sizeof(*hdr)) {
586		wpa_printf(MSG_DEBUG, "too short EAP packet "
587			       "received from authentication server");
588		os_free(eap);
589		return;
590	}
591
592	if (len > sizeof(*hdr))
593		eap_type = eap[sizeof(*hdr)];
594
595	hdr = (struct eap_hdr *) eap;
596	switch (hdr->code) {
597	case EAP_CODE_REQUEST:
598		os_snprintf(buf, sizeof(buf), "EAP-Request-%s (%d)",
599			    eap_type >= 0 ? eap_type_text(eap_type) : "??",
600			    eap_type);
601		break;
602	case EAP_CODE_RESPONSE:
603		os_snprintf(buf, sizeof(buf), "EAP Response-%s (%d)",
604			    eap_type >= 0 ? eap_type_text(eap_type) : "??",
605			    eap_type);
606		break;
607	case EAP_CODE_SUCCESS:
608		os_strlcpy(buf, "EAP Success", sizeof(buf));
609		/* LEAP uses EAP Success within an authentication, so must not
610		 * stop here with eloop_terminate(); */
611		break;
612	case EAP_CODE_FAILURE:
613		os_strlcpy(buf, "EAP Failure", sizeof(buf));
614		eloop_terminate();
615		break;
616	default:
617		os_strlcpy(buf, "unknown EAP code", sizeof(buf));
618		wpa_hexdump(MSG_DEBUG, "Decapsulated EAP packet", eap, len);
619		break;
620	}
621	wpa_printf(MSG_DEBUG, "decapsulated EAP packet (code=%d "
622		       "id=%d len=%d) from RADIUS server: %s",
623		      hdr->code, hdr->identifier, ntohs(hdr->length), buf);
624
625	/* sta->eapol_sm->be_auth.idFromServer = hdr->identifier; */
626
627	os_free(e->last_eap_radius);
628	e->last_eap_radius = eap;
629	e->last_eap_radius_len = len;
630
631	{
632		struct ieee802_1x_hdr *dot1x;
633		dot1x = os_malloc(sizeof(*dot1x) + len);
634		assert(dot1x != NULL);
635		dot1x->version = EAPOL_VERSION;
636		dot1x->type = IEEE802_1X_TYPE_EAP_PACKET;
637		dot1x->length = htons(len);
638		os_memcpy((u8 *) (dot1x + 1), eap, len);
639		eapol_sm_rx_eapol(e->wpa_s->eapol, e->wpa_s->bssid,
640				  (u8 *) dot1x, sizeof(*dot1x) + len);
641		os_free(dot1x);
642	}
643}
644
645
646static void ieee802_1x_get_keys(struct eapol_test_data *e,
647				struct radius_msg *msg, struct radius_msg *req,
648				const u8 *shared_secret,
649				size_t shared_secret_len)
650{
651	struct radius_ms_mppe_keys *keys;
652
653	keys = radius_msg_get_ms_keys(msg, req, shared_secret,
654				      shared_secret_len);
655	if (keys && keys->send == NULL && keys->recv == NULL) {
656		os_free(keys);
657		keys = radius_msg_get_cisco_keys(msg, req, shared_secret,
658						 shared_secret_len);
659	}
660
661	if (keys) {
662		if (keys->send) {
663			wpa_hexdump(MSG_DEBUG, "MS-MPPE-Send-Key (sign)",
664				    keys->send, keys->send_len);
665		}
666		if (keys->recv) {
667			wpa_hexdump(MSG_DEBUG, "MS-MPPE-Recv-Key (crypt)",
668				    keys->recv, keys->recv_len);
669			e->authenticator_pmk_len =
670				keys->recv_len > PMK_LEN ? PMK_LEN :
671				keys->recv_len;
672			os_memcpy(e->authenticator_pmk, keys->recv,
673				  e->authenticator_pmk_len);
674			if (e->authenticator_pmk_len == 16 && keys->send &&
675			    keys->send_len == 16) {
676				/* MS-CHAP-v2 derives 16 octet keys */
677				wpa_printf(MSG_DEBUG, "Use MS-MPPE-Send-Key "
678					   "to extend PMK to 32 octets");
679				os_memcpy(e->authenticator_pmk +
680					  e->authenticator_pmk_len,
681					  keys->send, keys->send_len);
682				e->authenticator_pmk_len += keys->send_len;
683			}
684		}
685
686		os_free(keys->send);
687		os_free(keys->recv);
688		os_free(keys);
689	}
690}
691
692
693/* Process the RADIUS frames from Authentication Server */
694static RadiusRxResult
695ieee802_1x_receive_auth(struct radius_msg *msg, struct radius_msg *req,
696			const u8 *shared_secret, size_t shared_secret_len,
697			void *data)
698{
699	struct eapol_test_data *e = data;
700	struct radius_hdr *hdr = radius_msg_get_hdr(msg);
701
702	/* RFC 2869, Ch. 5.13: valid Message-Authenticator attribute MUST be
703	 * present when packet contains an EAP-Message attribute */
704	if (hdr->code == RADIUS_CODE_ACCESS_REJECT &&
705	    radius_msg_get_attr(msg, RADIUS_ATTR_MESSAGE_AUTHENTICATOR, NULL,
706				0) < 0 &&
707	    radius_msg_get_attr(msg, RADIUS_ATTR_EAP_MESSAGE, NULL, 0) < 0) {
708		wpa_printf(MSG_DEBUG, "Allowing RADIUS "
709			      "Access-Reject without Message-Authenticator "
710			      "since it does not include EAP-Message\n");
711	} else if (radius_msg_verify(msg, shared_secret, shared_secret_len,
712				     req, 1)) {
713		printf("Incoming RADIUS packet did not have correct "
714		       "Message-Authenticator - dropped\n");
715		return RADIUS_RX_UNKNOWN;
716	}
717
718	if (hdr->code != RADIUS_CODE_ACCESS_ACCEPT &&
719	    hdr->code != RADIUS_CODE_ACCESS_REJECT &&
720	    hdr->code != RADIUS_CODE_ACCESS_CHALLENGE) {
721		printf("Unknown RADIUS message code\n");
722		return RADIUS_RX_UNKNOWN;
723	}
724
725	e->radius_identifier = -1;
726	wpa_printf(MSG_DEBUG, "RADIUS packet matching with station");
727
728	radius_msg_free(e->last_recv_radius);
729	e->last_recv_radius = msg;
730
731	switch (hdr->code) {
732	case RADIUS_CODE_ACCESS_ACCEPT:
733		e->radius_access_accept_received = 1;
734		ieee802_1x_get_keys(e, msg, req, shared_secret,
735				    shared_secret_len);
736		break;
737	case RADIUS_CODE_ACCESS_REJECT:
738		e->radius_access_reject_received = 1;
739		break;
740	}
741
742	ieee802_1x_decapsulate_radius(e);
743
744	if ((hdr->code == RADIUS_CODE_ACCESS_ACCEPT &&
745	     e->eapol_test_num_reauths < 0) ||
746	    hdr->code == RADIUS_CODE_ACCESS_REJECT) {
747		eloop_terminate();
748	}
749
750	return RADIUS_RX_QUEUED;
751}
752
753
754static void wpa_init_conf(struct eapol_test_data *e,
755			  struct wpa_supplicant *wpa_s, const char *authsrv,
756			  int port, const char *secret,
757			  const char *cli_addr)
758{
759	struct hostapd_radius_server *as;
760	int res;
761
762	wpa_s->bssid[5] = 1;
763	os_memcpy(wpa_s->own_addr, e->own_addr, ETH_ALEN);
764	e->own_ip_addr.s_addr = htonl((127 << 24) | 1);
765	os_strlcpy(wpa_s->ifname, "test", sizeof(wpa_s->ifname));
766
767	e->radius_conf = os_zalloc(sizeof(struct hostapd_radius_servers));
768	assert(e->radius_conf != NULL);
769	e->radius_conf->num_auth_servers = 1;
770	as = os_zalloc(sizeof(struct hostapd_radius_server));
771	assert(as != NULL);
772#if defined(CONFIG_NATIVE_WINDOWS) || defined(CONFIG_ANSI_C_EXTRA)
773	{
774		int a[4];
775		u8 *pos;
776		sscanf(authsrv, "%d.%d.%d.%d", &a[0], &a[1], &a[2], &a[3]);
777		pos = (u8 *) &as->addr.u.v4;
778		*pos++ = a[0];
779		*pos++ = a[1];
780		*pos++ = a[2];
781		*pos++ = a[3];
782	}
783#else /* CONFIG_NATIVE_WINDOWS or CONFIG_ANSI_C_EXTRA */
784	inet_aton(authsrv, &as->addr.u.v4);
785#endif /* CONFIG_NATIVE_WINDOWS or CONFIG_ANSI_C_EXTRA */
786	as->addr.af = AF_INET;
787	as->port = port;
788	as->shared_secret = (u8 *) os_strdup(secret);
789	as->shared_secret_len = os_strlen(secret);
790	e->radius_conf->auth_server = as;
791	e->radius_conf->auth_servers = as;
792	e->radius_conf->msg_dumps = 1;
793	if (cli_addr) {
794		if (hostapd_parse_ip_addr(cli_addr,
795					  &e->radius_conf->client_addr) == 0)
796			e->radius_conf->force_client_addr = 1;
797		else {
798			wpa_printf(MSG_ERROR, "Invalid IP address '%s'",
799				   cli_addr);
800			assert(0);
801		}
802	}
803
804	e->radius = radius_client_init(wpa_s, e->radius_conf);
805	assert(e->radius != NULL);
806
807	res = radius_client_register(e->radius, RADIUS_AUTH,
808				     ieee802_1x_receive_auth, e);
809	assert(res == 0);
810}
811
812
813static int scard_test(void)
814{
815	struct scard_data *scard;
816	size_t len;
817	char imsi[20];
818	unsigned char _rand[16];
819#ifdef PCSC_FUNCS
820	unsigned char sres[4];
821	unsigned char kc[8];
822#endif /* PCSC_FUNCS */
823#define num_triplets 5
824	unsigned char rand_[num_triplets][16];
825	unsigned char sres_[num_triplets][4];
826	unsigned char kc_[num_triplets][8];
827	int i, res;
828	size_t j;
829
830#define AKA_RAND_LEN 16
831#define AKA_AUTN_LEN 16
832#define AKA_AUTS_LEN 14
833#define RES_MAX_LEN 16
834#define IK_LEN 16
835#define CK_LEN 16
836	unsigned char aka_rand[AKA_RAND_LEN];
837	unsigned char aka_autn[AKA_AUTN_LEN];
838	unsigned char aka_auts[AKA_AUTS_LEN];
839	unsigned char aka_res[RES_MAX_LEN];
840	size_t aka_res_len;
841	unsigned char aka_ik[IK_LEN];
842	unsigned char aka_ck[CK_LEN];
843
844	scard = scard_init(SCARD_TRY_BOTH);
845	if (scard == NULL)
846		return -1;
847	if (scard_set_pin(scard, "1234")) {
848		wpa_printf(MSG_WARNING, "PIN validation failed");
849		scard_deinit(scard);
850		return -1;
851	}
852
853	len = sizeof(imsi);
854	if (scard_get_imsi(scard, imsi, &len))
855		goto failed;
856	wpa_hexdump_ascii(MSG_DEBUG, "SCARD: IMSI", (u8 *) imsi, len);
857	/* NOTE: Permanent Username: 1 | IMSI */
858
859	os_memset(_rand, 0, sizeof(_rand));
860	if (scard_gsm_auth(scard, _rand, sres, kc))
861		goto failed;
862
863	os_memset(_rand, 0xff, sizeof(_rand));
864	if (scard_gsm_auth(scard, _rand, sres, kc))
865		goto failed;
866
867	for (i = 0; i < num_triplets; i++) {
868		os_memset(rand_[i], i, sizeof(rand_[i]));
869		if (scard_gsm_auth(scard, rand_[i], sres_[i], kc_[i]))
870			goto failed;
871	}
872
873	for (i = 0; i < num_triplets; i++) {
874		printf("1");
875		for (j = 0; j < len; j++)
876			printf("%c", imsi[j]);
877		printf(",");
878		for (j = 0; j < 16; j++)
879			printf("%02X", rand_[i][j]);
880		printf(",");
881		for (j = 0; j < 4; j++)
882			printf("%02X", sres_[i][j]);
883		printf(",");
884		for (j = 0; j < 8; j++)
885			printf("%02X", kc_[i][j]);
886		printf("\n");
887	}
888
889	wpa_printf(MSG_DEBUG, "Trying to use UMTS authentication");
890
891	/* seq 39 (0x28) */
892	os_memset(aka_rand, 0xaa, 16);
893	os_memcpy(aka_autn, "\x86\x71\x31\xcb\xa2\xfc\x61\xdf"
894		  "\xa3\xb3\x97\x9d\x07\x32\xa2\x12", 16);
895
896	res = scard_umts_auth(scard, aka_rand, aka_autn, aka_res, &aka_res_len,
897			      aka_ik, aka_ck, aka_auts);
898	if (res == 0) {
899		wpa_printf(MSG_DEBUG, "UMTS auth completed successfully");
900		wpa_hexdump(MSG_DEBUG, "RES", aka_res, aka_res_len);
901		wpa_hexdump(MSG_DEBUG, "IK", aka_ik, IK_LEN);
902		wpa_hexdump(MSG_DEBUG, "CK", aka_ck, CK_LEN);
903	} else if (res == -2) {
904		wpa_printf(MSG_DEBUG, "UMTS auth resulted in synchronization "
905			   "failure");
906		wpa_hexdump(MSG_DEBUG, "AUTS", aka_auts, AKA_AUTS_LEN);
907	} else {
908		wpa_printf(MSG_DEBUG, "UMTS auth failed");
909	}
910
911failed:
912	scard_deinit(scard);
913
914	return 0;
915#undef num_triplets
916}
917
918
919static int scard_get_triplets(int argc, char *argv[])
920{
921	struct scard_data *scard;
922	size_t len;
923	char imsi[20];
924	unsigned char _rand[16];
925	unsigned char sres[4];
926	unsigned char kc[8];
927	int num_triplets;
928	int i;
929	size_t j;
930
931	if (argc < 2 || ((num_triplets = atoi(argv[1])) <= 0)) {
932		printf("invalid parameters for sim command\n");
933		return -1;
934	}
935
936	if (argc <= 2 || os_strcmp(argv[2], "debug") != 0) {
937		/* disable debug output */
938		wpa_debug_level = 99;
939	}
940
941	scard = scard_init(SCARD_GSM_SIM_ONLY);
942	if (scard == NULL) {
943		printf("Failed to open smartcard connection\n");
944		return -1;
945	}
946	if (scard_set_pin(scard, argv[0])) {
947		wpa_printf(MSG_WARNING, "PIN validation failed");
948		scard_deinit(scard);
949		return -1;
950	}
951
952	len = sizeof(imsi);
953	if (scard_get_imsi(scard, imsi, &len)) {
954		scard_deinit(scard);
955		return -1;
956	}
957
958	for (i = 0; i < num_triplets; i++) {
959		os_memset(_rand, i, sizeof(_rand));
960		if (scard_gsm_auth(scard, _rand, sres, kc))
961			break;
962
963		/* IMSI:Kc:SRES:RAND */
964		for (j = 0; j < len; j++)
965			printf("%c", imsi[j]);
966		printf(":");
967		for (j = 0; j < 8; j++)
968			printf("%02X", kc[j]);
969		printf(":");
970		for (j = 0; j < 4; j++)
971			printf("%02X", sres[j]);
972		printf(":");
973		for (j = 0; j < 16; j++)
974			printf("%02X", _rand[j]);
975		printf("\n");
976	}
977
978	scard_deinit(scard);
979
980	return 0;
981}
982
983
984static void eapol_test_terminate(int sig, void *signal_ctx)
985{
986	struct wpa_supplicant *wpa_s = signal_ctx;
987	wpa_msg(wpa_s, MSG_INFO, "Signal %d received - terminating", sig);
988	eloop_terminate();
989}
990
991
992static void usage(void)
993{
994	printf("usage:\n"
995	       "eapol_test [-nWS] -c<conf> [-a<AS IP>] [-p<AS port>] "
996	       "[-s<AS secret>]\\\n"
997	       "           [-r<count>] [-t<timeout>] [-C<Connect-Info>] \\\n"
998	       "           [-M<client MAC address>] \\\n"
999	       "           [-N<attr spec>] \\\n"
1000	       "           [-A<client IP>]\n"
1001	       "eapol_test scard\n"
1002	       "eapol_test sim <PIN> <num triplets> [debug]\n"
1003	       "\n");
1004	printf("options:\n"
1005	       "  -c<conf> = configuration file\n"
1006	       "  -a<AS IP> = IP address of the authentication server, "
1007	       "default 127.0.0.1\n"
1008	       "  -p<AS port> = UDP port of the authentication server, "
1009	       "default 1812\n"
1010	       "  -s<AS secret> = shared secret with the authentication "
1011	       "server, default 'radius'\n"
1012	       "  -A<client IP> = IP address of the client, default: select "
1013	       "automatically\n"
1014	       "  -r<count> = number of re-authentications\n"
1015	       "  -W = wait for a control interface monitor before starting\n"
1016	       "  -S = save configuration after authentication\n"
1017	       "  -n = no MPPE keys expected\n"
1018	       "  -t<timeout> = sets timeout in seconds (default: 30 s)\n"
1019	       "  -C<Connect-Info> = RADIUS Connect-Info (default: "
1020	       "CONNECT 11Mbps 802.11b)\n"
1021	       "  -M<client MAC address> = Set own MAC address "
1022	       "(Calling-Station-Id,\n"
1023	       "                           default: 02:00:00:00:00:01)\n"
1024	       "  -N<attr spec> = send arbitrary attribute specified by:\n"
1025	       "                  attr_id:syntax:value or attr_id\n"
1026	       "                  attr_id - number id of the attribute\n"
1027	       "                  syntax - one of: s, d, x\n"
1028	       "                     s = string\n"
1029	       "                     d = integer\n"
1030	       "                     x = octet string\n"
1031	       "                  value - attribute value.\n"
1032	       "       When only attr_id is specified, NULL will be used as "
1033	       "value.\n"
1034	       "       Multiple attributes can be specified by using the "
1035	       "option several times.\n");
1036}
1037
1038
1039int main(int argc, char *argv[])
1040{
1041	struct wpa_supplicant wpa_s;
1042	int c, ret = 1, wait_for_monitor = 0, save_config = 0;
1043	char *as_addr = "127.0.0.1";
1044	int as_port = 1812;
1045	char *as_secret = "radius";
1046	char *cli_addr = NULL;
1047	char *conf = NULL;
1048	int timeout = 30;
1049	char *pos;
1050	struct extra_radius_attr *p = NULL, *p1;
1051
1052	if (os_program_init())
1053		return -1;
1054
1055	hostapd_logger_register_cb(hostapd_logger_cb);
1056
1057	os_memset(&eapol_test, 0, sizeof(eapol_test));
1058	eapol_test.connect_info = "CONNECT 11Mbps 802.11b";
1059	os_memcpy(eapol_test.own_addr, "\x02\x00\x00\x00\x00\x01", ETH_ALEN);
1060
1061	wpa_debug_level = 0;
1062	wpa_debug_show_keys = 1;
1063
1064	for (;;) {
1065		c = getopt(argc, argv, "a:A:c:C:M:nN:p:r:s:St:W");
1066		if (c < 0)
1067			break;
1068		switch (c) {
1069		case 'a':
1070			as_addr = optarg;
1071			break;
1072		case 'A':
1073			cli_addr = optarg;
1074			break;
1075		case 'c':
1076			conf = optarg;
1077			break;
1078		case 'C':
1079			eapol_test.connect_info = optarg;
1080			break;
1081		case 'M':
1082			if (hwaddr_aton(optarg, eapol_test.own_addr)) {
1083				usage();
1084				return -1;
1085			}
1086			break;
1087		case 'n':
1088			eapol_test.no_mppe_keys++;
1089			break;
1090		case 'p':
1091			as_port = atoi(optarg);
1092			break;
1093		case 'r':
1094			eapol_test.eapol_test_num_reauths = atoi(optarg);
1095			break;
1096		case 's':
1097			as_secret = optarg;
1098			break;
1099		case 'S':
1100			save_config++;
1101			break;
1102		case 't':
1103			timeout = atoi(optarg);
1104			break;
1105		case 'W':
1106			wait_for_monitor++;
1107			break;
1108		case 'N':
1109			p1 = os_zalloc(sizeof(p1));
1110			if (p1 == NULL)
1111				break;
1112			if (!p)
1113				eapol_test.extra_attrs = p1;
1114			else
1115				p->next = p1;
1116			p = p1;
1117
1118			p->type = atoi(optarg);
1119			pos = os_strchr(optarg, ':');
1120			if (pos == NULL) {
1121				p->syntax = 'n';
1122				p->data = NULL;
1123				break;
1124			}
1125
1126			pos++;
1127			if (pos[0] == '\0' || pos[1] != ':') {
1128				printf("Incorrect format of attribute "
1129				       "specification\n");
1130				break;
1131			}
1132
1133			p->syntax = pos[0];
1134			p->data = pos + 2;
1135			break;
1136		default:
1137			usage();
1138			return -1;
1139		}
1140	}
1141
1142	if (argc > optind && os_strcmp(argv[optind], "scard") == 0) {
1143		return scard_test();
1144	}
1145
1146	if (argc > optind && os_strcmp(argv[optind], "sim") == 0) {
1147		return scard_get_triplets(argc - optind - 1,
1148					  &argv[optind + 1]);
1149	}
1150
1151	if (conf == NULL) {
1152		usage();
1153		printf("Configuration file is required.\n");
1154		return -1;
1155	}
1156
1157	if (eap_register_methods()) {
1158		wpa_printf(MSG_ERROR, "Failed to register EAP methods");
1159		return -1;
1160	}
1161
1162	if (eloop_init()) {
1163		wpa_printf(MSG_ERROR, "Failed to initialize event loop");
1164		return -1;
1165	}
1166
1167	os_memset(&wpa_s, 0, sizeof(wpa_s));
1168	eapol_test.wpa_s = &wpa_s;
1169	wpa_s.conf = wpa_config_read(conf);
1170	if (wpa_s.conf == NULL) {
1171		printf("Failed to parse configuration file '%s'.\n", conf);
1172		return -1;
1173	}
1174	if (wpa_s.conf->ssid == NULL) {
1175		printf("No networks defined.\n");
1176		return -1;
1177	}
1178
1179	wpa_init_conf(&eapol_test, &wpa_s, as_addr, as_port, as_secret,
1180		      cli_addr);
1181	wpa_s.ctrl_iface = wpa_supplicant_ctrl_iface_init(&wpa_s);
1182	if (wpa_s.ctrl_iface == NULL) {
1183		printf("Failed to initialize control interface '%s'.\n"
1184		       "You may have another eapol_test process already "
1185		       "running or the file was\n"
1186		       "left by an unclean termination of eapol_test in "
1187		       "which case you will need\n"
1188		       "to manually remove this file before starting "
1189		       "eapol_test again.\n",
1190		       wpa_s.conf->ctrl_interface);
1191		return -1;
1192	}
1193	if (wpa_supplicant_scard_init(&wpa_s, wpa_s.conf->ssid))
1194		return -1;
1195
1196	if (test_eapol(&eapol_test, &wpa_s, wpa_s.conf->ssid))
1197		return -1;
1198
1199	if (wait_for_monitor)
1200		wpa_supplicant_ctrl_iface_wait(wpa_s.ctrl_iface);
1201
1202	eloop_register_timeout(timeout, 0, eapol_test_timeout, &eapol_test,
1203			       NULL);
1204	eloop_register_timeout(0, 0, send_eap_request_identity, &wpa_s, NULL);
1205	eloop_register_signal_terminate(eapol_test_terminate, &wpa_s);
1206	eloop_register_signal_reconfig(eapol_test_terminate, &wpa_s);
1207	eloop_run();
1208
1209	eloop_cancel_timeout(eapol_test_timeout, &eapol_test, NULL);
1210	eloop_cancel_timeout(eapol_sm_reauth, &eapol_test, NULL);
1211
1212	if (eapol_test_compare_pmk(&eapol_test) == 0 ||
1213	    eapol_test.no_mppe_keys)
1214		ret = 0;
1215	if (eapol_test.auth_timed_out)
1216		ret = -2;
1217	if (eapol_test.radius_access_reject_received)
1218		ret = -3;
1219
1220	if (save_config)
1221		wpa_config_write(conf, wpa_s.conf);
1222
1223	test_eapol_clean(&eapol_test, &wpa_s);
1224
1225	eap_peer_unregister_methods();
1226#ifdef CONFIG_AP
1227	eap_server_unregister_methods();
1228#endif /* CONFIG_AP */
1229
1230	eloop_destroy();
1231
1232	printf("MPPE keys OK: %d  mismatch: %d\n",
1233	       eapol_test.num_mppe_ok, eapol_test.num_mppe_mismatch);
1234	if (eapol_test.num_mppe_mismatch)
1235		ret = -4;
1236	if (ret)
1237		printf("FAILURE\n");
1238	else
1239		printf("SUCCESS\n");
1240
1241	os_program_deinit();
1242
1243	return ret;
1244}
1245