18d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/*
28d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * WPA Supplicant - test code
3051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt * Copyright (c) 2003-2013, Jouni Malinen <j@w1.fi>
48d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
5c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * This software may be distributed under the terms of the BSD license.
6c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * See README for more details.
78d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
88d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * IEEE 802.1X Supplicant test code (to be used in place of wpa_supplicant.c.
98d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Not used in production version.
108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "includes.h"
138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include <assert.h>
148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "common.h"
1661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#include "utils/ext_password.h"
17d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt#include "common/version.h"
188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "config.h"
198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "eapol_supp/eapol_supp_sm.h"
208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "eap_peer/eap.h"
218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "eap_server/eap_methods.h"
228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "eloop.h"
231f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#include "utils/base64.h"
248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "rsn_supp/wpa.h"
258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "wpa_supplicant_i.h"
268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "radius/radius.h"
278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "radius/radius_client.h"
28c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt#include "common/wpa_ctrl.h"
298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "ctrl_iface.h"
308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "pcsc_funcs.h"
31051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt#include "wpas_glue.h"
328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
341d755d025b206e22b06aeb322e25a79f98ca7777Dmitry Shmidtconst struct wpa_driver_ops *const wpa_drivers[] = { NULL };
358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct extra_radius_attr {
388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 type;
398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char syntax;
408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char *data;
418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct extra_radius_attr *next;
428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt};
438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct eapol_test_data {
458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_supplicant *wpa_s;
468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int eapol_test_num_reauths;
488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int no_mppe_keys;
498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int num_mppe_ok, num_mppe_mismatch;
505a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	int req_eap_key_name;
518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 radius_identifier;
538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct radius_msg *last_recv_radius;
548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct in_addr own_ip_addr;
558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct radius_client_data *radius;
568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct hostapd_radius_servers *radius_conf;
578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	 /* last received EAP Response from Authentication Server */
5961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	struct wpabuf *last_eap_radius;
608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 authenticator_pmk[PMK_LEN];
628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t authenticator_pmk_len;
635a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	u8 authenticator_eap_key_name[256];
645a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	size_t authenticator_eap_key_name_len;
658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int radius_access_accept_received;
668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int radius_access_reject_received;
678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int auth_timed_out;
688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 *eap_identity;
708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t eap_identity_len;
718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char *connect_info;
738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 own_addr[ETH_ALEN];
748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct extra_radius_attr *extra_attrs;
751f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
761f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	FILE *server_cert_file;
772271d3fdd5982d0e5e81cf9999a861bba933eacbDmitry Shmidt
782271d3fdd5982d0e5e81cf9999a861bba933eacbDmitry Shmidt	const char *pcsc_reader;
792271d3fdd5982d0e5e81cf9999a861bba933eacbDmitry Shmidt	const char *pcsc_pin;
80d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
81d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	unsigned int ctrl_iface:1;
82d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	unsigned int id_req_sent:1;
838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt};
848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct eapol_test_data eapol_test;
868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void send_eap_request_identity(void *eloop_ctx, void *timeout_ctx);
898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void hostapd_logger_cb(void *ctx, const u8 *addr, unsigned int module,
928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			      int level, const char *txt, size_t len)
938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (addr)
958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "STA " MACSTR ": %s\n",
968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   MAC2STR(addr), txt);
978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else
988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "%s", txt);
998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int add_extra_attr(struct radius_msg *msg,
1038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  struct extra_radius_attr *attr)
1048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t len;
1068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char *pos;
1078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u32 val;
108a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	char buf[RADIUS_MAX_ATTR_LEN + 1];
1098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	switch (attr->syntax) {
1118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case 's':
1128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_snprintf(buf, sizeof(buf), "%s", attr->data);
1138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		len = os_strlen(buf);
1148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
1158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case 'n':
1168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		buf[0] = '\0';
1178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		len = 1;
1188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
1198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case 'x':
1208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos = attr->data;
1218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (pos[0] == '0' && pos[1] == 'x')
1228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			pos += 2;
1238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		len = os_strlen(pos);
124a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		if ((len & 1) || (len / 2) > RADIUS_MAX_ATTR_LEN) {
1258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			printf("Invalid extra attribute hexstring\n");
1268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
1278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
1288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		len /= 2;
1298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (hexstr2bin(pos, (u8 *) buf, len) < 0) {
1308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			printf("Invalid extra attribute hexstring\n");
1318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
1328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
1338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
1348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case 'd':
1358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		val = htonl(atoi(attr->data));
1368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(buf, &val, 4);
1378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		len = 4;
1388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
1398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	default:
1408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		printf("Incorrect extra attribute syntax specification\n");
1418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
1428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!radius_msg_add_attr(msg, attr->type, (u8 *) buf, len)) {
1458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		printf("Could not add attribute %d\n", attr->type);
1468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
1478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
1508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int add_extra_attrs(struct radius_msg *msg,
1548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   struct extra_radius_attr *attrs)
1558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct extra_radius_attr *p;
1578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (p = attrs; p; p = p->next) {
1588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (add_extra_attr(msg, p) < 0)
1598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
1608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
1628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct extra_radius_attr *
1668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtfind_extra_attr(struct extra_radius_attr *attrs, u8 type)
1678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct extra_radius_attr *p;
1698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (p = attrs; p; p = p->next) {
1708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (p->type == type)
1718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return p;
1728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return NULL;
1748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void ieee802_1x_encapsulate_radius(struct eapol_test_data *e,
1788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					  const u8 *eap, size_t len)
1798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct radius_msg *msg;
181a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	char buf[RADIUS_MAX_ATTR_LEN + 1];
1828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const struct eap_hdr *hdr;
1838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const u8 *pos;
1848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "Encapsulating EAP message into a RADIUS "
1868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   "packet");
1878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	e->radius_identifier = radius_client_get_id(e->radius);
1898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	msg = radius_msg_new(RADIUS_CODE_ACCESS_REQUEST,
1908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			     e->radius_identifier);
1918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (msg == NULL) {
1928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		printf("Could not create net RADIUS packet\n");
1938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
1948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
196b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt	radius_msg_make_authenticator(msg);
1978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	hdr = (const struct eap_hdr *) eap;
1998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos = (const u8 *) (hdr + 1);
2008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (len > sizeof(*hdr) && hdr->code == EAP_CODE_RESPONSE &&
2018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    pos[0] == EAP_TYPE_IDENTITY) {
2028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos++;
2038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(e->eap_identity);
2048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		e->eap_identity_len = len - sizeof(*hdr) - 1;
2058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		e->eap_identity = os_malloc(e->eap_identity_len);
2068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (e->eap_identity) {
2078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			os_memcpy(e->eap_identity, pos, e->eap_identity_len);
2088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_hexdump(MSG_DEBUG, "Learned identity from "
2098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				    "EAP-Response-Identity",
2108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				    e->eap_identity, e->eap_identity_len);
2118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
2128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (e->eap_identity &&
2158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    !radius_msg_add_attr(msg, RADIUS_ATTR_USER_NAME,
2168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				 e->eap_identity, e->eap_identity_len)) {
2178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		printf("Could not add User-Name\n");
2188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto fail;
2198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2215a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (e->req_eap_key_name &&
2225a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	    !radius_msg_add_attr(msg, RADIUS_ATTR_EAP_KEY_NAME, (u8 *) "\0",
2235a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt				 1)) {
2245a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		printf("Could not add EAP-Key-Name\n");
2255a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		goto fail;
2265a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
2275a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
2288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!find_extra_attr(e->extra_attrs, RADIUS_ATTR_NAS_IP_ADDRESS) &&
2298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    !radius_msg_add_attr(msg, RADIUS_ATTR_NAS_IP_ADDRESS,
2308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				 (u8 *) &e->own_ip_addr, 4)) {
2318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		printf("Could not add NAS-IP-Address\n");
2328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto fail;
2338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_snprintf(buf, sizeof(buf), RADIUS_802_1X_ADDR_FORMAT,
2368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    MAC2STR(e->wpa_s->own_addr));
2378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!find_extra_attr(e->extra_attrs, RADIUS_ATTR_CALLING_STATION_ID)
2388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    &&
2398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    !radius_msg_add_attr(msg, RADIUS_ATTR_CALLING_STATION_ID,
2408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				 (u8 *) buf, os_strlen(buf))) {
2418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		printf("Could not add Calling-Station-Id\n");
2428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto fail;
2438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* TODO: should probably check MTU from driver config; 2304 is max for
2468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * IEEE 802.11, but use 1400 to avoid problems with too large packets
2478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 */
2488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!find_extra_attr(e->extra_attrs, RADIUS_ATTR_FRAMED_MTU) &&
2498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    !radius_msg_add_attr_int32(msg, RADIUS_ATTR_FRAMED_MTU, 1400)) {
2508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		printf("Could not add Framed-MTU\n");
2518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto fail;
2528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!find_extra_attr(e->extra_attrs, RADIUS_ATTR_NAS_PORT_TYPE) &&
2558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    !radius_msg_add_attr_int32(msg, RADIUS_ATTR_NAS_PORT_TYPE,
2568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       RADIUS_NAS_PORT_TYPE_IEEE_802_11)) {
2578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		printf("Could not add NAS-Port-Type\n");
2588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto fail;
2598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26157c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt	if (!find_extra_attr(e->extra_attrs, RADIUS_ATTR_SERVICE_TYPE) &&
26257c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt	    !radius_msg_add_attr_int32(msg, RADIUS_ATTR_SERVICE_TYPE,
26357c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt				       RADIUS_SERVICE_TYPE_FRAMED)) {
26457c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt		printf("Could not add Service-Type\n");
26557c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt		goto fail;
26657c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt	}
26757c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt
2688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_snprintf(buf, sizeof(buf), "%s", e->connect_info);
2698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!find_extra_attr(e->extra_attrs, RADIUS_ATTR_CONNECT_INFO) &&
2708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    !radius_msg_add_attr(msg, RADIUS_ATTR_CONNECT_INFO,
2718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				 (u8 *) buf, os_strlen(buf))) {
2728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		printf("Could not add Connect-Info\n");
2738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto fail;
2748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (add_extra_attrs(msg, e->extra_attrs) < 0)
2778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto fail;
2788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (eap && !radius_msg_add_eap(msg, eap, len)) {
2808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		printf("Could not add EAP-Message\n");
2818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto fail;
2828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* State attribute must be copied if and only if this packet is
2858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * Access-Request reply to the previous Access-Challenge */
2868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (e->last_recv_radius &&
2878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    radius_msg_get_hdr(e->last_recv_radius)->code ==
2888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    RADIUS_CODE_ACCESS_CHALLENGE) {
2898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		int res = radius_msg_copy_attr(msg, e->last_recv_radius,
2908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					       RADIUS_ATTR_STATE);
2918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (res < 0) {
2928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			printf("Could not copy State attribute from previous "
2938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			       "Access-Challenge\n");
2948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			goto fail;
2958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
2968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (res > 0) {
2978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "  Copied RADIUS State "
2988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "Attribute");
2998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
3008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
30204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	if (radius_client_send(e->radius, msg, RADIUS_AUTH, e->wpa_s->own_addr)
30304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	    < 0)
30404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		goto fail;
3058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return;
3068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt fail:
3088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	radius_msg_free(msg);
3098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
3108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int eapol_test_eapol_send(void *ctx, int type, const u8 *buf,
3138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				 size_t len)
3148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
3158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	printf("WPA: eapol_test_eapol_send(type=%d len=%lu)\n",
3168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	       type, (unsigned long) len);
3178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (type == IEEE802_1X_TYPE_EAP_PACKET) {
3188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_hexdump(MSG_DEBUG, "TX EAP -> RADIUS", buf, len);
3198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ieee802_1x_encapsulate_radius(&eapol_test, buf, len);
3208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
3228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
3238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eapol_test_set_config_blob(void *ctx,
3268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       struct wpa_config_blob *blob)
3278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
3281f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	struct eapol_test_data *e = ctx;
3291f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	wpa_config_set_blob(e->wpa_s->conf, blob);
3308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
3318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic const struct wpa_config_blob *
3348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidteapol_test_get_config_blob(void *ctx, const char *name)
3358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
3361f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	struct eapol_test_data *e = ctx;
3371f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	return wpa_config_get_blob(e->wpa_s->conf, name);
3388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
3398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eapol_test_eapol_done_cb(void *ctx)
3428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
343d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	struct eapol_test_data *e = ctx;
344d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
3458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	printf("WPA: EAPOL processing complete\n");
346d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	wpa_supplicant_cancel_auth_timeout(e->wpa_s);
347d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	wpa_supplicant_set_state(e->wpa_s, WPA_COMPLETED);
3488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
3498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eapol_sm_reauth(void *eloop_ctx, void *timeout_ctx)
3528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
3538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct eapol_test_data *e = eloop_ctx;
3548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	printf("\n\n\n\n\neapol_test: Triggering EAP reauthentication\n\n");
3558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	e->radius_access_accept_received = 0;
3568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	send_eap_request_identity(e->wpa_s, NULL);
3578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
3588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int eapol_test_compare_pmk(struct eapol_test_data *e)
3618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
3628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 pmk[PMK_LEN];
3638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int ret = 1;
3645a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	const u8 *sess_id;
3655a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	size_t sess_id_len;
3668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (eapol_sm_get_key(e->wpa_s->eapol, pmk, PMK_LEN) == 0) {
3688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_hexdump(MSG_DEBUG, "PMK from EAPOL", pmk, PMK_LEN);
3698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (os_memcmp(pmk, e->authenticator_pmk, PMK_LEN) != 0) {
3708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			printf("WARNING: PMK mismatch\n");
3718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_hexdump(MSG_DEBUG, "PMK from AS",
3728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				    e->authenticator_pmk, PMK_LEN);
3738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		} else if (e->radius_access_accept_received)
3748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			ret = 0;
3758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else if (e->authenticator_pmk_len == 16 &&
3768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   eapol_sm_get_key(e->wpa_s->eapol, pmk, 16) == 0) {
3778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_hexdump(MSG_DEBUG, "LEAP PMK from EAPOL", pmk, 16);
3788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (os_memcmp(pmk, e->authenticator_pmk, 16) != 0) {
3798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			printf("WARNING: PMK mismatch\n");
3808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_hexdump(MSG_DEBUG, "PMK from AS",
3818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				    e->authenticator_pmk, 16);
3828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		} else if (e->radius_access_accept_received)
3838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			ret = 0;
3848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else if (e->radius_access_accept_received && e->no_mppe_keys) {
3858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* No keying material expected */
3868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ret = 0;
3878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ret && !e->no_mppe_keys)
3908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		e->num_mppe_mismatch++;
3918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else if (!e->no_mppe_keys)
3928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		e->num_mppe_ok++;
3938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3945a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	sess_id = eapol_sm_get_session_id(e->wpa_s->eapol, &sess_id_len);
3955a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (!sess_id)
3965a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return ret;
3975a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (e->authenticator_eap_key_name_len == 0) {
3985a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		wpa_printf(MSG_INFO, "No EAP-Key-Name received from server");
3995a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return ret;
4005a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
4015a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
4025a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (e->authenticator_eap_key_name_len != sess_id_len ||
4035a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	    os_memcmp(e->authenticator_eap_key_name, sess_id, sess_id_len) != 0)
4045a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	{
4055a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		wpa_printf(MSG_INFO,
4065a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			   "Locally derived EAP Session-Id does not match EAP-Key-Name from server");
4075a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		wpa_hexdump(MSG_DEBUG, "EAP Session-Id", sess_id, sess_id_len);
4085a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		wpa_hexdump(MSG_DEBUG, "EAP-Key-Name from server",
4095a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			    e->authenticator_eap_key_name,
4105a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			    e->authenticator_eap_key_name_len);
4115a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	} else {
4125a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		wpa_printf(MSG_INFO,
4135a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			   "Locally derived EAP Session-Id matches EAP-Key-Name from server");
4145a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
4155a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
4168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return ret;
4178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
4188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
420344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidtstatic void eapol_sm_cb(struct eapol_sm *eapol, enum eapol_supp_result result,
421344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt			void *ctx)
4228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
4238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct eapol_test_data *e = ctx;
424344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt	printf("eapol_sm_cb: result=%d\n", result);
425d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	e->id_req_sent = 0;
426d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	if (e->ctrl_iface)
427d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		return;
4288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	e->eapol_test_num_reauths--;
4298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (e->eapol_test_num_reauths < 0)
4308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eloop_terminate();
4318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else {
4328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eapol_test_compare_pmk(e);
4338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eloop_register_timeout(0, 100000, eapol_sm_reauth, e, NULL);
4348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
4358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
4368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4381f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstatic void eapol_test_write_cert(FILE *f, const char *subject,
4391f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				  const struct wpabuf *cert)
4401f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{
4411f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	unsigned char *encoded;
4421f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
4431f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	encoded = base64_encode(wpabuf_head(cert), wpabuf_len(cert), NULL);
4441f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (encoded == NULL)
4451f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		return;
4461f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	fprintf(f, "%s\n-----BEGIN CERTIFICATE-----\n%s"
4471f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		"-----END CERTIFICATE-----\n\n", subject, encoded);
4481f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	os_free(encoded);
4491f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt}
4501f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
4511f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
452051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt#if defined(CONFIG_CTRL_IFACE) || !defined(CONFIG_NO_STDOUT_DEBUG)
453051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidtstatic void eapol_test_eap_param_needed(void *ctx, enum wpa_ctrl_req_type field,
454051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt					const char *default_txt)
455051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt{
456051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt	struct eapol_test_data *e = ctx;
457051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt	struct wpa_supplicant *wpa_s = e->wpa_s;
458051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt	struct wpa_ssid *ssid = wpa_s->current_ssid;
459051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt	const char *field_name, *txt = NULL;
460051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt	char *buf;
461051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt	size_t buflen;
462051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt	int len;
463051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt
464051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt	if (ssid == NULL)
465051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt		return;
466051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt
467051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt	field_name = wpa_supplicant_ctrl_req_to_string(field, default_txt,
468051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt						       &txt);
469051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt	if (field_name == NULL) {
470051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt		wpa_printf(MSG_WARNING, "Unhandled EAP param %d needed",
471051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt			   field);
472051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt		return;
473051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt	}
474051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt
475051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt	buflen = 100 + os_strlen(txt) + ssid->ssid_len;
476051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt	buf = os_malloc(buflen);
477051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt	if (buf == NULL)
478051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt		return;
479051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt	len = os_snprintf(buf, buflen,
480051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt			  WPA_CTRL_REQ "%s-%d:%s needed for SSID ",
481051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt			  field_name, ssid->id, txt);
4826c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	if (os_snprintf_error(buflen, len)) {
483051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt		os_free(buf);
484051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt		return;
485051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt	}
486051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt	if (ssid->ssid && buflen > len + ssid->ssid_len) {
487051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt		os_memcpy(buf + len, ssid->ssid, ssid->ssid_len);
488051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt		len += ssid->ssid_len;
489051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt		buf[len] = '\0';
490051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt	}
491051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt	buf[buflen - 1] = '\0';
492051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt	wpa_msg(wpa_s, MSG_INFO, "%s", buf);
493051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt	os_free(buf);
494051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt}
495051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt#else /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */
496051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt#define eapol_test_eap_param_needed NULL
497051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt#endif /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */
498051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt
499051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt
500c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidtstatic void eapol_test_cert_cb(void *ctx, int depth, const char *subject,
5012f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt			       const char *altsubject[], int num_altsubject,
502c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt			       const char *cert_hash,
503c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt			       const struct wpabuf *cert)
504c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt{
505c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt	struct eapol_test_data *e = ctx;
506c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt
507c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt	wpa_msg(e->wpa_s, MSG_INFO, WPA_EVENT_EAP_PEER_CERT
508c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt		"depth=%d subject='%s'%s%s",
509c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt		depth, subject,
510c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt		cert_hash ? " hash=" : "",
511c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt		cert_hash ? cert_hash : "");
512c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt
513c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt	if (cert) {
514c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt		char *cert_hex;
515c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt		size_t len = wpabuf_len(cert) * 2 + 1;
516c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt		cert_hex = os_malloc(len);
517c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt		if (cert_hex) {
518c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt			wpa_snprintf_hex(cert_hex, len, wpabuf_head(cert),
519c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt					 wpabuf_len(cert));
520c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt			wpa_msg_ctrl(e->wpa_s, MSG_INFO,
521c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt				     WPA_EVENT_EAP_PEER_CERT
522c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt				     "depth=%d subject='%s' cert=%s",
523c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt				     depth, subject, cert_hex);
524c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt			os_free(cert_hex);
525c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt		}
5261f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
5271f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		if (e->server_cert_file)
5281f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			eapol_test_write_cert(e->server_cert_file,
5291f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt					      subject, cert);
530c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt	}
5312f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt
5322f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt	if (altsubject) {
5332f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt		int i;
5342f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt
5352f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt		for (i = 0; i < num_altsubject; i++)
5362f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt			wpa_msg(e->wpa_s, MSG_INFO, WPA_EVENT_EAP_PEER_ALT
5372f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt				"depth=%d %s", depth, altsubject[i]);
5382f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt	}
539c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt}
540c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt
541c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt
5424530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidtstatic void eapol_test_set_anon_id(void *ctx, const u8 *id, size_t len)
5434530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt{
5444530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	struct eapol_test_data *e = ctx;
5454530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	struct wpa_supplicant *wpa_s = e->wpa_s;
5464530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	char *str;
5474530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	int res;
5484530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
5494530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	wpa_hexdump_ascii(MSG_DEBUG, "EAP method updated anonymous_identity",
5504530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt			  id, len);
5514530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
5524530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	if (wpa_s->current_ssid == NULL)
5534530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		return;
5544530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
5554530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	if (id == NULL) {
5564530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		if (wpa_config_set(wpa_s->current_ssid, "anonymous_identity",
5574530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt				   "NULL", 0) < 0)
5584530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt			return;
5594530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	} else {
5604530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		str = os_malloc(len * 2 + 1);
5614530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		if (str == NULL)
5624530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt			return;
5634530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		wpa_snprintf_hex(str, len * 2 + 1, id, len);
5644530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		res = wpa_config_set(wpa_s->current_ssid, "anonymous_identity",
5654530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt				     str, 0);
5664530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		os_free(str);
5674530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		if (res < 0)
5684530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt			return;
5694530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	}
5704530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt}
5714530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
5724530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
573d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidtstatic enum wpa_states eapol_test_get_state(void *ctx)
574d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt{
575d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	struct eapol_test_data *e = ctx;
576d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	struct wpa_supplicant *wpa_s = e->wpa_s;
577d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
578d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	return wpa_s->wpa_state;
579d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt}
580d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
581d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
5828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int test_eapol(struct eapol_test_data *e, struct wpa_supplicant *wpa_s,
5838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		      struct wpa_ssid *ssid)
5848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
5858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct eapol_config eapol_conf;
5868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct eapol_ctx *ctx;
587d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	struct wpa_sm_ctx *wctx;
5888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ctx = os_zalloc(sizeof(*ctx));
5908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ctx == NULL) {
5918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		printf("Failed to allocate EAPOL context.\n");
5928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
5938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
5941f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	ctx->ctx = e;
5958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ctx->msg_ctx = wpa_s;
5968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ctx->scard_ctx = wpa_s->scard;
5978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ctx->cb = eapol_sm_cb;
5988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ctx->cb_ctx = e;
5998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ctx->eapol_send_ctx = wpa_s;
6008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ctx->preauth = 0;
6018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ctx->eapol_done_cb = eapol_test_eapol_done_cb;
6028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ctx->eapol_send = eapol_test_eapol_send;
6038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ctx->set_config_blob = eapol_test_set_config_blob;
6048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ctx->get_config_blob = eapol_test_get_config_blob;
6058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ctx->opensc_engine_path = wpa_s->conf->opensc_engine_path;
6068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ctx->pkcs11_engine_path = wpa_s->conf->pkcs11_engine_path;
6078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ctx->pkcs11_module_path = wpa_s->conf->pkcs11_module_path;
6086c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	ctx->openssl_ciphers = wpa_s->conf->openssl_ciphers;
609051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt	ctx->eap_param_needed = eapol_test_eap_param_needed;
610c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt	ctx->cert_cb = eapol_test_cert_cb;
6111f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	ctx->cert_in_cb = 1;
6124530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	ctx->set_anon_id = eapol_test_set_anon_id;
6138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_s->eapol = eapol_sm_init(ctx);
6158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_s->eapol == NULL) {
6168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(ctx);
6178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		printf("Failed to initialize EAPOL state machines.\n");
6188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
6198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
621d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_NO_WPA;
622d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	wctx = os_zalloc(sizeof(*wctx));
623d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	if (wctx == NULL) {
624d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		os_free(ctx);
625d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		return -1;
626d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	}
627d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	wctx->ctx = e;
628d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	wctx->msg_ctx = wpa_s;
629d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	wctx->get_state = eapol_test_get_state;
630d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	wpa_s->wpa = wpa_sm_init(wctx);
631d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	if (!wpa_s->wpa) {
632d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		os_free(ctx);
633d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		os_free(wctx);
634d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		return -1;
635d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	}
636d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
637d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	if (!ssid)
638d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		return 0;
639d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
6408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_s->current_ssid = ssid;
6418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memset(&eapol_conf, 0, sizeof(eapol_conf));
6428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eapol_conf.accept_802_1x_keys = 1;
6438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eapol_conf.required_keys = 0;
6448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eapol_conf.fast_reauth = wpa_s->conf->fast_reauth;
6458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eapol_conf.workaround = ssid->eap_workaround;
646051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt	eapol_conf.external_sim = wpa_s->conf->external_sim;
6478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eapol_sm_notify_config(wpa_s->eapol, &ssid->eap, &eapol_conf);
6488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eapol_sm_register_scard_ctx(wpa_s->eapol, wpa_s->scard);
6498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eapol_sm_notify_portValid(wpa_s->eapol, FALSE);
6528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* 802.1X::portControl = Auto */
6538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eapol_sm_notify_portEnabled(wpa_s->eapol, TRUE);
6548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
6568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
6578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void test_eapol_clean(struct eapol_test_data *e,
6608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			     struct wpa_supplicant *wpa_s)
6618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
6628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct extra_radius_attr *p, *prev;
6638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
664d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	wpa_sm_deinit(wpa_s->wpa);
665d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	wpa_s->wpa = NULL;
6668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	radius_client_deinit(e->radius);
66761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	wpabuf_free(e->last_eap_radius);
6688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	radius_msg_free(e->last_recv_radius);
6698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	e->last_recv_radius = NULL;
6708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(e->eap_identity);
6718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	e->eap_identity = NULL;
6728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eapol_sm_deinit(wpa_s->eapol);
6738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_s->eapol = NULL;
6748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (e->radius_conf && e->radius_conf->auth_server) {
6758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(e->radius_conf->auth_server->shared_secret);
6768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(e->radius_conf->auth_server);
6778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(e->radius_conf);
6798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	e->radius_conf = NULL;
6808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	scard_deinit(wpa_s->scard);
6818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_s->ctrl_iface) {
6828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_supplicant_ctrl_iface_deinit(wpa_s->ctrl_iface);
6838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_s->ctrl_iface = NULL;
6848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
68561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
68661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	ext_password_deinit(wpa_s->ext_pw);
68761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	wpa_s->ext_pw = NULL;
68861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
6898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_config_free(wpa_s->conf);
6908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p = e->extra_attrs;
6928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	while (p) {
6938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		prev = p;
6948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p = p->next;
6958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(prev);
6968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
6988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void send_eap_request_identity(void *eloop_ctx, void *timeout_ctx)
7018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
7028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_supplicant *wpa_s = eloop_ctx;
7038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 buf[100], *pos;
7048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct ieee802_1x_hdr *hdr;
7058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct eap_hdr *eap;
7068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	hdr = (struct ieee802_1x_hdr *) buf;
7088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	hdr->version = EAPOL_VERSION;
7098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	hdr->type = IEEE802_1X_TYPE_EAP_PACKET;
7108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	hdr->length = htons(5);
7118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eap = (struct eap_hdr *) (hdr + 1);
7138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eap->code = EAP_CODE_REQUEST;
7148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eap->identifier = 0;
7158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eap->length = htons(5);
7168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos = (u8 *) (eap + 1);
7178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	*pos = EAP_TYPE_IDENTITY;
7188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	printf("Sending fake EAP-Request-Identity\n");
7208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eapol_sm_rx_eapol(wpa_s->eapol, wpa_s->bssid, buf,
7218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  sizeof(*hdr) + 5);
7228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
7238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eapol_test_timeout(void *eloop_ctx, void *timeout_ctx)
7268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
7278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct eapol_test_data *e = eloop_ctx;
7288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	printf("EAPOL test timed out\n");
7298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	e->auth_timed_out = 1;
7308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_terminate();
7318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
7328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic char *eap_type_text(u8 type)
7358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
7368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	switch (type) {
7378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case EAP_TYPE_IDENTITY: return "Identity";
7388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case EAP_TYPE_NOTIFICATION: return "Notification";
7398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case EAP_TYPE_NAK: return "Nak";
7408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case EAP_TYPE_TLS: return "TLS";
7418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case EAP_TYPE_TTLS: return "TTLS";
7428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case EAP_TYPE_PEAP: return "PEAP";
7438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case EAP_TYPE_SIM: return "SIM";
7448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case EAP_TYPE_GTC: return "GTC";
7458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case EAP_TYPE_MD5: return "MD5";
7468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case EAP_TYPE_OTP: return "OTP";
7478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case EAP_TYPE_FAST: return "FAST";
7488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case EAP_TYPE_SAKE: return "SAKE";
7498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case EAP_TYPE_PSK: return "PSK";
7508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	default: return "Unknown";
7518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
7528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
7538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void ieee802_1x_decapsulate_radius(struct eapol_test_data *e)
7568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
75761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	struct wpabuf *eap;
75861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	const struct eap_hdr *hdr;
7598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int eap_type = -1;
7608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char buf[64];
7618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct radius_msg *msg;
7628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (e->last_recv_radius == NULL)
7648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
7658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	msg = e->last_recv_radius;
7678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
76861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	eap = radius_msg_get_eap(msg);
7698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (eap == NULL) {
7708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* draft-aboba-radius-rfc2869bis-20.txt, Chap. 2.6.3:
7718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * RADIUS server SHOULD NOT send Access-Reject/no EAP-Message
7728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * attribute */
7738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "could not extract "
7748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			       "EAP-Message from RADIUS message");
77561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		wpabuf_free(e->last_eap_radius);
7768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		e->last_eap_radius = NULL;
7778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
7788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
7798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
78061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (wpabuf_len(eap) < sizeof(*hdr)) {
7818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "too short EAP packet "
7828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			       "received from authentication server");
78361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		wpabuf_free(eap);
7848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
7858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
7868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
78761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (wpabuf_len(eap) > sizeof(*hdr))
78861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		eap_type = (wpabuf_head_u8(eap))[sizeof(*hdr)];
7898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
79061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	hdr = wpabuf_head(eap);
7918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	switch (hdr->code) {
7928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case EAP_CODE_REQUEST:
7938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_snprintf(buf, sizeof(buf), "EAP-Request-%s (%d)",
7948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    eap_type >= 0 ? eap_type_text(eap_type) : "??",
7958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    eap_type);
7968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
7978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case EAP_CODE_RESPONSE:
7988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_snprintf(buf, sizeof(buf), "EAP Response-%s (%d)",
7998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    eap_type >= 0 ? eap_type_text(eap_type) : "??",
8008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    eap_type);
8018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
8028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case EAP_CODE_SUCCESS:
8038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_strlcpy(buf, "EAP Success", sizeof(buf));
8048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* LEAP uses EAP Success within an authentication, so must not
8058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * stop here with eloop_terminate(); */
8068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
8078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case EAP_CODE_FAILURE:
8088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_strlcpy(buf, "EAP Failure", sizeof(buf));
809d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		if (e->ctrl_iface)
810d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			break;
8118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eloop_terminate();
8128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
8138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	default:
8148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_strlcpy(buf, "unknown EAP code", sizeof(buf));
81561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		wpa_hexdump_buf(MSG_DEBUG, "Decapsulated EAP packet", eap);
8168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
8178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
8188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "decapsulated EAP packet (code=%d "
8198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		       "id=%d len=%d) from RADIUS server: %s",
8208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		      hdr->code, hdr->identifier, ntohs(hdr->length), buf);
8218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* sta->eapol_sm->be_auth.idFromServer = hdr->identifier; */
8238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
82461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	wpabuf_free(e->last_eap_radius);
8258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	e->last_eap_radius = eap;
8268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	{
8288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		struct ieee802_1x_hdr *dot1x;
82961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		dot1x = os_malloc(sizeof(*dot1x) + wpabuf_len(eap));
8308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		assert(dot1x != NULL);
8318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dot1x->version = EAPOL_VERSION;
8328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dot1x->type = IEEE802_1X_TYPE_EAP_PACKET;
83361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		dot1x->length = htons(wpabuf_len(eap));
83461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		os_memcpy((u8 *) (dot1x + 1), wpabuf_head(eap),
83561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			  wpabuf_len(eap));
8368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eapol_sm_rx_eapol(e->wpa_s->eapol, e->wpa_s->bssid,
83761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt				  (u8 *) dot1x,
83861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt				  sizeof(*dot1x) + wpabuf_len(eap));
8398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(dot1x);
8408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
8418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
8428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void ieee802_1x_get_keys(struct eapol_test_data *e,
8458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				struct radius_msg *msg, struct radius_msg *req,
8468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				const u8 *shared_secret,
8478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				size_t shared_secret_len)
8488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
8498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct radius_ms_mppe_keys *keys;
8505a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	u8 *buf;
8515a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	size_t len;
8528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	keys = radius_msg_get_ms_keys(msg, req, shared_secret,
8548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				      shared_secret_len);
8558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (keys && keys->send == NULL && keys->recv == NULL) {
8568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(keys);
8578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		keys = radius_msg_get_cisco_keys(msg, req, shared_secret,
8588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						 shared_secret_len);
8598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
8608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (keys) {
8628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (keys->send) {
8638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_hexdump(MSG_DEBUG, "MS-MPPE-Send-Key (sign)",
8648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				    keys->send, keys->send_len);
8658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
8668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (keys->recv) {
8678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_hexdump(MSG_DEBUG, "MS-MPPE-Recv-Key (crypt)",
8688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				    keys->recv, keys->recv_len);
8698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			e->authenticator_pmk_len =
8708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				keys->recv_len > PMK_LEN ? PMK_LEN :
8718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				keys->recv_len;
8728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			os_memcpy(e->authenticator_pmk, keys->recv,
8738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  e->authenticator_pmk_len);
8748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (e->authenticator_pmk_len == 16 && keys->send &&
8758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    keys->send_len == 16) {
8768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				/* MS-CHAP-v2 derives 16 octet keys */
8778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				wpa_printf(MSG_DEBUG, "Use MS-MPPE-Send-Key "
8788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   "to extend PMK to 32 octets");
8798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				os_memcpy(e->authenticator_pmk +
8808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					  e->authenticator_pmk_len,
8818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					  keys->send, keys->send_len);
8828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				e->authenticator_pmk_len += keys->send_len;
8838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			}
8848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
8858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(keys->send);
8878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(keys->recv);
8888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(keys);
8898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
8905a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
8915a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (radius_msg_get_attr_ptr(msg, RADIUS_ATTR_EAP_KEY_NAME, &buf, &len,
8925a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt				    NULL) == 0) {
8935a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		os_memcpy(e->authenticator_eap_key_name, buf, len);
8945a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		e->authenticator_eap_key_name_len = len;
8955a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	} else {
8965a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		e->authenticator_eap_key_name_len = 0;
8975a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
8988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
8998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* Process the RADIUS frames from Authentication Server */
9028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic RadiusRxResult
9038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtieee802_1x_receive_auth(struct radius_msg *msg, struct radius_msg *req,
9048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			const u8 *shared_secret, size_t shared_secret_len,
9058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			void *data)
9068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
9078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct eapol_test_data *e = data;
9088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct radius_hdr *hdr = radius_msg_get_hdr(msg);
9098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* RFC 2869, Ch. 5.13: valid Message-Authenticator attribute MUST be
9118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * present when packet contains an EAP-Message attribute */
9128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (hdr->code == RADIUS_CODE_ACCESS_REJECT &&
9138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    radius_msg_get_attr(msg, RADIUS_ATTR_MESSAGE_AUTHENTICATOR, NULL,
9148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				0) < 0 &&
9158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    radius_msg_get_attr(msg, RADIUS_ATTR_EAP_MESSAGE, NULL, 0) < 0) {
9168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "Allowing RADIUS "
9178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			      "Access-Reject without Message-Authenticator "
9188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			      "since it does not include EAP-Message\n");
9198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else if (radius_msg_verify(msg, shared_secret, shared_secret_len,
9208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				     req, 1)) {
9218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		printf("Incoming RADIUS packet did not have correct "
9228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		       "Message-Authenticator - dropped\n");
9238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return RADIUS_RX_UNKNOWN;
9248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
9258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (hdr->code != RADIUS_CODE_ACCESS_ACCEPT &&
9278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    hdr->code != RADIUS_CODE_ACCESS_REJECT &&
9288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    hdr->code != RADIUS_CODE_ACCESS_CHALLENGE) {
9298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		printf("Unknown RADIUS message code\n");
9308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return RADIUS_RX_UNKNOWN;
9318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
9328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	e->radius_identifier = -1;
9348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "RADIUS packet matching with station");
9358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	radius_msg_free(e->last_recv_radius);
9378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	e->last_recv_radius = msg;
9388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	switch (hdr->code) {
9408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case RADIUS_CODE_ACCESS_ACCEPT:
9418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		e->radius_access_accept_received = 1;
9428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ieee802_1x_get_keys(e, msg, req, shared_secret,
9438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				    shared_secret_len);
9448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
9458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case RADIUS_CODE_ACCESS_REJECT:
9468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		e->radius_access_reject_received = 1;
9478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
9488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
9498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ieee802_1x_decapsulate_radius(e);
9518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if ((hdr->code == RADIUS_CODE_ACCESS_ACCEPT &&
9538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	     e->eapol_test_num_reauths < 0) ||
9548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    hdr->code == RADIUS_CODE_ACCESS_REJECT) {
955d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		if (!e->ctrl_iface)
956d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			eloop_terminate();
9578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
9588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return RADIUS_RX_QUEUED;
9608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
9618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
963d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidtstatic int driver_get_ssid(void *priv, u8 *ssid)
964d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt{
965d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	ssid[0] = 0;
966d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	return 0;
967d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt}
968d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
969d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
970d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidtstatic int driver_get_bssid(void *priv, u8 *bssid)
971d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt{
972d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	struct eapol_test_data *e = priv;
973d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
974d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	if (e->ctrl_iface && !e->id_req_sent) {
975d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		eloop_register_timeout(0, 0, send_eap_request_identity,
976d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt				       e->wpa_s, NULL);
977d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		e->id_req_sent = 1;
978d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	}
979d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
980d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	os_memset(bssid, 0, ETH_ALEN);
981d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	bssid[5] = 1;
982d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	return 0;
983d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt}
984d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
985d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
986d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidtstatic int driver_get_capa(void *priv, struct wpa_driver_capa *capa)
987d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt{
988d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	os_memset(capa, 0, sizeof(*capa));
989d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	capa->flags = WPA_DRIVER_FLAGS_WIRED;
990d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	return 0;
991d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt}
992d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
993d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
994d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidtstruct wpa_driver_ops eapol_test_drv_ops = {
995d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	.name = "test",
996d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	.get_ssid = driver_get_ssid,
997d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	.get_bssid = driver_get_bssid,
998d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	.get_capa = driver_get_capa,
999d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt};
1000d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt
10018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_init_conf(struct eapol_test_data *e,
10028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  struct wpa_supplicant *wpa_s, const char *authsrv,
10038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  int port, const char *secret,
1004d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			  const char *cli_addr, const char *ifname)
10058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
10068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct hostapd_radius_server *as;
10078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int res;
10088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1009d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	wpa_s->driver = &eapol_test_drv_ops;
1010d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	wpa_s->drv_priv = e;
10118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_s->bssid[5] = 1;
10128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(wpa_s->own_addr, e->own_addr, ETH_ALEN);
10138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	e->own_ip_addr.s_addr = htonl((127 << 24) | 1);
1014d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	os_strlcpy(wpa_s->ifname, ifname, sizeof(wpa_s->ifname));
10158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	e->radius_conf = os_zalloc(sizeof(struct hostapd_radius_servers));
10178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	assert(e->radius_conf != NULL);
10188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	e->radius_conf->num_auth_servers = 1;
10198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	as = os_zalloc(sizeof(struct hostapd_radius_server));
10208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	assert(as != NULL);
10218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#if defined(CONFIG_NATIVE_WINDOWS) || defined(CONFIG_ANSI_C_EXTRA)
10228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	{
10238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		int a[4];
10248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		u8 *pos;
10258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sscanf(authsrv, "%d.%d.%d.%d", &a[0], &a[1], &a[2], &a[3]);
10268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos = (u8 *) &as->addr.u.v4;
10278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		*pos++ = a[0];
10288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		*pos++ = a[1];
10298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		*pos++ = a[2];
10308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		*pos++ = a[3];
10318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
10328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#else /* CONFIG_NATIVE_WINDOWS or CONFIG_ANSI_C_EXTRA */
10337a53dbb56693ee9f55c0cab1a8297436511e8613Dmitry Shmidt	if (hostapd_parse_ip_addr(authsrv, &as->addr) < 0) {
10346c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		wpa_printf(MSG_ERROR, "Invalid IP address '%s'",
10356c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt			   authsrv);
10366c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		assert(0);
10376c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	}
10388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_NATIVE_WINDOWS or CONFIG_ANSI_C_EXTRA */
10398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	as->port = port;
10408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	as->shared_secret = (u8 *) os_strdup(secret);
10418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	as->shared_secret_len = os_strlen(secret);
10428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	e->radius_conf->auth_server = as;
10438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	e->radius_conf->auth_servers = as;
10448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	e->radius_conf->msg_dumps = 1;
10458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (cli_addr) {
10468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (hostapd_parse_ip_addr(cli_addr,
10478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					  &e->radius_conf->client_addr) == 0)
10488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			e->radius_conf->force_client_addr = 1;
10498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		else {
10508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_ERROR, "Invalid IP address '%s'",
10518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   cli_addr);
10528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			assert(0);
10538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
10548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
10558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	e->radius = radius_client_init(wpa_s, e->radius_conf);
10578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	assert(e->radius != NULL);
10588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	res = radius_client_register(e->radius, RADIUS_AUTH,
10608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				     ieee802_1x_receive_auth, e);
10618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	assert(res == 0);
10628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
10638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10652271d3fdd5982d0e5e81cf9999a861bba933eacbDmitry Shmidtstatic int scard_test(struct eapol_test_data *e)
10668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
10678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct scard_data *scard;
10688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t len;
10698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char imsi[20];
10708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	unsigned char _rand[16];
10718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef PCSC_FUNCS
10728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	unsigned char sres[4];
10738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	unsigned char kc[8];
10748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* PCSC_FUNCS */
10758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define num_triplets 5
10768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	unsigned char rand_[num_triplets][16];
10778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	unsigned char sres_[num_triplets][4];
10788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	unsigned char kc_[num_triplets][8];
10798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int i, res;
10808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t j;
10818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define AKA_RAND_LEN 16
10838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define AKA_AUTN_LEN 16
10848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define AKA_AUTS_LEN 14
10858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define RES_MAX_LEN 16
10868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define IK_LEN 16
10878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define CK_LEN 16
10888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	unsigned char aka_rand[AKA_RAND_LEN];
10898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	unsigned char aka_autn[AKA_AUTN_LEN];
10908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	unsigned char aka_auts[AKA_AUTS_LEN];
10918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	unsigned char aka_res[RES_MAX_LEN];
10928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t aka_res_len;
10938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	unsigned char aka_ik[IK_LEN];
10948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	unsigned char aka_ck[CK_LEN];
10958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10962271d3fdd5982d0e5e81cf9999a861bba933eacbDmitry Shmidt	scard = scard_init(e->pcsc_reader);
10978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (scard == NULL)
10988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
10992271d3fdd5982d0e5e81cf9999a861bba933eacbDmitry Shmidt	if (scard_set_pin(scard, e->pcsc_pin)) {
11008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_WARNING, "PIN validation failed");
11018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		scard_deinit(scard);
11028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
11038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
11048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	len = sizeof(imsi);
11068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (scard_get_imsi(scard, imsi, &len))
11078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto failed;
11088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump_ascii(MSG_DEBUG, "SCARD: IMSI", (u8 *) imsi, len);
11098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* NOTE: Permanent Username: 1 | IMSI */
11108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1111c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	wpa_printf(MSG_DEBUG, "SCARD: MNC length %d",
1112c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt		   scard_get_mnc_len(scard));
1113c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt
11148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memset(_rand, 0, sizeof(_rand));
11158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (scard_gsm_auth(scard, _rand, sres, kc))
11168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto failed;
11178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memset(_rand, 0xff, sizeof(_rand));
11198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (scard_gsm_auth(scard, _rand, sres, kc))
11208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto failed;
11218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (i = 0; i < num_triplets; i++) {
11238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memset(rand_[i], i, sizeof(rand_[i]));
11248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (scard_gsm_auth(scard, rand_[i], sres_[i], kc_[i]))
11258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			goto failed;
11268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
11278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (i = 0; i < num_triplets; i++) {
11298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		printf("1");
11308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		for (j = 0; j < len; j++)
11318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			printf("%c", imsi[j]);
11328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		printf(",");
11338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		for (j = 0; j < 16; j++)
11348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			printf("%02X", rand_[i][j]);
11358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		printf(",");
11368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		for (j = 0; j < 4; j++)
11378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			printf("%02X", sres_[i][j]);
11388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		printf(",");
11398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		for (j = 0; j < 8; j++)
11408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			printf("%02X", kc_[i][j]);
11418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		printf("\n");
11428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
11438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "Trying to use UMTS authentication");
11458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* seq 39 (0x28) */
11478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memset(aka_rand, 0xaa, 16);
11488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(aka_autn, "\x86\x71\x31\xcb\xa2\xfc\x61\xdf"
11498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		  "\xa3\xb3\x97\x9d\x07\x32\xa2\x12", 16);
11508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	res = scard_umts_auth(scard, aka_rand, aka_autn, aka_res, &aka_res_len,
11528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			      aka_ik, aka_ck, aka_auts);
11538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (res == 0) {
11548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "UMTS auth completed successfully");
11558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_hexdump(MSG_DEBUG, "RES", aka_res, aka_res_len);
11568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_hexdump(MSG_DEBUG, "IK", aka_ik, IK_LEN);
11578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_hexdump(MSG_DEBUG, "CK", aka_ck, CK_LEN);
11588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else if (res == -2) {
11598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "UMTS auth resulted in synchronization "
11608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "failure");
11618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_hexdump(MSG_DEBUG, "AUTS", aka_auts, AKA_AUTS_LEN);
11628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
11638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "UMTS auth failed");
11648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
11658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtfailed:
11678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	scard_deinit(scard);
11688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
11708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#undef num_triplets
11718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
11728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11742271d3fdd5982d0e5e81cf9999a861bba933eacbDmitry Shmidtstatic int scard_get_triplets(struct eapol_test_data *e, int argc, char *argv[])
11758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
11768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct scard_data *scard;
11778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t len;
11788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char imsi[20];
11798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	unsigned char _rand[16];
11808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	unsigned char sres[4];
11818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	unsigned char kc[8];
11828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int num_triplets;
11838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int i;
11848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t j;
11858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (argc < 2 || ((num_triplets = atoi(argv[1])) <= 0)) {
11878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		printf("invalid parameters for sim command\n");
11888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
11898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
11908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (argc <= 2 || os_strcmp(argv[2], "debug") != 0) {
11928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* disable debug output */
11938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_debug_level = 99;
11948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
11958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11962271d3fdd5982d0e5e81cf9999a861bba933eacbDmitry Shmidt	scard = scard_init(e->pcsc_reader);
11978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (scard == NULL) {
11988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		printf("Failed to open smartcard connection\n");
11998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
12008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
12018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (scard_set_pin(scard, argv[0])) {
12028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_WARNING, "PIN validation failed");
12038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		scard_deinit(scard);
12048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
12058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
12068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	len = sizeof(imsi);
12088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (scard_get_imsi(scard, imsi, &len)) {
12098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		scard_deinit(scard);
12108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
12118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
12128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (i = 0; i < num_triplets; i++) {
12148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memset(_rand, i, sizeof(_rand));
12158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (scard_gsm_auth(scard, _rand, sres, kc))
12168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
12178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* IMSI:Kc:SRES:RAND */
12198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		for (j = 0; j < len; j++)
12208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			printf("%c", imsi[j]);
12218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		printf(":");
12228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		for (j = 0; j < 8; j++)
12238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			printf("%02X", kc[j]);
12248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		printf(":");
12258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		for (j = 0; j < 4; j++)
12268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			printf("%02X", sres[j]);
12278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		printf(":");
12288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		for (j = 0; j < 16; j++)
12298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			printf("%02X", _rand[j]);
12308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		printf("\n");
12318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
12328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	scard_deinit(scard);
12348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
12368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
12378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eapol_test_terminate(int sig, void *signal_ctx)
12408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
12418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_supplicant *wpa_s = signal_ctx;
12428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(wpa_s, MSG_INFO, "Signal %d received - terminating", sig);
12438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_terminate();
12448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
12458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void usage(void)
12488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
12498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	printf("usage:\n"
1250d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	       "eapol_test [-enWSv] -c<conf> [-a<AS IP>] [-p<AS port>] "
12518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	       "[-s<AS secret>]\\\n"
12528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	       "           [-r<count>] [-t<timeout>] [-C<Connect-Info>] \\\n"
12531f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	       "           [-M<client MAC address>] [-o<server cert file] \\\n"
12542271d3fdd5982d0e5e81cf9999a861bba933eacbDmitry Shmidt	       "           [-N<attr spec>] [-R<PC/SC reader>] "
12552271d3fdd5982d0e5e81cf9999a861bba933eacbDmitry Shmidt	       "[-P<PC/SC PIN>] \\\n"
1256d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	       "           [-A<client IP>] [-i<ifname>] [-T<ctrl_iface>]\n"
12578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	       "eapol_test scard\n"
12588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	       "eapol_test sim <PIN> <num triplets> [debug]\n"
12598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	       "\n");
12608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	printf("options:\n"
12618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	       "  -c<conf> = configuration file\n"
12628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	       "  -a<AS IP> = IP address of the authentication server, "
12638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	       "default 127.0.0.1\n"
12648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	       "  -p<AS port> = UDP port of the authentication server, "
12658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	       "default 1812\n"
12668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	       "  -s<AS secret> = shared secret with the authentication "
12678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	       "server, default 'radius'\n"
12688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	       "  -A<client IP> = IP address of the client, default: select "
12698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	       "automatically\n"
12708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	       "  -r<count> = number of re-authentications\n"
12715a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	       "  -e = Request EAP-Key-Name\n"
12728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	       "  -W = wait for a control interface monitor before starting\n"
12738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	       "  -S = save configuration after authentication\n"
12748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	       "  -n = no MPPE keys expected\n"
1275d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	       "  -v = show version\n"
12768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	       "  -t<timeout> = sets timeout in seconds (default: 30 s)\n"
12778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	       "  -C<Connect-Info> = RADIUS Connect-Info (default: "
12788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	       "CONNECT 11Mbps 802.11b)\n"
12798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	       "  -M<client MAC address> = Set own MAC address "
12808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	       "(Calling-Station-Id,\n"
12818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	       "                           default: 02:00:00:00:00:01)\n"
12821f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	       "  -o<server cert file> = Write received server certificate\n"
12831f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	       "                         chain to the specified file\n"
12848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	       "  -N<attr spec> = send arbitrary attribute specified by:\n"
12858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	       "                  attr_id:syntax:value or attr_id\n"
12868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	       "                  attr_id - number id of the attribute\n"
12878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	       "                  syntax - one of: s, d, x\n"
12888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	       "                     s = string\n"
12898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	       "                     d = integer\n"
12908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	       "                     x = octet string\n"
12918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	       "                  value - attribute value.\n"
12928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	       "       When only attr_id is specified, NULL will be used as "
12938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	       "value.\n"
12948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	       "       Multiple attributes can be specified by using the "
12958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	       "option several times.\n");
12968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
12978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint main(int argc, char *argv[])
13008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1301051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt	struct wpa_global global;
13028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_supplicant wpa_s;
13038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int c, ret = 1, wait_for_monitor = 0, save_config = 0;
13048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char *as_addr = "127.0.0.1";
13058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int as_port = 1812;
13068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char *as_secret = "radius";
13078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char *cli_addr = NULL;
13088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char *conf = NULL;
13098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int timeout = 30;
13108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char *pos;
13118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct extra_radius_attr *p = NULL, *p1;
1312d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	const char *ifname = "test";
1313d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	const char *ctrl_iface = NULL;
13148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (os_program_init())
13168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
13178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	hostapd_logger_register_cb(hostapd_logger_cb);
13198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memset(&eapol_test, 0, sizeof(eapol_test));
13218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eapol_test.connect_info = "CONNECT 11Mbps 802.11b";
13228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(eapol_test.own_addr, "\x02\x00\x00\x00\x00\x01", ETH_ALEN);
13232271d3fdd5982d0e5e81cf9999a861bba933eacbDmitry Shmidt	eapol_test.pcsc_pin = "1234";
13248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_debug_level = 0;
13268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_debug_show_keys = 1;
13278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (;;) {
1329d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		c = getopt(argc, argv, "a:A:c:C:ei:M:nN:o:p:P:r:R:s:St:T:vW");
13308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (c < 0)
13318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
13328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		switch (c) {
13338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		case 'a':
13348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			as_addr = optarg;
13358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
13368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		case 'A':
13378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			cli_addr = optarg;
13388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
13398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		case 'c':
13408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			conf = optarg;
13418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
13428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		case 'C':
13438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			eapol_test.connect_info = optarg;
13448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
13455a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		case 'e':
13465a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			eapol_test.req_eap_key_name = 1;
13475a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			break;
1348d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		case 'i':
1349d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			ifname = optarg;
1350d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			break;
13518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		case 'M':
13528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (hwaddr_aton(optarg, eapol_test.own_addr)) {
13538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				usage();
13548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				return -1;
13558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			}
13568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
13578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		case 'n':
13588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			eapol_test.no_mppe_keys++;
13598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
13601f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		case 'o':
13611f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			if (eapol_test.server_cert_file)
13621f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				fclose(eapol_test.server_cert_file);
13631f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			eapol_test.server_cert_file = fopen(optarg, "w");
13641f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			if (eapol_test.server_cert_file == NULL) {
13651f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				printf("Could not open '%s' for writing\n",
13661f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				       optarg);
13671f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				return -1;
13681f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			}
13691f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			break;
13708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		case 'p':
13718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			as_port = atoi(optarg);
13728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
13732271d3fdd5982d0e5e81cf9999a861bba933eacbDmitry Shmidt		case 'P':
13742271d3fdd5982d0e5e81cf9999a861bba933eacbDmitry Shmidt			eapol_test.pcsc_pin = optarg;
13752271d3fdd5982d0e5e81cf9999a861bba933eacbDmitry Shmidt			break;
13768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		case 'r':
13778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			eapol_test.eapol_test_num_reauths = atoi(optarg);
13788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
13792271d3fdd5982d0e5e81cf9999a861bba933eacbDmitry Shmidt		case 'R':
13802271d3fdd5982d0e5e81cf9999a861bba933eacbDmitry Shmidt			eapol_test.pcsc_reader = optarg;
1381d30ac604c9f6da71a0dd7f46d25be05a2a62cfbbDmitry Shmidt			break;
13828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		case 's':
13838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			as_secret = optarg;
13848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
13858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		case 'S':
13868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			save_config++;
13878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
13888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		case 't':
13898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			timeout = atoi(optarg);
13908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
1391d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		case 'T':
1392d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			ctrl_iface = optarg;
1393d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			eapol_test.ctrl_iface = 1;
1394d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			break;
1395d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		case 'v':
1396d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			printf("eapol_test v" VERSION_STR "\n");
1397d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt			return 0;
13988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		case 'W':
13998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wait_for_monitor++;
14008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
14018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		case 'N':
1402a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt			p1 = os_zalloc(sizeof(*p1));
14038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (p1 == NULL)
14048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				break;
14058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (!p)
14068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				eapol_test.extra_attrs = p1;
14078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			else
14088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				p->next = p1;
14098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			p = p1;
14108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			p->type = atoi(optarg);
14128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			pos = os_strchr(optarg, ':');
14138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (pos == NULL) {
14148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				p->syntax = 'n';
14158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				p->data = NULL;
14168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				break;
14178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			}
14188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			pos++;
14208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (pos[0] == '\0' || pos[1] != ':') {
14218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				printf("Incorrect format of attribute "
14228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       "specification\n");
14238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				break;
14248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			}
14258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			p->syntax = pos[0];
14278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			p->data = pos + 2;
14288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
14298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		default:
14308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			usage();
14318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
14328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
14338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
14348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (argc > optind && os_strcmp(argv[optind], "scard") == 0) {
14362271d3fdd5982d0e5e81cf9999a861bba933eacbDmitry Shmidt		return scard_test(&eapol_test);
14378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
14388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (argc > optind && os_strcmp(argv[optind], "sim") == 0) {
14402271d3fdd5982d0e5e81cf9999a861bba933eacbDmitry Shmidt		return scard_get_triplets(&eapol_test, argc - optind - 1,
14418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					  &argv[optind + 1]);
14428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
14438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1444d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	if (conf == NULL && !ctrl_iface) {
14458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		usage();
14468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		printf("Configuration file is required.\n");
14478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
14488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
14498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (eap_register_methods()) {
14518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_ERROR, "Failed to register EAP methods");
14528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
14538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
14548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (eloop_init()) {
14568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_ERROR, "Failed to initialize event loop");
14578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
14588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
14598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1460051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt	os_memset(&global, 0, sizeof(global));
14618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memset(&wpa_s, 0, sizeof(wpa_s));
1462051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt	wpa_s.global = &global;
14638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eapol_test.wpa_s = &wpa_s;
1464051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt	dl_list_init(&wpa_s.bss);
1465051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt	dl_list_init(&wpa_s.bss_id);
1466d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	if (conf)
1467d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		wpa_s.conf = wpa_config_read(conf, NULL);
1468d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	else
1469d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		wpa_s.conf = wpa_config_alloc_empty(ctrl_iface, NULL);
14708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_s.conf == NULL) {
14718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		printf("Failed to parse configuration file '%s'.\n", conf);
14728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
14738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1474d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	if (!ctrl_iface && wpa_s.conf->ssid == NULL) {
14758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		printf("No networks defined.\n");
14768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
14778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
14788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14792271d3fdd5982d0e5e81cf9999a861bba933eacbDmitry Shmidt	if (eapol_test.pcsc_reader) {
14802271d3fdd5982d0e5e81cf9999a861bba933eacbDmitry Shmidt		os_free(wpa_s.conf->pcsc_reader);
14812271d3fdd5982d0e5e81cf9999a861bba933eacbDmitry Shmidt		wpa_s.conf->pcsc_reader = os_strdup(eapol_test.pcsc_reader);
14822271d3fdd5982d0e5e81cf9999a861bba933eacbDmitry Shmidt	}
14832271d3fdd5982d0e5e81cf9999a861bba933eacbDmitry Shmidt
14848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_init_conf(&eapol_test, &wpa_s, as_addr, as_port, as_secret,
1485d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		      cli_addr, ifname);
14868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_s.ctrl_iface = wpa_supplicant_ctrl_iface_init(&wpa_s);
14878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_s.ctrl_iface == NULL) {
14888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		printf("Failed to initialize control interface '%s'.\n"
14898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		       "You may have another eapol_test process already "
14908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		       "running or the file was\n"
14918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		       "left by an unclean termination of eapol_test in "
14928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		       "which case you will need\n"
14938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		       "to manually remove this file before starting "
14948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		       "eapol_test again.\n",
14958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		       wpa_s.conf->ctrl_interface);
14968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
14978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1498d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	if (wpa_s.conf->ssid &&
1499d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	    wpa_supplicant_scard_init(&wpa_s, wpa_s.conf->ssid))
15008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
15018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (test_eapol(&eapol_test, &wpa_s, wpa_s.conf->ssid))
15038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
15048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
150561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (wpas_init_ext_pw(&wpa_s) < 0)
150661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		return -1;
150761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
15088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wait_for_monitor)
15098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_supplicant_ctrl_iface_wait(wpa_s.ctrl_iface);
15108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1511d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	if (!ctrl_iface) {
1512d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		eloop_register_timeout(timeout, 0, eapol_test_timeout,
1513d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt				       &eapol_test, NULL);
1514d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt		eloop_register_timeout(0, 0, send_eap_request_identity, &wpa_s,
1515d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt				       NULL);
1516d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	}
15178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_register_signal_terminate(eapol_test_terminate, &wpa_s);
15188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_register_signal_reconfig(eapol_test_terminate, &wpa_s);
15198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_run();
15208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_cancel_timeout(eapol_test_timeout, &eapol_test, NULL);
15228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_cancel_timeout(eapol_sm_reauth, &eapol_test, NULL);
15238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (eapol_test_compare_pmk(&eapol_test) == 0 ||
15258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    eapol_test.no_mppe_keys)
15268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ret = 0;
15278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (eapol_test.auth_timed_out)
15288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ret = -2;
15298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (eapol_test.radius_access_reject_received)
15308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ret = -3;
15318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (save_config)
15338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_config_write(conf, wpa_s.conf);
15348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	test_eapol_clean(&eapol_test, &wpa_s);
15368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eap_peer_unregister_methods();
15388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_AP
15398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eap_server_unregister_methods();
15408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_AP */
15418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_destroy();
15438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15441f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (eapol_test.server_cert_file)
15451f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		fclose(eapol_test.server_cert_file);
15461f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
15478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	printf("MPPE keys OK: %d  mismatch: %d\n",
15488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	       eapol_test.num_mppe_ok, eapol_test.num_mppe_mismatch);
15498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (eapol_test.num_mppe_mismatch)
15508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ret = -4;
15518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ret)
15528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		printf("FAILURE\n");
15538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else
15548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		printf("SUCCESS\n");
15558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_program_deinit();
15578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return ret;
15598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1560