$search
00001 /* 00002 * WPA Supplicant - test code 00003 * Copyright (c) 2003-2007, Jouni Malinen <j@w1.fi> 00004 * 00005 * This program is free software; you can redistribute it and/or modify 00006 * it under the terms of the GNU General Public License version 2 as 00007 * published by the Free Software Foundation. 00008 * 00009 * Alternatively, this software may be distributed under the terms of BSD 00010 * license. 00011 * 00012 * See README and COPYING for more details. 00013 * 00014 * IEEE 802.1X Supplicant test code (to be used in place of wpa_supplicant.c. 00015 * Not used in production version. 00016 */ 00017 00018 #include "includes.h" 00019 #include <assert.h> 00020 00021 #include "common.h" 00022 #include "config.h" 00023 #include "eapol_supp/eapol_supp_sm.h" 00024 #include "eap_peer/eap.h" 00025 #include "eloop.h" 00026 #include "rsn_supp/wpa.h" 00027 #include "eap_peer/eap_i.h" 00028 #include "wpa_supplicant_i.h" 00029 #include "radius/radius.h" 00030 #include "radius/radius_client.h" 00031 #include "ctrl_iface.h" 00032 #include "pcsc_funcs.h" 00033 00034 00035 extern int wpa_debug_level; 00036 extern int wpa_debug_show_keys; 00037 00038 struct wpa_driver_ops *wpa_drivers[] = { NULL }; 00039 00040 00041 struct extra_radius_attr { 00042 u8 type; 00043 char syntax; 00044 char *data; 00045 struct extra_radius_attr *next; 00046 }; 00047 00048 struct eapol_test_data { 00049 struct wpa_supplicant *wpa_s; 00050 00051 int eapol_test_num_reauths; 00052 int no_mppe_keys; 00053 int num_mppe_ok, num_mppe_mismatch; 00054 00055 u8 radius_identifier; 00056 struct radius_msg *last_recv_radius; 00057 struct in_addr own_ip_addr; 00058 struct radius_client_data *radius; 00059 struct hostapd_radius_servers *radius_conf; 00060 00061 u8 *last_eap_radius; /* last received EAP Response from Authentication 00062 * Server */ 00063 size_t last_eap_radius_len; 00064 00065 u8 authenticator_pmk[PMK_LEN]; 00066 size_t authenticator_pmk_len; 00067 int radius_access_accept_received; 00068 int radius_access_reject_received; 00069 int auth_timed_out; 00070 00071 u8 *eap_identity; 00072 size_t eap_identity_len; 00073 00074 char *connect_info; 00075 u8 own_addr[ETH_ALEN]; 00076 struct extra_radius_attr *extra_attrs; 00077 }; 00078 00079 static struct eapol_test_data eapol_test; 00080 00081 00082 static void send_eap_request_identity(void *eloop_ctx, void *timeout_ctx); 00083 00084 00085 static void hostapd_logger_cb(void *ctx, const u8 *addr, unsigned int module, 00086 int level, const char *txt, size_t len) 00087 { 00088 if (addr) 00089 wpa_printf(MSG_DEBUG, "STA " MACSTR ": %s\n", 00090 MAC2STR(addr), txt); 00091 else 00092 wpa_printf(MSG_DEBUG, "%s", txt); 00093 } 00094 00095 00096 static int add_extra_attr(struct radius_msg *msg, 00097 struct extra_radius_attr *attr) 00098 { 00099 size_t len; 00100 char *pos; 00101 u32 val; 00102 char buf[128]; 00103 00104 switch (attr->syntax) { 00105 case 's': 00106 os_snprintf(buf, sizeof(buf), "%s", attr->data); 00107 len = os_strlen(buf); 00108 break; 00109 case 'n': 00110 buf[0] = '\0'; 00111 len = 1; 00112 break; 00113 case 'x': 00114 pos = attr->data; 00115 if (pos[0] == '0' && pos[1] == 'x') 00116 pos += 2; 00117 len = os_strlen(pos); 00118 if ((len & 1) || (len / 2) > sizeof(buf)) { 00119 printf("Invalid extra attribute hexstring\n"); 00120 return -1; 00121 } 00122 len /= 2; 00123 if (hexstr2bin(pos, (u8 *) buf, len) < 0) { 00124 printf("Invalid extra attribute hexstring\n"); 00125 return -1; 00126 } 00127 break; 00128 case 'd': 00129 val = htonl(atoi(attr->data)); 00130 os_memcpy(buf, &val, 4); 00131 len = 4; 00132 break; 00133 default: 00134 printf("Incorrect extra attribute syntax specification\n"); 00135 return -1; 00136 } 00137 00138 if (!radius_msg_add_attr(msg, attr->type, (u8 *) buf, len)) { 00139 printf("Could not add attribute %d\n", attr->type); 00140 return -1; 00141 } 00142 00143 return 0; 00144 } 00145 00146 00147 static int add_extra_attrs(struct radius_msg *msg, 00148 struct extra_radius_attr *attrs) 00149 { 00150 struct extra_radius_attr *p; 00151 for (p = attrs; p; p = p->next) { 00152 if (add_extra_attr(msg, p) < 0) 00153 return -1; 00154 } 00155 return 0; 00156 } 00157 00158 00159 static struct extra_radius_attr * 00160 find_extra_attr(struct extra_radius_attr *attrs, u8 type) 00161 { 00162 struct extra_radius_attr *p; 00163 for (p = attrs; p; p = p->next) { 00164 if (p->type == type) 00165 return p; 00166 } 00167 return NULL; 00168 } 00169 00170 00171 static void ieee802_1x_encapsulate_radius(struct eapol_test_data *e, 00172 const u8 *eap, size_t len) 00173 { 00174 struct radius_msg *msg; 00175 char buf[128]; 00176 const struct eap_hdr *hdr; 00177 const u8 *pos; 00178 00179 wpa_printf(MSG_DEBUG, "Encapsulating EAP message into a RADIUS " 00180 "packet"); 00181 00182 e->radius_identifier = radius_client_get_id(e->radius); 00183 msg = radius_msg_new(RADIUS_CODE_ACCESS_REQUEST, 00184 e->radius_identifier); 00185 if (msg == NULL) { 00186 printf("Could not create net RADIUS packet\n"); 00187 return; 00188 } 00189 00190 radius_msg_make_authenticator(msg, (u8 *) e, sizeof(*e)); 00191 00192 hdr = (const struct eap_hdr *) eap; 00193 pos = (const u8 *) (hdr + 1); 00194 if (len > sizeof(*hdr) && hdr->code == EAP_CODE_RESPONSE && 00195 pos[0] == EAP_TYPE_IDENTITY) { 00196 pos++; 00197 os_free(e->eap_identity); 00198 e->eap_identity_len = len - sizeof(*hdr) - 1; 00199 e->eap_identity = os_malloc(e->eap_identity_len); 00200 if (e->eap_identity) { 00201 os_memcpy(e->eap_identity, pos, e->eap_identity_len); 00202 wpa_hexdump(MSG_DEBUG, "Learned identity from " 00203 "EAP-Response-Identity", 00204 e->eap_identity, e->eap_identity_len); 00205 } 00206 } 00207 00208 if (e->eap_identity && 00209 !radius_msg_add_attr(msg, RADIUS_ATTR_USER_NAME, 00210 e->eap_identity, e->eap_identity_len)) { 00211 printf("Could not add User-Name\n"); 00212 goto fail; 00213 } 00214 00215 if (!find_extra_attr(e->extra_attrs, RADIUS_ATTR_NAS_IP_ADDRESS) && 00216 !radius_msg_add_attr(msg, RADIUS_ATTR_NAS_IP_ADDRESS, 00217 (u8 *) &e->own_ip_addr, 4)) { 00218 printf("Could not add NAS-IP-Address\n"); 00219 goto fail; 00220 } 00221 00222 os_snprintf(buf, sizeof(buf), RADIUS_802_1X_ADDR_FORMAT, 00223 MAC2STR(e->wpa_s->own_addr)); 00224 if (!find_extra_attr(e->extra_attrs, RADIUS_ATTR_CALLING_STATION_ID) 00225 && 00226 !radius_msg_add_attr(msg, RADIUS_ATTR_CALLING_STATION_ID, 00227 (u8 *) buf, os_strlen(buf))) { 00228 printf("Could not add Calling-Station-Id\n"); 00229 goto fail; 00230 } 00231 00232 /* TODO: should probably check MTU from driver config; 2304 is max for 00233 * IEEE 802.11, but use 1400 to avoid problems with too large packets 00234 */ 00235 if (!find_extra_attr(e->extra_attrs, RADIUS_ATTR_FRAMED_MTU) && 00236 !radius_msg_add_attr_int32(msg, RADIUS_ATTR_FRAMED_MTU, 1400)) { 00237 printf("Could not add Framed-MTU\n"); 00238 goto fail; 00239 } 00240 00241 if (!find_extra_attr(e->extra_attrs, RADIUS_ATTR_NAS_PORT_TYPE) && 00242 !radius_msg_add_attr_int32(msg, RADIUS_ATTR_NAS_PORT_TYPE, 00243 RADIUS_NAS_PORT_TYPE_IEEE_802_11)) { 00244 printf("Could not add NAS-Port-Type\n"); 00245 goto fail; 00246 } 00247 00248 os_snprintf(buf, sizeof(buf), "%s", e->connect_info); 00249 if (!find_extra_attr(e->extra_attrs, RADIUS_ATTR_CONNECT_INFO) && 00250 !radius_msg_add_attr(msg, RADIUS_ATTR_CONNECT_INFO, 00251 (u8 *) buf, os_strlen(buf))) { 00252 printf("Could not add Connect-Info\n"); 00253 goto fail; 00254 } 00255 00256 if (add_extra_attrs(msg, e->extra_attrs) < 0) 00257 goto fail; 00258 00259 if (eap && !radius_msg_add_eap(msg, eap, len)) { 00260 printf("Could not add EAP-Message\n"); 00261 goto fail; 00262 } 00263 00264 /* State attribute must be copied if and only if this packet is 00265 * Access-Request reply to the previous Access-Challenge */ 00266 if (e->last_recv_radius && 00267 radius_msg_get_hdr(e->last_recv_radius)->code == 00268 RADIUS_CODE_ACCESS_CHALLENGE) { 00269 int res = radius_msg_copy_attr(msg, e->last_recv_radius, 00270 RADIUS_ATTR_STATE); 00271 if (res < 0) { 00272 printf("Could not copy State attribute from previous " 00273 "Access-Challenge\n"); 00274 goto fail; 00275 } 00276 if (res > 0) { 00277 wpa_printf(MSG_DEBUG, " Copied RADIUS State " 00278 "Attribute"); 00279 } 00280 } 00281 00282 radius_client_send(e->radius, msg, RADIUS_AUTH, e->wpa_s->own_addr); 00283 return; 00284 00285 fail: 00286 radius_msg_free(msg); 00287 } 00288 00289 00290 static int eapol_test_eapol_send(void *ctx, int type, const u8 *buf, 00291 size_t len) 00292 { 00293 /* struct wpa_supplicant *wpa_s = ctx; */ 00294 printf("WPA: eapol_test_eapol_send(type=%d len=%lu)\n", 00295 type, (unsigned long) len); 00296 if (type == IEEE802_1X_TYPE_EAP_PACKET) { 00297 wpa_hexdump(MSG_DEBUG, "TX EAP -> RADIUS", buf, len); 00298 ieee802_1x_encapsulate_radius(&eapol_test, buf, len); 00299 } 00300 return 0; 00301 } 00302 00303 00304 static void eapol_test_set_config_blob(void *ctx, 00305 struct wpa_config_blob *blob) 00306 { 00307 struct wpa_supplicant *wpa_s = ctx; 00308 wpa_config_set_blob(wpa_s->conf, blob); 00309 } 00310 00311 00312 static const struct wpa_config_blob * 00313 eapol_test_get_config_blob(void *ctx, const char *name) 00314 { 00315 struct wpa_supplicant *wpa_s = ctx; 00316 return wpa_config_get_blob(wpa_s->conf, name); 00317 } 00318 00319 00320 static void eapol_test_eapol_done_cb(void *ctx) 00321 { 00322 printf("WPA: EAPOL processing complete\n"); 00323 } 00324 00325 00326 static void eapol_sm_reauth(void *eloop_ctx, void *timeout_ctx) 00327 { 00328 struct eapol_test_data *e = eloop_ctx; 00329 printf("\n\n\n\n\neapol_test: Triggering EAP reauthentication\n\n"); 00330 e->radius_access_accept_received = 0; 00331 send_eap_request_identity(e->wpa_s, NULL); 00332 } 00333 00334 00335 static int eapol_test_compare_pmk(struct eapol_test_data *e) 00336 { 00337 u8 pmk[PMK_LEN]; 00338 int ret = 1; 00339 00340 if (eapol_sm_get_key(e->wpa_s->eapol, pmk, PMK_LEN) == 0) { 00341 wpa_hexdump(MSG_DEBUG, "PMK from EAPOL", pmk, PMK_LEN); 00342 if (os_memcmp(pmk, e->authenticator_pmk, PMK_LEN) != 0) { 00343 printf("WARNING: PMK mismatch\n"); 00344 wpa_hexdump(MSG_DEBUG, "PMK from AS", 00345 e->authenticator_pmk, PMK_LEN); 00346 } else if (e->radius_access_accept_received) 00347 ret = 0; 00348 } else if (e->authenticator_pmk_len == 16 && 00349 eapol_sm_get_key(e->wpa_s->eapol, pmk, 16) == 0) { 00350 wpa_hexdump(MSG_DEBUG, "LEAP PMK from EAPOL", pmk, 16); 00351 if (os_memcmp(pmk, e->authenticator_pmk, 16) != 0) { 00352 printf("WARNING: PMK mismatch\n"); 00353 wpa_hexdump(MSG_DEBUG, "PMK from AS", 00354 e->authenticator_pmk, 16); 00355 } else if (e->radius_access_accept_received) 00356 ret = 0; 00357 } else if (e->radius_access_accept_received && e->no_mppe_keys) { 00358 /* No keying material expected */ 00359 ret = 0; 00360 } 00361 00362 if (ret && !e->no_mppe_keys) 00363 e->num_mppe_mismatch++; 00364 else if (!e->no_mppe_keys) 00365 e->num_mppe_ok++; 00366 00367 return ret; 00368 } 00369 00370 00371 static void eapol_sm_cb(struct eapol_sm *eapol, int success, void *ctx) 00372 { 00373 struct eapol_test_data *e = ctx; 00374 printf("eapol_sm_cb: success=%d\n", success); 00375 e->eapol_test_num_reauths--; 00376 if (e->eapol_test_num_reauths < 0) 00377 eloop_terminate(); 00378 else { 00379 eapol_test_compare_pmk(e); 00380 eloop_register_timeout(0, 100000, eapol_sm_reauth, e, NULL); 00381 } 00382 } 00383 00384 00385 static int test_eapol(struct eapol_test_data *e, struct wpa_supplicant *wpa_s, 00386 struct wpa_ssid *ssid) 00387 { 00388 struct eapol_config eapol_conf; 00389 struct eapol_ctx *ctx; 00390 00391 ctx = os_zalloc(sizeof(*ctx)); 00392 if (ctx == NULL) { 00393 printf("Failed to allocate EAPOL context.\n"); 00394 return -1; 00395 } 00396 ctx->ctx = wpa_s; 00397 ctx->msg_ctx = wpa_s; 00398 ctx->scard_ctx = wpa_s->scard; 00399 ctx->cb = eapol_sm_cb; 00400 ctx->cb_ctx = e; 00401 ctx->eapol_send_ctx = wpa_s; 00402 ctx->preauth = 0; 00403 ctx->eapol_done_cb = eapol_test_eapol_done_cb; 00404 ctx->eapol_send = eapol_test_eapol_send; 00405 ctx->set_config_blob = eapol_test_set_config_blob; 00406 ctx->get_config_blob = eapol_test_get_config_blob; 00407 ctx->opensc_engine_path = wpa_s->conf->opensc_engine_path; 00408 ctx->pkcs11_engine_path = wpa_s->conf->pkcs11_engine_path; 00409 ctx->pkcs11_module_path = wpa_s->conf->pkcs11_module_path; 00410 00411 wpa_s->eapol = eapol_sm_init(ctx); 00412 if (wpa_s->eapol == NULL) { 00413 os_free(ctx); 00414 printf("Failed to initialize EAPOL state machines.\n"); 00415 return -1; 00416 } 00417 00418 wpa_s->current_ssid = ssid; 00419 os_memset(&eapol_conf, 0, sizeof(eapol_conf)); 00420 eapol_conf.accept_802_1x_keys = 1; 00421 eapol_conf.required_keys = 0; 00422 eapol_conf.fast_reauth = wpa_s->conf->fast_reauth; 00423 eapol_conf.workaround = ssid->eap_workaround; 00424 eapol_sm_notify_config(wpa_s->eapol, &ssid->eap, &eapol_conf); 00425 eapol_sm_register_scard_ctx(wpa_s->eapol, wpa_s->scard); 00426 00427 00428 eapol_sm_notify_portValid(wpa_s->eapol, FALSE); 00429 /* 802.1X::portControl = Auto */ 00430 eapol_sm_notify_portEnabled(wpa_s->eapol, TRUE); 00431 00432 return 0; 00433 } 00434 00435 00436 static void test_eapol_clean(struct eapol_test_data *e, 00437 struct wpa_supplicant *wpa_s) 00438 { 00439 struct extra_radius_attr *p, *prev; 00440 00441 radius_client_deinit(e->radius); 00442 os_free(e->last_eap_radius); 00443 radius_msg_free(e->last_recv_radius); 00444 e->last_recv_radius = NULL; 00445 os_free(e->eap_identity); 00446 e->eap_identity = NULL; 00447 eapol_sm_deinit(wpa_s->eapol); 00448 wpa_s->eapol = NULL; 00449 if (e->radius_conf && e->radius_conf->auth_server) { 00450 os_free(e->radius_conf->auth_server->shared_secret); 00451 os_free(e->radius_conf->auth_server); 00452 } 00453 os_free(e->radius_conf); 00454 e->radius_conf = NULL; 00455 scard_deinit(wpa_s->scard); 00456 if (wpa_s->ctrl_iface) { 00457 wpa_supplicant_ctrl_iface_deinit(wpa_s->ctrl_iface); 00458 wpa_s->ctrl_iface = NULL; 00459 } 00460 wpa_config_free(wpa_s->conf); 00461 00462 p = e->extra_attrs; 00463 while (p) { 00464 prev = p; 00465 p = p->next; 00466 os_free(prev); 00467 } 00468 } 00469 00470 00471 static void send_eap_request_identity(void *eloop_ctx, void *timeout_ctx) 00472 { 00473 struct wpa_supplicant *wpa_s = eloop_ctx; 00474 u8 buf[100], *pos; 00475 struct ieee802_1x_hdr *hdr; 00476 struct eap_hdr *eap; 00477 00478 hdr = (struct ieee802_1x_hdr *) buf; 00479 hdr->version = EAPOL_VERSION; 00480 hdr->type = IEEE802_1X_TYPE_EAP_PACKET; 00481 hdr->length = htons(5); 00482 00483 eap = (struct eap_hdr *) (hdr + 1); 00484 eap->code = EAP_CODE_REQUEST; 00485 eap->identifier = 0; 00486 eap->length = htons(5); 00487 pos = (u8 *) (eap + 1); 00488 *pos = EAP_TYPE_IDENTITY; 00489 00490 printf("Sending fake EAP-Request-Identity\n"); 00491 eapol_sm_rx_eapol(wpa_s->eapol, wpa_s->bssid, buf, 00492 sizeof(*hdr) + 5); 00493 } 00494 00495 00496 static void eapol_test_timeout(void *eloop_ctx, void *timeout_ctx) 00497 { 00498 struct eapol_test_data *e = eloop_ctx; 00499 printf("EAPOL test timed out\n"); 00500 e->auth_timed_out = 1; 00501 eloop_terminate(); 00502 } 00503 00504 00505 static char *eap_type_text(u8 type) 00506 { 00507 switch (type) { 00508 case EAP_TYPE_IDENTITY: return "Identity"; 00509 case EAP_TYPE_NOTIFICATION: return "Notification"; 00510 case EAP_TYPE_NAK: return "Nak"; 00511 case EAP_TYPE_TLS: return "TLS"; 00512 case EAP_TYPE_TTLS: return "TTLS"; 00513 case EAP_TYPE_PEAP: return "PEAP"; 00514 case EAP_TYPE_SIM: return "SIM"; 00515 case EAP_TYPE_GTC: return "GTC"; 00516 case EAP_TYPE_MD5: return "MD5"; 00517 case EAP_TYPE_OTP: return "OTP"; 00518 case EAP_TYPE_FAST: return "FAST"; 00519 case EAP_TYPE_SAKE: return "SAKE"; 00520 case EAP_TYPE_PSK: return "PSK"; 00521 default: return "Unknown"; 00522 } 00523 } 00524 00525 00526 static void ieee802_1x_decapsulate_radius(struct eapol_test_data *e) 00527 { 00528 u8 *eap; 00529 size_t len; 00530 struct eap_hdr *hdr; 00531 int eap_type = -1; 00532 char buf[64]; 00533 struct radius_msg *msg; 00534 00535 if (e->last_recv_radius == NULL) 00536 return; 00537 00538 msg = e->last_recv_radius; 00539 00540 eap = radius_msg_get_eap(msg, &len); 00541 if (eap == NULL) { 00542 /* draft-aboba-radius-rfc2869bis-20.txt, Chap. 2.6.3: 00543 * RADIUS server SHOULD NOT send Access-Reject/no EAP-Message 00544 * attribute */ 00545 wpa_printf(MSG_DEBUG, "could not extract " 00546 "EAP-Message from RADIUS message"); 00547 os_free(e->last_eap_radius); 00548 e->last_eap_radius = NULL; 00549 e->last_eap_radius_len = 0; 00550 return; 00551 } 00552 00553 if (len < sizeof(*hdr)) { 00554 wpa_printf(MSG_DEBUG, "too short EAP packet " 00555 "received from authentication server"); 00556 os_free(eap); 00557 return; 00558 } 00559 00560 if (len > sizeof(*hdr)) 00561 eap_type = eap[sizeof(*hdr)]; 00562 00563 hdr = (struct eap_hdr *) eap; 00564 switch (hdr->code) { 00565 case EAP_CODE_REQUEST: 00566 os_snprintf(buf, sizeof(buf), "EAP-Request-%s (%d)", 00567 eap_type >= 0 ? eap_type_text(eap_type) : "??", 00568 eap_type); 00569 break; 00570 case EAP_CODE_RESPONSE: 00571 os_snprintf(buf, sizeof(buf), "EAP Response-%s (%d)", 00572 eap_type >= 0 ? eap_type_text(eap_type) : "??", 00573 eap_type); 00574 break; 00575 case EAP_CODE_SUCCESS: 00576 os_strlcpy(buf, "EAP Success", sizeof(buf)); 00577 /* LEAP uses EAP Success within an authentication, so must not 00578 * stop here with eloop_terminate(); */ 00579 break; 00580 case EAP_CODE_FAILURE: 00581 os_strlcpy(buf, "EAP Failure", sizeof(buf)); 00582 eloop_terminate(); 00583 break; 00584 default: 00585 os_strlcpy(buf, "unknown EAP code", sizeof(buf)); 00586 wpa_hexdump(MSG_DEBUG, "Decapsulated EAP packet", eap, len); 00587 break; 00588 } 00589 wpa_printf(MSG_DEBUG, "decapsulated EAP packet (code=%d " 00590 "id=%d len=%d) from RADIUS server: %s", 00591 hdr->code, hdr->identifier, ntohs(hdr->length), buf); 00592 00593 /* sta->eapol_sm->be_auth.idFromServer = hdr->identifier; */ 00594 00595 os_free(e->last_eap_radius); 00596 e->last_eap_radius = eap; 00597 e->last_eap_radius_len = len; 00598 00599 { 00600 struct ieee802_1x_hdr *dot1x; 00601 dot1x = os_malloc(sizeof(*dot1x) + len); 00602 assert(dot1x != NULL); 00603 dot1x->version = EAPOL_VERSION; 00604 dot1x->type = IEEE802_1X_TYPE_EAP_PACKET; 00605 dot1x->length = htons(len); 00606 os_memcpy((u8 *) (dot1x + 1), eap, len); 00607 eapol_sm_rx_eapol(e->wpa_s->eapol, e->wpa_s->bssid, 00608 (u8 *) dot1x, sizeof(*dot1x) + len); 00609 os_free(dot1x); 00610 } 00611 } 00612 00613 00614 static void ieee802_1x_get_keys(struct eapol_test_data *e, 00615 struct radius_msg *msg, struct radius_msg *req, 00616 const u8 *shared_secret, 00617 size_t shared_secret_len) 00618 { 00619 struct radius_ms_mppe_keys *keys; 00620 00621 keys = radius_msg_get_ms_keys(msg, req, shared_secret, 00622 shared_secret_len); 00623 if (keys && keys->send == NULL && keys->recv == NULL) { 00624 os_free(keys); 00625 keys = radius_msg_get_cisco_keys(msg, req, shared_secret, 00626 shared_secret_len); 00627 } 00628 00629 if (keys) { 00630 if (keys->send) { 00631 wpa_hexdump(MSG_DEBUG, "MS-MPPE-Send-Key (sign)", 00632 keys->send, keys->send_len); 00633 } 00634 if (keys->recv) { 00635 wpa_hexdump(MSG_DEBUG, "MS-MPPE-Recv-Key (crypt)", 00636 keys->recv, keys->recv_len); 00637 e->authenticator_pmk_len = 00638 keys->recv_len > PMK_LEN ? PMK_LEN : 00639 keys->recv_len; 00640 os_memcpy(e->authenticator_pmk, keys->recv, 00641 e->authenticator_pmk_len); 00642 if (e->authenticator_pmk_len == 16 && keys->send && 00643 keys->send_len == 16) { 00644 /* MS-CHAP-v2 derives 16 octet keys */ 00645 wpa_printf(MSG_DEBUG, "Use MS-MPPE-Send-Key " 00646 "to extend PMK to 32 octets"); 00647 os_memcpy(e->authenticator_pmk + 00648 e->authenticator_pmk_len, 00649 keys->send, keys->send_len); 00650 e->authenticator_pmk_len += keys->send_len; 00651 } 00652 } 00653 00654 os_free(keys->send); 00655 os_free(keys->recv); 00656 os_free(keys); 00657 } 00658 } 00659 00660 00661 /* Process the RADIUS frames from Authentication Server */ 00662 static RadiusRxResult 00663 ieee802_1x_receive_auth(struct radius_msg *msg, struct radius_msg *req, 00664 const u8 *shared_secret, size_t shared_secret_len, 00665 void *data) 00666 { 00667 struct eapol_test_data *e = data; 00668 struct radius_hdr *hdr = radius_msg_get_hdr(msg); 00669 00670 /* RFC 2869, Ch. 5.13: valid Message-Authenticator attribute MUST be 00671 * present when packet contains an EAP-Message attribute */ 00672 if (hdr->code == RADIUS_CODE_ACCESS_REJECT && 00673 radius_msg_get_attr(msg, RADIUS_ATTR_MESSAGE_AUTHENTICATOR, NULL, 00674 0) < 0 && 00675 radius_msg_get_attr(msg, RADIUS_ATTR_EAP_MESSAGE, NULL, 0) < 0) { 00676 wpa_printf(MSG_DEBUG, "Allowing RADIUS " 00677 "Access-Reject without Message-Authenticator " 00678 "since it does not include EAP-Message\n"); 00679 } else if (radius_msg_verify(msg, shared_secret, shared_secret_len, 00680 req, 1)) { 00681 printf("Incoming RADIUS packet did not have correct " 00682 "Message-Authenticator - dropped\n"); 00683 return RADIUS_RX_UNKNOWN; 00684 } 00685 00686 if (hdr->code != RADIUS_CODE_ACCESS_ACCEPT && 00687 hdr->code != RADIUS_CODE_ACCESS_REJECT && 00688 hdr->code != RADIUS_CODE_ACCESS_CHALLENGE) { 00689 printf("Unknown RADIUS message code\n"); 00690 return RADIUS_RX_UNKNOWN; 00691 } 00692 00693 e->radius_identifier = -1; 00694 wpa_printf(MSG_DEBUG, "RADIUS packet matching with station"); 00695 00696 radius_msg_free(e->last_recv_radius); 00697 e->last_recv_radius = msg; 00698 00699 switch (hdr->code) { 00700 case RADIUS_CODE_ACCESS_ACCEPT: 00701 e->radius_access_accept_received = 1; 00702 ieee802_1x_get_keys(e, msg, req, shared_secret, 00703 shared_secret_len); 00704 break; 00705 case RADIUS_CODE_ACCESS_REJECT: 00706 e->radius_access_reject_received = 1; 00707 break; 00708 } 00709 00710 ieee802_1x_decapsulate_radius(e); 00711 00712 if ((hdr->code == RADIUS_CODE_ACCESS_ACCEPT && 00713 e->eapol_test_num_reauths < 0) || 00714 hdr->code == RADIUS_CODE_ACCESS_REJECT) { 00715 eloop_terminate(); 00716 } 00717 00718 return RADIUS_RX_QUEUED; 00719 } 00720 00721 00722 static void wpa_init_conf(struct eapol_test_data *e, 00723 struct wpa_supplicant *wpa_s, const char *authsrv, 00724 int port, const char *secret, 00725 const char *cli_addr) 00726 { 00727 struct hostapd_radius_server *as; 00728 int res; 00729 00730 wpa_s->bssid[5] = 1; 00731 os_memcpy(wpa_s->own_addr, e->own_addr, ETH_ALEN); 00732 e->own_ip_addr.s_addr = htonl((127 << 24) | 1); 00733 os_strlcpy(wpa_s->ifname, "test", sizeof(wpa_s->ifname)); 00734 00735 e->radius_conf = os_zalloc(sizeof(struct hostapd_radius_servers)); 00736 assert(e->radius_conf != NULL); 00737 e->radius_conf->num_auth_servers = 1; 00738 as = os_zalloc(sizeof(struct hostapd_radius_server)); 00739 assert(as != NULL); 00740 #if defined(CONFIG_NATIVE_WINDOWS) || defined(CONFIG_ANSI_C_EXTRA) 00741 { 00742 int a[4]; 00743 u8 *pos; 00744 sscanf(authsrv, "%d.%d.%d.%d", &a[0], &a[1], &a[2], &a[3]); 00745 pos = (u8 *) &as->addr.u.v4; 00746 *pos++ = a[0]; 00747 *pos++ = a[1]; 00748 *pos++ = a[2]; 00749 *pos++ = a[3]; 00750 } 00751 #else /* CONFIG_NATIVE_WINDOWS or CONFIG_ANSI_C_EXTRA */ 00752 inet_aton(authsrv, &as->addr.u.v4); 00753 #endif /* CONFIG_NATIVE_WINDOWS or CONFIG_ANSI_C_EXTRA */ 00754 as->addr.af = AF_INET; 00755 as->port = port; 00756 as->shared_secret = (u8 *) os_strdup(secret); 00757 as->shared_secret_len = os_strlen(secret); 00758 e->radius_conf->auth_server = as; 00759 e->radius_conf->auth_servers = as; 00760 e->radius_conf->msg_dumps = 1; 00761 if (cli_addr) { 00762 if (hostapd_parse_ip_addr(cli_addr, 00763 &e->radius_conf->client_addr) == 0) 00764 e->radius_conf->force_client_addr = 1; 00765 else { 00766 wpa_printf(MSG_ERROR, "Invalid IP address '%s'", 00767 cli_addr); 00768 assert(0); 00769 } 00770 } 00771 00772 e->radius = radius_client_init(wpa_s, e->radius_conf); 00773 assert(e->radius != NULL); 00774 00775 res = radius_client_register(e->radius, RADIUS_AUTH, 00776 ieee802_1x_receive_auth, e); 00777 assert(res == 0); 00778 } 00779 00780 00781 static int scard_test(void) 00782 { 00783 struct scard_data *scard; 00784 size_t len; 00785 char imsi[20]; 00786 unsigned char _rand[16]; 00787 #ifdef PCSC_FUNCS 00788 unsigned char sres[4]; 00789 unsigned char kc[8]; 00790 #endif /* PCSC_FUNCS */ 00791 #define num_triplets 5 00792 unsigned char rand_[num_triplets][16]; 00793 unsigned char sres_[num_triplets][4]; 00794 unsigned char kc_[num_triplets][8]; 00795 int i, res; 00796 size_t j; 00797 00798 #define AKA_RAND_LEN 16 00799 #define AKA_AUTN_LEN 16 00800 #define AKA_AUTS_LEN 14 00801 #define RES_MAX_LEN 16 00802 #define IK_LEN 16 00803 #define CK_LEN 16 00804 unsigned char aka_rand[AKA_RAND_LEN]; 00805 unsigned char aka_autn[AKA_AUTN_LEN]; 00806 unsigned char aka_auts[AKA_AUTS_LEN]; 00807 unsigned char aka_res[RES_MAX_LEN]; 00808 size_t aka_res_len; 00809 unsigned char aka_ik[IK_LEN]; 00810 unsigned char aka_ck[CK_LEN]; 00811 00812 scard = scard_init(SCARD_TRY_BOTH); 00813 if (scard == NULL) 00814 return -1; 00815 if (scard_set_pin(scard, "1234")) { 00816 wpa_printf(MSG_WARNING, "PIN validation failed"); 00817 scard_deinit(scard); 00818 return -1; 00819 } 00820 00821 len = sizeof(imsi); 00822 if (scard_get_imsi(scard, imsi, &len)) 00823 goto failed; 00824 wpa_hexdump_ascii(MSG_DEBUG, "SCARD: IMSI", (u8 *) imsi, len); 00825 /* NOTE: Permanent Username: 1 | IMSI */ 00826 00827 os_memset(_rand, 0, sizeof(_rand)); 00828 if (scard_gsm_auth(scard, _rand, sres, kc)) 00829 goto failed; 00830 00831 os_memset(_rand, 0xff, sizeof(_rand)); 00832 if (scard_gsm_auth(scard, _rand, sres, kc)) 00833 goto failed; 00834 00835 for (i = 0; i < num_triplets; i++) { 00836 os_memset(rand_[i], i, sizeof(rand_[i])); 00837 if (scard_gsm_auth(scard, rand_[i], sres_[i], kc_[i])) 00838 goto failed; 00839 } 00840 00841 for (i = 0; i < num_triplets; i++) { 00842 printf("1"); 00843 for (j = 0; j < len; j++) 00844 printf("%c", imsi[j]); 00845 printf(","); 00846 for (j = 0; j < 16; j++) 00847 printf("%02X", rand_[i][j]); 00848 printf(","); 00849 for (j = 0; j < 4; j++) 00850 printf("%02X", sres_[i][j]); 00851 printf(","); 00852 for (j = 0; j < 8; j++) 00853 printf("%02X", kc_[i][j]); 00854 printf("\n"); 00855 } 00856 00857 wpa_printf(MSG_DEBUG, "Trying to use UMTS authentication"); 00858 00859 /* seq 39 (0x28) */ 00860 os_memset(aka_rand, 0xaa, 16); 00861 os_memcpy(aka_autn, "\x86\x71\x31\xcb\xa2\xfc\x61\xdf" 00862 "\xa3\xb3\x97\x9d\x07\x32\xa2\x12", 16); 00863 00864 res = scard_umts_auth(scard, aka_rand, aka_autn, aka_res, &aka_res_len, 00865 aka_ik, aka_ck, aka_auts); 00866 if (res == 0) { 00867 wpa_printf(MSG_DEBUG, "UMTS auth completed successfully"); 00868 wpa_hexdump(MSG_DEBUG, "RES", aka_res, aka_res_len); 00869 wpa_hexdump(MSG_DEBUG, "IK", aka_ik, IK_LEN); 00870 wpa_hexdump(MSG_DEBUG, "CK", aka_ck, CK_LEN); 00871 } else if (res == -2) { 00872 wpa_printf(MSG_DEBUG, "UMTS auth resulted in synchronization " 00873 "failure"); 00874 wpa_hexdump(MSG_DEBUG, "AUTS", aka_auts, AKA_AUTS_LEN); 00875 } else { 00876 wpa_printf(MSG_DEBUG, "UMTS auth failed"); 00877 } 00878 00879 failed: 00880 scard_deinit(scard); 00881 00882 return 0; 00883 #undef num_triplets 00884 } 00885 00886 00887 static int scard_get_triplets(int argc, char *argv[]) 00888 { 00889 struct scard_data *scard; 00890 size_t len; 00891 char imsi[20]; 00892 unsigned char _rand[16]; 00893 unsigned char sres[4]; 00894 unsigned char kc[8]; 00895 int num_triplets; 00896 int i; 00897 size_t j; 00898 00899 if (argc < 2 || ((num_triplets = atoi(argv[1])) <= 0)) { 00900 printf("invalid parameters for sim command\n"); 00901 return -1; 00902 } 00903 00904 if (argc <= 2 || os_strcmp(argv[2], "debug") != 0) { 00905 /* disable debug output */ 00906 wpa_debug_level = 99; 00907 } 00908 00909 scard = scard_init(SCARD_GSM_SIM_ONLY); 00910 if (scard == NULL) { 00911 printf("Failed to open smartcard connection\n"); 00912 return -1; 00913 } 00914 if (scard_set_pin(scard, argv[0])) { 00915 wpa_printf(MSG_WARNING, "PIN validation failed"); 00916 scard_deinit(scard); 00917 return -1; 00918 } 00919 00920 len = sizeof(imsi); 00921 if (scard_get_imsi(scard, imsi, &len)) { 00922 scard_deinit(scard); 00923 return -1; 00924 } 00925 00926 for (i = 0; i < num_triplets; i++) { 00927 os_memset(_rand, i, sizeof(_rand)); 00928 if (scard_gsm_auth(scard, _rand, sres, kc)) 00929 break; 00930 00931 /* IMSI:Kc:SRES:RAND */ 00932 for (j = 0; j < len; j++) 00933 printf("%c", imsi[j]); 00934 printf(":"); 00935 for (j = 0; j < 8; j++) 00936 printf("%02X", kc[j]); 00937 printf(":"); 00938 for (j = 0; j < 4; j++) 00939 printf("%02X", sres[j]); 00940 printf(":"); 00941 for (j = 0; j < 16; j++) 00942 printf("%02X", _rand[j]); 00943 printf("\n"); 00944 } 00945 00946 scard_deinit(scard); 00947 00948 return 0; 00949 } 00950 00951 00952 static void eapol_test_terminate(int sig, void *signal_ctx) 00953 { 00954 struct wpa_supplicant *wpa_s = signal_ctx; 00955 wpa_msg(wpa_s, MSG_INFO, "Signal %d received - terminating", sig); 00956 eloop_terminate(); 00957 } 00958 00959 00960 static void usage(void) 00961 { 00962 printf("usage:\n" 00963 "eapol_test [-nWS] -c<conf> [-a<AS IP>] [-p<AS port>] " 00964 "[-s<AS secret>]\\\n" 00965 " [-r<count>] [-t<timeout>] [-C<Connect-Info>] \\\n" 00966 " [-M<client MAC address>] \\\n" 00967 " [-N<attr spec>] \\\n" 00968 " [-A<client IP>]\n" 00969 "eapol_test scard\n" 00970 "eapol_test sim <PIN> <num triplets> [debug]\n" 00971 "\n"); 00972 printf("options:\n" 00973 " -c<conf> = configuration file\n" 00974 " -a<AS IP> = IP address of the authentication server, " 00975 "default 127.0.0.1\n" 00976 " -p<AS port> = UDP port of the authentication server, " 00977 "default 1812\n" 00978 " -s<AS secret> = shared secret with the authentication " 00979 "server, default 'radius'\n" 00980 " -A<client IP> = IP address of the client, default: select " 00981 "automatically\n" 00982 " -r<count> = number of re-authentications\n" 00983 " -W = wait for a control interface monitor before starting\n" 00984 " -S = save configuration after authentication\n" 00985 " -n = no MPPE keys expected\n" 00986 " -t<timeout> = sets timeout in seconds (default: 30 s)\n" 00987 " -C<Connect-Info> = RADIUS Connect-Info (default: " 00988 "CONNECT 11Mbps 802.11b)\n" 00989 " -M<client MAC address> = Set own MAC address " 00990 "(Calling-Station-Id,\n" 00991 " default: 02:00:00:00:00:01)\n" 00992 " -N<attr spec> = send arbitrary attribute specified by:\n" 00993 " attr_id:syntax:value or attr_id\n" 00994 " attr_id - number id of the attribute\n" 00995 " syntax - one of: s, d, x\n" 00996 " s = string\n" 00997 " d = integer\n" 00998 " x = octet string\n" 00999 " value - attribute value.\n" 01000 " When only attr_id is specified, NULL will be used as " 01001 "value.\n" 01002 " Multiple attributes can be specified by using the " 01003 "option several times.\n"); 01004 } 01005 01006 01007 int main(int argc, char *argv[]) 01008 { 01009 struct wpa_supplicant wpa_s; 01010 int c, ret = 1, wait_for_monitor = 0, save_config = 0; 01011 char *as_addr = "127.0.0.1"; 01012 int as_port = 1812; 01013 char *as_secret = "radius"; 01014 char *cli_addr = NULL; 01015 char *conf = NULL; 01016 int timeout = 30; 01017 char *pos; 01018 struct extra_radius_attr *p = NULL, *p1; 01019 01020 if (os_program_init()) 01021 return -1; 01022 01023 hostapd_logger_register_cb(hostapd_logger_cb); 01024 01025 os_memset(&eapol_test, 0, sizeof(eapol_test)); 01026 eapol_test.connect_info = "CONNECT 11Mbps 802.11b"; 01027 os_memcpy(eapol_test.own_addr, "\x02\x00\x00\x00\x00\x01", ETH_ALEN); 01028 01029 wpa_debug_level = 0; 01030 wpa_debug_show_keys = 1; 01031 01032 for (;;) { 01033 c = getopt(argc, argv, "a:A:c:C:M:nN:p:r:s:St:W"); 01034 if (c < 0) 01035 break; 01036 switch (c) { 01037 case 'a': 01038 as_addr = optarg; 01039 break; 01040 case 'A': 01041 cli_addr = optarg; 01042 break; 01043 case 'c': 01044 conf = optarg; 01045 break; 01046 case 'C': 01047 eapol_test.connect_info = optarg; 01048 break; 01049 case 'M': 01050 if (hwaddr_aton(optarg, eapol_test.own_addr)) { 01051 usage(); 01052 return -1; 01053 } 01054 break; 01055 case 'n': 01056 eapol_test.no_mppe_keys++; 01057 break; 01058 case 'p': 01059 as_port = atoi(optarg); 01060 break; 01061 case 'r': 01062 eapol_test.eapol_test_num_reauths = atoi(optarg); 01063 break; 01064 case 's': 01065 as_secret = optarg; 01066 break; 01067 case 'S': 01068 save_config++; 01069 break; 01070 case 't': 01071 timeout = atoi(optarg); 01072 break; 01073 case 'W': 01074 wait_for_monitor++; 01075 break; 01076 case 'N': 01077 p1 = os_zalloc(sizeof(p1)); 01078 if (p1 == NULL) 01079 break; 01080 if (!p) 01081 eapol_test.extra_attrs = p1; 01082 else 01083 p->next = p1; 01084 p = p1; 01085 01086 p->type = atoi(optarg); 01087 pos = os_strchr(optarg, ':'); 01088 if (pos == NULL) { 01089 p->syntax = 'n'; 01090 p->data = NULL; 01091 break; 01092 } 01093 01094 pos++; 01095 if (pos[0] == '\0' || pos[1] != ':') { 01096 printf("Incorrect format of attribute " 01097 "specification\n"); 01098 break; 01099 } 01100 01101 p->syntax = pos[0]; 01102 p->data = pos + 2; 01103 break; 01104 default: 01105 usage(); 01106 return -1; 01107 } 01108 } 01109 01110 if (argc > optind && os_strcmp(argv[optind], "scard") == 0) { 01111 return scard_test(); 01112 } 01113 01114 if (argc > optind && os_strcmp(argv[optind], "sim") == 0) { 01115 return scard_get_triplets(argc - optind - 1, 01116 &argv[optind + 1]); 01117 } 01118 01119 if (conf == NULL) { 01120 usage(); 01121 printf("Configuration file is required.\n"); 01122 return -1; 01123 } 01124 01125 if (eap_register_methods()) { 01126 wpa_printf(MSG_ERROR, "Failed to register EAP methods"); 01127 return -1; 01128 } 01129 01130 if (eloop_init()) { 01131 wpa_printf(MSG_ERROR, "Failed to initialize event loop"); 01132 return -1; 01133 } 01134 01135 os_memset(&wpa_s, 0, sizeof(wpa_s)); 01136 eapol_test.wpa_s = &wpa_s; 01137 wpa_s.conf = wpa_config_read(conf); 01138 if (wpa_s.conf == NULL) { 01139 printf("Failed to parse configuration file '%s'.\n", conf); 01140 return -1; 01141 } 01142 if (wpa_s.conf->ssid == NULL) { 01143 printf("No networks defined.\n"); 01144 return -1; 01145 } 01146 01147 wpa_init_conf(&eapol_test, &wpa_s, as_addr, as_port, as_secret, 01148 cli_addr); 01149 wpa_s.ctrl_iface = wpa_supplicant_ctrl_iface_init(&wpa_s); 01150 if (wpa_s.ctrl_iface == NULL) { 01151 printf("Failed to initialize control interface '%s'.\n" 01152 "You may have another eapol_test process already " 01153 "running or the file was\n" 01154 "left by an unclean termination of eapol_test in " 01155 "which case you will need\n" 01156 "to manually remove this file before starting " 01157 "eapol_test again.\n", 01158 wpa_s.conf->ctrl_interface); 01159 return -1; 01160 } 01161 if (wpa_supplicant_scard_init(&wpa_s, wpa_s.conf->ssid)) 01162 return -1; 01163 01164 if (test_eapol(&eapol_test, &wpa_s, wpa_s.conf->ssid)) 01165 return -1; 01166 01167 if (wait_for_monitor) 01168 wpa_supplicant_ctrl_iface_wait(wpa_s.ctrl_iface); 01169 01170 eloop_register_timeout(timeout, 0, eapol_test_timeout, &eapol_test, 01171 NULL); 01172 eloop_register_timeout(0, 0, send_eap_request_identity, &wpa_s, NULL); 01173 eloop_register_signal_terminate(eapol_test_terminate, &wpa_s); 01174 eloop_register_signal_reconfig(eapol_test_terminate, &wpa_s); 01175 eloop_run(); 01176 01177 eloop_cancel_timeout(eapol_test_timeout, &eapol_test, NULL); 01178 eloop_cancel_timeout(eapol_sm_reauth, &eapol_test, NULL); 01179 01180 if (eapol_test_compare_pmk(&eapol_test) == 0 || 01181 eapol_test.no_mppe_keys) 01182 ret = 0; 01183 if (eapol_test.auth_timed_out) 01184 ret = -2; 01185 if (eapol_test.radius_access_reject_received) 01186 ret = -3; 01187 01188 if (save_config) 01189 wpa_config_write(conf, wpa_s.conf); 01190 01191 test_eapol_clean(&eapol_test, &wpa_s); 01192 01193 eap_peer_unregister_methods(); 01194 01195 eloop_destroy(); 01196 01197 printf("MPPE keys OK: %d mismatch: %d\n", 01198 eapol_test.num_mppe_ok, eapol_test.num_mppe_mismatch); 01199 if (eapol_test.num_mppe_mismatch) 01200 ret = -4; 01201 if (ret) 01202 printf("FAILURE\n"); 01203 else 01204 printf("SUCCESS\n"); 01205 01206 os_program_deinit(); 01207 01208 return ret; 01209 }