]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/wpa_supplicant/eapol_test.c
This commit was generated by cvs2svn to compensate for changes in r161818,
[FreeBSD/FreeBSD.git] / contrib / wpa_supplicant / eapol_test.c
1 /*
2  * WPA Supplicant - test code
3  * Copyright (c) 2003-2006, Jouni Malinen <jkmaline@cc.hut.fi>
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License version 2 as
7  * published by the Free Software Foundation.
8  *
9  * Alternatively, this software may be distributed under the terms of BSD
10  * license.
11  *
12  * See README and COPYING for more details.
13  *
14  * IEEE 802.1X Supplicant test code (to be used in place of wpa_supplicant.c.
15  * Not used in production version.
16  */
17
18 #include <stdio.h>
19 #include <stdlib.h>
20 #include <stdarg.h>
21 #include <unistd.h>
22 #include <ctype.h>
23 #include <string.h>
24 #include <signal.h>
25 #ifndef CONFIG_NATIVE_WINDOWS
26 #include <netinet/in.h>
27 #include <arpa/inet.h>
28 #endif /* CONFIG_NATIVE_WINDOWS */
29 #include <assert.h>
30
31 #include "common.h"
32 #include "config.h"
33 #include "eapol_sm.h"
34 #include "eloop.h"
35 #include "wpa.h"
36 #include "eap_i.h"
37 #include "wpa_supplicant.h"
38 #include "wpa_supplicant_i.h"
39 #include "radius.h"
40 #include "radius_client.h"
41 #include "l2_packet.h"
42 #include "ctrl_iface.h"
43 #include "pcsc_funcs.h"
44
45
46 extern int wpa_debug_level;
47 extern int wpa_debug_show_keys;
48
49 struct wpa_driver_ops *wpa_supplicant_drivers[] = { };
50
51
52 struct eapol_test_data {
53         struct wpa_supplicant *wpa_s;
54
55         int eapol_test_num_reauths;
56         int no_mppe_keys;
57         int num_mppe_ok, num_mppe_mismatch;
58
59         u8 radius_identifier;
60         struct radius_msg *last_recv_radius;
61         struct in_addr own_ip_addr;
62         struct radius_client_data *radius;
63         struct hostapd_radius_servers *radius_conf;
64
65         u8 *last_eap_radius; /* last received EAP Response from Authentication
66                               * Server */
67         size_t last_eap_radius_len;
68
69         u8 authenticator_pmk[PMK_LEN];
70         size_t authenticator_pmk_len;
71         int radius_access_accept_received;
72         int radius_access_reject_received;
73         int auth_timed_out;
74
75         u8 *eap_identity;
76         size_t eap_identity_len;
77 };
78
79 static struct eapol_test_data eapol_test;
80
81
82 static void send_eap_request_identity(void *eloop_ctx, void *timeout_ctx);
83
84
85 void hostapd_logger(void *ctx, u8 *addr, unsigned int module, int level,
86                     char *fmt, ...)
87 {
88         char *format;
89         int maxlen;
90         va_list ap;
91
92         maxlen = strlen(fmt) + 100;
93         format = malloc(maxlen);
94         if (!format)
95                 return;
96
97         va_start(ap, fmt);
98
99
100         if (addr)
101                 snprintf(format, maxlen, "STA " MACSTR ": %s",
102                          MAC2STR(addr), fmt);
103         else
104                 snprintf(format, maxlen, "%s", fmt);
105
106         vprintf(format, ap);
107         printf("\n");
108
109         free(format);
110
111         va_end(ap);
112 }
113
114
115 const char * hostapd_ip_txt(const struct hostapd_ip_addr *addr, char *buf,
116                             size_t buflen)
117 {
118         if (buflen == 0 || addr == NULL)
119                 return NULL;
120
121         if (addr->af == AF_INET) {
122                 snprintf(buf, buflen, "%s", inet_ntoa(addr->u.v4));
123         } else {
124                 buf[0] = '\0';
125         }
126 #ifdef CONFIG_IPV6
127         if (addr->af == AF_INET6) {
128                 if (inet_ntop(AF_INET6, &addr->u.v6, buf, buflen) == NULL)
129                         buf[0] = '\0';
130         }
131 #endif /* CONFIG_IPV6 */
132
133         return buf;
134 }
135
136
137 static void ieee802_1x_encapsulate_radius(struct eapol_test_data *e,
138                                           const u8 *eap, size_t len)
139 {
140         struct radius_msg *msg;
141         char buf[128];
142         const struct eap_hdr *hdr;
143         const u8 *pos;
144
145         wpa_printf(MSG_DEBUG, "Encapsulating EAP message into a RADIUS "
146                    "packet");
147
148         e->radius_identifier = radius_client_get_id(e->radius);
149         msg = radius_msg_new(RADIUS_CODE_ACCESS_REQUEST,
150                              e->radius_identifier);
151         if (msg == NULL) {
152                 printf("Could not create net RADIUS packet\n");
153                 return;
154         }
155
156         radius_msg_make_authenticator(msg, (u8 *) e, sizeof(*e));
157
158         hdr = (const struct eap_hdr *) eap;
159         pos = (const u8 *) (hdr + 1);
160         if (len > sizeof(*hdr) && hdr->code == EAP_CODE_RESPONSE &&
161             pos[0] == EAP_TYPE_IDENTITY) {
162                 pos++;
163                 free(e->eap_identity);
164                 e->eap_identity_len = len - sizeof(*hdr) - 1;
165                 e->eap_identity = malloc(e->eap_identity_len);
166                 if (e->eap_identity) {
167                         memcpy(e->eap_identity, pos, e->eap_identity_len);
168                         wpa_hexdump(MSG_DEBUG, "Learned identity from "
169                                     "EAP-Response-Identity",
170                                     e->eap_identity, e->eap_identity_len);
171                 }
172         }
173
174         if (e->eap_identity &&
175             !radius_msg_add_attr(msg, RADIUS_ATTR_USER_NAME,
176                                  e->eap_identity, e->eap_identity_len)) {
177                 printf("Could not add User-Name\n");
178                 goto fail;
179         }
180
181         if (!radius_msg_add_attr(msg, RADIUS_ATTR_NAS_IP_ADDRESS,
182                                  (u8 *) &e->own_ip_addr, 4)) {
183                 printf("Could not add NAS-IP-Address\n");
184                 goto fail;
185         }
186
187         snprintf(buf, sizeof(buf), RADIUS_802_1X_ADDR_FORMAT,
188                  MAC2STR(e->wpa_s->own_addr));
189         if (!radius_msg_add_attr(msg, RADIUS_ATTR_CALLING_STATION_ID,
190                                  (u8 *) buf, strlen(buf))) {
191                 printf("Could not add Calling-Station-Id\n");
192                 goto fail;
193         }
194
195         /* TODO: should probably check MTU from driver config; 2304 is max for
196          * IEEE 802.11, but use 1400 to avoid problems with too large packets
197          */
198         if (!radius_msg_add_attr_int32(msg, RADIUS_ATTR_FRAMED_MTU, 1400)) {
199                 printf("Could not add Framed-MTU\n");
200                 goto fail;
201         }
202
203         if (!radius_msg_add_attr_int32(msg, RADIUS_ATTR_NAS_PORT_TYPE,
204                                        RADIUS_NAS_PORT_TYPE_IEEE_802_11)) {
205                 printf("Could not add NAS-Port-Type\n");
206                 goto fail;
207         }
208
209         snprintf(buf, sizeof(buf), "CONNECT 11Mbps 802.11b");
210         if (!radius_msg_add_attr(msg, RADIUS_ATTR_CONNECT_INFO,
211                                  (u8 *) buf, strlen(buf))) {
212                 printf("Could not add Connect-Info\n");
213                 goto fail;
214         }
215
216         if (eap && !radius_msg_add_eap(msg, eap, len)) {
217                 printf("Could not add EAP-Message\n");
218                 goto fail;
219         }
220
221         /* State attribute must be copied if and only if this packet is
222          * Access-Request reply to the previous Access-Challenge */
223         if (e->last_recv_radius && e->last_recv_radius->hdr->code ==
224             RADIUS_CODE_ACCESS_CHALLENGE) {
225                 int res = radius_msg_copy_attr(msg, e->last_recv_radius,
226                                                RADIUS_ATTR_STATE);
227                 if (res < 0) {
228                         printf("Could not copy State attribute from previous "
229                                "Access-Challenge\n");
230                         goto fail;
231                 }
232                 if (res > 0) {
233                         wpa_printf(MSG_DEBUG, "  Copied RADIUS State "
234                                    "Attribute");
235                 }
236         }
237
238         radius_client_send(e->radius, msg, RADIUS_AUTH, e->wpa_s->own_addr);
239         return;
240
241  fail:
242         radius_msg_free(msg);
243         free(msg);
244 }
245
246
247 static int eapol_test_eapol_send(void *ctx, int type, const u8 *buf,
248                                  size_t len)
249 {
250         /* struct wpa_supplicant *wpa_s = ctx; */
251         printf("WPA: eapol_test_eapol_send(type=%d len=%d)\n", type, len);
252         if (type == IEEE802_1X_TYPE_EAP_PACKET) {
253                 wpa_hexdump(MSG_DEBUG, "TX EAP -> RADIUS", buf, len);
254                 ieee802_1x_encapsulate_radius(&eapol_test, buf, len);
255         }
256         return 0;
257 }
258
259
260 static void eapol_test_set_config_blob(void *ctx,
261                                        struct wpa_config_blob *blob)
262 {
263         struct wpa_supplicant *wpa_s = ctx;
264         wpa_config_set_blob(wpa_s->conf, blob);
265 }
266
267
268 static const struct wpa_config_blob *
269 eapol_test_get_config_blob(void *ctx, const char *name)
270 {
271         struct wpa_supplicant *wpa_s = ctx;
272         return wpa_config_get_blob(wpa_s->conf, name);
273 }
274
275
276 static void eapol_test_eapol_done_cb(void *ctx)
277 {
278         printf("WPA: EAPOL processing complete\n");
279 }
280
281
282 static void eapol_sm_reauth(void *eloop_ctx, void *timeout_ctx)
283 {
284         struct eapol_test_data *e = eloop_ctx;
285         printf("\n\n\n\n\neapol_test: Triggering EAP reauthentication\n\n");
286         e->radius_access_accept_received = 0;
287         send_eap_request_identity(e->wpa_s, NULL);
288 }
289
290
291 static int eapol_test_compare_pmk(struct eapol_test_data *e)
292 {
293         u8 pmk[PMK_LEN];
294         int ret = 1;
295
296         if (eapol_sm_get_key(e->wpa_s->eapol, pmk, PMK_LEN) == 0) {
297                 wpa_hexdump(MSG_DEBUG, "PMK from EAPOL", pmk, PMK_LEN);
298                 if (memcmp(pmk, e->authenticator_pmk, PMK_LEN) != 0)
299                         printf("WARNING: PMK mismatch\n");
300                 else if (e->radius_access_accept_received)
301                         ret = 0;
302         } else if (e->authenticator_pmk_len == 16 &&
303                    eapol_sm_get_key(e->wpa_s->eapol, pmk, 16) == 0) {
304                 wpa_hexdump(MSG_DEBUG, "LEAP PMK from EAPOL", pmk, 16);
305                 if (memcmp(pmk, e->authenticator_pmk, 16) != 0)
306                         printf("WARNING: PMK mismatch\n");
307                 else if (e->radius_access_accept_received)
308                         ret = 0;
309         } else if (e->radius_access_accept_received && e->no_mppe_keys) {
310                 /* No keying material expected */
311                 ret = 0;
312         }
313
314         if (ret)
315                 e->num_mppe_mismatch++;
316         else if (!e->no_mppe_keys)
317                 e->num_mppe_ok++;
318
319         return ret;
320 }
321
322
323 static void eapol_sm_cb(struct eapol_sm *eapol, int success, void *ctx)
324 {
325         struct eapol_test_data *e = ctx;
326         printf("eapol_sm_cb: success=%d\n", success);
327         e->eapol_test_num_reauths--;
328         if (e->eapol_test_num_reauths < 0)
329                 eloop_terminate();
330         else {
331                 eapol_test_compare_pmk(e);
332                 eloop_register_timeout(0, 100000, eapol_sm_reauth, e, NULL);
333         }
334 }
335
336
337 static int test_eapol(struct eapol_test_data *e, struct wpa_supplicant *wpa_s,
338                       struct wpa_ssid *ssid)
339 {
340         struct eapol_config eapol_conf;
341         struct eapol_ctx *ctx;
342
343         ctx = malloc(sizeof(*ctx));
344         if (ctx == NULL) {
345                 printf("Failed to allocate EAPOL context.\n");
346                 return -1;
347         }
348         memset(ctx, 0, sizeof(*ctx));
349         ctx->ctx = wpa_s;
350         ctx->msg_ctx = wpa_s;
351         ctx->scard_ctx = wpa_s->scard;
352         ctx->cb = eapol_sm_cb;
353         ctx->cb_ctx = e;
354         ctx->eapol_send_ctx = wpa_s;
355         ctx->preauth = 0;
356         ctx->eapol_done_cb = eapol_test_eapol_done_cb;
357         ctx->eapol_send = eapol_test_eapol_send;
358         ctx->set_config_blob = eapol_test_set_config_blob;
359         ctx->get_config_blob = eapol_test_get_config_blob;
360         ctx->opensc_engine_path = wpa_s->conf->opensc_engine_path;
361         ctx->pkcs11_engine_path = wpa_s->conf->pkcs11_engine_path;
362         ctx->pkcs11_module_path = wpa_s->conf->pkcs11_module_path;
363
364         wpa_s->eapol = eapol_sm_init(ctx);
365         if (wpa_s->eapol == NULL) {
366                 free(ctx);
367                 printf("Failed to initialize EAPOL state machines.\n");
368                 return -1;
369         }
370
371         wpa_s->current_ssid = ssid;
372         memset(&eapol_conf, 0, sizeof(eapol_conf));
373         eapol_conf.accept_802_1x_keys = 1;
374         eapol_conf.required_keys = 0;
375         eapol_conf.fast_reauth = wpa_s->conf->fast_reauth;
376         eapol_conf.workaround = ssid->eap_workaround;
377         eapol_sm_notify_config(wpa_s->eapol, ssid, &eapol_conf);
378         eapol_sm_register_scard_ctx(wpa_s->eapol, wpa_s->scard);
379
380
381         eapol_sm_notify_portValid(wpa_s->eapol, FALSE);
382         /* 802.1X::portControl = Auto */
383         eapol_sm_notify_portEnabled(wpa_s->eapol, TRUE);
384
385         return 0;
386 }
387
388
389 static void test_eapol_clean(struct eapol_test_data *e,
390                              struct wpa_supplicant *wpa_s)
391 {
392         radius_client_deinit(e->radius);
393         free(e->last_eap_radius);
394         if (e->last_recv_radius) {
395                 radius_msg_free(e->last_recv_radius);
396                 free(e->last_recv_radius);
397         }
398         free(e->eap_identity);
399         e->eap_identity = NULL;
400         eapol_sm_deinit(wpa_s->eapol);
401         wpa_s->eapol = NULL;
402         if (e->radius_conf && e->radius_conf->auth_server) {
403                 free(e->radius_conf->auth_server->shared_secret);
404                 free(e->radius_conf->auth_server);
405         }
406         free(e->radius_conf);
407         e->radius_conf = NULL;
408         scard_deinit(wpa_s->scard);
409         wpa_supplicant_ctrl_iface_deinit(wpa_s);
410         wpa_config_free(wpa_s->conf);
411 }
412
413
414 static void send_eap_request_identity(void *eloop_ctx, void *timeout_ctx)
415 {
416         struct wpa_supplicant *wpa_s = eloop_ctx;
417         u8 buf[100], *pos;
418         struct ieee802_1x_hdr *hdr;
419         struct eap_hdr *eap;
420
421         hdr = (struct ieee802_1x_hdr *) buf;
422         hdr->version = EAPOL_VERSION;
423         hdr->type = IEEE802_1X_TYPE_EAP_PACKET;
424         hdr->length = htons(5);
425
426         eap = (struct eap_hdr *) (hdr + 1);
427         eap->code = EAP_CODE_REQUEST;
428         eap->identifier = 0;
429         eap->length = htons(5);
430         pos = (u8 *) (eap + 1);
431         *pos = EAP_TYPE_IDENTITY;
432
433         printf("Sending fake EAP-Request-Identity\n");
434         eapol_sm_rx_eapol(wpa_s->eapol, wpa_s->bssid, buf,
435                           sizeof(*hdr) + 5);
436 }
437
438
439 static void eapol_test_timeout(void *eloop_ctx, void *timeout_ctx)
440 {
441         struct eapol_test_data *e = eloop_ctx;
442         printf("EAPOL test timed out\n");
443         e->auth_timed_out = 1;
444         eloop_terminate();
445 }
446
447
448 static char *eap_type_text(u8 type)
449 {
450         switch (type) {
451         case EAP_TYPE_IDENTITY: return "Identity";
452         case EAP_TYPE_NOTIFICATION: return "Notification";
453         case EAP_TYPE_NAK: return "Nak";
454         case EAP_TYPE_TLS: return "TLS";
455         case EAP_TYPE_TTLS: return "TTLS";
456         case EAP_TYPE_PEAP: return "PEAP";
457         case EAP_TYPE_SIM: return "SIM";
458         case EAP_TYPE_GTC: return "GTC";
459         case EAP_TYPE_MD5: return "MD5";
460         case EAP_TYPE_OTP: return "OTP";
461         default: return "Unknown";
462         }
463 }
464
465
466 static void ieee802_1x_decapsulate_radius(struct eapol_test_data *e)
467 {
468         u8 *eap;
469         size_t len;
470         struct eap_hdr *hdr;
471         int eap_type = -1;
472         char buf[64];
473         struct radius_msg *msg;
474
475         if (e->last_recv_radius == NULL)
476                 return;
477
478         msg = e->last_recv_radius;
479
480         eap = radius_msg_get_eap(msg, &len);
481         if (eap == NULL) {
482                 /* draft-aboba-radius-rfc2869bis-20.txt, Chap. 2.6.3:
483                  * RADIUS server SHOULD NOT send Access-Reject/no EAP-Message
484                  * attribute */
485                 wpa_printf(MSG_DEBUG, "could not extract "
486                                "EAP-Message from RADIUS message");
487                 free(e->last_eap_radius);
488                 e->last_eap_radius = NULL;
489                 e->last_eap_radius_len = 0;
490                 return;
491         }
492
493         if (len < sizeof(*hdr)) {
494                 wpa_printf(MSG_DEBUG, "too short EAP packet "
495                                "received from authentication server");
496                 free(eap);
497                 return;
498         }
499
500         if (len > sizeof(*hdr))
501                 eap_type = eap[sizeof(*hdr)];
502
503         hdr = (struct eap_hdr *) eap;
504         switch (hdr->code) {
505         case EAP_CODE_REQUEST:
506                 snprintf(buf, sizeof(buf), "EAP-Request-%s (%d)",
507                          eap_type >= 0 ? eap_type_text(eap_type) : "??",
508                          eap_type);
509                 break;
510         case EAP_CODE_RESPONSE:
511                 snprintf(buf, sizeof(buf), "EAP Response-%s (%d)",
512                          eap_type >= 0 ? eap_type_text(eap_type) : "??",
513                          eap_type);
514                 break;
515         case EAP_CODE_SUCCESS:
516                 snprintf(buf, sizeof(buf), "EAP Success");
517                 /* LEAP uses EAP Success within an authentication, so must not
518                  * stop here with eloop_terminate(); */
519                 break;
520         case EAP_CODE_FAILURE:
521                 snprintf(buf, sizeof(buf), "EAP Failure");
522                 eloop_terminate();
523                 break;
524         default:
525                 snprintf(buf, sizeof(buf), "unknown EAP code");
526                 wpa_hexdump(MSG_DEBUG, "Decapsulated EAP packet", eap, len);
527                 break;
528         }
529         wpa_printf(MSG_DEBUG, "decapsulated EAP packet (code=%d "
530                        "id=%d len=%d) from RADIUS server: %s",
531                       hdr->code, hdr->identifier, ntohs(hdr->length), buf);
532
533         /* sta->eapol_sm->be_auth.idFromServer = hdr->identifier; */
534
535         free(e->last_eap_radius);
536         e->last_eap_radius = eap;
537         e->last_eap_radius_len = len;
538
539         {
540                 struct ieee802_1x_hdr *hdr;
541                 hdr = malloc(sizeof(*hdr) + len);
542                 assert(hdr != NULL);
543                 hdr->version = EAPOL_VERSION;
544                 hdr->type = IEEE802_1X_TYPE_EAP_PACKET;
545                 hdr->length = htons(len);
546                 memcpy((u8 *) (hdr + 1), eap, len);
547                 eapol_sm_rx_eapol(e->wpa_s->eapol, e->wpa_s->bssid,
548                                   (u8 *) hdr, sizeof(*hdr) + len);
549                 free(hdr);
550         }
551 }
552
553
554 static void ieee802_1x_get_keys(struct eapol_test_data *e,
555                                 struct radius_msg *msg, struct radius_msg *req,
556                                 u8 *shared_secret, size_t shared_secret_len)
557 {
558         struct radius_ms_mppe_keys *keys;
559
560         keys = radius_msg_get_ms_keys(msg, req, shared_secret,
561                                       shared_secret_len);
562         if (keys && keys->send == NULL && keys->recv == NULL) {
563                 free(keys);
564                 keys = radius_msg_get_cisco_keys(msg, req, shared_secret,
565                                                  shared_secret_len);
566         }
567
568         if (keys) {
569                 if (keys->send) {
570                         wpa_hexdump(MSG_DEBUG, "MS-MPPE-Send-Key (sign)",
571                                     keys->send, keys->send_len);
572                 }
573                 if (keys->recv) {
574                         wpa_hexdump(MSG_DEBUG, "MS-MPPE-Recv-Key (crypt)",
575                                     keys->recv, keys->recv_len);
576                         e->authenticator_pmk_len =
577                                 keys->recv_len > PMK_LEN ? PMK_LEN :
578                                 keys->recv_len;
579                         memcpy(e->authenticator_pmk, keys->recv,
580                                e->authenticator_pmk_len);
581                 }
582
583                 free(keys->send);
584                 free(keys->recv);
585                 free(keys);
586         }
587 }
588
589
590 /* Process the RADIUS frames from Authentication Server */
591 static RadiusRxResult
592 ieee802_1x_receive_auth(struct radius_msg *msg, struct radius_msg *req,
593                         u8 *shared_secret, size_t shared_secret_len,
594                         void *data)
595 {
596         struct eapol_test_data *e = data;
597
598         /* RFC 2869, Ch. 5.13: valid Message-Authenticator attribute MUST be
599          * present when packet contains an EAP-Message attribute */
600         if (msg->hdr->code == RADIUS_CODE_ACCESS_REJECT &&
601             radius_msg_get_attr(msg, RADIUS_ATTR_MESSAGE_AUTHENTICATOR, NULL,
602                                 0) < 0 &&
603             radius_msg_get_attr(msg, RADIUS_ATTR_EAP_MESSAGE, NULL, 0) < 0) {
604                 wpa_printf(MSG_DEBUG, "Allowing RADIUS "
605                               "Access-Reject without Message-Authenticator "
606                               "since it does not include EAP-Message\n");
607         } else if (radius_msg_verify(msg, shared_secret, shared_secret_len,
608                                      req, 1)) {
609                 printf("Incoming RADIUS packet did not have correct "
610                        "Message-Authenticator - dropped\n");
611                 return RADIUS_RX_UNKNOWN;
612         }
613
614         if (msg->hdr->code != RADIUS_CODE_ACCESS_ACCEPT &&
615             msg->hdr->code != RADIUS_CODE_ACCESS_REJECT &&
616             msg->hdr->code != RADIUS_CODE_ACCESS_CHALLENGE) {
617                 printf("Unknown RADIUS message code\n");
618                 return RADIUS_RX_UNKNOWN;
619         }
620
621         e->radius_identifier = -1;
622         wpa_printf(MSG_DEBUG, "RADIUS packet matching with station");
623
624         if (e->last_recv_radius) {
625                 radius_msg_free(e->last_recv_radius);
626                 free(e->last_recv_radius);
627         }
628
629         e->last_recv_radius = msg;
630
631         switch (msg->hdr->code) {
632         case RADIUS_CODE_ACCESS_ACCEPT:
633                 e->radius_access_accept_received = 1;
634                 ieee802_1x_get_keys(e, msg, req, shared_secret,
635                                     shared_secret_len);
636                 break;
637         case RADIUS_CODE_ACCESS_REJECT:
638                 e->radius_access_reject_received = 1;
639                 break;
640         }
641
642         ieee802_1x_decapsulate_radius(e);
643
644         if ((msg->hdr->code == RADIUS_CODE_ACCESS_ACCEPT &&
645              e->eapol_test_num_reauths < 0) ||
646             msg->hdr->code == RADIUS_CODE_ACCESS_REJECT) {
647                 eloop_terminate();
648         }
649
650         return RADIUS_RX_QUEUED;
651 }
652
653
654 static void wpa_init_conf(struct eapol_test_data *e,
655                           struct wpa_supplicant *wpa_s, const char *authsrv,
656                           int port, const char *secret)
657 {
658         struct hostapd_radius_server *as;
659         int res;
660
661         wpa_s->bssid[5] = 1;
662         wpa_s->own_addr[5] = 2;
663         e->own_ip_addr.s_addr = htonl((127 << 24) | 1);
664         strncpy(wpa_s->ifname, "test", sizeof(wpa_s->ifname));
665
666         e->radius_conf = malloc(sizeof(struct hostapd_radius_servers));
667         assert(e->radius_conf != NULL);
668         memset(e->radius_conf, 0, sizeof(struct hostapd_radius_servers));
669         e->radius_conf->num_auth_servers = 1;
670         as = malloc(sizeof(struct hostapd_radius_server));
671         assert(as != NULL);
672         memset(as, 0, sizeof(*as));
673 #ifdef CONFIG_NATIVE_WINDOWS
674         {
675                 int a[4];
676                 u8 *pos;
677                 sscanf(authsrv, "%d.%d.%d.%d", &a[0], &a[1], &a[2], &a[3]);
678                 pos = (u8 *) &as->addr.u.v4;
679                 *pos++ = a[0];
680                 *pos++ = a[1];
681                 *pos++ = a[2];
682                 *pos++ = a[3];
683         }
684 #else /* CONFIG_NATIVE_WINDOWS */
685         inet_aton(authsrv, &as->addr.u.v4);
686 #endif /* CONFIG_NATIVE_WINDOWS */
687         as->addr.af = AF_INET;
688         as->port = port;
689         as->shared_secret = (u8 *) strdup(secret);
690         as->shared_secret_len = strlen(secret);
691         e->radius_conf->auth_server = as;
692         e->radius_conf->auth_servers = as;
693         e->radius_conf->msg_dumps = 1;
694
695         e->radius = radius_client_init(wpa_s, e->radius_conf);
696         assert(e->radius != NULL);
697
698         res = radius_client_register(e->radius, RADIUS_AUTH,
699                                      ieee802_1x_receive_auth, e);
700         assert(res == 0);
701 }
702
703
704 static int scard_test(void)
705 {
706         struct scard_data *scard;
707         size_t len;
708         char imsi[20];
709         unsigned char rand[16];
710 #ifdef PCSC_FUNCS
711         unsigned char sres[4];
712         unsigned char kc[8];
713 #endif /* PCSC_FUNCS */
714 #define num_triplets 5
715         unsigned char rand_[num_triplets][16];
716         unsigned char sres_[num_triplets][4];
717         unsigned char kc_[num_triplets][8];
718         int i, j, res;
719
720 #define AKA_RAND_LEN 16
721 #define AKA_AUTN_LEN 16
722 #define AKA_AUTS_LEN 14
723 #define RES_MAX_LEN 16
724 #define IK_LEN 16
725 #define CK_LEN 16
726         unsigned char aka_rand[AKA_RAND_LEN];
727         unsigned char aka_autn[AKA_AUTN_LEN];
728         unsigned char aka_auts[AKA_AUTS_LEN];
729         unsigned char aka_res[RES_MAX_LEN];
730         size_t aka_res_len;
731         unsigned char aka_ik[IK_LEN];
732         unsigned char aka_ck[CK_LEN];
733
734         scard = scard_init(SCARD_TRY_BOTH);
735         if (scard == NULL)
736                 return -1;
737         if (scard_set_pin(scard, "1234")) {
738                 wpa_printf(MSG_WARNING, "PIN validation failed");
739                 scard_deinit(scard);
740                 return -1;
741         }
742
743         len = sizeof(imsi);
744         if (scard_get_imsi(scard, imsi, &len))
745                 goto failed;
746         wpa_hexdump_ascii(MSG_DEBUG, "SCARD: IMSI", (u8 *) imsi, len);
747         /* NOTE: Permanent Username: 1 | IMSI */
748
749         memset(rand, 0, sizeof(rand));
750         if (scard_gsm_auth(scard, rand, sres, kc))
751                 goto failed;
752
753         memset(rand, 0xff, sizeof(rand));
754         if (scard_gsm_auth(scard, rand, sres, kc))
755                 goto failed;
756
757         for (i = 0; i < num_triplets; i++) {
758                 memset(rand_[i], i, sizeof(rand_[i]));
759                 if (scard_gsm_auth(scard, rand_[i], sres_[i], kc_[i]))
760                         goto failed;
761         }
762
763         for (i = 0; i < num_triplets; i++) {
764                 printf("1");
765                 for (j = 0; j < len; j++)
766                         printf("%c", imsi[j]);
767                 printf(",");
768                 for (j = 0; j < 16; j++)
769                         printf("%02X", rand_[i][j]);
770                 printf(",");
771                 for (j = 0; j < 4; j++)
772                         printf("%02X", sres_[i][j]);
773                 printf(",");
774                 for (j = 0; j < 8; j++)
775                         printf("%02X", kc_[i][j]);
776                 printf("\n");
777         }
778
779         wpa_printf(MSG_DEBUG, "Trying to use UMTS authentication");
780
781         /* seq 39 (0x28) */
782         memset(aka_rand, 0xaa, 16);
783         memcpy(aka_autn, "\x86\x71\x31\xcb\xa2\xfc\x61\xdf"
784                "\xa3\xb3\x97\x9d\x07\x32\xa2\x12", 16);
785
786         res = scard_umts_auth(scard, aka_rand, aka_autn, aka_res, &aka_res_len,
787                               aka_ik, aka_ck, aka_auts);
788         if (res == 0) {
789                 wpa_printf(MSG_DEBUG, "UMTS auth completed successfully");
790                 wpa_hexdump(MSG_DEBUG, "RES", aka_res, aka_res_len);
791                 wpa_hexdump(MSG_DEBUG, "IK", aka_ik, IK_LEN);
792                 wpa_hexdump(MSG_DEBUG, "CK", aka_ck, CK_LEN);
793         } else if (res == -2) {
794                 wpa_printf(MSG_DEBUG, "UMTS auth resulted in synchronization "
795                            "failure");
796                 wpa_hexdump(MSG_DEBUG, "AUTS", aka_auts, AKA_AUTS_LEN);
797         } else {
798                 wpa_printf(MSG_DEBUG, "UMTS auth failed");
799         }
800
801 failed:
802         scard_deinit(scard);
803
804         return 0;
805 #undef num_triplets
806 }
807
808
809 static int scard_get_triplets(int argc, char *argv[])
810 {
811         struct scard_data *scard;
812         size_t len;
813         char imsi[20];
814         unsigned char rand[16];
815         unsigned char sres[4];
816         unsigned char kc[8];
817         int num_triplets;
818         int i, j;
819
820         if (argc < 2 || ((num_triplets = atoi(argv[1])) <= 0)) {
821                 printf("invalid parameters for sim command\n");
822                 return -1;
823         }
824
825         if (argc <= 2 || strcmp(argv[2], "debug") != 0) {
826                 /* disable debug output */
827                 wpa_debug_level = 99;
828         }
829
830         scard = scard_init(SCARD_GSM_SIM_ONLY);
831         if (scard == NULL) {
832                 printf("Failed to open smartcard connection\n");
833                 return -1;
834         }
835         if (scard_set_pin(scard, argv[0])) {
836                 wpa_printf(MSG_WARNING, "PIN validation failed");
837                 scard_deinit(scard);
838                 return -1;
839         }
840
841         len = sizeof(imsi);
842         if (scard_get_imsi(scard, imsi, &len)) {
843                 scard_deinit(scard);
844                 return -1;
845         }
846
847         for (i = 0; i < num_triplets; i++) {
848                 memset(rand, i, sizeof(rand));
849                 if (scard_gsm_auth(scard, rand, sres, kc))
850                         break;
851
852                 /* IMSI:Kc:SRES:RAND */
853                 for (j = 0; j < len; j++)
854                         printf("%c", imsi[j]);
855                 printf(":");
856                 for (j = 0; j < 8; j++)
857                         printf("%02X", kc[j]);
858                 printf(":");
859                 for (j = 0; j < 4; j++)
860                         printf("%02X", sres[j]);
861                 printf(":");
862                 for (j = 0; j < 16; j++)
863                         printf("%02X", rand[j]);
864                 printf("\n");
865         }
866
867         scard_deinit(scard);
868
869         return 0;
870 }
871
872
873 static void eapol_test_terminate(int sig, void *eloop_ctx,
874                                  void *signal_ctx)
875 {
876         struct wpa_supplicant *wpa_s = eloop_ctx;
877         wpa_msg(wpa_s, MSG_INFO, "Signal %d received - terminating", sig);
878         eloop_terminate();
879 }
880
881
882 static void usage(void)
883 {
884         printf("usage:\n"
885                "eapol_test [-nWS] -c<conf> [-a<AS IP>] [-p<AS port>] "
886                "[-s<AS secret>] [-r<count>]\n"
887                "eapol_test scard\n"
888                "eapol_test sim <PIN> <num triplets> [debug]\n"
889                "\n"
890                "options:\n"
891                "  -c<conf> = configuration file\n"
892                "  -a<AS IP> = IP address of the authentication server, "
893                "default 127.0.0.1\n"
894                "  -p<AS port> = UDP port of the authentication server, "
895                "default 1812\n"
896                "  -s<AS secret> = shared secret with the authentication "
897                "server, default 'radius'\n"
898                "  -r<count> = number of re-authentications\n"
899                "  -W = wait for a control interface monitor before starting\n"
900                "  -S = save configuration after authentiation\n"
901                "  -n = no MPPE keys expected\n");
902 }
903
904
905 int main(int argc, char *argv[])
906 {
907         struct wpa_supplicant wpa_s;
908         int c, ret = 1, wait_for_monitor = 0, save_config = 0;
909         char *as_addr = "127.0.0.1";
910         int as_port = 1812;
911         char *as_secret = "radius";
912         char *conf = NULL;
913
914 #ifdef CONFIG_NATIVE_WINDOWS
915         WSADATA wsaData;
916         if (WSAStartup(MAKEWORD(2, 0), &wsaData)) {
917                 printf("Could not find a usable WinSock.dll\n");
918                 return -1;
919         }
920 #endif /* CONFIG_NATIVE_WINDOWS */
921
922         memset(&eapol_test, 0, sizeof(eapol_test));
923
924         wpa_debug_level = 0;
925         wpa_debug_show_keys = 1;
926
927         for (;;) {
928                 c = getopt(argc, argv, "a:c:np:r:s:SW");
929                 if (c < 0)
930                         break;
931                 switch (c) {
932                 case 'a':
933                         as_addr = optarg;
934                         break;
935                 case 'c':
936                         conf = optarg;
937                         break;
938                 case 'n':
939                         eapol_test.no_mppe_keys++;
940                         break;
941                 case 'p':
942                         as_port = atoi(optarg);
943                         break;
944                 case 'r':
945                         eapol_test.eapol_test_num_reauths = atoi(optarg);
946                         break;
947                 case 's':
948                         as_secret = optarg;
949                         break;
950                 case 'S':
951                         save_config++;
952                         break;
953                 case 'W':
954                         wait_for_monitor++;
955                         break;
956                 default:
957                         usage();
958                         return -1;
959                 }
960         }
961
962         if (argc > optind && strcmp(argv[optind], "scard") == 0) {
963                 return scard_test();
964         }
965
966         if (argc > optind && strcmp(argv[optind], "sim") == 0) {
967                 return scard_get_triplets(argc - optind - 1,
968                                           &argv[optind + 1]);
969         }
970
971         if (conf == NULL) {
972                 usage();
973                 printf("Configuration file is required.\n");
974                 return -1;
975         }
976
977         eloop_init(&wpa_s);
978
979         memset(&wpa_s, 0, sizeof(wpa_s));
980         eapol_test.wpa_s = &wpa_s;
981         wpa_s.conf = wpa_config_read(conf);
982         if (wpa_s.conf == NULL) {
983                 printf("Failed to parse configuration file '%s'.\n", conf);
984                 return -1;
985         }
986         if (wpa_s.conf->ssid == NULL) {
987                 printf("No networks defined.\n");
988                 return -1;
989         }
990
991         wpa_init_conf(&eapol_test, &wpa_s, as_addr, as_port, as_secret);
992         if (wpa_supplicant_ctrl_iface_init(&wpa_s)) {
993                 printf("Failed to initialize control interface '%s'.\n"
994                        "You may have another eapol_test process already "
995                        "running or the file was\n"
996                        "left by an unclean termination of eapol_test in "
997                        "which case you will need\n"
998                        "to manually remove this file before starting "
999                        "eapol_test again.\n",
1000                        wpa_s.conf->ctrl_interface);
1001                 return -1;
1002         }
1003         if (wpa_supplicant_scard_init(&wpa_s, wpa_s.conf->ssid))
1004                 return -1;
1005
1006         if (test_eapol(&eapol_test, &wpa_s, wpa_s.conf->ssid))
1007                 return -1;
1008
1009         if (wait_for_monitor)
1010                 wpa_supplicant_ctrl_iface_wait(&wpa_s);
1011
1012         eloop_register_timeout(30, 0, eapol_test_timeout, &eapol_test, NULL);
1013         eloop_register_timeout(0, 0, send_eap_request_identity, &wpa_s, NULL);
1014         eloop_register_signal(SIGINT, eapol_test_terminate, NULL);
1015         eloop_register_signal(SIGTERM, eapol_test_terminate, NULL);
1016 #ifndef CONFIG_NATIVE_WINDOWS
1017         eloop_register_signal(SIGHUP, eapol_test_terminate, NULL);
1018 #endif /* CONFIG_NATIVE_WINDOWS */
1019         eloop_run();
1020
1021         if (eapol_test_compare_pmk(&eapol_test) == 0)
1022                 ret = 0;
1023         if (eapol_test.auth_timed_out)
1024                 ret = -2;
1025         if (eapol_test.radius_access_reject_received)
1026                 ret = -3;
1027
1028         if (save_config)
1029                 wpa_config_write(conf, wpa_s.conf);
1030
1031         test_eapol_clean(&eapol_test, &wpa_s);
1032
1033         eloop_destroy();
1034
1035         printf("MPPE keys OK: %d  mismatch: %d\n",
1036                eapol_test.num_mppe_ok, eapol_test.num_mppe_mismatch);
1037         if (eapol_test.num_mppe_mismatch)
1038                 ret = -4;
1039         if (ret)
1040                 printf("FAILURE\n");
1041         else
1042                 printf("SUCCESS\n");
1043
1044 #ifdef CONFIG_NATIVE_WINDOWS
1045         WSACleanup();
1046 #endif /* CONFIG_NATIVE_WINDOWS */
1047
1048         return ret;
1049 }