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