X-Git-Url: http://www.project-moonshot.org/gitweb/?p=mech_eap.git;a=blobdiff_plain;f=libeap%2Fsrc%2Feap_server%2Feap_server_tls.c;fp=libeap%2Fsrc%2Feap_server%2Feap_server_tls.c;h=7249858844ef2bf27ec5922f97bf2765b9a906a3;hp=c98fa185bb5dfdaa196f51279674d83b101abe03;hb=f3746d009c6d7f50025af1f58a85e5fee9680be6;hpb=244f18d04aaf29e68495b5ffeb40ef5cca50942f diff --git a/libeap/src/eap_server/eap_server_tls.c b/libeap/src/eap_server/eap_server_tls.c index c98fa18..7249858 100644 --- a/libeap/src/eap_server/eap_server_tls.c +++ b/libeap/src/eap_server/eap_server_tls.c @@ -2,14 +2,8 @@ * hostapd / EAP-TLS (RFC 2716) * Copyright (c) 2004-2008, Jouni Malinen * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. + * This software may be distributed under the terms of the BSD license. + * See README for more details. */ #include "includes.h" @@ -27,6 +21,7 @@ struct eap_tls_data { struct eap_ssl_data ssl; enum { START, CONTINUE, SUCCESS, FAILURE } state; int established; + u8 eap_type; }; @@ -53,6 +48,23 @@ static void eap_tls_state(struct eap_tls_data *data, int state) eap_tls_state_txt(data->state), eap_tls_state_txt(state)); data->state = state; + if (state == FAILURE) + tls_connection_remove_session(data->ssl.conn); +} + + +static void eap_tls_valid_session(struct eap_sm *sm, struct eap_tls_data *data) +{ + struct wpabuf *buf; + + if (!sm->tls_session_lifetime) + return; + + buf = wpabuf_alloc(1); + if (!buf) + return; + wpabuf_put_u8(buf, data->eap_type); + tls_connection_set_success_data(data->ssl.conn, buf); } @@ -65,14 +77,61 @@ static void * eap_tls_init(struct eap_sm *sm) return NULL; data->state = START; - if (eap_server_tls_ssl_init(sm, &data->ssl, 1)) { + if (eap_server_tls_ssl_init(sm, &data->ssl, 1, EAP_TYPE_TLS)) { + wpa_printf(MSG_INFO, "EAP-TLS: Failed to initialize SSL."); + eap_tls_reset(sm, data); + return NULL; + } + + data->eap_type = EAP_TYPE_TLS; + + return data; +} + + +#ifdef EAP_SERVER_UNAUTH_TLS +static void * eap_unauth_tls_init(struct eap_sm *sm) +{ + struct eap_tls_data *data; + + data = os_zalloc(sizeof(*data)); + if (data == NULL) + return NULL; + data->state = START; + + if (eap_server_tls_ssl_init(sm, &data->ssl, 0, EAP_UNAUTH_TLS_TYPE)) { wpa_printf(MSG_INFO, "EAP-TLS: Failed to initialize SSL."); eap_tls_reset(sm, data); return NULL; } + data->eap_type = EAP_UNAUTH_TLS_TYPE; return data; } +#endif /* EAP_SERVER_UNAUTH_TLS */ + + +#ifdef CONFIG_HS20 +static void * eap_wfa_unauth_tls_init(struct eap_sm *sm) +{ + struct eap_tls_data *data; + + data = os_zalloc(sizeof(*data)); + if (data == NULL) + return NULL; + data->state = START; + + if (eap_server_tls_ssl_init(sm, &data->ssl, 0, + EAP_WFA_UNAUTH_TLS_TYPE)) { + wpa_printf(MSG_INFO, "EAP-TLS: Failed to initialize SSL."); + eap_tls_reset(sm, data); + return NULL; + } + + data->eap_type = EAP_WFA_UNAUTH_TLS_TYPE; + return data; +} +#endif /* CONFIG_HS20 */ static void eap_tls_reset(struct eap_sm *sm, void *priv) @@ -90,8 +149,7 @@ static struct wpabuf * eap_tls_build_start(struct eap_sm *sm, { struct wpabuf *req; - req = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_TLS, 1, EAP_CODE_REQUEST, - id); + req = eap_tls_msg_alloc(data->eap_type, 1, EAP_CODE_REQUEST, id); if (req == NULL) { wpa_printf(MSG_ERROR, "EAP-TLS: Failed to allocate memory for " "request"); @@ -113,11 +171,11 @@ static struct wpabuf * eap_tls_buildReq(struct eap_sm *sm, void *priv, u8 id) struct wpabuf *res; if (data->ssl.state == FRAG_ACK) { - return eap_server_tls_build_ack(id, EAP_TYPE_TLS, 0); + return eap_server_tls_build_ack(id, data->eap_type, 0); } if (data->ssl.state == WAIT_FRAG_ACK) { - res = eap_server_tls_build_msg(&data->ssl, EAP_TYPE_TLS, 0, + res = eap_server_tls_build_msg(&data->ssl, data->eap_type, 0, id); goto check_established; } @@ -135,7 +193,7 @@ static struct wpabuf * eap_tls_buildReq(struct eap_sm *sm, void *priv, u8 id) return NULL; } - res = eap_server_tls_build_msg(&data->ssl, EAP_TYPE_TLS, 0, id); + res = eap_server_tls_build_msg(&data->ssl, data->eap_type, 0, id); check_established: if (data->established && data->ssl.state != WAIT_FRAG_ACK) { @@ -143,6 +201,7 @@ check_established: * fragments waiting to be sent out. */ wpa_printf(MSG_DEBUG, "EAP-TLS: Done"); eap_tls_state(data, SUCCESS); + eap_tls_valid_session(sm, data); } return res; @@ -152,10 +211,21 @@ check_established: static Boolean eap_tls_check(struct eap_sm *sm, void *priv, struct wpabuf *respData) { + struct eap_tls_data *data = priv; const u8 *pos; size_t len; - pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_TLS, respData, &len); + if (data->eap_type == EAP_UNAUTH_TLS_TYPE) + pos = eap_hdr_validate(EAP_VENDOR_UNAUTH_TLS, + EAP_VENDOR_TYPE_UNAUTH_TLS, respData, + &len); + else if (data->eap_type == EAP_WFA_UNAUTH_TLS_TYPE) + pos = eap_hdr_validate(EAP_VENDOR_WFA_NEW, + EAP_VENDOR_WFA_UNAUTH_TLS, respData, + &len); + else + pos = eap_hdr_validate(EAP_VENDOR_IETF, data->eap_type, + respData, &len); if (pos == NULL || len < 1) { wpa_printf(MSG_INFO, "EAP-TLS: Invalid frame"); return TRUE; @@ -183,10 +253,41 @@ static void eap_tls_process(struct eap_sm *sm, void *priv, struct wpabuf *respData) { struct eap_tls_data *data = priv; + const struct wpabuf *buf; + const u8 *pos; + if (eap_server_tls_process(sm, &data->ssl, respData, data, - EAP_TYPE_TLS, NULL, eap_tls_process_msg) < - 0) + data->eap_type, NULL, eap_tls_process_msg) < + 0) { + eap_tls_state(data, FAILURE); + return; + } + + if (!tls_connection_established(sm->ssl_ctx, data->ssl.conn) || + !tls_connection_resumed(sm->ssl_ctx, data->ssl.conn)) + return; + + buf = tls_connection_get_success_data(data->ssl.conn); + if (!buf || wpabuf_len(buf) < 1) { + wpa_printf(MSG_DEBUG, + "EAP-TLS: No success data in resumed session - reject attempt"); eap_tls_state(data, FAILURE); + return; + } + + pos = wpabuf_head(buf); + if (*pos != data->eap_type) { + wpa_printf(MSG_DEBUG, + "EAP-TLS: Resumed session for another EAP type (%u) - reject attempt", + *pos); + eap_tls_state(data, FAILURE); + return; + } + + wpa_printf(MSG_DEBUG, + "EAP-TLS: Resuming previous session"); + eap_tls_state(data, SUCCESS); + tls_connection_set_success_data_resumed(data->ssl.conn); } @@ -236,7 +337,7 @@ static u8 * eap_tls_get_emsk(struct eap_sm *sm, void *priv, size_t *len) if (emsk) os_memcpy(emsk, eapKeyData + EAP_TLS_KEY_LEN, EAP_EMSK_LEN); - os_free(eapKeyData); + bin_clear_free(eapKeyData, EAP_TLS_KEY_LEN + EAP_EMSK_LEN); } else emsk = NULL; @@ -259,10 +360,21 @@ static Boolean eap_tls_isSuccess(struct eap_sm *sm, void *priv) } +static u8 * eap_tls_get_session_id(struct eap_sm *sm, void *priv, size_t *len) +{ + struct eap_tls_data *data = priv; + + if (data->state != SUCCESS) + return NULL; + + return eap_server_tls_derive_session_id(sm, &data->ssl, EAP_TYPE_TLS, + len); +} + + int eap_server_tls_register(void) { struct eap_method *eap; - int ret; eap = eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION, EAP_VENDOR_IETF, EAP_TYPE_TLS, "TLS"); @@ -278,9 +390,61 @@ int eap_server_tls_register(void) eap->getKey = eap_tls_getKey; eap->isSuccess = eap_tls_isSuccess; eap->get_emsk = eap_tls_get_emsk; + eap->getSessionId = eap_tls_get_session_id; + + return eap_server_method_register(eap); +} + + +#ifdef EAP_SERVER_UNAUTH_TLS +int eap_server_unauth_tls_register(void) +{ + struct eap_method *eap; + + eap = eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION, + EAP_VENDOR_UNAUTH_TLS, + EAP_VENDOR_TYPE_UNAUTH_TLS, + "UNAUTH-TLS"); + if (eap == NULL) + return -1; + + eap->init = eap_unauth_tls_init; + eap->reset = eap_tls_reset; + eap->buildReq = eap_tls_buildReq; + eap->check = eap_tls_check; + eap->process = eap_tls_process; + eap->isDone = eap_tls_isDone; + eap->getKey = eap_tls_getKey; + eap->isSuccess = eap_tls_isSuccess; + eap->get_emsk = eap_tls_get_emsk; + + return eap_server_method_register(eap); +} +#endif /* EAP_SERVER_UNAUTH_TLS */ + + +#ifdef CONFIG_HS20 +int eap_server_wfa_unauth_tls_register(void) +{ + struct eap_method *eap; + + eap = eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION, + EAP_VENDOR_WFA_NEW, + EAP_VENDOR_WFA_UNAUTH_TLS, + "WFA-UNAUTH-TLS"); + if (eap == NULL) + return -1; + + eap->init = eap_wfa_unauth_tls_init; + eap->reset = eap_tls_reset; + eap->buildReq = eap_tls_buildReq; + eap->check = eap_tls_check; + eap->process = eap_tls_process; + eap->isDone = eap_tls_isDone; + eap->getKey = eap_tls_getKey; + eap->isSuccess = eap_tls_isSuccess; + eap->get_emsk = eap_tls_get_emsk; - ret = eap_server_method_register(eap); - if (ret) - eap_server_method_free(eap); - return ret; + return eap_server_method_register(eap); } +#endif /* CONFIG_HS20 */