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