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