ERP: Add support for ERP on EAP server and authenticator
Derive rRK and rIK on EAP server if ERP is enabled and use these keys to allow EAP re-authentication to be used and to derive rMSK. The new hostapd configuration parameter eap_server_erp=1 can now be used to configure the integrated EAP server to derive EMSK, rRK, and rIK at the successful completion of an EAP authentication method. This functionality is not included in the default build and can be enabled with CONFIG_ERP=y. Signed-off-by: Jouni Malinen <j@w1.fi>
This commit is contained in:
parent
e2ee327b19
commit
d3bddd8b84
15 changed files with 676 additions and 13 deletions
|
@ -233,6 +233,7 @@ struct hostapd_bss_config {
|
|||
struct hostapd_eap_user *eap_user;
|
||||
char *eap_user_sqlite;
|
||||
char *eap_sim_db;
|
||||
int eap_server_erp; /* Whether ERP is enabled on internal EAP server */
|
||||
struct hostapd_ip_addr own_ip_addr;
|
||||
char *nas_identifier;
|
||||
struct hostapd_radius_servers *radius;
|
||||
|
|
|
@ -124,6 +124,8 @@ static int hostapd_setup_radius_srv(struct hostapd_data *hapd)
|
|||
srv.subscr_remediation_url = conf->subscr_remediation_url;
|
||||
srv.subscr_remediation_method = conf->subscr_remediation_method;
|
||||
#endif /* CONFIG_HS20 */
|
||||
srv.erp = conf->eap_server_erp;
|
||||
srv.erp_domain = conf->erp_domain;
|
||||
|
||||
hapd->radius_srv = radius_server_init(&srv);
|
||||
if (hapd->radius_srv == NULL) {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* hostapd / Initialization and configuration
|
||||
* Copyright (c) 2002-2013, Jouni Malinen <j@w1.fi>
|
||||
* Copyright (c) 2002-2014, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
|
@ -10,6 +10,7 @@
|
|||
#define HOSTAPD_H
|
||||
|
||||
#include "common/defs.h"
|
||||
#include "utils/list.h"
|
||||
#include "ap_config.h"
|
||||
#include "drivers/driver.h"
|
||||
|
||||
|
@ -153,6 +154,7 @@ struct hostapd_data {
|
|||
void *ssl_ctx;
|
||||
void *eap_sim_db_priv;
|
||||
struct radius_server_data *radius_srv;
|
||||
struct dl_list erp_keys; /* struct eap_server_erp_key */
|
||||
|
||||
int parameter_set_count;
|
||||
|
||||
|
|
|
@ -296,9 +296,15 @@ static void ieee802_1x_learn_identity(struct hostapd_data *hapd,
|
|||
{
|
||||
const u8 *identity;
|
||||
size_t identity_len;
|
||||
const struct eap_hdr *hdr = (const struct eap_hdr *) eap;
|
||||
|
||||
if (len <= sizeof(struct eap_hdr) ||
|
||||
eap[sizeof(struct eap_hdr)] != EAP_TYPE_IDENTITY)
|
||||
(hdr->code == EAP_CODE_RESPONSE &&
|
||||
eap[sizeof(struct eap_hdr)] != EAP_TYPE_IDENTITY) ||
|
||||
(hdr->code == EAP_CODE_INITIATE &&
|
||||
eap[sizeof(struct eap_hdr)] != EAP_ERP_TYPE_REAUTH) ||
|
||||
(hdr->code != EAP_CODE_RESPONSE &&
|
||||
hdr->code != EAP_CODE_INITIATE))
|
||||
return;
|
||||
|
||||
identity = eap_get_identity(sm->eap, &identity_len);
|
||||
|
@ -711,6 +717,39 @@ static void handle_eap_response(struct hostapd_data *hapd,
|
|||
}
|
||||
|
||||
|
||||
static void handle_eap_initiate(struct hostapd_data *hapd,
|
||||
struct sta_info *sta, struct eap_hdr *eap,
|
||||
size_t len)
|
||||
{
|
||||
#ifdef CONFIG_ERP
|
||||
u8 type, *data;
|
||||
struct eapol_state_machine *sm = sta->eapol_sm;
|
||||
|
||||
if (sm == NULL)
|
||||
return;
|
||||
|
||||
if (len < sizeof(*eap) + 1) {
|
||||
wpa_printf(MSG_INFO,
|
||||
"handle_eap_initiate: too short response data");
|
||||
return;
|
||||
}
|
||||
|
||||
data = (u8 *) (eap + 1);
|
||||
type = data[0];
|
||||
|
||||
hostapd_logger(hapd, sm->addr, HOSTAPD_MODULE_IEEE8021X,
|
||||
HOSTAPD_LEVEL_DEBUG, "received EAP packet (code=%d "
|
||||
"id=%d len=%d) from STA: EAP Initiate type %u",
|
||||
eap->code, eap->identifier, be_to_host16(eap->length),
|
||||
type);
|
||||
|
||||
wpabuf_free(sm->eap_if->eapRespData);
|
||||
sm->eap_if->eapRespData = wpabuf_alloc_copy(eap, len);
|
||||
sm->eapolEap = TRUE;
|
||||
#endif /* CONFIG_ERP */
|
||||
}
|
||||
|
||||
|
||||
/* Process incoming EAP packet from Supplicant */
|
||||
static void handle_eap(struct hostapd_data *hapd, struct sta_info *sta,
|
||||
u8 *buf, size_t len)
|
||||
|
@ -754,6 +793,13 @@ static void handle_eap(struct hostapd_data *hapd, struct sta_info *sta,
|
|||
case EAP_CODE_FAILURE:
|
||||
wpa_printf(MSG_DEBUG, " (failure)");
|
||||
return;
|
||||
case EAP_CODE_INITIATE:
|
||||
wpa_printf(MSG_DEBUG, " (initiate)");
|
||||
handle_eap_initiate(hapd, sta, eap, eap_len);
|
||||
break;
|
||||
case EAP_CODE_FINISH:
|
||||
wpa_printf(MSG_DEBUG, " (finish)");
|
||||
break;
|
||||
default:
|
||||
wpa_printf(MSG_DEBUG, " (unknown code)");
|
||||
return;
|
||||
|
@ -1986,12 +2032,43 @@ static void ieee802_1x_eapol_event(void *ctx, void *sta_ctx,
|
|||
}
|
||||
|
||||
|
||||
#ifdef CONFIG_ERP
|
||||
|
||||
static struct eap_server_erp_key *
|
||||
ieee802_1x_erp_get_key(void *ctx, const char *keyname)
|
||||
{
|
||||
struct hostapd_data *hapd = ctx;
|
||||
struct eap_server_erp_key *erp;
|
||||
|
||||
dl_list_for_each(erp, &hapd->erp_keys, struct eap_server_erp_key,
|
||||
list) {
|
||||
if (os_strcmp(erp->keyname_nai, keyname) == 0)
|
||||
return erp;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
static int ieee802_1x_erp_add_key(void *ctx, struct eap_server_erp_key *erp)
|
||||
{
|
||||
struct hostapd_data *hapd = ctx;
|
||||
|
||||
dl_list_add(&hapd->erp_keys, &erp->list);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_ERP */
|
||||
|
||||
|
||||
int ieee802_1x_init(struct hostapd_data *hapd)
|
||||
{
|
||||
int i;
|
||||
struct eapol_auth_config conf;
|
||||
struct eapol_auth_cb cb;
|
||||
|
||||
dl_list_init(&hapd->erp_keys);
|
||||
|
||||
os_memset(&conf, 0, sizeof(conf));
|
||||
conf.ctx = hapd;
|
||||
conf.eap_reauth_period = hapd->conf->eap_reauth_period;
|
||||
|
@ -2005,6 +2082,7 @@ int ieee802_1x_init(struct hostapd_data *hapd)
|
|||
conf.eap_req_id_text_len = hapd->conf->eap_req_id_text_len;
|
||||
conf.erp_send_reauth_start = hapd->conf->erp_send_reauth_start;
|
||||
conf.erp_domain = hapd->conf->erp_domain;
|
||||
conf.erp = hapd->conf->eap_server_erp;
|
||||
conf.pac_opaque_encr_key = hapd->conf->pac_opaque_encr_key;
|
||||
conf.eap_fast_a_id = hapd->conf->eap_fast_a_id;
|
||||
conf.eap_fast_a_id_len = hapd->conf->eap_fast_a_id_len;
|
||||
|
@ -2037,6 +2115,10 @@ int ieee802_1x_init(struct hostapd_data *hapd)
|
|||
cb.abort_auth = _ieee802_1x_abort_auth;
|
||||
cb.tx_key = _ieee802_1x_tx_key;
|
||||
cb.eapol_event = ieee802_1x_eapol_event;
|
||||
#ifdef CONFIG_ERP
|
||||
cb.erp_get_key = ieee802_1x_erp_get_key;
|
||||
cb.erp_add_key = ieee802_1x_erp_add_key;
|
||||
#endif /* CONFIG_ERP */
|
||||
|
||||
hapd->eapol_auth = eapol_auth_init(&conf, &cb);
|
||||
if (hapd->eapol_auth == NULL)
|
||||
|
@ -2070,6 +2152,8 @@ int ieee802_1x_init(struct hostapd_data *hapd)
|
|||
|
||||
void ieee802_1x_deinit(struct hostapd_data *hapd)
|
||||
{
|
||||
struct eap_server_erp_key *erp;
|
||||
|
||||
eloop_cancel_timeout(ieee802_1x_rekey, hapd, NULL);
|
||||
|
||||
if (hapd->driver != NULL &&
|
||||
|
@ -2078,6 +2162,12 @@ void ieee802_1x_deinit(struct hostapd_data *hapd)
|
|||
|
||||
eapol_auth_deinit(hapd->eapol_auth);
|
||||
hapd->eapol_auth = NULL;
|
||||
|
||||
while ((erp = dl_list_first(&hapd->erp_keys, struct eap_server_erp_key,
|
||||
list)) != NULL) {
|
||||
dl_list_del(&erp->list);
|
||||
bin_clear_free(erp, sizeof(*erp));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue