Add RADIUS server support for identity selection hint (RFC 4284)
Previously, only the delivery option 1 from RFC 4284 (EAP-Request/Identity from the AP) was supported. Now option 3 (subsequent EAP-Request/Identity from RADIUS server) can also be used when hostapd is used as a RADIUS server. The eap_user file will need to have a Phase 1 user entry pointing to Identity method in order for this to happen (e.g., "* Identity" in the end of the file). The identity hint is configured in the same was as for AP/Authenticator case (eap_message in hostapd.conf).
This commit is contained in:
parent
d9f5626293
commit
65d50f0ac6
5 changed files with 46 additions and 0 deletions
|
@ -1221,6 +1221,8 @@ static int hostapd_setup_radius_srv(struct hostapd_data *hapd,
|
||||||
srv.wps = hapd->wps;
|
srv.wps = hapd->wps;
|
||||||
srv.ipv6 = conf->radius_server_ipv6;
|
srv.ipv6 = conf->radius_server_ipv6;
|
||||||
srv.get_eap_user = hostapd_radius_get_eap_user;
|
srv.get_eap_user = hostapd_radius_get_eap_user;
|
||||||
|
srv.eap_req_id_text = conf->eap_req_id_text;
|
||||||
|
srv.eap_req_id_text_len = conf->eap_req_id_text_len;
|
||||||
|
|
||||||
hapd->radius_srv = radius_server_init(&srv);
|
hapd->radius_srv = radius_server_init(&srv);
|
||||||
if (hapd->radius_srv == NULL) {
|
if (hapd->radius_srv == NULL) {
|
||||||
|
|
|
@ -1051,11 +1051,30 @@ static int eap_sm_Policy_getDecision(struct eap_sm *sm)
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((sm->user == NULL || sm->update_user) && sm->identity) {
|
if ((sm->user == NULL || sm->update_user) && sm->identity) {
|
||||||
|
/*
|
||||||
|
* Allow Identity method to be started once to allow identity
|
||||||
|
* selection hint to be sent from the authentication server,
|
||||||
|
* but prevent a loop of Identity requests by only allowing
|
||||||
|
* this to happen once.
|
||||||
|
*/
|
||||||
|
int id_req = 0;
|
||||||
|
if (sm->user && sm->currentMethod == EAP_TYPE_IDENTITY &&
|
||||||
|
sm->user->methods[0].vendor == EAP_VENDOR_IETF &&
|
||||||
|
sm->user->methods[0].method == EAP_TYPE_IDENTITY)
|
||||||
|
id_req = 1;
|
||||||
if (eap_user_get(sm, sm->identity, sm->identity_len, 0) != 0) {
|
if (eap_user_get(sm, sm->identity, sm->identity_len, 0) != 0) {
|
||||||
wpa_printf(MSG_DEBUG, "EAP: getDecision: user not "
|
wpa_printf(MSG_DEBUG, "EAP: getDecision: user not "
|
||||||
"found from database -> FAILURE");
|
"found from database -> FAILURE");
|
||||||
return DECISION_FAILURE;
|
return DECISION_FAILURE;
|
||||||
}
|
}
|
||||||
|
if (id_req && sm->user &&
|
||||||
|
sm->user->methods[0].vendor == EAP_VENDOR_IETF &&
|
||||||
|
sm->user->methods[0].method == EAP_TYPE_IDENTITY) {
|
||||||
|
wpa_printf(MSG_DEBUG, "EAP: getDecision: stop "
|
||||||
|
"identity request loop -> FAILURE");
|
||||||
|
sm->update_user = TRUE;
|
||||||
|
return DECISION_FAILURE;
|
||||||
|
}
|
||||||
sm->update_user = FALSE;
|
sm->update_user = FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -125,6 +125,8 @@ static void eap_identity_process(struct eap_sm *sm, void *priv,
|
||||||
return; /* Should not happen - frame already validated */
|
return; /* Should not happen - frame already validated */
|
||||||
|
|
||||||
wpa_hexdump_ascii(MSG_DEBUG, "EAP-Identity: Peer identity", pos, len);
|
wpa_hexdump_ascii(MSG_DEBUG, "EAP-Identity: Peer identity", pos, len);
|
||||||
|
if (sm->identity)
|
||||||
|
sm->update_user = TRUE;
|
||||||
os_free(sm->identity);
|
os_free(sm->identity);
|
||||||
sm->identity = os_malloc(len ? len : 1);
|
sm->identity = os_malloc(len ? len : 1);
|
||||||
if (sm->identity == NULL) {
|
if (sm->identity == NULL) {
|
||||||
|
|
|
@ -99,6 +99,8 @@ struct radius_server_data {
|
||||||
struct radius_server_counters counters;
|
struct radius_server_counters counters;
|
||||||
int (*get_eap_user)(void *ctx, const u8 *identity, size_t identity_len,
|
int (*get_eap_user)(void *ctx, const u8 *identity, size_t identity_len,
|
||||||
int phase2, struct eap_user *user);
|
int phase2, struct eap_user *user);
|
||||||
|
char *eap_req_id_text;
|
||||||
|
size_t eap_req_id_text_len;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -1043,6 +1045,14 @@ radius_server_init(struct radius_server_conf *conf)
|
||||||
data->eap_sim_aka_result_ind = conf->eap_sim_aka_result_ind;
|
data->eap_sim_aka_result_ind = conf->eap_sim_aka_result_ind;
|
||||||
data->tnc = conf->tnc;
|
data->tnc = conf->tnc;
|
||||||
data->wps = conf->wps;
|
data->wps = conf->wps;
|
||||||
|
if (conf->eap_req_id_text) {
|
||||||
|
data->eap_req_id_text = os_malloc(conf->eap_req_id_text_len);
|
||||||
|
if (data->eap_req_id_text) {
|
||||||
|
os_memcpy(data->eap_req_id_text, conf->eap_req_id_text,
|
||||||
|
conf->eap_req_id_text_len);
|
||||||
|
data->eap_req_id_text_len = conf->eap_req_id_text_len;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
data->clients = radius_server_read_clients(conf->client_file,
|
data->clients = radius_server_read_clients(conf->client_file,
|
||||||
conf->ipv6);
|
conf->ipv6);
|
||||||
|
@ -1090,6 +1100,7 @@ void radius_server_deinit(struct radius_server_data *data)
|
||||||
os_free(data->pac_opaque_encr_key);
|
os_free(data->pac_opaque_encr_key);
|
||||||
os_free(data->eap_fast_a_id);
|
os_free(data->eap_fast_a_id);
|
||||||
os_free(data->eap_fast_a_id_info);
|
os_free(data->eap_fast_a_id_info);
|
||||||
|
os_free(data->eap_req_id_text);
|
||||||
os_free(data);
|
os_free(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1217,9 +1228,19 @@ static int radius_server_get_eap_user(void *ctx, const u8 *identity,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static const char * radius_server_get_eap_req_id_text(void *ctx, size_t *len)
|
||||||
|
{
|
||||||
|
struct radius_session *sess = ctx;
|
||||||
|
struct radius_server_data *data = sess->server;
|
||||||
|
*len = data->eap_req_id_text_len;
|
||||||
|
return data->eap_req_id_text;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static struct eapol_callbacks radius_server_eapol_cb =
|
static struct eapol_callbacks radius_server_eapol_cb =
|
||||||
{
|
{
|
||||||
.get_eap_user = radius_server_get_eap_user,
|
.get_eap_user = radius_server_get_eap_user,
|
||||||
|
.get_eap_req_id_text = radius_server_get_eap_req_id_text,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -37,6 +37,8 @@ struct radius_server_conf {
|
||||||
int ipv6;
|
int ipv6;
|
||||||
int (*get_eap_user)(void *ctx, const u8 *identity, size_t identity_len,
|
int (*get_eap_user)(void *ctx, const u8 *identity, size_t identity_len,
|
||||||
int phase2, struct eap_user *user);
|
int phase2, struct eap_user *user);
|
||||||
|
const char *eap_req_id_text;
|
||||||
|
size_t eap_req_id_text_len;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue