blob: 88d4241bc98f070576b3ce11928cf3ce1e72c680 [file] [log] [blame]
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001/*
2 * WPA Supplicant - test code
Dmitry Shmidt051af732013-10-22 13:52:46 -07003 * Copyright (c) 2003-2013, Jouni Malinen <j@w1.fi>
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004 *
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005 * This software may be distributed under the terms of the BSD license.
6 * See README for more details.
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007 *
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"
Dmitry Shmidt61d9df32012-08-29 16:22:06 -070016#include "utils/ext_password.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070017#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"
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080022#include "utils/base64.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070023#include "rsn_supp/wpa.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070024#include "wpa_supplicant_i.h"
25#include "radius/radius.h"
26#include "radius/radius_client.h"
Dmitry Shmidtc55524a2011-07-07 11:18:38 -070027#include "common/wpa_ctrl.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070028#include "ctrl_iface.h"
29#include "pcsc_funcs.h"
Dmitry Shmidt051af732013-10-22 13:52:46 -070030#include "wpas_glue.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070031
32
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070033struct wpa_driver_ops *wpa_drivers[] = { NULL };
34
35
36struct extra_radius_attr {
37 u8 type;
38 char syntax;
39 char *data;
40 struct extra_radius_attr *next;
41};
42
43struct 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;
Dmitry Shmidt5a1480c2014-05-12 09:46:02 -070049 int req_eap_key_name;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070050
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
Dmitry Shmidt61d9df32012-08-29 16:22:06 -070057 /* last received EAP Response from Authentication Server */
58 struct wpabuf *last_eap_radius;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070059
60 u8 authenticator_pmk[PMK_LEN];
61 size_t authenticator_pmk_len;
Dmitry Shmidt5a1480c2014-05-12 09:46:02 -070062 u8 authenticator_eap_key_name[256];
63 size_t authenticator_eap_key_name_len;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070064 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;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080074
75 FILE *server_cert_file;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070076};
77
78static struct eapol_test_data eapol_test;
79
80
81static void send_eap_request_identity(void *eloop_ctx, void *timeout_ctx);
82
83
84static 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
95static 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;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800101 char buf[RADIUS_MAX_ATTR_LEN + 1];
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700102
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);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800117 if ((len & 1) || (len / 2) > RADIUS_MAX_ATTR_LEN) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700118 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
146static 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
158static struct extra_radius_attr *
159find_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
170static void ieee802_1x_encapsulate_radius(struct eapol_test_data *e,
171 const u8 *eap, size_t len)
172{
173 struct radius_msg *msg;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800174 char buf[RADIUS_MAX_ATTR_LEN + 1];
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700175 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
Dmitry Shmidt5a1480c2014-05-12 09:46:02 -0700214 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
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700221 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
Dmitry Shmidt04949592012-07-19 12:16:46 -0700288 if (radius_client_send(e->radius, msg, RADIUS_AUTH, e->wpa_s->own_addr)
289 < 0)
290 goto fail;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700291 return;
292
293 fail:
294 radius_msg_free(msg);
295}
296
297
298static int eapol_test_eapol_send(void *ctx, int type, const u8 *buf,
299 size_t len)
300{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700301 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
311static void eapol_test_set_config_blob(void *ctx,
312 struct wpa_config_blob *blob)
313{
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800314 struct eapol_test_data *e = ctx;
315 wpa_config_set_blob(e->wpa_s->conf, blob);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700316}
317
318
319static const struct wpa_config_blob *
320eapol_test_get_config_blob(void *ctx, const char *name)
321{
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800322 struct eapol_test_data *e = ctx;
323 return wpa_config_get_blob(e->wpa_s->conf, name);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700324}
325
326
327static void eapol_test_eapol_done_cb(void *ctx)
328{
329 printf("WPA: EAPOL processing complete\n");
330}
331
332
333static 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
342static int eapol_test_compare_pmk(struct eapol_test_data *e)
343{
344 u8 pmk[PMK_LEN];
345 int ret = 1;
Dmitry Shmidt5a1480c2014-05-12 09:46:02 -0700346 const u8 *sess_id;
347 size_t sess_id_len;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700348
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
Dmitry Shmidt5a1480c2014-05-12 09:46:02 -0700376 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
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700398 return ret;
399}
400
401
Dmitry Shmidt344abd32014-01-14 13:17:00 -0800402static void eapol_sm_cb(struct eapol_sm *eapol, enum eapol_supp_result result,
403 void *ctx)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700404{
405 struct eapol_test_data *e = ctx;
Dmitry Shmidt344abd32014-01-14 13:17:00 -0800406 printf("eapol_sm_cb: result=%d\n", result);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700407 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
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800417static 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
Dmitry Shmidt051af732013-10-22 13:52:46 -0700431#if defined(CONFIG_CTRL_IFACE) || !defined(CONFIG_NO_STDOUT_DEBUG)
432static 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
Dmitry Shmidtc55524a2011-07-07 11:18:38 -0700479static 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 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800504
505 if (e->server_cert_file)
506 eapol_test_write_cert(e->server_cert_file,
507 subject, cert);
Dmitry Shmidtc55524a2011-07-07 11:18:38 -0700508 }
509}
510
511
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -0700512static 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
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700543static 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 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800554 ctx->ctx = e;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700555 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;
Dmitry Shmidt051af732013-10-22 13:52:46 -0700568 ctx->eap_param_needed = eapol_test_eap_param_needed;
Dmitry Shmidtc55524a2011-07-07 11:18:38 -0700569 ctx->cert_cb = eapol_test_cert_cb;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800570 ctx->cert_in_cb = 1;
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -0700571 ctx->set_anon_id = eapol_test_set_anon_id;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700572
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;
Dmitry Shmidt051af732013-10-22 13:52:46 -0700586 eapol_conf.external_sim = wpa_s->conf->external_sim;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700587 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
599static 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);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700605 wpabuf_free(e->last_eap_radius);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700606 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 }
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700623
624 ext_password_deinit(wpa_s->ext_pw);
625 wpa_s->ext_pw = NULL;
626
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700627 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
638static 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
663static 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
672static 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
693static void ieee802_1x_decapsulate_radius(struct eapol_test_data *e)
694{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700695 struct wpabuf *eap;
696 const struct eap_hdr *hdr;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700697 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
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700706 eap = radius_msg_get_eap(msg);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700707 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");
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700713 wpabuf_free(e->last_eap_radius);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700714 e->last_eap_radius = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700715 return;
716 }
717
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700718 if (wpabuf_len(eap) < sizeof(*hdr)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700719 wpa_printf(MSG_DEBUG, "too short EAP packet "
720 "received from authentication server");
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700721 wpabuf_free(eap);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700722 return;
723 }
724
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700725 if (wpabuf_len(eap) > sizeof(*hdr))
726 eap_type = (wpabuf_head_u8(eap))[sizeof(*hdr)];
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700727
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700728 hdr = wpabuf_head(eap);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700729 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));
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700751 wpa_hexdump_buf(MSG_DEBUG, "Decapsulated EAP packet", eap);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700752 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
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700760 wpabuf_free(e->last_eap_radius);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700761 e->last_eap_radius = eap;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700762
763 {
764 struct ieee802_1x_hdr *dot1x;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700765 dot1x = os_malloc(sizeof(*dot1x) + wpabuf_len(eap));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700766 assert(dot1x != NULL);
767 dot1x->version = EAPOL_VERSION;
768 dot1x->type = IEEE802_1X_TYPE_EAP_PACKET;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700769 dot1x->length = htons(wpabuf_len(eap));
770 os_memcpy((u8 *) (dot1x + 1), wpabuf_head(eap),
771 wpabuf_len(eap));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700772 eapol_sm_rx_eapol(e->wpa_s->eapol, e->wpa_s->bssid,
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700773 (u8 *) dot1x,
774 sizeof(*dot1x) + wpabuf_len(eap));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700775 os_free(dot1x);
776 }
777}
778
779
780static 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;
Dmitry Shmidt5a1480c2014-05-12 09:46:02 -0700786 u8 *buf;
787 size_t len;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700788
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 }
Dmitry Shmidt5a1480c2014-05-12 09:46:02 -0700826
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 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700834}
835
836
837/* Process the RADIUS frames from Authentication Server */
838static RadiusRxResult
839ieee802_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
898static 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
957static 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
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -0800988 scard = scard_init(NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700989 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
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08001003 wpa_printf(MSG_DEBUG, "SCARD: MNC length %d",
1004 scard_get_mnc_len(scard));
1005
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001006 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
1058failed:
1059 scard_deinit(scard);
1060
1061 return 0;
1062#undef num_triplets
1063}
1064
1065
1066static 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
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08001088 scard = scard_init(NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001089 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
1131static 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
1139static void usage(void)
1140{
1141 printf("usage:\n"
Dmitry Shmidt5a1480c2014-05-12 09:46:02 -07001142 "eapol_test [-enWS] -c<conf> [-a<AS IP>] [-p<AS port>] "
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001143 "[-s<AS secret>]\\\n"
1144 " [-r<count>] [-t<timeout>] [-C<Connect-Info>] \\\n"
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001145 " [-M<client MAC address>] [-o<server cert file] \\\n"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001146 " [-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"
Dmitry Shmidt5a1480c2014-05-12 09:46:02 -07001162 " -e = Request EAP-Key-Name\n"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001163 " -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"
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001172 " -o<server cert file> = Write received server certificate\n"
1173 " chain to the specified file\n"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001174 " -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
1189int main(int argc, char *argv[])
1190{
Dmitry Shmidt051af732013-10-22 13:52:46 -07001191 struct wpa_global global;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001192 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 (;;) {
Dmitry Shmidt5a1480c2014-05-12 09:46:02 -07001216 c = getopt(argc, argv, "a:A:c:C:eM:nN:o:p:r:s:St:W");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001217 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;
Dmitry Shmidt5a1480c2014-05-12 09:46:02 -07001232 case 'e':
1233 eapol_test.req_eap_key_name = 1;
1234 break;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001235 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;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001244 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;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001254 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':
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001273 p1 = os_zalloc(sizeof(*p1));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001274 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
Dmitry Shmidt051af732013-10-22 13:52:46 -07001331 os_memset(&global, 0, sizeof(global));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001332 os_memset(&wpa_s, 0, sizeof(wpa_s));
Dmitry Shmidt051af732013-10-22 13:52:46 -07001333 wpa_s.global = &global;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001334 eapol_test.wpa_s = &wpa_s;
Dmitry Shmidt051af732013-10-22 13:52:46 -07001335 dl_list_init(&wpa_s.bss);
1336 dl_list_init(&wpa_s.bss_id);
Dmitry Shmidt64f47c52013-04-16 10:41:54 -07001337 wpa_s.conf = wpa_config_read(conf, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001338 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
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001367 if (wpas_init_ext_pw(&wpa_s) < 0)
1368 return -1;
1369
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001370 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
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001403 if (eapol_test.server_cert_file)
1404 fclose(eapol_test.server_cert_file);
1405
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001406 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}