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