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