1/* 2 * EAP peer method: EAP-PEAP (draft-josefsson-pppext-eap-tls-eap-07.txt) 3 * Copyright (c) 2004-2006, 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 15#include "includes.h" 16 17#include "common.h" 18#include "eap_i.h" 19#include "eap_tls_common.h" 20#include "config_ssid.h" 21#include "tls.h" 22#include "eap_tlv.h" 23 24 25/* Maximum supported PEAP version 26 * 0 = Microsoft's PEAP version 0; draft-kamath-pppext-peapv0-00.txt 27 * 1 = draft-josefsson-ppext-eap-tls-eap-05.txt 28 * 2 = draft-josefsson-ppext-eap-tls-eap-07.txt 29 */ 30#define EAP_PEAP_VERSION 1 31 32 33static void eap_peap_deinit(struct eap_sm *sm, void *priv); 34 35 36struct eap_peap_data { 37 struct eap_ssl_data ssl; 38 39 int peap_version, force_peap_version, force_new_label; 40 41 const struct eap_method *phase2_method; 42 void *phase2_priv; 43 int phase2_success; 44 int phase2_eap_success; 45 int phase2_eap_started; 46 47 struct eap_method_type phase2_type; 48 struct eap_method_type *phase2_types; 49 size_t num_phase2_types; 50 51 int peap_outer_success; /* 0 = PEAP terminated on Phase 2 inner 52 * EAP-Success 53 * 1 = reply with tunneled EAP-Success to inner 54 * EAP-Success and expect AS to send outer 55 * (unencrypted) EAP-Success after this 56 * 2 = reply with PEAP/TLS ACK to inner 57 * EAP-Success and expect AS to send outer 58 * (unencrypted) EAP-Success after this */ 59 int resuming; /* starting a resumed session */ 60 u8 *key_data; 61 62 u8 *pending_phase2_req; 63 size_t pending_phase2_req_len; 64}; 65 66 67static void * eap_peap_init(struct eap_sm *sm) 68{ 69 struct eap_peap_data *data; 70 struct wpa_ssid *config = eap_get_config(sm); 71 72 data = os_zalloc(sizeof(*data)); 73 if (data == NULL) 74 return NULL; 75 sm->peap_done = FALSE; 76 data->peap_version = EAP_PEAP_VERSION; 77 data->force_peap_version = -1; 78 data->peap_outer_success = 2; 79 80 if (config && config->phase1) { 81 char *pos = os_strstr(config->phase1, "peapver="); 82 if (pos) { 83 data->force_peap_version = atoi(pos + 8); 84 data->peap_version = data->force_peap_version; 85 wpa_printf(MSG_DEBUG, "EAP-PEAP: Forced PEAP version " 86 "%d", data->force_peap_version); 87 } 88 89 if (os_strstr(config->phase1, "peaplabel=1")) { 90 data->force_new_label = 1; 91 wpa_printf(MSG_DEBUG, "EAP-PEAP: Force new label for " 92 "key derivation"); 93 } 94 95 if (os_strstr(config->phase1, "peap_outer_success=0")) { 96 data->peap_outer_success = 0; 97 wpa_printf(MSG_DEBUG, "EAP-PEAP: terminate " 98 "authentication on tunneled EAP-Success"); 99 } else if (os_strstr(config->phase1, "peap_outer_success=1")) { 100 data->peap_outer_success = 1; 101 wpa_printf(MSG_DEBUG, "EAP-PEAP: send tunneled " 102 "EAP-Success after receiving tunneled " 103 "EAP-Success"); 104 } else if (os_strstr(config->phase1, "peap_outer_success=2")) { 105 data->peap_outer_success = 2; 106 wpa_printf(MSG_DEBUG, "EAP-PEAP: send PEAP/TLS ACK " 107 "after receiving tunneled EAP-Success"); 108 } 109 } 110 111 if (config && config->phase2) { 112 char *start, *pos, *buf; 113 struct eap_method_type *methods = NULL, *_methods; 114 u8 method; 115 size_t num_methods = 0; 116 start = buf = os_strdup(config->phase2); 117 if (buf == NULL) { 118 eap_peap_deinit(sm, data); 119 return NULL; 120 } 121 while (start && *start != '\0') { 122 int vendor; 123 pos = os_strstr(start, "auth="); 124 if (pos == NULL) 125 break; 126 if (start != pos && *(pos - 1) != ' ') { 127 start = pos + 5; 128 continue; 129 } 130 131 start = pos + 5; 132 pos = os_strchr(start, ' '); 133 if (pos) 134 *pos++ = '\0'; 135 method = eap_get_phase2_type(start, &vendor); 136 if (vendor == EAP_VENDOR_IETF && 137 method == EAP_TYPE_NONE) { 138 wpa_printf(MSG_ERROR, "EAP-PEAP: Unsupported " 139 "Phase2 method '%s'", start); 140 } else { 141 num_methods++; 142 _methods = os_realloc( 143 methods, 144 num_methods * sizeof(*methods)); 145 if (_methods == NULL) { 146 os_free(methods); 147 os_free(buf); 148 eap_peap_deinit(sm, data); 149 return NULL; 150 } 151 methods = _methods; 152 methods[num_methods - 1].vendor = vendor; 153 methods[num_methods - 1].method = method; 154 } 155 156 start = pos; 157 } 158 os_free(buf); 159 data->phase2_types = methods; 160 data->num_phase2_types = num_methods; 161 } 162 if (data->phase2_types == NULL) { 163 data->phase2_types = 164 eap_get_phase2_types(config, &data->num_phase2_types); 165 } 166 if (data->phase2_types == NULL) { 167 wpa_printf(MSG_ERROR, "EAP-PEAP: No Phase2 method available"); 168 eap_peap_deinit(sm, data); 169 return NULL; 170 } 171 wpa_hexdump(MSG_DEBUG, "EAP-PEAP: Phase2 EAP types", 172 (u8 *) data->phase2_types, 173 data->num_phase2_types * sizeof(struct eap_method_type)); 174 data->phase2_type.vendor = EAP_VENDOR_IETF; 175 data->phase2_type.method = EAP_TYPE_NONE; 176 177 if (eap_tls_ssl_init(sm, &data->ssl, config)) { 178 wpa_printf(MSG_INFO, "EAP-PEAP: Failed to initialize SSL."); 179 eap_peap_deinit(sm, data); 180 return NULL; 181 } 182 183 return data; 184} 185 186 187static void eap_peap_deinit(struct eap_sm *sm, void *priv) 188{ 189 struct eap_peap_data *data = priv; 190 if (data == NULL) 191 return; 192 if (data->phase2_priv && data->phase2_method) 193 data->phase2_method->deinit(sm, data->phase2_priv); 194 os_free(data->phase2_types); 195 eap_tls_ssl_deinit(sm, &data->ssl); 196 os_free(data->key_data); 197 os_free(data->pending_phase2_req); 198 os_free(data); 199} 200 201 202static int eap_peap_encrypt(struct eap_sm *sm, struct eap_peap_data *data, 203 int id, const u8 *plain, size_t plain_len, 204 u8 **out_data, size_t *out_len) 205{ 206 int res; 207 u8 *pos; 208 struct eap_hdr *resp; 209 210 /* TODO: add support for fragmentation, if needed. This will need to 211 * add TLS Message Length field, if the frame is fragmented. 212 * Note: Microsoft IAS did not seem to like TLS Message Length with 213 * PEAP/MSCHAPv2. */ 214 resp = os_malloc(sizeof(struct eap_hdr) + 2 + data->ssl.tls_out_limit); 215 if (resp == NULL) 216 return -1; 217 218 resp->code = EAP_CODE_RESPONSE; 219 resp->identifier = id; 220 221 pos = (u8 *) (resp + 1); 222 *pos++ = EAP_TYPE_PEAP; 223 *pos++ = data->peap_version; 224 225 res = tls_connection_encrypt(sm->ssl_ctx, data->ssl.conn, 226 plain, plain_len, 227 pos, data->ssl.tls_out_limit); 228 if (res < 0) { 229 wpa_printf(MSG_INFO, "EAP-PEAP: Failed to encrypt Phase 2 " 230 "data"); 231 os_free(resp); 232 return -1; 233 } 234 235 *out_len = sizeof(struct eap_hdr) + 2 + res; 236 resp->length = host_to_be16(*out_len); 237 *out_data = (u8 *) resp; 238 return 0; 239} 240 241 242static int eap_peap_phase2_nak(struct eap_peap_data *data, struct eap_hdr *hdr, 243 u8 **resp, size_t *resp_len) 244{ 245 struct eap_hdr *resp_hdr; 246 u8 *pos = (u8 *) (hdr + 1); 247 size_t i; 248 249 /* TODO: add support for expanded Nak */ 250 wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase 2 Request: Nak type=%d", *pos); 251 wpa_hexdump(MSG_DEBUG, "EAP-PEAP: Allowed Phase2 EAP types", 252 (u8 *) data->phase2_types, 253 data->num_phase2_types * sizeof(struct eap_method_type)); 254 *resp_len = sizeof(struct eap_hdr) + 1; 255 *resp = os_malloc(*resp_len + data->num_phase2_types); 256 if (*resp == NULL) 257 return -1; 258 259 resp_hdr = (struct eap_hdr *) (*resp); 260 resp_hdr->code = EAP_CODE_RESPONSE; 261 resp_hdr->identifier = hdr->identifier; 262 pos = (u8 *) (resp_hdr + 1); 263 *pos++ = EAP_TYPE_NAK; 264 for (i = 0; i < data->num_phase2_types; i++) { 265 if (data->phase2_types[i].vendor == EAP_VENDOR_IETF && 266 data->phase2_types[i].method < 256) { 267 (*resp_len)++; 268 *pos++ = data->phase2_types[i].method; 269 } 270 } 271 resp_hdr->length = host_to_be16(*resp_len); 272 273 return 0; 274} 275 276 277static int eap_peap_phase2_request(struct eap_sm *sm, 278 struct eap_peap_data *data, 279 struct eap_method_ret *ret, 280 struct eap_hdr *hdr, 281 u8 **resp, size_t *resp_len) 282{ 283 size_t len = be_to_host16(hdr->length); 284 u8 *pos; 285 struct eap_method_ret iret; 286 struct wpa_ssid *config = eap_get_config(sm); 287 288 if (len <= sizeof(struct eap_hdr)) { 289 wpa_printf(MSG_INFO, "EAP-PEAP: too short " 290 "Phase 2 request (len=%lu)", (unsigned long) len); 291 return -1; 292 } 293 pos = (u8 *) (hdr + 1); 294 wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase 2 Request: type=%d", *pos); 295 switch (*pos) { 296 case EAP_TYPE_IDENTITY: 297 *resp = eap_sm_buildIdentity(sm, hdr->identifier, resp_len, 1); 298 break; 299 case EAP_TYPE_TLV: 300 os_memset(&iret, 0, sizeof(iret)); 301 if (eap_tlv_process(sm, &iret, hdr, resp, resp_len, 302 data->phase2_eap_started && 303 !data->phase2_eap_success)) { 304 ret->methodState = METHOD_DONE; 305 ret->decision = DECISION_FAIL; 306 return -1; 307 } 308 if (iret.methodState == METHOD_DONE || 309 iret.methodState == METHOD_MAY_CONT) { 310 ret->methodState = iret.methodState; 311 ret->decision = iret.decision; 312 data->phase2_success = 1; 313 } 314 break; 315 default: 316 if (data->phase2_type.vendor == EAP_VENDOR_IETF && 317 data->phase2_type.method == EAP_TYPE_NONE) { 318 size_t i; 319 for (i = 0; i < data->num_phase2_types; i++) { 320 if (data->phase2_types[i].vendor != 321 EAP_VENDOR_IETF || 322 data->phase2_types[i].method != *pos) 323 continue; 324 325 data->phase2_type.vendor = 326 data->phase2_types[i].vendor; 327 data->phase2_type.method = 328 data->phase2_types[i].method; 329 wpa_printf(MSG_DEBUG, "EAP-PEAP: Selected " 330 "Phase 2 EAP vendor %d method %d", 331 data->phase2_type.vendor, 332 data->phase2_type.method); 333 break; 334 } 335 } 336 if (*pos != data->phase2_type.method || 337 *pos == EAP_TYPE_NONE) { 338 if (eap_peap_phase2_nak(data, hdr, resp, resp_len)) 339 return -1; 340 return 0; 341 } 342 343 if (data->phase2_priv == NULL) { 344 data->phase2_method = eap_sm_get_eap_methods( 345 data->phase2_type.vendor, 346 data->phase2_type.method); 347 if (data->phase2_method) { 348 sm->init_phase2 = 1; 349 data->phase2_priv = 350 data->phase2_method->init(sm); 351 sm->init_phase2 = 0; 352 } 353 } 354 if (data->phase2_priv == NULL || data->phase2_method == NULL) { 355 wpa_printf(MSG_INFO, "EAP-PEAP: failed to initialize " 356 "Phase 2 EAP method %d", *pos); 357 ret->methodState = METHOD_DONE; 358 ret->decision = DECISION_FAIL; 359 return -1; 360 } 361 data->phase2_eap_started = 1; 362 os_memset(&iret, 0, sizeof(iret)); 363 *resp = data->phase2_method->process(sm, data->phase2_priv, 364 &iret, (u8 *) hdr, len, 365 resp_len); 366 if ((iret.methodState == METHOD_DONE || 367 iret.methodState == METHOD_MAY_CONT) && 368 (iret.decision == DECISION_UNCOND_SUCC || 369 iret.decision == DECISION_COND_SUCC)) { 370 data->phase2_eap_success = 1; 371 data->phase2_success = 1; 372 } 373 break; 374 } 375 376 if (*resp == NULL && 377 (config->pending_req_identity || config->pending_req_password || 378 config->pending_req_otp || config->pending_req_new_password)) { 379 os_free(data->pending_phase2_req); 380 data->pending_phase2_req = os_malloc(len); 381 if (data->pending_phase2_req) { 382 os_memcpy(data->pending_phase2_req, hdr, len); 383 data->pending_phase2_req_len = len; 384 } 385 } 386 387 return 0; 388} 389 390 391static int eap_peap_decrypt(struct eap_sm *sm, struct eap_peap_data *data, 392 struct eap_method_ret *ret, 393 const struct eap_hdr *req, 394 const u8 *in_data, size_t in_len, 395 u8 **out_data, size_t *out_len) 396{ 397 u8 *in_decrypted; 398 int res, skip_change = 0; 399 struct eap_hdr *hdr, *rhdr; 400 u8 *resp = NULL; 401 size_t resp_len, len_decrypted, len, buf_len; 402 const u8 *msg; 403 size_t msg_len; 404 int need_more_input; 405 406 wpa_printf(MSG_DEBUG, "EAP-PEAP: received %lu bytes encrypted data for" 407 " Phase 2", (unsigned long) in_len); 408 409 if (data->pending_phase2_req) { 410 wpa_printf(MSG_DEBUG, "EAP-PEAP: Pending Phase 2 request - " 411 "skip decryption and use old data"); 412 /* Clear TLS reassembly state. */ 413 os_free(data->ssl.tls_in); 414 data->ssl.tls_in = NULL; 415 data->ssl.tls_in_len = 0; 416 data->ssl.tls_in_left = 0; 417 data->ssl.tls_in_total = 0; 418 in_decrypted = data->pending_phase2_req; 419 data->pending_phase2_req = NULL; 420 len_decrypted = data->pending_phase2_req_len; 421 skip_change = 1; 422 goto continue_req; 423 } 424 425 msg = eap_tls_data_reassemble(sm, &data->ssl, in_data, in_len, 426 &msg_len, &need_more_input); 427 if (msg == NULL) 428 return need_more_input ? 1 : -1; 429 430 if (in_len == 0 && sm->workaround && data->phase2_success) { 431 /* 432 * Cisco ACS seems to be using TLS ACK to terminate 433 * EAP-PEAPv0/GTC. Try to reply with TLS ACK. 434 */ 435 wpa_printf(MSG_DEBUG, "EAP-PEAP: Received TLS ACK, but " 436 "expected data - acknowledge with TLS ACK since " 437 "Phase 2 has been completed"); 438 ret->decision = DECISION_COND_SUCC; 439 ret->methodState = METHOD_DONE; 440 return 1; 441 } 442 443 buf_len = in_len; 444 if (data->ssl.tls_in_total > buf_len) 445 buf_len = data->ssl.tls_in_total; 446 in_decrypted = os_malloc(buf_len); 447 if (in_decrypted == NULL) { 448 os_free(data->ssl.tls_in); 449 data->ssl.tls_in = NULL; 450 data->ssl.tls_in_len = 0; 451 wpa_printf(MSG_WARNING, "EAP-PEAP: failed to allocate memory " 452 "for decryption"); 453 return -1; 454 } 455 456 res = tls_connection_decrypt(sm->ssl_ctx, data->ssl.conn, 457 msg, msg_len, in_decrypted, buf_len); 458 os_free(data->ssl.tls_in); 459 data->ssl.tls_in = NULL; 460 data->ssl.tls_in_len = 0; 461 if (res < 0) { 462 wpa_printf(MSG_INFO, "EAP-PEAP: Failed to decrypt Phase 2 " 463 "data"); 464 os_free(in_decrypted); 465 return 0; 466 } 467 len_decrypted = res; 468 469continue_req: 470 wpa_hexdump(MSG_DEBUG, "EAP-PEAP: Decrypted Phase 2 EAP", in_decrypted, 471 len_decrypted); 472 473 hdr = (struct eap_hdr *) in_decrypted; 474 if (len_decrypted == 5 && hdr->code == EAP_CODE_REQUEST && 475 be_to_host16(hdr->length) == 5 && 476 in_decrypted[4] == EAP_TYPE_IDENTITY) { 477 /* At least FreeRADIUS seems to send full EAP header with 478 * EAP Request Identity */ 479 skip_change = 1; 480 } 481 if (len_decrypted >= 5 && hdr->code == EAP_CODE_REQUEST && 482 in_decrypted[4] == EAP_TYPE_TLV) { 483 skip_change = 1; 484 } 485 486 if (data->peap_version == 0 && !skip_change) { 487 struct eap_hdr *nhdr = os_malloc(sizeof(struct eap_hdr) + 488 len_decrypted); 489 if (nhdr == NULL) { 490 os_free(in_decrypted); 491 return 0; 492 } 493 os_memcpy((u8 *) (nhdr + 1), in_decrypted, len_decrypted); 494 os_free(in_decrypted); 495 nhdr->code = req->code; 496 nhdr->identifier = req->identifier; 497 nhdr->length = host_to_be16(sizeof(struct eap_hdr) + 498 len_decrypted); 499 500 len_decrypted += sizeof(struct eap_hdr); 501 in_decrypted = (u8 *) nhdr; 502 } 503 hdr = (struct eap_hdr *) in_decrypted; 504 if (len_decrypted < sizeof(*hdr)) { 505 os_free(in_decrypted); 506 wpa_printf(MSG_INFO, "EAP-PEAP: Too short Phase 2 " 507 "EAP frame (len=%lu)", 508 (unsigned long) len_decrypted); 509 return 0; 510 } 511 len = be_to_host16(hdr->length); 512 if (len > len_decrypted) { 513 os_free(in_decrypted); 514 wpa_printf(MSG_INFO, "EAP-PEAP: Length mismatch in " 515 "Phase 2 EAP frame (len=%lu hdr->length=%lu)", 516 (unsigned long) len_decrypted, (unsigned long) len); 517 return 0; 518 } 519 if (len < len_decrypted) { 520 wpa_printf(MSG_INFO, "EAP-PEAP: Odd.. Phase 2 EAP header has " 521 "shorter length than full decrypted data " 522 "(%lu < %lu)", 523 (unsigned long) len, (unsigned long) len_decrypted); 524 if (sm->workaround && len == 4 && len_decrypted == 5 && 525 in_decrypted[4] == EAP_TYPE_IDENTITY) { 526 /* Radiator 3.9 seems to set Phase 2 EAP header to use 527 * incorrect length for the EAP-Request Identity 528 * packet, so fix the inner header to interoperate.. 529 * This was fixed in 2004-06-23 patch for Radiator and 530 * this workaround can be removed at some point. */ 531 wpa_printf(MSG_INFO, "EAP-PEAP: workaround -> replace " 532 "Phase 2 EAP header len (%lu) with real " 533 "decrypted len (%lu)", 534 (unsigned long) len, 535 (unsigned long) len_decrypted); 536 len = len_decrypted; 537 hdr->length = host_to_be16(len); 538 } 539 } 540 wpa_printf(MSG_DEBUG, "EAP-PEAP: received Phase 2: code=%d " 541 "identifier=%d length=%lu", hdr->code, hdr->identifier, 542 (unsigned long) len); 543 switch (hdr->code) { 544 case EAP_CODE_REQUEST: 545 if (eap_peap_phase2_request(sm, data, ret, hdr, 546 &resp, &resp_len)) { 547 os_free(in_decrypted); 548 wpa_printf(MSG_INFO, "EAP-PEAP: Phase2 Request " 549 "processing failed"); 550 return 0; 551 } 552 break; 553 case EAP_CODE_SUCCESS: 554 wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase 2 Success"); 555 if (data->peap_version == 1) { 556 /* EAP-Success within TLS tunnel is used to indicate 557 * shutdown of the TLS channel. The authentication has 558 * been completed. */ 559 if (data->phase2_eap_started && 560 !data->phase2_eap_success) { 561 wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase 2 " 562 "Success used to indicate success, " 563 "but Phase 2 EAP was not yet " 564 "completed successfully"); 565 ret->methodState = METHOD_DONE; 566 ret->decision = DECISION_FAIL; 567 os_free(in_decrypted); 568 return 0; 569 } 570 wpa_printf(MSG_DEBUG, "EAP-PEAP: Version 1 - " 571 "EAP-Success within TLS tunnel - " 572 "authentication completed"); 573 ret->decision = DECISION_UNCOND_SUCC; 574 ret->methodState = METHOD_DONE; 575 data->phase2_success = 1; 576 if (data->peap_outer_success == 2) { 577 os_free(in_decrypted); 578 wpa_printf(MSG_DEBUG, "EAP-PEAP: Use TLS ACK " 579 "to finish authentication"); 580 return 1; 581 } else if (data->peap_outer_success == 1) { 582 /* Reply with EAP-Success within the TLS 583 * channel to complete the authentication. */ 584 resp_len = sizeof(struct eap_hdr); 585 resp = os_zalloc(resp_len); 586 if (resp) { 587 rhdr = (struct eap_hdr *) resp; 588 rhdr->code = EAP_CODE_SUCCESS; 589 rhdr->identifier = hdr->identifier; 590 rhdr->length = host_to_be16(resp_len); 591 } 592 } else { 593 /* No EAP-Success expected for Phase 1 (outer, 594 * unencrypted auth), so force EAP state 595 * machine to SUCCESS state. */ 596 sm->peap_done = TRUE; 597 } 598 } else { 599 /* FIX: ? */ 600 } 601 break; 602 case EAP_CODE_FAILURE: 603 wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase 2 Failure"); 604 ret->decision = DECISION_FAIL; 605 ret->methodState = METHOD_MAY_CONT; 606 ret->allowNotifications = FALSE; 607 /* Reply with EAP-Failure within the TLS channel to complete 608 * failure reporting. */ 609 resp_len = sizeof(struct eap_hdr); 610 resp = os_zalloc(resp_len); 611 if (resp) { 612 rhdr = (struct eap_hdr *) resp; 613 rhdr->code = EAP_CODE_FAILURE; 614 rhdr->identifier = hdr->identifier; 615 rhdr->length = host_to_be16(resp_len); 616 } 617 break; 618 default: 619 wpa_printf(MSG_INFO, "EAP-PEAP: Unexpected code=%d in " 620 "Phase 2 EAP header", hdr->code); 621 break; 622 } 623 624 os_free(in_decrypted); 625 626 if (resp) { 627 u8 *resp_pos; 628 size_t resp_send_len; 629 int skip_change2 = 0; 630 631 wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: Encrypting Phase 2 data", 632 resp, resp_len); 633 /* PEAP version changes */ 634 if (resp_len >= 5 && resp[0] == EAP_CODE_RESPONSE && 635 resp[4] == EAP_TYPE_TLV) 636 skip_change2 = 1; 637 if (data->peap_version == 0 && !skip_change2) { 638 resp_pos = resp + sizeof(struct eap_hdr); 639 resp_send_len = resp_len - sizeof(struct eap_hdr); 640 } else { 641 resp_pos = resp; 642 resp_send_len = resp_len; 643 } 644 645 if (eap_peap_encrypt(sm, data, req->identifier, 646 resp_pos, resp_send_len, 647 out_data, out_len)) { 648 wpa_printf(MSG_INFO, "EAP-PEAP: Failed to encrypt " 649 "a Phase 2 frame"); 650 } 651 os_free(resp); 652 } 653 654 return 0; 655} 656 657 658static u8 * eap_peap_process(struct eap_sm *sm, void *priv, 659 struct eap_method_ret *ret, 660 const u8 *reqData, size_t reqDataLen, 661 size_t *respDataLen) 662{ 663 const struct eap_hdr *req; 664 size_t left; 665 int res; 666 u8 flags, *resp, id; 667 const u8 *pos; 668 struct eap_peap_data *data = priv; 669 670 pos = eap_tls_process_init(sm, &data->ssl, EAP_TYPE_PEAP, ret, 671 reqData, reqDataLen, &left, &flags); 672 if (pos == NULL) 673 return NULL; 674 req = (const struct eap_hdr *) reqData; 675 id = req->identifier; 676 677 if (flags & EAP_TLS_FLAGS_START) { 678 wpa_printf(MSG_DEBUG, "EAP-PEAP: Start (server ver=%d, own " 679 "ver=%d)", flags & EAP_PEAP_VERSION_MASK, 680 data->peap_version); 681 if ((flags & EAP_PEAP_VERSION_MASK) < data->peap_version) 682 data->peap_version = flags & EAP_PEAP_VERSION_MASK; 683 if (data->force_peap_version >= 0 && 684 data->force_peap_version != data->peap_version) { 685 wpa_printf(MSG_WARNING, "EAP-PEAP: Failed to select " 686 "forced PEAP version %d", 687 data->force_peap_version); 688 ret->methodState = METHOD_DONE; 689 ret->decision = DECISION_FAIL; 690 ret->allowNotifications = FALSE; 691 return NULL; 692 } 693 wpa_printf(MSG_DEBUG, "EAP-PEAP: Using PEAP version %d", 694 data->peap_version); 695 left = 0; /* make sure that this frame is empty, even though it 696 * should always be, anyway */ 697 } 698 699 resp = NULL; 700 if (tls_connection_established(sm->ssl_ctx, data->ssl.conn) && 701 !data->resuming) { 702 res = eap_peap_decrypt(sm, data, ret, req, pos, left, 703 &resp, respDataLen); 704 } else { 705 res = eap_tls_process_helper(sm, &data->ssl, EAP_TYPE_PEAP, 706 data->peap_version, id, pos, left, 707 &resp, respDataLen); 708 709 if (tls_connection_established(sm->ssl_ctx, data->ssl.conn)) { 710 char *label; 711 wpa_printf(MSG_DEBUG, 712 "EAP-PEAP: TLS done, proceed to Phase 2"); 713 os_free(data->key_data); 714 /* draft-josefsson-ppext-eap-tls-eap-05.txt 715 * specifies that PEAPv1 would use "client PEAP 716 * encryption" as the label. However, most existing 717 * PEAPv1 implementations seem to be using the old 718 * label, "client EAP encryption", instead. Use the old 719 * label by default, but allow it to be configured with 720 * phase1 parameter peaplabel=1. */ 721 if (data->peap_version > 1 || data->force_new_label) 722 label = "client PEAP encryption"; 723 else 724 label = "client EAP encryption"; 725 wpa_printf(MSG_DEBUG, "EAP-PEAP: using label '%s' in " 726 "key derivation", label); 727 data->key_data = 728 eap_tls_derive_key(sm, &data->ssl, label, 729 EAP_TLS_KEY_LEN); 730 if (data->key_data) { 731 wpa_hexdump_key(MSG_DEBUG, 732 "EAP-PEAP: Derived key", 733 data->key_data, 734 EAP_TLS_KEY_LEN); 735 } else { 736 wpa_printf(MSG_DEBUG, "EAP-PEAP: Failed to " 737 "derive key"); 738 } 739 740 if (sm->workaround && data->resuming) { 741 /* 742 * At least few RADIUS servers (Aegis v1.1.6; 743 * but not v1.1.4; and Cisco ACS) seem to be 744 * terminating PEAPv1 (Aegis) or PEAPv0 (Cisco 745 * ACS) session resumption with outer 746 * EAP-Success. This does not seem to follow 747 * draft-josefsson-pppext-eap-tls-eap-05.txt 748 * section 4.2, so only allow this if EAP 749 * workarounds are enabled. 750 */ 751 wpa_printf(MSG_DEBUG, "EAP-PEAP: Workaround - " 752 "allow outer EAP-Success to " 753 "terminate PEAP resumption"); 754 ret->decision = DECISION_COND_SUCC; 755 data->phase2_success = 1; 756 } 757 758 data->resuming = 0; 759 } 760 761 if (res == 2) { 762 /* 763 * Application data included in the handshake message. 764 */ 765 os_free(data->pending_phase2_req); 766 data->pending_phase2_req = resp; 767 data->pending_phase2_req_len = *respDataLen; 768 resp = NULL; 769 *respDataLen = 0; 770 res = eap_peap_decrypt(sm, data, ret, req, pos, left, 771 &resp, respDataLen); 772 } 773 } 774 775 if (ret->methodState == METHOD_DONE) { 776 ret->allowNotifications = FALSE; 777 } 778 779 if (res == 1) { 780 return eap_tls_build_ack(&data->ssl, respDataLen, id, 781 EAP_TYPE_PEAP, data->peap_version); 782 } 783 784 return resp; 785} 786 787 788static Boolean eap_peap_has_reauth_data(struct eap_sm *sm, void *priv) 789{ 790 struct eap_peap_data *data = priv; 791 return tls_connection_established(sm->ssl_ctx, data->ssl.conn) && 792 data->phase2_success; 793} 794 795 796static void eap_peap_deinit_for_reauth(struct eap_sm *sm, void *priv) 797{ 798 struct eap_peap_data *data = priv; 799 os_free(data->pending_phase2_req); 800 data->pending_phase2_req = NULL; 801} 802 803 804static void * eap_peap_init_for_reauth(struct eap_sm *sm, void *priv) 805{ 806 struct eap_peap_data *data = priv; 807 os_free(data->key_data); 808 data->key_data = NULL; 809 if (eap_tls_reauth_init(sm, &data->ssl)) { 810 os_free(data); 811 return NULL; 812 } 813 if (data->phase2_priv && data->phase2_method && 814 data->phase2_method->init_for_reauth) 815 data->phase2_method->init_for_reauth(sm, data->phase2_priv); 816 data->phase2_success = 0; 817 data->phase2_eap_success = 0; 818 data->phase2_eap_started = 0; 819 data->resuming = 1; 820 sm->peap_done = FALSE; 821 return priv; 822} 823 824 825static int eap_peap_get_status(struct eap_sm *sm, void *priv, char *buf, 826 size_t buflen, int verbose) 827{ 828 struct eap_peap_data *data = priv; 829 int len, ret; 830 831 len = eap_tls_status(sm, &data->ssl, buf, buflen, verbose); 832 if (data->phase2_method) { 833 ret = os_snprintf(buf + len, buflen - len, 834 "EAP-PEAPv%d Phase2 method=%s\n", 835 data->peap_version, 836 data->phase2_method->name); 837 if (ret < 0 || (size_t) ret >= buflen - len) 838 return len; 839 len += ret; 840 } 841 return len; 842} 843 844 845static Boolean eap_peap_isKeyAvailable(struct eap_sm *sm, void *priv) 846{ 847 struct eap_peap_data *data = priv; 848 return data->key_data != NULL && data->phase2_success; 849} 850 851 852static u8 * eap_peap_getKey(struct eap_sm *sm, void *priv, size_t *len) 853{ 854 struct eap_peap_data *data = priv; 855 u8 *key; 856 857 if (data->key_data == NULL || !data->phase2_success) 858 return NULL; 859 860 key = os_malloc(EAP_TLS_KEY_LEN); 861 if (key == NULL) 862 return NULL; 863 864 *len = EAP_TLS_KEY_LEN; 865 os_memcpy(key, data->key_data, EAP_TLS_KEY_LEN); 866 867 return key; 868} 869 870 871int eap_peer_peap_register(void) 872{ 873 struct eap_method *eap; 874 int ret; 875 876 eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION, 877 EAP_VENDOR_IETF, EAP_TYPE_PEAP, "PEAP"); 878 if (eap == NULL) 879 return -1; 880 881 eap->init = eap_peap_init; 882 eap->deinit = eap_peap_deinit; 883 eap->process = eap_peap_process; 884 eap->isKeyAvailable = eap_peap_isKeyAvailable; 885 eap->getKey = eap_peap_getKey; 886 eap->get_status = eap_peap_get_status; 887 eap->has_reauth_data = eap_peap_has_reauth_data; 888 eap->deinit_for_reauth = eap_peap_deinit_for_reauth; 889 eap->init_for_reauth = eap_peap_init_for_reauth; 890 891 ret = eap_peer_method_register(eap); 892 if (ret) 893 eap_peer_method_free(eap); 894 return ret; 895} 896