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"
178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "config.h"
188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "eapol_supp/eapol_supp_sm.h"
198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "eap_peer/eap.h"
208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "eap_server/eap_methods.h"
218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "eloop.h"
221f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#include "utils/base64.h"
238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "rsn_supp/wpa.h"
248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "wpa_supplicant_i.h"
258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "radius/radius.h"
268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "radius/radius_client.h"
27c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt#include "common/wpa_ctrl.h"
288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "ctrl_iface.h"
298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "pcsc_funcs.h"
30051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt#include "wpas_glue.h"
318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct wpa_driver_ops *wpa_drivers[] = { NULL };
348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct extra_radius_attr {
378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 type;
388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char syntax;
398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char *data;
408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct extra_radius_attr *next;
418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt};
428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct eapol_test_data {
448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_supplicant *wpa_s;
458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int eapol_test_num_reauths;
478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int no_mppe_keys;
488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int num_mppe_ok, num_mppe_mismatch;
495a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	int req_eap_key_name;
508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 radius_identifier;
528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct radius_msg *last_recv_radius;
538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct in_addr own_ip_addr;
548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct radius_client_data *radius;
558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct hostapd_radius_servers *radius_conf;
568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	 /* last received EAP Response from Authentication Server */
5861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	struct wpabuf *last_eap_radius;
598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 authenticator_pmk[PMK_LEN];
618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t authenticator_pmk_len;
625a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	u8 authenticator_eap_key_name[256];
635a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	size_t authenticator_eap_key_name_len;
648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int radius_access_accept_received;
658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int radius_access_reject_received;
668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int auth_timed_out;
678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 *eap_identity;
698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t eap_identity_len;
708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char *connect_info;
728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 own_addr[ETH_ALEN];
738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct extra_radius_attr *extra_attrs;
741f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
751f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	FILE *server_cert_file;
762271d3fdd5982d0e5e81cf9999a861bba933eacbDmitry Shmidt
772271d3fdd5982d0e5e81cf9999a861bba933eacbDmitry Shmidt	const char *pcsc_reader;
782271d3fdd5982d0e5e81cf9999a861bba933eacbDmitry Shmidt	const char *pcsc_pin;
798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt};
808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct eapol_test_data eapol_test;
828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void send_eap_request_identity(void *eloop_ctx, void *timeout_ctx);
858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void hostapd_logger_cb(void *ctx, const u8 *addr, unsigned int module,
888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			      int level, const char *txt, size_t len)
898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (addr)
918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "STA " MACSTR ": %s\n",
928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   MAC2STR(addr), txt);
938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else
948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "%s", txt);
958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int add_extra_attr(struct radius_msg *msg,
998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  struct extra_radius_attr *attr)
1008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t len;
1028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char *pos;
1038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u32 val;
104a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	char buf[RADIUS_MAX_ATTR_LEN + 1];
1058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	switch (attr->syntax) {
1078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case 's':
1088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_snprintf(buf, sizeof(buf), "%s", attr->data);
1098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		len = os_strlen(buf);
1108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
1118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case 'n':
1128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		buf[0] = '\0';
1138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		len = 1;
1148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
1158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case 'x':
1168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos = attr->data;
1178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (pos[0] == '0' && pos[1] == 'x')
1188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			pos += 2;
1198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		len = os_strlen(pos);
120a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		if ((len & 1) || (len / 2) > RADIUS_MAX_ATTR_LEN) {
1218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			printf("Invalid extra attribute hexstring\n");
1228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
1238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
1248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		len /= 2;
1258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (hexstr2bin(pos, (u8 *) buf, len) < 0) {
1268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			printf("Invalid extra attribute hexstring\n");
1278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
1288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
1298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
1308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case 'd':
1318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		val = htonl(atoi(attr->data));
1328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(buf, &val, 4);
1338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		len = 4;
1348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
1358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	default:
1368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		printf("Incorrect extra attribute syntax specification\n");
1378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
1388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!radius_msg_add_attr(msg, attr->type, (u8 *) buf, len)) {
1418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		printf("Could not add attribute %d\n", attr->type);
1428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
1438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
1468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int add_extra_attrs(struct radius_msg *msg,
1508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   struct extra_radius_attr *attrs)
1518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct extra_radius_attr *p;
1538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (p = attrs; p; p = p->next) {
1548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (add_extra_attr(msg, p) < 0)
1558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
1568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
1588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct extra_radius_attr *
1628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtfind_extra_attr(struct extra_radius_attr *attrs, u8 type)
1638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct extra_radius_attr *p;
1658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (p = attrs; p; p = p->next) {
1668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (p->type == type)
1678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return p;
1688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return NULL;
1708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void ieee802_1x_encapsulate_radius(struct eapol_test_data *e,
1748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					  const u8 *eap, size_t len)
1758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct radius_msg *msg;
177a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	char buf[RADIUS_MAX_ATTR_LEN + 1];
1788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const struct eap_hdr *hdr;
1798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const u8 *pos;
1808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "Encapsulating EAP message into a RADIUS "
1828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   "packet");
1838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	e->radius_identifier = radius_client_get_id(e->radius);
1858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	msg = radius_msg_new(RADIUS_CODE_ACCESS_REQUEST,
1868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			     e->radius_identifier);
1878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (msg == NULL) {
1888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		printf("Could not create net RADIUS packet\n");
1898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
1908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	radius_msg_make_authenticator(msg, (u8 *) e, sizeof(*e));
1938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	hdr = (const struct eap_hdr *) eap;
1958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos = (const u8 *) (hdr + 1);
1968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (len > sizeof(*hdr) && hdr->code == EAP_CODE_RESPONSE &&
1978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    pos[0] == EAP_TYPE_IDENTITY) {
1988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos++;
1998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(e->eap_identity);
2008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		e->eap_identity_len = len - sizeof(*hdr) - 1;
2018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		e->eap_identity = os_malloc(e->eap_identity_len);
2028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (e->eap_identity) {
2038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			os_memcpy(e->eap_identity, pos, e->eap_identity_len);
2048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_hexdump(MSG_DEBUG, "Learned identity from "
2058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				    "EAP-Response-Identity",
2068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				    e->eap_identity, e->eap_identity_len);
2078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
2088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (e->eap_identity &&
2118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    !radius_msg_add_attr(msg, RADIUS_ATTR_USER_NAME,
2128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				 e->eap_identity, e->eap_identity_len)) {
2138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		printf("Could not add User-Name\n");
2148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto fail;
2158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2175a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (e->req_eap_key_name &&
2185a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	    !radius_msg_add_attr(msg, RADIUS_ATTR_EAP_KEY_NAME, (u8 *) "\0",
2195a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt				 1)) {
2205a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		printf("Could not add EAP-Key-Name\n");
2215a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		goto fail;
2225a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
2235a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
2248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!find_extra_attr(e->extra_attrs, RADIUS_ATTR_NAS_IP_ADDRESS) &&
2258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    !radius_msg_add_attr(msg, RADIUS_ATTR_NAS_IP_ADDRESS,
2268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				 (u8 *) &e->own_ip_addr, 4)) {
2278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		printf("Could not add NAS-IP-Address\n");
2288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto fail;
2298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_snprintf(buf, sizeof(buf), RADIUS_802_1X_ADDR_FORMAT,
2328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    MAC2STR(e->wpa_s->own_addr));
2338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!find_extra_attr(e->extra_attrs, RADIUS_ATTR_CALLING_STATION_ID)
2348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    &&
2358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    !radius_msg_add_attr(msg, RADIUS_ATTR_CALLING_STATION_ID,
2368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				 (u8 *) buf, os_strlen(buf))) {
2378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		printf("Could not add Calling-Station-Id\n");
2388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto fail;
2398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* TODO: should probably check MTU from driver config; 2304 is max for
2428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * IEEE 802.11, but use 1400 to avoid problems with too large packets
2438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 */
2448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!find_extra_attr(e->extra_attrs, RADIUS_ATTR_FRAMED_MTU) &&
2458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    !radius_msg_add_attr_int32(msg, RADIUS_ATTR_FRAMED_MTU, 1400)) {
2468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		printf("Could not add Framed-MTU\n");
2478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto fail;
2488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!find_extra_attr(e->extra_attrs, RADIUS_ATTR_NAS_PORT_TYPE) &&
2518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    !radius_msg_add_attr_int32(msg, RADIUS_ATTR_NAS_PORT_TYPE,
2528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       RADIUS_NAS_PORT_TYPE_IEEE_802_11)) {
2538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		printf("Could not add NAS-Port-Type\n");
2548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto fail;
2558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_snprintf(buf, sizeof(buf), "%s", e->connect_info);
2588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!find_extra_attr(e->extra_attrs, RADIUS_ATTR_CONNECT_INFO) &&
2598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    !radius_msg_add_attr(msg, RADIUS_ATTR_CONNECT_INFO,
2608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				 (u8 *) buf, os_strlen(buf))) {
2618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		printf("Could not add Connect-Info\n");
2628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto fail;
2638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (add_extra_attrs(msg, e->extra_attrs) < 0)
2668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto fail;
2678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (eap && !radius_msg_add_eap(msg, eap, len)) {
2698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		printf("Could not add EAP-Message\n");
2708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto fail;
2718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* State attribute must be copied if and only if this packet is
2748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * Access-Request reply to the previous Access-Challenge */
2758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (e->last_recv_radius &&
2768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    radius_msg_get_hdr(e->last_recv_radius)->code ==
2778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    RADIUS_CODE_ACCESS_CHALLENGE) {
2788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		int res = radius_msg_copy_attr(msg, e->last_recv_radius,
2798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					       RADIUS_ATTR_STATE);
2808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (res < 0) {
2818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			printf("Could not copy State attribute from previous "
2828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			       "Access-Challenge\n");
2838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			goto fail;
2848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
2858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (res > 0) {
2868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "  Copied RADIUS State "
2878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "Attribute");
2888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
2898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
29104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	if (radius_client_send(e->radius, msg, RADIUS_AUTH, e->wpa_s->own_addr)
29204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	    < 0)
29304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		goto fail;
2948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return;
2958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt fail:
2978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	radius_msg_free(msg);
2988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
2998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int eapol_test_eapol_send(void *ctx, int type, const u8 *buf,
3028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				 size_t len)
3038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
3048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	printf("WPA: eapol_test_eapol_send(type=%d len=%lu)\n",
3058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	       type, (unsigned long) len);
3068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (type == IEEE802_1X_TYPE_EAP_PACKET) {
3078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_hexdump(MSG_DEBUG, "TX EAP -> RADIUS", buf, len);
3088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ieee802_1x_encapsulate_radius(&eapol_test, buf, len);
3098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
3118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
3128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eapol_test_set_config_blob(void *ctx,
3158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       struct wpa_config_blob *blob)
3168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
3171f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	struct eapol_test_data *e = ctx;
3181f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	wpa_config_set_blob(e->wpa_s->conf, blob);
3198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
3208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic const struct wpa_config_blob *
3238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidteapol_test_get_config_blob(void *ctx, const char *name)
3248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
3251f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	struct eapol_test_data *e = ctx;
3261f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	return wpa_config_get_blob(e->wpa_s->conf, name);
3278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
3288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eapol_test_eapol_done_cb(void *ctx)
3318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
3328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	printf("WPA: EAPOL processing complete\n");
3338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
3348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eapol_sm_reauth(void *eloop_ctx, void *timeout_ctx)
3378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
3388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct eapol_test_data *e = eloop_ctx;
3398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	printf("\n\n\n\n\neapol_test: Triggering EAP reauthentication\n\n");
3408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	e->radius_access_accept_received = 0;
3418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	send_eap_request_identity(e->wpa_s, NULL);
3428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
3438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int eapol_test_compare_pmk(struct eapol_test_data *e)
3468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
3478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 pmk[PMK_LEN];
3488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int ret = 1;
3495a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	const u8 *sess_id;
3505a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	size_t sess_id_len;
3518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (eapol_sm_get_key(e->wpa_s->eapol, pmk, PMK_LEN) == 0) {
3538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_hexdump(MSG_DEBUG, "PMK from EAPOL", pmk, PMK_LEN);
3548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (os_memcmp(pmk, e->authenticator_pmk, PMK_LEN) != 0) {
3558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			printf("WARNING: PMK mismatch\n");
3568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_hexdump(MSG_DEBUG, "PMK from AS",
3578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				    e->authenticator_pmk, PMK_LEN);
3588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		} else if (e->radius_access_accept_received)
3598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			ret = 0;
3608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else if (e->authenticator_pmk_len == 16 &&
3618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   eapol_sm_get_key(e->wpa_s->eapol, pmk, 16) == 0) {
3628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_hexdump(MSG_DEBUG, "LEAP PMK from EAPOL", pmk, 16);
3638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (os_memcmp(pmk, e->authenticator_pmk, 16) != 0) {
3648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			printf("WARNING: PMK mismatch\n");
3658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_hexdump(MSG_DEBUG, "PMK from AS",
3668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				    e->authenticator_pmk, 16);
3678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		} else if (e->radius_access_accept_received)
3688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			ret = 0;
3698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else if (e->radius_access_accept_received && e->no_mppe_keys) {
3708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* No keying material expected */
3718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ret = 0;
3728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ret && !e->no_mppe_keys)
3758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		e->num_mppe_mismatch++;
3768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else if (!e->no_mppe_keys)
3778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		e->num_mppe_ok++;
3788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3795a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	sess_id = eapol_sm_get_session_id(e->wpa_s->eapol, &sess_id_len);
3805a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (!sess_id)
3815a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return ret;
3825a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (e->authenticator_eap_key_name_len == 0) {
3835a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		wpa_printf(MSG_INFO, "No EAP-Key-Name received from server");
3845a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return ret;
3855a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
3865a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
3875a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (e->authenticator_eap_key_name_len != sess_id_len ||
3885a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	    os_memcmp(e->authenticator_eap_key_name, sess_id, sess_id_len) != 0)
3895a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	{
3905a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		wpa_printf(MSG_INFO,
3915a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			   "Locally derived EAP Session-Id does not match EAP-Key-Name from server");
3925a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		wpa_hexdump(MSG_DEBUG, "EAP Session-Id", sess_id, sess_id_len);
3935a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		wpa_hexdump(MSG_DEBUG, "EAP-Key-Name from server",
3945a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			    e->authenticator_eap_key_name,
3955a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			    e->authenticator_eap_key_name_len);
3965a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	} else {
3975a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		wpa_printf(MSG_INFO,
3985a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			   "Locally derived EAP Session-Id matches EAP-Key-Name from server");
3995a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
4005a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
4018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return ret;
4028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
4038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
405344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidtstatic void eapol_sm_cb(struct eapol_sm *eapol, enum eapol_supp_result result,
406344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt			void *ctx)
4078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
4088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct eapol_test_data *e = ctx;
409344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt	printf("eapol_sm_cb: result=%d\n", result);
4108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	e->eapol_test_num_reauths--;
4118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (e->eapol_test_num_reauths < 0)
4128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eloop_terminate();
4138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else {
4148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eapol_test_compare_pmk(e);
4158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eloop_register_timeout(0, 100000, eapol_sm_reauth, e, NULL);
4168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
4178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
4188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4201f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstatic void eapol_test_write_cert(FILE *f, const char *subject,
4211f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				  const struct wpabuf *cert)
4221f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{
4231f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	unsigned char *encoded;
4241f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
4251f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	encoded = base64_encode(wpabuf_head(cert), wpabuf_len(cert), NULL);
4261f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (encoded == NULL)
4271f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		return;
4281f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	fprintf(f, "%s\n-----BEGIN CERTIFICATE-----\n%s"
4291f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		"-----END CERTIFICATE-----\n\n", subject, encoded);
4301f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	os_free(encoded);
4311f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt}
4321f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
4331f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
434051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt#if defined(CONFIG_CTRL_IFACE) || !defined(CONFIG_NO_STDOUT_DEBUG)
435051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidtstatic void eapol_test_eap_param_needed(void *ctx, enum wpa_ctrl_req_type field,
436051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt					const char *default_txt)
437051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt{
438051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt	struct eapol_test_data *e = ctx;
439051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt	struct wpa_supplicant *wpa_s = e->wpa_s;
440051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt	struct wpa_ssid *ssid = wpa_s->current_ssid;
441051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt	const char *field_name, *txt = NULL;
442051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt	char *buf;
443051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt	size_t buflen;
444051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt	int len;
445051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt
446051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt	if (ssid == NULL)
447051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt		return;
448051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt
449051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt	field_name = wpa_supplicant_ctrl_req_to_string(field, default_txt,
450051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt						       &txt);
451051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt	if (field_name == NULL) {
452051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt		wpa_printf(MSG_WARNING, "Unhandled EAP param %d needed",
453051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt			   field);
454051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt		return;
455051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt	}
456051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt
457051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt	buflen = 100 + os_strlen(txt) + ssid->ssid_len;
458051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt	buf = os_malloc(buflen);
459051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt	if (buf == NULL)
460051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt		return;
461051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt	len = os_snprintf(buf, buflen,
462051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt			  WPA_CTRL_REQ "%s-%d:%s needed for SSID ",
463051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt			  field_name, ssid->id, txt);
464051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt	if (len < 0 || (size_t) len >= buflen) {
465051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt		os_free(buf);
466051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt		return;
467051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt	}
468051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt	if (ssid->ssid && buflen > len + ssid->ssid_len) {
469051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt		os_memcpy(buf + len, ssid->ssid, ssid->ssid_len);
470051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt		len += ssid->ssid_len;
471051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt		buf[len] = '\0';
472051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt	}
473051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt	buf[buflen - 1] = '\0';
474051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt	wpa_msg(wpa_s, MSG_INFO, "%s", buf);
475051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt	os_free(buf);
476051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt}
477051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt#else /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */
478051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt#define eapol_test_eap_param_needed NULL
479051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt#endif /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */
480051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt
481051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt
482c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidtstatic void eapol_test_cert_cb(void *ctx, int depth, const char *subject,
483c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt			       const char *cert_hash,
484c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt			       const struct wpabuf *cert)
485c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt{
486c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt	struct eapol_test_data *e = ctx;
487c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt
488c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt	wpa_msg(e->wpa_s, MSG_INFO, WPA_EVENT_EAP_PEER_CERT
489c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt		"depth=%d subject='%s'%s%s",
490c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt		depth, subject,
491c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt		cert_hash ? " hash=" : "",
492c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt		cert_hash ? cert_hash : "");
493c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt
494c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt	if (cert) {
495c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt		char *cert_hex;
496c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt		size_t len = wpabuf_len(cert) * 2 + 1;
497c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt		cert_hex = os_malloc(len);
498c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt		if (cert_hex) {
499c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt			wpa_snprintf_hex(cert_hex, len, wpabuf_head(cert),
500c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt					 wpabuf_len(cert));
501c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt			wpa_msg_ctrl(e->wpa_s, MSG_INFO,
502c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt				     WPA_EVENT_EAP_PEER_CERT
503c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt				     "depth=%d subject='%s' cert=%s",
504c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt				     depth, subject, cert_hex);
505c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt			os_free(cert_hex);
506c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt		}
5071f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
5081f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		if (e->server_cert_file)
5091f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			eapol_test_write_cert(e->server_cert_file,
5101f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt					      subject, cert);
511c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt	}
512c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt}
513c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt
514c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt
5154530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidtstatic void eapol_test_set_anon_id(void *ctx, const u8 *id, size_t len)
5164530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt{
5174530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	struct eapol_test_data *e = ctx;
5184530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	struct wpa_supplicant *wpa_s = e->wpa_s;
5194530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	char *str;
5204530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	int res;
5214530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
5224530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	wpa_hexdump_ascii(MSG_DEBUG, "EAP method updated anonymous_identity",
5234530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt			  id, len);
5244530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
5254530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	if (wpa_s->current_ssid == NULL)
5264530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		return;
5274530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
5284530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	if (id == NULL) {
5294530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		if (wpa_config_set(wpa_s->current_ssid, "anonymous_identity",
5304530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt				   "NULL", 0) < 0)
5314530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt			return;
5324530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	} else {
5334530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		str = os_malloc(len * 2 + 1);
5344530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		if (str == NULL)
5354530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt			return;
5364530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		wpa_snprintf_hex(str, len * 2 + 1, id, len);
5374530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		res = wpa_config_set(wpa_s->current_ssid, "anonymous_identity",
5384530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt				     str, 0);
5394530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		os_free(str);
5404530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		if (res < 0)
5414530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt			return;
5424530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	}
5434530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt}
5444530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
5454530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
5468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int test_eapol(struct eapol_test_data *e, struct wpa_supplicant *wpa_s,
5478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		      struct wpa_ssid *ssid)
5488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
5498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct eapol_config eapol_conf;
5508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct eapol_ctx *ctx;
5518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ctx = os_zalloc(sizeof(*ctx));
5538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ctx == NULL) {
5548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		printf("Failed to allocate EAPOL context.\n");
5558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
5568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
5571f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	ctx->ctx = e;
5588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ctx->msg_ctx = wpa_s;
5598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ctx->scard_ctx = wpa_s->scard;
5608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ctx->cb = eapol_sm_cb;
5618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ctx->cb_ctx = e;
5628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ctx->eapol_send_ctx = wpa_s;
5638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ctx->preauth = 0;
5648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ctx->eapol_done_cb = eapol_test_eapol_done_cb;
5658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ctx->eapol_send = eapol_test_eapol_send;
5668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ctx->set_config_blob = eapol_test_set_config_blob;
5678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ctx->get_config_blob = eapol_test_get_config_blob;
5688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ctx->opensc_engine_path = wpa_s->conf->opensc_engine_path;
5698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ctx->pkcs11_engine_path = wpa_s->conf->pkcs11_engine_path;
5708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ctx->pkcs11_module_path = wpa_s->conf->pkcs11_module_path;
571051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt	ctx->eap_param_needed = eapol_test_eap_param_needed;
572c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt	ctx->cert_cb = eapol_test_cert_cb;
5731f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	ctx->cert_in_cb = 1;
5744530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	ctx->set_anon_id = eapol_test_set_anon_id;
5758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_s->eapol = eapol_sm_init(ctx);
5778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_s->eapol == NULL) {
5788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(ctx);
5798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		printf("Failed to initialize EAPOL state machines.\n");
5808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
5818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
5828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_s->current_ssid = ssid;
5848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memset(&eapol_conf, 0, sizeof(eapol_conf));
5858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eapol_conf.accept_802_1x_keys = 1;
5868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eapol_conf.required_keys = 0;
5878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eapol_conf.fast_reauth = wpa_s->conf->fast_reauth;
5888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eapol_conf.workaround = ssid->eap_workaround;
589051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt	eapol_conf.external_sim = wpa_s->conf->external_sim;
5908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eapol_sm_notify_config(wpa_s->eapol, &ssid->eap, &eapol_conf);
5918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eapol_sm_register_scard_ctx(wpa_s->eapol, wpa_s->scard);
5928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eapol_sm_notify_portValid(wpa_s->eapol, FALSE);
5958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* 802.1X::portControl = Auto */
5968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eapol_sm_notify_portEnabled(wpa_s->eapol, TRUE);
5978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
5998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
6008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void test_eapol_clean(struct eapol_test_data *e,
6038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			     struct wpa_supplicant *wpa_s)
6048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
6058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct extra_radius_attr *p, *prev;
6068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	radius_client_deinit(e->radius);
60861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	wpabuf_free(e->last_eap_radius);
6098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	radius_msg_free(e->last_recv_radius);
6108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	e->last_recv_radius = NULL;
6118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(e->eap_identity);
6128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	e->eap_identity = NULL;
6138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eapol_sm_deinit(wpa_s->eapol);
6148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_s->eapol = NULL;
6158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (e->radius_conf && e->radius_conf->auth_server) {
6168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(e->radius_conf->auth_server->shared_secret);
6178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(e->radius_conf->auth_server);
6188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(e->radius_conf);
6208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	e->radius_conf = NULL;
6218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	scard_deinit(wpa_s->scard);
6228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_s->ctrl_iface) {
6238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_supplicant_ctrl_iface_deinit(wpa_s->ctrl_iface);
6248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_s->ctrl_iface = NULL;
6258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
62661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
62761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	ext_password_deinit(wpa_s->ext_pw);
62861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	wpa_s->ext_pw = NULL;
62961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
6308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_config_free(wpa_s->conf);
6318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p = e->extra_attrs;
6338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	while (p) {
6348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		prev = p;
6358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p = p->next;
6368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(prev);
6378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
6398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void send_eap_request_identity(void *eloop_ctx, void *timeout_ctx)
6428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
6438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_supplicant *wpa_s = eloop_ctx;
6448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 buf[100], *pos;
6458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct ieee802_1x_hdr *hdr;
6468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct eap_hdr *eap;
6478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	hdr = (struct ieee802_1x_hdr *) buf;
6498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	hdr->version = EAPOL_VERSION;
6508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	hdr->type = IEEE802_1X_TYPE_EAP_PACKET;
6518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	hdr->length = htons(5);
6528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eap = (struct eap_hdr *) (hdr + 1);
6548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eap->code = EAP_CODE_REQUEST;
6558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eap->identifier = 0;
6568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eap->length = htons(5);
6578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos = (u8 *) (eap + 1);
6588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	*pos = EAP_TYPE_IDENTITY;
6598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	printf("Sending fake EAP-Request-Identity\n");
6618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eapol_sm_rx_eapol(wpa_s->eapol, wpa_s->bssid, buf,
6628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  sizeof(*hdr) + 5);
6638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
6648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eapol_test_timeout(void *eloop_ctx, void *timeout_ctx)
6678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
6688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct eapol_test_data *e = eloop_ctx;
6698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	printf("EAPOL test timed out\n");
6708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	e->auth_timed_out = 1;
6718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_terminate();
6728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
6738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic char *eap_type_text(u8 type)
6768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
6778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	switch (type) {
6788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case EAP_TYPE_IDENTITY: return "Identity";
6798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case EAP_TYPE_NOTIFICATION: return "Notification";
6808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case EAP_TYPE_NAK: return "Nak";
6818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case EAP_TYPE_TLS: return "TLS";
6828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case EAP_TYPE_TTLS: return "TTLS";
6838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case EAP_TYPE_PEAP: return "PEAP";
6848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case EAP_TYPE_SIM: return "SIM";
6858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case EAP_TYPE_GTC: return "GTC";
6868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case EAP_TYPE_MD5: return "MD5";
6878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case EAP_TYPE_OTP: return "OTP";
6888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case EAP_TYPE_FAST: return "FAST";
6898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case EAP_TYPE_SAKE: return "SAKE";
6908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case EAP_TYPE_PSK: return "PSK";
6918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	default: return "Unknown";
6928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
6948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void ieee802_1x_decapsulate_radius(struct eapol_test_data *e)
6978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
69861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	struct wpabuf *eap;
69961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	const struct eap_hdr *hdr;
7008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int eap_type = -1;
7018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char buf[64];
7028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct radius_msg *msg;
7038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (e->last_recv_radius == NULL)
7058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
7068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	msg = e->last_recv_radius;
7088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
70961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	eap = radius_msg_get_eap(msg);
7108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (eap == NULL) {
7118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* draft-aboba-radius-rfc2869bis-20.txt, Chap. 2.6.3:
7128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * RADIUS server SHOULD NOT send Access-Reject/no EAP-Message
7138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * attribute */
7148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "could not extract "
7158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			       "EAP-Message from RADIUS message");
71661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		wpabuf_free(e->last_eap_radius);
7178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		e->last_eap_radius = NULL;
7188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
7198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
7208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
72161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (wpabuf_len(eap) < sizeof(*hdr)) {
7228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "too short EAP packet "
7238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			       "received from authentication server");
72461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		wpabuf_free(eap);
7258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
7268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
7278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
72861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (wpabuf_len(eap) > sizeof(*hdr))
72961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		eap_type = (wpabuf_head_u8(eap))[sizeof(*hdr)];
7308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
73161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	hdr = wpabuf_head(eap);
7328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	switch (hdr->code) {
7338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case EAP_CODE_REQUEST:
7348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_snprintf(buf, sizeof(buf), "EAP-Request-%s (%d)",
7358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    eap_type >= 0 ? eap_type_text(eap_type) : "??",
7368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    eap_type);
7378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
7388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case EAP_CODE_RESPONSE:
7398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_snprintf(buf, sizeof(buf), "EAP Response-%s (%d)",
7408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    eap_type >= 0 ? eap_type_text(eap_type) : "??",
7418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    eap_type);
7428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
7438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case EAP_CODE_SUCCESS:
7448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_strlcpy(buf, "EAP Success", sizeof(buf));
7458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* LEAP uses EAP Success within an authentication, so must not
7468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * stop here with eloop_terminate(); */
7478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
7488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case EAP_CODE_FAILURE:
7498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_strlcpy(buf, "EAP Failure", sizeof(buf));
7508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eloop_terminate();
7518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
7528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	default:
7538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_strlcpy(buf, "unknown EAP code", sizeof(buf));
75461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		wpa_hexdump_buf(MSG_DEBUG, "Decapsulated EAP packet", eap);
7558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
7568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
7578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "decapsulated EAP packet (code=%d "
7588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		       "id=%d len=%d) from RADIUS server: %s",
7598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		      hdr->code, hdr->identifier, ntohs(hdr->length), buf);
7608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* sta->eapol_sm->be_auth.idFromServer = hdr->identifier; */
7628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
76361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	wpabuf_free(e->last_eap_radius);
7648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	e->last_eap_radius = eap;
7658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	{
7678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		struct ieee802_1x_hdr *dot1x;
76861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		dot1x = os_malloc(sizeof(*dot1x) + wpabuf_len(eap));
7698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		assert(dot1x != NULL);
7708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dot1x->version = EAPOL_VERSION;
7718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dot1x->type = IEEE802_1X_TYPE_EAP_PACKET;
77261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		dot1x->length = htons(wpabuf_len(eap));
77361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		os_memcpy((u8 *) (dot1x + 1), wpabuf_head(eap),
77461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			  wpabuf_len(eap));
7758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eapol_sm_rx_eapol(e->wpa_s->eapol, e->wpa_s->bssid,
77661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt				  (u8 *) dot1x,
77761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt				  sizeof(*dot1x) + wpabuf_len(eap));
7788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(dot1x);
7798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
7808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
7818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void ieee802_1x_get_keys(struct eapol_test_data *e,
7848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				struct radius_msg *msg, struct radius_msg *req,
7858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				const u8 *shared_secret,
7868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				size_t shared_secret_len)
7878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
7888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct radius_ms_mppe_keys *keys;
7895a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	u8 *buf;
7905a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	size_t len;
7918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	keys = radius_msg_get_ms_keys(msg, req, shared_secret,
7938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				      shared_secret_len);
7948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (keys && keys->send == NULL && keys->recv == NULL) {
7958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(keys);
7968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		keys = radius_msg_get_cisco_keys(msg, req, shared_secret,
7978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						 shared_secret_len);
7988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
7998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (keys) {
8018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (keys->send) {
8028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_hexdump(MSG_DEBUG, "MS-MPPE-Send-Key (sign)",
8038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				    keys->send, keys->send_len);
8048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
8058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (keys->recv) {
8068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_hexdump(MSG_DEBUG, "MS-MPPE-Recv-Key (crypt)",
8078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				    keys->recv, keys->recv_len);
8088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			e->authenticator_pmk_len =
8098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				keys->recv_len > PMK_LEN ? PMK_LEN :
8108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				keys->recv_len;
8118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			os_memcpy(e->authenticator_pmk, keys->recv,
8128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  e->authenticator_pmk_len);
8138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (e->authenticator_pmk_len == 16 && keys->send &&
8148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    keys->send_len == 16) {
8158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				/* MS-CHAP-v2 derives 16 octet keys */
8168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				wpa_printf(MSG_DEBUG, "Use MS-MPPE-Send-Key "
8178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   "to extend PMK to 32 octets");
8188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				os_memcpy(e->authenticator_pmk +
8198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					  e->authenticator_pmk_len,
8208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					  keys->send, keys->send_len);
8218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				e->authenticator_pmk_len += keys->send_len;
8228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			}
8238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
8248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(keys->send);
8268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(keys->recv);
8278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(keys);
8288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
8295a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
8305a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (radius_msg_get_attr_ptr(msg, RADIUS_ATTR_EAP_KEY_NAME, &buf, &len,
8315a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt				    NULL) == 0) {
8325a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		os_memcpy(e->authenticator_eap_key_name, buf, len);
8335a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		e->authenticator_eap_key_name_len = len;
8345a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	} else {
8355a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		e->authenticator_eap_key_name_len = 0;
8365a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
8378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
8388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* Process the RADIUS frames from Authentication Server */
8418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic RadiusRxResult
8428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtieee802_1x_receive_auth(struct radius_msg *msg, struct radius_msg *req,
8438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			const u8 *shared_secret, size_t shared_secret_len,
8448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			void *data)
8458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
8468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct eapol_test_data *e = data;
8478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct radius_hdr *hdr = radius_msg_get_hdr(msg);
8488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* RFC 2869, Ch. 5.13: valid Message-Authenticator attribute MUST be
8508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * present when packet contains an EAP-Message attribute */
8518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (hdr->code == RADIUS_CODE_ACCESS_REJECT &&
8528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    radius_msg_get_attr(msg, RADIUS_ATTR_MESSAGE_AUTHENTICATOR, NULL,
8538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				0) < 0 &&
8548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    radius_msg_get_attr(msg, RADIUS_ATTR_EAP_MESSAGE, NULL, 0) < 0) {
8558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "Allowing RADIUS "
8568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			      "Access-Reject without Message-Authenticator "
8578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			      "since it does not include EAP-Message\n");
8588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else if (radius_msg_verify(msg, shared_secret, shared_secret_len,
8598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				     req, 1)) {
8608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		printf("Incoming RADIUS packet did not have correct "
8618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		       "Message-Authenticator - dropped\n");
8628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return RADIUS_RX_UNKNOWN;
8638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
8648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (hdr->code != RADIUS_CODE_ACCESS_ACCEPT &&
8668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    hdr->code != RADIUS_CODE_ACCESS_REJECT &&
8678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    hdr->code != RADIUS_CODE_ACCESS_CHALLENGE) {
8688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		printf("Unknown RADIUS message code\n");
8698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return RADIUS_RX_UNKNOWN;
8708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
8718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	e->radius_identifier = -1;
8738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "RADIUS packet matching with station");
8748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	radius_msg_free(e->last_recv_radius);
8768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	e->last_recv_radius = msg;
8778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	switch (hdr->code) {
8798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case RADIUS_CODE_ACCESS_ACCEPT:
8808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		e->radius_access_accept_received = 1;
8818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ieee802_1x_get_keys(e, msg, req, shared_secret,
8828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				    shared_secret_len);
8838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
8848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case RADIUS_CODE_ACCESS_REJECT:
8858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		e->radius_access_reject_received = 1;
8868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
8878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
8888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ieee802_1x_decapsulate_radius(e);
8908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if ((hdr->code == RADIUS_CODE_ACCESS_ACCEPT &&
8928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	     e->eapol_test_num_reauths < 0) ||
8938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    hdr->code == RADIUS_CODE_ACCESS_REJECT) {
8948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eloop_terminate();
8958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
8968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return RADIUS_RX_QUEUED;
8988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
8998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_init_conf(struct eapol_test_data *e,
9028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  struct wpa_supplicant *wpa_s, const char *authsrv,
9038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  int port, const char *secret,
9048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  const char *cli_addr)
9058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
9068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct hostapd_radius_server *as;
9078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int res;
9088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_s->bssid[5] = 1;
9108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(wpa_s->own_addr, e->own_addr, ETH_ALEN);
9118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	e->own_ip_addr.s_addr = htonl((127 << 24) | 1);
9128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_strlcpy(wpa_s->ifname, "test", sizeof(wpa_s->ifname));
9138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	e->radius_conf = os_zalloc(sizeof(struct hostapd_radius_servers));
9158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	assert(e->radius_conf != NULL);
9168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	e->radius_conf->num_auth_servers = 1;
9178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	as = os_zalloc(sizeof(struct hostapd_radius_server));
9188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	assert(as != NULL);
9198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#if defined(CONFIG_NATIVE_WINDOWS) || defined(CONFIG_ANSI_C_EXTRA)
9208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	{
9218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		int a[4];
9228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		u8 *pos;
9238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sscanf(authsrv, "%d.%d.%d.%d", &a[0], &a[1], &a[2], &a[3]);
9248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos = (u8 *) &as->addr.u.v4;
9258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		*pos++ = a[0];
9268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		*pos++ = a[1];
9278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		*pos++ = a[2];
9288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		*pos++ = a[3];
9298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
9308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#else /* CONFIG_NATIVE_WINDOWS or CONFIG_ANSI_C_EXTRA */
9318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	inet_aton(authsrv, &as->addr.u.v4);
9328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_NATIVE_WINDOWS or CONFIG_ANSI_C_EXTRA */
9338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	as->addr.af = AF_INET;
9348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	as->port = port;
9358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	as->shared_secret = (u8 *) os_strdup(secret);
9368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	as->shared_secret_len = os_strlen(secret);
9378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	e->radius_conf->auth_server = as;
9388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	e->radius_conf->auth_servers = as;
9398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	e->radius_conf->msg_dumps = 1;
9408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (cli_addr) {
9418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (hostapd_parse_ip_addr(cli_addr,
9428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					  &e->radius_conf->client_addr) == 0)
9438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			e->radius_conf->force_client_addr = 1;
9448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		else {
9458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_ERROR, "Invalid IP address '%s'",
9468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   cli_addr);
9478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			assert(0);
9488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
9498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
9508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	e->radius = radius_client_init(wpa_s, e->radius_conf);
9528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	assert(e->radius != NULL);
9538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	res = radius_client_register(e->radius, RADIUS_AUTH,
9558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				     ieee802_1x_receive_auth, e);
9568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	assert(res == 0);
9578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
9588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9602271d3fdd5982d0e5e81cf9999a861bba933eacbDmitry Shmidtstatic int scard_test(struct eapol_test_data *e)
9618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
9628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct scard_data *scard;
9638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t len;
9648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char imsi[20];
9658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	unsigned char _rand[16];
9668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef PCSC_FUNCS
9678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	unsigned char sres[4];
9688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	unsigned char kc[8];
9698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* PCSC_FUNCS */
9708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define num_triplets 5
9718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	unsigned char rand_[num_triplets][16];
9728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	unsigned char sres_[num_triplets][4];
9738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	unsigned char kc_[num_triplets][8];
9748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int i, res;
9758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t j;
9768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define AKA_RAND_LEN 16
9788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define AKA_AUTN_LEN 16
9798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define AKA_AUTS_LEN 14
9808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define RES_MAX_LEN 16
9818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define IK_LEN 16
9828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define CK_LEN 16
9838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	unsigned char aka_rand[AKA_RAND_LEN];
9848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	unsigned char aka_autn[AKA_AUTN_LEN];
9858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	unsigned char aka_auts[AKA_AUTS_LEN];
9868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	unsigned char aka_res[RES_MAX_LEN];
9878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t aka_res_len;
9888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	unsigned char aka_ik[IK_LEN];
9898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	unsigned char aka_ck[CK_LEN];
9908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9912271d3fdd5982d0e5e81cf9999a861bba933eacbDmitry Shmidt	scard = scard_init(e->pcsc_reader);
9928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (scard == NULL)
9938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
9942271d3fdd5982d0e5e81cf9999a861bba933eacbDmitry Shmidt	if (scard_set_pin(scard, e->pcsc_pin)) {
9958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_WARNING, "PIN validation failed");
9968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		scard_deinit(scard);
9978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
9988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
9998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	len = sizeof(imsi);
10018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (scard_get_imsi(scard, imsi, &len))
10028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto failed;
10038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump_ascii(MSG_DEBUG, "SCARD: IMSI", (u8 *) imsi, len);
10048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* NOTE: Permanent Username: 1 | IMSI */
10058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1006c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	wpa_printf(MSG_DEBUG, "SCARD: MNC length %d",
1007c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt		   scard_get_mnc_len(scard));
1008c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt
10098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memset(_rand, 0, sizeof(_rand));
10108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (scard_gsm_auth(scard, _rand, sres, kc))
10118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto failed;
10128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memset(_rand, 0xff, sizeof(_rand));
10148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (scard_gsm_auth(scard, _rand, sres, kc))
10158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto failed;
10168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (i = 0; i < num_triplets; i++) {
10188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memset(rand_[i], i, sizeof(rand_[i]));
10198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (scard_gsm_auth(scard, rand_[i], sres_[i], kc_[i]))
10208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			goto failed;
10218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
10228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (i = 0; i < num_triplets; i++) {
10248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		printf("1");
10258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		for (j = 0; j < len; j++)
10268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			printf("%c", imsi[j]);
10278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		printf(",");
10288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		for (j = 0; j < 16; j++)
10298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			printf("%02X", rand_[i][j]);
10308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		printf(",");
10318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		for (j = 0; j < 4; j++)
10328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			printf("%02X", sres_[i][j]);
10338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		printf(",");
10348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		for (j = 0; j < 8; j++)
10358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			printf("%02X", kc_[i][j]);
10368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		printf("\n");
10378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
10388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "Trying to use UMTS authentication");
10408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* seq 39 (0x28) */
10428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memset(aka_rand, 0xaa, 16);
10438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(aka_autn, "\x86\x71\x31\xcb\xa2\xfc\x61\xdf"
10448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		  "\xa3\xb3\x97\x9d\x07\x32\xa2\x12", 16);
10458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	res = scard_umts_auth(scard, aka_rand, aka_autn, aka_res, &aka_res_len,
10478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			      aka_ik, aka_ck, aka_auts);
10488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (res == 0) {
10498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "UMTS auth completed successfully");
10508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_hexdump(MSG_DEBUG, "RES", aka_res, aka_res_len);
10518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_hexdump(MSG_DEBUG, "IK", aka_ik, IK_LEN);
10528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_hexdump(MSG_DEBUG, "CK", aka_ck, CK_LEN);
10538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else if (res == -2) {
10548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "UMTS auth resulted in synchronization "
10558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "failure");
10568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_hexdump(MSG_DEBUG, "AUTS", aka_auts, AKA_AUTS_LEN);
10578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
10588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "UMTS auth failed");
10598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
10608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtfailed:
10628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	scard_deinit(scard);
10638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
10658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#undef num_triplets
10668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
10678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10692271d3fdd5982d0e5e81cf9999a861bba933eacbDmitry Shmidtstatic int scard_get_triplets(struct eapol_test_data *e, int argc, char *argv[])
10708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
10718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct scard_data *scard;
10728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t len;
10738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char imsi[20];
10748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	unsigned char _rand[16];
10758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	unsigned char sres[4];
10768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	unsigned char kc[8];
10778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int num_triplets;
10788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int i;
10798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t j;
10808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (argc < 2 || ((num_triplets = atoi(argv[1])) <= 0)) {
10828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		printf("invalid parameters for sim command\n");
10838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
10848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
10858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (argc <= 2 || os_strcmp(argv[2], "debug") != 0) {
10878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* disable debug output */
10888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_debug_level = 99;
10898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
10908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10912271d3fdd5982d0e5e81cf9999a861bba933eacbDmitry Shmidt	scard = scard_init(e->pcsc_reader);
10928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (scard == NULL) {
10938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		printf("Failed to open smartcard connection\n");
10948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
10958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
10968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (scard_set_pin(scard, argv[0])) {
10978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_WARNING, "PIN validation failed");
10988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		scard_deinit(scard);
10998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
11008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
11018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	len = sizeof(imsi);
11038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (scard_get_imsi(scard, imsi, &len)) {
11048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		scard_deinit(scard);
11058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
11068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
11078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (i = 0; i < num_triplets; i++) {
11098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memset(_rand, i, sizeof(_rand));
11108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (scard_gsm_auth(scard, _rand, sres, kc))
11118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
11128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* IMSI:Kc:SRES:RAND */
11148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		for (j = 0; j < len; j++)
11158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			printf("%c", imsi[j]);
11168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		printf(":");
11178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		for (j = 0; j < 8; j++)
11188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			printf("%02X", kc[j]);
11198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		printf(":");
11208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		for (j = 0; j < 4; j++)
11218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			printf("%02X", sres[j]);
11228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		printf(":");
11238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		for (j = 0; j < 16; j++)
11248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			printf("%02X", _rand[j]);
11258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		printf("\n");
11268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
11278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	scard_deinit(scard);
11298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
11318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
11328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eapol_test_terminate(int sig, void *signal_ctx)
11358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
11368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_supplicant *wpa_s = signal_ctx;
11378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(wpa_s, MSG_INFO, "Signal %d received - terminating", sig);
11388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_terminate();
11398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
11408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void usage(void)
11438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
11448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	printf("usage:\n"
11455a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	       "eapol_test [-enWS] -c<conf> [-a<AS IP>] [-p<AS port>] "
11468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	       "[-s<AS secret>]\\\n"
11478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	       "           [-r<count>] [-t<timeout>] [-C<Connect-Info>] \\\n"
11481f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	       "           [-M<client MAC address>] [-o<server cert file] \\\n"
11492271d3fdd5982d0e5e81cf9999a861bba933eacbDmitry Shmidt	       "           [-N<attr spec>] [-R<PC/SC reader>] "
11502271d3fdd5982d0e5e81cf9999a861bba933eacbDmitry Shmidt	       "[-P<PC/SC PIN>] \\\n"
11518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	       "           [-A<client IP>]\n"
11528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	       "eapol_test scard\n"
11538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	       "eapol_test sim <PIN> <num triplets> [debug]\n"
11548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	       "\n");
11558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	printf("options:\n"
11568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	       "  -c<conf> = configuration file\n"
11578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	       "  -a<AS IP> = IP address of the authentication server, "
11588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	       "default 127.0.0.1\n"
11598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	       "  -p<AS port> = UDP port of the authentication server, "
11608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	       "default 1812\n"
11618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	       "  -s<AS secret> = shared secret with the authentication "
11628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	       "server, default 'radius'\n"
11638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	       "  -A<client IP> = IP address of the client, default: select "
11648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	       "automatically\n"
11658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	       "  -r<count> = number of re-authentications\n"
11665a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	       "  -e = Request EAP-Key-Name\n"
11678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	       "  -W = wait for a control interface monitor before starting\n"
11688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	       "  -S = save configuration after authentication\n"
11698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	       "  -n = no MPPE keys expected\n"
11708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	       "  -t<timeout> = sets timeout in seconds (default: 30 s)\n"
11718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	       "  -C<Connect-Info> = RADIUS Connect-Info (default: "
11728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	       "CONNECT 11Mbps 802.11b)\n"
11738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	       "  -M<client MAC address> = Set own MAC address "
11748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	       "(Calling-Station-Id,\n"
11758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	       "                           default: 02:00:00:00:00:01)\n"
11761f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	       "  -o<server cert file> = Write received server certificate\n"
11771f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	       "                         chain to the specified file\n"
11788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	       "  -N<attr spec> = send arbitrary attribute specified by:\n"
11798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	       "                  attr_id:syntax:value or attr_id\n"
11808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	       "                  attr_id - number id of the attribute\n"
11818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	       "                  syntax - one of: s, d, x\n"
11828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	       "                     s = string\n"
11838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	       "                     d = integer\n"
11848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	       "                     x = octet string\n"
11858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	       "                  value - attribute value.\n"
11868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	       "       When only attr_id is specified, NULL will be used as "
11878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	       "value.\n"
11888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	       "       Multiple attributes can be specified by using the "
11898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	       "option several times.\n");
11908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
11918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint main(int argc, char *argv[])
11948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1195051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt	struct wpa_global global;
11968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_supplicant wpa_s;
11978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int c, ret = 1, wait_for_monitor = 0, save_config = 0;
11988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char *as_addr = "127.0.0.1";
11998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int as_port = 1812;
12008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char *as_secret = "radius";
12018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char *cli_addr = NULL;
12028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char *conf = NULL;
12038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int timeout = 30;
12048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char *pos;
12058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct extra_radius_attr *p = NULL, *p1;
12068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (os_program_init())
12088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
12098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	hostapd_logger_register_cb(hostapd_logger_cb);
12118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memset(&eapol_test, 0, sizeof(eapol_test));
12138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eapol_test.connect_info = "CONNECT 11Mbps 802.11b";
12148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(eapol_test.own_addr, "\x02\x00\x00\x00\x00\x01", ETH_ALEN);
12152271d3fdd5982d0e5e81cf9999a861bba933eacbDmitry Shmidt	eapol_test.pcsc_pin = "1234";
12168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_debug_level = 0;
12188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_debug_show_keys = 1;
12198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (;;) {
12212271d3fdd5982d0e5e81cf9999a861bba933eacbDmitry Shmidt		c = getopt(argc, argv, "a:A:c:C:eM:nN:o:p:P:r:R:s:St:W");
12228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (c < 0)
12238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
12248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		switch (c) {
12258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		case 'a':
12268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			as_addr = optarg;
12278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
12288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		case 'A':
12298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			cli_addr = optarg;
12308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
12318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		case 'c':
12328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			conf = optarg;
12338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
12348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		case 'C':
12358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			eapol_test.connect_info = optarg;
12368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
12375a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		case 'e':
12385a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			eapol_test.req_eap_key_name = 1;
12395a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			break;
12408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		case 'M':
12418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (hwaddr_aton(optarg, eapol_test.own_addr)) {
12428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				usage();
12438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				return -1;
12448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			}
12458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
12468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		case 'n':
12478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			eapol_test.no_mppe_keys++;
12488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
12491f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		case 'o':
12501f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			if (eapol_test.server_cert_file)
12511f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				fclose(eapol_test.server_cert_file);
12521f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			eapol_test.server_cert_file = fopen(optarg, "w");
12531f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			if (eapol_test.server_cert_file == NULL) {
12541f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				printf("Could not open '%s' for writing\n",
12551f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				       optarg);
12561f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				return -1;
12571f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			}
12581f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			break;
12598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		case 'p':
12608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			as_port = atoi(optarg);
12618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
12622271d3fdd5982d0e5e81cf9999a861bba933eacbDmitry Shmidt		case 'P':
12632271d3fdd5982d0e5e81cf9999a861bba933eacbDmitry Shmidt			eapol_test.pcsc_pin = optarg;
12642271d3fdd5982d0e5e81cf9999a861bba933eacbDmitry Shmidt			break;
12658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		case 'r':
12668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			eapol_test.eapol_test_num_reauths = atoi(optarg);
12678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
12682271d3fdd5982d0e5e81cf9999a861bba933eacbDmitry Shmidt		case 'R':
12692271d3fdd5982d0e5e81cf9999a861bba933eacbDmitry Shmidt			eapol_test.pcsc_reader = optarg;
1270d30ac604c9f6da71a0dd7f46d25be05a2a62cfbbDmitry Shmidt			break;
12718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		case 's':
12728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			as_secret = optarg;
12738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
12748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		case 'S':
12758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			save_config++;
12768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
12778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		case 't':
12788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			timeout = atoi(optarg);
12798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
12808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		case 'W':
12818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wait_for_monitor++;
12828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
12838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		case 'N':
1284a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt			p1 = os_zalloc(sizeof(*p1));
12858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (p1 == NULL)
12868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				break;
12878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (!p)
12888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				eapol_test.extra_attrs = p1;
12898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			else
12908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				p->next = p1;
12918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			p = p1;
12928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			p->type = atoi(optarg);
12948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			pos = os_strchr(optarg, ':');
12958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (pos == NULL) {
12968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				p->syntax = 'n';
12978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				p->data = NULL;
12988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				break;
12998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			}
13008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			pos++;
13028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (pos[0] == '\0' || pos[1] != ':') {
13038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				printf("Incorrect format of attribute "
13048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       "specification\n");
13058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				break;
13068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			}
13078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			p->syntax = pos[0];
13098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			p->data = pos + 2;
13108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
13118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		default:
13128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			usage();
13138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
13148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
13158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
13168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (argc > optind && os_strcmp(argv[optind], "scard") == 0) {
13182271d3fdd5982d0e5e81cf9999a861bba933eacbDmitry Shmidt		return scard_test(&eapol_test);
13198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
13208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (argc > optind && os_strcmp(argv[optind], "sim") == 0) {
13222271d3fdd5982d0e5e81cf9999a861bba933eacbDmitry Shmidt		return scard_get_triplets(&eapol_test, argc - optind - 1,
13238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					  &argv[optind + 1]);
13248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
13258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (conf == NULL) {
13278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		usage();
13288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		printf("Configuration file is required.\n");
13298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
13308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
13318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (eap_register_methods()) {
13338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_ERROR, "Failed to register EAP methods");
13348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
13358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
13368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (eloop_init()) {
13388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_ERROR, "Failed to initialize event loop");
13398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
13408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
13418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1342051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt	os_memset(&global, 0, sizeof(global));
13438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memset(&wpa_s, 0, sizeof(wpa_s));
1344051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt	wpa_s.global = &global;
13458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eapol_test.wpa_s = &wpa_s;
1346051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt	dl_list_init(&wpa_s.bss);
1347051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt	dl_list_init(&wpa_s.bss_id);
134864f47c5c24428834677459e048420f86e3514c20Dmitry Shmidt	wpa_s.conf = wpa_config_read(conf, NULL);
13498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_s.conf == NULL) {
13508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		printf("Failed to parse configuration file '%s'.\n", conf);
13518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
13528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
13538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_s.conf->ssid == NULL) {
13548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		printf("No networks defined.\n");
13558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
13568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
13578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13582271d3fdd5982d0e5e81cf9999a861bba933eacbDmitry Shmidt	if (eapol_test.pcsc_reader) {
13592271d3fdd5982d0e5e81cf9999a861bba933eacbDmitry Shmidt		os_free(wpa_s.conf->pcsc_reader);
13602271d3fdd5982d0e5e81cf9999a861bba933eacbDmitry Shmidt		wpa_s.conf->pcsc_reader = os_strdup(eapol_test.pcsc_reader);
13612271d3fdd5982d0e5e81cf9999a861bba933eacbDmitry Shmidt	}
13622271d3fdd5982d0e5e81cf9999a861bba933eacbDmitry Shmidt
13638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_init_conf(&eapol_test, &wpa_s, as_addr, as_port, as_secret,
13648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		      cli_addr);
13658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_s.ctrl_iface = wpa_supplicant_ctrl_iface_init(&wpa_s);
13668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_s.ctrl_iface == NULL) {
13678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		printf("Failed to initialize control interface '%s'.\n"
13688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		       "You may have another eapol_test process already "
13698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		       "running or the file was\n"
13708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		       "left by an unclean termination of eapol_test in "
13718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		       "which case you will need\n"
13728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		       "to manually remove this file before starting "
13738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		       "eapol_test again.\n",
13748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		       wpa_s.conf->ctrl_interface);
13758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
13768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
13778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_supplicant_scard_init(&wpa_s, wpa_s.conf->ssid))
13788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
13798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (test_eapol(&eapol_test, &wpa_s, wpa_s.conf->ssid))
13818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
13828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
138361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (wpas_init_ext_pw(&wpa_s) < 0)
138461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		return -1;
138561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
13868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wait_for_monitor)
13878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_supplicant_ctrl_iface_wait(wpa_s.ctrl_iface);
13888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_register_timeout(timeout, 0, eapol_test_timeout, &eapol_test,
13908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			       NULL);
13918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_register_timeout(0, 0, send_eap_request_identity, &wpa_s, NULL);
13928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_register_signal_terminate(eapol_test_terminate, &wpa_s);
13938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_register_signal_reconfig(eapol_test_terminate, &wpa_s);
13948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_run();
13958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_cancel_timeout(eapol_test_timeout, &eapol_test, NULL);
13978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_cancel_timeout(eapol_sm_reauth, &eapol_test, NULL);
13988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (eapol_test_compare_pmk(&eapol_test) == 0 ||
14008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    eapol_test.no_mppe_keys)
14018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ret = 0;
14028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (eapol_test.auth_timed_out)
14038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ret = -2;
14048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (eapol_test.radius_access_reject_received)
14058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ret = -3;
14068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (save_config)
14088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_config_write(conf, wpa_s.conf);
14098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	test_eapol_clean(&eapol_test, &wpa_s);
14118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eap_peer_unregister_methods();
14138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_AP
14148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eap_server_unregister_methods();
14158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_AP */
14168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_destroy();
14188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14191f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (eapol_test.server_cert_file)
14201f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		fclose(eapol_test.server_cert_file);
14211f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
14228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	printf("MPPE keys OK: %d  mismatch: %d\n",
14238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	       eapol_test.num_mppe_ok, eapol_test.num_mppe_mismatch);
14248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (eapol_test.num_mppe_mismatch)
14258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ret = -4;
14268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ret)
14278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		printf("FAILURE\n");
14288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else
14298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		printf("SUCCESS\n");
14308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_program_deinit();
14328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return ret;
14348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1435