X-Git-Url: http://vcs.maemo.org/git/?a=blobdiff_plain;f=src%2Feap_server%2Feap_ttls.c;h=6fe3bb13d33d17895a7e166123885e5ac1eb8446;hb=0915d02c3c089013ed2c3b7ff321c2c69f665282;hp=4c71b5fa2cec7c06f9d629d421dd0d641971c6d0;hpb=ef626b4d5053ea56817a39170c41686c014d6e37;p=wpasupplicant diff --git a/src/eap_server/eap_ttls.c b/src/eap_server/eap_ttls.c index 4c71b5f..6fe3bb1 100644 --- a/src/eap_server/eap_ttls.c +++ b/src/eap_server/eap_ttls.c @@ -1,5 +1,5 @@ /* - * hostapd / EAP-TTLS (draft-ietf-pppext-eap-ttls-05.txt) + * hostapd / EAP-TTLS (RFC 5281) * Copyright (c) 2004-2008, Jouni Malinen * * This program is free software; you can redistribute it and/or modify @@ -25,7 +25,7 @@ /* Maximum supported TTLS version - * 0 = draft-ietf-pppext-eap-ttls-03.txt / draft-funk-eap-ttls-v0-00.txt + * 0 = RFC 5281 * 1 = draft-funk-eap-ttls-v1-00.txt */ #ifndef EAP_TTLS_VERSION @@ -445,62 +445,6 @@ static struct wpabuf * eap_ttls_build_start(struct eap_sm *sm, } -static struct wpabuf * eap_ttls_build_req(struct eap_sm *sm, - struct eap_ttls_data *data, u8 id) -{ - int res; - struct wpabuf *req; - - res = eap_server_tls_buildReq_helper(sm, &data->ssl, EAP_TYPE_TTLS, - data->ttls_version, id, &req); - - if (tls_connection_established(sm->ssl_ctx, data->ssl.conn)) { - wpa_printf(MSG_DEBUG, "EAP-TTLS: Phase1 done, starting " - "Phase2"); - eap_ttls_state(data, PHASE2_START); - } - - if (res == 1) - return eap_server_tls_build_ack(id, EAP_TYPE_TTLS, - data->ttls_version); - return req; -} - - -static struct wpabuf * eap_ttls_encrypt(struct eap_sm *sm, - struct eap_ttls_data *data, - u8 id, u8 *plain, size_t plain_len) -{ - int res; - struct wpabuf *buf; - - /* TODO: add support for fragmentation, if needed. This will need to - * add TLS Message Length field, if the frame is fragmented. */ - buf = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_TTLS, - 1 + data->ssl.tls_out_limit, - EAP_CODE_REQUEST, id); - if (buf == NULL) - return NULL; - - wpabuf_put_u8(buf, data->ttls_version); - - res = tls_connection_encrypt(sm->ssl_ctx, data->ssl.conn, - plain, plain_len, wpabuf_put(buf, 0), - data->ssl.tls_out_limit); - if (res < 0) { - wpa_printf(MSG_INFO, "EAP-TTLS: Failed to encrypt Phase 2 " - "data"); - wpabuf_free(buf); - return NULL; - } - - wpabuf_put(buf, res); - eap_update_len(buf); - - return buf; -} - - static struct wpabuf * eap_ttls_build_phase2_eap_req( struct eap_sm *sm, struct eap_ttls_data *data, u8 id) { @@ -528,7 +472,7 @@ static struct wpabuf * eap_ttls_build_phase2_eap_req( wpa_hexdump_key(MSG_DEBUG, "EAP-TTLS/EAP: Encrypt encapsulated Phase " "2 data", req, req_len); - encr_req = eap_ttls_encrypt(sm, data, id, req, req_len); + encr_req = eap_server_tls_encrypt(sm, &data->ssl, req, req_len); wpabuf_free(buf); return encr_req; @@ -536,7 +480,7 @@ static struct wpabuf * eap_ttls_build_phase2_eap_req( static struct wpabuf * eap_ttls_build_phase2_mschapv2( - struct eap_sm *sm, struct eap_ttls_data *data, u8 id) + struct eap_sm *sm, struct eap_ttls_data *data) { struct wpabuf *encr_req; u8 *req, *pos, *end; @@ -570,7 +514,7 @@ static struct wpabuf * eap_ttls_build_phase2_mschapv2( wpa_hexdump_key(MSG_DEBUG, "EAP-TTLS/MSCHAPV2: Encrypting Phase 2 " "data", req, req_len); - encr_req = eap_ttls_encrypt(sm, data, id, req, req_len); + encr_req = eap_server_tls_encrypt(sm, &data->ssl, req, req_len); os_free(req); return encr_req; @@ -578,20 +522,16 @@ static struct wpabuf * eap_ttls_build_phase2_mschapv2( static struct wpabuf * eap_ttls_build_phase_finished( - struct eap_sm *sm, struct eap_ttls_data *data, u8 id, int final) + struct eap_sm *sm, struct eap_ttls_data *data, int final) { int len; struct wpabuf *req; const int max_len = 300; - len = 1 + max_len; - req = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_TTLS, len, - EAP_CODE_REQUEST, id); + req = wpabuf_alloc(max_len); if (req == NULL) return NULL; - wpabuf_put_u8(req, data->ttls_version); - len = tls_connection_ia_send_phase_finished(sm->ssl_ctx, data->ssl.conn, final, wpabuf_mhead(req), @@ -601,7 +541,6 @@ static struct wpabuf * eap_ttls_build_phase_finished( return NULL; } wpabuf_put(req, len); - eap_update_len(req); return req; } @@ -611,22 +550,50 @@ static struct wpabuf * eap_ttls_buildReq(struct eap_sm *sm, void *priv, u8 id) { struct eap_ttls_data *data = priv; + if (data->ssl.state == FRAG_ACK) { + return eap_server_tls_build_ack(id, EAP_TYPE_TTLS, + data->ttls_version); + } + + if (data->ssl.state == WAIT_FRAG_ACK) { + return eap_server_tls_build_msg(&data->ssl, EAP_TYPE_TTLS, + data->ttls_version, id); + } + switch (data->state) { case START: return eap_ttls_build_start(sm, data, id); case PHASE1: - return eap_ttls_build_req(sm, data, id); + if (tls_connection_established(sm->ssl_ctx, data->ssl.conn)) { + wpa_printf(MSG_DEBUG, "EAP-TTLS: Phase1 done, " + "starting Phase2"); + eap_ttls_state(data, PHASE2_START); + } + break; case PHASE2_METHOD: - return eap_ttls_build_phase2_eap_req(sm, data, id); + wpabuf_free(data->ssl.out_buf); + data->ssl.out_used = 0; + data->ssl.out_buf = eap_ttls_build_phase2_eap_req(sm, data, + id); + break; case PHASE2_MSCHAPV2_RESP: - return eap_ttls_build_phase2_mschapv2(sm, data, id); + wpabuf_free(data->ssl.out_buf); + data->ssl.out_used = 0; + data->ssl.out_buf = eap_ttls_build_phase2_mschapv2(sm, data); + break; case PHASE_FINISHED: - return eap_ttls_build_phase_finished(sm, data, id, 1); + wpabuf_free(data->ssl.out_buf); + data->ssl.out_used = 0; + data->ssl.out_buf = eap_ttls_build_phase_finished(sm, data, 1); + break; default: wpa_printf(MSG_DEBUG, "EAP-TTLS: %s - unexpected state %d", __func__, data->state); return NULL; } + + return eap_server_tls_build_msg(&data->ssl, EAP_TYPE_TTLS, + data->ttls_version, id); } @@ -987,7 +954,7 @@ static int eap_ttls_phase2_eap_init(struct eap_sm *sm, sm->init_phase2 = 1; data->phase2_priv = data->phase2_method->init(sm); sm->init_phase2 = 0; - return 0; + return data->phase2_priv == NULL ? -1 : 0; } @@ -1024,7 +991,13 @@ static void eap_ttls_process_phase2_eap_response(struct eap_sm *sm, sm->user_eap_method_index++].method; wpa_printf(MSG_DEBUG, "EAP-TTLS: try EAP type %d", next_type); - eap_ttls_phase2_eap_init(sm, data, next_type); + if (eap_ttls_phase2_eap_init(sm, data, next_type)) { + wpa_printf(MSG_DEBUG, "EAP-TTLS: Failed to " + "initialize EAP type %d", + next_type); + eap_ttls_state(data, FAILURE); + return; + } } else { eap_ttls_state(data, FAILURE); } @@ -1072,6 +1045,11 @@ static void eap_ttls_process_phase2_eap_response(struct eap_sm *sm, next_type = sm->user->methods[0].method; sm->user_eap_method_index = 1; wpa_printf(MSG_DEBUG, "EAP-TTLS: try EAP type %d", next_type); + if (eap_ttls_phase2_eap_init(sm, data, next_type)) { + wpa_printf(MSG_DEBUG, "EAP-TTLS: Failed to initialize " + "EAP type %d", next_type); + eap_ttls_state(data, FAILURE); + } break; case PHASE2_METHOD: if (data->ttls_version > 0) { @@ -1093,8 +1071,6 @@ static void eap_ttls_process_phase2_eap_response(struct eap_sm *sm, __func__, data->state); break; } - - eap_ttls_phase2_eap_init(sm, data, next_type); } @@ -1148,12 +1124,17 @@ static void eap_ttls_process_phase2_eap(struct eap_sm *sm, static void eap_ttls_process_phase2(struct eap_sm *sm, struct eap_ttls_data *data, - u8 *in_data, size_t in_len) + struct wpabuf *in_buf) { u8 *in_decrypted; - int len_decrypted, res; + int len_decrypted; struct eap_ttls_avp parse; size_t buf_len; + u8 *in_data; + size_t in_len; + + in_data = wpabuf_mhead(in_buf); + in_len = wpabuf_len(in_buf); wpa_printf(MSG_DEBUG, "EAP-TTLS: received %lu bytes encrypted data for" " Phase 2", (unsigned long) in_len); @@ -1169,14 +1150,7 @@ static void eap_ttls_process_phase2(struct eap_sm *sm, return; } - res = eap_server_tls_data_reassemble(sm, &data->ssl, &in_data, - &in_len); - if (res < 0 || res == 1) - return; - buf_len = in_len; - if (data->ssl.tls_in_total > buf_len) - buf_len = data->ssl.tls_in_total; /* * Even though we try to disable TLS compression, it is possible that * this cannot be done with all TLS libraries. Add extra buffer space @@ -1187,9 +1161,6 @@ static void eap_ttls_process_phase2(struct eap_sm *sm, buf_len *= 3; in_decrypted = os_malloc(buf_len); if (in_decrypted == NULL) { - os_free(data->ssl.tls_in); - data->ssl.tls_in = NULL; - data->ssl.tls_in_len = 0; wpa_printf(MSG_WARNING, "EAP-TTLS: failed to allocate memory " "for decryption"); return; @@ -1198,9 +1169,6 @@ static void eap_ttls_process_phase2(struct eap_sm *sm, len_decrypted = tls_connection_decrypt(sm->ssl_ctx, data->ssl.conn, in_data, in_len, in_decrypted, buf_len); - os_free(data->ssl.tls_in); - data->ssl.tls_in = NULL; - data->ssl.tls_in_len = 0; if (len_decrypted < 0) { wpa_printf(MSG_INFO, "EAP-TTLS: Failed to decrypt Phase 2 " "data"); @@ -1253,14 +1221,14 @@ static void eap_ttls_process_phase2(struct eap_sm *sm, } } -#ifdef EAP_TNC +#ifdef EAP_SERVER_TNC if (data->tnc_started && parse.eap == NULL) { wpa_printf(MSG_DEBUG, "EAP-TTLS: TNC started but no EAP " "response from peer"); eap_ttls_state(data, FAILURE); goto done; } -#endif /* EAP_TNC */ +#endif /* EAP_SERVER_TNC */ if (parse.eap) { eap_ttls_process_phase2_eap(sm, data, parse.eap, @@ -1296,7 +1264,7 @@ done: static void eap_ttls_start_tnc(struct eap_sm *sm, struct eap_ttls_data *data) { -#ifdef EAP_TNC +#ifdef EAP_SERVER_TNC if (!sm->tnc || data->state != SUCCESS || data->tnc_started) return; @@ -1309,30 +1277,14 @@ static void eap_ttls_start_tnc(struct eap_sm *sm, struct eap_ttls_data *data) data->tnc_started = 1; eap_ttls_state(data, PHASE2_METHOD); -#endif /* EAP_TNC */ +#endif /* EAP_SERVER_TNC */ } -static void eap_ttls_process(struct eap_sm *sm, void *priv, - struct wpabuf *respData) +static int eap_ttls_process_version(struct eap_sm *sm, void *priv, + int peer_version) { struct eap_ttls_data *data = priv; - const u8 *pos; - u8 flags; - size_t left; - unsigned int tls_msg_len; - int peer_version; - - pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_TTLS, respData, - &left); - if (pos == NULL || left < 1) - return; - flags = *pos++; - left--; - wpa_printf(MSG_DEBUG, "EAP-TTLS: Received packet(len=%lu) - " - "Flags 0x%02x", (unsigned long) wpabuf_len(respData), - flags); - peer_version = flags & EAP_PEAP_VERSION_MASK; if (peer_version < data->ttls_version) { wpa_printf(MSG_DEBUG, "EAP-TTLS: peer ver=%d, own ver=%d; " "use version %d", @@ -1344,51 +1296,34 @@ static void eap_ttls_process(struct eap_sm *sm, void *priv, if (tls_connection_set_ia(sm->ssl_ctx, data->ssl.conn, 1)) { wpa_printf(MSG_INFO, "EAP-TTLS: Failed to enable " "TLS/IA"); - eap_ttls_state(data, FAILURE); - return; + return -1; } data->tls_ia_configured = 1; } - if (flags & EAP_TLS_FLAGS_LENGTH_INCLUDED) { - if (left < 4) { - wpa_printf(MSG_INFO, "EAP-TTLS: Short frame with TLS " - "length"); - eap_ttls_state(data, FAILURE); - return; - } - tls_msg_len = WPA_GET_BE32(pos); - wpa_printf(MSG_DEBUG, "EAP-TTLS: TLS Message Length: %d", - tls_msg_len); - if (data->ssl.tls_in_left == 0) { - data->ssl.tls_in_total = tls_msg_len; - data->ssl.tls_in_left = tls_msg_len; - os_free(data->ssl.tls_in); - data->ssl.tls_in = NULL; - data->ssl.tls_in_len = 0; - } - pos += 4; - left -= 4; - } + return 0; +} + + +static void eap_ttls_process_msg(struct eap_sm *sm, void *priv, + const struct wpabuf *respData) +{ + struct eap_ttls_data *data = priv; switch (data->state) { case PHASE1: - if (eap_server_tls_process_helper(sm, &data->ssl, pos, left) < - 0) { - wpa_printf(MSG_INFO, "EAP-TTLS: TLS processing " - "failed"); + if (eap_server_tls_phase1(sm, &data->ssl) < 0) eap_ttls_state(data, FAILURE); - } break; case PHASE2_START: case PHASE2_METHOD: case PHASE_FINISHED: - /* FIX: get rid of const->non-const typecast */ - eap_ttls_process_phase2(sm, data, (u8 *) pos, left); + eap_ttls_process_phase2(sm, data, data->ssl.in_buf); eap_ttls_start_tnc(sm, data); break; case PHASE2_MSCHAPV2_RESP: - if (data->mschapv2_resp_ok && left == 0) { + if (data->mschapv2_resp_ok && wpabuf_len(data->ssl.in_buf) == + 0) { wpa_printf(MSG_DEBUG, "EAP-TTLS/MSCHAPV2: Peer " "acknowledged response"); eap_ttls_state(data, data->ttls_version > 0 ? @@ -1401,7 +1336,8 @@ static void eap_ttls_process(struct eap_sm *sm, void *priv, wpa_printf(MSG_DEBUG, "EAP-TTLS/MSCHAPV2: Unexpected " "frame from peer (payload len %lu, " "expected empty frame)", - (unsigned long) left); + (unsigned long) + wpabuf_len(data->ssl.in_buf)); eap_ttls_state(data, FAILURE); } eap_ttls_start_tnc(sm, data); @@ -1411,12 +1347,17 @@ static void eap_ttls_process(struct eap_sm *sm, void *priv, data->state, __func__); break; } +} + - if (tls_connection_get_write_alerts(sm->ssl_ctx, data->ssl.conn) > 1) { - wpa_printf(MSG_INFO, "EAP-TTLS: Locally detected fatal error " - "in TLS processing"); +static void eap_ttls_process(struct eap_sm *sm, void *priv, + struct wpabuf *respData) +{ + struct eap_ttls_data *data = priv; + if (eap_server_tls_process(sm, &data->ssl, respData, data, + EAP_TYPE_TTLS, eap_ttls_process_version, + eap_ttls_process_msg) < 0) eap_ttls_state(data, FAILURE); - } }