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