16d49e1aeSJan Lentfer /*
26d49e1aeSJan Lentfer  * WPA Supplicant - test code
33ff40c12SJohn Marino  * Copyright (c) 2003-2013, Jouni Malinen <j@w1.fi>
46d49e1aeSJan Lentfer  *
53ff40c12SJohn Marino  * This software may be distributed under the terms of the BSD license.
63ff40c12SJohn Marino  * See README for more details.
76d49e1aeSJan Lentfer  *
86d49e1aeSJan Lentfer  * IEEE 802.1X Supplicant test code (to be used in place of wpa_supplicant.c.
96d49e1aeSJan Lentfer  * Not used in production version.
106d49e1aeSJan Lentfer  */
116d49e1aeSJan Lentfer 
126d49e1aeSJan Lentfer #include "includes.h"
136d49e1aeSJan Lentfer #include <assert.h>
146d49e1aeSJan Lentfer 
156d49e1aeSJan Lentfer #include "common.h"
163ff40c12SJohn Marino #include "utils/ext_password.h"
17*a1157835SDaniel Fojt #include "common/version.h"
18*a1157835SDaniel Fojt #include "crypto/tls.h"
196d49e1aeSJan Lentfer #include "config.h"
206d49e1aeSJan Lentfer #include "eapol_supp/eapol_supp_sm.h"
216d49e1aeSJan Lentfer #include "eap_peer/eap.h"
223ff40c12SJohn Marino #include "eap_server/eap_methods.h"
236d49e1aeSJan Lentfer #include "eloop.h"
243ff40c12SJohn Marino #include "utils/base64.h"
253ff40c12SJohn Marino #include "rsn_supp/wpa.h"
266d49e1aeSJan Lentfer #include "wpa_supplicant_i.h"
276d49e1aeSJan Lentfer #include "radius/radius.h"
286d49e1aeSJan Lentfer #include "radius/radius_client.h"
293ff40c12SJohn Marino #include "common/wpa_ctrl.h"
306d49e1aeSJan Lentfer #include "ctrl_iface.h"
316d49e1aeSJan Lentfer #include "pcsc_funcs.h"
323ff40c12SJohn Marino #include "wpas_glue.h"
336d49e1aeSJan Lentfer 
346d49e1aeSJan Lentfer 
35*a1157835SDaniel Fojt const struct wpa_driver_ops *const wpa_drivers[] = { NULL };
366d49e1aeSJan Lentfer 
376d49e1aeSJan Lentfer 
386d49e1aeSJan Lentfer struct extra_radius_attr {
396d49e1aeSJan Lentfer 	u8 type;
406d49e1aeSJan Lentfer 	char syntax;
416d49e1aeSJan Lentfer 	char *data;
426d49e1aeSJan Lentfer 	struct extra_radius_attr *next;
436d49e1aeSJan Lentfer };
446d49e1aeSJan Lentfer 
456d49e1aeSJan Lentfer struct eapol_test_data {
466d49e1aeSJan Lentfer 	struct wpa_supplicant *wpa_s;
476d49e1aeSJan Lentfer 
486d49e1aeSJan Lentfer 	int eapol_test_num_reauths;
496d49e1aeSJan Lentfer 	int no_mppe_keys;
506d49e1aeSJan Lentfer 	int num_mppe_ok, num_mppe_mismatch;
51*a1157835SDaniel Fojt 	int req_eap_key_name;
526d49e1aeSJan Lentfer 
536d49e1aeSJan Lentfer 	u8 radius_identifier;
546d49e1aeSJan Lentfer 	struct radius_msg *last_recv_radius;
556d49e1aeSJan Lentfer 	struct in_addr own_ip_addr;
566d49e1aeSJan Lentfer 	struct radius_client_data *radius;
576d49e1aeSJan Lentfer 	struct hostapd_radius_servers *radius_conf;
586d49e1aeSJan Lentfer 
593ff40c12SJohn Marino 	 /* last received EAP Response from Authentication Server */
603ff40c12SJohn Marino 	struct wpabuf *last_eap_radius;
616d49e1aeSJan Lentfer 
626d49e1aeSJan Lentfer 	u8 authenticator_pmk[PMK_LEN];
636d49e1aeSJan Lentfer 	size_t authenticator_pmk_len;
64*a1157835SDaniel Fojt 	u8 authenticator_eap_key_name[256];
65*a1157835SDaniel Fojt 	size_t authenticator_eap_key_name_len;
666d49e1aeSJan Lentfer 	int radius_access_accept_received;
676d49e1aeSJan Lentfer 	int radius_access_reject_received;
686d49e1aeSJan Lentfer 	int auth_timed_out;
696d49e1aeSJan Lentfer 
706d49e1aeSJan Lentfer 	u8 *eap_identity;
716d49e1aeSJan Lentfer 	size_t eap_identity_len;
726d49e1aeSJan Lentfer 
736d49e1aeSJan Lentfer 	char *connect_info;
746d49e1aeSJan Lentfer 	u8 own_addr[ETH_ALEN];
756d49e1aeSJan Lentfer 	struct extra_radius_attr *extra_attrs;
763ff40c12SJohn Marino 
773ff40c12SJohn Marino 	FILE *server_cert_file;
78*a1157835SDaniel Fojt 
79*a1157835SDaniel Fojt 	const char *pcsc_reader;
80*a1157835SDaniel Fojt 	const char *pcsc_pin;
81*a1157835SDaniel Fojt 
82*a1157835SDaniel Fojt 	unsigned int ctrl_iface:1;
83*a1157835SDaniel Fojt 	unsigned int id_req_sent:1;
846d49e1aeSJan Lentfer };
856d49e1aeSJan Lentfer 
866d49e1aeSJan Lentfer static struct eapol_test_data eapol_test;
876d49e1aeSJan Lentfer 
886d49e1aeSJan Lentfer 
896d49e1aeSJan Lentfer static void send_eap_request_identity(void *eloop_ctx, void *timeout_ctx);
906d49e1aeSJan Lentfer 
916d49e1aeSJan Lentfer 
hostapd_logger_cb(void * ctx,const u8 * addr,unsigned int module,int level,const char * txt,size_t len)926d49e1aeSJan Lentfer static void hostapd_logger_cb(void *ctx, const u8 *addr, unsigned int module,
936d49e1aeSJan Lentfer 			      int level, const char *txt, size_t len)
946d49e1aeSJan Lentfer {
956d49e1aeSJan Lentfer 	if (addr)
966d49e1aeSJan Lentfer 		wpa_printf(MSG_DEBUG, "STA " MACSTR ": %s\n",
976d49e1aeSJan Lentfer 			   MAC2STR(addr), txt);
986d49e1aeSJan Lentfer 	else
996d49e1aeSJan Lentfer 		wpa_printf(MSG_DEBUG, "%s", txt);
1006d49e1aeSJan Lentfer }
1016d49e1aeSJan Lentfer 
1026d49e1aeSJan Lentfer 
add_extra_attr(struct radius_msg * msg,struct extra_radius_attr * attr)1036d49e1aeSJan Lentfer static int add_extra_attr(struct radius_msg *msg,
1046d49e1aeSJan Lentfer 			  struct extra_radius_attr *attr)
1056d49e1aeSJan Lentfer {
1066d49e1aeSJan Lentfer 	size_t len;
1076d49e1aeSJan Lentfer 	char *pos;
1086d49e1aeSJan Lentfer 	u32 val;
1093ff40c12SJohn Marino 	char buf[RADIUS_MAX_ATTR_LEN + 1];
1106d49e1aeSJan Lentfer 
1116d49e1aeSJan Lentfer 	switch (attr->syntax) {
1126d49e1aeSJan Lentfer 	case 's':
1136d49e1aeSJan Lentfer 		os_snprintf(buf, sizeof(buf), "%s", attr->data);
1146d49e1aeSJan Lentfer 		len = os_strlen(buf);
1156d49e1aeSJan Lentfer 		break;
1166d49e1aeSJan Lentfer 	case 'n':
1176d49e1aeSJan Lentfer 		buf[0] = '\0';
1186d49e1aeSJan Lentfer 		len = 1;
1196d49e1aeSJan Lentfer 		break;
1206d49e1aeSJan Lentfer 	case 'x':
1216d49e1aeSJan Lentfer 		pos = attr->data;
1226d49e1aeSJan Lentfer 		if (pos[0] == '0' && pos[1] == 'x')
1236d49e1aeSJan Lentfer 			pos += 2;
1246d49e1aeSJan Lentfer 		len = os_strlen(pos);
1253ff40c12SJohn Marino 		if ((len & 1) || (len / 2) > RADIUS_MAX_ATTR_LEN) {
1266d49e1aeSJan Lentfer 			printf("Invalid extra attribute hexstring\n");
1276d49e1aeSJan Lentfer 			return -1;
1286d49e1aeSJan Lentfer 		}
1296d49e1aeSJan Lentfer 		len /= 2;
1306d49e1aeSJan Lentfer 		if (hexstr2bin(pos, (u8 *) buf, len) < 0) {
1316d49e1aeSJan Lentfer 			printf("Invalid extra attribute hexstring\n");
1326d49e1aeSJan Lentfer 			return -1;
1336d49e1aeSJan Lentfer 		}
1346d49e1aeSJan Lentfer 		break;
1356d49e1aeSJan Lentfer 	case 'd':
1366d49e1aeSJan Lentfer 		val = htonl(atoi(attr->data));
1376d49e1aeSJan Lentfer 		os_memcpy(buf, &val, 4);
1386d49e1aeSJan Lentfer 		len = 4;
1396d49e1aeSJan Lentfer 		break;
1406d49e1aeSJan Lentfer 	default:
1416d49e1aeSJan Lentfer 		printf("Incorrect extra attribute syntax specification\n");
1426d49e1aeSJan Lentfer 		return -1;
1436d49e1aeSJan Lentfer 	}
1446d49e1aeSJan Lentfer 
1456d49e1aeSJan Lentfer 	if (!radius_msg_add_attr(msg, attr->type, (u8 *) buf, len)) {
1466d49e1aeSJan Lentfer 		printf("Could not add attribute %d\n", attr->type);
1476d49e1aeSJan Lentfer 		return -1;
1486d49e1aeSJan Lentfer 	}
1496d49e1aeSJan Lentfer 
1506d49e1aeSJan Lentfer 	return 0;
1516d49e1aeSJan Lentfer }
1526d49e1aeSJan Lentfer 
1536d49e1aeSJan Lentfer 
add_extra_attrs(struct radius_msg * msg,struct extra_radius_attr * attrs)1546d49e1aeSJan Lentfer static int add_extra_attrs(struct radius_msg *msg,
1556d49e1aeSJan Lentfer 			   struct extra_radius_attr *attrs)
1566d49e1aeSJan Lentfer {
1576d49e1aeSJan Lentfer 	struct extra_radius_attr *p;
1586d49e1aeSJan Lentfer 	for (p = attrs; p; p = p->next) {
1596d49e1aeSJan Lentfer 		if (add_extra_attr(msg, p) < 0)
1606d49e1aeSJan Lentfer 			return -1;
1616d49e1aeSJan Lentfer 	}
1626d49e1aeSJan Lentfer 	return 0;
1636d49e1aeSJan Lentfer }
1646d49e1aeSJan Lentfer 
1656d49e1aeSJan Lentfer 
1666d49e1aeSJan Lentfer static struct extra_radius_attr *
find_extra_attr(struct extra_radius_attr * attrs,u8 type)1676d49e1aeSJan Lentfer find_extra_attr(struct extra_radius_attr *attrs, u8 type)
1686d49e1aeSJan Lentfer {
1696d49e1aeSJan Lentfer 	struct extra_radius_attr *p;
1706d49e1aeSJan Lentfer 	for (p = attrs; p; p = p->next) {
1716d49e1aeSJan Lentfer 		if (p->type == type)
1726d49e1aeSJan Lentfer 			return p;
1736d49e1aeSJan Lentfer 	}
1746d49e1aeSJan Lentfer 	return NULL;
1756d49e1aeSJan Lentfer }
1766d49e1aeSJan Lentfer 
1776d49e1aeSJan Lentfer 
ieee802_1x_encapsulate_radius(struct eapol_test_data * e,const u8 * eap,size_t len)1786d49e1aeSJan Lentfer static void ieee802_1x_encapsulate_radius(struct eapol_test_data *e,
1796d49e1aeSJan Lentfer 					  const u8 *eap, size_t len)
1806d49e1aeSJan Lentfer {
1816d49e1aeSJan Lentfer 	struct radius_msg *msg;
1823ff40c12SJohn Marino 	char buf[RADIUS_MAX_ATTR_LEN + 1];
1836d49e1aeSJan Lentfer 	const struct eap_hdr *hdr;
1846d49e1aeSJan Lentfer 	const u8 *pos;
1856d49e1aeSJan Lentfer 
1866d49e1aeSJan Lentfer 	wpa_printf(MSG_DEBUG, "Encapsulating EAP message into a RADIUS "
1876d49e1aeSJan Lentfer 		   "packet");
1886d49e1aeSJan Lentfer 
1896d49e1aeSJan Lentfer 	e->radius_identifier = radius_client_get_id(e->radius);
1906d49e1aeSJan Lentfer 	msg = radius_msg_new(RADIUS_CODE_ACCESS_REQUEST,
1916d49e1aeSJan Lentfer 			     e->radius_identifier);
1926d49e1aeSJan Lentfer 	if (msg == NULL) {
1936d49e1aeSJan Lentfer 		printf("Could not create net RADIUS packet\n");
1946d49e1aeSJan Lentfer 		return;
1956d49e1aeSJan Lentfer 	}
1966d49e1aeSJan Lentfer 
197*a1157835SDaniel Fojt 	radius_msg_make_authenticator(msg);
1986d49e1aeSJan Lentfer 
1996d49e1aeSJan Lentfer 	hdr = (const struct eap_hdr *) eap;
2006d49e1aeSJan Lentfer 	pos = (const u8 *) (hdr + 1);
2016d49e1aeSJan Lentfer 	if (len > sizeof(*hdr) && hdr->code == EAP_CODE_RESPONSE &&
2026d49e1aeSJan Lentfer 	    pos[0] == EAP_TYPE_IDENTITY) {
2036d49e1aeSJan Lentfer 		pos++;
2046d49e1aeSJan Lentfer 		os_free(e->eap_identity);
2056d49e1aeSJan Lentfer 		e->eap_identity_len = len - sizeof(*hdr) - 1;
2066d49e1aeSJan Lentfer 		e->eap_identity = os_malloc(e->eap_identity_len);
2076d49e1aeSJan Lentfer 		if (e->eap_identity) {
2086d49e1aeSJan Lentfer 			os_memcpy(e->eap_identity, pos, e->eap_identity_len);
2096d49e1aeSJan Lentfer 			wpa_hexdump(MSG_DEBUG, "Learned identity from "
2106d49e1aeSJan Lentfer 				    "EAP-Response-Identity",
2116d49e1aeSJan Lentfer 				    e->eap_identity, e->eap_identity_len);
2126d49e1aeSJan Lentfer 		}
2136d49e1aeSJan Lentfer 	}
2146d49e1aeSJan Lentfer 
2156d49e1aeSJan Lentfer 	if (e->eap_identity &&
2166d49e1aeSJan Lentfer 	    !radius_msg_add_attr(msg, RADIUS_ATTR_USER_NAME,
2176d49e1aeSJan Lentfer 				 e->eap_identity, e->eap_identity_len)) {
2186d49e1aeSJan Lentfer 		printf("Could not add User-Name\n");
2196d49e1aeSJan Lentfer 		goto fail;
2206d49e1aeSJan Lentfer 	}
2216d49e1aeSJan Lentfer 
222*a1157835SDaniel Fojt 	if (e->req_eap_key_name &&
223*a1157835SDaniel Fojt 	    !radius_msg_add_attr(msg, RADIUS_ATTR_EAP_KEY_NAME, (u8 *) "\0",
224*a1157835SDaniel Fojt 				 1)) {
225*a1157835SDaniel Fojt 		printf("Could not add EAP-Key-Name\n");
226*a1157835SDaniel Fojt 		goto fail;
227*a1157835SDaniel Fojt 	}
228*a1157835SDaniel Fojt 
2296d49e1aeSJan Lentfer 	if (!find_extra_attr(e->extra_attrs, RADIUS_ATTR_NAS_IP_ADDRESS) &&
2306d49e1aeSJan Lentfer 	    !radius_msg_add_attr(msg, RADIUS_ATTR_NAS_IP_ADDRESS,
2316d49e1aeSJan Lentfer 				 (u8 *) &e->own_ip_addr, 4)) {
2326d49e1aeSJan Lentfer 		printf("Could not add NAS-IP-Address\n");
2336d49e1aeSJan Lentfer 		goto fail;
2346d49e1aeSJan Lentfer 	}
2356d49e1aeSJan Lentfer 
2366d49e1aeSJan Lentfer 	os_snprintf(buf, sizeof(buf), RADIUS_802_1X_ADDR_FORMAT,
2376d49e1aeSJan Lentfer 		    MAC2STR(e->wpa_s->own_addr));
2386d49e1aeSJan Lentfer 	if (!find_extra_attr(e->extra_attrs, RADIUS_ATTR_CALLING_STATION_ID)
2396d49e1aeSJan Lentfer 	    &&
2406d49e1aeSJan Lentfer 	    !radius_msg_add_attr(msg, RADIUS_ATTR_CALLING_STATION_ID,
2416d49e1aeSJan Lentfer 				 (u8 *) buf, os_strlen(buf))) {
2426d49e1aeSJan Lentfer 		printf("Could not add Calling-Station-Id\n");
2436d49e1aeSJan Lentfer 		goto fail;
2446d49e1aeSJan Lentfer 	}
2456d49e1aeSJan Lentfer 
2466d49e1aeSJan Lentfer 	/* TODO: should probably check MTU from driver config; 2304 is max for
2476d49e1aeSJan Lentfer 	 * IEEE 802.11, but use 1400 to avoid problems with too large packets
2486d49e1aeSJan Lentfer 	 */
2496d49e1aeSJan Lentfer 	if (!find_extra_attr(e->extra_attrs, RADIUS_ATTR_FRAMED_MTU) &&
2506d49e1aeSJan Lentfer 	    !radius_msg_add_attr_int32(msg, RADIUS_ATTR_FRAMED_MTU, 1400)) {
2516d49e1aeSJan Lentfer 		printf("Could not add Framed-MTU\n");
2526d49e1aeSJan Lentfer 		goto fail;
2536d49e1aeSJan Lentfer 	}
2546d49e1aeSJan Lentfer 
2556d49e1aeSJan Lentfer 	if (!find_extra_attr(e->extra_attrs, RADIUS_ATTR_NAS_PORT_TYPE) &&
2566d49e1aeSJan Lentfer 	    !radius_msg_add_attr_int32(msg, RADIUS_ATTR_NAS_PORT_TYPE,
2576d49e1aeSJan Lentfer 				       RADIUS_NAS_PORT_TYPE_IEEE_802_11)) {
2586d49e1aeSJan Lentfer 		printf("Could not add NAS-Port-Type\n");
2596d49e1aeSJan Lentfer 		goto fail;
2606d49e1aeSJan Lentfer 	}
2616d49e1aeSJan Lentfer 
262*a1157835SDaniel Fojt 	if (!find_extra_attr(e->extra_attrs, RADIUS_ATTR_SERVICE_TYPE) &&
263*a1157835SDaniel Fojt 	    !radius_msg_add_attr_int32(msg, RADIUS_ATTR_SERVICE_TYPE,
264*a1157835SDaniel Fojt 				       RADIUS_SERVICE_TYPE_FRAMED)) {
265*a1157835SDaniel Fojt 		printf("Could not add Service-Type\n");
266*a1157835SDaniel Fojt 		goto fail;
267*a1157835SDaniel Fojt 	}
268*a1157835SDaniel Fojt 
2696d49e1aeSJan Lentfer 	os_snprintf(buf, sizeof(buf), "%s", e->connect_info);
2706d49e1aeSJan Lentfer 	if (!find_extra_attr(e->extra_attrs, RADIUS_ATTR_CONNECT_INFO) &&
2716d49e1aeSJan Lentfer 	    !radius_msg_add_attr(msg, RADIUS_ATTR_CONNECT_INFO,
2726d49e1aeSJan Lentfer 				 (u8 *) buf, os_strlen(buf))) {
2736d49e1aeSJan Lentfer 		printf("Could not add Connect-Info\n");
2746d49e1aeSJan Lentfer 		goto fail;
2756d49e1aeSJan Lentfer 	}
2766d49e1aeSJan Lentfer 
2776d49e1aeSJan Lentfer 	if (add_extra_attrs(msg, e->extra_attrs) < 0)
2786d49e1aeSJan Lentfer 		goto fail;
2796d49e1aeSJan Lentfer 
2806d49e1aeSJan Lentfer 	if (eap && !radius_msg_add_eap(msg, eap, len)) {
2816d49e1aeSJan Lentfer 		printf("Could not add EAP-Message\n");
2826d49e1aeSJan Lentfer 		goto fail;
2836d49e1aeSJan Lentfer 	}
2846d49e1aeSJan Lentfer 
2856d49e1aeSJan Lentfer 	/* State attribute must be copied if and only if this packet is
2866d49e1aeSJan Lentfer 	 * Access-Request reply to the previous Access-Challenge */
2873ff40c12SJohn Marino 	if (e->last_recv_radius &&
2883ff40c12SJohn Marino 	    radius_msg_get_hdr(e->last_recv_radius)->code ==
2896d49e1aeSJan Lentfer 	    RADIUS_CODE_ACCESS_CHALLENGE) {
2906d49e1aeSJan Lentfer 		int res = radius_msg_copy_attr(msg, e->last_recv_radius,
2916d49e1aeSJan Lentfer 					       RADIUS_ATTR_STATE);
2926d49e1aeSJan Lentfer 		if (res < 0) {
2936d49e1aeSJan Lentfer 			printf("Could not copy State attribute from previous "
2946d49e1aeSJan Lentfer 			       "Access-Challenge\n");
2956d49e1aeSJan Lentfer 			goto fail;
2966d49e1aeSJan Lentfer 		}
2976d49e1aeSJan Lentfer 		if (res > 0) {
2986d49e1aeSJan Lentfer 			wpa_printf(MSG_DEBUG, "  Copied RADIUS State "
2996d49e1aeSJan Lentfer 				   "Attribute");
3006d49e1aeSJan Lentfer 		}
3016d49e1aeSJan Lentfer 	}
3026d49e1aeSJan Lentfer 
3033ff40c12SJohn Marino 	if (radius_client_send(e->radius, msg, RADIUS_AUTH, e->wpa_s->own_addr)
3043ff40c12SJohn Marino 	    < 0)
3053ff40c12SJohn Marino 		goto fail;
3066d49e1aeSJan Lentfer 	return;
3076d49e1aeSJan Lentfer 
3086d49e1aeSJan Lentfer  fail:
3096d49e1aeSJan Lentfer 	radius_msg_free(msg);
3106d49e1aeSJan Lentfer }
3116d49e1aeSJan Lentfer 
3126d49e1aeSJan Lentfer 
eapol_test_eapol_send(void * ctx,int type,const u8 * buf,size_t len)3136d49e1aeSJan Lentfer static int eapol_test_eapol_send(void *ctx, int type, const u8 *buf,
3146d49e1aeSJan Lentfer 				 size_t len)
3156d49e1aeSJan Lentfer {
3166d49e1aeSJan Lentfer 	printf("WPA: eapol_test_eapol_send(type=%d len=%lu)\n",
3176d49e1aeSJan Lentfer 	       type, (unsigned long) len);
3186d49e1aeSJan Lentfer 	if (type == IEEE802_1X_TYPE_EAP_PACKET) {
3196d49e1aeSJan Lentfer 		wpa_hexdump(MSG_DEBUG, "TX EAP -> RADIUS", buf, len);
3206d49e1aeSJan Lentfer 		ieee802_1x_encapsulate_radius(&eapol_test, buf, len);
3216d49e1aeSJan Lentfer 	}
3226d49e1aeSJan Lentfer 	return 0;
3236d49e1aeSJan Lentfer }
3246d49e1aeSJan Lentfer 
3256d49e1aeSJan Lentfer 
eapol_test_set_config_blob(void * ctx,struct wpa_config_blob * blob)3266d49e1aeSJan Lentfer static void eapol_test_set_config_blob(void *ctx,
3276d49e1aeSJan Lentfer 				       struct wpa_config_blob *blob)
3286d49e1aeSJan Lentfer {
3293ff40c12SJohn Marino 	struct eapol_test_data *e = ctx;
3303ff40c12SJohn Marino 	wpa_config_set_blob(e->wpa_s->conf, blob);
3316d49e1aeSJan Lentfer }
3326d49e1aeSJan Lentfer 
3336d49e1aeSJan Lentfer 
3346d49e1aeSJan Lentfer static const struct wpa_config_blob *
eapol_test_get_config_blob(void * ctx,const char * name)3356d49e1aeSJan Lentfer eapol_test_get_config_blob(void *ctx, const char *name)
3366d49e1aeSJan Lentfer {
3373ff40c12SJohn Marino 	struct eapol_test_data *e = ctx;
3383ff40c12SJohn Marino 	return wpa_config_get_blob(e->wpa_s->conf, name);
3396d49e1aeSJan Lentfer }
3406d49e1aeSJan Lentfer 
3416d49e1aeSJan Lentfer 
eapol_test_eapol_done_cb(void * ctx)3426d49e1aeSJan Lentfer static void eapol_test_eapol_done_cb(void *ctx)
3436d49e1aeSJan Lentfer {
344*a1157835SDaniel Fojt 	struct eapol_test_data *e = ctx;
345*a1157835SDaniel Fojt 
3466d49e1aeSJan Lentfer 	printf("WPA: EAPOL processing complete\n");
347*a1157835SDaniel Fojt 	wpa_supplicant_cancel_auth_timeout(e->wpa_s);
348*a1157835SDaniel Fojt 	wpa_supplicant_set_state(e->wpa_s, WPA_COMPLETED);
3496d49e1aeSJan Lentfer }
3506d49e1aeSJan Lentfer 
3516d49e1aeSJan Lentfer 
eapol_sm_reauth(void * eloop_ctx,void * timeout_ctx)3526d49e1aeSJan Lentfer static void eapol_sm_reauth(void *eloop_ctx, void *timeout_ctx)
3536d49e1aeSJan Lentfer {
3546d49e1aeSJan Lentfer 	struct eapol_test_data *e = eloop_ctx;
3556d49e1aeSJan Lentfer 	printf("\n\n\n\n\neapol_test: Triggering EAP reauthentication\n\n");
3566d49e1aeSJan Lentfer 	e->radius_access_accept_received = 0;
3576d49e1aeSJan Lentfer 	send_eap_request_identity(e->wpa_s, NULL);
3586d49e1aeSJan Lentfer }
3596d49e1aeSJan Lentfer 
3606d49e1aeSJan Lentfer 
eapol_test_compare_pmk(struct eapol_test_data * e)3616d49e1aeSJan Lentfer static int eapol_test_compare_pmk(struct eapol_test_data *e)
3626d49e1aeSJan Lentfer {
3636d49e1aeSJan Lentfer 	u8 pmk[PMK_LEN];
3646d49e1aeSJan Lentfer 	int ret = 1;
365*a1157835SDaniel Fojt 	const u8 *sess_id;
366*a1157835SDaniel Fojt 	size_t sess_id_len;
3676d49e1aeSJan Lentfer 
3686d49e1aeSJan Lentfer 	if (eapol_sm_get_key(e->wpa_s->eapol, pmk, PMK_LEN) == 0) {
3696d49e1aeSJan Lentfer 		wpa_hexdump(MSG_DEBUG, "PMK from EAPOL", pmk, PMK_LEN);
3706d49e1aeSJan Lentfer 		if (os_memcmp(pmk, e->authenticator_pmk, PMK_LEN) != 0) {
3716d49e1aeSJan Lentfer 			printf("WARNING: PMK mismatch\n");
3726d49e1aeSJan Lentfer 			wpa_hexdump(MSG_DEBUG, "PMK from AS",
3736d49e1aeSJan Lentfer 				    e->authenticator_pmk, PMK_LEN);
3746d49e1aeSJan Lentfer 		} else if (e->radius_access_accept_received)
3756d49e1aeSJan Lentfer 			ret = 0;
3766d49e1aeSJan Lentfer 	} else if (e->authenticator_pmk_len == 16 &&
3776d49e1aeSJan Lentfer 		   eapol_sm_get_key(e->wpa_s->eapol, pmk, 16) == 0) {
3786d49e1aeSJan Lentfer 		wpa_hexdump(MSG_DEBUG, "LEAP PMK from EAPOL", pmk, 16);
3796d49e1aeSJan Lentfer 		if (os_memcmp(pmk, e->authenticator_pmk, 16) != 0) {
3806d49e1aeSJan Lentfer 			printf("WARNING: PMK mismatch\n");
3816d49e1aeSJan Lentfer 			wpa_hexdump(MSG_DEBUG, "PMK from AS",
3826d49e1aeSJan Lentfer 				    e->authenticator_pmk, 16);
3836d49e1aeSJan Lentfer 		} else if (e->radius_access_accept_received)
3846d49e1aeSJan Lentfer 			ret = 0;
3856d49e1aeSJan Lentfer 	} else if (e->radius_access_accept_received && e->no_mppe_keys) {
3866d49e1aeSJan Lentfer 		/* No keying material expected */
3876d49e1aeSJan Lentfer 		ret = 0;
3886d49e1aeSJan Lentfer 	}
3896d49e1aeSJan Lentfer 
3906d49e1aeSJan Lentfer 	if (ret && !e->no_mppe_keys)
3916d49e1aeSJan Lentfer 		e->num_mppe_mismatch++;
3926d49e1aeSJan Lentfer 	else if (!e->no_mppe_keys)
3936d49e1aeSJan Lentfer 		e->num_mppe_ok++;
3946d49e1aeSJan Lentfer 
395*a1157835SDaniel Fojt 	sess_id = eapol_sm_get_session_id(e->wpa_s->eapol, &sess_id_len);
396*a1157835SDaniel Fojt 	if (!sess_id)
397*a1157835SDaniel Fojt 		return ret;
398*a1157835SDaniel Fojt 	if (e->authenticator_eap_key_name_len == 0) {
399*a1157835SDaniel Fojt 		wpa_printf(MSG_INFO, "No EAP-Key-Name received from server");
400*a1157835SDaniel Fojt 		return ret;
401*a1157835SDaniel Fojt 	}
402*a1157835SDaniel Fojt 
403*a1157835SDaniel Fojt 	if (e->authenticator_eap_key_name_len != sess_id_len ||
404*a1157835SDaniel Fojt 	    os_memcmp(e->authenticator_eap_key_name, sess_id, sess_id_len) != 0)
405*a1157835SDaniel Fojt 	{
406*a1157835SDaniel Fojt 		wpa_printf(MSG_INFO,
407*a1157835SDaniel Fojt 			   "Locally derived EAP Session-Id does not match EAP-Key-Name from server");
408*a1157835SDaniel Fojt 		wpa_hexdump(MSG_DEBUG, "EAP Session-Id", sess_id, sess_id_len);
409*a1157835SDaniel Fojt 		wpa_hexdump(MSG_DEBUG, "EAP-Key-Name from server",
410*a1157835SDaniel Fojt 			    e->authenticator_eap_key_name,
411*a1157835SDaniel Fojt 			    e->authenticator_eap_key_name_len);
412*a1157835SDaniel Fojt 	} else {
413*a1157835SDaniel Fojt 		wpa_printf(MSG_INFO,
414*a1157835SDaniel Fojt 			   "Locally derived EAP Session-Id matches EAP-Key-Name from server");
415*a1157835SDaniel Fojt 	}
416*a1157835SDaniel Fojt 
4176d49e1aeSJan Lentfer 	return ret;
4186d49e1aeSJan Lentfer }
4196d49e1aeSJan Lentfer 
4206d49e1aeSJan Lentfer 
eapol_sm_cb(struct eapol_sm * eapol,enum eapol_supp_result result,void * ctx)4213ff40c12SJohn Marino static void eapol_sm_cb(struct eapol_sm *eapol, enum eapol_supp_result result,
4223ff40c12SJohn Marino 			void *ctx)
4236d49e1aeSJan Lentfer {
4246d49e1aeSJan Lentfer 	struct eapol_test_data *e = ctx;
4253ff40c12SJohn Marino 	printf("eapol_sm_cb: result=%d\n", result);
426*a1157835SDaniel Fojt 	e->id_req_sent = 0;
427*a1157835SDaniel Fojt 	if (e->ctrl_iface)
428*a1157835SDaniel Fojt 		return;
4296d49e1aeSJan Lentfer 	e->eapol_test_num_reauths--;
4306d49e1aeSJan Lentfer 	if (e->eapol_test_num_reauths < 0)
4316d49e1aeSJan Lentfer 		eloop_terminate();
4326d49e1aeSJan Lentfer 	else {
4336d49e1aeSJan Lentfer 		eapol_test_compare_pmk(e);
4346d49e1aeSJan Lentfer 		eloop_register_timeout(0, 100000, eapol_sm_reauth, e, NULL);
4356d49e1aeSJan Lentfer 	}
4366d49e1aeSJan Lentfer }
4376d49e1aeSJan Lentfer 
4386d49e1aeSJan Lentfer 
eapol_test_write_cert(FILE * f,const char * subject,const struct wpabuf * cert)4393ff40c12SJohn Marino static void eapol_test_write_cert(FILE *f, const char *subject,
4403ff40c12SJohn Marino 				  const struct wpabuf *cert)
4413ff40c12SJohn Marino {
4423ff40c12SJohn Marino 	unsigned char *encoded;
4433ff40c12SJohn Marino 
4443ff40c12SJohn Marino 	encoded = base64_encode(wpabuf_head(cert), wpabuf_len(cert), NULL);
4453ff40c12SJohn Marino 	if (encoded == NULL)
4463ff40c12SJohn Marino 		return;
4473ff40c12SJohn Marino 	fprintf(f, "%s\n-----BEGIN CERTIFICATE-----\n%s"
4483ff40c12SJohn Marino 		"-----END CERTIFICATE-----\n\n", subject, encoded);
4493ff40c12SJohn Marino 	os_free(encoded);
4503ff40c12SJohn Marino }
4513ff40c12SJohn Marino 
4523ff40c12SJohn Marino 
4533ff40c12SJohn Marino #if defined(CONFIG_CTRL_IFACE) || !defined(CONFIG_NO_STDOUT_DEBUG)
eapol_test_eap_param_needed(void * ctx,enum wpa_ctrl_req_type field,const char * default_txt)4543ff40c12SJohn Marino static void eapol_test_eap_param_needed(void *ctx, enum wpa_ctrl_req_type field,
4553ff40c12SJohn Marino 					const char *default_txt)
4563ff40c12SJohn Marino {
4573ff40c12SJohn Marino 	struct eapol_test_data *e = ctx;
4583ff40c12SJohn Marino 	struct wpa_supplicant *wpa_s = e->wpa_s;
4593ff40c12SJohn Marino 	struct wpa_ssid *ssid = wpa_s->current_ssid;
4603ff40c12SJohn Marino 	const char *field_name, *txt = NULL;
4613ff40c12SJohn Marino 	char *buf;
4623ff40c12SJohn Marino 	size_t buflen;
4633ff40c12SJohn Marino 	int len;
4643ff40c12SJohn Marino 
4653ff40c12SJohn Marino 	if (ssid == NULL)
4663ff40c12SJohn Marino 		return;
4673ff40c12SJohn Marino 
4683ff40c12SJohn Marino 	field_name = wpa_supplicant_ctrl_req_to_string(field, default_txt,
4693ff40c12SJohn Marino 						       &txt);
4703ff40c12SJohn Marino 	if (field_name == NULL) {
4713ff40c12SJohn Marino 		wpa_printf(MSG_WARNING, "Unhandled EAP param %d needed",
4723ff40c12SJohn Marino 			   field);
4733ff40c12SJohn Marino 		return;
4743ff40c12SJohn Marino 	}
4753ff40c12SJohn Marino 
4763ff40c12SJohn Marino 	buflen = 100 + os_strlen(txt) + ssid->ssid_len;
4773ff40c12SJohn Marino 	buf = os_malloc(buflen);
4783ff40c12SJohn Marino 	if (buf == NULL)
4793ff40c12SJohn Marino 		return;
4803ff40c12SJohn Marino 	len = os_snprintf(buf, buflen,
4813ff40c12SJohn Marino 			  WPA_CTRL_REQ "%s-%d:%s needed for SSID ",
4823ff40c12SJohn Marino 			  field_name, ssid->id, txt);
483*a1157835SDaniel Fojt 	if (os_snprintf_error(buflen, len)) {
4843ff40c12SJohn Marino 		os_free(buf);
4853ff40c12SJohn Marino 		return;
4863ff40c12SJohn Marino 	}
4873ff40c12SJohn Marino 	if (ssid->ssid && buflen > len + ssid->ssid_len) {
4883ff40c12SJohn Marino 		os_memcpy(buf + len, ssid->ssid, ssid->ssid_len);
4893ff40c12SJohn Marino 		len += ssid->ssid_len;
4903ff40c12SJohn Marino 		buf[len] = '\0';
4913ff40c12SJohn Marino 	}
4923ff40c12SJohn Marino 	buf[buflen - 1] = '\0';
4933ff40c12SJohn Marino 	wpa_msg(wpa_s, MSG_INFO, "%s", buf);
4943ff40c12SJohn Marino 	os_free(buf);
4953ff40c12SJohn Marino }
4963ff40c12SJohn Marino #else /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */
4973ff40c12SJohn Marino #define eapol_test_eap_param_needed NULL
4983ff40c12SJohn Marino #endif /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */
4993ff40c12SJohn Marino 
5003ff40c12SJohn Marino 
eapol_test_cert_cb(void * ctx,struct tls_cert_data * cert,const char * cert_hash)501*a1157835SDaniel Fojt static void eapol_test_cert_cb(void *ctx, struct tls_cert_data *cert,
502*a1157835SDaniel Fojt 			       const char *cert_hash)
5033ff40c12SJohn Marino {
5043ff40c12SJohn Marino 	struct eapol_test_data *e = ctx;
505*a1157835SDaniel Fojt 	int i;
5063ff40c12SJohn Marino 
5073ff40c12SJohn Marino 	wpa_msg(e->wpa_s, MSG_INFO, WPA_EVENT_EAP_PEER_CERT
5083ff40c12SJohn Marino 		"depth=%d subject='%s'%s%s",
509*a1157835SDaniel Fojt 		cert->depth, cert->subject,
5103ff40c12SJohn Marino 		cert_hash ? " hash=" : "",
5113ff40c12SJohn Marino 		cert_hash ? cert_hash : "");
5123ff40c12SJohn Marino 
513*a1157835SDaniel Fojt 	if (cert->cert) {
5143ff40c12SJohn Marino 		char *cert_hex;
515*a1157835SDaniel Fojt 		size_t len = wpabuf_len(cert->cert) * 2 + 1;
5163ff40c12SJohn Marino 		cert_hex = os_malloc(len);
5173ff40c12SJohn Marino 		if (cert_hex) {
518*a1157835SDaniel Fojt 			wpa_snprintf_hex(cert_hex, len, wpabuf_head(cert->cert),
519*a1157835SDaniel Fojt 					 wpabuf_len(cert->cert));
5203ff40c12SJohn Marino 			wpa_msg_ctrl(e->wpa_s, MSG_INFO,
5213ff40c12SJohn Marino 				     WPA_EVENT_EAP_PEER_CERT
5223ff40c12SJohn Marino 				     "depth=%d subject='%s' cert=%s",
523*a1157835SDaniel Fojt 				     cert->depth, cert->subject, cert_hex);
5243ff40c12SJohn Marino 			os_free(cert_hex);
5253ff40c12SJohn Marino 		}
5263ff40c12SJohn Marino 
5273ff40c12SJohn Marino 		if (e->server_cert_file)
5283ff40c12SJohn Marino 			eapol_test_write_cert(e->server_cert_file,
529*a1157835SDaniel Fojt 					      cert->subject, cert->cert);
5303ff40c12SJohn Marino 	}
531*a1157835SDaniel Fojt 
532*a1157835SDaniel Fojt 	for (i = 0; i < cert->num_altsubject; i++)
533*a1157835SDaniel Fojt 		wpa_msg(e->wpa_s, MSG_INFO, WPA_EVENT_EAP_PEER_ALT
534*a1157835SDaniel Fojt 			"depth=%d %s", cert->depth, cert->altsubject[i]);
5353ff40c12SJohn Marino }
5363ff40c12SJohn Marino 
5373ff40c12SJohn Marino 
eapol_test_set_anon_id(void * ctx,const u8 * id,size_t len)5383ff40c12SJohn Marino static void eapol_test_set_anon_id(void *ctx, const u8 *id, size_t len)
5393ff40c12SJohn Marino {
5403ff40c12SJohn Marino 	struct eapol_test_data *e = ctx;
5413ff40c12SJohn Marino 	struct wpa_supplicant *wpa_s = e->wpa_s;
5423ff40c12SJohn Marino 	char *str;
5433ff40c12SJohn Marino 	int res;
5443ff40c12SJohn Marino 
5453ff40c12SJohn Marino 	wpa_hexdump_ascii(MSG_DEBUG, "EAP method updated anonymous_identity",
5463ff40c12SJohn Marino 			  id, len);
5473ff40c12SJohn Marino 
5483ff40c12SJohn Marino 	if (wpa_s->current_ssid == NULL)
5493ff40c12SJohn Marino 		return;
5503ff40c12SJohn Marino 
5513ff40c12SJohn Marino 	if (id == NULL) {
5523ff40c12SJohn Marino 		if (wpa_config_set(wpa_s->current_ssid, "anonymous_identity",
5533ff40c12SJohn Marino 				   "NULL", 0) < 0)
5543ff40c12SJohn Marino 			return;
5553ff40c12SJohn Marino 	} else {
5563ff40c12SJohn Marino 		str = os_malloc(len * 2 + 1);
5573ff40c12SJohn Marino 		if (str == NULL)
5583ff40c12SJohn Marino 			return;
5593ff40c12SJohn Marino 		wpa_snprintf_hex(str, len * 2 + 1, id, len);
5603ff40c12SJohn Marino 		res = wpa_config_set(wpa_s->current_ssid, "anonymous_identity",
5613ff40c12SJohn Marino 				     str, 0);
5623ff40c12SJohn Marino 		os_free(str);
5633ff40c12SJohn Marino 		if (res < 0)
5643ff40c12SJohn Marino 			return;
5653ff40c12SJohn Marino 	}
5663ff40c12SJohn Marino }
5673ff40c12SJohn Marino 
5683ff40c12SJohn Marino 
eapol_test_get_state(void * ctx)569*a1157835SDaniel Fojt static enum wpa_states eapol_test_get_state(void *ctx)
570*a1157835SDaniel Fojt {
571*a1157835SDaniel Fojt 	struct eapol_test_data *e = ctx;
572*a1157835SDaniel Fojt 	struct wpa_supplicant *wpa_s = e->wpa_s;
573*a1157835SDaniel Fojt 
574*a1157835SDaniel Fojt 	return wpa_s->wpa_state;
575*a1157835SDaniel Fojt }
576*a1157835SDaniel Fojt 
577*a1157835SDaniel Fojt 
test_eapol(struct eapol_test_data * e,struct wpa_supplicant * wpa_s,struct wpa_ssid * ssid)5786d49e1aeSJan Lentfer static int test_eapol(struct eapol_test_data *e, struct wpa_supplicant *wpa_s,
5796d49e1aeSJan Lentfer 		      struct wpa_ssid *ssid)
5806d49e1aeSJan Lentfer {
5816d49e1aeSJan Lentfer 	struct eapol_config eapol_conf;
5826d49e1aeSJan Lentfer 	struct eapol_ctx *ctx;
583*a1157835SDaniel Fojt 	struct wpa_sm_ctx *wctx;
5846d49e1aeSJan Lentfer 
5856d49e1aeSJan Lentfer 	ctx = os_zalloc(sizeof(*ctx));
5866d49e1aeSJan Lentfer 	if (ctx == NULL) {
5876d49e1aeSJan Lentfer 		printf("Failed to allocate EAPOL context.\n");
5886d49e1aeSJan Lentfer 		return -1;
5896d49e1aeSJan Lentfer 	}
5903ff40c12SJohn Marino 	ctx->ctx = e;
5916d49e1aeSJan Lentfer 	ctx->msg_ctx = wpa_s;
5926d49e1aeSJan Lentfer 	ctx->scard_ctx = wpa_s->scard;
5936d49e1aeSJan Lentfer 	ctx->cb = eapol_sm_cb;
5946d49e1aeSJan Lentfer 	ctx->cb_ctx = e;
5956d49e1aeSJan Lentfer 	ctx->eapol_send_ctx = wpa_s;
5966d49e1aeSJan Lentfer 	ctx->preauth = 0;
5976d49e1aeSJan Lentfer 	ctx->eapol_done_cb = eapol_test_eapol_done_cb;
5986d49e1aeSJan Lentfer 	ctx->eapol_send = eapol_test_eapol_send;
5996d49e1aeSJan Lentfer 	ctx->set_config_blob = eapol_test_set_config_blob;
6006d49e1aeSJan Lentfer 	ctx->get_config_blob = eapol_test_get_config_blob;
6016d49e1aeSJan Lentfer 	ctx->opensc_engine_path = wpa_s->conf->opensc_engine_path;
6026d49e1aeSJan Lentfer 	ctx->pkcs11_engine_path = wpa_s->conf->pkcs11_engine_path;
6036d49e1aeSJan Lentfer 	ctx->pkcs11_module_path = wpa_s->conf->pkcs11_module_path;
604*a1157835SDaniel Fojt 	ctx->openssl_ciphers = wpa_s->conf->openssl_ciphers;
6053ff40c12SJohn Marino 	ctx->eap_param_needed = eapol_test_eap_param_needed;
6063ff40c12SJohn Marino 	ctx->cert_cb = eapol_test_cert_cb;
6073ff40c12SJohn Marino 	ctx->cert_in_cb = 1;
6083ff40c12SJohn Marino 	ctx->set_anon_id = eapol_test_set_anon_id;
6096d49e1aeSJan Lentfer 
6106d49e1aeSJan Lentfer 	wpa_s->eapol = eapol_sm_init(ctx);
6116d49e1aeSJan Lentfer 	if (wpa_s->eapol == NULL) {
6126d49e1aeSJan Lentfer 		os_free(ctx);
6136d49e1aeSJan Lentfer 		printf("Failed to initialize EAPOL state machines.\n");
6146d49e1aeSJan Lentfer 		return -1;
6156d49e1aeSJan Lentfer 	}
6166d49e1aeSJan Lentfer 
617*a1157835SDaniel Fojt 	wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_NO_WPA;
618*a1157835SDaniel Fojt 	wctx = os_zalloc(sizeof(*wctx));
619*a1157835SDaniel Fojt 	if (wctx == NULL) {
620*a1157835SDaniel Fojt 		os_free(ctx);
621*a1157835SDaniel Fojt 		return -1;
622*a1157835SDaniel Fojt 	}
623*a1157835SDaniel Fojt 	wctx->ctx = e;
624*a1157835SDaniel Fojt 	wctx->msg_ctx = wpa_s;
625*a1157835SDaniel Fojt 	wctx->get_state = eapol_test_get_state;
626*a1157835SDaniel Fojt 	wpa_s->wpa = wpa_sm_init(wctx);
627*a1157835SDaniel Fojt 	if (!wpa_s->wpa) {
628*a1157835SDaniel Fojt 		os_free(ctx);
629*a1157835SDaniel Fojt 		os_free(wctx);
630*a1157835SDaniel Fojt 		return -1;
631*a1157835SDaniel Fojt 	}
632*a1157835SDaniel Fojt 
633*a1157835SDaniel Fojt 	if (!ssid)
634*a1157835SDaniel Fojt 		return 0;
635*a1157835SDaniel Fojt 
6366d49e1aeSJan Lentfer 	wpa_s->current_ssid = ssid;
6376d49e1aeSJan Lentfer 	os_memset(&eapol_conf, 0, sizeof(eapol_conf));
6386d49e1aeSJan Lentfer 	eapol_conf.accept_802_1x_keys = 1;
6396d49e1aeSJan Lentfer 	eapol_conf.required_keys = 0;
6406d49e1aeSJan Lentfer 	eapol_conf.fast_reauth = wpa_s->conf->fast_reauth;
6416d49e1aeSJan Lentfer 	eapol_conf.workaround = ssid->eap_workaround;
6423ff40c12SJohn Marino 	eapol_conf.external_sim = wpa_s->conf->external_sim;
6436d49e1aeSJan Lentfer 	eapol_sm_notify_config(wpa_s->eapol, &ssid->eap, &eapol_conf);
6446d49e1aeSJan Lentfer 	eapol_sm_register_scard_ctx(wpa_s->eapol, wpa_s->scard);
6456d49e1aeSJan Lentfer 
6466d49e1aeSJan Lentfer 
6476d49e1aeSJan Lentfer 	eapol_sm_notify_portValid(wpa_s->eapol, FALSE);
6486d49e1aeSJan Lentfer 	/* 802.1X::portControl = Auto */
6496d49e1aeSJan Lentfer 	eapol_sm_notify_portEnabled(wpa_s->eapol, TRUE);
6506d49e1aeSJan Lentfer 
6516d49e1aeSJan Lentfer 	return 0;
6526d49e1aeSJan Lentfer }
6536d49e1aeSJan Lentfer 
6546d49e1aeSJan Lentfer 
test_eapol_clean(struct eapol_test_data * e,struct wpa_supplicant * wpa_s)6556d49e1aeSJan Lentfer static void test_eapol_clean(struct eapol_test_data *e,
6566d49e1aeSJan Lentfer 			     struct wpa_supplicant *wpa_s)
6576d49e1aeSJan Lentfer {
6586d49e1aeSJan Lentfer 	struct extra_radius_attr *p, *prev;
6596d49e1aeSJan Lentfer 
660*a1157835SDaniel Fojt 	wpa_sm_deinit(wpa_s->wpa);
661*a1157835SDaniel Fojt 	wpa_s->wpa = NULL;
6626d49e1aeSJan Lentfer 	radius_client_deinit(e->radius);
6633ff40c12SJohn Marino 	wpabuf_free(e->last_eap_radius);
6646d49e1aeSJan Lentfer 	radius_msg_free(e->last_recv_radius);
6653ff40c12SJohn Marino 	e->last_recv_radius = NULL;
6666d49e1aeSJan Lentfer 	os_free(e->eap_identity);
6676d49e1aeSJan Lentfer 	e->eap_identity = NULL;
6686d49e1aeSJan Lentfer 	eapol_sm_deinit(wpa_s->eapol);
6696d49e1aeSJan Lentfer 	wpa_s->eapol = NULL;
6706d49e1aeSJan Lentfer 	if (e->radius_conf && e->radius_conf->auth_server) {
6716d49e1aeSJan Lentfer 		os_free(e->radius_conf->auth_server->shared_secret);
6726d49e1aeSJan Lentfer 		os_free(e->radius_conf->auth_server);
6736d49e1aeSJan Lentfer 	}
6746d49e1aeSJan Lentfer 	os_free(e->radius_conf);
6756d49e1aeSJan Lentfer 	e->radius_conf = NULL;
6766d49e1aeSJan Lentfer 	scard_deinit(wpa_s->scard);
6776d49e1aeSJan Lentfer 	if (wpa_s->ctrl_iface) {
6786d49e1aeSJan Lentfer 		wpa_supplicant_ctrl_iface_deinit(wpa_s->ctrl_iface);
6796d49e1aeSJan Lentfer 		wpa_s->ctrl_iface = NULL;
6806d49e1aeSJan Lentfer 	}
6813ff40c12SJohn Marino 
6823ff40c12SJohn Marino 	ext_password_deinit(wpa_s->ext_pw);
6833ff40c12SJohn Marino 	wpa_s->ext_pw = NULL;
6843ff40c12SJohn Marino 
6856d49e1aeSJan Lentfer 	wpa_config_free(wpa_s->conf);
6866d49e1aeSJan Lentfer 
6876d49e1aeSJan Lentfer 	p = e->extra_attrs;
6886d49e1aeSJan Lentfer 	while (p) {
6896d49e1aeSJan Lentfer 		prev = p;
6906d49e1aeSJan Lentfer 		p = p->next;
6916d49e1aeSJan Lentfer 		os_free(prev);
6926d49e1aeSJan Lentfer 	}
6936d49e1aeSJan Lentfer }
6946d49e1aeSJan Lentfer 
6956d49e1aeSJan Lentfer 
send_eap_request_identity(void * eloop_ctx,void * timeout_ctx)6966d49e1aeSJan Lentfer static void send_eap_request_identity(void *eloop_ctx, void *timeout_ctx)
6976d49e1aeSJan Lentfer {
6986d49e1aeSJan Lentfer 	struct wpa_supplicant *wpa_s = eloop_ctx;
6996d49e1aeSJan Lentfer 	u8 buf[100], *pos;
7006d49e1aeSJan Lentfer 	struct ieee802_1x_hdr *hdr;
7016d49e1aeSJan Lentfer 	struct eap_hdr *eap;
7026d49e1aeSJan Lentfer 
7036d49e1aeSJan Lentfer 	hdr = (struct ieee802_1x_hdr *) buf;
7046d49e1aeSJan Lentfer 	hdr->version = EAPOL_VERSION;
7056d49e1aeSJan Lentfer 	hdr->type = IEEE802_1X_TYPE_EAP_PACKET;
7066d49e1aeSJan Lentfer 	hdr->length = htons(5);
7076d49e1aeSJan Lentfer 
7086d49e1aeSJan Lentfer 	eap = (struct eap_hdr *) (hdr + 1);
7096d49e1aeSJan Lentfer 	eap->code = EAP_CODE_REQUEST;
710*a1157835SDaniel Fojt 	if (os_get_random((u8 *) &eap->identifier, sizeof(eap->identifier)) < 0)
711*a1157835SDaniel Fojt 		eap->identifier = os_random() & 0xff;
7126d49e1aeSJan Lentfer 	eap->length = htons(5);
7136d49e1aeSJan Lentfer 	pos = (u8 *) (eap + 1);
7146d49e1aeSJan Lentfer 	*pos = EAP_TYPE_IDENTITY;
7156d49e1aeSJan Lentfer 
7166d49e1aeSJan Lentfer 	printf("Sending fake EAP-Request-Identity\n");
7176d49e1aeSJan Lentfer 	eapol_sm_rx_eapol(wpa_s->eapol, wpa_s->bssid, buf,
7186d49e1aeSJan Lentfer 			  sizeof(*hdr) + 5);
7196d49e1aeSJan Lentfer }
7206d49e1aeSJan Lentfer 
7216d49e1aeSJan Lentfer 
eapol_test_timeout(void * eloop_ctx,void * timeout_ctx)7226d49e1aeSJan Lentfer static void eapol_test_timeout(void *eloop_ctx, void *timeout_ctx)
7236d49e1aeSJan Lentfer {
7246d49e1aeSJan Lentfer 	struct eapol_test_data *e = eloop_ctx;
7256d49e1aeSJan Lentfer 	printf("EAPOL test timed out\n");
7266d49e1aeSJan Lentfer 	e->auth_timed_out = 1;
7276d49e1aeSJan Lentfer 	eloop_terminate();
7286d49e1aeSJan Lentfer }
7296d49e1aeSJan Lentfer 
7306d49e1aeSJan Lentfer 
eap_type_text(u8 type)7316d49e1aeSJan Lentfer static char *eap_type_text(u8 type)
7326d49e1aeSJan Lentfer {
7336d49e1aeSJan Lentfer 	switch (type) {
7346d49e1aeSJan Lentfer 	case EAP_TYPE_IDENTITY: return "Identity";
7356d49e1aeSJan Lentfer 	case EAP_TYPE_NOTIFICATION: return "Notification";
7366d49e1aeSJan Lentfer 	case EAP_TYPE_NAK: return "Nak";
7376d49e1aeSJan Lentfer 	case EAP_TYPE_TLS: return "TLS";
7386d49e1aeSJan Lentfer 	case EAP_TYPE_TTLS: return "TTLS";
7396d49e1aeSJan Lentfer 	case EAP_TYPE_PEAP: return "PEAP";
7406d49e1aeSJan Lentfer 	case EAP_TYPE_SIM: return "SIM";
7416d49e1aeSJan Lentfer 	case EAP_TYPE_GTC: return "GTC";
7426d49e1aeSJan Lentfer 	case EAP_TYPE_MD5: return "MD5";
7436d49e1aeSJan Lentfer 	case EAP_TYPE_OTP: return "OTP";
7446d49e1aeSJan Lentfer 	case EAP_TYPE_FAST: return "FAST";
7456d49e1aeSJan Lentfer 	case EAP_TYPE_SAKE: return "SAKE";
7466d49e1aeSJan Lentfer 	case EAP_TYPE_PSK: return "PSK";
7476d49e1aeSJan Lentfer 	default: return "Unknown";
7486d49e1aeSJan Lentfer 	}
7496d49e1aeSJan Lentfer }
7506d49e1aeSJan Lentfer 
7516d49e1aeSJan Lentfer 
ieee802_1x_decapsulate_radius(struct eapol_test_data * e)7526d49e1aeSJan Lentfer static void ieee802_1x_decapsulate_radius(struct eapol_test_data *e)
7536d49e1aeSJan Lentfer {
7543ff40c12SJohn Marino 	struct wpabuf *eap;
7553ff40c12SJohn Marino 	const struct eap_hdr *hdr;
7566d49e1aeSJan Lentfer 	int eap_type = -1;
7576d49e1aeSJan Lentfer 	char buf[64];
7586d49e1aeSJan Lentfer 	struct radius_msg *msg;
7596d49e1aeSJan Lentfer 
7606d49e1aeSJan Lentfer 	if (e->last_recv_radius == NULL)
7616d49e1aeSJan Lentfer 		return;
7626d49e1aeSJan Lentfer 
7636d49e1aeSJan Lentfer 	msg = e->last_recv_radius;
7646d49e1aeSJan Lentfer 
7653ff40c12SJohn Marino 	eap = radius_msg_get_eap(msg);
7666d49e1aeSJan Lentfer 	if (eap == NULL) {
7676d49e1aeSJan Lentfer 		/* draft-aboba-radius-rfc2869bis-20.txt, Chap. 2.6.3:
7686d49e1aeSJan Lentfer 		 * RADIUS server SHOULD NOT send Access-Reject/no EAP-Message
7696d49e1aeSJan Lentfer 		 * attribute */
7706d49e1aeSJan Lentfer 		wpa_printf(MSG_DEBUG, "could not extract "
7716d49e1aeSJan Lentfer 			       "EAP-Message from RADIUS message");
7723ff40c12SJohn Marino 		wpabuf_free(e->last_eap_radius);
7736d49e1aeSJan Lentfer 		e->last_eap_radius = NULL;
7746d49e1aeSJan Lentfer 		return;
7756d49e1aeSJan Lentfer 	}
7766d49e1aeSJan Lentfer 
7773ff40c12SJohn Marino 	if (wpabuf_len(eap) < sizeof(*hdr)) {
7786d49e1aeSJan Lentfer 		wpa_printf(MSG_DEBUG, "too short EAP packet "
7796d49e1aeSJan Lentfer 			       "received from authentication server");
7803ff40c12SJohn Marino 		wpabuf_free(eap);
7816d49e1aeSJan Lentfer 		return;
7826d49e1aeSJan Lentfer 	}
7836d49e1aeSJan Lentfer 
7843ff40c12SJohn Marino 	if (wpabuf_len(eap) > sizeof(*hdr))
7853ff40c12SJohn Marino 		eap_type = (wpabuf_head_u8(eap))[sizeof(*hdr)];
7866d49e1aeSJan Lentfer 
7873ff40c12SJohn Marino 	hdr = wpabuf_head(eap);
7886d49e1aeSJan Lentfer 	switch (hdr->code) {
7896d49e1aeSJan Lentfer 	case EAP_CODE_REQUEST:
7906d49e1aeSJan Lentfer 		os_snprintf(buf, sizeof(buf), "EAP-Request-%s (%d)",
7916d49e1aeSJan Lentfer 			    eap_type >= 0 ? eap_type_text(eap_type) : "??",
7926d49e1aeSJan Lentfer 			    eap_type);
7936d49e1aeSJan Lentfer 		break;
7946d49e1aeSJan Lentfer 	case EAP_CODE_RESPONSE:
7956d49e1aeSJan Lentfer 		os_snprintf(buf, sizeof(buf), "EAP Response-%s (%d)",
7966d49e1aeSJan Lentfer 			    eap_type >= 0 ? eap_type_text(eap_type) : "??",
7976d49e1aeSJan Lentfer 			    eap_type);
7986d49e1aeSJan Lentfer 		break;
7996d49e1aeSJan Lentfer 	case EAP_CODE_SUCCESS:
8006d49e1aeSJan Lentfer 		os_strlcpy(buf, "EAP Success", sizeof(buf));
8016d49e1aeSJan Lentfer 		/* LEAP uses EAP Success within an authentication, so must not
8026d49e1aeSJan Lentfer 		 * stop here with eloop_terminate(); */
8036d49e1aeSJan Lentfer 		break;
8046d49e1aeSJan Lentfer 	case EAP_CODE_FAILURE:
8056d49e1aeSJan Lentfer 		os_strlcpy(buf, "EAP Failure", sizeof(buf));
806*a1157835SDaniel Fojt 		if (e->ctrl_iface)
807*a1157835SDaniel Fojt 			break;
8086d49e1aeSJan Lentfer 		eloop_terminate();
8096d49e1aeSJan Lentfer 		break;
8106d49e1aeSJan Lentfer 	default:
8116d49e1aeSJan Lentfer 		os_strlcpy(buf, "unknown EAP code", sizeof(buf));
8123ff40c12SJohn Marino 		wpa_hexdump_buf(MSG_DEBUG, "Decapsulated EAP packet", eap);
8136d49e1aeSJan Lentfer 		break;
8146d49e1aeSJan Lentfer 	}
8156d49e1aeSJan Lentfer 	wpa_printf(MSG_DEBUG, "decapsulated EAP packet (code=%d "
8166d49e1aeSJan Lentfer 		       "id=%d len=%d) from RADIUS server: %s",
8176d49e1aeSJan Lentfer 		      hdr->code, hdr->identifier, ntohs(hdr->length), buf);
8186d49e1aeSJan Lentfer 
8196d49e1aeSJan Lentfer 	/* sta->eapol_sm->be_auth.idFromServer = hdr->identifier; */
8206d49e1aeSJan Lentfer 
8213ff40c12SJohn Marino 	wpabuf_free(e->last_eap_radius);
8226d49e1aeSJan Lentfer 	e->last_eap_radius = eap;
8236d49e1aeSJan Lentfer 
8246d49e1aeSJan Lentfer 	{
8256d49e1aeSJan Lentfer 		struct ieee802_1x_hdr *dot1x;
8263ff40c12SJohn Marino 		dot1x = os_malloc(sizeof(*dot1x) + wpabuf_len(eap));
8276d49e1aeSJan Lentfer 		assert(dot1x != NULL);
8286d49e1aeSJan Lentfer 		dot1x->version = EAPOL_VERSION;
8296d49e1aeSJan Lentfer 		dot1x->type = IEEE802_1X_TYPE_EAP_PACKET;
8303ff40c12SJohn Marino 		dot1x->length = htons(wpabuf_len(eap));
8313ff40c12SJohn Marino 		os_memcpy((u8 *) (dot1x + 1), wpabuf_head(eap),
8323ff40c12SJohn Marino 			  wpabuf_len(eap));
8336d49e1aeSJan Lentfer 		eapol_sm_rx_eapol(e->wpa_s->eapol, e->wpa_s->bssid,
8343ff40c12SJohn Marino 				  (u8 *) dot1x,
8353ff40c12SJohn Marino 				  sizeof(*dot1x) + wpabuf_len(eap));
8366d49e1aeSJan Lentfer 		os_free(dot1x);
8376d49e1aeSJan Lentfer 	}
8386d49e1aeSJan Lentfer }
8396d49e1aeSJan Lentfer 
8406d49e1aeSJan Lentfer 
ieee802_1x_get_keys(struct eapol_test_data * e,struct radius_msg * msg,struct radius_msg * req,const u8 * shared_secret,size_t shared_secret_len)8416d49e1aeSJan Lentfer static void ieee802_1x_get_keys(struct eapol_test_data *e,
8426d49e1aeSJan Lentfer 				struct radius_msg *msg, struct radius_msg *req,
8436d49e1aeSJan Lentfer 				const u8 *shared_secret,
8446d49e1aeSJan Lentfer 				size_t shared_secret_len)
8456d49e1aeSJan Lentfer {
8466d49e1aeSJan Lentfer 	struct radius_ms_mppe_keys *keys;
847*a1157835SDaniel Fojt 	u8 *buf;
848*a1157835SDaniel Fojt 	size_t len;
8496d49e1aeSJan Lentfer 
8506d49e1aeSJan Lentfer 	keys = radius_msg_get_ms_keys(msg, req, shared_secret,
8516d49e1aeSJan Lentfer 				      shared_secret_len);
8526d49e1aeSJan Lentfer 	if (keys && keys->send == NULL && keys->recv == NULL) {
8536d49e1aeSJan Lentfer 		os_free(keys);
8546d49e1aeSJan Lentfer 		keys = radius_msg_get_cisco_keys(msg, req, shared_secret,
8556d49e1aeSJan Lentfer 						 shared_secret_len);
8566d49e1aeSJan Lentfer 	}
8576d49e1aeSJan Lentfer 
8586d49e1aeSJan Lentfer 	if (keys) {
8596d49e1aeSJan Lentfer 		if (keys->send) {
8606d49e1aeSJan Lentfer 			wpa_hexdump(MSG_DEBUG, "MS-MPPE-Send-Key (sign)",
8616d49e1aeSJan Lentfer 				    keys->send, keys->send_len);
8626d49e1aeSJan Lentfer 		}
8636d49e1aeSJan Lentfer 		if (keys->recv) {
8646d49e1aeSJan Lentfer 			wpa_hexdump(MSG_DEBUG, "MS-MPPE-Recv-Key (crypt)",
8656d49e1aeSJan Lentfer 				    keys->recv, keys->recv_len);
8666d49e1aeSJan Lentfer 			e->authenticator_pmk_len =
8676d49e1aeSJan Lentfer 				keys->recv_len > PMK_LEN ? PMK_LEN :
8686d49e1aeSJan Lentfer 				keys->recv_len;
8696d49e1aeSJan Lentfer 			os_memcpy(e->authenticator_pmk, keys->recv,
8706d49e1aeSJan Lentfer 				  e->authenticator_pmk_len);
8716d49e1aeSJan Lentfer 			if (e->authenticator_pmk_len == 16 && keys->send &&
8726d49e1aeSJan Lentfer 			    keys->send_len == 16) {
8736d49e1aeSJan Lentfer 				/* MS-CHAP-v2 derives 16 octet keys */
8746d49e1aeSJan Lentfer 				wpa_printf(MSG_DEBUG, "Use MS-MPPE-Send-Key "
8756d49e1aeSJan Lentfer 					   "to extend PMK to 32 octets");
8766d49e1aeSJan Lentfer 				os_memcpy(e->authenticator_pmk +
8776d49e1aeSJan Lentfer 					  e->authenticator_pmk_len,
8786d49e1aeSJan Lentfer 					  keys->send, keys->send_len);
8796d49e1aeSJan Lentfer 				e->authenticator_pmk_len += keys->send_len;
8806d49e1aeSJan Lentfer 			}
8816d49e1aeSJan Lentfer 		}
8826d49e1aeSJan Lentfer 
8836d49e1aeSJan Lentfer 		os_free(keys->send);
8846d49e1aeSJan Lentfer 		os_free(keys->recv);
8856d49e1aeSJan Lentfer 		os_free(keys);
8866d49e1aeSJan Lentfer 	}
887*a1157835SDaniel Fojt 
888*a1157835SDaniel Fojt 	if (radius_msg_get_attr_ptr(msg, RADIUS_ATTR_EAP_KEY_NAME, &buf, &len,
889*a1157835SDaniel Fojt 				    NULL) == 0) {
890*a1157835SDaniel Fojt 		os_memcpy(e->authenticator_eap_key_name, buf, len);
891*a1157835SDaniel Fojt 		e->authenticator_eap_key_name_len = len;
892*a1157835SDaniel Fojt 	} else {
893*a1157835SDaniel Fojt 		e->authenticator_eap_key_name_len = 0;
894*a1157835SDaniel Fojt 	}
8956d49e1aeSJan Lentfer }
8966d49e1aeSJan Lentfer 
8976d49e1aeSJan Lentfer 
8986d49e1aeSJan Lentfer /* Process the RADIUS frames from Authentication Server */
8996d49e1aeSJan Lentfer static RadiusRxResult
ieee802_1x_receive_auth(struct radius_msg * msg,struct radius_msg * req,const u8 * shared_secret,size_t shared_secret_len,void * data)9006d49e1aeSJan Lentfer ieee802_1x_receive_auth(struct radius_msg *msg, struct radius_msg *req,
9016d49e1aeSJan Lentfer 			const u8 *shared_secret, size_t shared_secret_len,
9026d49e1aeSJan Lentfer 			void *data)
9036d49e1aeSJan Lentfer {
9046d49e1aeSJan Lentfer 	struct eapol_test_data *e = data;
9053ff40c12SJohn Marino 	struct radius_hdr *hdr = radius_msg_get_hdr(msg);
9066d49e1aeSJan Lentfer 
9076d49e1aeSJan Lentfer 	/* RFC 2869, Ch. 5.13: valid Message-Authenticator attribute MUST be
9086d49e1aeSJan Lentfer 	 * present when packet contains an EAP-Message attribute */
9093ff40c12SJohn Marino 	if (hdr->code == RADIUS_CODE_ACCESS_REJECT &&
9106d49e1aeSJan Lentfer 	    radius_msg_get_attr(msg, RADIUS_ATTR_MESSAGE_AUTHENTICATOR, NULL,
9116d49e1aeSJan Lentfer 				0) < 0 &&
9126d49e1aeSJan Lentfer 	    radius_msg_get_attr(msg, RADIUS_ATTR_EAP_MESSAGE, NULL, 0) < 0) {
9136d49e1aeSJan Lentfer 		wpa_printf(MSG_DEBUG, "Allowing RADIUS "
9146d49e1aeSJan Lentfer 			      "Access-Reject without Message-Authenticator "
9156d49e1aeSJan Lentfer 			      "since it does not include EAP-Message\n");
9166d49e1aeSJan Lentfer 	} else if (radius_msg_verify(msg, shared_secret, shared_secret_len,
9176d49e1aeSJan Lentfer 				     req, 1)) {
9186d49e1aeSJan Lentfer 		printf("Incoming RADIUS packet did not have correct "
9196d49e1aeSJan Lentfer 		       "Message-Authenticator - dropped\n");
9206d49e1aeSJan Lentfer 		return RADIUS_RX_UNKNOWN;
9216d49e1aeSJan Lentfer 	}
9226d49e1aeSJan Lentfer 
9233ff40c12SJohn Marino 	if (hdr->code != RADIUS_CODE_ACCESS_ACCEPT &&
9243ff40c12SJohn Marino 	    hdr->code != RADIUS_CODE_ACCESS_REJECT &&
9253ff40c12SJohn Marino 	    hdr->code != RADIUS_CODE_ACCESS_CHALLENGE) {
9266d49e1aeSJan Lentfer 		printf("Unknown RADIUS message code\n");
9276d49e1aeSJan Lentfer 		return RADIUS_RX_UNKNOWN;
9286d49e1aeSJan Lentfer 	}
9296d49e1aeSJan Lentfer 
9306d49e1aeSJan Lentfer 	e->radius_identifier = -1;
9316d49e1aeSJan Lentfer 	wpa_printf(MSG_DEBUG, "RADIUS packet matching with station");
9326d49e1aeSJan Lentfer 
9336d49e1aeSJan Lentfer 	radius_msg_free(e->last_recv_radius);
9346d49e1aeSJan Lentfer 	e->last_recv_radius = msg;
9356d49e1aeSJan Lentfer 
9363ff40c12SJohn Marino 	switch (hdr->code) {
9376d49e1aeSJan Lentfer 	case RADIUS_CODE_ACCESS_ACCEPT:
9386d49e1aeSJan Lentfer 		e->radius_access_accept_received = 1;
9396d49e1aeSJan Lentfer 		ieee802_1x_get_keys(e, msg, req, shared_secret,
9406d49e1aeSJan Lentfer 				    shared_secret_len);
9416d49e1aeSJan Lentfer 		break;
9426d49e1aeSJan Lentfer 	case RADIUS_CODE_ACCESS_REJECT:
9436d49e1aeSJan Lentfer 		e->radius_access_reject_received = 1;
9446d49e1aeSJan Lentfer 		break;
9456d49e1aeSJan Lentfer 	}
9466d49e1aeSJan Lentfer 
9476d49e1aeSJan Lentfer 	ieee802_1x_decapsulate_radius(e);
9486d49e1aeSJan Lentfer 
9493ff40c12SJohn Marino 	if ((hdr->code == RADIUS_CODE_ACCESS_ACCEPT &&
9506d49e1aeSJan Lentfer 	     e->eapol_test_num_reauths < 0) ||
9513ff40c12SJohn Marino 	    hdr->code == RADIUS_CODE_ACCESS_REJECT) {
952*a1157835SDaniel Fojt 		if (!e->ctrl_iface)
9536d49e1aeSJan Lentfer 			eloop_terminate();
9546d49e1aeSJan Lentfer 	}
9556d49e1aeSJan Lentfer 
9566d49e1aeSJan Lentfer 	return RADIUS_RX_QUEUED;
9576d49e1aeSJan Lentfer }
9586d49e1aeSJan Lentfer 
9596d49e1aeSJan Lentfer 
driver_get_ssid(void * priv,u8 * ssid)960*a1157835SDaniel Fojt static int driver_get_ssid(void *priv, u8 *ssid)
961*a1157835SDaniel Fojt {
962*a1157835SDaniel Fojt 	ssid[0] = 0;
963*a1157835SDaniel Fojt 	return 0;
964*a1157835SDaniel Fojt }
965*a1157835SDaniel Fojt 
966*a1157835SDaniel Fojt 
driver_get_bssid(void * priv,u8 * bssid)967*a1157835SDaniel Fojt static int driver_get_bssid(void *priv, u8 *bssid)
968*a1157835SDaniel Fojt {
969*a1157835SDaniel Fojt 	struct eapol_test_data *e = priv;
970*a1157835SDaniel Fojt 
971*a1157835SDaniel Fojt 	if (e->ctrl_iface && !e->id_req_sent) {
972*a1157835SDaniel Fojt 		eloop_register_timeout(0, 0, send_eap_request_identity,
973*a1157835SDaniel Fojt 				       e->wpa_s, NULL);
974*a1157835SDaniel Fojt 		e->id_req_sent = 1;
975*a1157835SDaniel Fojt 	}
976*a1157835SDaniel Fojt 
977*a1157835SDaniel Fojt 	os_memset(bssid, 0, ETH_ALEN);
978*a1157835SDaniel Fojt 	bssid[5] = 1;
979*a1157835SDaniel Fojt 	return 0;
980*a1157835SDaniel Fojt }
981*a1157835SDaniel Fojt 
982*a1157835SDaniel Fojt 
driver_get_capa(void * priv,struct wpa_driver_capa * capa)983*a1157835SDaniel Fojt static int driver_get_capa(void *priv, struct wpa_driver_capa *capa)
984*a1157835SDaniel Fojt {
985*a1157835SDaniel Fojt 	os_memset(capa, 0, sizeof(*capa));
986*a1157835SDaniel Fojt 	capa->flags = WPA_DRIVER_FLAGS_WIRED;
987*a1157835SDaniel Fojt 	return 0;
988*a1157835SDaniel Fojt }
989*a1157835SDaniel Fojt 
990*a1157835SDaniel Fojt 
991*a1157835SDaniel Fojt struct wpa_driver_ops eapol_test_drv_ops = {
992*a1157835SDaniel Fojt 	.name = "test",
993*a1157835SDaniel Fojt 	.get_ssid = driver_get_ssid,
994*a1157835SDaniel Fojt 	.get_bssid = driver_get_bssid,
995*a1157835SDaniel Fojt 	.get_capa = driver_get_capa,
996*a1157835SDaniel Fojt };
997*a1157835SDaniel Fojt 
wpa_init_conf(struct eapol_test_data * e,struct wpa_supplicant * wpa_s,const char * authsrv,int port,const char * secret,const char * cli_addr,const char * ifname)9986d49e1aeSJan Lentfer static void wpa_init_conf(struct eapol_test_data *e,
9996d49e1aeSJan Lentfer 			  struct wpa_supplicant *wpa_s, const char *authsrv,
10006d49e1aeSJan Lentfer 			  int port, const char *secret,
1001*a1157835SDaniel Fojt 			  const char *cli_addr, const char *ifname)
10026d49e1aeSJan Lentfer {
10036d49e1aeSJan Lentfer 	struct hostapd_radius_server *as;
10046d49e1aeSJan Lentfer 	int res;
10056d49e1aeSJan Lentfer 
1006*a1157835SDaniel Fojt 	wpa_s->driver = &eapol_test_drv_ops;
1007*a1157835SDaniel Fojt 	wpa_s->drv_priv = e;
10086d49e1aeSJan Lentfer 	wpa_s->bssid[5] = 1;
10096d49e1aeSJan Lentfer 	os_memcpy(wpa_s->own_addr, e->own_addr, ETH_ALEN);
10106d49e1aeSJan Lentfer 	e->own_ip_addr.s_addr = htonl((127 << 24) | 1);
1011*a1157835SDaniel Fojt 	os_strlcpy(wpa_s->ifname, ifname, sizeof(wpa_s->ifname));
10126d49e1aeSJan Lentfer 
10136d49e1aeSJan Lentfer 	e->radius_conf = os_zalloc(sizeof(struct hostapd_radius_servers));
10146d49e1aeSJan Lentfer 	assert(e->radius_conf != NULL);
10156d49e1aeSJan Lentfer 	e->radius_conf->num_auth_servers = 1;
10166d49e1aeSJan Lentfer 	as = os_zalloc(sizeof(struct hostapd_radius_server));
10176d49e1aeSJan Lentfer 	assert(as != NULL);
10186d49e1aeSJan Lentfer #if defined(CONFIG_NATIVE_WINDOWS) || defined(CONFIG_ANSI_C_EXTRA)
10196d49e1aeSJan Lentfer 	{
10206d49e1aeSJan Lentfer 		int a[4];
10216d49e1aeSJan Lentfer 		u8 *pos;
10226d49e1aeSJan Lentfer 		sscanf(authsrv, "%d.%d.%d.%d", &a[0], &a[1], &a[2], &a[3]);
10236d49e1aeSJan Lentfer 		pos = (u8 *) &as->addr.u.v4;
10246d49e1aeSJan Lentfer 		*pos++ = a[0];
10256d49e1aeSJan Lentfer 		*pos++ = a[1];
10266d49e1aeSJan Lentfer 		*pos++ = a[2];
10276d49e1aeSJan Lentfer 		*pos++ = a[3];
10286d49e1aeSJan Lentfer 	}
10296d49e1aeSJan Lentfer #else /* CONFIG_NATIVE_WINDOWS or CONFIG_ANSI_C_EXTRA */
1030*a1157835SDaniel Fojt 	if (hostapd_parse_ip_addr(authsrv, &as->addr) < 0) {
1031*a1157835SDaniel Fojt 		wpa_printf(MSG_ERROR, "Invalid IP address '%s'",
1032*a1157835SDaniel Fojt 			   authsrv);
1033*a1157835SDaniel Fojt 		assert(0);
1034*a1157835SDaniel Fojt 	}
10356d49e1aeSJan Lentfer #endif /* CONFIG_NATIVE_WINDOWS or CONFIG_ANSI_C_EXTRA */
10366d49e1aeSJan Lentfer 	as->port = port;
10376d49e1aeSJan Lentfer 	as->shared_secret = (u8 *) os_strdup(secret);
10386d49e1aeSJan Lentfer 	as->shared_secret_len = os_strlen(secret);
10396d49e1aeSJan Lentfer 	e->radius_conf->auth_server = as;
10406d49e1aeSJan Lentfer 	e->radius_conf->auth_servers = as;
10416d49e1aeSJan Lentfer 	e->radius_conf->msg_dumps = 1;
10426d49e1aeSJan Lentfer 	if (cli_addr) {
10436d49e1aeSJan Lentfer 		if (hostapd_parse_ip_addr(cli_addr,
10446d49e1aeSJan Lentfer 					  &e->radius_conf->client_addr) == 0)
10456d49e1aeSJan Lentfer 			e->radius_conf->force_client_addr = 1;
10466d49e1aeSJan Lentfer 		else {
10476d49e1aeSJan Lentfer 			wpa_printf(MSG_ERROR, "Invalid IP address '%s'",
10486d49e1aeSJan Lentfer 				   cli_addr);
10496d49e1aeSJan Lentfer 			assert(0);
10506d49e1aeSJan Lentfer 		}
10516d49e1aeSJan Lentfer 	}
10526d49e1aeSJan Lentfer 
10536d49e1aeSJan Lentfer 	e->radius = radius_client_init(wpa_s, e->radius_conf);
10546d49e1aeSJan Lentfer 	assert(e->radius != NULL);
10556d49e1aeSJan Lentfer 
10566d49e1aeSJan Lentfer 	res = radius_client_register(e->radius, RADIUS_AUTH,
10576d49e1aeSJan Lentfer 				     ieee802_1x_receive_auth, e);
10586d49e1aeSJan Lentfer 	assert(res == 0);
10596d49e1aeSJan Lentfer }
10606d49e1aeSJan Lentfer 
10616d49e1aeSJan Lentfer 
scard_test(struct eapol_test_data * e)1062*a1157835SDaniel Fojt static int scard_test(struct eapol_test_data *e)
10636d49e1aeSJan Lentfer {
10646d49e1aeSJan Lentfer 	struct scard_data *scard;
10656d49e1aeSJan Lentfer 	size_t len;
10666d49e1aeSJan Lentfer 	char imsi[20];
10676d49e1aeSJan Lentfer 	unsigned char _rand[16];
10686d49e1aeSJan Lentfer #ifdef PCSC_FUNCS
10696d49e1aeSJan Lentfer 	unsigned char sres[4];
10706d49e1aeSJan Lentfer 	unsigned char kc[8];
10716d49e1aeSJan Lentfer #endif /* PCSC_FUNCS */
10726d49e1aeSJan Lentfer #define num_triplets 5
10736d49e1aeSJan Lentfer 	unsigned char rand_[num_triplets][16];
10746d49e1aeSJan Lentfer 	unsigned char sres_[num_triplets][4];
10756d49e1aeSJan Lentfer 	unsigned char kc_[num_triplets][8];
10766d49e1aeSJan Lentfer 	int i, res;
10776d49e1aeSJan Lentfer 	size_t j;
10786d49e1aeSJan Lentfer 
10796d49e1aeSJan Lentfer #define AKA_RAND_LEN 16
10806d49e1aeSJan Lentfer #define AKA_AUTN_LEN 16
10816d49e1aeSJan Lentfer #define AKA_AUTS_LEN 14
10826d49e1aeSJan Lentfer #define RES_MAX_LEN 16
10836d49e1aeSJan Lentfer #define IK_LEN 16
10846d49e1aeSJan Lentfer #define CK_LEN 16
10856d49e1aeSJan Lentfer 	unsigned char aka_rand[AKA_RAND_LEN];
10866d49e1aeSJan Lentfer 	unsigned char aka_autn[AKA_AUTN_LEN];
10876d49e1aeSJan Lentfer 	unsigned char aka_auts[AKA_AUTS_LEN];
10886d49e1aeSJan Lentfer 	unsigned char aka_res[RES_MAX_LEN];
10896d49e1aeSJan Lentfer 	size_t aka_res_len;
10906d49e1aeSJan Lentfer 	unsigned char aka_ik[IK_LEN];
10916d49e1aeSJan Lentfer 	unsigned char aka_ck[CK_LEN];
10926d49e1aeSJan Lentfer 
1093*a1157835SDaniel Fojt 	scard = scard_init(e->pcsc_reader);
10946d49e1aeSJan Lentfer 	if (scard == NULL)
10956d49e1aeSJan Lentfer 		return -1;
1096*a1157835SDaniel Fojt 	if (scard_set_pin(scard, e->pcsc_pin)) {
10976d49e1aeSJan Lentfer 		wpa_printf(MSG_WARNING, "PIN validation failed");
10986d49e1aeSJan Lentfer 		scard_deinit(scard);
10996d49e1aeSJan Lentfer 		return -1;
11006d49e1aeSJan Lentfer 	}
11016d49e1aeSJan Lentfer 
11026d49e1aeSJan Lentfer 	len = sizeof(imsi);
11036d49e1aeSJan Lentfer 	if (scard_get_imsi(scard, imsi, &len))
11046d49e1aeSJan Lentfer 		goto failed;
11056d49e1aeSJan Lentfer 	wpa_hexdump_ascii(MSG_DEBUG, "SCARD: IMSI", (u8 *) imsi, len);
11066d49e1aeSJan Lentfer 	/* NOTE: Permanent Username: 1 | IMSI */
11076d49e1aeSJan Lentfer 
11083ff40c12SJohn Marino 	wpa_printf(MSG_DEBUG, "SCARD: MNC length %d",
11093ff40c12SJohn Marino 		   scard_get_mnc_len(scard));
11103ff40c12SJohn Marino 
11116d49e1aeSJan Lentfer 	os_memset(_rand, 0, sizeof(_rand));
11126d49e1aeSJan Lentfer 	if (scard_gsm_auth(scard, _rand, sres, kc))
11136d49e1aeSJan Lentfer 		goto failed;
11146d49e1aeSJan Lentfer 
11156d49e1aeSJan Lentfer 	os_memset(_rand, 0xff, sizeof(_rand));
11166d49e1aeSJan Lentfer 	if (scard_gsm_auth(scard, _rand, sres, kc))
11176d49e1aeSJan Lentfer 		goto failed;
11186d49e1aeSJan Lentfer 
11196d49e1aeSJan Lentfer 	for (i = 0; i < num_triplets; i++) {
11206d49e1aeSJan Lentfer 		os_memset(rand_[i], i, sizeof(rand_[i]));
11216d49e1aeSJan Lentfer 		if (scard_gsm_auth(scard, rand_[i], sres_[i], kc_[i]))
11226d49e1aeSJan Lentfer 			goto failed;
11236d49e1aeSJan Lentfer 	}
11246d49e1aeSJan Lentfer 
11256d49e1aeSJan Lentfer 	for (i = 0; i < num_triplets; i++) {
11266d49e1aeSJan Lentfer 		printf("1");
11276d49e1aeSJan Lentfer 		for (j = 0; j < len; j++)
11286d49e1aeSJan Lentfer 			printf("%c", imsi[j]);
11296d49e1aeSJan Lentfer 		printf(",");
11306d49e1aeSJan Lentfer 		for (j = 0; j < 16; j++)
11316d49e1aeSJan Lentfer 			printf("%02X", rand_[i][j]);
11326d49e1aeSJan Lentfer 		printf(",");
11336d49e1aeSJan Lentfer 		for (j = 0; j < 4; j++)
11346d49e1aeSJan Lentfer 			printf("%02X", sres_[i][j]);
11356d49e1aeSJan Lentfer 		printf(",");
11366d49e1aeSJan Lentfer 		for (j = 0; j < 8; j++)
11376d49e1aeSJan Lentfer 			printf("%02X", kc_[i][j]);
11386d49e1aeSJan Lentfer 		printf("\n");
11396d49e1aeSJan Lentfer 	}
11406d49e1aeSJan Lentfer 
11416d49e1aeSJan Lentfer 	wpa_printf(MSG_DEBUG, "Trying to use UMTS authentication");
11426d49e1aeSJan Lentfer 
11436d49e1aeSJan Lentfer 	/* seq 39 (0x28) */
11446d49e1aeSJan Lentfer 	os_memset(aka_rand, 0xaa, 16);
11456d49e1aeSJan Lentfer 	os_memcpy(aka_autn, "\x86\x71\x31\xcb\xa2\xfc\x61\xdf"
11466d49e1aeSJan Lentfer 		  "\xa3\xb3\x97\x9d\x07\x32\xa2\x12", 16);
11476d49e1aeSJan Lentfer 
11486d49e1aeSJan Lentfer 	res = scard_umts_auth(scard, aka_rand, aka_autn, aka_res, &aka_res_len,
11496d49e1aeSJan Lentfer 			      aka_ik, aka_ck, aka_auts);
11506d49e1aeSJan Lentfer 	if (res == 0) {
11516d49e1aeSJan Lentfer 		wpa_printf(MSG_DEBUG, "UMTS auth completed successfully");
11526d49e1aeSJan Lentfer 		wpa_hexdump(MSG_DEBUG, "RES", aka_res, aka_res_len);
11536d49e1aeSJan Lentfer 		wpa_hexdump(MSG_DEBUG, "IK", aka_ik, IK_LEN);
11546d49e1aeSJan Lentfer 		wpa_hexdump(MSG_DEBUG, "CK", aka_ck, CK_LEN);
11556d49e1aeSJan Lentfer 	} else if (res == -2) {
11566d49e1aeSJan Lentfer 		wpa_printf(MSG_DEBUG, "UMTS auth resulted in synchronization "
11576d49e1aeSJan Lentfer 			   "failure");
11586d49e1aeSJan Lentfer 		wpa_hexdump(MSG_DEBUG, "AUTS", aka_auts, AKA_AUTS_LEN);
11596d49e1aeSJan Lentfer 	} else {
11606d49e1aeSJan Lentfer 		wpa_printf(MSG_DEBUG, "UMTS auth failed");
11616d49e1aeSJan Lentfer 	}
11626d49e1aeSJan Lentfer 
11636d49e1aeSJan Lentfer failed:
11646d49e1aeSJan Lentfer 	scard_deinit(scard);
11656d49e1aeSJan Lentfer 
11666d49e1aeSJan Lentfer 	return 0;
11676d49e1aeSJan Lentfer #undef num_triplets
11686d49e1aeSJan Lentfer }
11696d49e1aeSJan Lentfer 
11706d49e1aeSJan Lentfer 
scard_get_triplets(struct eapol_test_data * e,int argc,char * argv[])1171*a1157835SDaniel Fojt static int scard_get_triplets(struct eapol_test_data *e, int argc, char *argv[])
11726d49e1aeSJan Lentfer {
11736d49e1aeSJan Lentfer 	struct scard_data *scard;
11746d49e1aeSJan Lentfer 	size_t len;
11756d49e1aeSJan Lentfer 	char imsi[20];
11766d49e1aeSJan Lentfer 	unsigned char _rand[16];
11776d49e1aeSJan Lentfer 	unsigned char sres[4];
11786d49e1aeSJan Lentfer 	unsigned char kc[8];
11796d49e1aeSJan Lentfer 	int num_triplets;
11806d49e1aeSJan Lentfer 	int i;
11816d49e1aeSJan Lentfer 	size_t j;
11826d49e1aeSJan Lentfer 
11836d49e1aeSJan Lentfer 	if (argc < 2 || ((num_triplets = atoi(argv[1])) <= 0)) {
11846d49e1aeSJan Lentfer 		printf("invalid parameters for sim command\n");
11856d49e1aeSJan Lentfer 		return -1;
11866d49e1aeSJan Lentfer 	}
11876d49e1aeSJan Lentfer 
11886d49e1aeSJan Lentfer 	if (argc <= 2 || os_strcmp(argv[2], "debug") != 0) {
11896d49e1aeSJan Lentfer 		/* disable debug output */
11906d49e1aeSJan Lentfer 		wpa_debug_level = 99;
11916d49e1aeSJan Lentfer 	}
11926d49e1aeSJan Lentfer 
1193*a1157835SDaniel Fojt 	scard = scard_init(e->pcsc_reader);
11946d49e1aeSJan Lentfer 	if (scard == NULL) {
11956d49e1aeSJan Lentfer 		printf("Failed to open smartcard connection\n");
11966d49e1aeSJan Lentfer 		return -1;
11976d49e1aeSJan Lentfer 	}
11986d49e1aeSJan Lentfer 	if (scard_set_pin(scard, argv[0])) {
11996d49e1aeSJan Lentfer 		wpa_printf(MSG_WARNING, "PIN validation failed");
12006d49e1aeSJan Lentfer 		scard_deinit(scard);
12016d49e1aeSJan Lentfer 		return -1;
12026d49e1aeSJan Lentfer 	}
12036d49e1aeSJan Lentfer 
12046d49e1aeSJan Lentfer 	len = sizeof(imsi);
12056d49e1aeSJan Lentfer 	if (scard_get_imsi(scard, imsi, &len)) {
12066d49e1aeSJan Lentfer 		scard_deinit(scard);
12076d49e1aeSJan Lentfer 		return -1;
12086d49e1aeSJan Lentfer 	}
12096d49e1aeSJan Lentfer 
12106d49e1aeSJan Lentfer 	for (i = 0; i < num_triplets; i++) {
12116d49e1aeSJan Lentfer 		os_memset(_rand, i, sizeof(_rand));
12126d49e1aeSJan Lentfer 		if (scard_gsm_auth(scard, _rand, sres, kc))
12136d49e1aeSJan Lentfer 			break;
12146d49e1aeSJan Lentfer 
12156d49e1aeSJan Lentfer 		/* IMSI:Kc:SRES:RAND */
12166d49e1aeSJan Lentfer 		for (j = 0; j < len; j++)
12176d49e1aeSJan Lentfer 			printf("%c", imsi[j]);
12186d49e1aeSJan Lentfer 		printf(":");
12196d49e1aeSJan Lentfer 		for (j = 0; j < 8; j++)
12206d49e1aeSJan Lentfer 			printf("%02X", kc[j]);
12216d49e1aeSJan Lentfer 		printf(":");
12226d49e1aeSJan Lentfer 		for (j = 0; j < 4; j++)
12236d49e1aeSJan Lentfer 			printf("%02X", sres[j]);
12246d49e1aeSJan Lentfer 		printf(":");
12256d49e1aeSJan Lentfer 		for (j = 0; j < 16; j++)
12266d49e1aeSJan Lentfer 			printf("%02X", _rand[j]);
12276d49e1aeSJan Lentfer 		printf("\n");
12286d49e1aeSJan Lentfer 	}
12296d49e1aeSJan Lentfer 
12306d49e1aeSJan Lentfer 	scard_deinit(scard);
12316d49e1aeSJan Lentfer 
12326d49e1aeSJan Lentfer 	return 0;
12336d49e1aeSJan Lentfer }
12346d49e1aeSJan Lentfer 
12356d49e1aeSJan Lentfer 
eapol_test_terminate(int sig,void * signal_ctx)12363ff40c12SJohn Marino static void eapol_test_terminate(int sig, void *signal_ctx)
12376d49e1aeSJan Lentfer {
12383ff40c12SJohn Marino 	struct wpa_supplicant *wpa_s = signal_ctx;
12396d49e1aeSJan Lentfer 	wpa_msg(wpa_s, MSG_INFO, "Signal %d received - terminating", sig);
12406d49e1aeSJan Lentfer 	eloop_terminate();
12416d49e1aeSJan Lentfer }
12426d49e1aeSJan Lentfer 
12436d49e1aeSJan Lentfer 
usage(void)12446d49e1aeSJan Lentfer static void usage(void)
12456d49e1aeSJan Lentfer {
12466d49e1aeSJan Lentfer 	printf("usage:\n"
1247*a1157835SDaniel Fojt 	       "eapol_test [-enWSv] -c<conf> [-a<AS IP>] [-p<AS port>] "
12486d49e1aeSJan Lentfer 	       "[-s<AS secret>]\\\n"
12496d49e1aeSJan Lentfer 	       "           [-r<count>] [-t<timeout>] [-C<Connect-Info>] \\\n"
12503ff40c12SJohn Marino 	       "           [-M<client MAC address>] [-o<server cert file] \\\n"
1251*a1157835SDaniel Fojt 	       "           [-N<attr spec>] [-R<PC/SC reader>] "
1252*a1157835SDaniel Fojt 	       "[-P<PC/SC PIN>] \\\n"
1253*a1157835SDaniel Fojt 	       "           [-A<client IP>] [-i<ifname>] [-T<ctrl_iface>]\n"
12546d49e1aeSJan Lentfer 	       "eapol_test scard\n"
12556d49e1aeSJan Lentfer 	       "eapol_test sim <PIN> <num triplets> [debug]\n"
12566d49e1aeSJan Lentfer 	       "\n");
12576d49e1aeSJan Lentfer 	printf("options:\n"
12586d49e1aeSJan Lentfer 	       "  -c<conf> = configuration file\n"
12596d49e1aeSJan Lentfer 	       "  -a<AS IP> = IP address of the authentication server, "
12606d49e1aeSJan Lentfer 	       "default 127.0.0.1\n"
12616d49e1aeSJan Lentfer 	       "  -p<AS port> = UDP port of the authentication server, "
12626d49e1aeSJan Lentfer 	       "default 1812\n"
12636d49e1aeSJan Lentfer 	       "  -s<AS secret> = shared secret with the authentication "
12646d49e1aeSJan Lentfer 	       "server, default 'radius'\n"
12656d49e1aeSJan Lentfer 	       "  -A<client IP> = IP address of the client, default: select "
12666d49e1aeSJan Lentfer 	       "automatically\n"
12676d49e1aeSJan Lentfer 	       "  -r<count> = number of re-authentications\n"
1268*a1157835SDaniel Fojt 	       "  -e = Request EAP-Key-Name\n"
12696d49e1aeSJan Lentfer 	       "  -W = wait for a control interface monitor before starting\n"
12706d49e1aeSJan Lentfer 	       "  -S = save configuration after authentication\n"
12716d49e1aeSJan Lentfer 	       "  -n = no MPPE keys expected\n"
1272*a1157835SDaniel Fojt 	       "  -v = show version\n"
12736d49e1aeSJan Lentfer 	       "  -t<timeout> = sets timeout in seconds (default: 30 s)\n"
12746d49e1aeSJan Lentfer 	       "  -C<Connect-Info> = RADIUS Connect-Info (default: "
12756d49e1aeSJan Lentfer 	       "CONNECT 11Mbps 802.11b)\n"
12766d49e1aeSJan Lentfer 	       "  -M<client MAC address> = Set own MAC address "
12776d49e1aeSJan Lentfer 	       "(Calling-Station-Id,\n"
12786d49e1aeSJan Lentfer 	       "                           default: 02:00:00:00:00:01)\n"
12793ff40c12SJohn Marino 	       "  -o<server cert file> = Write received server certificate\n"
12803ff40c12SJohn Marino 	       "                         chain to the specified file\n"
12816d49e1aeSJan Lentfer 	       "  -N<attr spec> = send arbitrary attribute specified by:\n"
12826d49e1aeSJan Lentfer 	       "                  attr_id:syntax:value or attr_id\n"
12836d49e1aeSJan Lentfer 	       "                  attr_id - number id of the attribute\n"
12846d49e1aeSJan Lentfer 	       "                  syntax - one of: s, d, x\n"
12856d49e1aeSJan Lentfer 	       "                     s = string\n"
12866d49e1aeSJan Lentfer 	       "                     d = integer\n"
12876d49e1aeSJan Lentfer 	       "                     x = octet string\n"
12886d49e1aeSJan Lentfer 	       "                  value - attribute value.\n"
12896d49e1aeSJan Lentfer 	       "       When only attr_id is specified, NULL will be used as "
12906d49e1aeSJan Lentfer 	       "value.\n"
12916d49e1aeSJan Lentfer 	       "       Multiple attributes can be specified by using the "
12926d49e1aeSJan Lentfer 	       "option several times.\n");
12936d49e1aeSJan Lentfer }
12946d49e1aeSJan Lentfer 
12956d49e1aeSJan Lentfer 
main(int argc,char * argv[])12966d49e1aeSJan Lentfer int main(int argc, char *argv[])
12976d49e1aeSJan Lentfer {
12983ff40c12SJohn Marino 	struct wpa_global global;
12996d49e1aeSJan Lentfer 	struct wpa_supplicant wpa_s;
13006d49e1aeSJan Lentfer 	int c, ret = 1, wait_for_monitor = 0, save_config = 0;
13016d49e1aeSJan Lentfer 	char *as_addr = "127.0.0.1";
13026d49e1aeSJan Lentfer 	int as_port = 1812;
13036d49e1aeSJan Lentfer 	char *as_secret = "radius";
13046d49e1aeSJan Lentfer 	char *cli_addr = NULL;
13056d49e1aeSJan Lentfer 	char *conf = NULL;
13066d49e1aeSJan Lentfer 	int timeout = 30;
13076d49e1aeSJan Lentfer 	char *pos;
13086d49e1aeSJan Lentfer 	struct extra_radius_attr *p = NULL, *p1;
1309*a1157835SDaniel Fojt 	const char *ifname = "test";
1310*a1157835SDaniel Fojt 	const char *ctrl_iface = NULL;
13116d49e1aeSJan Lentfer 
13126d49e1aeSJan Lentfer 	if (os_program_init())
13136d49e1aeSJan Lentfer 		return -1;
13146d49e1aeSJan Lentfer 
13156d49e1aeSJan Lentfer 	hostapd_logger_register_cb(hostapd_logger_cb);
13166d49e1aeSJan Lentfer 
13176d49e1aeSJan Lentfer 	os_memset(&eapol_test, 0, sizeof(eapol_test));
13186d49e1aeSJan Lentfer 	eapol_test.connect_info = "CONNECT 11Mbps 802.11b";
13196d49e1aeSJan Lentfer 	os_memcpy(eapol_test.own_addr, "\x02\x00\x00\x00\x00\x01", ETH_ALEN);
1320*a1157835SDaniel Fojt 	eapol_test.pcsc_pin = "1234";
13216d49e1aeSJan Lentfer 
13226d49e1aeSJan Lentfer 	wpa_debug_level = 0;
13236d49e1aeSJan Lentfer 	wpa_debug_show_keys = 1;
13246d49e1aeSJan Lentfer 
13256d49e1aeSJan Lentfer 	for (;;) {
1326*a1157835SDaniel Fojt 		c = getopt(argc, argv, "a:A:c:C:ei:M:nN:o:p:P:r:R:s:St:T:vW");
13276d49e1aeSJan Lentfer 		if (c < 0)
13286d49e1aeSJan Lentfer 			break;
13296d49e1aeSJan Lentfer 		switch (c) {
13306d49e1aeSJan Lentfer 		case 'a':
13316d49e1aeSJan Lentfer 			as_addr = optarg;
13326d49e1aeSJan Lentfer 			break;
13336d49e1aeSJan Lentfer 		case 'A':
13346d49e1aeSJan Lentfer 			cli_addr = optarg;
13356d49e1aeSJan Lentfer 			break;
13366d49e1aeSJan Lentfer 		case 'c':
13376d49e1aeSJan Lentfer 			conf = optarg;
13386d49e1aeSJan Lentfer 			break;
13396d49e1aeSJan Lentfer 		case 'C':
13406d49e1aeSJan Lentfer 			eapol_test.connect_info = optarg;
13416d49e1aeSJan Lentfer 			break;
1342*a1157835SDaniel Fojt 		case 'e':
1343*a1157835SDaniel Fojt 			eapol_test.req_eap_key_name = 1;
1344*a1157835SDaniel Fojt 			break;
1345*a1157835SDaniel Fojt 		case 'i':
1346*a1157835SDaniel Fojt 			ifname = optarg;
1347*a1157835SDaniel Fojt 			break;
13486d49e1aeSJan Lentfer 		case 'M':
13496d49e1aeSJan Lentfer 			if (hwaddr_aton(optarg, eapol_test.own_addr)) {
13506d49e1aeSJan Lentfer 				usage();
13516d49e1aeSJan Lentfer 				return -1;
13526d49e1aeSJan Lentfer 			}
13536d49e1aeSJan Lentfer 			break;
13546d49e1aeSJan Lentfer 		case 'n':
13556d49e1aeSJan Lentfer 			eapol_test.no_mppe_keys++;
13566d49e1aeSJan Lentfer 			break;
13573ff40c12SJohn Marino 		case 'o':
13583ff40c12SJohn Marino 			if (eapol_test.server_cert_file)
13593ff40c12SJohn Marino 				fclose(eapol_test.server_cert_file);
13603ff40c12SJohn Marino 			eapol_test.server_cert_file = fopen(optarg, "w");
13613ff40c12SJohn Marino 			if (eapol_test.server_cert_file == NULL) {
13623ff40c12SJohn Marino 				printf("Could not open '%s' for writing\n",
13633ff40c12SJohn Marino 				       optarg);
13643ff40c12SJohn Marino 				return -1;
13653ff40c12SJohn Marino 			}
13663ff40c12SJohn Marino 			break;
13676d49e1aeSJan Lentfer 		case 'p':
13686d49e1aeSJan Lentfer 			as_port = atoi(optarg);
13696d49e1aeSJan Lentfer 			break;
1370*a1157835SDaniel Fojt 		case 'P':
1371*a1157835SDaniel Fojt 			eapol_test.pcsc_pin = optarg;
1372*a1157835SDaniel Fojt 			break;
13736d49e1aeSJan Lentfer 		case 'r':
13746d49e1aeSJan Lentfer 			eapol_test.eapol_test_num_reauths = atoi(optarg);
13756d49e1aeSJan Lentfer 			break;
1376*a1157835SDaniel Fojt 		case 'R':
1377*a1157835SDaniel Fojt 			eapol_test.pcsc_reader = optarg;
1378*a1157835SDaniel Fojt 			break;
13796d49e1aeSJan Lentfer 		case 's':
13806d49e1aeSJan Lentfer 			as_secret = optarg;
13816d49e1aeSJan Lentfer 			break;
13826d49e1aeSJan Lentfer 		case 'S':
13836d49e1aeSJan Lentfer 			save_config++;
13846d49e1aeSJan Lentfer 			break;
13856d49e1aeSJan Lentfer 		case 't':
13866d49e1aeSJan Lentfer 			timeout = atoi(optarg);
13876d49e1aeSJan Lentfer 			break;
1388*a1157835SDaniel Fojt 		case 'T':
1389*a1157835SDaniel Fojt 			ctrl_iface = optarg;
1390*a1157835SDaniel Fojt 			eapol_test.ctrl_iface = 1;
1391*a1157835SDaniel Fojt 			break;
1392*a1157835SDaniel Fojt 		case 'v':
1393*a1157835SDaniel Fojt 			printf("eapol_test v" VERSION_STR "\n");
1394*a1157835SDaniel Fojt 			return 0;
13956d49e1aeSJan Lentfer 		case 'W':
13966d49e1aeSJan Lentfer 			wait_for_monitor++;
13976d49e1aeSJan Lentfer 			break;
13986d49e1aeSJan Lentfer 		case 'N':
13993ff40c12SJohn Marino 			p1 = os_zalloc(sizeof(*p1));
14006d49e1aeSJan Lentfer 			if (p1 == NULL)
14016d49e1aeSJan Lentfer 				break;
14026d49e1aeSJan Lentfer 			if (!p)
14036d49e1aeSJan Lentfer 				eapol_test.extra_attrs = p1;
14046d49e1aeSJan Lentfer 			else
14056d49e1aeSJan Lentfer 				p->next = p1;
14066d49e1aeSJan Lentfer 			p = p1;
14076d49e1aeSJan Lentfer 
14086d49e1aeSJan Lentfer 			p->type = atoi(optarg);
14096d49e1aeSJan Lentfer 			pos = os_strchr(optarg, ':');
14106d49e1aeSJan Lentfer 			if (pos == NULL) {
14116d49e1aeSJan Lentfer 				p->syntax = 'n';
14126d49e1aeSJan Lentfer 				p->data = NULL;
14136d49e1aeSJan Lentfer 				break;
14146d49e1aeSJan Lentfer 			}
14156d49e1aeSJan Lentfer 
14166d49e1aeSJan Lentfer 			pos++;
14176d49e1aeSJan Lentfer 			if (pos[0] == '\0' || pos[1] != ':') {
14186d49e1aeSJan Lentfer 				printf("Incorrect format of attribute "
14196d49e1aeSJan Lentfer 				       "specification\n");
14206d49e1aeSJan Lentfer 				break;
14216d49e1aeSJan Lentfer 			}
14226d49e1aeSJan Lentfer 
14236d49e1aeSJan Lentfer 			p->syntax = pos[0];
14246d49e1aeSJan Lentfer 			p->data = pos + 2;
14256d49e1aeSJan Lentfer 			break;
14266d49e1aeSJan Lentfer 		default:
14276d49e1aeSJan Lentfer 			usage();
14286d49e1aeSJan Lentfer 			return -1;
14296d49e1aeSJan Lentfer 		}
14306d49e1aeSJan Lentfer 	}
14316d49e1aeSJan Lentfer 
14326d49e1aeSJan Lentfer 	if (argc > optind && os_strcmp(argv[optind], "scard") == 0) {
1433*a1157835SDaniel Fojt 		return scard_test(&eapol_test);
14346d49e1aeSJan Lentfer 	}
14356d49e1aeSJan Lentfer 
14366d49e1aeSJan Lentfer 	if (argc > optind && os_strcmp(argv[optind], "sim") == 0) {
1437*a1157835SDaniel Fojt 		return scard_get_triplets(&eapol_test, argc - optind - 1,
14386d49e1aeSJan Lentfer 					  &argv[optind + 1]);
14396d49e1aeSJan Lentfer 	}
14406d49e1aeSJan Lentfer 
1441*a1157835SDaniel Fojt 	if (conf == NULL && !ctrl_iface) {
14426d49e1aeSJan Lentfer 		usage();
14436d49e1aeSJan Lentfer 		printf("Configuration file is required.\n");
14446d49e1aeSJan Lentfer 		return -1;
14456d49e1aeSJan Lentfer 	}
14466d49e1aeSJan Lentfer 
14473ff40c12SJohn Marino 	if (eap_register_methods()) {
14486d49e1aeSJan Lentfer 		wpa_printf(MSG_ERROR, "Failed to register EAP methods");
14496d49e1aeSJan Lentfer 		return -1;
14506d49e1aeSJan Lentfer 	}
14516d49e1aeSJan Lentfer 
14523ff40c12SJohn Marino 	if (eloop_init()) {
14536d49e1aeSJan Lentfer 		wpa_printf(MSG_ERROR, "Failed to initialize event loop");
14546d49e1aeSJan Lentfer 		return -1;
14556d49e1aeSJan Lentfer 	}
14566d49e1aeSJan Lentfer 
14573ff40c12SJohn Marino 	os_memset(&global, 0, sizeof(global));
14586d49e1aeSJan Lentfer 	os_memset(&wpa_s, 0, sizeof(wpa_s));
14593ff40c12SJohn Marino 	wpa_s.global = &global;
14606d49e1aeSJan Lentfer 	eapol_test.wpa_s = &wpa_s;
14613ff40c12SJohn Marino 	dl_list_init(&wpa_s.bss);
14623ff40c12SJohn Marino 	dl_list_init(&wpa_s.bss_id);
1463*a1157835SDaniel Fojt 	if (conf)
14643ff40c12SJohn Marino 		wpa_s.conf = wpa_config_read(conf, NULL);
1465*a1157835SDaniel Fojt 	else
1466*a1157835SDaniel Fojt 		wpa_s.conf = wpa_config_alloc_empty(ctrl_iface, NULL);
14676d49e1aeSJan Lentfer 	if (wpa_s.conf == NULL) {
14686d49e1aeSJan Lentfer 		printf("Failed to parse configuration file '%s'.\n", conf);
14696d49e1aeSJan Lentfer 		return -1;
14706d49e1aeSJan Lentfer 	}
1471*a1157835SDaniel Fojt 	if (!ctrl_iface && wpa_s.conf->ssid == NULL) {
14726d49e1aeSJan Lentfer 		printf("No networks defined.\n");
14736d49e1aeSJan Lentfer 		return -1;
14746d49e1aeSJan Lentfer 	}
14756d49e1aeSJan Lentfer 
1476*a1157835SDaniel Fojt 	if (eapol_test.pcsc_reader) {
1477*a1157835SDaniel Fojt 		os_free(wpa_s.conf->pcsc_reader);
1478*a1157835SDaniel Fojt 		wpa_s.conf->pcsc_reader = os_strdup(eapol_test.pcsc_reader);
1479*a1157835SDaniel Fojt 	}
1480*a1157835SDaniel Fojt 
14816d49e1aeSJan Lentfer 	wpa_init_conf(&eapol_test, &wpa_s, as_addr, as_port, as_secret,
1482*a1157835SDaniel Fojt 		      cli_addr, ifname);
14836d49e1aeSJan Lentfer 	wpa_s.ctrl_iface = wpa_supplicant_ctrl_iface_init(&wpa_s);
14846d49e1aeSJan Lentfer 	if (wpa_s.ctrl_iface == NULL) {
14856d49e1aeSJan Lentfer 		printf("Failed to initialize control interface '%s'.\n"
14866d49e1aeSJan Lentfer 		       "You may have another eapol_test process already "
14876d49e1aeSJan Lentfer 		       "running or the file was\n"
14886d49e1aeSJan Lentfer 		       "left by an unclean termination of eapol_test in "
14896d49e1aeSJan Lentfer 		       "which case you will need\n"
14906d49e1aeSJan Lentfer 		       "to manually remove this file before starting "
14916d49e1aeSJan Lentfer 		       "eapol_test again.\n",
14926d49e1aeSJan Lentfer 		       wpa_s.conf->ctrl_interface);
14936d49e1aeSJan Lentfer 		return -1;
14946d49e1aeSJan Lentfer 	}
1495*a1157835SDaniel Fojt 	if (wpa_s.conf->ssid &&
1496*a1157835SDaniel Fojt 	    wpa_supplicant_scard_init(&wpa_s, wpa_s.conf->ssid))
14976d49e1aeSJan Lentfer 		return -1;
14986d49e1aeSJan Lentfer 
14996d49e1aeSJan Lentfer 	if (test_eapol(&eapol_test, &wpa_s, wpa_s.conf->ssid))
15006d49e1aeSJan Lentfer 		return -1;
15016d49e1aeSJan Lentfer 
15023ff40c12SJohn Marino 	if (wpas_init_ext_pw(&wpa_s) < 0)
15033ff40c12SJohn Marino 		return -1;
15043ff40c12SJohn Marino 
15056d49e1aeSJan Lentfer 	if (wait_for_monitor)
15066d49e1aeSJan Lentfer 		wpa_supplicant_ctrl_iface_wait(wpa_s.ctrl_iface);
15076d49e1aeSJan Lentfer 
1508*a1157835SDaniel Fojt 	if (!ctrl_iface) {
1509*a1157835SDaniel Fojt 		eloop_register_timeout(timeout, 0, eapol_test_timeout,
1510*a1157835SDaniel Fojt 				       &eapol_test, NULL);
1511*a1157835SDaniel Fojt 		eloop_register_timeout(0, 0, send_eap_request_identity, &wpa_s,
15126d49e1aeSJan Lentfer 				       NULL);
1513*a1157835SDaniel Fojt 	}
15143ff40c12SJohn Marino 	eloop_register_signal_terminate(eapol_test_terminate, &wpa_s);
15153ff40c12SJohn Marino 	eloop_register_signal_reconfig(eapol_test_terminate, &wpa_s);
15166d49e1aeSJan Lentfer 	eloop_run();
15176d49e1aeSJan Lentfer 
15186d49e1aeSJan Lentfer 	eloop_cancel_timeout(eapol_test_timeout, &eapol_test, NULL);
15196d49e1aeSJan Lentfer 	eloop_cancel_timeout(eapol_sm_reauth, &eapol_test, NULL);
15206d49e1aeSJan Lentfer 
15216d49e1aeSJan Lentfer 	if (eapol_test_compare_pmk(&eapol_test) == 0 ||
15226d49e1aeSJan Lentfer 	    eapol_test.no_mppe_keys)
15236d49e1aeSJan Lentfer 		ret = 0;
15246d49e1aeSJan Lentfer 	if (eapol_test.auth_timed_out)
15256d49e1aeSJan Lentfer 		ret = -2;
15266d49e1aeSJan Lentfer 	if (eapol_test.radius_access_reject_received)
15276d49e1aeSJan Lentfer 		ret = -3;
15286d49e1aeSJan Lentfer 
15296d49e1aeSJan Lentfer 	if (save_config)
15306d49e1aeSJan Lentfer 		wpa_config_write(conf, wpa_s.conf);
15316d49e1aeSJan Lentfer 
15326d49e1aeSJan Lentfer 	test_eapol_clean(&eapol_test, &wpa_s);
15336d49e1aeSJan Lentfer 
15346d49e1aeSJan Lentfer 	eap_peer_unregister_methods();
15353ff40c12SJohn Marino #ifdef CONFIG_AP
15363ff40c12SJohn Marino 	eap_server_unregister_methods();
15373ff40c12SJohn Marino #endif /* CONFIG_AP */
15386d49e1aeSJan Lentfer 
15396d49e1aeSJan Lentfer 	eloop_destroy();
15406d49e1aeSJan Lentfer 
15413ff40c12SJohn Marino 	if (eapol_test.server_cert_file)
15423ff40c12SJohn Marino 		fclose(eapol_test.server_cert_file);
15433ff40c12SJohn Marino 
15446d49e1aeSJan Lentfer 	printf("MPPE keys OK: %d  mismatch: %d\n",
15456d49e1aeSJan Lentfer 	       eapol_test.num_mppe_ok, eapol_test.num_mppe_mismatch);
15466d49e1aeSJan Lentfer 	if (eapol_test.num_mppe_mismatch)
15476d49e1aeSJan Lentfer 		ret = -4;
15486d49e1aeSJan Lentfer 	if (ret)
15496d49e1aeSJan Lentfer 		printf("FAILURE\n");
15506d49e1aeSJan Lentfer 	else
15516d49e1aeSJan Lentfer 		printf("SUCCESS\n");
15526d49e1aeSJan Lentfer 
15536d49e1aeSJan Lentfer 	os_program_deinit();
15546d49e1aeSJan Lentfer 
15556d49e1aeSJan Lentfer 	return ret;
15566d49e1aeSJan Lentfer }
1557