00001
00016 #include <stdlib.h>
00017 #include <stdio.h>
00018 #include <string.h>
00019
00020 #include "common.h"
00021 #include "eap_i.h"
00022 #include "eap_tls_common.h"
00023 #include "wpa_supplicant.h"
00024 #include "config_ssid.h"
00025 #include "tls.h"
00026 #include "eap_tlv.h"
00027
00028
00029
00030
00031
00032
00033
00034 #define EAP_PEAP_VERSION 1
00035
00036
00037 static void eap_peap_deinit(struct eap_sm *sm, void *priv);
00038
00039
00040 struct eap_peap_data {
00041 struct eap_ssl_data ssl;
00042
00043 int peap_version, force_peap_version, force_new_label;
00044
00045 const struct eap_method *phase2_method;
00046 void *phase2_priv;
00047 int phase2_success;
00048
00049 u8 phase2_type;
00050 u8 *phase2_types;
00051 size_t num_phase2_types;
00052
00053 int peap_outer_success;
00054
00055
00056
00057
00058
00059
00060
00061 int resuming;
00062 u8 *key_data;
00063
00064 u8 *pending_phase2_req;
00065 size_t pending_phase2_req_len;
00066 };
00067
00068
00069 static void * eap_peap_init(struct eap_sm *sm)
00070 {
00071 struct eap_peap_data *data;
00072 struct wpa_ssid *config = eap_get_config(sm);
00073
00074 data = malloc(sizeof(*data));
00075 if (data == NULL)
00076 return NULL;
00077 sm->peap_done = FALSE;
00078 memset(data, 0, sizeof(*data));
00079 data->peap_version = EAP_PEAP_VERSION;
00080 data->force_peap_version = -1;
00081 data->peap_outer_success = 2;
00082
00083 if (config && config->phase1) {
00084 char *pos = strstr(config->phase1, "peapver=");
00085 if (pos) {
00086 data->force_peap_version = atoi(pos + 8);
00087 data->peap_version = data->force_peap_version;
00088 wpa_printf(MSG_DEBUG, "EAP-PEAP: Forced PEAP version "
00089 "%d", data->force_peap_version);
00090 }
00091
00092 if (strstr(config->phase1, "peaplabel=1")) {
00093 data->force_new_label = 1;
00094 wpa_printf(MSG_DEBUG, "EAP-PEAP: Force new label for "
00095 "key derivation");
00096 }
00097
00098 if (strstr(config->phase1, "peap_outer_success=0")) {
00099 data->peap_outer_success = 0;
00100 wpa_printf(MSG_DEBUG, "EAP-PEAP: terminate "
00101 "authentication on tunneled EAP-Success");
00102 } else if (strstr(config->phase1, "peap_outer_success=1")) {
00103 data->peap_outer_success = 1;
00104 wpa_printf(MSG_DEBUG, "EAP-PEAP: send tunneled "
00105 "EAP-Success after receiving tunneled "
00106 "EAP-Success");
00107 } else if (strstr(config->phase1, "peap_outer_success=2")) {
00108 data->peap_outer_success = 2;
00109 wpa_printf(MSG_DEBUG, "EAP-PEAP: send PEAP/TLS ACK "
00110 "after receiving tunneled EAP-Success");
00111 }
00112 }
00113
00114 if (config && config->phase2) {
00115 char *start, *pos, *buf;
00116 u8 method, *methods = NULL, *_methods;
00117 size_t num_methods = 0;
00118 start = buf = strdup(config->phase2);
00119 if (buf == NULL) {
00120 eap_peap_deinit(sm, data);
00121 return NULL;
00122 }
00123 while (start && *start != '\0') {
00124 pos = strstr(start, "auth=");
00125 if (pos == NULL)
00126 break;
00127 if (start != pos && *(pos - 1) != ' ') {
00128 start = pos + 5;
00129 continue;
00130 }
00131
00132 start = pos + 5;
00133 pos = strchr(start, ' ');
00134 if (pos)
00135 *pos++ = '\0';
00136 method = eap_get_phase2_type(start);
00137 if (method == EAP_TYPE_NONE) {
00138 wpa_printf(MSG_ERROR, "EAP-PEAP: Unsupported "
00139 "Phase2 method '%s'", start);
00140 } else {
00141 num_methods++;
00142 _methods = realloc(methods, num_methods);
00143 if (_methods == NULL) {
00144 free(methods);
00145 free(buf);
00146 eap_peap_deinit(sm, data);
00147 return NULL;
00148 }
00149 methods = _methods;
00150 methods[num_methods - 1] = method;
00151 }
00152
00153 start = pos;
00154 }
00155 free(buf);
00156 data->phase2_types = methods;
00157 data->num_phase2_types = num_methods;
00158 }
00159 if (data->phase2_types == NULL) {
00160 data->phase2_types =
00161 eap_get_phase2_types(config, &data->num_phase2_types);
00162 }
00163 if (data->phase2_types == NULL) {
00164 wpa_printf(MSG_ERROR, "EAP-PEAP: No Phase2 method available");
00165 eap_peap_deinit(sm, data);
00166 return NULL;
00167 }
00168 wpa_hexdump(MSG_DEBUG, "EAP-PEAP: Phase2 EAP types",
00169 data->phase2_types, data->num_phase2_types);
00170 data->phase2_type = EAP_TYPE_NONE;
00171
00172 if (eap_tls_ssl_init(sm, &data->ssl, config)) {
00173 wpa_printf(MSG_INFO, "EAP-PEAP: Failed to initialize SSL.");
00174 eap_peap_deinit(sm, data);
00175 return NULL;
00176 }
00177
00178 return data;
00179 }
00180
00181
00182 static void eap_peap_deinit(struct eap_sm *sm, void *priv)
00183 {
00184 struct eap_peap_data *data = priv;
00185 if (data == NULL)
00186 return;
00187 if (data->phase2_priv && data->phase2_method)
00188 data->phase2_method->deinit(sm, data->phase2_priv);
00189 free(data->phase2_types);
00190 eap_tls_ssl_deinit(sm, &data->ssl);
00191 free(data->key_data);
00192 free(data->pending_phase2_req);
00193 free(data);
00194 }
00195
00196
00197 static int eap_peap_encrypt(struct eap_sm *sm, struct eap_peap_data *data,
00198 int id, const u8 *plain, size_t plain_len,
00199 u8 **out_data, size_t *out_len)
00200 {
00201 int res;
00202 u8 *pos;
00203 struct eap_hdr *resp;
00204
00205
00206
00207
00208
00209 resp = malloc(sizeof(struct eap_hdr) + 2 + data->ssl.tls_out_limit);
00210 if (resp == NULL)
00211 return -1;
00212
00213 resp->code = EAP_CODE_RESPONSE;
00214 resp->identifier = id;
00215
00216 pos = (u8 *) (resp + 1);
00217 *pos++ = EAP_TYPE_PEAP;
00218 *pos++ = data->peap_version;
00219
00220 res = tls_connection_encrypt(sm->ssl_ctx, data->ssl.conn,
00221 plain, plain_len,
00222 pos, data->ssl.tls_out_limit);
00223 if (res < 0) {
00224 wpa_printf(MSG_INFO, "EAP-PEAP: Failed to encrypt Phase 2 "
00225 "data");
00226 free(resp);
00227 return -1;
00228 }
00229
00230 *out_len = sizeof(struct eap_hdr) + 2 + res;
00231 resp->length = host_to_be16(*out_len);
00232 *out_data = (u8 *) resp;
00233 return 0;
00234 }
00235
00236
00237 static int eap_peap_phase2_nak(struct eap_sm *sm,
00238 struct eap_peap_data *data,
00239 struct eap_hdr *hdr,
00240 u8 **resp, size_t *resp_len)
00241 {
00242 struct eap_hdr *resp_hdr;
00243 u8 *pos = (u8 *) (hdr + 1);
00244
00245 wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase 2 Request: Nak type=%d", *pos);
00246 wpa_hexdump(MSG_DEBUG, "EAP-PEAP: Allowed Phase2 EAP types",
00247 data->phase2_types, data->num_phase2_types);
00248 *resp_len = sizeof(struct eap_hdr) + 1 + data->num_phase2_types;
00249 *resp = malloc(*resp_len);
00250 if (*resp == NULL)
00251 return -1;
00252
00253 resp_hdr = (struct eap_hdr *) (*resp);
00254 resp_hdr->code = EAP_CODE_RESPONSE;
00255 resp_hdr->identifier = hdr->identifier;
00256 resp_hdr->length = host_to_be16(*resp_len);
00257 pos = (u8 *) (resp_hdr + 1);
00258 *pos++ = EAP_TYPE_NAK;
00259 memcpy(pos, data->phase2_types, data->num_phase2_types);
00260
00261 return 0;
00262 }
00263
00264
00265 static int eap_peap_phase2_request(struct eap_sm *sm,
00266 struct eap_peap_data *data,
00267 struct eap_method_ret *ret,
00268 const struct eap_hdr *req,
00269 struct eap_hdr *hdr,
00270 u8 **resp, size_t *resp_len)
00271 {
00272 size_t len = be_to_host16(hdr->length);
00273 u8 *pos;
00274 struct eap_method_ret iret;
00275 struct wpa_ssid *config = eap_get_config(sm);
00276
00277 if (len <= sizeof(struct eap_hdr)) {
00278 wpa_printf(MSG_INFO, "EAP-PEAP: too short "
00279 "Phase 2 request (len=%lu)", (unsigned long) len);
00280 return -1;
00281 }
00282 pos = (u8 *) (hdr + 1);
00283 wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase 2 Request: type=%d", *pos);
00284 switch (*pos) {
00285 case EAP_TYPE_IDENTITY:
00286 *resp = eap_sm_buildIdentity(sm, req->identifier, resp_len, 1);
00287 break;
00288 case EAP_TYPE_TLV:
00289 memset(&iret, 0, sizeof(iret));
00290 if (eap_tlv_process(sm, &iret, hdr, resp, resp_len)) {
00291 ret->methodState = METHOD_DONE;
00292 ret->decision = DECISION_FAIL;
00293 return -1;
00294 }
00295 if (iret.methodState == METHOD_DONE ||
00296 iret.methodState == METHOD_MAY_CONT) {
00297 ret->methodState = iret.methodState;
00298 ret->decision = iret.decision;
00299 data->phase2_success = 1;
00300 }
00301 break;
00302 default:
00303 if (data->phase2_type == EAP_TYPE_NONE) {
00304 int i;
00305 for (i = 0; i < data->num_phase2_types; i++) {
00306 if (data->phase2_types[i] != *pos)
00307 continue;
00308
00309 data->phase2_type = *pos;
00310 wpa_printf(MSG_DEBUG, "EAP-PEAP: Selected "
00311 "Phase 2 EAP method %d",
00312 data->phase2_type);
00313 break;
00314 }
00315 }
00316 if (*pos != data->phase2_type || *pos == EAP_TYPE_NONE) {
00317 if (eap_peap_phase2_nak(sm, data, hdr, resp, resp_len))
00318 return -1;
00319 return 0;
00320 }
00321
00322 if (data->phase2_priv == NULL) {
00323 data->phase2_method = eap_sm_get_eap_methods(*pos);
00324 if (data->phase2_method) {
00325 sm->init_phase2 = 1;
00326 data->phase2_priv =
00327 data->phase2_method->init(sm);
00328 sm->init_phase2 = 0;
00329 }
00330 }
00331 if (data->phase2_priv == NULL || data->phase2_method == NULL) {
00332 wpa_printf(MSG_INFO, "EAP-PEAP: failed to initialize "
00333 "Phase 2 EAP method %d", *pos);
00334 ret->methodState = METHOD_DONE;
00335 ret->decision = DECISION_FAIL;
00336 return -1;
00337 }
00338 memset(&iret, 0, sizeof(iret));
00339 *resp = data->phase2_method->process(sm, data->phase2_priv,
00340 &iret, (u8 *) hdr, len,
00341 resp_len);
00342 if ((iret.methodState == METHOD_DONE ||
00343 iret.methodState == METHOD_MAY_CONT) &&
00344 (iret.decision == DECISION_UNCOND_SUCC ||
00345 iret.decision == DECISION_COND_SUCC)) {
00346 data->phase2_success = 1;
00347 }
00348 break;
00349 }
00350
00351 if (*resp == NULL &&
00352 (config->pending_req_identity || config->pending_req_password ||
00353 config->pending_req_otp || config->pending_req_new_password)) {
00354 free(data->pending_phase2_req);
00355 data->pending_phase2_req = malloc(len);
00356 if (data->pending_phase2_req) {
00357 memcpy(data->pending_phase2_req, hdr, len);
00358 data->pending_phase2_req_len = len;
00359 }
00360 }
00361
00362 return 0;
00363 }
00364
00365
00366 static int eap_peap_decrypt(struct eap_sm *sm, struct eap_peap_data *data,
00367 struct eap_method_ret *ret,
00368 const struct eap_hdr *req,
00369 const u8 *in_data, size_t in_len,
00370 u8 **out_data, size_t *out_len)
00371 {
00372 u8 *in_decrypted;
00373 int buf_len, len_decrypted, len, skip_change = 0;
00374 struct eap_hdr *hdr, *rhdr;
00375 u8 *resp = NULL;
00376 size_t resp_len;
00377 const u8 *msg;
00378 size_t msg_len;
00379 int need_more_input;
00380
00381 wpa_printf(MSG_DEBUG, "EAP-PEAP: received %lu bytes encrypted data for"
00382 " Phase 2", (unsigned long) in_len);
00383
00384 if (data->pending_phase2_req) {
00385 wpa_printf(MSG_DEBUG, "EAP-PEAP: Pending Phase 2 request - "
00386 "skip decryption and use old data");
00387
00388 free(data->ssl.tls_in);
00389 data->ssl.tls_in = NULL;
00390 data->ssl.tls_in_len = 0;
00391 data->ssl.tls_in_left = 0;
00392 data->ssl.tls_in_total = 0;
00393 in_decrypted = data->pending_phase2_req;
00394 data->pending_phase2_req = NULL;
00395 len_decrypted = data->pending_phase2_req_len;
00396 skip_change = 1;
00397 goto continue_req;
00398 }
00399
00400 msg = eap_tls_data_reassemble(sm, &data->ssl, in_data, in_len,
00401 &msg_len, &need_more_input);
00402 if (msg == NULL)
00403 return need_more_input ? 1 : -1;
00404
00405 if (in_len == 0 && sm->workaround && data->phase2_success) {
00406
00407
00408
00409
00410 wpa_printf(MSG_DEBUG, "EAP-PEAP: Received TLS ACK, but "
00411 "expected data - acknowledge with TLS ACK since "
00412 "Phase 2 has been completed");
00413 ret->decision = DECISION_COND_SUCC;
00414 ret->methodState = METHOD_DONE;
00415 return 1;
00416 }
00417
00418 buf_len = in_len;
00419 if (data->ssl.tls_in_total > buf_len)
00420 buf_len = data->ssl.tls_in_total;
00421 in_decrypted = malloc(buf_len);
00422 if (in_decrypted == NULL) {
00423 free(data->ssl.tls_in);
00424 data->ssl.tls_in = NULL;
00425 data->ssl.tls_in_len = 0;
00426 wpa_printf(MSG_WARNING, "EAP-PEAP: failed to allocate memory "
00427 "for decryption");
00428 return -1;
00429 }
00430
00431 len_decrypted = tls_connection_decrypt(sm->ssl_ctx, data->ssl.conn,
00432 msg, msg_len,
00433 in_decrypted, buf_len);
00434 free(data->ssl.tls_in);
00435 data->ssl.tls_in = NULL;
00436 data->ssl.tls_in_len = 0;
00437 if (len_decrypted < 0) {
00438 wpa_printf(MSG_INFO, "EAP-PEAP: Failed to decrypt Phase 2 "
00439 "data");
00440 free(in_decrypted);
00441 return 0;
00442 }
00443
00444 continue_req:
00445 wpa_hexdump(MSG_DEBUG, "EAP-PEAP: Decrypted Phase 2 EAP", in_decrypted,
00446 len_decrypted);
00447
00448 hdr = (struct eap_hdr *) in_decrypted;
00449 if (len_decrypted == 5 && hdr->code == EAP_CODE_REQUEST &&
00450 be_to_host16(hdr->length) == 5 &&
00451 in_decrypted[4] == EAP_TYPE_IDENTITY) {
00452
00453
00454 skip_change = 1;
00455 }
00456 if (len_decrypted >= 5 && hdr->code == EAP_CODE_REQUEST &&
00457 in_decrypted[4] == EAP_TYPE_TLV) {
00458 skip_change = 1;
00459 }
00460
00461 if (data->peap_version == 0 && !skip_change) {
00462 struct eap_hdr *nhdr = malloc(sizeof(struct eap_hdr) +
00463 len_decrypted);
00464 if (nhdr == NULL) {
00465 free(in_decrypted);
00466 return 0;
00467 }
00468 memcpy((u8 *) (nhdr + 1), in_decrypted, len_decrypted);
00469 free(in_decrypted);
00470 nhdr->code = req->code;
00471 nhdr->identifier = req->identifier;
00472 nhdr->length = host_to_be16(sizeof(struct eap_hdr) +
00473 len_decrypted);
00474
00475 len_decrypted += sizeof(struct eap_hdr);
00476 in_decrypted = (u8 *) nhdr;
00477 }
00478 hdr = (struct eap_hdr *) in_decrypted;
00479 if (len_decrypted < sizeof(*hdr)) {
00480 free(in_decrypted);
00481 wpa_printf(MSG_INFO, "EAP-PEAP: Too short Phase 2 "
00482 "EAP frame (len=%d)", len_decrypted);
00483 return 0;
00484 }
00485 len = be_to_host16(hdr->length);
00486 if (len > len_decrypted) {
00487 free(in_decrypted);
00488 wpa_printf(MSG_INFO, "EAP-PEAP: Length mismatch in "
00489 "Phase 2 EAP frame (len=%d hdr->length=%d)",
00490 len_decrypted, len);
00491 return 0;
00492 }
00493 if (len < len_decrypted) {
00494 wpa_printf(MSG_INFO, "EAP-PEAP: Odd.. Phase 2 EAP header has "
00495 "shorter length than full decrypted data (%d < %d)",
00496 len, len_decrypted);
00497 if (sm->workaround && len == 4 && len_decrypted == 5 &&
00498 in_decrypted[4] == EAP_TYPE_IDENTITY) {
00499
00500
00501
00502
00503
00504 wpa_printf(MSG_INFO, "EAP-PEAP: workaround -> replace "
00505 "Phase 2 EAP header len (%d) with real "
00506 "decrypted len (%d)", len, len_decrypted);
00507 len = len_decrypted;
00508 hdr->length = host_to_be16(len);
00509 }
00510 }
00511 wpa_printf(MSG_DEBUG, "EAP-PEAP: received Phase 2: code=%d "
00512 "identifier=%d length=%d", hdr->code, hdr->identifier, len);
00513 switch (hdr->code) {
00514 case EAP_CODE_REQUEST:
00515 if (eap_peap_phase2_request(sm, data, ret, req, hdr,
00516 &resp, &resp_len)) {
00517 free(in_decrypted);
00518 wpa_printf(MSG_INFO, "EAP-PEAP: Phase2 Request "
00519 "processing failed");
00520 return 0;
00521 }
00522 break;
00523 case EAP_CODE_SUCCESS:
00524 wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase 2 Success");
00525 if (data->peap_version == 1) {
00526
00527
00528
00529 wpa_printf(MSG_DEBUG, "EAP-PEAP: Version 1 - "
00530 "EAP-Success within TLS tunnel - "
00531 "authentication completed");
00532 ret->decision = DECISION_UNCOND_SUCC;
00533 ret->methodState = METHOD_DONE;
00534 data->phase2_success = 1;
00535 if (data->peap_outer_success == 2) {
00536 free(in_decrypted);
00537 wpa_printf(MSG_DEBUG, "EAP-PEAP: Use TLS ACK "
00538 "to finish authentication");
00539 return 1;
00540 } else if (data->peap_outer_success == 1) {
00541
00542
00543 resp_len = sizeof(struct eap_hdr);
00544 resp = malloc(resp_len);
00545 if (resp) {
00546 memset(resp, 0, resp_len);
00547 rhdr = (struct eap_hdr *) resp;
00548 rhdr->code = EAP_CODE_SUCCESS;
00549 rhdr->identifier = hdr->identifier;
00550 rhdr->length = host_to_be16(resp_len);
00551 }
00552 } else {
00553
00554
00555
00556 sm->peap_done = TRUE;
00557 }
00558 } else {
00559
00560 }
00561 break;
00562 case EAP_CODE_FAILURE:
00563 wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase 2 Failure");
00564 ret->decision = DECISION_FAIL;
00565 ret->methodState = METHOD_MAY_CONT;
00566 ret->allowNotifications = FALSE;
00567
00568
00569 resp_len = sizeof(struct eap_hdr);
00570 resp = malloc(resp_len);
00571 if (resp) {
00572 memset(resp, 0, resp_len);
00573 rhdr = (struct eap_hdr *) resp;
00574 rhdr->code = EAP_CODE_FAILURE;
00575 rhdr->identifier = hdr->identifier;
00576 rhdr->length = host_to_be16(resp_len);
00577 }
00578 break;
00579 default:
00580 wpa_printf(MSG_INFO, "EAP-PEAP: Unexpected code=%d in "
00581 "Phase 2 EAP header", hdr->code);
00582 break;
00583 }
00584
00585 free(in_decrypted);
00586
00587 if (resp) {
00588 u8 *resp_pos;
00589 size_t resp_send_len;
00590 int skip_change = 0;
00591
00592 wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: Encrypting Phase 2 data",
00593 resp, resp_len);
00594
00595 if (resp_len >= 5 && resp[0] == EAP_CODE_RESPONSE &&
00596 resp[4] == EAP_TYPE_TLV)
00597 skip_change = 1;
00598 if (data->peap_version == 0 && !skip_change) {
00599 resp_pos = resp + sizeof(struct eap_hdr);
00600 resp_send_len = resp_len - sizeof(struct eap_hdr);
00601 } else {
00602 resp_pos = resp;
00603 resp_send_len = resp_len;
00604 }
00605
00606 if (eap_peap_encrypt(sm, data, req->identifier,
00607 resp_pos, resp_send_len,
00608 out_data, out_len)) {
00609 wpa_printf(MSG_INFO, "EAP-PEAP: Failed to encrypt "
00610 "a Phase 2 frame");
00611 }
00612 free(resp);
00613 }
00614
00615 return 0;
00616 }
00617
00618
00619 static u8 * eap_peap_process(struct eap_sm *sm, void *priv,
00620 struct eap_method_ret *ret,
00621 const u8 *reqData, size_t reqDataLen,
00622 size_t *respDataLen)
00623 {
00624 const struct eap_hdr *req;
00625 size_t left;
00626 int res;
00627 u8 flags, *resp, id;
00628 const u8 *pos;
00629 struct eap_peap_data *data = priv;
00630
00631 pos = eap_tls_process_init(sm, &data->ssl, EAP_TYPE_PEAP, ret,
00632 reqData, reqDataLen, &left, &flags);
00633 if (pos == NULL)
00634 return NULL;
00635 req = (const struct eap_hdr *) reqData;
00636 id = req->identifier;
00637
00638 if (flags & EAP_TLS_FLAGS_START) {
00639 wpa_printf(MSG_DEBUG, "EAP-PEAP: Start (server ver=%d, own "
00640 "ver=%d)", flags & EAP_PEAP_VERSION_MASK,
00641 data->peap_version);
00642 if ((flags & EAP_PEAP_VERSION_MASK) < data->peap_version)
00643 data->peap_version = flags & EAP_PEAP_VERSION_MASK;
00644 if (data->force_peap_version >= 0 &&
00645 data->force_peap_version != data->peap_version) {
00646 wpa_printf(MSG_WARNING, "EAP-PEAP: Failed to select "
00647 "forced PEAP version %d",
00648 data->force_peap_version);
00649 ret->methodState = METHOD_DONE;
00650 ret->decision = DECISION_FAIL;
00651 ret->allowNotifications = FALSE;
00652 return NULL;
00653 }
00654 wpa_printf(MSG_DEBUG, "EAP-PEAP: Using PEAP version %d",
00655 data->peap_version);
00656 left = 0;
00657
00658 }
00659
00660 resp = NULL;
00661 if (tls_connection_established(sm->ssl_ctx, data->ssl.conn) &&
00662 !data->resuming) {
00663 res = eap_peap_decrypt(sm, data, ret, req, pos, left,
00664 &resp, respDataLen);
00665 } else {
00666 res = eap_tls_process_helper(sm, &data->ssl, EAP_TYPE_PEAP,
00667 data->peap_version, id, pos, left,
00668 &resp, respDataLen);
00669
00670 if (tls_connection_established(sm->ssl_ctx, data->ssl.conn)) {
00671 char *label;
00672 wpa_printf(MSG_DEBUG,
00673 "EAP-PEAP: TLS done, proceed to Phase 2");
00674 free(data->key_data);
00675
00676
00677
00678
00679
00680
00681
00682 if (data->peap_version > 1 || data->force_new_label)
00683 label = "client PEAP encryption";
00684 else
00685 label = "client EAP encryption";
00686 wpa_printf(MSG_DEBUG, "EAP-PEAP: using label '%s' in "
00687 "key derivation", label);
00688 data->key_data =
00689 eap_tls_derive_key(sm, &data->ssl, label,
00690 EAP_TLS_KEY_LEN);
00691 if (data->key_data) {
00692 wpa_hexdump_key(MSG_DEBUG,
00693 "EAP-PEAP: Derived key",
00694 data->key_data,
00695 EAP_TLS_KEY_LEN);
00696 } else {
00697 wpa_printf(MSG_DEBUG, "EAP-PEAP: Failed to "
00698 "derive key");
00699 }
00700
00701 if (sm->workaround && data->resuming) {
00702
00703
00704
00705
00706
00707
00708
00709
00710
00711
00712 wpa_printf(MSG_DEBUG, "EAP-PEAP: Workaround - "
00713 "allow outer EAP-Success to "
00714 "terminate PEAP resumption");
00715 ret->decision = DECISION_COND_SUCC;
00716 data->phase2_success = 1;
00717 }
00718
00719 data->resuming = 0;
00720 }
00721 }
00722
00723 if (ret->methodState == METHOD_DONE) {
00724 ret->allowNotifications = FALSE;
00725 }
00726
00727 if (res == 1) {
00728 return eap_tls_build_ack(&data->ssl, respDataLen, id,
00729 EAP_TYPE_PEAP, data->peap_version);
00730 }
00731
00732 return resp;
00733 }
00734
00735
00736 static Boolean eap_peap_has_reauth_data(struct eap_sm *sm, void *priv)
00737 {
00738 struct eap_peap_data *data = priv;
00739 return tls_connection_established(sm->ssl_ctx, data->ssl.conn) &&
00740 data->phase2_success;
00741 }
00742
00743
00744 static void eap_peap_deinit_for_reauth(struct eap_sm *sm, void *priv)
00745 {
00746 struct eap_peap_data *data = priv;
00747 free(data->pending_phase2_req);
00748 data->pending_phase2_req = NULL;
00749 }
00750
00751
00752 static void * eap_peap_init_for_reauth(struct eap_sm *sm, void *priv)
00753 {
00754 struct eap_peap_data *data = priv;
00755 free(data->key_data);
00756 data->key_data = NULL;
00757 if (eap_tls_reauth_init(sm, &data->ssl)) {
00758 free(data);
00759 return NULL;
00760 }
00761 data->phase2_success = 0;
00762 data->resuming = 1;
00763 sm->peap_done = FALSE;
00764 return priv;
00765 }
00766
00767
00768 static int eap_peap_get_status(struct eap_sm *sm, void *priv, char *buf,
00769 size_t buflen, int verbose)
00770 {
00771 struct eap_peap_data *data = priv;
00772 int len;
00773
00774 len = eap_tls_status(sm, &data->ssl, buf, buflen, verbose);
00775 if (data->phase2_method) {
00776 len += snprintf(buf + len, buflen - len,
00777 "EAP-PEAPv%d Phase2 method=%s\n",
00778 data->peap_version, data->phase2_method->name);
00779 }
00780 return len;
00781 }
00782
00783
00784 static Boolean eap_peap_isKeyAvailable(struct eap_sm *sm, void *priv)
00785 {
00786 struct eap_peap_data *data = priv;
00787 return data->key_data != NULL && data->phase2_success;
00788 }
00789
00790
00791 static u8 * eap_peap_getKey(struct eap_sm *sm, void *priv, size_t *len)
00792 {
00793 struct eap_peap_data *data = priv;
00794 u8 *key;
00795
00796 if (data->key_data == NULL || !data->phase2_success)
00797 return NULL;
00798
00799 key = malloc(EAP_TLS_KEY_LEN);
00800 if (key == NULL)
00801 return NULL;
00802
00803 *len = EAP_TLS_KEY_LEN;
00804 memcpy(key, data->key_data, EAP_TLS_KEY_LEN);
00805
00806 return key;
00807 }
00808
00809
00810 const struct eap_method eap_method_peap =
00811 {
00812 .method = EAP_TYPE_PEAP,
00813 .name = "PEAP",
00814 .init = eap_peap_init,
00815 .deinit = eap_peap_deinit,
00816 .process = eap_peap_process,
00817 .isKeyAvailable = eap_peap_isKeyAvailable,
00818 .getKey = eap_peap_getKey,
00819 .get_status = eap_peap_get_status,
00820 .has_reauth_data = eap_peap_has_reauth_data,
00821 .deinit_for_reauth = eap_peap_deinit_for_reauth,
00822 .init_for_reauth = eap_peap_init_for_reauth,
00823 };
00824